forked from OSchip/llvm-project
Centralized all disassembly into static functions in source/Core/Disassembler.cpp.
Added the ability to read memory from the target's object files when we aren't running, so disassembling works before you run! Cleaned up the API to lldb_private::Target::ReadMemory(). Cleaned up the API to the Disassembler to use actual "lldb_private::Address" objects instead of just an "addr_t". This is nice because the Address objects when resolved carry along their section and module which can get us the object file. This allows Target::ReadMemory to be used when we are not running. Added a new lldb_private::Address dump style: DumpStyleDetailedSymbolContext This will show a full breakdown of what an address points to. To see some sample output, execute a "image lookup --address <addr>". Fixed SymbolContext::DumpStopContext(...) to not require a live process in order to be able to print function and symbol offsets. llvm-svn: 107350
This commit is contained in:
parent
56f2e34a6a
commit
dda4f7b520
|
@ -122,7 +122,8 @@ public:
|
|||
//Disassemble ();
|
||||
|
||||
void
|
||||
Disassemble (lldb::addr_t file_address_start, lldb::addr_t file_address_end = LLDB_INVALID_ADDRESS,
|
||||
Disassemble (lldb::addr_t start_address,
|
||||
lldb::addr_t end_address = LLDB_INVALID_ADDRESS,
|
||||
const char *module_name = NULL);
|
||||
|
||||
void
|
||||
|
|
|
@ -82,7 +82,12 @@ public:
|
|||
///< \code
|
||||
/// // address for printf in libSystem.B.dylib as a load address
|
||||
/// 0x00007fff8306bcff \endcode
|
||||
DumpStyleResolvedDescription ///< Display the name that an address resolves to
|
||||
DumpStyleResolvedDescription, ///< Display the details about what an address resolves to. This can
|
||||
///< be anything from a symbol context summary (module, function/symbol,
|
||||
///< and file and line), to information about what the pointer points to
|
||||
///< if the address is in a section (section of pointers, c strings, etc).
|
||||
DumpStyleDetailedSymbolContext ///< Detailed symbol context information for an address for all symbol
|
||||
///< context members.
|
||||
} DumpStyle;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -221,7 +226,8 @@ public:
|
|||
Dump (Stream *s,
|
||||
ExecutionContextScope *exe_scope,
|
||||
DumpStyle style,
|
||||
DumpStyle fallback_style = DumpStyleInvalid) const;
|
||||
DumpStyle fallback_style = DumpStyleInvalid,
|
||||
uint32_t addr_byte_size = UINT32_MAX) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Dump a debug description of this object to a Stream.
|
||||
|
|
|
@ -42,8 +42,13 @@ public:
|
|||
GetByteSize() const = 0;
|
||||
|
||||
virtual void
|
||||
Dump (Stream *s, lldb::addr_t base_address, DataExtractor *bytes, uint32_t bytes_offset, const lldb_private::ExecutionContext exe_ctx, bool raw) = 0;
|
||||
|
||||
Dump (Stream *s,
|
||||
Address *address,
|
||||
const DataExtractor *bytes,
|
||||
uint32_t bytes_offset,
|
||||
const ExecutionContext &exe_ctx,
|
||||
bool raw) = 0;
|
||||
|
||||
virtual bool
|
||||
DoesBranch () const = 0;
|
||||
|
||||
|
@ -89,7 +94,36 @@ public:
|
|||
Disassemble (Debugger &debugger,
|
||||
const ArchSpec &arch,
|
||||
const ExecutionContext &exe_ctx,
|
||||
uint32_t mixed_context_lines,
|
||||
const AddressRange &range,
|
||||
uint32_t num_mixed_context_lines,
|
||||
bool show_bytes,
|
||||
Stream &strm);
|
||||
|
||||
static size_t
|
||||
Disassemble (Debugger &debugger,
|
||||
const ArchSpec &arch,
|
||||
const ExecutionContext &exe_ctx,
|
||||
SymbolContextList &sc_list,
|
||||
uint32_t num_mixed_context_lines,
|
||||
bool show_bytes,
|
||||
Stream &strm);
|
||||
|
||||
static bool
|
||||
Disassemble (Debugger &debugger,
|
||||
const ArchSpec &arch,
|
||||
const ExecutionContext &exe_ctx,
|
||||
const ConstString &name,
|
||||
Module *module,
|
||||
uint32_t num_mixed_context_lines,
|
||||
bool show_bytes,
|
||||
Stream &strm);
|
||||
|
||||
static bool
|
||||
Disassemble (Debugger &debugger,
|
||||
const ArchSpec &arch,
|
||||
const ExecutionContext &exe_ctx,
|
||||
uint32_t num_mixed_context_lines,
|
||||
bool show_bytes,
|
||||
Stream &strm);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -102,17 +136,14 @@ public:
|
|||
|
||||
size_t
|
||||
ParseInstructions (const ExecutionContext *exe_ctx,
|
||||
lldb::AddressType addr_type,
|
||||
lldb::addr_t addr,
|
||||
size_t byte_size,
|
||||
const AddressRange &range,
|
||||
DataExtractor& data);
|
||||
|
||||
virtual size_t
|
||||
ParseInstructions (const DataExtractor& data,
|
||||
uint32_t data_offset,
|
||||
uint32_t num_instructions,
|
||||
lldb::addr_t base_addr) = 0;
|
||||
|
||||
DecodeInstructions (const DataExtractor& data,
|
||||
uint32_t data_offset,
|
||||
uint32_t num_instructions) = 0;
|
||||
|
||||
InstructionList &
|
||||
GetInstructionList ();
|
||||
|
||||
|
|
|
@ -392,6 +392,9 @@ public:
|
|||
lldb::DataBufferSP
|
||||
ReadFileContents (off_t offset = 0, size_t length = SIZE_MAX) const;
|
||||
|
||||
size_t
|
||||
ReadFileContents (off_t file_offset, void *dst, size_t dst_len) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Change the file specificed with a new path.
|
||||
///
|
||||
|
|
|
@ -217,6 +217,9 @@ public:
|
|||
size_t
|
||||
MemoryMapSectionDataFromObjectFile (const ObjectFile* file, DataExtractor& section_data) const;
|
||||
|
||||
size_t
|
||||
ReadSectionDataFromObjectFile (const ObjectFile* objfile, off_t section_offset, void *dst, size_t dst_len) const;
|
||||
|
||||
size_t
|
||||
ReadSectionDataFromObjectFile (const ObjectFile* file, DataExtractor& section_data) const;
|
||||
|
||||
|
|
|
@ -264,13 +264,11 @@ public:
|
|||
GetTargetTriple (ConstString &target_triple);
|
||||
|
||||
size_t
|
||||
ReadMemory (lldb::AddressType addr_type,
|
||||
lldb::addr_t addr,
|
||||
void *buf,
|
||||
size_t size,
|
||||
Error &error,
|
||||
ObjectFile* objfile = NULL);
|
||||
|
||||
ReadMemory (const Address& addr,
|
||||
void *dst,
|
||||
size_t dst_len,
|
||||
Error &error);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// lldb::ExecutionContextScope pure virtual functions
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -384,9 +384,9 @@ SBTarget::GetBroadcaster () const
|
|||
}
|
||||
|
||||
void
|
||||
SBTarget::Disassemble (lldb::addr_t file_address_start, lldb::addr_t file_address_end, const char *module_name)
|
||||
SBTarget::Disassemble (lldb::addr_t start_addr, lldb::addr_t end_addr, const char *module_name)
|
||||
{
|
||||
if (file_address_start == LLDB_INVALID_ADDRESS)
|
||||
if (start_addr == LLDB_INVALID_ADDRESS)
|
||||
return;
|
||||
|
||||
FILE *out = m_opaque_sp->GetDebugger().GetOutputFileHandle();
|
||||
|
@ -395,61 +395,65 @@ SBTarget::Disassemble (lldb::addr_t file_address_start, lldb::addr_t file_addres
|
|||
|
||||
if (m_opaque_sp)
|
||||
{
|
||||
SBModule module;
|
||||
ModuleSP module_sp;
|
||||
if (module_name != NULL)
|
||||
{
|
||||
SBFileSpec file_spec (module_name);
|
||||
module = FindModule (file_spec);
|
||||
FileSpec module_file_spec (module_name);
|
||||
module_sp = m_opaque_sp->GetImages().FindFirstModuleForFileSpec (module_file_spec, NULL);
|
||||
}
|
||||
|
||||
AddressRange range;
|
||||
|
||||
// Make sure the process object is alive if we have one (it might be
|
||||
// created but we might not be launched yet).
|
||||
Process *process = m_opaque_sp->GetProcessSP().get();
|
||||
if (process && !process->IsAlive())
|
||||
process = NULL;
|
||||
|
||||
// If we are given a module, then "start_addr" is a file address in
|
||||
// that module.
|
||||
if (module_sp)
|
||||
{
|
||||
if (!module_sp->ResolveFileAddress (start_addr, range.GetBaseAddress()))
|
||||
range.GetBaseAddress().SetOffset(start_addr);
|
||||
}
|
||||
else if (process)
|
||||
{
|
||||
// We don't have a module, se we need to figure out if "start_addr"
|
||||
// resolves to anything in a running process.
|
||||
if (!process->ResolveLoadAddress(start_addr, range.GetBaseAddress()))
|
||||
range.GetBaseAddress().SetOffset(start_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_opaque_sp->GetImages().ResolveFileAddress (start_addr, range.GetBaseAddress()))
|
||||
range.GetBaseAddress().SetOffset(start_addr);
|
||||
}
|
||||
ArchSpec arch (m_opaque_sp->GetArchitecture());
|
||||
if (!arch.IsValid())
|
||||
return;
|
||||
Disassembler *disassembler = Disassembler::FindPlugin (arch);
|
||||
if (disassembler == NULL)
|
||||
return;
|
||||
|
||||
// For now, we need a process; the disassembly functions insist. If we don't have one already,
|
||||
// make one.
|
||||
|
||||
SBProcess process = GetProcess();
|
||||
if (! process.IsValid())
|
||||
process = CreateProcess();
|
||||
ExecutionContext exe_ctx;
|
||||
|
||||
ExecutionContext exe_context (process.get());
|
||||
if (process)
|
||||
process->Calculate(exe_ctx);
|
||||
else
|
||||
m_opaque_sp->Calculate(exe_ctx);
|
||||
|
||||
if (file_address_end == LLDB_INVALID_ADDRESS
|
||||
|| file_address_end < file_address_start)
|
||||
file_address_end = file_address_start + DEFAULT_DISASM_BYTE_SIZE;
|
||||
if (end_addr == LLDB_INVALID_ADDRESS || end_addr < start_addr)
|
||||
range.SetByteSize( DEFAULT_DISASM_BYTE_SIZE);
|
||||
else
|
||||
range.SetByteSize(end_addr - start_addr);
|
||||
|
||||
// TO BE FIXED: SOMEHOW WE NEED TO SPECIFY/USE THE MODULE, IF THE USER SPECIFIED ONE. I'M NOT
|
||||
// SURE HOW TO DO THAT AT THE MOMENT. WE ALSO NEED TO FIGURE OUT WHAT TO DO IF THERE ARE MULTIPLE
|
||||
// MODULES CONTAINING THE SPECIFIED ADDRESSES (E.G. THEY HAVEN'T ALL LOADED & BEEN GIVEN UNIQUE
|
||||
// ADDRESSES YET).
|
||||
StreamFile out_stream (out);
|
||||
|
||||
DataExtractor data;
|
||||
size_t bytes_disassembled = disassembler->ParseInstructions (&exe_context, eAddressTypeLoad,
|
||||
file_address_start,
|
||||
file_address_end - file_address_start, data);
|
||||
|
||||
if (bytes_disassembled > 0)
|
||||
{
|
||||
size_t num_instructions = disassembler->GetInstructionList().GetSize();
|
||||
uint32_t offset = 0;
|
||||
StreamFile out_stream (out);
|
||||
|
||||
for (size_t i = 0; i < num_instructions; ++i)
|
||||
{
|
||||
Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
|
||||
if (inst)
|
||||
{
|
||||
lldb::addr_t cur_addr = file_address_start + offset;
|
||||
size_t inst_byte_size = inst->GetByteSize();
|
||||
inst->Dump (&out_stream, cur_addr, &data, offset, exe_context, false);
|
||||
out_stream.EOL();
|
||||
offset += inst_byte_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
Disassembler::Disassemble (m_opaque_sp->GetDebugger(),
|
||||
m_opaque_sp->GetArchitecture(),
|
||||
exe_ctx,
|
||||
range,
|
||||
3,
|
||||
false,
|
||||
out_stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -465,102 +469,40 @@ SBTarget::Disassemble (const char *function_name, const char *module_name)
|
|||
|
||||
if (m_opaque_sp)
|
||||
{
|
||||
SBModule module;
|
||||
|
||||
if (module_name != NULL)
|
||||
{
|
||||
SBFileSpec file_spec (module_name);
|
||||
module = FindModule (file_spec);
|
||||
}
|
||||
|
||||
ArchSpec arch (m_opaque_sp->GetArchitecture());
|
||||
if (!arch.IsValid())
|
||||
return;
|
||||
|
||||
Disassembler *disassembler = Disassembler::FindPlugin (arch);
|
||||
Disassembler *disassembler = Disassembler::FindPlugin (m_opaque_sp->GetArchitecture());
|
||||
if (disassembler == NULL)
|
||||
return;
|
||||
|
||||
// For now, we need a process; the disassembly functions insist. If we don't have one already,
|
||||
// make one.
|
||||
|
||||
SBProcess process = GetProcess();
|
||||
if (! process.IsValid()
|
||||
|| process.GetProcessID() == 0)
|
||||
{
|
||||
fprintf (out, "Cannot disassemble functions until after process has launched.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ExecutionContext exe_context (process.get());
|
||||
|
||||
FileSpec *containing_module = NULL;
|
||||
|
||||
ModuleSP module_sp;
|
||||
if (module_name != NULL)
|
||||
containing_module = new FileSpec (module_name);
|
||||
|
||||
SearchFilterSP filter_sp (m_opaque_sp->GetSearchFilterForModule (containing_module));
|
||||
AddressResolverSP resolver_sp (new AddressResolverName (function_name));
|
||||
|
||||
resolver_sp->ResolveAddress (*filter_sp);
|
||||
|
||||
size_t num_matches_found = resolver_sp->GetNumberOfAddresses();
|
||||
|
||||
if (num_matches_found == 1)
|
||||
{
|
||||
DataExtractor data;
|
||||
|
||||
AddressRange func_addresses = resolver_sp->GetAddressRangeAtIndex (0);
|
||||
Address start_addr = func_addresses.GetBaseAddress();
|
||||
lldb::addr_t num_bytes = func_addresses.GetByteSize();
|
||||
|
||||
lldb::addr_t addr = LLDB_INVALID_ADDRESS;
|
||||
size_t bytes_disassembled = 0;
|
||||
|
||||
|
||||
if (process.GetProcessID() == 0)
|
||||
{
|
||||
// Leave this branch in for now, but it should not be reached, since we exit above if the PID is 0.
|
||||
addr = start_addr.GetFileAddress ();
|
||||
bytes_disassembled = disassembler->ParseInstructions (&exe_context, eAddressTypeFile, addr,
|
||||
num_bytes, data);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = start_addr.GetLoadAddress (process.get());
|
||||
bytes_disassembled = disassembler->ParseInstructions (&exe_context, eAddressTypeLoad, addr,
|
||||
num_bytes, data);
|
||||
|
||||
}
|
||||
|
||||
if (bytes_disassembled > 0)
|
||||
{
|
||||
size_t num_instructions = disassembler->GetInstructionList().GetSize();
|
||||
uint32_t offset = 0;
|
||||
StreamFile out_stream (out);
|
||||
|
||||
for (size_t i = 0; i < num_instructions; ++i)
|
||||
{
|
||||
Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
|
||||
if (inst)
|
||||
{
|
||||
lldb::addr_t cur_addr = addr + offset;
|
||||
size_t inst_byte_size = inst->GetByteSize();
|
||||
inst->Dump (&out_stream, cur_addr, &data, offset, exe_context, false);
|
||||
out_stream.EOL();
|
||||
offset += inst_byte_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
FileSpec module_file_spec (module_name);
|
||||
module_sp = m_opaque_sp->GetImages().FindFirstModuleForFileSpec (module_file_spec, NULL);
|
||||
}
|
||||
else if (num_matches_found > 1)
|
||||
{
|
||||
// TO BE FIXED: Eventually we want to list/disassemble all functions found.
|
||||
fprintf (out, "Function '%s' was found in multiple modules; please specify the desired module name.\n",
|
||||
function_name);
|
||||
}
|
||||
else
|
||||
fprintf (out, "Function '%s' was not found.\n", function_name);
|
||||
|
||||
ExecutionContext exe_ctx;
|
||||
|
||||
// Make sure the process object is alive if we have one (it might be
|
||||
// created but we might not be launched yet).
|
||||
Process *process = m_opaque_sp->GetProcessSP().get();
|
||||
if (process && !process->IsAlive())
|
||||
process = NULL;
|
||||
|
||||
if (process)
|
||||
process->Calculate(exe_ctx);
|
||||
else
|
||||
m_opaque_sp->Calculate(exe_ctx);
|
||||
|
||||
|
||||
StreamFile out_stream (out);
|
||||
|
||||
Disassembler::Disassemble (m_opaque_sp->GetDebugger(),
|
||||
m_opaque_sp->GetArchitecture(),
|
||||
exe_ctx,
|
||||
ConstString (function_name),
|
||||
module_sp.get(),
|
||||
3,
|
||||
false,
|
||||
out_stream);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,135 +152,6 @@ CommandObjectDisassemble::~CommandObjectDisassemble()
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
CommandObjectDisassemble::Disassemble
|
||||
(
|
||||
CommandInterpreter &interpreter,
|
||||
CommandReturnObject &result,
|
||||
Disassembler *disassembler,
|
||||
const SymbolContextList &sc_list
|
||||
)
|
||||
{
|
||||
const size_t count = sc_list.GetSize();
|
||||
SymbolContext sc;
|
||||
AddressRange range;
|
||||
for (size_t i=0; i<count; ++i)
|
||||
{
|
||||
if (sc_list.GetContextAtIndex(i, sc) == false)
|
||||
break;
|
||||
if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
|
||||
{
|
||||
lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(interpreter.GetDebugger().GetExecutionContext().process);
|
||||
if (addr != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
lldb::addr_t end_addr = addr + range.GetByteSize();
|
||||
Disassemble (interpreter, result, disassembler, addr, end_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CommandObjectDisassemble::Disassemble
|
||||
(
|
||||
CommandInterpreter &interpreter,
|
||||
CommandReturnObject &result,
|
||||
Disassembler *disassembler,
|
||||
lldb::addr_t addr,
|
||||
lldb::addr_t end_addr
|
||||
)
|
||||
{
|
||||
if (addr == LLDB_INVALID_ADDRESS)
|
||||
return;
|
||||
|
||||
if (end_addr == LLDB_INVALID_ADDRESS || addr >= end_addr)
|
||||
end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
|
||||
|
||||
ExecutionContext exe_ctx (interpreter.GetDebugger().GetExecutionContext());
|
||||
DataExtractor data;
|
||||
size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, eAddressTypeLoad, addr, end_addr - addr, data);
|
||||
if (bytes_disassembled == 0)
|
||||
{
|
||||
// Nothing got disassembled...
|
||||
}
|
||||
else
|
||||
{
|
||||
// We got some things disassembled...
|
||||
size_t num_instructions = disassembler->GetInstructionList().GetSize();
|
||||
uint32_t offset = 0;
|
||||
Stream &output_stream = result.GetOutputStream();
|
||||
SymbolContext sc;
|
||||
SymbolContext prev_sc;
|
||||
AddressRange sc_range;
|
||||
if (m_options.show_mixed)
|
||||
output_stream.IndentMore ();
|
||||
|
||||
for (size_t i=0; i<num_instructions; ++i)
|
||||
{
|
||||
Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
|
||||
if (inst)
|
||||
{
|
||||
lldb::addr_t curr_addr = addr + offset;
|
||||
if (m_options.show_mixed)
|
||||
{
|
||||
Process *process = interpreter.GetDebugger().GetExecutionContext().process;
|
||||
if (!sc_range.ContainsLoadAddress (curr_addr, process))
|
||||
{
|
||||
prev_sc = sc;
|
||||
Address curr_so_addr;
|
||||
if (process && process->ResolveLoadAddress (curr_addr, curr_so_addr))
|
||||
{
|
||||
if (curr_so_addr.GetSection())
|
||||
{
|
||||
Module *module = curr_so_addr.GetSection()->GetModule();
|
||||
uint32_t resolved_mask = module->ResolveSymbolContextForAddress(curr_so_addr, eSymbolContextEverything, sc);
|
||||
if (resolved_mask)
|
||||
{
|
||||
sc.GetAddressRange (eSymbolContextEverything, sc_range);
|
||||
if (sc != prev_sc)
|
||||
{
|
||||
if (offset != 0)
|
||||
output_stream.EOL();
|
||||
|
||||
sc.DumpStopContext(&output_stream, process, curr_so_addr);
|
||||
output_stream.EOL();
|
||||
if (sc.comp_unit && sc.line_entry.IsValid())
|
||||
{
|
||||
interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (
|
||||
sc.line_entry.file,
|
||||
sc.line_entry.line,
|
||||
m_options.num_lines_context,
|
||||
m_options.num_lines_context,
|
||||
m_options.num_lines_context ? "->" : "",
|
||||
&output_stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_options.show_mixed)
|
||||
output_stream.IndentMore ();
|
||||
output_stream.Indent();
|
||||
size_t inst_byte_size = inst->GetByteSize();
|
||||
inst->Dump(&output_stream, curr_addr, m_options.show_bytes ? &data : NULL, offset, exe_ctx, m_options.raw);
|
||||
output_stream.EOL();
|
||||
offset += inst_byte_size;
|
||||
if (m_options.show_mixed)
|
||||
output_stream.IndentLess ();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_options.show_mixed)
|
||||
output_stream.IndentLess ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CommandObjectDisassemble::Execute
|
||||
(
|
||||
|
@ -316,99 +187,94 @@ CommandObjectDisassemble::Execute
|
|||
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
|
||||
lldb::addr_t addr = LLDB_INVALID_ADDRESS;
|
||||
lldb::addr_t end_addr = LLDB_INVALID_ADDRESS;
|
||||
ConstString name;
|
||||
const size_t argc = command.GetArgumentCount();
|
||||
if (argc != 0)
|
||||
if (command.GetArgumentCount() != 0)
|
||||
{
|
||||
result.AppendErrorWithFormat ("\"disassemble\" doesn't take any arguments.\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_options.m_start_addr != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
addr = m_options.m_start_addr;
|
||||
if (m_options.m_end_addr != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
end_addr = m_options.m_end_addr;
|
||||
if (end_addr < addr)
|
||||
{
|
||||
result.AppendErrorWithFormat ("End address before start address.\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
|
||||
}
|
||||
else if (!m_options.m_func_name.empty())
|
||||
{
|
||||
ConstString tmpname(m_options.m_func_name.c_str());
|
||||
name = tmpname;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
|
||||
if (exe_ctx.frame)
|
||||
{
|
||||
SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
|
||||
if (sc.function)
|
||||
{
|
||||
addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(exe_ctx.process);
|
||||
if (addr != LLDB_INVALID_ADDRESS)
|
||||
end_addr = addr + sc.function->GetAddressRange().GetByteSize();
|
||||
}
|
||||
else if (sc.symbol && sc.symbol->GetAddressRangePtr())
|
||||
{
|
||||
addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetLoadAddress(exe_ctx.process);
|
||||
if (addr != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
end_addr = addr + sc.symbol->GetAddressRangePtr()->GetByteSize();
|
||||
if (addr == end_addr)
|
||||
end_addr += DEFAULT_DISASM_BYTE_SIZE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = exe_ctx.frame->GetPC().GetLoadAddress(exe_ctx.process);
|
||||
if (addr != LLDB_INVALID_ADDRESS)
|
||||
end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("invalid frame");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
|
||||
|
||||
if (!name.IsEmpty())
|
||||
{
|
||||
SymbolContextList sc_list;
|
||||
if (m_options.show_mixed && m_options.num_lines_context == 0)
|
||||
m_options.num_lines_context = 3;
|
||||
|
||||
if (target->GetImages().FindFunctions(name,
|
||||
eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
|
||||
sc_list))
|
||||
if (!m_options.m_func_name.empty())
|
||||
{
|
||||
ConstString name(m_options.m_func_name.c_str());
|
||||
|
||||
if (Disassembler::Disassemble (interpreter.GetDebugger(),
|
||||
arch,
|
||||
exe_ctx,
|
||||
name,
|
||||
NULL, // Module *
|
||||
m_options.show_mixed ? m_options.num_lines_context : 0,
|
||||
m_options.show_bytes,
|
||||
result.GetOutputStream()))
|
||||
{
|
||||
Disassemble (interpreter, result, disassembler, sc_list);
|
||||
}
|
||||
else if (target->GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeCode, sc_list))
|
||||
{
|
||||
Disassemble (interpreter, result, disassembler, sc_list);
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Disassemble (interpreter, result, disassembler, addr, end_addr);
|
||||
AddressRange range;
|
||||
if (m_options.m_start_addr != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
range.GetBaseAddress().SetOffset (m_options.m_start_addr);
|
||||
if (m_options.m_end_addr != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
if (m_options.m_end_addr < m_options.m_start_addr)
|
||||
{
|
||||
result.AppendErrorWithFormat ("End address before start address.\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
range.SetByteSize (m_options.m_end_addr - m_options.m_start_addr);
|
||||
}
|
||||
else
|
||||
range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (exe_ctx.frame)
|
||||
{
|
||||
SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
|
||||
if (sc.function)
|
||||
range = sc.function->GetAddressRange();
|
||||
else if (sc.symbol && sc.symbol->GetAddressRangePtr())
|
||||
range = *sc.symbol->GetAddressRangePtr();
|
||||
else
|
||||
range.GetBaseAddress() = exe_ctx.frame->GetPC();
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("invalid frame");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (range.GetByteSize() == 0)
|
||||
range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
|
||||
|
||||
if (Disassembler::Disassemble (interpreter.GetDebugger(),
|
||||
arch,
|
||||
exe_ctx,
|
||||
range,
|
||||
m_options.show_mixed ? m_options.num_lines_context : 0,
|
||||
m_options.show_bytes,
|
||||
result.GetOutputStream()))
|
||||
{
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
}
|
||||
|
||||
return result.Succeeded();
|
||||
|
|
|
@ -74,18 +74,6 @@ public:
|
|||
protected:
|
||||
CommandOptions m_options;
|
||||
|
||||
void
|
||||
Disassemble (CommandInterpreter &interpreter,
|
||||
CommandReturnObject &result,
|
||||
Disassembler *disassembler,
|
||||
lldb::addr_t addr,
|
||||
lldb::addr_t end_addr);
|
||||
|
||||
void
|
||||
Disassemble (CommandInterpreter &interpreter,
|
||||
CommandReturnObject &result,
|
||||
Disassembler *disassembler,
|
||||
const SymbolContextList &sc_list);
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
|
|
@ -231,7 +231,11 @@ LookupAddressInModule (CommandInterpreter &interpreter, Stream &strm, Module *mo
|
|||
strm.Indent (" Address: ");
|
||||
so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset);
|
||||
strm.EOL();
|
||||
strm.Indent (" Summary: ");
|
||||
so_addr.Dump (&strm, exe_scope, Address::DumpStyleResolvedDescription);
|
||||
strm.EOL();
|
||||
if (so_addr.Dump (&strm, exe_scope, Address::DumpStyleDetailedSymbolContext))
|
||||
strm.EOL();
|
||||
strm.IndentLess();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -17,39 +17,57 @@
|
|||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
//static size_t
|
||||
//ReadBytes (ExecutionContextScope *exe_scope, const Address &address, void *dst, size_t dst_len)
|
||||
//{
|
||||
// if (exe_scope == NULL)
|
||||
// return 0;
|
||||
//
|
||||
// lldb::AddressType addr_type = eAddressTypeInvalid;
|
||||
// addr_t addr = LLDB_INVALID_ADDRESS;
|
||||
//
|
||||
// Process *process = exe_scope->CalculateProcess();
|
||||
//
|
||||
// if (process && process->IsAlive())
|
||||
// {
|
||||
// addr = address.GetLoadAddress(process);
|
||||
// if (addr != LLDB_INVALID_ADDRESS)
|
||||
// addr_type = eAddressTypeLoad;
|
||||
// }
|
||||
//
|
||||
// if (addr == LLDB_INVALID_ADDRESS)
|
||||
// {
|
||||
// addr = address.GetFileAddress();
|
||||
// if (addr != LLDB_INVALID_ADDRESS)
|
||||
// addr_type = eAddressTypeFile;
|
||||
// }
|
||||
//
|
||||
// if (addr_type == eAddressTypeInvalid)
|
||||
// return false;
|
||||
//
|
||||
// Target *target = exe_scope->CalculateTarget();
|
||||
// if (target)
|
||||
// {
|
||||
// Error error;
|
||||
// ObjectFile *objfile = NULL;
|
||||
// if (address.GetModule())
|
||||
// objfile = address.GetModule()->GetObjectFile();
|
||||
// return target->ReadMemory (addr_type, addr, dst, dst_len, error, objfile);
|
||||
// }
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
static size_t
|
||||
ReadBytes (ExecutionContextScope *exe_scope, const Address &address, void *dst, size_t dst_len)
|
||||
{
|
||||
if (exe_scope == NULL)
|
||||
return 0;
|
||||
|
||||
lldb::AddressType addr_type = eAddressTypeInvalid;
|
||||
addr_t addr = LLDB_INVALID_ADDRESS;
|
||||
|
||||
Process *process = exe_scope->CalculateProcess();
|
||||
|
||||
if (process && process->IsAlive())
|
||||
{
|
||||
addr = address.GetLoadAddress(process);
|
||||
if (addr != LLDB_INVALID_ADDRESS)
|
||||
addr_type = eAddressTypeLoad;
|
||||
}
|
||||
|
||||
if (addr == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
addr = address.GetFileAddress();
|
||||
if (addr != LLDB_INVALID_ADDRESS)
|
||||
addr_type = eAddressTypeFile;
|
||||
}
|
||||
|
||||
if (addr_type == eAddressTypeInvalid)
|
||||
return false;
|
||||
|
||||
Target *target = exe_scope->CalculateTarget();
|
||||
if (target)
|
||||
{
|
||||
Error error;
|
||||
return target->ReadMemory (addr_type, addr, dst, dst_len, error, NULL);
|
||||
return target->ReadMemory (address, dst, dst_len, error);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -386,7 +404,7 @@ Address::Clear()
|
|||
|
||||
|
||||
bool
|
||||
Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style) const
|
||||
Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style, uint32_t addr_size) const
|
||||
{
|
||||
// If the section was NULL, only load address is going to work.
|
||||
if (m_section == NULL)
|
||||
|
@ -395,12 +413,17 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
|
|||
Process *process = NULL;
|
||||
if (exe_scope)
|
||||
process = exe_scope->CalculateProcess();
|
||||
int addr_size = sizeof (addr_t);
|
||||
if (process)
|
||||
addr_size = process->GetAddressByteSize ();
|
||||
// If addr_byte_size is UINT32_MAX, then determine the correct address
|
||||
// byte size for the process or default to the size of addr_t
|
||||
if (addr_size == UINT32_MAX)
|
||||
{
|
||||
if (process)
|
||||
addr_size = process->GetAddressByteSize ();
|
||||
else
|
||||
addr_size = sizeof(addr_t);
|
||||
}
|
||||
|
||||
lldb_private::Address so_addr;
|
||||
|
||||
switch (style)
|
||||
{
|
||||
case DumpStyleSectionNameOffset:
|
||||
|
@ -411,12 +434,13 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
|
|||
}
|
||||
else
|
||||
{
|
||||
s->Printf("0x%16.16llx", m_offset);
|
||||
s->Address(m_offset, addr_size);
|
||||
}
|
||||
break;
|
||||
|
||||
case DumpStyleSectionPointerOffset:
|
||||
s->Printf("(Section *)%.*p + 0x%16.16llx", (int)sizeof(void*) * 2, m_section, m_offset);
|
||||
s->Printf("(Section *)%.*p + ", (int)sizeof(void*) * 2, m_section);
|
||||
s->Address(m_offset, addr_size);
|
||||
break;
|
||||
|
||||
case DumpStyleModuleWithFileAddress:
|
||||
|
@ -428,7 +452,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
|
|||
if (file_addr == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
if (fallback_style != DumpStyleInvalid)
|
||||
return Dump (s, exe_scope, fallback_style);
|
||||
return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
|
||||
return false;
|
||||
}
|
||||
s->Address (file_addr, addr_size);
|
||||
|
@ -443,7 +467,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
|
|||
if (load_addr == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
if (fallback_style != DumpStyleInvalid)
|
||||
return Dump (s, exe_scope, fallback_style);
|
||||
return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
|
||||
return false;
|
||||
}
|
||||
s->Address (load_addr, addr_size);
|
||||
|
@ -592,13 +616,17 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
|
|||
if (so_addr.IsSectionOffset())
|
||||
{
|
||||
lldb_private::SymbolContext pointer_sc;
|
||||
process->GetTarget().GetImages().ResolveSymbolContextForAddress (so_addr,
|
||||
eSymbolContextEverything,
|
||||
pointer_sc);
|
||||
if (pointer_sc.function || pointer_sc.symbol)
|
||||
Target *target = exe_scope->CalculateTarget();
|
||||
if (target)
|
||||
{
|
||||
s->PutCString(": ");
|
||||
pointer_sc.DumpStopContext(s, process, so_addr, false);
|
||||
target->GetImages().ResolveSymbolContextForAddress (so_addr,
|
||||
eSymbolContextEverything,
|
||||
pointer_sc);
|
||||
if (pointer_sc.function || pointer_sc.symbol)
|
||||
{
|
||||
s->PutCString(": ");
|
||||
pointer_sc.DumpStopContext(s, process, so_addr, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -629,10 +657,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
|
|||
{
|
||||
// We have a function or a symbol from the same
|
||||
// sections as this address.
|
||||
s->Indent(" Summary: ");
|
||||
sc.DumpStopContext(s, process, *this, false);
|
||||
s->EOL();
|
||||
sc.GetDescription(s, eDescriptionLevelBrief, process);
|
||||
sc.DumpStopContext(s, process, *this, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -648,10 +673,45 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
|
|||
else
|
||||
{
|
||||
if (fallback_style != DumpStyleInvalid)
|
||||
return Dump (s, exe_scope, fallback_style);
|
||||
return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case DumpStyleDetailedSymbolContext:
|
||||
if (IsSectionOffset())
|
||||
{
|
||||
lldb::AddressType addr_type = eAddressTypeLoad;
|
||||
addr_t addr = GetLoadAddress (process);
|
||||
if (addr == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
addr = GetFileAddress();
|
||||
addr_type = eAddressTypeFile;
|
||||
}
|
||||
|
||||
lldb_private::Module *module = GetModule();
|
||||
if (module)
|
||||
{
|
||||
lldb_private::SymbolContext sc;
|
||||
module->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc);
|
||||
if (sc.function || sc.symbol)
|
||||
{
|
||||
if (sc.function == NULL && sc.symbol != NULL)
|
||||
{
|
||||
// If we have just a symbol make sure it is in the right section
|
||||
if (sc.symbol->GetAddressRangePtr() && sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetSection() == GetSection())
|
||||
{
|
||||
sc.GetDescription(s, eDescriptionLevelBrief, process);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fallback_style != DumpStyleInvalid)
|
||||
return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -52,53 +52,121 @@ Disassembler::FindPlugin (const ArchSpec &arch)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t
|
||||
Disassembler::Disassemble
|
||||
(
|
||||
Debugger &debugger,
|
||||
const ArchSpec &arch,
|
||||
const ExecutionContext &exe_ctx,
|
||||
SymbolContextList &sc_list,
|
||||
uint32_t num_mixed_context_lines,
|
||||
bool show_bytes,
|
||||
Stream &strm
|
||||
)
|
||||
{
|
||||
size_t success_count = 0;
|
||||
const size_t count = sc_list.GetSize();
|
||||
SymbolContext sc;
|
||||
AddressRange range;
|
||||
for (size_t i=0; i<count; ++i)
|
||||
{
|
||||
if (sc_list.GetContextAtIndex(i, sc) == false)
|
||||
break;
|
||||
if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
|
||||
{
|
||||
if (Disassemble (debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, strm))
|
||||
{
|
||||
++success_count;
|
||||
strm.EOL();
|
||||
}
|
||||
}
|
||||
}
|
||||
return success_count;
|
||||
}
|
||||
|
||||
bool
|
||||
Disassembler::Disassemble
|
||||
(
|
||||
Debugger &debugger,
|
||||
const ArchSpec &arch,
|
||||
const ExecutionContext &exe_ctx,
|
||||
uint32_t mixed_context_lines,
|
||||
const ConstString &name,
|
||||
Module *module,
|
||||
uint32_t num_mixed_context_lines,
|
||||
bool show_bytes,
|
||||
Stream &strm
|
||||
)
|
||||
{
|
||||
Disassembler *disassembler = Disassembler::FindPlugin(arch);
|
||||
if (exe_ctx.target == NULL && name)
|
||||
return false;
|
||||
|
||||
if (disassembler)
|
||||
SymbolContextList sc_list;
|
||||
|
||||
if (module)
|
||||
{
|
||||
lldb::addr_t addr = LLDB_INVALID_ADDRESS;
|
||||
size_t byte_size = 0;
|
||||
if (exe_ctx.frame)
|
||||
if (!module->FindFunctions (name,
|
||||
eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
|
||||
true,
|
||||
sc_list))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (exe_ctx.target->GetImages().FindFunctions (name,
|
||||
eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
|
||||
sc_list))
|
||||
{
|
||||
SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
|
||||
if (sc.function)
|
||||
return Disassemble (debugger, arch, exe_ctx, sc_list, num_mixed_context_lines, show_bytes, strm);
|
||||
}
|
||||
else if (exe_ctx.target->GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeCode, sc_list))
|
||||
{
|
||||
return Disassemble (debugger, arch, exe_ctx, sc_list, num_mixed_context_lines, show_bytes, strm);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Disassembler::Disassemble
|
||||
(
|
||||
Debugger &debugger,
|
||||
const ArchSpec &arch,
|
||||
const ExecutionContext &exe_ctx,
|
||||
const AddressRange &disasm_range,
|
||||
uint32_t num_mixed_context_lines,
|
||||
bool show_bytes,
|
||||
Stream &strm
|
||||
)
|
||||
{
|
||||
if (disasm_range.GetByteSize())
|
||||
{
|
||||
Disassembler *disassembler = Disassembler::FindPlugin(arch);
|
||||
|
||||
if (disassembler)
|
||||
{
|
||||
AddressRange range(disasm_range);
|
||||
|
||||
Process *process = exe_ctx.process;
|
||||
|
||||
// If we weren't passed in a section offset address range,
|
||||
// try and resolve it to something
|
||||
if (range.GetBaseAddress().IsSectionOffset() == false)
|
||||
{
|
||||
addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(exe_ctx.process);
|
||||
if (addr != LLDB_INVALID_ADDRESS)
|
||||
byte_size = sc.function->GetAddressRange().GetByteSize();
|
||||
}
|
||||
else if (sc.symbol && sc.symbol->GetAddressRangePtr())
|
||||
{
|
||||
addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetLoadAddress(exe_ctx.process);
|
||||
if (addr != LLDB_INVALID_ADDRESS)
|
||||
if (process && process->IsAlive())
|
||||
{
|
||||
byte_size = sc.symbol->GetAddressRangePtr()->GetByteSize();
|
||||
if (byte_size == 0)
|
||||
byte_size = DEFAULT_DISASM_BYTE_SIZE;
|
||||
process->ResolveLoadAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
|
||||
}
|
||||
else if (exe_ctx.target)
|
||||
{
|
||||
exe_ctx.target->GetImages().ResolveFileAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = exe_ctx.frame->GetPC().GetLoadAddress(exe_ctx.process);
|
||||
if (addr != LLDB_INVALID_ADDRESS)
|
||||
byte_size = DEFAULT_DISASM_BYTE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
if (byte_size)
|
||||
{
|
||||
|
||||
DataExtractor data;
|
||||
size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, eAddressTypeLoad, addr, byte_size, data);
|
||||
size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, range, data);
|
||||
if (bytes_disassembled == 0)
|
||||
{
|
||||
return false;
|
||||
|
@ -111,63 +179,94 @@ Disassembler::Disassemble
|
|||
SymbolContext sc;
|
||||
SymbolContext prev_sc;
|
||||
AddressRange sc_range;
|
||||
if (mixed_context_lines)
|
||||
if (num_mixed_context_lines)
|
||||
strm.IndentMore ();
|
||||
|
||||
|
||||
Address addr(range.GetBaseAddress());
|
||||
|
||||
// We extract the section to make sure we don't transition out
|
||||
// of the current section when disassembling
|
||||
const Section *addr_section = addr.GetSection();
|
||||
Module *range_module = range.GetBaseAddress().GetModule();
|
||||
|
||||
for (size_t i=0; i<num_instructions; ++i)
|
||||
{
|
||||
Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
|
||||
if (inst)
|
||||
{
|
||||
lldb::addr_t curr_addr = addr + offset;
|
||||
if (mixed_context_lines)
|
||||
addr_t file_addr = addr.GetFileAddress();
|
||||
if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false)
|
||||
{
|
||||
if (!sc_range.ContainsLoadAddress (curr_addr, exe_ctx.process))
|
||||
if (range_module)
|
||||
range_module->ResolveFileAddress (file_addr, addr);
|
||||
else if (exe_ctx.target)
|
||||
exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr);
|
||||
|
||||
addr_section = addr.GetSection();
|
||||
}
|
||||
|
||||
prev_sc = sc;
|
||||
|
||||
if (addr_section)
|
||||
{
|
||||
Module *module = addr_section->GetModule();
|
||||
uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
|
||||
if (resolved_mask)
|
||||
{
|
||||
prev_sc = sc;
|
||||
Address curr_so_addr;
|
||||
Process *process = exe_ctx.process;
|
||||
if (process && process->ResolveLoadAddress (curr_addr, curr_so_addr))
|
||||
if (prev_sc.function != sc.function || prev_sc.symbol != sc.symbol)
|
||||
{
|
||||
if (curr_so_addr.GetSection())
|
||||
if (prev_sc.function || prev_sc.symbol)
|
||||
strm.EOL();
|
||||
|
||||
strm << sc.module_sp->GetFileSpec().GetFilename();
|
||||
|
||||
if (sc.function)
|
||||
strm << '`' << sc.function->GetMangled().GetName();
|
||||
else if (sc.symbol)
|
||||
strm << '`' << sc.symbol->GetMangled().GetName();
|
||||
strm << ":\n";
|
||||
}
|
||||
|
||||
if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr))
|
||||
{
|
||||
sc.GetAddressRange (eSymbolContextEverything, sc_range);
|
||||
|
||||
if (sc != prev_sc)
|
||||
{
|
||||
Module *module = curr_so_addr.GetSection()->GetModule();
|
||||
uint32_t resolved_mask = module->ResolveSymbolContextForAddress(curr_so_addr, eSymbolContextEverything, sc);
|
||||
if (resolved_mask)
|
||||
if (offset != 0)
|
||||
strm.EOL();
|
||||
|
||||
sc.DumpStopContext(&strm, process, addr);
|
||||
|
||||
if (sc.comp_unit && sc.line_entry.IsValid())
|
||||
{
|
||||
sc.GetAddressRange (eSymbolContextEverything, sc_range);
|
||||
if (sc != prev_sc)
|
||||
{
|
||||
if (offset != 0)
|
||||
strm.EOL();
|
||||
|
||||
sc.DumpStopContext(&strm, process, curr_so_addr);
|
||||
|
||||
if (sc.comp_unit && sc.line_entry.IsValid())
|
||||
{
|
||||
debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (
|
||||
sc.line_entry.file,
|
||||
sc.line_entry.line,
|
||||
mixed_context_lines,
|
||||
mixed_context_lines,
|
||||
mixed_context_lines ? "->" : "",
|
||||
&strm);
|
||||
}
|
||||
}
|
||||
debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
|
||||
sc.line_entry.line,
|
||||
num_mixed_context_lines,
|
||||
num_mixed_context_lines,
|
||||
num_mixed_context_lines ? "->" : "",
|
||||
&strm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.Clear();
|
||||
}
|
||||
}
|
||||
if (mixed_context_lines)
|
||||
if (num_mixed_context_lines)
|
||||
strm.IndentMore ();
|
||||
strm.Indent();
|
||||
size_t inst_byte_size = inst->GetByteSize();
|
||||
//inst->Dump(&strm, curr_addr, &data, offset); // Do dump opcode bytes
|
||||
inst->Dump(&strm, curr_addr, NULL, offset, exe_ctx, false); // Don't dump opcode bytes
|
||||
inst->Dump(&strm, &addr, show_bytes ? &data : NULL, offset, exe_ctx, show_bytes);
|
||||
strm.EOL();
|
||||
offset += inst_byte_size;
|
||||
if (mixed_context_lines)
|
||||
|
||||
addr.SetOffset (addr.GetOffset() + inst_byte_size);
|
||||
|
||||
if (num_mixed_context_lines)
|
||||
strm.IndentLess ();
|
||||
}
|
||||
else
|
||||
|
@ -175,7 +274,7 @@ Disassembler::Disassemble
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (mixed_context_lines)
|
||||
if (num_mixed_context_lines)
|
||||
strm.IndentLess ();
|
||||
|
||||
}
|
||||
|
@ -185,6 +284,42 @@ Disassembler::Disassemble
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Disassembler::Disassemble
|
||||
(
|
||||
Debugger &debugger,
|
||||
const ArchSpec &arch,
|
||||
const ExecutionContext &exe_ctx,
|
||||
uint32_t num_mixed_context_lines,
|
||||
bool show_bytes,
|
||||
Stream &strm
|
||||
)
|
||||
{
|
||||
AddressRange range;
|
||||
if (exe_ctx.frame)
|
||||
{
|
||||
SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
|
||||
if (sc.function)
|
||||
{
|
||||
range = sc.function->GetAddressRange();
|
||||
}
|
||||
else if (sc.symbol && sc.symbol->GetAddressRangePtr())
|
||||
{
|
||||
range = *sc.symbol->GetAddressRangePtr();
|
||||
}
|
||||
else
|
||||
{
|
||||
range.GetBaseAddress() = exe_ctx.frame->GetPC();
|
||||
}
|
||||
|
||||
if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
|
||||
range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
|
||||
}
|
||||
|
||||
return Disassemble(debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, strm);
|
||||
}
|
||||
|
||||
Disassembler::Instruction::Instruction()
|
||||
{
|
||||
}
|
||||
|
@ -244,26 +379,39 @@ size_t
|
|||
Disassembler::ParseInstructions
|
||||
(
|
||||
const ExecutionContext *exe_ctx,
|
||||
lldb::AddressType addr_type,
|
||||
lldb::addr_t addr,
|
||||
size_t byte_size,
|
||||
const AddressRange &range,
|
||||
DataExtractor& data
|
||||
)
|
||||
{
|
||||
Process *process = exe_ctx->process;
|
||||
Target *target = exe_ctx->target;
|
||||
|
||||
if (process == NULL)
|
||||
const addr_t byte_size = range.GetByteSize();
|
||||
if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
|
||||
return 0;
|
||||
|
||||
DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0'));
|
||||
DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
|
||||
DataBufferSP data_sp(heap_buffer);
|
||||
|
||||
Error error;
|
||||
if (process->GetTarget().ReadMemory (addr_type, addr, data_sp->GetBytes(), data_sp->GetByteSize(), error, NULL))
|
||||
const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), heap_buffer->GetBytes(), heap_buffer->GetByteSize(), error);
|
||||
|
||||
if (bytes_read > 0)
|
||||
{
|
||||
if (bytes_read != heap_buffer->GetByteSize())
|
||||
heap_buffer->SetByteSize (bytes_read);
|
||||
|
||||
data.SetData(data_sp);
|
||||
data.SetByteOrder(process->GetByteOrder());
|
||||
data.SetAddressByteSize(process->GetAddressByteSize());
|
||||
return ParseInstructions (data, 0, UINT32_MAX, addr);
|
||||
if (exe_ctx->process)
|
||||
{
|
||||
data.SetByteOrder(exe_ctx->process->GetByteOrder());
|
||||
data.SetAddressByteSize(exe_ctx->process->GetAddressByteSize());
|
||||
}
|
||||
else
|
||||
{
|
||||
data.SetByteOrder(target->GetArchitecture().GetDefaultEndian());
|
||||
data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
|
||||
}
|
||||
return DecodeInstructions (data, 0, UINT32_MAX);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -496,21 +496,11 @@ FileSpec::MemorySize() const
|
|||
return m_filename.MemorySize() + m_directory.MemorySize();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Returns a shared pointer to a data buffer that contains all or
|
||||
// part of the contents of a file. The data copies into a heap based
|
||||
// buffer that lives in the DataBuffer shared pointer object returned.
|
||||
// The data that is cached will start "file_offset" bytes into the
|
||||
// file, and "file_size" bytes will be mapped. If "file_size" is
|
||||
// greater than the number of bytes available in the file starting
|
||||
// at "file_offset", the number of bytes will be appropriately
|
||||
// truncated. The final number of bytes that get mapped can be
|
||||
// verified using the DataBuffer::GetByteSize() function.
|
||||
//------------------------------------------------------------------
|
||||
DataBufferSP
|
||||
FileSpec::ReadFileContents(off_t file_offset, size_t file_size) const
|
||||
|
||||
size_t
|
||||
FileSpec::ReadFileContents (off_t file_offset, void *dst, size_t dst_len) const
|
||||
{
|
||||
DataBufferSP data_sp;
|
||||
size_t bytes_read = 0;
|
||||
char resolved_path[PATH_MAX];
|
||||
if (GetPath(resolved_path, sizeof(resolved_path)))
|
||||
{
|
||||
|
@ -521,6 +511,50 @@ FileSpec::ReadFileContents(off_t file_offset, size_t file_size) const
|
|||
if (::fstat (fd, &file_stats) == 0)
|
||||
{
|
||||
// Read bytes directly into our basic_string buffer
|
||||
if (file_stats.st_size > 0)
|
||||
{
|
||||
off_t lseek_result = 0;
|
||||
if (file_offset > 0)
|
||||
lseek_result = ::lseek (fd, file_offset, SEEK_SET);
|
||||
|
||||
if (lseek_result == file_offset)
|
||||
{
|
||||
ssize_t n = ::read (fd, dst, dst_len);
|
||||
if (n >= 0)
|
||||
bytes_read = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Returns a shared pointer to a data buffer that contains all or
|
||||
// part of the contents of a file. The data copies into a heap based
|
||||
// buffer that lives in the DataBuffer shared pointer object returned.
|
||||
// The data that is cached will start "file_offset" bytes into the
|
||||
// file, and "file_size" bytes will be mapped. If "file_size" is
|
||||
// greater than the number of bytes available in the file starting
|
||||
// at "file_offset", the number of bytes will be appropriately
|
||||
// truncated. The final number of bytes that get mapped can be
|
||||
// verified using the DataBuffer::GetByteSize() function.
|
||||
//------------------------------------------------------------------
|
||||
DataBufferSP
|
||||
FileSpec::ReadFileContents (off_t file_offset, size_t file_size) const
|
||||
{
|
||||
DataBufferSP data_sp;
|
||||
char resolved_path[PATH_MAX];
|
||||
if (GetPath(resolved_path, sizeof(resolved_path)))
|
||||
{
|
||||
int fd = ::open (resolved_path, O_RDONLY, 0);
|
||||
if (fd != -1)
|
||||
{
|
||||
struct stat file_stats;
|
||||
if (::fstat (fd, &file_stats) == 0)
|
||||
{
|
||||
if (file_stats.st_size > 0)
|
||||
{
|
||||
off_t lseek_result = 0;
|
||||
|
@ -533,11 +567,13 @@ FileSpec::ReadFileContents(off_t file_offset, size_t file_size) const
|
|||
}
|
||||
else if (lseek_result == file_offset)
|
||||
{
|
||||
const size_t bytes_left = file_stats.st_size - file_offset;
|
||||
size_t num_bytes_to_read = file_size;
|
||||
if (num_bytes_to_read > bytes_left)
|
||||
num_bytes_to_read = bytes_left;
|
||||
|
||||
std::auto_ptr<DataBufferHeap> data_heap_ap;
|
||||
if (file_stats.st_size < file_size)
|
||||
data_heap_ap.reset(new DataBufferHeap(file_stats.st_size, '\0'));
|
||||
else
|
||||
data_heap_ap.reset(new DataBufferHeap(file_size, '\0'));
|
||||
data_heap_ap.reset(new DataBufferHeap(num_bytes_to_read, '\0'));
|
||||
|
||||
if (data_heap_ap.get())
|
||||
{
|
||||
|
|
|
@ -323,6 +323,22 @@ Section::GetSectionDataFromImage (const DataExtractor& image_data, DataExtractor
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t
|
||||
Section::ReadSectionDataFromObjectFile (const ObjectFile* objfile, off_t section_offset, void *dst, size_t dst_len) const
|
||||
{
|
||||
if (objfile && dst && dst_len)
|
||||
{
|
||||
const FileSpec& file = objfile->GetFileSpec();
|
||||
|
||||
if (file)
|
||||
{
|
||||
off_t section_file_offset = GetFileOffset() + objfile->GetOffset() + section_offset;
|
||||
return file.ReadFileContents (section_file_offset, dst, dst_len);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Get the section data the file on disk
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -340,11 +356,11 @@ Section::ReadSectionDataFromObjectFile(const ObjectFile* objfile, DataExtractor&
|
|||
if (section_file_size > 0)
|
||||
{
|
||||
off_t section_file_offset = GetFileOffset() + objfile->GetOffset();
|
||||
DataBufferSP sectionDataSP(file.ReadFileContents(section_file_offset, section_file_size));
|
||||
DataBufferSP section_data_sp(file.ReadFileContents(section_file_offset, section_file_size));
|
||||
|
||||
section_data.SetByteOrder(objfile->GetByteOrder());
|
||||
section_data.SetAddressByteSize(objfile->GetAddressByteSize());
|
||||
return section_data.SetData (sectionDataSP);
|
||||
return section_data.SetData (section_data_sp);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -364,10 +380,10 @@ Section::MemoryMapSectionDataFromObjectFile(const ObjectFile* objfile, DataExtra
|
|||
if (section_file_size > 0)
|
||||
{
|
||||
off_t section_file_offset = GetFileOffset() + objfile->GetOffset();
|
||||
DataBufferSP sectionDataSP(file.MemoryMapFileContents(section_file_offset, section_file_size));
|
||||
DataBufferSP section_data_sp(file.MemoryMapFileContents(section_file_offset, section_file_size));
|
||||
section_data.SetByteOrder(objfile->GetByteOrder());
|
||||
section_data.SetAddressByteSize(objfile->GetAddressByteSize());
|
||||
return section_data.SetData (sectionDataSP);
|
||||
return section_data.SetData (section_data_sp);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -100,19 +100,27 @@ void
|
|||
DisassemblerLLVM::Instruction::Dump
|
||||
(
|
||||
Stream *s,
|
||||
lldb::addr_t base_address,
|
||||
DataExtractor *bytes,
|
||||
lldb_private::Address *inst_addr_ptr,
|
||||
const DataExtractor *bytes,
|
||||
uint32_t bytes_offset,
|
||||
const lldb_private::ExecutionContext exe_ctx,
|
||||
const lldb_private::ExecutionContext& exe_ctx,
|
||||
bool raw
|
||||
)
|
||||
{
|
||||
const size_t opcodeColumnWidth = 7;
|
||||
const size_t operandColumnWidth = 25;
|
||||
|
||||
ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
|
||||
// If we have an address, print it out
|
||||
if (base_address != LLDB_INVALID_ADDRESS)
|
||||
s->Printf("0x%llx: ", base_address);
|
||||
if (inst_addr_ptr)
|
||||
{
|
||||
if (inst_addr_ptr->Dump (s,
|
||||
exe_scope,
|
||||
Address::DumpStyleLoadAddress,
|
||||
Address::DumpStyleModuleWithFileAddress,
|
||||
0))
|
||||
s->PutCString(": ");
|
||||
}
|
||||
|
||||
// If we are supposed to show bytes, "bytes" will be non-NULL.
|
||||
if (bytes)
|
||||
|
@ -131,9 +139,15 @@ DisassemblerLLVM::Instruction::Dump
|
|||
|
||||
int currentOpIndex = -1;
|
||||
|
||||
RegisterReaderArg rra(base_address + EDInstByteSize(m_inst), m_disassembler);
|
||||
|
||||
lldb_private::Process *process = exe_ctx.process;
|
||||
addr_t base_addr = LLDB_INVALID_ADDRESS;
|
||||
if (process && process->IsAlive())
|
||||
base_addr = inst_addr_ptr->GetLoadAddress (process);
|
||||
if (base_addr == LLDB_INVALID_ADDRESS)
|
||||
base_addr = inst_addr_ptr->GetFileAddress ();
|
||||
|
||||
RegisterReaderArg rra(base_addr + EDInstByteSize(m_inst), m_disassembler);
|
||||
|
||||
|
||||
bool printTokenized = false;
|
||||
|
||||
|
@ -228,13 +242,21 @@ DisassemblerLLVM::Instruction::Dump
|
|||
}
|
||||
|
||||
lldb_private::Address so_addr;
|
||||
if (process)
|
||||
if (process && process->IsAlive())
|
||||
{
|
||||
if (process->ResolveLoadAddress(operand_value, so_addr))
|
||||
if (process->ResolveLoadAddress (operand_value, so_addr))
|
||||
so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescription, Address::DumpStyleSectionNameOffset);
|
||||
}
|
||||
else if (inst_addr_ptr)
|
||||
{
|
||||
Module *module = inst_addr_ptr->GetModule();
|
||||
if (module)
|
||||
{
|
||||
so_addr.Dump(&comment, process, Address::DumpStyleResolvedDescription, Address::DumpStyleSectionNameOffset);
|
||||
if (module->ResolveFileAddress (operand_value, so_addr))
|
||||
so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescription, Address::DumpStyleSectionNameOffset);
|
||||
}
|
||||
}
|
||||
|
||||
} // EDEvaluateOperand
|
||||
} // EDOperandIsMemory
|
||||
} // EDGetOperand
|
||||
|
@ -364,12 +386,11 @@ DisassemblerLLVM::~DisassemblerLLVM()
|
|||
}
|
||||
|
||||
size_t
|
||||
DisassemblerLLVM::ParseInstructions
|
||||
DisassemblerLLVM::DecodeInstructions
|
||||
(
|
||||
const DataExtractor& data,
|
||||
uint32_t data_offset,
|
||||
uint32_t num_instructions,
|
||||
lldb::addr_t base_addr
|
||||
uint32_t num_instructions
|
||||
)
|
||||
{
|
||||
size_t total_inst_byte_size = 0;
|
||||
|
|
|
@ -32,10 +32,10 @@ public:
|
|||
|
||||
void
|
||||
Dump (lldb_private::Stream *s,
|
||||
lldb::addr_t base_address,
|
||||
lldb_private::DataExtractor *bytes,
|
||||
lldb_private::Address *instr_addr_ptr,
|
||||
const lldb_private::DataExtractor *bytes,
|
||||
uint32_t bytes_offset,
|
||||
const lldb_private::ExecutionContext exe_ctx,
|
||||
const lldb_private::ExecutionContext& exe_ctx,
|
||||
bool raw);
|
||||
|
||||
bool
|
||||
|
@ -78,11 +78,10 @@ public:
|
|||
~DisassemblerLLVM();
|
||||
|
||||
size_t
|
||||
ParseInstructions (const lldb_private::DataExtractor& data,
|
||||
uint32_t data_offset,
|
||||
uint32_t num_instructions,
|
||||
lldb::addr_t base_addr);
|
||||
|
||||
DecodeInstructions (const lldb_private::DataExtractor& data,
|
||||
uint32_t data_offset,
|
||||
uint32_t num_instructions);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// PluginInterface protocol
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -117,11 +117,6 @@ SymbolContext::DumpStopContext
|
|||
bool show_module
|
||||
) const
|
||||
{
|
||||
Process *process = NULL;
|
||||
if (exe_scope)
|
||||
process = exe_scope->CalculateProcess();
|
||||
addr_t load_addr = addr.GetLoadAddress (process);
|
||||
|
||||
if (show_module && module_sp)
|
||||
{
|
||||
*s << module_sp->GetFileSpec().GetFilename() << '`';
|
||||
|
@ -132,9 +127,9 @@ SymbolContext::DumpStopContext
|
|||
if (function->GetMangled().GetName())
|
||||
function->GetMangled().GetName().Dump(s);
|
||||
|
||||
const addr_t func_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(process);
|
||||
if (load_addr > func_load_addr)
|
||||
s->Printf(" + %llu", load_addr - func_load_addr);
|
||||
const addr_t function_offset = addr.GetOffset() - function->GetAddressRange().GetBaseAddress().GetOffset();
|
||||
if (function_offset)
|
||||
s->Printf(" + %llu", function_offset);
|
||||
|
||||
if (block != NULL)
|
||||
{
|
||||
|
@ -158,9 +153,9 @@ SymbolContext::DumpStopContext
|
|||
|
||||
if (symbol->GetAddressRangePtr())
|
||||
{
|
||||
const addr_t sym_load_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetLoadAddress(process);
|
||||
if (load_addr > sym_load_addr)
|
||||
s->Printf(" + %llu", load_addr - sym_load_addr);
|
||||
const addr_t symbol_offset = addr.GetOffset() - symbol->GetAddressRangePtr()->GetBaseAddress().GetOffset();
|
||||
if (symbol_offset)
|
||||
s->Printf(" + %llu", symbol_offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -181,6 +181,7 @@ StackFrame::Disassemble ()
|
|||
target.GetArchitecture(),
|
||||
exe_ctx,
|
||||
0,
|
||||
false,
|
||||
m_disassembly);
|
||||
if (m_disassembly.GetSize() == 0)
|
||||
return NULL;
|
||||
|
|
|
@ -507,90 +507,170 @@ Target::ModulesDidUnload (ModuleList &module_list)
|
|||
BroadcastEvent (eBroadcastBitModulesUnloaded, NULL);
|
||||
}
|
||||
|
||||
|
||||
//size_t
|
||||
//Target::ReadMemory
|
||||
//(
|
||||
// lldb::AddressType addr_type,
|
||||
// lldb::addr_t addr,
|
||||
// void *dst,
|
||||
// size_t dst_len,
|
||||
// Error &error,
|
||||
// ObjectFile* objfile
|
||||
//)
|
||||
//{
|
||||
// size_t bytes_read = 0;
|
||||
// error.Clear();
|
||||
// switch (addr_type)
|
||||
// {
|
||||
// case eAddressTypeFile:
|
||||
// if (objfile)
|
||||
// {
|
||||
// Address so_addr(addr, objfile->GetSectionList());
|
||||
// if (m_process_sp.get())
|
||||
// {
|
||||
// // If we have an execution context with a process, lets try and
|
||||
// // resolve the file address in "objfile" and read it from the
|
||||
// // process
|
||||
// lldb::addr_t load_addr = so_addr.GetLoadAddress(m_process_sp.get());
|
||||
// if (load_addr == LLDB_INVALID_ADDRESS)
|
||||
// {
|
||||
// if (objfile->GetFileSpec())
|
||||
// error.SetErrorStringWithFormat("0x%llx can't be resolved, %s in not currently loaded.\n", addr, objfile->GetFileSpec().GetFilename().AsCString());
|
||||
// else
|
||||
// error.SetErrorStringWithFormat("0x%llx can't be resolved.\n", addr, objfile->GetFileSpec().GetFilename().AsCString());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// bytes_read = m_process_sp->ReadMemory(load_addr, dst, dst_len, error);
|
||||
// if (bytes_read != dst_len)
|
||||
// {
|
||||
// if (error.Success())
|
||||
// {
|
||||
// if (bytes_read == 0)
|
||||
// error.SetErrorStringWithFormat("Read memory from 0x%llx failed.\n", load_addr);
|
||||
// else
|
||||
// error.SetErrorStringWithFormat("Only %zu of %zu bytes were read from memory at 0x%llx.\n", bytes_read, dst_len, load_addr);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // Try and read the file based address from the object file's
|
||||
// // section data.
|
||||
// const Section *section = so_addr.GetSection();
|
||||
// if (section)
|
||||
// return section->ReadSectionDataFromObjectFile(objfile, so_addr.GetOffset(), dst, dst_len);
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
//
|
||||
// case eAddressTypeLoad:
|
||||
// if (m_process_sp.get())
|
||||
// {
|
||||
// bytes_read = m_process_sp->ReadMemory(addr, dst, dst_len, error);
|
||||
// if (bytes_read != dst_len)
|
||||
// {
|
||||
// if (error.Success())
|
||||
// {
|
||||
// if (bytes_read == 0)
|
||||
// error.SetErrorStringWithFormat("Read memory from 0x%llx failed.\n", addr);
|
||||
// else
|
||||
// error.SetErrorStringWithFormat("Only %zu of %zu bytes were read from memory at 0x%llx.\n", bytes_read, dst_len, addr);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// error.SetErrorStringWithFormat("Need valid process to read load address.\n");
|
||||
// break;
|
||||
//
|
||||
// case eAddressTypeHost:
|
||||
// // The address is an address in this process, so just copy it
|
||||
// ::memcpy (dst, (uint8_t*)NULL + addr, dst_len);
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// error.SetErrorStringWithFormat ("Unsupported lldb::AddressType value (%i).\n", addr_type);
|
||||
// break;
|
||||
// }
|
||||
// return bytes_read;
|
||||
//}
|
||||
|
||||
size_t
|
||||
Target::ReadMemory
|
||||
(
|
||||
lldb::AddressType addr_type,
|
||||
lldb::addr_t addr,
|
||||
const Address& addr,
|
||||
void *dst,
|
||||
size_t dst_len,
|
||||
Error &error,
|
||||
ObjectFile* objfile
|
||||
Error &error
|
||||
)
|
||||
{
|
||||
size_t bytes_read = 0;
|
||||
error.Clear();
|
||||
switch (addr_type)
|
||||
{
|
||||
case eAddressTypeFile:
|
||||
if (objfile)
|
||||
{
|
||||
if (m_process_sp.get())
|
||||
{
|
||||
// If we have an execution context with a process, lets try and
|
||||
// resolve the file address in "objfile" and read it from the
|
||||
// process
|
||||
Address so_addr(addr, objfile->GetSectionList());
|
||||
lldb::addr_t load_addr = so_addr.GetLoadAddress(m_process_sp.get());
|
||||
if (load_addr == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
if (objfile->GetFileSpec())
|
||||
error.SetErrorStringWithFormat("0x%llx can't be resolved, %s in not currently loaded.\n", addr, objfile->GetFileSpec().GetFilename().AsCString());
|
||||
else
|
||||
error.SetErrorStringWithFormat("0x%llx can't be resolved.\n", addr, objfile->GetFileSpec().GetFilename().AsCString());
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes_read = m_process_sp->ReadMemory(load_addr, dst, dst_len, error);
|
||||
if (bytes_read != dst_len)
|
||||
{
|
||||
if (error.Success())
|
||||
{
|
||||
if (bytes_read == 0)
|
||||
error.SetErrorStringWithFormat("Read memory from 0x%llx failed.\n", load_addr);
|
||||
else
|
||||
error.SetErrorStringWithFormat("Only %zu of %zu bytes were read from memory at 0x%llx.\n", bytes_read, dst_len, load_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try and read the file based address from the object file's
|
||||
// section data.
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case eAddressTypeLoad:
|
||||
if (m_process_sp.get())
|
||||
bool process_is_valid = m_process_sp && m_process_sp->IsAlive();
|
||||
|
||||
Address resolved_addr(addr);
|
||||
if (!resolved_addr.IsSectionOffset())
|
||||
{
|
||||
if (process_is_valid)
|
||||
{
|
||||
bytes_read = m_process_sp->ReadMemory(addr, dst, dst_len, error);
|
||||
m_process_sp->ResolveLoadAddress (addr.GetOffset(), resolved_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_images.ResolveFileAddress(addr.GetOffset(), resolved_addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (process_is_valid)
|
||||
{
|
||||
lldb::addr_t load_addr = resolved_addr.GetLoadAddress(m_process_sp.get());
|
||||
if (load_addr == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
if (resolved_addr.GetModule() && resolved_addr.GetModule()->GetFileSpec())
|
||||
error.SetErrorStringWithFormat("%s[0x%llx] can't be resolved, %s in not currently loaded.\n",
|
||||
resolved_addr.GetModule()->GetFileSpec().GetFilename().AsCString(),
|
||||
resolved_addr.GetFileAddress());
|
||||
else
|
||||
error.SetErrorStringWithFormat("0x%llx can't be resolved.\n", resolved_addr.GetFileAddress());
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_read = m_process_sp->ReadMemory(load_addr, dst, dst_len, error);
|
||||
if (bytes_read != dst_len)
|
||||
{
|
||||
if (error.Success())
|
||||
{
|
||||
if (bytes_read == 0)
|
||||
error.SetErrorStringWithFormat("Read memory from 0x%llx failed.\n", addr);
|
||||
error.SetErrorStringWithFormat("Read memory from 0x%llx failed.\n", load_addr);
|
||||
else
|
||||
error.SetErrorStringWithFormat("Only %zu of %zu bytes were read from memory at 0x%llx.\n", bytes_read, dst_len, addr);
|
||||
error.SetErrorStringWithFormat("Only %zu of %zu bytes were read from memory at 0x%llx.\n", bytes_read, dst_len, load_addr);
|
||||
}
|
||||
}
|
||||
if (bytes_read)
|
||||
return bytes_read;
|
||||
// If the address is not section offset we have an address that
|
||||
// doesn't resolve to any address in any currently loaded shared
|
||||
// libaries and we failed to read memory so there isn't anything
|
||||
// more we can do. If it is section offset, we might be able to
|
||||
// read cached memory from the object file.
|
||||
if (!resolved_addr.IsSectionOffset())
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
error.SetErrorStringWithFormat("Need valid process to read load address.\n");
|
||||
break;
|
||||
|
||||
case eAddressTypeHost:
|
||||
// The address is an address in this process, so just copy it
|
||||
::memcpy (dst, (uint8_t*)NULL + addr, dst_len);
|
||||
break;
|
||||
|
||||
default:
|
||||
error.SetErrorStringWithFormat ("Unsupported lldb::AddressType value (%i).\n", addr_type);
|
||||
break;
|
||||
}
|
||||
return bytes_read;
|
||||
|
||||
const Section *section = resolved_addr.GetSection();
|
||||
if (section && section->GetModule())
|
||||
{
|
||||
ObjectFile *objfile = section->GetModule()->GetObjectFile();
|
||||
return section->ReadSectionDataFromObjectFile (objfile,
|
||||
resolved_addr.GetOffset(),
|
||||
dst,
|
||||
dst_len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue