From dda4f7b520827fb1cce38dbef9a00758067df99a Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Wed, 30 Jun 2010 23:03:03 +0000 Subject: [PATCH] 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 ". Fixed SymbolContext::DumpStopContext(...) to not require a live process in order to be able to print function and symbol offsets. llvm-svn: 107350 --- lldb/include/lldb/API/SBTarget.h | 3 +- lldb/include/lldb/Core/Address.h | 10 +- lldb/include/lldb/Core/Disassembler.h | 53 +++- lldb/include/lldb/Core/FileSpec.h | 3 + lldb/include/lldb/Core/Section.h | 3 + lldb/include/lldb/Target/Target.h | 12 +- lldb/source/API/SBTarget.cpp | 216 +++++-------- .../Commands/CommandObjectDisassemble.cpp | 278 +++++----------- .../Commands/CommandObjectDisassemble.h | 12 - lldb/source/Commands/CommandObjectImage.cpp | 4 + lldb/source/Core/Address.cpp | 146 ++++++--- lldb/source/Core/Disassembler.cpp | 298 +++++++++++++----- lldb/source/Core/FileSpec.cpp | 72 +++-- lldb/source/Core/Section.cpp | 24 +- .../Disassembler/llvm/DisassemblerLLVM.cpp | 47 ++- .../Disassembler/llvm/DisassemblerLLVM.h | 15 +- lldb/source/Symbol/SymbolContext.cpp | 17 +- lldb/source/Target/StackFrame.cpp | 1 + lldb/source/Target/Target.cpp | 208 ++++++++---- 19 files changed, 810 insertions(+), 612 deletions(-) diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index 12e3195a0599..652bad1846c2 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -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 diff --git a/lldb/include/lldb/Core/Address.h b/lldb/include/lldb/Core/Address.h index 2485036b598e..c7ce0f8701d6 100644 --- a/lldb/include/lldb/Core/Address.h +++ b/lldb/include/lldb/Core/Address.h @@ -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. diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h index 5e831823c25c..80de7b3af8ce 100644 --- a/lldb/include/lldb/Core/Disassembler.h +++ b/lldb/include/lldb/Core/Disassembler.h @@ -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 (); diff --git a/lldb/include/lldb/Core/FileSpec.h b/lldb/include/lldb/Core/FileSpec.h index af691e59ad29..fccc328319d5 100644 --- a/lldb/include/lldb/Core/FileSpec.h +++ b/lldb/include/lldb/Core/FileSpec.h @@ -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. /// diff --git a/lldb/include/lldb/Core/Section.h b/lldb/include/lldb/Core/Section.h index 8ea652a3f01a..3b3e43d4af3c 100644 --- a/lldb/include/lldb/Core/Section.h +++ b/lldb/include/lldb/Core/Section.h @@ -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; diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 055b5cf33538..fe18fdda8900 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -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 //------------------------------------------------------------------ diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index f964409813fd..ba0ed01f460c 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -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); } } diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp index c5fbbea0b410..4bf392c094f4 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.cpp +++ b/lldb/source/Commands/CommandObjectDisassemble.cpp @@ -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= 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; iGetInstructionList().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(); diff --git a/lldb/source/Commands/CommandObjectDisassemble.h b/lldb/source/Commands/CommandObjectDisassemble.h index 830b102017e1..8ea992707f62 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.h +++ b/lldb/source/Commands/CommandObjectDisassemble.h @@ -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 diff --git a/lldb/source/Commands/CommandObjectImage.cpp b/lldb/source/Commands/CommandObjectImage.cpp index 909b36d09c25..c835aa311a65 100644 --- a/lldb/source/Commands/CommandObjectImage.cpp +++ b/lldb/source/Commands/CommandObjectImage.cpp @@ -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; } diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp index f7e750017018..4658cf27add9 100644 --- a/lldb/source/Core/Address.cpp +++ b/lldb/source/Core/Address.cpp @@ -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; diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index 9cdf618c087d..a8eceb74ff99 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -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; iFindFunctions (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; iGetInstructionList().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; diff --git a/lldb/source/Core/FileSpec.cpp b/lldb/source/Core/FileSpec.cpp index 91ad6b04351b..ea3d3af3c752 100644 --- a/lldb/source/Core/FileSpec.cpp +++ b/lldb/source/Core/FileSpec.cpp @@ -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 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()) { diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp index 6ed47730c6f9..89549f002ab8 100644 --- a/lldb/source/Core/Section.cpp +++ b/lldb/source/Core/Section.cpp @@ -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; diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp index 0abfd93b1124..340d90637b9e 100644 --- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp +++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp @@ -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; diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h index 98166cb558c2..7116e5952331 100644 --- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h +++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h @@ -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 //------------------------------------------------------------------ diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp index eca278e0ac89..7963a1fbbe7b 100644 --- a/lldb/source/Symbol/SymbolContext.cpp +++ b/lldb/source/Symbol/SymbolContext.cpp @@ -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 diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 3ebc0c28a981..2b74ae1acc57 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -181,6 +181,7 @@ StackFrame::Disassemble () target.GetArchitecture(), exe_ctx, 0, + false, m_disassembly); if (m_disassembly.GetSize() == 0) return NULL; diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index cba72e90b3e9..2c67503bf26e 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -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; }