diff options
Diffstat (limited to 'lldb/source')
19 files changed, 875 insertions, 907 deletions
diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp index abde4ac42c9..e4b599dff49 100644 --- a/lldb/source/Core/Address.cpp +++ b/lldb/source/Core/Address.cpp @@ -1015,29 +1015,6 @@ lldb_private::operator!= (const Address& a, const Address& rhs) a.GetOffset() != rhs.GetOffset(); } -bool -Address::IsLinkedAddress () const -{ - SectionSP section_sp (GetSection()); - return section_sp && section_sp->GetLinkedSection(); -} - - -void -Address::ResolveLinkedAddress () -{ - SectionSP section_sp (GetSection()); - if (section_sp) - { - SectionSP linked_section_sp (section_sp->GetLinkedSection()); - if (linked_section_sp) - { - m_offset += section_sp->GetLinkedOffset(); - m_section_wp = linked_section_sp; - } - } -} - AddressClass Address::GetAddressClass () const { diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp index a9481d2ccac..0d924a34a65 100644 --- a/lldb/source/Core/Section.cpp +++ b/lldb/source/Core/Section.cpp @@ -21,8 +21,8 @@ Section::Section (const ModuleSP &module_sp, SectionType sect_type, addr_t file_addr, addr_t byte_size, - uint64_t file_offset, - uint64_t file_size, + lldb::offset_t file_offset, + lldb::offset_t file_size, uint32_t flags) : ModuleChild (module_sp), UserID (sect_id), @@ -37,9 +37,7 @@ Section::Section (const ModuleSP &module_sp, m_children (), m_fake (false), m_encrypted (false), - m_thread_specific (false), - m_linked_section_wp(), - m_linked_offset (0) + m_thread_specific (false) { // printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s\n", // this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, name.GetCString()); @@ -52,8 +50,8 @@ Section::Section (const lldb::SectionSP &parent_section_sp, SectionType sect_type, addr_t file_addr, addr_t byte_size, - uint64_t file_offset, - uint64_t file_size, + lldb::offset_t file_offset, + lldb::offset_t file_size, uint32_t flags) : ModuleChild (module_sp), UserID (sect_id), @@ -68,9 +66,7 @@ Section::Section (const lldb::SectionSP &parent_section_sp, m_children (), m_fake (false), m_encrypted (false), - m_thread_specific (false), - m_linked_section_wp(), - m_linked_offset (0) + m_thread_specific (false) { // printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s.%s\n", // this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, parent_section_sp->GetName().GetCString(), name.GetCString()); @@ -83,15 +79,6 @@ Section::~Section() // printf ("Section::~Section(%p)\n", this); } -const ConstString& -Section::GetName() const -{ - SectionSP linked_section_sp (m_linked_section_wp.lock()); - if (linked_section_sp) - return linked_section_sp->GetName(); - return m_name; -} - addr_t Section::GetFileAddress () const { @@ -119,43 +106,21 @@ Section::GetOffset () const return 0; } - -addr_t -Section::GetLinkedFileAddress () const -{ - SectionSP linked_section_sp (m_linked_section_wp.lock()); - if (linked_section_sp) - return linked_section_sp->GetFileAddress() + m_linked_offset; - return LLDB_INVALID_ADDRESS; -} - - addr_t Section::GetLoadBaseAddress (Target *target) const { addr_t load_base_addr = LLDB_INVALID_ADDRESS; - SectionSP linked_section_sp (m_linked_section_wp.lock()); - if (linked_section_sp) + SectionSP parent_sp (GetParent ()); + if (parent_sp) { - load_base_addr = linked_section_sp->GetLoadBaseAddress(target); + load_base_addr = parent_sp->GetLoadBaseAddress (target); if (load_base_addr != LLDB_INVALID_ADDRESS) - load_base_addr += m_linked_offset; + load_base_addr += GetOffset(); } else { - SectionSP parent_sp (GetParent ()); - if (parent_sp) - { - load_base_addr = parent_sp->GetLoadBaseAddress (target); - if (load_base_addr != LLDB_INVALID_ADDRESS) - load_base_addr += GetOffset(); - } - else - { - load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress (const_cast<Section *>(this)->shared_from_this()); - } + load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress (const_cast<Section *>(this)->shared_from_this()); } - return load_base_addr; } @@ -174,22 +139,13 @@ Section::ResolveContainedAddress (addr_t offset, Address &so_addr) const return child_section->ResolveContainedAddress (offset - child_offset, so_addr); } } - SectionSP linked_section_sp (m_linked_section_wp.lock()); - if (linked_section_sp) - { - so_addr.SetOffset(m_linked_offset + offset); - so_addr.SetSection(linked_section_sp); - } - else - { - so_addr.SetOffset(offset); - so_addr.SetSection(const_cast<Section *>(this)->shared_from_this()); - + so_addr.SetOffset(offset); + so_addr.SetSection(const_cast<Section *>(this)->shared_from_this()); + #ifdef LLDB_CONFIGURATION_DEBUG - // For debug builds, ensure that there are no orphaned (i.e., moduleless) sections. - assert(GetModule().get()); + // For debug builds, ensure that there are no orphaned (i.e., moduleless) sections. + assert(GetModule().get()); #endif - } return true; } @@ -208,21 +164,6 @@ Section::ContainsFileAddress (addr_t vm_addr) const return false; } -bool -Section::ContainsLinkedFileAddress (addr_t vm_addr) const -{ - const addr_t linked_file_addr = GetLinkedFileAddress(); - if (linked_file_addr != LLDB_INVALID_ADDRESS) - { - if (linked_file_addr <= vm_addr) - { - const addr_t offset = vm_addr - linked_file_addr; - return offset < GetByteSize(); - } - } - return false; -} - int Section::Compare (const Section& a, const Section& b) { @@ -261,12 +202,11 @@ Section::Dump (Stream *s, Target *target, uint32_t depth) const bool resolved = true; addr_t addr = LLDB_INVALID_ADDRESS; - SectionSP linked_section_sp (m_linked_section_wp.lock()); if (GetByteSize() == 0) s->Printf("%39s", ""); else { - if (target && linked_section_sp.get() == NULL) + if (target) addr = GetLoadBaseAddress (target); if (addr == LLDB_INVALID_ADDRESS) @@ -286,35 +226,6 @@ Section::Dump (Stream *s, Target *target, uint32_t depth) const s->EOL(); - if (linked_section_sp) - { - addr = LLDB_INVALID_ADDRESS; - resolved = true; - if (target) - { - addr = linked_section_sp->GetLoadBaseAddress(target); - if (addr != LLDB_INVALID_ADDRESS) - addr += m_linked_offset; - } - - if (addr == LLDB_INVALID_ADDRESS) - { - if (target) - resolved = false; - addr = linked_section_sp->GetFileAddress() + m_linked_offset; - } - - int indent = 28 + s->GetIndentLevel(); - s->Printf("%*.*s", indent, indent, ""); - VMRange linked_range(addr, addr + m_byte_size); - linked_range.Dump (s, 0); - indent = 3 * (sizeof(uint32_t) * 2 + 2 + 1) + 1; - s->Printf("%c%*.*s", resolved ? ' ' : '*', indent, indent, ""); - - linked_section_sp->DumpName(s); - s->Printf(" + 0x%" PRIx64 "\n", m_linked_offset); - } - if (depth > 0) m_children.Dump(s, target, false, depth - 1); } @@ -371,22 +282,10 @@ Section::Slide (addr_t slide_amount, bool slide_children) return false; } -void -Section::SetLinkedLocation (const lldb::SectionSP &linked_section_sp, uint64_t linked_offset) -{ - if (linked_section_sp) - m_module_wp = linked_section_sp->GetModule(); - m_linked_section_wp = linked_section_sp; - m_linked_offset = linked_offset; -} - #pragma mark SectionList SectionList::SectionList () : m_sections() -#ifdef LLDB_CONFIGURATION_DEBUG - , m_finalized(false) -#endif { } @@ -401,7 +300,6 @@ SectionList::AddSection (const lldb::SectionSP& section_sp) assert (section_sp.get()); size_t section_index = m_sections.size(); m_sections.push_back(section_sp); - InvalidateRangeCache(); return section_index; } @@ -441,7 +339,6 @@ SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp, if ((*sect_iter)->GetID() == sect_id) { *sect_iter = sect_sp; - InvalidateRangeCache(); return true; } else if (depth > 0) @@ -575,71 +472,6 @@ SectionList::FindSectionContainingFileAddress (addr_t vm_addr, uint32_t depth) c return sect_sp; } -void -SectionList::BuildRangeCache() const -{ - m_range_cache.Clear(); - - for (collection::size_type idx = 0, last_idx = m_sections.size(); - idx < last_idx; - ++idx) - { - Section *sect = m_sections[idx].get(); - - addr_t linked_file_address = sect->GetLinkedFileAddress(); - - if (linked_file_address != LLDB_INVALID_ADDRESS) - m_range_cache.Append(SectionRangeCache::Entry(linked_file_address, sect->GetByteSize(), idx)); - } - - m_range_cache.Sort(); - -#ifdef LLDB_CONFIGURATION_DEBUG - m_finalized = true; -#endif -} - -void -SectionList::InvalidateRangeCache() const -{ -#ifdef LLDB_CONFIGURATION_DEBUG - assert(!m_finalized); -#endif - m_range_cache.Clear(); -} - -SectionSP -SectionList::FindSectionContainingLinkedFileAddress (addr_t vm_addr, uint32_t depth) const -{ - //if (m_range_cache.IsEmpty()) - // BuildRangeCache(); -#ifdef LLDB_CONFIGURATION_DEBUG - assert(m_finalized); -#endif - - SectionRangeCache::Entry *entry = m_range_cache.FindEntryThatContains(vm_addr); - - if (entry) - return m_sections[entry->data]; - - if (depth == 0) - return SectionSP(); - - for (const_iterator si = m_sections.begin(), se = m_sections.end(); - si != se; - ++si) - { - Section *sect = si->get(); - - SectionSP sect_sp = sect->GetChildren().FindSectionContainingLinkedFileAddress(vm_addr, depth - 1); - - if (sect_sp) - return sect_sp; - } - - return SectionSP(); -} - bool SectionList::ContainsSection(user_id_t sect_id) const { @@ -681,15 +513,12 @@ SectionList::Slide (addr_t slide_amount, bool slide_children) if ((*pos)->Slide(slide_amount, slide_children)) ++count; } - InvalidateRangeCache(); return count; } void SectionList::Finalize () { - BuildRangeCache(); - for (const_iterator si = m_sections.begin(), se = m_sections.end(); si != se; ++si) diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 0be564a1785..27671b20463 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -1009,24 +1009,25 @@ GetOpcodeDataSize (const DataExtractor &data, const lldb::offset_t data_offset, return LLDB_INVALID_OFFSET; } -bool -DWARFExpression::LocationContains_DW_OP_addr (lldb::addr_t file_addr, bool &error) const +lldb::addr_t +DWARFExpression::GetLocation_DW_OP_addr (uint32_t op_addr_idx, bool &error) const { error = false; if (IsLocationList()) - return false; + return LLDB_INVALID_ADDRESS; lldb::offset_t offset = 0; + uint32_t curr_op_addr_idx = 0; while (m_data.ValidOffset(offset)) { const uint8_t op = m_data.GetU8(&offset); if (op == DW_OP_addr) { - if (file_addr == LLDB_INVALID_ADDRESS) - return true; - addr_t op_file_addr = m_data.GetAddress(&offset); - if (op_file_addr == file_addr) - return true; + const lldb::addr_t op_file_addr = m_data.GetAddress(&offset); + if (curr_op_addr_idx == op_addr_idx) + return op_file_addr; + else + ++curr_op_addr_idx; } else { @@ -1039,7 +1040,7 @@ DWARFExpression::LocationContains_DW_OP_addr (lldb::addr_t file_addr, bool &erro offset += op_arg_size; } } - return false; + return LLDB_INVALID_ADDRESS; } bool diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 42bfefe8d62..37434beac43 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -254,8 +254,6 @@ ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp, m_header(), m_program_headers(), m_section_headers(), - m_sections_ap(), - m_symtab_ap(), m_filespec_ap(), m_shstr_data() { diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 2c1ff6c4d38..ba4057c5f3d 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -153,12 +153,6 @@ private: /// Collection of symbols from the dynamic table. DynamicSymbolColl m_dynamic_symbols; - /// List of sections present in this ELF object file. - mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap; - - /// Table of all non-dynamic symbols present in this object file. - mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap; - /// List of file specifications corresponding to the modules (shared /// libraries) on which this object file depends. mutable std::auto_ptr<lldb_private::FileSpecList> m_filespec_ap; diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 9ca6d7bc048..0f2a858bb52 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -501,8 +501,6 @@ ObjectFileMachO::ObjectFileMachO(const lldb::ModuleSP &module_sp, lldb::offset_t file_offset, lldb::offset_t length) : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset), - m_sections_ap(), - m_symtab_ap(), m_mach_segments(), m_mach_sections(), m_entry_point_address(), @@ -518,8 +516,6 @@ ObjectFileMachO::ObjectFileMachO (const lldb::ModuleSP &module_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) : ObjectFile(module_sp, process_sp, header_addr, header_data_sp), - m_sections_ap(), - m_symtab_ap(), m_mach_segments(), m_mach_sections(), m_entry_point_address(), diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h index 1d0443731d9..c4a15407c4e 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -146,8 +146,6 @@ public: protected: llvm::MachO::mach_header m_header; - mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap; - mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap; static const lldb_private::ConstString &GetSegmentNameTEXT(); static const lldb_private::ConstString &GetSegmentNameDATA(); static const lldb_private::ConstString &GetSegmentNameOBJC(); @@ -157,7 +155,7 @@ protected: llvm::MachO::dysymtab_command m_dysymtab; std::vector<llvm::MachO::segment_command_64> m_mach_segments; std::vector<llvm::MachO::section_64> m_mach_sections; - typedef lldb_private::RangeArray<uint32_t, uint32_t, 1> FileRangeArray; + typedef lldb_private::RangeVector<uint32_t, uint32_t> FileRangeArray; lldb_private::Address m_entry_point_address; FileRangeArray m_thread_context_offsets; bool m_thread_context_offsets_valid; diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h index aad2696b2ef..814559f5638 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h @@ -229,8 +229,6 @@ protected: typedef SectionHeaderColl::iterator SectionHeaderCollIter; typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter; private: - mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap; - mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap; dos_header_t m_dos_header; coff_header_t m_coff_header; coff_opt_header_t m_coff_header_opt; diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h index e5564a9dda3..0119613336f 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h @@ -130,7 +130,7 @@ private: // For ProcessMachCore only //------------------------------------------------------------------ typedef lldb_private::Range<uint32_t, uint32_t> FileRange; - typedef lldb_private::RangeDataArray<lldb::addr_t, lldb::addr_t, FileRange, 1> VMRangeToFileOffset; + typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange> VMRangeToFileOffset; VMRangeToFileOffset m_core_aranges; lldb::ModuleSP m_core_module_sp; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h index f35ff165f1f..5f3b437d964 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef SymbolFileDWARF_DWARFDebugLine_h_ -#define SymbolFileDWARF_DWARFDebugLine_h_ +#ifndef SymbolFileDWARF_DWARFDebugMacinfo_h_ +#define SymbolFileDWARF_DWARFDebugMacinfo_h_ #include "SymbolFileDWARF.h" @@ -26,4 +26,4 @@ public: }; -#endif // SymbolFileDWARF_DWARFDebugLine_h_ +#endif // SymbolFileDWARF_DWARFDebugMacinfo_h_ diff --git a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp index a21741b2342..10f8cef2594 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp @@ -182,9 +182,9 @@ LogChannelDWARF::ListCategories (Stream *strm) " line - log the parsing if .debug_line\n" " pubnames - log the parsing if .debug_pubnames\n" " pubtypes - log the parsing if .debug_pubtypes\n" - " lookups - log any lookups that happen by name, regex, or address\n\n" - " completion - log struct/unions/class type completions\n\n" - " map - log insertions of object files into DWARF debug maps\n\n", + " lookups - log any lookups that happen by name, regex, or address\n" + " completion - log struct/unions/class type completions\n" + " map - log insertions of object files into DWARF debug maps\n", SymbolFileDWARF::GetPluginNameStatic()); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index ffda80bca19..603d824f315 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -891,28 +891,40 @@ SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompile assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED); - func_range.GetBaseAddress().ResolveLinkedAddress(); - - const user_id_t func_user_id = MakeUserID(die->GetOffset()); - func_sp.reset(new Function (sc.comp_unit, - func_user_id, // UserID is the DIE offset - func_user_id, - func_name, - func_type, - func_range)); // first address range - - if (func_sp.get() != NULL) + if (FixupAddress (func_range.GetBaseAddress())) { - if (frame_base.IsValid()) - func_sp->GetFrameBaseExpression() = frame_base; - sc.comp_unit->AddFunction(func_sp); - return func_sp.get(); + const user_id_t func_user_id = MakeUserID(die->GetOffset()); + func_sp.reset(new Function (sc.comp_unit, + MakeUserID(func_user_id), // UserID is the DIE offset + MakeUserID(func_user_id), + func_name, + func_type, + func_range)); // first address range + + if (func_sp.get() != NULL) + { + if (frame_base.IsValid()) + func_sp->GetFrameBaseExpression() = frame_base; + sc.comp_unit->AddFunction(func_sp); + return func_sp.get(); + } } } } return NULL; } +bool +SymbolFileDWARF::FixupAddress (Address &addr) +{ + SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile (); + if (debug_map_symfile) + { + return debug_map_symfile->LinkOSOAddress(addr); + } + // This is a normal DWARF file, no address fixups need to happen + return true; +} lldb::LanguageType SymbolFileDWARF::ParseCompileUnitLanguage (const SymbolContext& sc) { @@ -983,15 +995,7 @@ SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpec struct ParseDWARFLineTableCallbackInfo { LineTable* line_table; - const SectionList *section_list; - lldb::addr_t prev_sect_file_base_addr; - lldb::addr_t curr_sect_file_base_addr; - bool is_oso_for_debug_map; - bool prev_in_final_executable; - DWARFDebugLine::Row prev_row; - SectionSP prev_section_sp; - SectionSP curr_section_sp; - llvm::OwningPtr<LineSequence> curr_sequence_ap; + std::auto_ptr<LineSequence> sequence_ap; }; //---------------------------------------------------------------------- @@ -1000,7 +1004,6 @@ struct ParseDWARFLineTableCallbackInfo static void ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& state, void* userData) { - LineTable* line_table = ((ParseDWARFLineTableCallbackInfo*)userData)->line_table; if (state.row == DWARFDebugLine::State::StartParsingLineTable) { // Just started parsing the line table @@ -1012,166 +1015,32 @@ ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& sta else { ParseDWARFLineTableCallbackInfo* info = (ParseDWARFLineTableCallbackInfo*)userData; - // We have a new row, lets append it + LineTable* line_table = info->line_table; - if (info->curr_section_sp.get() == NULL || info->curr_section_sp->ContainsFileAddress(state.address) == false) + // If this is our first time here, we need to create a + // sequence container. + if (!info->sequence_ap.get()) { - info->prev_section_sp = info->curr_section_sp; - info->prev_sect_file_base_addr = info->curr_sect_file_base_addr; - // If this is an end sequence entry, then we subtract one from the - // address to make sure we get an address that is not the end of - // a section. - if (state.end_sequence && state.address != 0) - info->curr_section_sp = info->section_list->FindSectionContainingFileAddress (state.address - 1); - else - info->curr_section_sp = info->section_list->FindSectionContainingFileAddress (state.address); - - if (info->curr_section_sp.get()) - info->curr_sect_file_base_addr = info->curr_section_sp->GetFileAddress (); - else - info->curr_sect_file_base_addr = 0; + info->sequence_ap.reset(line_table->CreateLineSequenceContainer()); + assert(info->sequence_ap.get()); } - if (info->curr_section_sp.get()) + line_table->AppendLineEntryToSequence (info->sequence_ap.get(), + state.address, + state.line, + state.column, + state.file, + state.is_stmt, + state.basic_block, + state.prologue_end, + state.epilogue_begin, + state.end_sequence); + if (state.end_sequence) { - lldb::addr_t curr_line_section_offset = state.address - info->curr_sect_file_base_addr; - // Check for the fancy section magic to determine if we - - if (info->is_oso_for_debug_map) - { - // When this is a debug map object file that contains DWARF - // (referenced from an N_OSO debug map nlist entry) we will have - // a file address in the file range for our section from the - // original .o file, and a load address in the executable that - // contains the debug map. - // - // If the sections for the file range and load range are - // different, we have a remapped section for the function and - // this address is resolved. If they are the same, then the - // function for this address didn't make it into the final - // executable. - bool curr_in_final_executable = (bool) info->curr_section_sp->GetLinkedSection (); - - // If we are doing DWARF with debug map, then we need to carefully - // add each line table entry as there may be gaps as functions - // get moved around or removed. - if (!info->prev_row.end_sequence && info->prev_section_sp.get()) - { - if (info->prev_in_final_executable) - { - bool terminate_previous_entry = false; - if (!curr_in_final_executable) - { - // Check for the case where the previous line entry - // in a function made it into the final executable, - // yet the current line entry falls in a function - // that didn't. The line table used to be contiguous - // through this address range but now it isn't. We - // need to terminate the previous line entry so - // that we can reconstruct the line range correctly - // for it and to keep the line table correct. - terminate_previous_entry = true; - } - else if (info->curr_section_sp.get() != info->prev_section_sp.get()) - { - // Check for cases where the line entries used to be - // contiguous address ranges, but now they aren't. - // This can happen when order files specify the - // ordering of the functions. - lldb::addr_t prev_line_section_offset = info->prev_row.address - info->prev_sect_file_base_addr; - Section *curr_sect = info->curr_section_sp.get(); - Section *prev_sect = info->prev_section_sp.get(); - assert (curr_sect->GetLinkedSection()); - assert (prev_sect->GetLinkedSection()); - lldb::addr_t object_file_addr_delta = state.address - info->prev_row.address; - lldb::addr_t curr_linked_file_addr = curr_sect->GetLinkedFileAddress() + curr_line_section_offset; - lldb::addr_t prev_linked_file_addr = prev_sect->GetLinkedFileAddress() + prev_line_section_offset; - lldb::addr_t linked_file_addr_delta = curr_linked_file_addr - prev_linked_file_addr; - if (object_file_addr_delta != linked_file_addr_delta) - terminate_previous_entry = true; - } - - if (terminate_previous_entry) - { - line_table->InsertLineEntry (info->prev_section_sp, - state.address - info->prev_sect_file_base_addr, - info->prev_row.line, - info->prev_row.column, - info->prev_row.file, - false, // is_stmt - false, // basic_block - false, // state.prologue_end - false, // state.epilogue_begin - true); // end_sequence); - } - } - } - - if (curr_in_final_executable) - { - line_table->InsertLineEntry (info->curr_section_sp, - curr_line_section_offset, - state.line, - state.column, - state.file, - state.is_stmt, - state.basic_block, - state.prologue_end, - state.epilogue_begin, - state.end_sequence); - info->prev_section_sp = info->curr_section_sp; - } - else - { - // If the current address didn't make it into the final - // executable, the current section will be the __text - // segment in the .o file, so we need to clear this so - // we can catch the next function that did make it into - // the final executable. - info->prev_section_sp.reset(); - info->curr_section_sp.reset(); - } - - info->prev_in_final_executable = curr_in_final_executable; - } - else - { - // We are not in an object file that contains DWARF for an - // N_OSO, this is just a normal DWARF file. The DWARF spec - // guarantees that the addresses will be in increasing order - // for a sequence, but the line table for a single compile unit - // may contain multiple sequences so we append entries to the - // current sequence until we find its end, then we merge the - // sequence into the main line table collection. - - // If this is our first time here, we need to create a - // sequence container. - if (!info->curr_sequence_ap) - { - info->curr_sequence_ap.reset(line_table->CreateLineSequenceContainer()); - assert(info->curr_sequence_ap); - } - line_table->AppendLineEntryToSequence(info->curr_sequence_ap.get(), - info->curr_section_sp, - curr_line_section_offset, - state.line, - state.column, - state.file, - state.is_stmt, - state.basic_block, - state.prologue_end, - state.epilogue_begin, - state.end_sequence); - if (state.end_sequence) - { - // First, put the current sequence into the line table. - line_table->InsertSequence(info->curr_sequence_ap.get()); - // Then, empty it to prepare for the next sequence. - info->curr_sequence_ap->Clear(); - } - } + // First, put the current sequence into the line table. + line_table->InsertSequence(info->sequence_ap.get()); + // Then, empty it to prepare for the next sequence. + info->sequence_ap->Clear(); } - - info->prev_row = state; } } @@ -1194,22 +1063,23 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc) std::auto_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit)); if (line_table_ap.get()) { - ParseDWARFLineTableCallbackInfo info = { - line_table_ap.get(), - m_obj_file->GetSectionList(), - 0, - 0, - GetDebugMapSymfile () != NULL, - false, - DWARFDebugLine::Row(), - SectionSP(), - SectionSP(), - llvm::OwningPtr<LineSequence>() - }; + ParseDWARFLineTableCallbackInfo info; + info.line_table = line_table_ap.get(); lldb::offset_t offset = cu_line_offset; DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, &info); - sc.comp_unit->SetLineTable(line_table_ap.release()); - return true; + if (m_debug_map_symfile) + { + // We have an object file that has a line table with addresses + // that are not linked. We need to link the line table and convert + // the addresses that are relative to the .o file into addresses + // for the main executable. + sc.comp_unit->SetLineTable (m_debug_map_symfile->LinkOSOLineTable (this, line_table_ap.get())); + } + else + { + sc.comp_unit->SetLineTable(line_table_ap.release()); + return true; + } } } } @@ -2672,19 +2542,19 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_ LineTable *line_table = sc.comp_unit->GetLineTable(); if (line_table != NULL) { - if (so_addr.IsLinkedAddress()) + // And address that makes it into this function should be in terms + // of this debug file if there is no debug map, or it will be an + // address in the .o file which needs to be fixed up to be in terms + // of the debug map executable. Either way, calling FixupAddress() + // will work for us. + Address exe_so_addr (so_addr); + if (FixupAddress(exe_so_addr)) { - Address linked_addr (so_addr); - linked_addr.ResolveLinkedAddress(); - if (line_table->FindLineEntryByAddress (linked_addr, sc.line_entry)) + if (line_table->FindLineEntryByAddress (exe_so_addr, sc.line_entry)) { resolved |= eSymbolContextLineEntry; } } - else if (line_table->FindLineEntryByAddress (so_addr, sc.line_entry)) - { - resolved |= eSymbolContextLineEntry; - } } } @@ -6976,14 +6846,13 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) if (info == NULL) return 0; - uint32_t cu_idx = UINT32_MAX; - DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID(), &cu_idx).get(); - - if (dwarf_cu == NULL) - return 0; - if (sc.function) { + DWARFCompileUnit* dwarf_cu = info->GetCompileUnitContainingDIE(sc.function->GetID()).get(); + + if (dwarf_cu == NULL) + return 0; + const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(sc.function->GetID()); dw_addr_t func_lo_pc = function_die->GetAttributeValueAsUnsigned (this, dwarf_cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS); @@ -6998,6 +6867,11 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) } else if (sc.comp_unit) { + DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID()).get(); + + if (dwarf_cu == NULL) + return 0; + uint32_t vars_added = 0; VariableListSP variables (sc.comp_unit->GetVariableList(false)); @@ -7232,10 +7106,10 @@ SymbolFileDWARF::ParseVariableDIE { bool op_error = false; // Check if the location has a DW_OP_addr with any address value... - addr_t location_has_op_addr = false; + lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS; if (!location_is_const_value_data) { - location_has_op_addr = location.LocationContains_DW_OP_addr (LLDB_INVALID_ADDRESS, op_error); + location_DW_OP_addr = location.GetLocation_DW_OP_addr (0, op_error); if (op_error) { StreamString strm; @@ -7244,67 +7118,63 @@ SymbolFileDWARF::ParseVariableDIE } } - if (location_has_op_addr) + if (location_DW_OP_addr != LLDB_INVALID_ADDRESS) { if (is_external) - { scope = eValueTypeVariableGlobal; - - if (GetDebugMapSymfile ()) + else + scope = eValueTypeVariableStatic; + + + SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile (); + + if (debug_map_symfile) + { + // When leaving the DWARF in the .o files on darwin, + // when we have a global variable that wasn't initialized, + // the .o file might not have allocated a virtual + // address for the global variable. In this case it will + // have created a symbol for the global variable + // that is undefined/data and external and the value will + // be the byte size of the variable. When we do the + // address map in SymbolFileDWARFDebugMap we rely on + // having an address, we need to do some magic here + // so we can get the correct address for our global + // variable. The address for all of these entries + // will be zero, and there will be an undefined symbol + // in this object file, and the executable will have + // a matching symbol with a good address. So here we + // dig up the correct address and replace it in the + // location for the variable, and set the variable's + // symbol context scope to be that of the main executable + // so the file address will resolve correctly. + bool linked_oso_file_addr = false; + if (is_external && location_DW_OP_addr == 0) { - // When leaving the DWARF in the .o files on darwin, - // when we have a global variable that wasn't initialized, - // the .o file might not have allocated a virtual - // address for the global variable. In this case it will - // have created a symbol for the global variable - // that is undefined/data and external and the value will - // be the byte size of the variable. When we do the - // address map in SymbolFileDWARFDebugMap we rely on - // having an address, we need to do some magic here - // so we can get the correct address for our global - // variable. The address for all of these entries - // will be zero, and there will be an undefined symbol - // in this object file, and the executable will have - // a matching symbol with a good address. So here we - // dig up the correct address and replace it in the - // location for the variable, and set the variable's - // symbol context scope to be that of the main executable - // so the file address will resolve correctly. - if (location.LocationContains_DW_OP_addr (0, op_error)) + + // we have a possible uninitialized extern global + ConstString const_name(mangled ? mangled : name); + ObjectFile *debug_map_objfile = debug_map_symfile->GetObjectFile(); + if (debug_map_objfile) { - - // we have a possible uninitialized extern global - Symtab *symtab = m_obj_file->GetSymtab(); - if (symtab) + Symtab *debug_map_symtab = debug_map_objfile->GetSymtab(); + if (debug_map_symtab) { - ConstString const_name(mangled ? mangled : name); - Symbol *o_symbol = symtab->FindFirstSymbolWithNameAndType (const_name, - eSymbolTypeAny, - Symtab::eDebugNo, - Symtab::eVisibilityExtern); - - if (o_symbol) + Symbol *exe_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name, + eSymbolTypeData, + Symtab::eDebugYes, + Symtab::eVisibilityExtern); + if (exe_symbol) { - ObjectFile *debug_map_objfile = m_debug_map_symfile->GetObjectFile(); - if (debug_map_objfile) + if (exe_symbol->ValueIsAddress()) { - Symtab *debug_map_symtab = debug_map_objfile->GetSymtab(); - Symbol *defined_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name, - eSymbolTypeData, - Symtab::eDebugYes, - Symtab::eVisibilityExtern); - if (defined_symbol) + const addr_t exe_file_addr = exe_symbol->GetAddress().GetFileAddress(); + if (exe_file_addr != LLDB_INVALID_ADDRESS) { - if (defined_symbol->ValueIsAddress()) + if (location.Update_DW_OP_addr (exe_file_addr)) { - const addr_t defined_addr = defined_symbol->GetAddress().GetFileAddress(); - if (defined_addr != LLDB_INVALID_ADDRESS) - { - if (location.Update_DW_OP_addr (defined_addr)) - { - symbol_context_scope = defined_symbol; - } - } + linked_oso_file_addr = true; + symbol_context_scope = exe_symbol; } } } @@ -7312,10 +7182,23 @@ SymbolFileDWARF::ParseVariableDIE } } } - } - else - { - scope = eValueTypeVariableStatic; + + if (!linked_oso_file_addr) + { + // The DW_OP_addr is not zero, but it contains a .o file address which + // needs to be linked up correctly. + const lldb::addr_t exe_file_addr = debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr); + if (exe_file_addr != LLDB_INVALID_ADDRESS) + { + // Update the file address for this variable + location.Update_DW_OP_addr (exe_file_addr); + } + else + { + // Variable didn't make it into the final executable + return var_sp; + } + } } } else diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 06db2860166..31fb4cc3b3f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -541,6 +541,9 @@ protected: const DWARFDebugInfoEntry *dst_class_die, llvm::SmallVectorImpl <const DWARFDebugInfoEntry *> &failures); + bool + FixupAddress (lldb_private::Address &addr); + lldb::ModuleWP m_debug_map_module_wp; SymbolFileDWARFDebugMap * m_debug_map_symfile; clang::TranslationUnitDecl * m_clang_tu_decl; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index bdc2e683d0a..26b2d77a445 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -14,6 +14,8 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Section.h" + +//#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT #if defined(DEBUG_OSO_DMAP) #include "lldb/Core/StreamFile.h" #endif @@ -21,6 +23,7 @@ #include "lldb/Symbol/ClangExternalASTSourceCallbacks.h" #include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/VariableList.h" @@ -35,207 +38,171 @@ using namespace lldb_private; // (so we can fixup the object file sections) and also for "Module::GetSymbolVendor()" // (so we can fixup the symbol file id. -class DebugMapModule : public Module + + + +const SymbolFileDWARFDebugMap::FileRangeMap & +SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile) { -public: - DebugMapModule (const ModuleSP &exe_module_sp, - uint32_t cu_idx, - const FileSpec& file_spec, - const ArchSpec& arch, - const ConstString *object_name, - off_t object_offset) : - Module (file_spec, arch, object_name, object_offset), - m_exe_module_wp (exe_module_sp), - m_cu_idx (cu_idx) - { - LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); - if (log) - log->Printf("%p: DebugMapModule::DebugMapModule (exe_module=%p, cu_idx=%u, oso_path='%s/%s', object_name='%s')", - this, - exe_module_sp.get(), - cu_idx, - file_spec.GetDirectory().GetCString(), - file_spec.GetFilename().GetCString(), - object_name ? object_name->GetCString() : ""); - } + if (file_range_map_valid) + return file_range_map; - virtual - ~DebugMapModule () + file_range_map_valid = true; + + Module *oso_module = exe_symfile->GetModuleByCompUnitInfo (this); + ObjectFile *oso_objfile = oso_module->GetObjectFile(); + + LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); + if (log) { - LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); - if (log) - log->Printf("%p: DebugMapModule::~DebugMapModule ()", this); + ConstString object_name (oso_module->GetObjectName()); + log->Printf("%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s/%s%s%s%s')", + this, + oso_module->GetFileSpec().GetDirectory().GetCString(), + oso_module->GetFileSpec().GetFilename().GetCString(), + object_name ? "(" : "", + object_name ? object_name.GetCString() : "", + object_name ? ")" : ""); } + - virtual ObjectFile * - GetObjectFile () + std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos; + if (exe_symfile->GetCompUnitInfosForModule(oso_module, cu_infos)) { - Mutex::Locker locker (m_mutex); - if (m_did_load_objfile == false) + for (auto comp_unit_info : cu_infos) { - ModuleSP exe_module_sp (m_exe_module_wp.lock()); - if (exe_module_sp) + Symtab *exe_symtab = exe_symfile->GetObjectFile()->GetSymtab(); + ModuleSP oso_module_sp (oso_objfile->GetModule()); + Symtab *oso_symtab = oso_objfile->GetSymtab(); +#if defined(DEBUG_OSO_DMAP) + StreamFile s(stdout, false); + s << "OSO symtab:\n"; + oso_symtab->Dump(&s, NULL, eSortOrderNone); + s << "OSO sections before:\n"; + oso_objfile->GetSectionList()->Dump(&s, NULL, true, UINT32_MAX); +#endif + + ///const uint32_t fun_resolve_flags = SymbolContext::Module | eSymbolContextCompUnit | eSymbolContextFunction; + //SectionList *oso_sections = oso_objfile->Sections(); + // Now we need to make sections that map from zero based object + // file addresses to where things eneded up in the main executable. + + assert (comp_unit_info->first_symbol_index != UINT32_MAX); + // End index is one past the last valid symbol index + const uint32_t oso_end_idx = comp_unit_info->last_symbol_index + 1; + for (uint32_t idx = comp_unit_info->first_symbol_index + 2; // Skip the N_SO and N_OSO + idx < oso_end_idx; + ++idx) { - ObjectFile *exe_objfile = exe_module_sp->GetObjectFile(); - ObjectFile *oso_objfile = Module::GetObjectFile(); - SymbolVendor *exe_sym_vendor = exe_module_sp->GetSymbolVendor(); - - if (exe_objfile && oso_objfile && exe_sym_vendor) + Symbol *exe_symbol = exe_symtab->SymbolAtIndex(idx); + if (exe_symbol) { - SymbolFileDWARFDebugMap *exe_symfile = (SymbolFileDWARFDebugMap *)exe_sym_vendor->GetSymbolFile(); - if (exe_symfile) + if (exe_symbol->IsDebug() == false) + continue; + + switch (exe_symbol->GetType()) { - std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos; - if (exe_symfile->GetCompUnitInfosForModule(this, cu_infos)) + default: + break; + + case eSymbolTypeCode: { - for (auto comp_unit_info : cu_infos) + // For each N_FUN, or function that we run into in the debug map + // we make a new section that we add to the sections found in the + // .o file. This new section has the file address set to what the + // addresses are in the .o file, and the load address is adjusted + // to match where it ended up in the final executable! We do this + // before we parse any dwarf info so that when it goes get parsed + // all section/offset addresses that get registered will resolve + // correctly to the new addresses in the main executable. + + // First we find the original symbol in the .o file's symbol table + Symbol *oso_fun_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(Mangled::ePreferMangled), + eSymbolTypeCode, + Symtab::eDebugNo, + Symtab::eVisibilityAny); + if (oso_fun_symbol) { - // Set the ID of the symbol file DWARF to the index of the OSO - // shifted left by 32 bits to provide a unique prefix for any - // UserID's that get created in the symbol file. - //comp_unit_info->exe_sections_sp.reset(new SectionList); + // Add the inverse OSO file address to debug map entry mapping + exe_symfile->AddOSOFileRange (this, + exe_symbol->GetAddress().GetFileAddress(), + oso_fun_symbol->GetAddress().GetFileAddress(), + std::min<addr_t>(exe_symbol->GetByteSize(), oso_fun_symbol->GetByteSize())); - Symtab *exe_symtab = exe_objfile->GetSymtab(); - ModuleSP oso_module_sp (oso_objfile->GetModule()); - Symtab *oso_symtab = oso_objfile->GetSymtab(); - //#define DEBUG_OSO_DMAP // Do not check in with this defined... -#if defined(DEBUG_OSO_DMAP) - StreamFile s(stdout); - s << "OSO symtab:\n"; - oso_symtab->Dump(&s, NULL); - s << "OSO sections before:\n"; - oso_objfile->GetSectionList()->Dump(&s, NULL, true); -#endif - - ///const uint32_t fun_resolve_flags = SymbolContext::Module | eSymbolContextCompUnit | eSymbolContextFunction; - //SectionList *oso_sections = oso_objfile->Sections(); - // Now we need to make sections that map from zero based object - // file addresses to where things eneded up in the main executable. - - assert (comp_unit_info->first_symbol_index != UINT32_MAX); - // End index is one past the last valid symbol index - const uint32_t oso_end_idx = comp_unit_info->last_symbol_index + 1; - uint32_t sect_id = 0x10000; - for (uint32_t idx = comp_unit_info->first_symbol_index + 2; // Skip the N_SO and N_OSO - idx < oso_end_idx; - ++idx) - { - Symbol *exe_symbol = exe_symtab->SymbolAtIndex(idx); - if (exe_symbol) - { - if (exe_symbol->IsDebug() == false) - continue; - - switch (exe_symbol->GetType()) - { - default: - break; - - case eSymbolTypeCode: - { - // For each N_FUN, or function that we run into in the debug map - // we make a new section that we add to the sections found in the - // .o file. This new section has the file address set to what the - // addresses are in the .o file, and the load address is adjusted - // to match where it ended up in the final executable! We do this - // before we parse any dwarf info so that when it goes get parsed - // all section/offset addresses that get registered will resolve - // correctly to the new addresses in the main executable. - - // First we find the original symbol in the .o file's symbol table - Symbol *oso_fun_symbol = oso_symtab->FindFirstSymbolWithNameAndType(exe_symbol->GetMangled().GetName(Mangled::ePreferMangled), eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny); - if (oso_fun_symbol) - { - // If we found the symbol, then we - SectionSP exe_fun_section (exe_symbol->GetAddress().GetSection()); - SectionSP oso_fun_section (oso_fun_symbol->GetAddress().GetSection()); - if (oso_fun_section) - { - // Now we create a section that we will add as a child of the - // section in which the .o symbol (the N_FUN) exists. - - // We use the exe_symbol size because the one in the .o file - // will just be a symbol with no size, and the exe_symbol - // size will reflect any size changes (ppc has been known to - // shrink function sizes when it gets rid of jump islands that - // aren't needed anymore). - SectionSP oso_fun_section_sp (new Section (oso_fun_symbol->GetAddress().GetSection(), - oso_module_sp, // Module (the .o file) - sect_id++, // Section ID starts at 0x10000 and increments so the section IDs don't overlap with the standard mach IDs - exe_symbol->GetMangled().GetName(Mangled::ePreferMangled), // Name the section the same as the symbol for which is was generated! - eSectionTypeDebug, - oso_fun_symbol->GetAddress().GetOffset(), // File VM address offset in the current section - exe_symbol->GetByteSize(), // File size (we need the size from the executable) - 0, 0, 0)); - - oso_fun_section_sp->SetLinkedLocation (exe_fun_section, - exe_symbol->GetAddress().GetFileAddress() - exe_fun_section->GetFileAddress()); - oso_fun_section->GetChildren().AddSection(oso_fun_section_sp); - } - } - } - break; - - case eSymbolTypeData: - { - // For each N_GSYM we remap the address for the global by making - // a new section that we add to the sections found in the .o file. - // This new section has the file address set to what the - // addresses are in the .o file, and the load address is adjusted - // to match where it ended up in the final executable! We do this - // before we parse any dwarf info so that when it goes get parsed - // all section/offset addresses that get registered will resolve - // correctly to the new addresses in the main executable. We - // initially set the section size to be 1 byte, but will need to - // fix up these addresses further after all globals have been - // parsed to span the gaps, or we can find the global variable - // sizes from the DWARF info as we are parsing. - - // Next we find the non-stab entry that corresponds to the N_GSYM in the .o file - Symbol *oso_gsym_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(), - eSymbolTypeData, - Symtab::eDebugNo, - Symtab::eVisibilityAny); - - if (exe_symbol && oso_gsym_symbol && exe_symbol->ValueIsAddress() && oso_gsym_symbol->ValueIsAddress()) - { - // If we found the symbol, then we - SectionSP exe_gsym_section (exe_symbol->GetAddress().GetSection()); - SectionSP oso_gsym_section (oso_gsym_symbol->GetAddress().GetSection()); - if (oso_gsym_section) - { - SectionSP oso_gsym_section_sp (new Section (oso_gsym_symbol->GetAddress().GetSection(), - oso_module_sp, // Module (the .o file) - sect_id++, // Section ID starts at 0x10000 and increments so the section IDs don't overlap with the standard mach IDs - exe_symbol->GetMangled().GetName(Mangled::ePreferMangled), // Name the section the same as the symbol for which is was generated! - eSectionTypeDebug, - oso_gsym_symbol->GetAddress().GetOffset(), // File VM address offset in the current section - 1, // We don't know the size of the global, just do the main address for now. - 0, 0, 0)); - - oso_gsym_section_sp->SetLinkedLocation (exe_gsym_section, - exe_symbol->GetAddress().GetFileAddress() - exe_gsym_section->GetFileAddress()); - oso_gsym_section->GetChildren().AddSection(oso_gsym_section_sp); - } - } - } - break; - } - } - } - oso_objfile->GetSectionList()->Finalize(); // Now that we're done adding sections, finalize to build fast-lookup caches - #if defined(DEBUG_OSO_DMAP) - s << "OSO sections after:\n"; - oso_objfile->GetSectionList()->Dump(&s, NULL, true); - #endif } } + break; + + case eSymbolTypeData: + { + // For each N_GSYM we remap the address for the global by making + // a new section that we add to the sections found in the .o file. + // This new section has the file address set to what the + // addresses are in the .o file, and the load address is adjusted + // to match where it ended up in the final executable! We do this + // before we parse any dwarf info so that when it goes get parsed + // all section/offset addresses that get registered will resolve + // correctly to the new addresses in the main executable. We + // initially set the section size to be 1 byte, but will need to + // fix up these addresses further after all globals have been + // parsed to span the gaps, or we can find the global variable + // sizes from the DWARF info as we are parsing. + + // Next we find the non-stab entry that corresponds to the N_GSYM in the .o file + Symbol *oso_gsym_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(Mangled::ePreferMangled), + eSymbolTypeData, + Symtab::eDebugNo, + Symtab::eVisibilityAny); + + if (exe_symbol && oso_gsym_symbol && + exe_symbol->ValueIsAddress() && + oso_gsym_symbol->ValueIsAddress()) + { + // Add the inverse OSO file address to debug map entry mapping + exe_symfile->AddOSOFileRange (this, + exe_symbol->GetAddress().GetFileAddress(), + oso_gsym_symbol->GetAddress().GetFileAddress(), + std::min<addr_t>(exe_symbol->GetByteSize(), oso_gsym_symbol->GetByteSize())); + } + } + break; } } } + + exe_symfile->FinalizeOSOFileRanges (this); +#if defined(DEBUG_OSO_DMAP) + s << "OSO sections after:\n"; + oso_objfile->GetSectionList()->Dump(&s, NULL, true, UINT32_MAX); +#endif + // We don't need the symbols anymore for the .o files + oso_objfile->ClearSymtab(); } - return m_objfile_sp.get(); } + return file_range_map; +} + + +class DebugMapModule : public Module +{ +public: + DebugMapModule (const ModuleSP &exe_module_sp, + uint32_t cu_idx, + const FileSpec& file_spec, + const ArchSpec& arch, + const ConstString *object_name, + off_t object_offset) : + Module (file_spec, arch, object_name, object_offset), + m_exe_module_wp (exe_module_sp), + m_cu_idx (cu_idx) + { + } + + virtual + ~DebugMapModule () + { + } + virtual SymbolVendor* GetSymbolVendor(bool can_create = true, lldb_private::Stream *feedback_strm = NULL) @@ -356,14 +323,12 @@ SymbolFileDWARFDebugMap::InitializeObject() GetClangASTContext().SetExternalSource (ast_source_ap); } - - void SymbolFileDWARFDebugMap::InitOSO() { if (m_flags.test(kHaveInitializedOSOs)) return; - + m_flags.set(kHaveInitializedOSOs); // In order to get the abilities of this plug-in, we look at the list of // N_OSO entries (object files) from the symbol table and make sure that @@ -376,10 +341,6 @@ SymbolFileDWARFDebugMap::InitOSO() LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); std::vector<uint32_t> oso_indexes; -#if defined(DEBUG_OSO_DMAP) -// StreamFile s(stdout); -// symtab->Dump(&s, NULL, eSortOrderNone); -#endif // When a mach-o symbol is encoded, the n_type field is encoded in bits // 23:16, and the n_desc field is encoded in bits 15:0. // @@ -399,7 +360,31 @@ SymbolFileDWARFDebugMap::InitOSO() symtab->SortSymbolIndexesByValue(m_func_indexes, true); symtab->SortSymbolIndexesByValue(m_glob_indexes, true); + for (uint32_t sym_idx : m_func_indexes) + { + const Symbol *symbol = symtab->SymbolAtIndex(sym_idx); + lldb::addr_t file_addr = symbol->GetAddress().GetFileAddress(); + lldb::addr_t byte_size = symbol->GetByteSize(); + DebugMap::Entry debug_map_entry(file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS)); + m_debug_map.Append(debug_map_entry); + } + for (uint32_t sym_idx : m_glob_indexes) + { + const Symbol *symbol = symtab->SymbolAtIndex(sym_idx); + lldb::addr_t file_addr = symbol->GetAddress().GetFileAddress(); + lldb::addr_t byte_size = symbol->GetByteSize(); + DebugMap::Entry debug_map_entry(file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS)); + m_debug_map.Append(debug_map_entry); + } + m_debug_map.Sort(); + +#if defined(DEBUG_OSO_DMAP) + StreamFile s(stdout, false); + symtab->Dump(&s, NULL, m_func_indexes); + symtab->Dump(&s, NULL, m_glob_indexes); +#endif m_compile_unit_infos.resize(oso_index_count); + // s.Printf("%s N_OSO symbols:\n", __PRETTY_FUNCTION__); // symtab->Dump(&s, oso_indexes); @@ -643,34 +628,20 @@ SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) FileSpec so_file_spec; if (GetFileSpecForSO (cu_idx, so_file_spec)) { - Module *oso_module = GetModuleByOSOIndex (cu_idx); - if (oso_module) - { - // User zero as the ID to match the compile unit at offset - // zero in each .o file since each .o file can only have - // one compile unit for now. - lldb::user_id_t cu_id = 0; - m_compile_unit_infos[cu_idx].compile_unit_sp.reset (new CompileUnit (oso_module->shared_from_this(), - NULL, - so_file_spec, - cu_id, - eLanguageTypeUnknown)); - } - - if (!m_compile_unit_infos[cu_idx].compile_unit_sp) - { - m_compile_unit_infos[cu_idx].compile_unit_sp.reset(new CompileUnit (m_obj_file->GetModule(), - NULL, - so_file_spec, - cu_idx, - eLanguageTypeUnknown)); - } + // User zero as the ID to match the compile unit at offset + // zero in each .o file since each .o file can only have + // one compile unit for now. + lldb::user_id_t cu_id = 0; + m_compile_unit_infos[cu_idx].compile_unit_sp.reset(new CompileUnit (m_obj_file->GetModule(), + NULL, + so_file_spec, + cu_id, + eLanguageTypeUnknown)); if (m_compile_unit_infos[cu_idx].compile_unit_sp) { // Let our symbol vendor know about this compile unit - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex (cu_idx, - m_compile_unit_infos[cu_idx].compile_unit_sp); + m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex (cu_idx, m_compile_unit_infos[cu_idx].compile_unit_sp); } } } @@ -779,7 +750,7 @@ SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid); SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx); if (oso_dwarf) - oso_dwarf->ResolveTypeUID (type_uid); + return oso_dwarf->ResolveTypeUID (type_uid); return NULL; } @@ -798,30 +769,30 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext (const Address& exe_so_addr, uint3 if (symtab) { const addr_t exe_file_addr = exe_so_addr.GetFileAddress(); - sc.symbol = symtab->FindSymbolContainingFileAddress (exe_file_addr, &m_func_indexes[0], m_func_indexes.size()); - if (sc.symbol != NULL) + const DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains (exe_file_addr); + if (debug_map_entry) { - resolved_flags |= eSymbolContextSymbol; - uint32_t oso_idx = 0; - CompileUnitInfo* comp_unit_info = GetCompileUnitInfoForSymbolWithID (sc.symbol->GetID(), &oso_idx); - if (comp_unit_info) - { - SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx); - ObjectFile *oso_objfile = GetObjectFileByOSOIndex (oso_idx); - if (oso_dwarf && oso_objfile) - { - SectionList *oso_section_list = oso_objfile->GetSectionList(); + sc.symbol = symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex()); - SectionSP oso_symbol_section_sp (oso_section_list->FindSectionContainingLinkedFileAddress (exe_file_addr, UINT32_MAX)); + if (sc.symbol != NULL) + { + resolved_flags |= eSymbolContextSymbol; - if (oso_symbol_section_sp) + uint32_t oso_idx = 0; + CompileUnitInfo* comp_unit_info = GetCompileUnitInfoForSymbolWithID (sc.symbol->GetID(), &oso_idx); + if (comp_unit_info) + { + Module *oso_module = GetModuleByCompUnitInfo (comp_unit_info); + if (oso_module) { - const addr_t linked_file_addr = oso_symbol_section_sp->GetLinkedFileAddress(); - Address oso_so_addr (oso_symbol_section_sp, exe_file_addr - linked_file_addr); - if (oso_so_addr.IsSectionOffset()) - resolved_flags |= oso_dwarf->ResolveSymbolContext (oso_so_addr, resolve_scope, sc); + lldb::addr_t oso_file_addr = exe_file_addr - debug_map_entry->GetRangeBase() + debug_map_entry->data.GetOSOFileAddress(); + Address oso_so_addr; + if (oso_module->ResolveFileAddress(oso_file_addr, oso_so_addr)) + { + resolved_flags |= oso_module->GetSymbolVendor()->ResolveSymbolContext (oso_so_addr, resolve_scope, sc); + } } } } @@ -1307,6 +1278,24 @@ SymbolFileDWARFDebugMap::GetCompileUnit (SymbolFileDWARF *oso_dwarf) return lldb::CompUnitSP(); } +SymbolFileDWARFDebugMap::CompileUnitInfo * +SymbolFileDWARFDebugMap::GetCompileUnitInfo (SymbolFileDWARF *oso_dwarf) +{ + if (oso_dwarf) + { + const uint32_t cu_count = GetNumCompileUnits(); + for (uint32_t cu_idx=0; cu_idx<cu_count; ++cu_idx) + { + SymbolFileDWARF *oso_symfile = GetSymbolFileByCompUnitInfo (&m_compile_unit_infos[cu_idx]); + if (oso_symfile == oso_dwarf) + { + return &m_compile_unit_infos[cu_idx]; + } + } + } + return NULL; +} + void SymbolFileDWARFDebugMap::SetCompileUnit (SymbolFileDWARF *oso_dwarf, const CompUnitSP &cu_sp) @@ -1415,4 +1404,99 @@ SymbolFileDWARFDebugMap::GetClangDeclContextForTypeUID (const lldb_private::Symb return NULL; } +bool +SymbolFileDWARFDebugMap::AddOSOFileRange (CompileUnitInfo *cu_info, + lldb::addr_t exe_file_addr, + lldb::addr_t oso_file_addr, + lldb::addr_t oso_byte_size) +{ + assert (cu_info);// REMOVE THIS PRIOR TO CHECKIN + const uint32_t debug_map_idx = m_debug_map.FindEntryIndexThatContains(exe_file_addr); + if (debug_map_idx != UINT32_MAX) + { + DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains(exe_file_addr); + assert (debug_map_entry);// REMOVE THIS PRIOR TO CHECKIN + debug_map_entry->data.SetOSOFileAddress(oso_file_addr); + cu_info->file_range_map.Append(FileRangeMap::Entry(oso_file_addr, oso_byte_size, exe_file_addr)); + return true; + } + return false; +} + +void +SymbolFileDWARFDebugMap::FinalizeOSOFileRanges (CompileUnitInfo *cu_info) +{ + cu_info->file_range_map.Sort(); +#if defined(DEBUG_OSO_DMAP) + const FileRangeMap &oso_file_range_map = cu_info->GetFileRangeMap(this); + const size_t n = oso_file_range_map.GetSize(); + printf ("SymbolFileDWARFDebugMap::FinalizeOSOFileRanges (cu_info = %p)\n", cu_info); + for (size_t i=0; i<n; ++i) + { + const FileRangeMap::Entry &entry = oso_file_range_map.GetEntryRef(i); + printf ("oso [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ") ==> exe [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", + entry.GetRangeBase(), entry.GetRangeEnd(), + entry.data, entry.data + entry.GetByteSize()); + } +#endif +} + +lldb::addr_t +SymbolFileDWARFDebugMap::LinkOSOFileAddress (SymbolFileDWARF *oso_symfile, lldb::addr_t oso_file_addr) +{ + CompileUnitInfo *cu_info = GetCompileUnitInfo (oso_symfile); + if (cu_info) + { + const FileRangeMap::Entry *oso_range_entry = cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr); + if (oso_range_entry) + { + const DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains(oso_range_entry->data); + if (debug_map_entry) + { + const lldb::addr_t offset = oso_file_addr - oso_range_entry->GetRangeBase(); + const lldb::addr_t exe_file_addr = debug_map_entry->GetRangeBase() + offset; + return exe_file_addr; + } + } + } + return LLDB_INVALID_ADDRESS; +} + +bool +SymbolFileDWARFDebugMap::LinkOSOAddress (Address &addr) +{ + // Make sure this address hasn't been fixed already + Module *exe_module = GetObjectFile()->GetModule().get(); + Module *addr_module = addr.GetModule().get(); + if (addr_module == exe_module) + return true; // Address is already in terms of the main executable module + + CompileUnitInfo *cu_info = GetCompileUnitInfo ((SymbolFileDWARF *)addr_module->GetSymbolVendor()->GetSymbolFile()); + if (cu_info) + { + const lldb::addr_t oso_file_addr = addr.GetFileAddress(); + const FileRangeMap::Entry *oso_range_entry = cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr); + if (oso_range_entry) + { + const DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains(oso_range_entry->data); + if (debug_map_entry) + { + const lldb::addr_t offset = oso_file_addr - oso_range_entry->GetRangeBase(); + const lldb::addr_t exe_file_addr = debug_map_entry->GetRangeBase() + offset; + return exe_module->ResolveFileAddress(exe_file_addr, addr); + } + } + } + return true; +} + +LineTable * +SymbolFileDWARFDebugMap::LinkOSOLineTable (SymbolFileDWARF *oso_dwarf, LineTable *line_table) +{ + CompileUnitInfo *cu_info = GetCompileUnitInfo (oso_dwarf); + if (cu_info) + return line_table->LinkLineTable(cu_info->GetFileRangeMap(this)); + return NULL; +} + diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 971d3e1659b..02d0c6205c8 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -16,6 +16,7 @@ #include "clang/AST/CharUnits.h" +#include "lldb/Core/RangeMap.h" #include "lldb/Symbol/SymbolFile.h" #include "UniqueDWARFASTType.h" @@ -143,6 +144,8 @@ protected: typedef STD_SHARED_PTR(OSOInfo) OSOInfoSP; + typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, lldb::addr_t> FileRangeMap; + //------------------------------------------------------------------ // Class specific types //------------------------------------------------------------------ @@ -156,6 +159,9 @@ protected: uint32_t last_symbol_index; uint32_t first_symbol_id; uint32_t last_symbol_id; + FileRangeMap file_range_map; + bool file_range_map_valid; + CompileUnitInfo() : so_file (), @@ -165,9 +171,14 @@ protected: first_symbol_index (UINT32_MAX), last_symbol_index (UINT32_MAX), first_symbol_id (UINT32_MAX), - last_symbol_id (UINT32_MAX) + last_symbol_id (UINT32_MAX), + file_range_map (), + file_range_map_valid (false) { } + + const FileRangeMap & + GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile); }; //------------------------------------------------------------------ @@ -240,6 +251,9 @@ protected: lldb::CompUnitSP GetCompileUnit (SymbolFileDWARF *oso_dwarf); + + CompileUnitInfo * + GetCompileUnitInfo (SymbolFileDWARF *oso_dwarf); lldb::TypeSP FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx); @@ -258,6 +272,58 @@ protected: { return m_unique_ast_type_map; } + + + //------------------------------------------------------------------ + // OSOEntry + //------------------------------------------------------------------ + class OSOEntry + { + public: + + OSOEntry () : + m_exe_sym_idx (UINT32_MAX), + m_oso_file_addr (LLDB_INVALID_ADDRESS) + { + } + + OSOEntry (uint32_t exe_sym_idx, + lldb::addr_t oso_file_addr) : + m_exe_sym_idx (exe_sym_idx), + m_oso_file_addr (oso_file_addr) + { + } + + uint32_t + GetExeSymbolIndex () const + { + return m_exe_sym_idx; + } + + bool + operator < (const OSOEntry &rhs) const + { + return m_exe_sym_idx < rhs.m_exe_sym_idx; + } + + lldb::addr_t + GetOSOFileAddress () const + { + return m_oso_file_addr; + } + + void + SetOSOFileAddress (lldb::addr_t oso_file_addr) + { + m_oso_file_addr = oso_file_addr; + } + protected: + uint32_t m_exe_sym_idx; + lldb::addr_t m_oso_file_addr; + }; + + typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, OSOEntry> DebugMap; + //------------------------------------------------------------------ // Member Variables //------------------------------------------------------------------ @@ -268,6 +334,77 @@ protected: std::map<lldb_private::ConstString, OSOInfoSP> m_oso_map; UniqueDWARFASTTypeMap m_unique_ast_type_map; lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type; + DebugMap m_debug_map; + + //------------------------------------------------------------------ + // When an object file from the debug map gets parsed in + // SymbolFileDWARF, it needs to tell the debug map about the object + // files addresses by calling this function once for each N_FUN, + // N_GSYM and N_STSYM and after all entries in the debug map have + // been matched up, FinalizeOSOFileRanges() should be called. + //------------------------------------------------------------------ + bool + AddOSOFileRange (CompileUnitInfo *cu_info, + lldb::addr_t exe_file_addr, + lldb::addr_t oso_file_addr, + lldb::addr_t oso_byte_size); + + //------------------------------------------------------------------ + // Called after calling AddOSOFileRange() for each object file debug + // map entry to finalize the info for the unlinked compile unit. + //------------------------------------------------------------------ + void + FinalizeOSOFileRanges (CompileUnitInfo *cu_info); + + //------------------------------------------------------------------ + /// Convert \a addr from a .o file address, to an executable address. + /// + /// @param[in] addr + /// A section offset address from a .o file + /// + /// @return + /// Returns true if \a addr was converted to be an executable + /// section/offset address, false otherwise. + //------------------------------------------------------------------ + bool + LinkOSOAddress (lldb_private::Address &addr); + + //------------------------------------------------------------------ + /// Convert a .o file "file address" to an executable "file address". + /// + /// @param[in] oso_symfile + /// The DWARF symbol file that contains \a oso_file_addr + /// + /// @param[in] oso_file_addr + /// A .o file "file address" to convert. + /// + /// @return + /// LLDB_INVALID_ADDRESS if \a oso_file_addr is not in the + /// linked executable, otherwise a valid "file address" from the + /// linked executable that contains the debug map. + //------------------------------------------------------------------ + lldb::addr_t + LinkOSOFileAddress (SymbolFileDWARF *oso_symfile, lldb::addr_t oso_file_addr); + + //------------------------------------------------------------------ + /// Given a line table full of lines with "file adresses" that are + /// for a .o file represented by \a oso_symfile, link a new line table + /// and return it. + /// + /// @param[in] oso_symfile + /// The DWARF symbol file that produced the \a line_table + /// + /// @param[in] addr + /// A section offset address from a .o file + /// + /// @return + /// Returns a valid line table full of linked addresses, or NULL + /// if none of the line table adresses exist in the main + /// executable. + //------------------------------------------------------------------ + lldb_private::LineTable * + LinkOSOLineTable (SymbolFileDWARF *oso_symfile, + lldb_private::LineTable *line_table); }; #endif // #ifndef SymbolFileDWARF_SymbolFileDWARFDebugMap_h_ diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp index 34f2ea560a9..64c22efa784 100644 --- a/lldb/source/Symbol/Function.cpp +++ b/lldb/source/Symbol/Function.cpp @@ -392,13 +392,7 @@ Function::CalculateSymbolContextModule () { SectionSP section_sp (m_range.GetBaseAddress().GetSection()); if (section_sp) - { - SectionSP linked_section_sp (section_sp->GetLinkedSection()); - if (linked_section_sp) - return linked_section_sp->GetModule(); - else - return section_sp->GetModule(); - } + return section_sp->GetModule(); return this->GetCompileUnit()->GetModule(); } diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp index 6784ac0b2df..479d8cb09e8 100644 --- a/lldb/source/Symbol/LineTable.cpp +++ b/lldb/source/Symbol/LineTable.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/Address.h" +#include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Core/Stream.h" #include "lldb/Symbol/CompileUnit.h" @@ -22,7 +23,6 @@ using namespace lldb_private; //---------------------------------------------------------------------- LineTable::LineTable(CompileUnit* comp_unit) : m_comp_unit(comp_unit), - m_section_list(), m_entries() { } @@ -37,8 +37,7 @@ LineTable::~LineTable() void LineTable::InsertLineEntry ( - const SectionSP& section_sp, - lldb::addr_t section_offset, + lldb::addr_t file_addr, uint32_t line, uint16_t column, uint16_t file_idx, @@ -49,21 +48,7 @@ LineTable::InsertLineEntry bool is_terminal_entry ) { - SectionSP line_section_sp; - SectionSP linked_section_sp (section_sp->GetLinkedSection()); - if (linked_section_sp) - { - section_offset += section_sp->GetLinkedOffset(); - line_section_sp = linked_section_sp; - } - else - { - line_section_sp = section_sp; - } - assert(line_section_sp.get()); - - uint32_t sect_idx = m_section_list.AddUniqueSection (line_section_sp); - Entry entry(sect_idx, section_offset, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry); + Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry); entry_collection::iterator begin_pos = m_entries.begin(); entry_collection::iterator end_pos = m_entries.end(); @@ -85,7 +70,7 @@ LineSequence::LineSequence() void LineTable::LineSequenceImpl::Clear() { - m_seq_entries.clear(); + m_entries.clear(); } LineSequence* LineTable::CreateLineSequenceContainer () @@ -97,8 +82,7 @@ void LineTable::AppendLineEntryToSequence ( LineSequence* sequence, - const SectionSP& section_sp, - lldb::addr_t section_offset, + lldb::addr_t file_addr, uint32_t line, uint16_t column, uint16_t file_idx, @@ -111,9 +95,8 @@ LineTable::AppendLineEntryToSequence { assert(sequence != NULL); LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence); - uint32_t sect_idx = m_section_list.AddUniqueSection (section_sp); - Entry entry(sect_idx, section_offset, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry); - seq->m_seq_entries.push_back (entry); + Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry); + seq->m_entries.push_back (entry); } void @@ -121,17 +104,17 @@ LineTable::InsertSequence (LineSequence* sequence) { assert(sequence != NULL); LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence); - if (seq->m_seq_entries.empty()) + if (seq->m_entries.empty()) return; - Entry& entry = seq->m_seq_entries.front(); - + Entry& entry = seq->m_entries.front(); + // If the first entry address in this sequence is greater than or equal to // the address of the last item in our entry collection, just append. if (m_entries.empty() || !Entry::EntryAddressLessThan(entry, m_entries.back())) { m_entries.insert(m_entries.end(), - seq->m_seq_entries.begin(), - seq->m_seq_entries.end()); + seq->m_entries.begin(), + seq->m_entries.end()); return; } @@ -149,7 +132,7 @@ LineTable::InsertSequence (LineSequence* sequence) assert(prev_pos->is_terminal_entry); } #endif - m_entries.insert(pos, seq->m_seq_entries.begin(), seq->m_seq_entries.end()); + m_entries.insert(pos, seq->m_entries.begin(), seq->m_entries.end()); } //---------------------------------------------------------------------- @@ -161,37 +144,23 @@ LineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate(LineTable *li bool LineTable::Entry::LessThanBinaryPredicate::operator() (const LineTable::Entry& a, const LineTable::Entry& b) const { - if (a.sect_idx == b.sect_idx) - { - #define LT_COMPARE(a,b) if (a != b) return a < b - LT_COMPARE (a.sect_offset, b.sect_offset); - // b and a reversed on purpose below. - LT_COMPARE (b.is_terminal_entry, a.is_terminal_entry); - LT_COMPARE (a.line, b.line); - LT_COMPARE (a.column, b.column); - LT_COMPARE (a.is_start_of_statement, b.is_start_of_statement); - LT_COMPARE (a.is_start_of_basic_block, b.is_start_of_basic_block); - // b and a reversed on purpose below. - LT_COMPARE (b.is_prologue_end, a.is_prologue_end); - LT_COMPARE (a.is_epilogue_begin, b.is_epilogue_begin); - LT_COMPARE (a.file_idx, b.file_idx); - return false; - #undef LT_COMPARE - } - - const Section *a_section = m_line_table->GetSectionForEntryIndex (a.sect_idx); - const Section *b_section = m_line_table->GetSectionForEntryIndex (b.sect_idx); - return Section::Compare(*a_section, *b_section) < 0; + #define LT_COMPARE(a,b) if (a != b) return a < b + LT_COMPARE (a.file_addr, b.file_addr); + // b and a reversed on purpose below. + LT_COMPARE (b.is_terminal_entry, a.is_terminal_entry); + LT_COMPARE (a.line, b.line); + LT_COMPARE (a.column, b.column); + LT_COMPARE (a.is_start_of_statement, b.is_start_of_statement); + LT_COMPARE (a.is_start_of_basic_block, b.is_start_of_basic_block); + // b and a reversed on purpose below. + LT_COMPARE (b.is_prologue_end, a.is_prologue_end); + LT_COMPARE (a.is_epilogue_begin, b.is_epilogue_begin); + LT_COMPARE (a.file_idx, b.file_idx); + return false; + #undef LT_COMPARE } -Section * -LineTable::GetSectionForEntryIndex (uint32_t idx) -{ - if (idx < m_section_list.GetSize()) - return m_section_list.GetSectionAtIndex(idx).get(); - return NULL; -} uint32_t LineTable::GetSize() const @@ -218,69 +187,69 @@ LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry *index_ptr = UINT32_MAX; bool success = false; - uint32_t sect_idx = m_section_list.FindSectionIndex (so_addr.GetSection().get()); - if (sect_idx != UINT32_MAX) + + if (so_addr.GetModule().get() == m_comp_unit->GetModule().get()) { Entry search_entry; - search_entry.sect_idx = sect_idx; - search_entry.sect_offset = so_addr.GetOffset(); - - entry_collection::const_iterator begin_pos = m_entries.begin(); - entry_collection::const_iterator end_pos = m_entries.end(); - entry_collection::const_iterator pos = lower_bound(begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan); - if (pos != end_pos) + search_entry.file_addr = so_addr.GetFileAddress(); + if (search_entry.file_addr != LLDB_INVALID_ADDRESS) { - if (pos != begin_pos) + entry_collection::const_iterator begin_pos = m_entries.begin(); + entry_collection::const_iterator end_pos = m_entries.end(); + entry_collection::const_iterator pos = lower_bound(begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan); + if (pos != end_pos) { - if (pos->sect_offset != search_entry.sect_offset) - --pos; - else if (pos->sect_offset == search_entry.sect_offset) + if (pos != begin_pos) { - // If this is a termination entry, it should't match since - // entries with the "is_terminal_entry" member set to true - // are termination entries that define the range for the - // previous entry. - if (pos->is_terminal_entry) + if (pos->file_addr != search_entry.file_addr) + --pos; + else if (pos->file_addr == search_entry.file_addr) { - // The matching entry is a terminal entry, so we skip - // ahead to the next entry to see if there is another - // entry following this one whose section/offset matches. - ++pos; - if (pos != end_pos) + // If this is a termination entry, it should't match since + // entries with the "is_terminal_entry" member set to true + // are termination entries that define the range for the + // previous entry. + if (pos->is_terminal_entry) { - if (pos->sect_offset != search_entry.sect_offset) - pos = end_pos; + // The matching entry is a terminal entry, so we skip + // ahead to the next entry to see if there is another + // entry following this one whose section/offset matches. + ++pos; + if (pos != end_pos) + { + if (pos->file_addr != search_entry.file_addr) + pos = end_pos; + } } - } - - if (pos != end_pos) - { - // While in the same section/offset backup to find the first - // line entry that matches the address in case there are - // multiple - while (pos != begin_pos) + + if (pos != end_pos) { - entry_collection::const_iterator prev_pos = pos - 1; - if (prev_pos->sect_idx == search_entry.sect_idx && - prev_pos->sect_offset == search_entry.sect_offset && - prev_pos->is_terminal_entry == false) - --pos; - else - break; + // While in the same section/offset backup to find the first + // line entry that matches the address in case there are + // multiple + while (pos != begin_pos) + { + entry_collection::const_iterator prev_pos = pos - 1; + if (prev_pos->file_addr == search_entry.file_addr && + prev_pos->is_terminal_entry == false) + --pos; + else + break; + } } } - } - } - - // Make sure we have a valid match and that the match isn't a terminating - // entry for a previous line... - if (pos != end_pos && pos->is_terminal_entry == false) - { - uint32_t match_idx = std::distance (begin_pos, pos); - success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry); - if (index_ptr != NULL && success) - *index_ptr = match_idx; + } + + // Make sure we have a valid match and that the match isn't a terminating + // entry for a previous line... + if (pos != end_pos && pos->is_terminal_entry == false) + { + uint32_t match_idx = std::distance (begin_pos, pos); + success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry); + if (index_ptr != NULL && success) + *index_ptr = match_idx; + } } } } @@ -294,32 +263,24 @@ LineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry) if (idx < m_entries.size()) { const Entry& entry = m_entries[idx]; - line_entry.range.GetBaseAddress().SetSection(m_section_list.GetSectionAtIndex (entry.sect_idx)); - line_entry.range.GetBaseAddress().SetOffset(entry.sect_offset); - if (!entry.is_terminal_entry && idx + 1 < m_entries.size()) + ModuleSP module_sp (m_comp_unit->GetModule()); + if (module_sp && module_sp->ResolveFileAddress(entry.file_addr, line_entry.range.GetBaseAddress())) { - const Entry& next_entry = m_entries[idx+1]; - if (next_entry.sect_idx == entry.sect_idx) - { - line_entry.range.SetByteSize(next_entry.sect_offset - entry.sect_offset); - } + if (!entry.is_terminal_entry && idx + 1 < m_entries.size()) + line_entry.range.SetByteSize(m_entries[idx+1].file_addr - entry.file_addr); else - { - Address next_line_addr(m_section_list.GetSectionAtIndex (next_entry.sect_idx), next_entry.sect_offset); - line_entry.range.SetByteSize(next_line_addr.GetFileAddress() - line_entry.range.GetBaseAddress().GetFileAddress()); - } + line_entry.range.SetByteSize(0); + + line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx); + line_entry.line = entry.line; + line_entry.column = entry.column; + line_entry.is_start_of_statement = entry.is_start_of_statement; + line_entry.is_start_of_basic_block = entry.is_start_of_basic_block; + line_entry.is_prologue_end = entry.is_prologue_end; + line_entry.is_epilogue_begin = entry.is_epilogue_begin; + line_entry.is_terminal_entry = entry.is_terminal_entry; + return true; } - else - line_entry.range.SetByteSize(0); - line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx); - line_entry.line = entry.line; - line_entry.column = entry.column; - line_entry.is_start_of_statement = entry.is_start_of_statement; - line_entry.is_start_of_basic_block = entry.is_start_of_basic_block; - line_entry.is_prologue_end = entry.is_prologue_end; - line_entry.is_epilogue_begin = entry.is_epilogue_begin; - line_entry.is_terminal_entry = entry.is_terminal_entry; - return true; } return false; } @@ -503,7 +464,6 @@ LineTable::GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool const size_t count = m_entries.size(); LineEntry line_entry; - std::vector<addr_t> section_base_file_addrs (m_section_list.GetSize(), LLDB_INVALID_ADDRESS); FileAddressRanges::Entry range (LLDB_INVALID_ADDRESS, 0); for (size_t idx = 0; idx < count; ++idx) { @@ -513,23 +473,89 @@ LineTable::GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool { if (range.GetRangeBase() != LLDB_INVALID_ADDRESS) { - if (section_base_file_addrs[entry.sect_idx] == LLDB_INVALID_ADDRESS) - section_base_file_addrs[entry.sect_idx] = m_section_list.GetSectionAtIndex (entry.sect_idx)->GetFileAddress(); - range.SetRangeEnd(section_base_file_addrs[entry.sect_idx] + entry.sect_offset); + range.SetRangeEnd(entry.file_addr); file_ranges.Append(range); range.Clear(LLDB_INVALID_ADDRESS); } } else if (range.GetRangeBase() == LLDB_INVALID_ADDRESS) { - if (section_base_file_addrs[entry.sect_idx] == LLDB_INVALID_ADDRESS) - section_base_file_addrs[entry.sect_idx] = m_section_list.GetSectionAtIndex (entry.sect_idx)->GetFileAddress(); - range.SetRangeBase(section_base_file_addrs[entry.sect_idx] + entry.sect_offset); + range.SetRangeBase(entry.file_addr); } } return file_ranges.GetSize() - initial_count; } +LineTable * +LineTable::LinkLineTable (const FileRangeMap &file_range_map) +{ + std::auto_ptr<LineTable> line_table_ap (new LineTable (m_comp_unit)); + LineSequenceImpl sequence; + const size_t count = m_entries.size(); + LineEntry line_entry; + const FileRangeMap::Entry *file_range_entry = NULL; + const FileRangeMap::Entry *prev_file_range_entry = NULL; + lldb::addr_t prev_file_addr = LLDB_INVALID_ADDRESS; + bool prev_entry_was_linked = false; + for (size_t idx = 0; idx < count; ++idx) + { + const Entry& entry = m_entries[idx]; + + const bool end_sequence = entry.is_terminal_entry; + const lldb::addr_t lookup_file_addr = entry.file_addr - (end_sequence ? 1 : 0); + if (file_range_entry == NULL || !file_range_entry->Contains(lookup_file_addr)) + { + prev_file_range_entry = file_range_entry; + file_range_entry = file_range_map.FindEntryThatContains(lookup_file_addr); + } + + if (file_range_entry) + { + // This entry has an address remapping and it needs to have its address relinked + sequence.m_entries.push_back(entry); + // Fix tha addresss + const lldb::addr_t linked_file_addr = entry.file_addr - file_range_entry->GetRangeBase() + file_range_entry->data; +// if (linked_file_addr == 0x000000000128b7d5) +// puts("remove this"); + sequence.m_entries.back().file_addr = linked_file_addr; + } + else if (prev_entry_was_linked) + { + // This entry doesn't have a remapping and it needs to be removed. + // Watch out in case we need to terminate a previous entry needs to + // be terminated now that one line entry in a sequence is not longer valid. + if (!entry.is_terminal_entry && + !sequence.m_entries.empty() && + !sequence.m_entries.back().is_terminal_entry) + { + assert (prev_file_addr != LLDB_INVALID_ADDRESS); + sequence.m_entries.push_back(sequence.m_entries.back()); + const lldb::addr_t linked_file_addr = std::min<lldb::addr_t>(entry.file_addr,prev_file_range_entry->GetRangeEnd()) - prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data; + sequence.m_entries.back().file_addr = linked_file_addr; + sequence.m_entries.back().is_terminal_entry = true; + } + } + + // If we have items in the sequence and the last entry is a terminal entry, + // insert this sequence into our new line table. + if (!sequence.m_entries.empty() && sequence.m_entries.back().is_terminal_entry) + { + line_table_ap->InsertSequence (&sequence); + sequence.Clear(); + prev_entry_was_linked = false; + prev_file_addr = LLDB_INVALID_ADDRESS; + } + else + { + prev_entry_was_linked = file_range_entry != NULL; + prev_file_addr = entry.file_addr; + } + } + if (line_table_ap->m_entries.empty()) + return NULL; + return line_table_ap.release(); +} + diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp index a3574a52c20..4ad515b94d8 100644 --- a/lldb/source/Symbol/ObjectFile.cpp +++ b/lldb/source/Symbol/ObjectFile.cpp @@ -200,8 +200,10 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, m_data (), m_unwind_table (*this), m_process_wp(), - m_memory_addr (LLDB_INVALID_ADDRESS) -{ + m_memory_addr (LLDB_INVALID_ADDRESS), + m_sections_ap (), + m_symtab_ap () +{ if (file_spec_ptr) m_file = *file_spec_ptr; if (data_sp) @@ -209,12 +211,16 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); if (log) { + const ConstString object_name (module_sp->GetObjectName()); if (m_file) { - log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = %s/%s, file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64 "\n", + log->Printf ("%p ObjectFile::ObjectFile() module = %p (%s%s%s%s), file = %s/%s, file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64, this, - module_sp->GetFileSpec().GetDirectory().AsCString(), + module_sp.get(), module_sp->GetFileSpec().GetFilename().AsCString(), + object_name ? "(" : "", + object_name ? object_name.GetCString() : "", + object_name ? ")" : "", m_file.GetDirectory().AsCString(), m_file.GetFilename().AsCString(), m_file_offset, @@ -222,10 +228,13 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, } else { - log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = <NULL>, file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64 "\n", + log->Printf ("%p ObjectFile::ObjectFile() module = %p (%s%s%s%s), file = <NULL>, file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64, this, - module_sp->GetFileSpec().GetDirectory().AsCString(), + module_sp.get(), module_sp->GetFileSpec().GetFilename().AsCString(), + object_name ? "(" : "", + object_name ? object_name.GetCString() : "", + object_name ? ")" : "", m_file_offset, m_length); } @@ -246,17 +255,23 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, m_data (), m_unwind_table (*this), m_process_wp (process_sp), - m_memory_addr (header_addr) -{ + m_memory_addr (header_addr), + m_sections_ap (), + m_symtab_ap () +{ if (header_data_sp) m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize()); LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); if (log) { - log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, process = %p, header_addr = 0x%" PRIx64 "\n", + const ConstString object_name (module_sp->GetObjectName()); + log->Printf ("%p ObjectFile::ObjectFile() module = %p (%s%s%s%s), process = %p, header_addr = 0x%" PRIx64, this, - module_sp->GetFileSpec().GetDirectory().AsCString(), + module_sp.get(), module_sp->GetFileSpec().GetFilename().AsCString(), + object_name ? "(" : "", + object_name ? object_name.GetCString() : "", + object_name ? ")" : "", process_sp.get(), m_memory_addr); } @@ -519,3 +534,20 @@ ObjectFile::SplitArchivePathWithObject (const char *path_with_object, FileSpec & return false; } +void +ObjectFile::ClearSymtab () +{ + ModuleSP module_sp(GetModule()); + if (module_sp) + { + lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); + if (log) + { + log->Printf ("%p ObjectFile::ClearSymtab () symtab = %p", + this, + m_symtab_ap.get()); + } + m_symtab_ap.reset(); + } +} diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp index ee660fb733d..37c204d1890 100644 --- a/lldb/source/Symbol/Symtab.cpp +++ b/lldb/source/Symbol/Symtab.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/RegularExpression.h" +#include "lldb/Core/Section.h" #include "lldb/Core/Timer.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" @@ -882,13 +883,13 @@ Symtab::CalculateSymbolSize (Symbol *symbol) if (!m_addr_indexes_computed) InitAddressIndexes(); const size_t num_addr_indexes = m_addr_indexes.size(); + const lldb::addr_t symbol_file_addr = symbol->GetAddress().GetFileAddress(); SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress (this, - symbol->GetAddress().GetFileAddress(), + symbol_file_addr, &m_addr_indexes.front(), num_addr_indexes); if (info.match_index_ptr != NULL) { - const lldb::addr_t curr_file_addr = symbol->GetAddress().GetFileAddress(); // We can figure out the address range of all symbols except the // last one by taking the delta between the current symbol and // the next symbol @@ -899,15 +900,32 @@ Symtab::CalculateSymbolSize (Symbol *symbol) { Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]); if (next_symbol == NULL) - break; - - const lldb::addr_t next_file_addr = next_symbol->GetAddress().GetFileAddress(); - if (next_file_addr > curr_file_addr) { - byte_size = next_file_addr - curr_file_addr; - symbol->SetByteSize(byte_size); - symbol->SetSizeIsSynthesized(true); - break; + // No next symbol take the size to be the remaining bytes in the section + // in which the symbol resides + SectionSP section_sp (m_objfile->GetSectionList()->FindSectionContainingFileAddress (symbol_file_addr)); + if (section_sp) + { + const lldb::addr_t end_section_file_addr = section_sp->GetFileAddress() + section_sp->GetByteSize(); + if (end_section_file_addr > symbol_file_addr) + { + byte_size = end_section_file_addr - symbol_file_addr; + symbol->SetByteSize(byte_size); + symbol->SetSizeIsSynthesized(true); + break; + } + } + } + else + { + const lldb::addr_t next_file_addr = next_symbol->GetAddress().GetFileAddress(); + if (next_file_addr > symbol_file_addr) + { + byte_size = next_file_addr - symbol_file_addr; + symbol->SetByteSize(byte_size); + symbol->SetSizeIsSynthesized(true); + break; + } } } } |