From a7499c98301e847d2e525921801e1edcc44e34da Mon Sep 17 00:00:00 2001 From: Michael Sartain Date: Mon, 1 Jul 2013 19:45:50 +0000 Subject: [PATCH] Split symbol support for ELF and Linux. llvm-svn: 185366 --- lldb/include/lldb/Core/Module.h | 19 +- lldb/include/lldb/Core/Section.h | 32 + lldb/include/lldb/Core/UUID.h | 2 +- lldb/include/lldb/Symbol/ObjectFile.h | 49 +- lldb/include/lldb/Symbol/SymbolVendor.h | 10 +- lldb/include/lldb/Target/Target.h | 6 + lldb/include/lldb/lldb-enumerations.h | 4 + lldb/lib/Makefile | 1 + lldb/source/API/SBModule.cpp | 121 ++-- lldb/source/CMakeLists.txt | 1 + lldb/source/Commands/CommandObjectTarget.cpp | 32 +- lldb/source/Core/Address.cpp | 11 +- lldb/source/Core/Module.cpp | 112 ++-- lldb/source/Core/Section.cpp | 60 +- lldb/source/Core/UUID.cpp | 16 +- lldb/source/Host/common/Symbols.cpp | 119 +++- .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 585 ++++++++++++------ .../Plugins/ObjectFile/ELF/ObjectFileELF.h | 53 +- .../ObjectFile/Mach-O/ObjectFileMachO.cpp | 11 +- .../ObjectFile/Mach-O/ObjectFileMachO.h | 2 +- .../ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 5 +- .../ObjectFile/PECOFF/ObjectFilePECOFF.h | 2 +- .../Plugins/Process/POSIX/ProcessPOSIX.cpp | 2 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 13 +- .../DWARF/SymbolFileDWARFDebugMap.cpp | 10 +- .../SymbolFile/Symtab/SymbolFileSymtab.cpp | 10 +- .../Plugins/SymbolVendor/CMakeLists.txt | 2 + .../Plugins/SymbolVendor/ELF/CMakeLists.txt | 5 + lldb/source/Plugins/SymbolVendor/ELF/Makefile | 14 + .../SymbolVendor/ELF/SymbolVendorELF.cpp | 200 ++++++ .../SymbolVendor/ELF/SymbolVendorELF.h | 58 ++ .../MacOSX/SymbolVendorMacOSX.cpp | 212 ++++--- lldb/source/Symbol/Function.cpp | 25 +- lldb/source/Symbol/ObjectFile.cpp | 44 +- lldb/source/Symbol/Symbol.cpp | 72 ++- lldb/source/Symbol/SymbolVendor.cpp | 41 +- lldb/source/Target/Target.cpp | 20 + lldb/source/lldb.cpp | 7 + 38 files changed, 1473 insertions(+), 515 deletions(-) create mode 100644 lldb/source/Plugins/SymbolVendor/ELF/CMakeLists.txt create mode 100644 lldb/source/Plugins/SymbolVendor/ELF/Makefile create mode 100644 lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp create mode 100644 lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index 79da79718142..7561f2b003f3 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -45,7 +45,7 @@ class Module : public SymbolContextScope { public: - // Static functions that can track the lifetime of moodule objects. + // Static functions that can track the lifetime of module objects. // This is handy because we might have Module objects that are in // shared pointers that aren't in the global module list (from // ModuleList). If this is the case we need to know about it. @@ -638,7 +638,21 @@ public: //------------------------------------------------------------------ virtual ObjectFile * GetObjectFile (); - + + //------------------------------------------------------------------ + /// Get the unified section list for the module. This is the section + /// list created by the module's object file and any debug info and + /// symbol files created by the symbol vendor. + /// + /// If the symbol vendor has not been loaded yet, this function + /// will return the section list for the object file. + /// + /// @return + /// Unified module section list. + //------------------------------------------------------------------ + virtual SectionList * + GetUnifiedSectionList (); + uint32_t GetVersion (uint32_t *versions, uint32_t num_versions); @@ -986,6 +1000,7 @@ protected: std::unique_ptr m_symfile_ap; ///< A pointer to the symbol vendor for this module. ClangASTContext m_ast; ///< The AST context for this module. PathMappingList m_source_mappings; ///< Module specific source remappings for when you have debug info for a module that doesn't match where the sources currently are + std::unique_ptr m_unified_sections_ap; ///< Unified section list for module. bool m_did_load_objfile:1, m_did_load_symbol_vendor:1, diff --git a/lldb/include/lldb/Core/Section.h b/lldb/include/lldb/Core/Section.h index a8747aeff739..0eb6b48c2c4d 100644 --- a/lldb/include/lldb/Core/Section.h +++ b/lldb/include/lldb/Core/Section.h @@ -18,6 +18,7 @@ #include "lldb/Core/RangeMap.h" #include "lldb/Core/UserID.h" #include "lldb/Core/VMRange.h" +#include "lldb/Symbol/ObjectFile.h" #include namespace lldb_private { @@ -33,6 +34,9 @@ public: ~SectionList(); + bool + Copy (SectionList* dest_section_list); + size_t AddSection (const lldb::SectionSP& section_sp); @@ -77,6 +81,10 @@ public: bool ReplaceSection (lldb::user_id_t sect_id, const lldb::SectionSP& section_sp, uint32_t depth = UINT32_MAX); + // Warning, this can be slow as it's removing items from a std::vector. + bool + DeleteSection (size_t idx); + lldb::SectionSP GetSectionAtIndex (size_t idx) const; @@ -87,6 +95,13 @@ public: void Finalize (); + // Each time Finalize() is called with changes, revision id increments. + uint32_t + GetRevisionID() const + { + return m_revision_id; + } + void Clear () { @@ -94,6 +109,8 @@ public: } protected: + bool m_changed; + uint32_t m_revision_id; collection m_sections; }; @@ -107,6 +124,7 @@ class Section : public: // Create a root section (one that has no parent) Section (const lldb::ModuleSP &module_sp, + ObjectFile *obj_file, lldb::user_id_t sect_id, const ConstString &name, lldb::SectionType sect_type, @@ -119,6 +137,7 @@ public: // Create a section that is a child of parent_section_sp Section (const lldb::SectionSP &parent_section_sp, // NULL for top level sections, non-NULL for child sections const lldb::ModuleSP &module_sp, + ObjectFile *obj_file, lldb::user_id_t sect_id, const ConstString &name, lldb::SectionType sect_type, @@ -271,8 +290,21 @@ public: m_children.Finalize(); } + ObjectFile * + GetObjectFile () + { + return m_obj_file; + } + const ObjectFile * + GetObjectFile () const + { + return m_obj_file; + } + + protected: + ObjectFile *m_obj_file; // The object file that data for this section should be read from lldb::SectionType m_type; // The type of this section lldb::SectionWP m_parent_wp; // Weak pointer to parent section ConstString m_name; // Name of this section diff --git a/lldb/include/lldb/Core/UUID.h b/lldb/include/lldb/Core/UUID.h index 86ba099e2706..8a1a173ac302 100644 --- a/lldb/include/lldb/Core/UUID.h +++ b/lldb/include/lldb/Core/UUID.h @@ -56,7 +56,7 @@ public: SetBytes (const void *uuid_bytes, uint32_t num_uuid_bytes = 16); std::string - GetAsString () const; + GetAsString (const char *separator = NULL) const; size_t SetFromCString (const char *c_str, uint32_t num_uuid_bytes = 16); diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h index c8f3cd5254c9..92a530df287f 100644 --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/lldb/include/lldb/Symbol/ObjectFile.h @@ -13,6 +13,7 @@ #include "lldb/lldb-private.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Host/FileSpec.h" +#include "lldb/Core/FileSpecList.h" #include "lldb/Core/ModuleChild.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Host/Endian.h" @@ -78,7 +79,12 @@ public: eStrataKernel, eStrataRawImage } Strata; - + + typedef enum + { + eSymtabFromUnifiedSectionList = 0x0001 /// Return symbol table from unified module section list + } SymtabFlags; + //------------------------------------------------------------------ /// Construct with a parent module, offset, and header data. /// @@ -356,22 +362,30 @@ public: /// Symbol table parsing can be deferred by ObjectFile instances /// until this accessor is called the first time. /// + /// @param[in] flags + /// eSymtabFromUnifiedSectionList: Whether to get symbol table + /// for unified module section list, or object file. + /// /// @return /// The symbol table for this object file. //------------------------------------------------------------------ virtual Symtab * - GetSymtab () = 0; + GetSymtab (uint32_t flags = 0) = 0; //------------------------------------------------------------------ /// Frees the symbol table. /// /// This function should only be used when an object file is /// + /// @param[in] flags + /// eSymtabFromUnifiedSectionList: Whether to clear symbol table + /// for unified module section list, or object file. + /// /// @return /// The symbol table for this object file. //------------------------------------------------------------------ virtual void - ClearSymtab (); + ClearSymtab (uint32_t flags = 0); //------------------------------------------------------------------ /// Gets the UUID for this object file. @@ -388,6 +402,21 @@ public: virtual bool GetUUID (lldb_private::UUID* uuid) = 0; + //------------------------------------------------------------------ + /// Gets the symbol file spec list for this object file. + /// + /// If the object file format contains a debug symbol file link, + /// the values will be return in the FileSpecList. + /// + /// @return + /// Returns filespeclist. + //------------------------------------------------------------------ + virtual lldb_private::FileSpecList + GetDebugSymbolFilePaths() + { + return FileSpecList(); + } + //------------------------------------------------------------------ /// Gets whether endian swapping should occur when extracting data /// from this object file. @@ -485,6 +514,7 @@ public: { return lldb::RegisterContextSP(); } + //------------------------------------------------------------------ /// The object file should be able to calculate its type by looking /// at its file header and possibly the sections or other data in @@ -500,6 +530,17 @@ public: virtual Type CalculateType() = 0; + //------------------------------------------------------------------ + /// In cases where the type can't be calculated (elf files), this + /// routine allows someone to explicitly set it. As an example, + /// SymbolVendorELF uses this routine to set eTypeDebugInfo when + /// loading debug link files. + virtual void + SetType (Type type) + { + m_type = type; + } + //------------------------------------------------------------------ /// The object file should be able to calculate the strata of the /// object file. @@ -635,6 +676,8 @@ protected: const lldb::addr_t m_memory_addr; std::unique_ptr m_sections_ap; std::unique_ptr m_symtab_ap; + std::unique_ptr m_symtab_unified_ap; ///< Unified section list symbol table. + uint32_t m_symtab_unified_revisionid; ///< Unified section list symbol table revision id for when m_symtab_unified_ap was last modified. //------------------------------------------------------------------ /// Sets the architecture for a module. At present the architecture diff --git a/lldb/include/lldb/Symbol/SymbolVendor.h b/lldb/include/lldb/Symbol/SymbolVendor.h index 212fceb8f108..0ca2c0e9c0d7 100644 --- a/lldb/include/lldb/Symbol/SymbolVendor.h +++ b/lldb/include/lldb/Symbol/SymbolVendor.h @@ -164,6 +164,14 @@ public: return m_sym_file_ap.get(); } + // Get module unified section list symbol table. + virtual Symtab * + GetSymtab (); + + // Clear module unified section list symbol table. + virtual void + ClearSymtab (); + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ @@ -184,7 +192,7 @@ protected: TypeList m_type_list; // Uniqued types for all parsers owned by this module CompileUnits m_compile_units; // The current compile units lldb::ObjectFileSP m_objfile_sp; // Keep a reference to the object file in case it isn't the same as the module object file (debug symbols in a separate file) - std::unique_ptr m_sym_file_ap; // A single symbol file. Suclasses can add more of these if needed. + std::unique_ptr m_sym_file_ap; // A single symbol file. Subclasses can add more of these if needed. private: //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 908c7b544561..33effa1a1b25 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -118,6 +118,9 @@ public: FileSpecList & GetExecutableSearchPaths (); + + FileSpecList & + GetDebugFileSearchPaths (); bool GetEnableSyntheticValue () const; @@ -378,6 +381,9 @@ public: static FileSpecList GetDefaultExecutableSearchPaths (); + static FileSpecList + GetDefaultDebugFileSearchPaths (); + static ArchSpec GetDefaultArchitecture (); diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index 3b3ff087b665..6ec5ed6a35e2 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -515,6 +515,10 @@ namespace lldb { eSectionTypeDWARFAppleTypes, eSectionTypeDWARFAppleNamespaces, eSectionTypeDWARFAppleObjC, + eSectionTypeELFSymbolTable, // Elf SHT_SYMTAB section + eSectionTypeELFDynamicSymbols, // Elf SHT_DYNSYM section + eSectionTypeELFRelocationEntries, // Elf SHT_REL or SHT_REL section + eSectionTypeELFDynamicLinkInfo, // Elf SHT_DYNAMIC section eSectionTypeEHFrame, eSectionTypeOther diff --git a/lldb/lib/Makefile b/lldb/lib/Makefile index 6a57d00084b7..ea028ce37354 100644 --- a/lldb/lib/Makefile +++ b/lldb/lib/Makefile @@ -40,6 +40,7 @@ USEDLIBS = lldbAPI.a \ lldbPluginLanguageRuntimeObjCAppleObjCRuntime.a \ lldbPluginObjectContainerBSDArchive.a \ lldbPluginObjectFileELF.a \ + lldbPluginSymbolVendorELF.a \ lldbPluginObjectFilePECOFF.a \ lldbPluginOperatingSystemPython.a \ lldbPluginPlatformGDBServer.a \ diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp index 47540b6f5114..11a2c6c419d4 100644 --- a/lldb/source/API/SBModule.cpp +++ b/lldb/source/API/SBModule.cpp @@ -300,19 +300,27 @@ SBModule::GetCompileUnitAtIndex (uint32_t index) return sb_cu; } +static Symtab * +GetUnifiedSymbolTable (const lldb::ModuleSP& module_sp) +{ + if (module_sp) + { + SymbolVendor *symbols = module_sp->GetSymbolVendor(); + if (symbols) + return symbols->GetSymtab(); + } + return NULL; +} + size_t SBModule::GetNumSymbols () { ModuleSP module_sp (GetSP ()); if (module_sp) { - ObjectFile *obj_file = module_sp->GetObjectFile(); - if (obj_file) - { - Symtab *symtab = obj_file->GetSymtab(); - if (symtab) - return symtab->GetNumSymbols(); - } + Symtab *symtab = GetUnifiedSymbolTable (module_sp); + if (symtab) + return symtab->GetNumSymbols(); } return 0; } @@ -322,16 +330,9 @@ SBModule::GetSymbolAtIndex (size_t idx) { SBSymbol sb_symbol; ModuleSP module_sp (GetSP ()); - if (module_sp) - { - ObjectFile *obj_file = module_sp->GetObjectFile(); - if (obj_file) - { - Symtab *symtab = obj_file->GetSymtab(); - if (symtab) - sb_symbol.SetSymbol(symtab->SymbolAtIndex (idx)); - } - } + Symtab *symtab = GetUnifiedSymbolTable (module_sp); + if (symtab) + sb_symbol.SetSymbol(symtab->SymbolAtIndex (idx)); return sb_symbol; } @@ -343,16 +344,9 @@ SBModule::FindSymbol (const char *name, if (name && name[0]) { ModuleSP module_sp (GetSP ()); - if (module_sp) - { - ObjectFile *obj_file = module_sp->GetObjectFile(); - if (obj_file) - { - Symtab *symtab = obj_file->GetSymtab(); - if (symtab) - sb_symbol.SetSymbol(symtab->FindFirstSymbolWithNameAndType(ConstString(name), symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny)); - } - } + Symtab *symtab = GetUnifiedSymbolTable (module_sp); + if (symtab) + sb_symbol.SetSymbol(symtab->FindFirstSymbolWithNameAndType(ConstString(name), symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny)); } return sb_symbol; } @@ -365,28 +359,21 @@ SBModule::FindSymbols (const char *name, lldb::SymbolType symbol_type) if (name && name[0]) { ModuleSP module_sp (GetSP ()); - if (module_sp) + Symtab *symtab = GetUnifiedSymbolTable (module_sp); + if (symtab) { - ObjectFile *obj_file = module_sp->GetObjectFile(); - if (obj_file) + std::vector matching_symbol_indexes; + const size_t num_matches = symtab->FindAllSymbolsWithNameAndType(ConstString(name), symbol_type, matching_symbol_indexes); + if (num_matches) { - Symtab *symtab = obj_file->GetSymtab(); - if (symtab) + SymbolContext sc; + sc.module_sp = module_sp; + SymbolContextList &sc_list = *sb_sc_list; + for (size_t i=0; i matching_symbol_indexes; - const size_t num_matches = symtab->FindAllSymbolsWithNameAndType(ConstString(name), symbol_type, matching_symbol_indexes); - if (num_matches) - { - SymbolContext sc; - sc.module_sp = module_sp; - SymbolContextList &sc_list = *sb_sc_list; - for (size_t i=0; iSymbolAtIndex (matching_symbol_indexes[i]); - if (sc.symbol) - sc_list.Append(sc); - } - } + sc.symbol = symtab->SymbolAtIndex (matching_symbol_indexes[i]); + if (sc.symbol) + sc_list.Append(sc); } } } @@ -403,13 +390,11 @@ SBModule::GetNumSections () ModuleSP module_sp (GetSP ()); if (module_sp) { - ObjectFile *obj_file = module_sp->GetObjectFile(); - if (obj_file) - { - SectionList *section_list = obj_file->GetSectionList (); - if (section_list) - return section_list->GetSize(); - } + // Give the symbol vendor a chance to add to the unified section list. + module_sp->GetSymbolVendor(); + SectionList *section_list = module_sp->GetUnifiedSectionList(); + if (section_list) + return section_list->GetSize(); } return 0; } @@ -421,14 +406,12 @@ SBModule::GetSectionAtIndex (size_t idx) ModuleSP module_sp (GetSP ()); if (module_sp) { - ObjectFile *obj_file = module_sp->GetObjectFile(); - if (obj_file) - { - SectionList *section_list = obj_file->GetSectionList (); + // Give the symbol vendor a chance to add to the unified section list. + module_sp->GetSymbolVendor(); + SectionList *section_list = module_sp->GetUnifiedSectionList (); - if (section_list) - sb_section.SetSP(section_list->GetSectionAtIndex (idx)); - } + if (section_list) + sb_section.SetSP(section_list->GetSectionAtIndex (idx)); } return sb_section; } @@ -588,18 +571,16 @@ SBModule::FindSection (const char *sect_name) ModuleSP module_sp (GetSP ()); if (sect_name && module_sp) { - ObjectFile *objfile = module_sp->GetObjectFile(); - if (objfile) + // Give the symbol vendor a chance to add to the unified section list. + module_sp->GetSymbolVendor(); + SectionList *section_list = module_sp->GetUnifiedSectionList(); + if (section_list) { - SectionList *section_list = objfile->GetSectionList(); - if (section_list) + ConstString const_sect_name(sect_name); + SectionSP section_sp (section_list->FindSectionByName(const_sect_name)); + if (section_sp) { - ConstString const_sect_name(sect_name); - SectionSP section_sp (section_list->FindSectionByName(const_sect_name)); - if (section_sp) - { - sb_section.SetSP (section_sp); - } + sb_section.SetSP (section_sp); } } } diff --git a/lldb/source/CMakeLists.txt b/lldb/source/CMakeLists.txt index 595acf07f0ed..8b7d34f73ed3 100644 --- a/lldb/source/CMakeLists.txt +++ b/lldb/source/CMakeLists.txt @@ -49,6 +49,7 @@ set( LLDB_USED_LIBS lldbPluginObjectFileMachO lldbPluginObjectFileELF + lldbPluginSymbolVendorELF lldbPluginObjectContainerBSDArchive lldbPluginObjectContainerMachOArchive lldbPluginProcessGDBRemote diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 689fb2e9f035..0ba1dd4751d3 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -1438,10 +1438,10 @@ DumpModuleSymtab (CommandInterpreter &interpreter, Stream &strm, Module *module, { if (module) { - ObjectFile *objfile = module->GetObjectFile (); - if (objfile) + SymbolVendor *sym_vendor = module->GetSymbolVendor (); + if (sym_vendor) { - Symtab *symtab = objfile->GetSymtab(); + Symtab *symtab = sym_vendor->GetSymtab(); if (symtab) symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), sort_order); } @@ -1453,19 +1453,15 @@ DumpModuleSections (CommandInterpreter &interpreter, Stream &strm, Module *modul { if (module) { - ObjectFile *objfile = module->GetObjectFile (); - if (objfile) + SectionList *section_list = module->GetUnifiedSectionList(); + if (section_list) { - SectionList *section_list = objfile->GetSectionList(); - if (section_list) - { - strm.Printf ("Sections for '%s' (%s):\n", - module->GetSpecificationDescription().c_str(), - module->GetArchitecture().GetArchitectureName()); - strm.IndentMore(); - section_list->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), true, UINT32_MAX); - strm.IndentLess(); - } + strm.Printf ("Sections for '%s' (%s):\n", + module->GetSpecificationDescription().c_str(), + module->GetArchitecture().GetArchitectureName()); + strm.IndentMore(); + section_list->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), true, UINT32_MAX); + strm.IndentLess(); } } } @@ -1569,10 +1565,10 @@ LookupSymbolInModule (CommandInterpreter &interpreter, Stream &strm, Module *mod { SymbolContext sc; - ObjectFile *objfile = module->GetObjectFile (); - if (objfile) + SymbolVendor *sym_vendor = module->GetSymbolVendor (); + if (sym_vendor) { - Symtab *symtab = objfile->GetSymtab(); + Symtab *symtab = sym_vendor->GetSymtab(); if (symtab) { uint32_t i; diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp index 48a3e215678d..8d599d80ad4f 100644 --- a/lldb/source/Core/Address.cpp +++ b/lldb/source/Core/Address.cpp @@ -18,6 +18,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Symbol/SymbolVendor.h" #include "llvm/ADT/Triple.h" @@ -456,10 +457,10 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum case eSectionTypeData: if (module_sp) { - ObjectFile *objfile = module_sp->GetObjectFile(); - if (objfile) + SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); + if (sym_vendor) { - Symtab *symtab = objfile->GetSymtab(); + Symtab *symtab = sym_vendor->GetSymtab(); if (symtab) { const addr_t file_Addr = GetFileAddress(); @@ -1023,7 +1024,11 @@ Address::GetAddressClass () const { ObjectFile *obj_file = module_sp->GetObjectFile(); if (obj_file) + { + // Give the symbol vendor a chance to add to the unified section list. + module_sp->GetSymbolVendor(); return obj_file->GetAddressClass (GetFileAddress()); + } } return eAddressClassUnknown; } diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index df0ffb6ed023..e5df43287d12 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -33,6 +33,7 @@ #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Symbol/SymbolFile.h" using namespace lldb; using namespace lldb_private; @@ -244,6 +245,7 @@ Module::~Module() // function calls back into this module object. The ordering is important // here because symbol files can require the module object file. So we tear // down the symbol file first, then the object file. + m_unified_sections_ap.reset(); m_symfile_ap.reset(); m_objfile_sp.reset(); } @@ -480,10 +482,10 @@ Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve // Resolve the symbol if requested, but don't re-look it up if we've already found it. if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol)) { - ObjectFile* ofile = GetObjectFile(); - if (ofile) + SymbolVendor* sym_vendor = GetSymbolVendor(); + if (sym_vendor) { - Symtab *symtab = ofile->GetSymtab(); + Symtab *symtab = sym_vendor->GetSymtab(); if (symtab) { if (so_addr.IsSectionOffset()) @@ -613,6 +615,7 @@ Module::FindFunctions (const ConstString &name, match_name_after_lookup); if (symbols) + { symbols->FindFunctions(lookup_name, namespace_decl, lookup_name_type_mask, @@ -620,13 +623,10 @@ Module::FindFunctions (const ConstString &name, append, sc_list); - // Now check our symbol table for symbols that are code symbols if requested - if (include_symbols) - { - ObjectFile *objfile = GetObjectFile(); - if (objfile) + // Now check our symbol table for symbols that are code symbols if requested + if (include_symbols) { - Symtab *symtab = objfile->GetSymtab(); + Symtab *symtab = symbols->GetSymtab(); if (symtab) symtab->FindFunctionSymbols(lookup_name, lookup_name_type_mask, sc_list); } @@ -652,20 +652,17 @@ Module::FindFunctions (const ConstString &name, ++i; } } - } else { if (symbols) + { symbols->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list); - // Now check our symbol table for symbols that are code symbols if requested - if (include_symbols) - { - ObjectFile *objfile = GetObjectFile(); - if (objfile) + // Now check our symbol table for symbols that are code symbols if requested + if (include_symbols) { - Symtab *symtab = objfile->GetSymtab(); + Symtab *symtab = symbols->GetSymtab(); if (symtab) symtab->FindFunctionSymbols(name, name_type_mask, sc_list); } @@ -689,14 +686,13 @@ Module::FindFunctions (const RegularExpression& regex, SymbolVendor *symbols = GetSymbolVendor (); if (symbols) - symbols->FindFunctions(regex, include_inlines, append, sc_list); - // Now check our symbol table for symbols that are code symbols if requested - if (include_symbols) { - ObjectFile *objfile = GetObjectFile(); - if (objfile) + symbols->FindFunctions(regex, include_inlines, append, sc_list); + + // Now check our symbol table for symbols that are code symbols if requested + if (include_symbols) { - Symtab *symtab = objfile->GetSymtab(); + Symtab *symtab = symbols->GetSymtab(); if (symtab) { std::vector symbol_indexes; @@ -1067,13 +1063,12 @@ Module::Dump(Stream *s) m_object_name ? ")" : ""); s->IndentMore(); + ObjectFile *objfile = GetObjectFile (); - if (objfile) objfile->Dump(s); SymbolVendor *symbols = GetSymbolVendor (); - if (symbols) symbols->Dump(s); @@ -1115,15 +1110,29 @@ Module::GetObjectFile() data_offset); if (m_objfile_sp) { - // Once we get the object file, update our module with the object file's - // architecture since it might differ in vendor/os if some parts were - // unknown. + // Once we get the object file, update our module with the object file's + // architecture since it might differ in vendor/os if some parts were + // unknown. m_objfile_sp->GetArchitecture (m_arch); + + // Populate m_unified_sections_ap with sections from objfile. + SectionList *section_list = m_objfile_sp->GetSectionList(); + if (section_list) + { + m_unified_sections_ap.reset(new SectionList()); + section_list->Copy (m_unified_sections_ap.get()); + m_unified_sections_ap->Finalize(); + } } } return m_objfile_sp.get(); } +SectionList * +Module::GetUnifiedSectionList() +{ + return m_unified_sections_ap.get(); +} const Symbol * Module::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type) @@ -1132,10 +1141,10 @@ Module::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symb "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)", name.AsCString(), symbol_type); - ObjectFile *objfile = GetObjectFile(); - if (objfile) + SymbolVendor* sym_vendor = GetSymbolVendor(); + if (sym_vendor) { - Symtab *symtab = objfile->GetSymtab(); + Symtab *symtab = sym_vendor->GetSymtab(); if (symtab) return symtab->FindFirstSymbolWithNameAndType (name, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny); } @@ -1170,10 +1179,10 @@ Module::FindFunctionSymbols (const ConstString &name, "Module::FindSymbolsFunctions (name = %s, mask = 0x%8.8x)", name.AsCString(), name_type_mask); - ObjectFile *objfile = GetObjectFile (); - if (objfile) + SymbolVendor* sym_vendor = GetSymbolVendor(); + if (sym_vendor) { - Symtab *symtab = objfile->GetSymtab(); + Symtab *symtab = sym_vendor->GetSymtab(); if (symtab) return symtab->FindFunctionSymbols (name, name_type_mask, sc_list); } @@ -1192,10 +1201,10 @@ Module::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_t name.AsCString(), symbol_type); const size_t initial_size = sc_list.GetSize(); - ObjectFile *objfile = GetObjectFile (); - if (objfile) + SymbolVendor* sym_vendor = GetSymbolVendor(); + if (sym_vendor) { - Symtab *symtab = objfile->GetSymtab(); + Symtab *symtab = sym_vendor->GetSymtab(); if (symtab) { std::vector symbol_indexes; @@ -1217,10 +1226,10 @@ Module::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, SymbolT regex.GetText(), symbol_type); const size_t initial_size = sc_list.GetSize(); - ObjectFile *objfile = GetObjectFile (); - if (objfile) + SymbolVendor* sym_vendor = GetSymbolVendor(); + if (sym_vendor) { - Symtab *symtab = objfile->GetSymtab(); + Symtab *symtab = sym_vendor->GetSymtab(); if (symtab) { std::vector symbol_indexes; @@ -1234,12 +1243,35 @@ Module::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, SymbolT void Module::SetSymbolFileFileSpec (const FileSpec &file) { + // Remove any sections in the unified section list that come from the current symbol vendor. + if (m_symfile_ap) + { + SectionList *section_list = GetUnifiedSectionList(); + SymbolFile *symbol_file = m_symfile_ap->GetSymbolFile(); + if (section_list && symbol_file) + { + ObjectFile *obj_file = symbol_file->GetObjectFile(); + if (obj_file) + { + size_t num_sections = section_list->GetNumSections (0); + for (size_t idx = num_sections; idx > 0; --idx) + { + lldb::SectionSP section_sp (section_list->GetSectionAtIndex (idx - 1)); + if (section_sp->GetObjectFile() == obj_file) + { + m_unified_sections_ap->DeleteSection (idx - 1); + } + } + m_unified_sections_ap->Finalize(); + } + } + } + m_symfile_spec = file; m_symfile_ap.reset(); m_did_load_symbol_vendor = false; } - bool Module::IsExecutable () { diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp index 203a6daf5cc7..cb565f07a27e 100644 --- a/lldb/source/Core/Section.cpp +++ b/lldb/source/Core/Section.cpp @@ -16,6 +16,7 @@ using namespace lldb; using namespace lldb_private; Section::Section (const ModuleSP &module_sp, + ObjectFile *obj_file, user_id_t sect_id, const ConstString &name, SectionType sect_type, @@ -27,6 +28,7 @@ Section::Section (const ModuleSP &module_sp, ModuleChild (module_sp), UserID (sect_id), Flags (flags), + m_obj_file (obj_file), m_type (sect_type), m_parent_wp (), m_name (name), @@ -45,6 +47,7 @@ Section::Section (const ModuleSP &module_sp, Section::Section (const lldb::SectionSP &parent_section_sp, const ModuleSP &module_sp, + ObjectFile *obj_file, user_id_t sect_id, const ConstString &name, SectionType sect_type, @@ -56,6 +59,7 @@ Section::Section (const lldb::SectionSP &parent_section_sp, ModuleChild (module_sp), UserID (sect_id), Flags (flags), + m_obj_file (obj_file), m_type (sect_type), m_parent_wp (), m_name (name), @@ -242,13 +246,16 @@ Section::DumpName (Stream *s) const else { // The top most section prints the module basename + const char * name = NULL; ModuleSP module_sp (GetModule()); - if (module_sp) - { - const char *module_basename = module_sp->GetFileSpec().GetFilename().AsCString(); - if (module_basename && module_basename[0]) - s->Printf("%s.", module_basename); - } + const FileSpec &file_spec = m_obj_file->GetFileSpec(); + + if (m_obj_file) + name = file_spec.GetFilename().AsCString(); + if ((!name || !name[0]) && module_sp) + name = module_sp->GetFileSpec().GetFilename().AsCString(); + if (name && name[0]) + s->Printf("%s.", name); } m_name.Dump(s); } @@ -285,6 +292,8 @@ Section::Slide (addr_t slide_amount, bool slide_children) #pragma mark SectionList SectionList::SectionList () : + m_changed(false), + m_revision_id(0), m_sections() { } @@ -294,15 +303,41 @@ SectionList::~SectionList () { } +bool +SectionList::Copy (SectionList *dest_section_list) +{ + if (dest_section_list) + { + dest_section_list->m_sections = m_sections; + dest_section_list->m_changed = true; + return true; + } + return false; +} + size_t SectionList::AddSection (const lldb::SectionSP& section_sp) { + m_changed = true; assert (section_sp.get()); size_t section_index = m_sections.size(); m_sections.push_back(section_sp); return section_index; } +// Warning, this can be slow as it's removing items from a std::vector. +bool +SectionList::DeleteSection (size_t idx) +{ + if (idx < m_sections.size()) + { + m_changed = true; + m_sections.erase (m_sections.begin() + idx); + return true; + } + return false; +} + size_t SectionList::FindSectionIndex (const Section* sect) { @@ -325,11 +360,13 @@ SectionList::AddUniqueSection (const lldb::SectionSP& sect_sp) { size_t sect_idx = FindSectionIndex (sect_sp.get()); if (sect_idx == UINT32_MAX) + { + m_changed = true; sect_idx = AddSection (sect_sp); + } return sect_idx; } - bool SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp, uint32_t depth) { @@ -338,6 +375,7 @@ SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp, { if ((*sect_iter)->GetID() == sect_id) { + m_changed = true; *sect_iter = sect_sp; return true; } @@ -350,7 +388,6 @@ SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp, return false; } - size_t SectionList::GetNumSections (uint32_t depth) const { @@ -527,5 +564,10 @@ SectionList::Finalize () sect->GetChildren().Finalize(); } -} + if (m_changed) + { + m_revision_id++; + m_changed = false; + } +} diff --git a/lldb/source/Core/UUID.cpp b/lldb/source/Core/UUID.cpp index a5124314d59a..8b2158b88e26 100644 --- a/lldb/source/Core/UUID.cpp +++ b/lldb/source/Core/UUID.cpp @@ -67,20 +67,26 @@ UUID::GetBytes() const } std::string -UUID::GetAsString () const +UUID::GetAsString (const char *separator) const { std::string result; - char buf[64]; + char buf[256]; + if (!separator) + separator = "-"; const uint8_t *u = (const uint8_t *)GetBytes(); if (sizeof (buf) > (size_t)snprintf (buf, sizeof (buf), - "%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", - u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15])) + "%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", + u[0],u[1],u[2],u[3],separator, + u[4],u[5],separator, + u[6],u[7],separator, + u[8],u[9],separator, + u[10],u[11],u[12],u[13],u[14],u[15])) { result.append (buf); if (m_num_uuid_bytes == 20) { - if (sizeof (buf) > (size_t)snprintf (buf, sizeof (buf), "-%2.2X%2.2X%2.2X%2.2X", u[16],u[17],u[18],u[19])) + if (sizeof (buf) > (size_t)snprintf (buf, sizeof (buf), "%s%2.2X%2.2X%2.2X%2.2X", separator,u[16],u[17],u[18],u[19])) result.append (buf); } } diff --git a/lldb/source/Host/common/Symbols.cpp b/lldb/source/Host/common/Symbols.cpp index ae6d16613b17..26f6db57c14f 100644 --- a/lldb/source/Host/common/Symbols.cpp +++ b/lldb/source/Host/common/Symbols.cpp @@ -8,11 +8,127 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/Symbols.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/DataBuffer.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/Timer.h" +#include "lldb/Core/UUID.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Target.h" using namespace lldb; using namespace lldb_private; -#if !defined (__APPLE__) +#if defined (__linux__) + +FileSpec +Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec) +{ + // FIXME + return FileSpec(); +} + +FileSpec +Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec) +{ + const char *symbol_filename = module_spec.GetSymbolFileSpec().GetFilename().AsCString(); + if (!symbol_filename || !symbol_filename[0]) + return FileSpec(); + + FileSpecList debug_file_search_paths (Target::GetDefaultDebugFileSearchPaths()); + + // Add module directory. + const ConstString &file_dir = module_spec.GetFileSpec().GetDirectory(); + debug_file_search_paths.AppendIfUnique (FileSpec(file_dir.AsCString("."), true)); + + // Add current working directory. + debug_file_search_paths.AppendIfUnique (FileSpec(".", true)); + + // Add /usr/lib/debug directory. + debug_file_search_paths.AppendIfUnique (FileSpec("/usr/lib/debug", true)); + + std::string uuid_str; + const UUID &module_uuid = module_spec.GetUUID(); + if (module_uuid.IsValid()) + { + // Some debug files are stored in the .build-id directory like this: + // /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug + uuid_str = module_uuid.GetAsString(""); + uuid_str.insert (2, 1, '/'); + uuid_str = uuid_str + ".debug"; + } + + // Get full path to our module. Needed to check debug files like this: + // /usr/lib/debug/usr/lib/libboost_date_time.so.1.46.1 + std::string module_filename = module_spec.GetFileSpec().GetPath(); + + size_t num_directories = debug_file_search_paths.GetSize(); + for (size_t idx = 0; idx < num_directories; ++idx) + { + FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex (idx); + dirspec.ResolvePath(); + if (!dirspec.Exists() || !dirspec.IsDirectory()) + continue; + + std::vector files; + std::string dirname = dirspec.GetPath(); + + files.push_back (dirname + "/" + symbol_filename); + files.push_back (dirname + "/.debug/" + symbol_filename); + files.push_back (dirname + "/.build-id/" + uuid_str); + files.push_back (dirname + module_filename); + + const uint32_t num_files = files.size(); + for (size_t idx_file = 0; idx_file < num_files; ++idx_file) + { + const std::string &filename = files[idx_file]; + FileSpec file_spec (filename.c_str(), true); + + if (file_spec == module_spec.GetFileSpec()) + continue; + + if (file_spec.Exists()) + { + lldb_private::ModuleSpecList specs; + const size_t num_specs = ObjectFile::GetModuleSpecifications (file_spec, 0, specs); + assert (num_specs <= 1 && "Symbol Vendor supports only a single architecture"); + if (num_specs == 1) + { + ModuleSpec mspec; + if (specs.GetModuleSpecAtIndex (0, mspec)) + { + if (mspec.GetUUID() == module_uuid) + return file_spec; + } + } + } + } + } + + return FileSpec(); +} + +FileSpec +Symbols::FindSymbolFileInBundle (const FileSpec& symfile_bundle, + const lldb_private::UUID *uuid, + const ArchSpec *arch) +{ + // FIXME + return FileSpec(); +} + +bool +Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup) +{ + // Fill in the module_spec.GetFileSpec() for the object file and/or the + // module_spec.GetSymbolFileSpec() for the debug symbols file. + return false; +} + +#elif !defined (__APPLE__) FileSpec Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec) @@ -44,5 +160,4 @@ Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup return false; } - #endif diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 9e1febb7e754..5215b081ee9d 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -262,13 +262,27 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file, if (spec.GetArchitecture().IsValid()) { // We could parse the ABI tag information (in .note, .notes, or .note.ABI-tag) to get the - // machine information. However, we'd have to read a good bit of the rest of the file, - // and this info isn't guaranteed to exist or be correct. More details here: + // machine information. However, this info isn't guaranteed to exist or be correct. Details: // http://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/noteabitag.html // Instead of passing potentially incorrect information down the pipeline, grab // the host information and use it. spec.GetArchitecture().GetTriple().setOSName (Host::GetOSString().GetCString()); spec.GetArchitecture().GetTriple().setVendorName(Host::GetVendorString().GetCString()); + + // Try to get the UUID from the section list. Usually that's at the end, so + // map the file in if we don't have it already. + size_t section_header_end = header.e_shoff + header.e_shnum * header.e_shentsize; + if (section_header_end > data_sp->GetByteSize()) + { + data_sp = file.MemoryMapFileContents (file_offset, section_header_end); + data.SetData(data_sp); + } + + uint32_t gnu_debuglink_crc; + std::string gnu_debuglink_file; + SectionHeaderColl section_headers; + GetSectionHeaderInfo(section_headers, data, header, spec.GetUUID(), gnu_debuglink_file, gnu_debuglink_crc); + specs.Append(spec); } } @@ -306,12 +320,13 @@ ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp, m_header(), m_program_headers(), m_section_headers(), - m_filespec_ap(), - m_shstr_data() + m_filespec_ap() { if (file) m_file = *file; ::memset(&m_header, 0, sizeof(m_header)); + m_gnu_debuglink_crc = 0; + m_gnu_debuglink_file.clear(); } ObjectFileELF::~ObjectFileELF() @@ -359,18 +374,111 @@ ObjectFileELF::ParseHeader() return m_header.Parse(m_data, &offset); } +/* + * crc function from http://svnweb.freebsd.org/base/head/sys/libkern/crc32.c + * + * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or + * code or tables extracted from it, as desired without restriction. + */ +static uint32_t +calc_gnu_debuglink_crc32(const void *buf, size_t size) +{ + static const uint32_t g_crc32_tab[] = + { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d + }; + const uint8_t *p = (const uint8_t *)buf; + uint32_t crc; + + crc = ~0U; + while (size--) + crc = g_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + return crc ^ ~0U; +} + bool ObjectFileELF::GetUUID(lldb_private::UUID* uuid) { + // Need to parse the section list to get the UUIDs, so make sure that's been done. + if (!ParseSectionHeaders()) + return false; + if (m_uuid.IsValid()) { + // We have the full build id uuid. *uuid = m_uuid; return true; } - // FIXME: Return MD5 sum here. See comment in ObjectFile.h. + else + { + m_gnu_debuglink_crc = calc_gnu_debuglink_crc32 (m_data.GetDataStart(), m_data.GetByteSize()); + if (m_gnu_debuglink_crc) + { + // Use 4 bytes of crc from the .gnu_debuglink section. + uint32_t uuidt[4] = { m_gnu_debuglink_crc, 0, 0, 0 }; + uuid->SetBytes (uuidt, sizeof(uuidt)); + return true; + } + } + return false; } +lldb_private::FileSpecList +ObjectFileELF::GetDebugSymbolFilePaths() +{ + FileSpecList file_spec_list; + + if (!m_gnu_debuglink_file.empty()) + { + FileSpec file_spec (m_gnu_debuglink_file.c_str(), false); + file_spec_list.Append (file_spec); + } + return file_spec_list; +} + uint32_t ObjectFileELF::GetDependentModules(FileSpecList &files) { @@ -416,7 +524,7 @@ ObjectFileELF::GetImageInfoAddress() if (!dynsym_id) return Address(); - const ELFSectionHeader *dynsym_hdr = GetSectionHeaderByIndex(dynsym_id); + const ELFSectionHeaderInfo *dynsym_hdr = GetSectionHeaderByIndex(dynsym_id); if (!dynsym_hdr) return Address(); @@ -477,7 +585,7 @@ ObjectFileELF::ParseDependentModules() m_filespec_ap.reset(new FileSpecList()); - if (!(ParseSectionHeaders() && GetSectionHeaderStringTable())) + if (!ParseSectionHeaders()) return 0; // Locate the dynamic table. @@ -574,102 +682,8 @@ ObjectFileELF::ParseProgramHeaders() return m_program_headers.size(); } -//---------------------------------------------------------------------- -// ParseSectionHeaders -//---------------------------------------------------------------------- -size_t -ObjectFileELF::ParseSectionHeaders() -{ - // We have already parsed the section headers - if (!m_section_headers.empty()) - return m_section_headers.size(); - - // If there are no section headers we are done. - if (m_header.e_shnum == 0) - return 0; - - m_section_headers.resize(m_header.e_shnum); - if (m_section_headers.size() != m_header.e_shnum) - return 0; - - const size_t sh_size = m_header.e_shnum * m_header.e_shentsize; - const elf_off sh_offset = m_header.e_shoff; - DataExtractor data; - if (GetData (sh_offset, sh_size, data) != sh_size) - return 0; - - uint32_t idx; - lldb::offset_t offset; - for (idx = 0, offset = 0; idx < m_header.e_shnum; ++idx) - { - if (m_section_headers[idx].Parse(data, &offset) == false) - break; - } - if (idx < m_section_headers.size()) - m_section_headers.resize(idx); - - return m_section_headers.size(); -} - -size_t -ObjectFileELF::GetSectionHeaderStringTable() -{ - if (m_shstr_data.GetByteSize() == 0) - { - const unsigned strtab_idx = m_header.e_shstrndx; - - if (strtab_idx && strtab_idx < m_section_headers.size()) - { - const ELFSectionHeader &sheader = m_section_headers[strtab_idx]; - const size_t byte_size = sheader.sh_size; - const Elf64_Off offset = sheader.sh_offset; - m_shstr_data.SetData (m_data, offset, byte_size); - - if (m_shstr_data.GetByteSize() != byte_size) - return 0; - } - } - return m_shstr_data.GetByteSize(); -} - -lldb::user_id_t -ObjectFileELF::GetSectionIndexByName(const char *name) -{ - if (!(ParseSectionHeaders() && GetSectionHeaderStringTable())) - return 0; - - // Search the collection of section headers for one with a matching name. - for (SectionHeaderCollIter I = m_section_headers.begin(); - I != m_section_headers.end(); ++I) - { - const char *sectionName = m_shstr_data.PeekCStr(I->sh_name); - - if (!sectionName) - return 0; - - if (strcmp(name, sectionName) != 0) - continue; - - return SectionIndex(I); - } - - return 0; -} - -const elf::ELFSectionHeader * -ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id) -{ - if (!ParseSectionHeaders() || !id) - return NULL; - - if (--id < m_section_headers.size()) - return &m_section_headers[id]; - - return NULL; -} - static bool -ParseNoteGNUBuildID(DataExtractor& data, lldb_private::UUID& uuid) +ParseNoteGNUBuildID(DataExtractor &data, lldb_private::UUID &uuid) { // Try to parse the note section (ie .note.gnu.build-id|.notes|.note|...) and get the build id. // BuildID documentation: https://fedoraproject.org/wiki/Releases/FeatureBuildId @@ -712,23 +726,158 @@ ParseNoteGNUBuildID(DataExtractor& data, lldb_private::UUID& uuid) } return false; } - + +//---------------------------------------------------------------------- +// GetSectionHeaderInfo +//---------------------------------------------------------------------- +size_t +ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, + lldb_private::DataExtractor &object_data, + const elf::ELFHeader &header, + lldb_private::UUID &uuid, + std::string &gnu_debuglink_file, + uint32_t &gnu_debuglink_crc) +{ + // We have already parsed the section headers + if (!section_headers.empty()) + return section_headers.size(); + + // If there are no section headers we are done. + if (header.e_shnum == 0) + return 0; + + section_headers.resize(header.e_shnum); + if (section_headers.size() != header.e_shnum) + return 0; + + const size_t sh_size = header.e_shnum * header.e_shentsize; + const elf_off sh_offset = header.e_shoff; + DataExtractor sh_data; + if (sh_data.SetData (object_data, sh_offset, sh_size) != sh_size) + return 0; + + uint32_t idx; + lldb::offset_t offset; + for (idx = 0, offset = 0; idx < header.e_shnum; ++idx) + { + if (section_headers[idx].Parse(sh_data, &offset) == false) + break; + } + if (idx < section_headers.size()) + section_headers.resize(idx); + + const unsigned strtab_idx = header.e_shstrndx; + if (strtab_idx && strtab_idx < section_headers.size()) + { + const ELFSectionHeaderInfo &sheader = section_headers[strtab_idx]; + const size_t byte_size = sheader.sh_size; + const Elf64_Off offset = sheader.sh_offset; + lldb_private::DataExtractor shstr_data; + + if (shstr_data.SetData (object_data, offset, byte_size) == byte_size) + { + for (SectionHeaderCollIter I = section_headers.begin(); + I != section_headers.end(); ++I) + { + static ConstString g_sect_name_gnu_debuglink (".gnu_debuglink"); + const ELFSectionHeaderInfo &header = *I; + const uint64_t section_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size; + ConstString name(shstr_data.PeekCStr(I->sh_name)); + + I->section_name = name; + + if (name == g_sect_name_gnu_debuglink) + { + DataExtractor data; + if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size)) + { + lldb::offset_t gnu_debuglink_offset = 0; + gnu_debuglink_file = data.GetCStr (&gnu_debuglink_offset); + gnu_debuglink_offset = llvm::RoundUpToAlignment (gnu_debuglink_offset, 4); + data.GetU32 (&gnu_debuglink_offset, &gnu_debuglink_crc, 1); + } + } + + if (header.sh_type == SHT_NOTE && !uuid.IsValid()) + { + DataExtractor data; + if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size)) + { + ParseNoteGNUBuildID (data, uuid); + } + } + } + + return section_headers.size(); + } + } + + section_headers.clear(); + return 0; +} + +//---------------------------------------------------------------------- +// ParseSectionHeaders +//---------------------------------------------------------------------- +size_t +ObjectFileELF::ParseSectionHeaders() +{ + return GetSectionHeaderInfo(m_section_headers, m_data, m_header, m_uuid, m_gnu_debuglink_file, m_gnu_debuglink_crc); +} + +lldb::user_id_t +ObjectFileELF::GetSectionIndexByName(const char *name) +{ + if (!ParseSectionHeaders()) + return 0; + + // Search the collection of section headers for one with a matching name. + for (SectionHeaderCollIter I = m_section_headers.begin(); + I != m_section_headers.end(); ++I) + { + const char *sectionName = I->section_name.AsCString(); + + if (!sectionName) + return 0; + + if (strcmp(name, sectionName) != 0) + continue; + + return SectionIndex(I); + } + + return 0; +} + +const ObjectFileELF::ELFSectionHeaderInfo * +ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id) +{ + if (!ParseSectionHeaders() || !id) + return NULL; + + if (--id < m_section_headers.size()) + return &m_section_headers[id]; + + return NULL; +} + + SectionList * ObjectFileELF::GetSectionList() { if (m_sections_ap.get()) return m_sections_ap.get(); - if (ParseSectionHeaders() && GetSectionHeaderStringTable()) + if (ParseSectionHeaders()) { m_sections_ap.reset(new SectionList()); for (SectionHeaderCollIter I = m_section_headers.begin(); I != m_section_headers.end(); ++I) { - const ELFSectionHeader &header = *I; + const ELFSectionHeaderInfo &header = *I; - ConstString name(m_shstr_data.PeekCStr(header.sh_name)); + ConstString& name = I->section_name; const uint64_t file_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size; const uint64_t vm_size = header.sh_flags & SHF_ALLOC ? header.sh_size : 0; @@ -753,7 +902,7 @@ ObjectFileELF::GetSectionList() SectionType sect_type = eSectionTypeOther; bool is_thread_specific = false; - + if (name == g_sect_name_text) sect_type = eSectionTypeCode; else if (name == g_sect_name_data) sect_type = eSectionTypeData; else if (name == g_sect_name_bss) sect_type = eSectionTypeZeroFill; @@ -767,6 +916,19 @@ ObjectFileELF::GetSectionList() sect_type = eSectionTypeZeroFill; is_thread_specific = true; } + // .debug_abbrev – Abbreviations used in the .debug_info section + // .debug_aranges – Lookup table for mapping addresses to compilation units + // .debug_frame – Call frame information + // .debug_info – The core DWARF information section + // .debug_line – Line number information + // .debug_loc – Location lists used in DW_AT_location attributes + // .debug_macinfo – Macro information + // .debug_pubnames – Lookup table for mapping object and function names to compilation units + // .debug_pubtypes – Lookup table for mapping type names to compilation units + // .debug_ranges – Address ranges used in DW_AT_ranges attributes + // .debug_str – String table used in .debug_info + // MISSING? .debug-index http://src.chromium.org/viewvc/chrome/trunk/src/build/gdb-add-index?pathrev=144644 + // MISSING? .debug_types - Type descriptions from DWARF 4? See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo else if (name == g_sect_name_dwarf_debug_abbrev) sect_type = eSectionTypeDWARFDebugAbbrev; else if (name == g_sect_name_dwarf_debug_aranges) sect_type = eSectionTypeDWARFDebugAranges; else if (name == g_sect_name_dwarf_debug_frame) sect_type = eSectionTypeDWARFDebugFrame; @@ -779,20 +941,31 @@ ObjectFileELF::GetSectionList() else if (name == g_sect_name_dwarf_debug_ranges) sect_type = eSectionTypeDWARFDebugRanges; else if (name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr; else if (name == g_sect_name_eh_frame) sect_type = eSectionTypeEHFrame; - else if (header.sh_type == SHT_NOTE) + + switch (header.sh_type) { - if (!m_uuid.IsValid()) - { - DataExtractor data; - if (vm_size && (GetData (header.sh_offset, vm_size, data) == vm_size)) - { - ParseNoteGNUBuildID (data, m_uuid); - } - } + case SHT_SYMTAB: + assert (sect_type == eSectionTypeOther); + sect_type = eSectionTypeELFSymbolTable; + break; + case SHT_DYNSYM: + assert (sect_type == eSectionTypeOther); + sect_type = eSectionTypeELFDynamicSymbols; + break; + case SHT_RELA: + case SHT_REL: + assert (sect_type == eSectionTypeOther); + sect_type = eSectionTypeELFRelocationEntries; + break; + case SHT_DYNAMIC: + assert (sect_type == eSectionTypeOther); + sect_type = eSectionTypeELFDynamicLinkInfo; + break; } - + SectionSP section_sp(new Section( GetModule(), // Module to which this section belongs. + this, // ObjectFile to which this section belongs and should read section data from. SectionIndex(I), // Section ID. name, // Section name. sect_type, // Section type. @@ -806,18 +979,18 @@ ObjectFileELF::GetSectionList() section_sp->SetIsThreadSpecific (is_thread_specific); m_sections_ap->AddSection(section_sp); } - + m_sections_ap->Finalize(); // Now that we're done adding sections, finalize to build fast-lookup caches } return m_sections_ap.get(); } -static unsigned -ParseSymbols(Symtab *symtab, +unsigned +ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id, SectionList *section_list, - const ELFSectionHeader *symtab_shdr, + const ELFSectionHeaderInfo *symtab_shdr, const DataExtractor &symtab_data, const DataExtractor &strtab_data) { @@ -936,6 +1109,29 @@ ParseSymbols(Symtab *symtab, } } + // If the symbol section we've found has no data (SHT_NOBITS), then check the module + // for the main object file and use the section there if it has data. This can happen + // if we're parsing the debug file and the it has no .text section, for example. + if (symbol_section_sp && (symbol_section_sp->GetFileSize() == 0)) + { + ModuleSP module_sp(GetModule()); + if (module_sp) + { + ObjectFile *obj_file = module_sp->GetObjectFile(); + // Check if we've got a different object file than ourselves. + if (obj_file && (obj_file != this)) + { + const ConstString §_name = symbol_section_sp->GetName(); + SectionList *obj_file_section_list = obj_file->GetSectionList(); + lldb::SectionSP section_sp (obj_file_section_list->FindSectionByName (sect_name)); + if (section_sp && section_sp->GetFileSize()) + { + symbol_section_sp = section_sp; + } + } + } + } + uint64_t symbol_value = symbol.st_value; if (symbol_section_sp) symbol_value -= symbol_section_sp->GetFileAddress(); @@ -963,18 +1159,17 @@ ParseSymbols(Symtab *symtab, } unsigned -ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id, - const ELFSectionHeader *symtab_hdr, - user_id_t symtab_id) +ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id, user_id_t symtab_id) { - assert(symtab_hdr->sh_type == SHT_SYMTAB || - symtab_hdr->sh_type == SHT_DYNSYM); - // Parse in the section list if needed. SectionList *section_list = GetSectionList(); if (!section_list) return 0; + const ELFSectionHeaderInfo *symtab_hdr = &m_section_headers[symtab_id - 1]; + assert(symtab_hdr->sh_type == SHT_SYMTAB || + symtab_hdr->sh_type == SHT_DYNSYM); + // Section ID's are ones based. user_id_t strtab_id = symtab_hdr->sh_link + 1; @@ -1040,10 +1235,6 @@ ObjectFileELF::FindDynamicSymbol(unsigned tag) if (!ParseDynamicSymbols()) return NULL; - SectionList *section_list = GetSectionList(); - if (!section_list) - return 0; - DynamicSymbolCollIter I = m_dynamic_symbols.begin(); DynamicSymbolCollIter E = m_dynamic_symbols.end(); for ( ; I != E; ++I) @@ -1057,21 +1248,6 @@ ObjectFileELF::FindDynamicSymbol(unsigned tag) return NULL; } -Section * -ObjectFileELF::PLTSection() -{ - const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL); - SectionList *section_list = GetSectionList(); - - if (symbol && section_list) - { - addr_t addr = symbol->d_ptr; - return section_list->FindSectionContainingFileAddress(addr).get(); - } - - return NULL; -} - unsigned ObjectFileELF::PLTRelocationType() { @@ -1160,12 +1336,12 @@ ParsePLTRelocations(Symtab *symbol_table, unsigned ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id, - const ELFSectionHeader *rel_hdr, + const ELFSectionHeaderInfo *rel_hdr, user_id_t rel_id) { assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL); - // The link field points to the asscoiated symbol table. The info field + // The link field points to the associated symbol table. The info field // points to the section holding the plt. user_id_t symtab_id = rel_hdr->sh_link; user_id_t plt_id = rel_hdr->sh_info; @@ -1177,11 +1353,11 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, symtab_id++; plt_id++; - const ELFSectionHeader *plt_hdr = GetSectionHeaderByIndex(plt_id); + const ELFSectionHeaderInfo *plt_hdr = GetSectionHeaderByIndex(plt_id); if (!plt_hdr) return 0; - const ELFSectionHeader *sym_hdr = GetSectionHeaderByIndex(symtab_id); + const ELFSectionHeaderInfo *sym_hdr = GetSectionHeaderByIndex(symtab_id); if (!sym_hdr) return 0; @@ -1235,45 +1411,82 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, } Symtab * -ObjectFileELF::GetSymtab() +ObjectFileELF::GetSymtab(uint32_t flags) { - if (m_symtab_ap.get()) - return m_symtab_ap.get(); - - Symtab *symbol_table = new Symtab(this); - m_symtab_ap.reset(symbol_table); - - Mutex::Locker locker(symbol_table->GetMutex()); - - if (!(ParseSectionHeaders() && GetSectionHeaderStringTable())) - return symbol_table; - - // Locate and parse all linker symbol tables. - uint64_t symbol_id = 0; - for (SectionHeaderCollIter I = m_section_headers.begin(); - I != m_section_headers.end(); ++I) + ModuleSP module_sp(GetModule()); + if (module_sp) { - if (I->sh_type == SHT_SYMTAB || I->sh_type == SHT_DYNSYM) + lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + + bool from_unified_section_list = !!(flags & eSymtabFromUnifiedSectionList); + SectionList *section_list = from_unified_section_list ? module_sp->GetUnifiedSectionList() : GetSectionList(); + if (!section_list) + return NULL; + + // If we're doing the unified section list and it has been modified, then clear our + // cache and reload the symbols. If needed, we could check on only the sections that + // we use to create the symbol table... + std::unique_ptr &symtab_ap = from_unified_section_list ? m_symtab_unified_ap : m_symtab_ap; + if (from_unified_section_list && (m_symtab_unified_revisionid != section_list->GetRevisionID())) { - const ELFSectionHeader &symtab_header = *I; - user_id_t section_id = SectionIndex(I); - symbol_id += ParseSymbolTable(symbol_table, symbol_id, - &symtab_header, section_id); + symtab_ap.reset(); + m_symtab_unified_revisionid = section_list->GetRevisionID(); + } + else if (symtab_ap.get()) + { + return symtab_ap.get(); } - } - - // Synthesize trampoline symbols to help navigate the PLT. - Section *reloc_section = PLTSection(); - if (reloc_section) - { - user_id_t reloc_id = reloc_section->GetID(); - const ELFSectionHeader *reloc_header = GetSectionHeaderByIndex(reloc_id); - assert(reloc_header); - ParseTrampolineSymbols(symbol_table, symbol_id, reloc_header, reloc_id); - } + Symtab *symbol_table = new Symtab(this); + symtab_ap.reset(symbol_table); - return symbol_table; + // Sharable objects and dynamic executables usually have 2 distinct symbol + // tables, one named ".symtab", and the other ".dynsym". The dynsym is a smaller + // version of the symtab that only contains global symbols. The information found + // in the dynsym is therefore also found in the symtab, while the reverse is not + // necessarily true. + Section *section_sym = section_list->FindSectionByType (eSectionTypeELFSymbolTable, true).get(); + if (!section_sym) + { + // The symtab section is non-allocable and can be stripped, so if it doesn't exist + // then use the dynsym section which should always be there. + section_sym = section_list->FindSectionByType (eSectionTypeELFDynamicSymbols, true).get(); + } + + uint64_t symbol_id = 0; + if (section_sym) + { + user_id_t section_id = section_sym->GetID(); + ObjectFileELF *obj_file_elf = static_cast(section_sym->GetObjectFile()); + + symbol_id += obj_file_elf->ParseSymbolTable (symbol_table, symbol_id, section_id); + } + + Section *section = section_list->FindSectionByType (eSectionTypeELFDynamicLinkInfo, true).get(); + if (section) + { + ObjectFileELF *obj_file_elf = static_cast(section->GetObjectFile()); + + // Synthesize trampoline symbols to help navigate the PLT. + const ELFDynamic *symbol = obj_file_elf->FindDynamicSymbol(DT_JMPREL); + if (symbol) + { + addr_t addr = symbol->d_ptr; + Section *reloc_section = section_list->FindSectionContainingFileAddress(addr).get(); + if (reloc_section) + { + user_id_t reloc_id = reloc_section->GetID(); + const ELFSectionHeaderInfo *reloc_header = obj_file_elf->GetSectionHeaderByIndex(reloc_id); + assert(reloc_header); + + obj_file_elf->ParseTrampolineSymbols(symbol_table, symbol_id, reloc_header, reloc_id); + } + } + } + + return symbol_table; + } + return NULL; } //===----------------------------------------------------------------------===// @@ -1472,7 +1685,7 @@ ObjectFileELF::DumpELFProgramHeaders(Stream *s) // Dump a single ELF section header to the specified output stream //---------------------------------------------------------------------- void -ObjectFileELF::DumpELFSectionHeader(Stream *s, const ELFSectionHeader &sh) +ObjectFileELF::DumpELFSectionHeader(Stream *s, const ELFSectionHeaderInfo &sh) { s->Printf("%8.8x ", sh.sh_name); DumpELFSectionHeader_sh_type(s, sh.sh_type); @@ -1540,7 +1753,7 @@ ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s, elf_xword sh_flags) void ObjectFileELF::DumpELFSectionHeaders(Stream *s) { - if (!(ParseSectionHeaders() && GetSectionHeaderStringTable())) + if (!ParseSectionHeaders()) return; s->PutCString("Section Headers\n"); @@ -1557,7 +1770,7 @@ ObjectFileELF::DumpELFSectionHeaders(Stream *s) { s->Printf("[%2u] ", idx); ObjectFileELF::DumpELFSectionHeader(s, *I); - const char* section_name = m_shstr_data.PeekCStr(I->sh_name); + const char* section_name = I->section_name.AsCString(""); if (section_name) *s << ' ' << section_name << "\n"; } diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index f1fea3c666d6..a6e3cbb3fd99 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -100,7 +100,7 @@ public: GetAddressByteSize() const; virtual lldb_private::Symtab * - GetSymtab(); + GetSymtab(uint32_t flags = 0); virtual lldb_private::SectionList * GetSectionList(); @@ -114,6 +114,9 @@ public: virtual bool GetUUID(lldb_private::UUID* uuid); + virtual lldb_private::FileSpecList + GetDebugSymbolFilePaths(); + virtual uint32_t GetDependentModules(lldb_private::FileSpecList& files); @@ -141,7 +144,11 @@ private: typedef ProgramHeaderColl::iterator ProgramHeaderCollIter; typedef ProgramHeaderColl::const_iterator ProgramHeaderCollConstIter; - typedef std::vector SectionHeaderColl; + struct ELFSectionHeaderInfo : public elf::ELFSectionHeader + { + lldb_private::ConstString section_name; + }; + typedef std::vector SectionHeaderColl; typedef SectionHeaderColl::iterator SectionHeaderCollIter; typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter; @@ -155,9 +162,13 @@ private: /// ELF file header. elf::ELFHeader m_header; - /// ELF build ID + /// ELF build ID. lldb_private::UUID m_uuid; + /// ELF .gnu_debuglink file and crc data if available. + std::string m_gnu_debuglink_file; + uint32_t m_gnu_debuglink_crc; + /// Collection of program headers. ProgramHeaderColl m_program_headers; @@ -171,9 +182,6 @@ private: /// libraries) on which this object file depends. mutable std::unique_ptr m_filespec_ap; - /// Data extractor holding the string table used to resolve section names. - lldb_private::DataExtractor m_shstr_data; - /// Cached value of the entry point for this module. lldb_private::Address m_entry_point_address; @@ -197,6 +205,15 @@ private: size_t ParseSectionHeaders(); + /// Parses the elf section headers and returns the uuid, debug link name, crc. + static size_t + GetSectionHeaderInfo(SectionHeaderColl §ion_headers, + lldb_private::DataExtractor &data, + const elf::ELFHeader &header, + lldb_private::UUID &uuid, + std::string &gnu_debuglink_file, + uint32_t &gnu_debuglink_crc); + /// Scans the dynamic section and locates all dependent modules (shared /// libraries) populating m_filespec_ap. This method will compute the /// dependent module list only once. Returns the number of dependent @@ -215,23 +232,26 @@ private: unsigned ParseSymbolTable(lldb_private::Symtab *symbol_table, lldb::user_id_t start_id, - const elf::ELFSectionHeader *symtab_section, lldb::user_id_t symtab_id); + /// Helper routine for ParseSymbolTable(). + unsigned + ParseSymbols(lldb_private::Symtab *symbol_table, + lldb::user_id_t start_id, + lldb_private::SectionList *section_list, + const ELFSectionHeaderInfo *symtab_shdr, + const lldb_private::DataExtractor &symtab_data, + const lldb_private::DataExtractor &strtab_data); + /// Scans the relocation entries and adds a set of artificial symbols to the /// given symbol table for each PLT slot. Returns the number of symbols /// added. unsigned ParseTrampolineSymbols(lldb_private::Symtab *symbol_table, lldb::user_id_t start_id, - const elf::ELFSectionHeader *rela_hdr, + const ELFSectionHeaderInfo *rela_hdr, lldb::user_id_t section_id); - /// Loads the section name string table into m_shstr_data. Returns the - /// number of bytes constituting the table. - size_t - GetSectionHeaderStringTable(); - /// Utility method for looking up a section given its name. Returns the /// index of the corresponding section or zero if no section with the given /// name can be found (note that section indices are always 1 based, and so @@ -244,7 +264,7 @@ private: GetSectionIndexByType(unsigned type); /// Returns the section header with the given id or NULL. - const elf::ELFSectionHeader * + const ELFSectionHeaderInfo * GetSectionHeaderByIndex(lldb::user_id_t id); /// @name ELF header dump routines @@ -284,7 +304,7 @@ private: static void DumpELFSectionHeader(lldb_private::Stream *s, - const elf::ELFSectionHeader& sh); + const ELFSectionHeaderInfo& sh); static void DumpELFSectionHeader_sh_type(lldb_private::Stream *s, @@ -302,9 +322,6 @@ private: const elf::ELFDynamic * FindDynamicSymbol(unsigned tag); - lldb_private::Section * - PLTSection(); - unsigned PLTRelocationType(); }; diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 9f27c1c5107b..c59da7b16a17 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -838,6 +838,10 @@ ObjectFileMachO::GetAddressClass (lldb::addr_t file_addr) case eSectionTypeDWARFAppleObjC: return eAddressClassDebug; case eSectionTypeEHFrame: return eAddressClassRuntime; + case eSectionTypeELFSymbolTable: + case eSectionTypeELFDynamicSymbols: + case eSectionTypeELFRelocationEntries: + case eSectionTypeELFDynamicLinkInfo: case eSectionTypeOther: return eAddressClassUnknown; } } @@ -891,7 +895,7 @@ ObjectFileMachO::GetAddressClass (lldb::addr_t file_addr) } Symtab * -ObjectFileMachO::GetSymtab() +ObjectFileMachO::GetSymtab(uint32_t flags) { ModuleSP module_sp(GetModule()); if (module_sp) @@ -1033,6 +1037,7 @@ ObjectFileMachO::ParseSections () if (segment_name || is_core) { segment_sp.reset(new Section (module_sp, // Module to which this section belongs + this, // Object file to which this sections belongs ++segID << 8, // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible segment_name, // Name of this section eSectionTypeContainer, // This section is a container of other sections. @@ -1129,7 +1134,8 @@ ObjectFileMachO::ParseSections () { // Create a fake section for the section's named segment segment_sp.reset(new Section (segment_sp, // Parent section - module_sp, // Module to which this section belongs + module_sp, // Module to which this section belongs + this, // Object file to which this section belongs ++segID << 8, // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible segment_name, // Name of this section eSectionTypeContainer, // This section is a container of other sections. @@ -1258,6 +1264,7 @@ ObjectFileMachO::ParseSections () SectionSP section_sp(new Section (segment_sp, module_sp, + this, ++sectID, section_name, sect_type, diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h index 349928e9538d..65874533ed36 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -102,7 +102,7 @@ public: GetAddressClass (lldb::addr_t file_addr); virtual lldb_private::Symtab * - GetSymtab(); + GetSymtab(uint32_t flags = 0); virtual lldb_private::SectionList * GetSectionList(); diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index 4da254ca9a07..ec1aef784c2b 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -511,7 +511,7 @@ ObjectFilePECOFF::GetSectionName(std::string& sect_name, const section_header_t& // GetNListSymtab //---------------------------------------------------------------------- Symtab * -ObjectFilePECOFF::GetSymtab() +ObjectFilePECOFF::GetSymtab(uint32_t flags) { ModuleSP module_sp(GetModule()); if (module_sp) @@ -698,9 +698,10 @@ ObjectFilePECOFF::GetSectionList() // Use a segment ID of the segment index shifted left by 8 so they // never conflict with any of the sections. SectionSP section_sp (new Section (module_sp, // Module to which this section belongs + this, // Object file to which this section belongs idx + 1, // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible const_sect_name, // Name of this section - section_type, // This section is a container of other sections. + section_type, // This section is a container of other sections. m_coff_header_opt.image_base + m_sect_headers[idx].vmaddr, // File VM address == addresses as they are found in the object file m_sect_headers[idx].vmsize, // VM size in bytes of this section m_sect_headers[idx].offset, // Offset to the data for this section in the file diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h index d980006eab6e..c12c7b9c5e26 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h @@ -86,7 +86,7 @@ public: // GetAddressClass (lldb::addr_t file_addr); // virtual lldb_private::Symtab * - GetSymtab(); + GetSymtab(uint32_t flags = 0); virtual lldb_private::SectionList * GetSectionList(); diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp index 1f33013f4da3..824d797cd79a 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp +++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp @@ -81,7 +81,7 @@ ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener) // FIXME: Putting this code in the ctor and saving the byte order in a // member variable is a hack to avoid const qual issues in GetByteOrder. lldb::ModuleSP module = GetTarget().GetExecutableModule(); - if (module != NULL && module->GetObjectFile() != NULL) + if (module && module->GetObjectFile()) m_byte_order = module->GetObjectFile()->GetByteOrder(); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index f0a94c2ceaa8..b860a5927040 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -543,7 +543,7 @@ SymbolFileDWARF::InitializeObject() ModuleSP module_sp (m_obj_file->GetModule()); if (module_sp) { - const SectionList *section_list = m_obj_file->GetSectionList(); + const SectionList *section_list = module_sp->GetUnifiedSectionList(); const Section* section = section_list->FindSectionByName(GetDWARFMachOSegmentName ()).get(); @@ -704,8 +704,9 @@ SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type, { if (m_flags.IsClear (got_flag)) { + ModuleSP module_sp (m_obj_file->GetModule()); m_flags.Set (got_flag); - const SectionList *section_list = m_obj_file->GetSectionList(); + const SectionList *section_list = module_sp->GetUnifiedSectionList(); if (section_list) { SectionSP section_sp (section_list->FindSectionByType(sect_type, true)); @@ -1054,7 +1055,8 @@ SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompile lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd (0); if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr) { - func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, m_obj_file->GetSectionList()); + ModuleSP module_sp (m_obj_file->GetModule()); + func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, module_sp->GetUnifiedSectionList()); if (func_range.GetBaseAddress().IsValid()) func_range.SetByteSize(highest_func_addr - lowest_func_addr); } @@ -4721,7 +4723,7 @@ SymbolFileDWARF::GetObjCClassSymbol (const ConstString &objc_class_name) Symbol *objc_class_symbol = NULL; if (m_obj_file) { - Symtab *symtab = m_obj_file->GetSymtab(); + Symtab *symtab = m_obj_file->GetSymtab (ObjectFile::eSymtabFromUnifiedSectionList); if (symtab) { objc_class_symbol = symtab->FindFirstSymbolWithNameAndType (objc_class_name, @@ -7429,13 +7431,12 @@ SymbolFileDWARF::ParseVariableDIE bool linked_oso_file_addr = false; if (is_external && location_DW_OP_addr == 0) { - // 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) { - Symtab *debug_map_symtab = debug_map_objfile->GetSymtab(); + Symtab *debug_map_symtab = debug_map_objfile->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList); if (debug_map_symtab) { Symbol *exe_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index fbfbf5cdd3fb..4b18d5860936 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -75,9 +75,9 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa { for (auto comp_unit_info : cu_infos) { - Symtab *exe_symtab = exe_symfile->GetObjectFile()->GetSymtab(); + Symtab *exe_symtab = exe_symfile->GetObjectFile()->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList); ModuleSP oso_module_sp (oso_objfile->GetModule()); - Symtab *oso_symtab = oso_objfile->GetSymtab(); + Symtab *oso_symtab = oso_objfile->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList); ///const uint32_t fun_resolve_flags = SymbolContext::Module | eSymbolContextCompUnit | eSymbolContextFunction; //SectionList *oso_sections = oso_objfile->Sections(); @@ -169,7 +169,7 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa exe_symfile->FinalizeOSOFileRanges (this); // We don't need the symbols anymore for the .o files - oso_objfile->ClearSymtab(); + oso_objfile->ClearSymtab(ObjectFile::eSymtabFromUnifiedSectionList); } } return file_range_map; @@ -330,7 +330,7 @@ SymbolFileDWARFDebugMap::InitOSO() // these files exist and also contain valid DWARF. If we get any of that // then we return the abilities of the first N_OSO's DWARF. - Symtab* symtab = m_obj_file->GetSymtab(); + Symtab* symtab = m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList); if (symtab) { Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); @@ -777,7 +777,7 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext (const Address& exe_so_addr, uint32_t resolve_scope, SymbolContext& sc) { uint32_t resolved_flags = 0; - Symtab* symtab = m_obj_file->GetSymtab(); + Symtab* symtab = m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList); if (symtab) { const addr_t exe_file_addr = exe_so_addr.GetFileAddress(); diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index 28078693b350..f0bd08569b94 100644 --- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -93,7 +93,7 @@ SymbolFileSymtab::CalculateAbilities () uint32_t abilities = 0; if (m_obj_file) { - const Symtab *symtab = m_obj_file->GetSymtab(); + const Symtab *symtab = m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList); if (symtab) { //---------------------------------------------------------------------- @@ -159,7 +159,7 @@ SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) // the entire object file if (idx < m_source_indexes.size()) { - const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]); + const Symbol *cu_symbol = m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList)->SymbolAtIndex(m_source_indexes[idx]); if (cu_symbol) cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetMangled().GetName().AsCString(), 0, eLanguageTypeUnknown)); } @@ -179,7 +179,7 @@ SymbolFileSymtab::ParseCompileUnitFunctions (const SymbolContext &sc) size_t num_added = 0; // We must at least have a valid compile unit assert (sc.comp_unit != NULL); - const Symtab *symtab = m_obj_file->GetSymtab(); + const Symtab *symtab = m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList); const Symbol *curr_symbol = NULL; const Symbol *next_symbol = NULL; // const char *prefix = m_obj_file->SymbolPrefix(); @@ -307,13 +307,13 @@ SymbolFileSymtab::FindNamespace (const SymbolContext& sc, const ConstString &nam uint32_t SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) { - if (m_obj_file->GetSymtab() == NULL) + if (m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList) == NULL) return 0; uint32_t resolved_flags = 0; if (resolve_scope & eSymbolContextSymbol) { - sc.symbol = m_obj_file->GetSymtab()->FindSymbolContainingFileAddress(so_addr.GetFileAddress()); + sc.symbol = m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList)->FindSymbolContainingFileAddress(so_addr.GetFileAddress()); if (sc.symbol) resolved_flags |= eSymbolContextSymbol; } diff --git a/lldb/source/Plugins/SymbolVendor/CMakeLists.txt b/lldb/source/Plugins/SymbolVendor/CMakeLists.txt index 5bd3ac342eac..9f5c6311b22d 100644 --- a/lldb/source/Plugins/SymbolVendor/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolVendor/CMakeLists.txt @@ -1,3 +1,5 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") add_subdirectory(MacOSX) endif() + +add_subdirectory(ELF) diff --git a/lldb/source/Plugins/SymbolVendor/ELF/CMakeLists.txt b/lldb/source/Plugins/SymbolVendor/ELF/CMakeLists.txt new file mode 100644 index 000000000000..2401b76a3428 --- /dev/null +++ b/lldb/source/Plugins/SymbolVendor/ELF/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginSymbolVendorELF + SymbolVendorELF.cpp + ) diff --git a/lldb/source/Plugins/SymbolVendor/ELF/Makefile b/lldb/source/Plugins/SymbolVendor/ELF/Makefile new file mode 100644 index 000000000000..47c24a2bda34 --- /dev/null +++ b/lldb/source/Plugins/SymbolVendor/ELF/Makefile @@ -0,0 +1,14 @@ +##===- source/Plugins/SymbolVendor/ELF/Makefile ---------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLDB_LEVEL := ../../../.. +LIBRARYNAME := lldbPluginSymbolVendorELF +BUILD_ARCHIVE = 1 + +include $(LLDB_LEVEL)/Makefile diff --git a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp new file mode 100644 index 000000000000..2dd2cea6ca9a --- /dev/null +++ b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp @@ -0,0 +1,200 @@ +//===-- SymbolVendorELF.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SymbolVendorELF.h" + +//#include +// #include +#include + +// #include + +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/Timer.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/Symbols.h" +#include "lldb/Symbol/ObjectFile.h" + +using namespace lldb; +using namespace lldb_private; + +//---------------------------------------------------------------------- +// SymbolVendorELF constructor +//---------------------------------------------------------------------- +SymbolVendorELF::SymbolVendorELF(const lldb::ModuleSP &module_sp) : + SymbolVendor (module_sp) +{ +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +SymbolVendorELF::~SymbolVendorELF() +{ +} + +void +SymbolVendorELF::Initialize() +{ + PluginManager::RegisterPlugin (GetPluginNameStatic(), + GetPluginDescriptionStatic(), + CreateInstance); +} + +void +SymbolVendorELF::Terminate() +{ + PluginManager::UnregisterPlugin (CreateInstance); +} + + +lldb_private::ConstString +SymbolVendorELF::GetPluginNameStatic() +{ + static ConstString g_name("ELF"); + return g_name; +} + +const char * +SymbolVendorELF::GetPluginDescriptionStatic() +{ + return "Symbol vendor for ELF that looks for dSYM files that match executables."; +} + + + +//---------------------------------------------------------------------- +// CreateInstance +// +// Platforms can register a callback to use when creating symbol +// vendors to allow for complex debug information file setups, and to +// also allow for finding separate debug information files. +//---------------------------------------------------------------------- +SymbolVendor* +SymbolVendorELF::CreateInstance (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm) +{ + if (!module_sp) + return NULL; + + ObjectFile *obj_file = module_sp->GetObjectFile(); + if (!obj_file) + return NULL; + + static ConstString obj_file_elf("elf"); + ConstString obj_name = obj_file->GetPluginName(); + if (obj_name != obj_file_elf) + return NULL; + + lldb_private::UUID uuid; + if (!obj_file->GetUUID (&uuid)) + return NULL; + + // Get the .gnu_debuglink file (if specified). + FileSpecList file_spec_list = obj_file->GetDebugSymbolFilePaths(); + + // If the module specified a filespec, use it first. + FileSpec debug_symbol_fspec (module_sp->GetSymbolFileFileSpec()); + if (debug_symbol_fspec) + file_spec_list.Insert (0, debug_symbol_fspec); + + // If we have no debug symbol files, then nothing to do. + if (file_spec_list.IsEmpty()) + return NULL; + + Timer scoped_timer (__PRETTY_FUNCTION__, + "SymbolVendorELF::CreateInstance (module = %s)", + module_sp->GetFileSpec().GetPath().c_str()); + + for (size_t idx = 0; idx < file_spec_list.GetSize(); ++idx) + { + ModuleSpec module_spec; + const FileSpec fspec = file_spec_list.GetFileSpecAtIndex (idx); + + module_spec.GetFileSpec() = obj_file->GetFileSpec(); + module_spec.GetFileSpec().ResolvePath(); + module_spec.GetSymbolFileSpec() = fspec; + module_spec.GetUUID() = uuid; + FileSpec dsym_fspec = Symbols::LocateExecutableSymbolFile (module_spec); + if (dsym_fspec) + { + DataBufferSP dsym_file_data_sp; + lldb::offset_t dsym_file_data_offset = 0; + ObjectFileSP dsym_objfile_sp = ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(), dsym_file_data_sp, dsym_file_data_offset); + if (dsym_objfile_sp) + { + // This objfile is for debugging purposes. Sadly, ObjectFileELF won't be able + // to figure this out consistently as the symbol file may not have stripped the + // code sections, etc. + dsym_objfile_sp->SetType (ObjectFile::eTypeDebugInfo); + + SymbolVendorELF* symbol_vendor = new SymbolVendorELF(module_sp); + if (symbol_vendor) + { + // Get the module unified section list and add our debug sections to that. + SectionList *module_section_list = module_sp->GetUnifiedSectionList(); + SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList(); + + static const SectionType g_sections[] = + { + eSectionTypeDWARFDebugAranges, + eSectionTypeDWARFDebugInfo, + eSectionTypeDWARFDebugAbbrev, + eSectionTypeDWARFDebugFrame, + eSectionTypeDWARFDebugLine, + eSectionTypeDWARFDebugStr, + eSectionTypeDWARFDebugLoc, + eSectionTypeDWARFDebugMacInfo, + eSectionTypeDWARFDebugPubNames, + eSectionTypeDWARFDebugPubTypes, + eSectionTypeDWARFDebugRanges, + eSectionTypeELFSymbolTable, + }; + for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); ++idx) + { + SectionType section_type = g_sections[idx]; + SectionSP section_sp (objfile_section_list->FindSectionByType (section_type, true)); + if (section_sp) + { + SectionSP module_section_sp (module_section_list->FindSectionByType (section_type, true)); + if (module_section_sp) + module_section_list->ReplaceSection (module_section_sp->GetID(), section_sp); + else + module_section_list->AddSection (section_sp); + } + } + module_section_list->Finalize(); + + symbol_vendor->AddSymbolFileRepresentation (dsym_objfile_sp); + return symbol_vendor; + } + } + } + } + return NULL; +} + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +ConstString +SymbolVendorELF::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +SymbolVendorELF::GetPluginVersion() +{ + return 1; +} + diff --git a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h new file mode 100644 index 000000000000..acd62b6cc3ab --- /dev/null +++ b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h @@ -0,0 +1,58 @@ +//===-- SymbolVendorELF.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_SymbolVendorELF_h_ +#define liblldb_SymbolVendorELF_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Symbol/SymbolVendor.h" + +class SymbolVendorELF : public lldb_private::SymbolVendor +{ +public: + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + static void + Initialize(); + + static void + Terminate(); + + static lldb_private::ConstString + GetPluginNameStatic(); + + static const char * + GetPluginDescriptionStatic(); + + static lldb_private::SymbolVendor* + CreateInstance (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + SymbolVendorELF (const lldb::ModuleSP &module_sp); + + virtual + ~SymbolVendorELF(); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual lldb_private::ConstString + GetPluginName(); + + virtual uint32_t + GetPluginVersion(); + +private: + DISALLOW_COPY_AND_ASSIGN (SymbolVendorELF); +}; + +#endif // liblldb_SymbolVendorELF_h_ diff --git a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp index a598cf7d8890..ab8c4e7d5caa 100644 --- a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp +++ b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp @@ -83,7 +83,7 @@ UUIDsMatch(Module *module, ObjectFile *ofile, lldb_private::Stream *feedback_str return false; } -static void +static bool ReplaceDSYMSectionsWithExecutableSections (ObjectFile *exec_objfile, ObjectFile *dsym_objfile) { // We need both the executable and the dSYM to live off of the @@ -123,7 +123,9 @@ ReplaceDSYMSectionsWithExecutableSections (ObjectFile *exec_objfile, ObjectFile } dsym_section_list->Finalize(); // Now that we're done adding sections, finalize to build fast-lookup caches + return true; } + return false; } void @@ -169,6 +171,15 @@ SymbolVendorMacOSX::CreateInstance (const lldb::ModuleSP &module_sp, lldb_privat if (!module_sp) return NULL; + ObjectFile * obj_file = module_sp->GetObjectFile(); + if (!obj_file) + return NULL; + + static ConstString obj_file_macho("mach-o"); + ConstString obj_name = obj_file->GetPluginName(); + if (obj_name != obj_file_macho) + return NULL; + Timer scoped_timer (__PRETTY_FUNCTION__, "SymbolVendorMacOSX::CreateInstance (module = %s)", module_sp->GetFileSpec().GetPath().c_str()); @@ -179,119 +190,115 @@ SymbolVendorMacOSX::CreateInstance (const lldb::ModuleSP &module_sp, lldb_privat path[0] = '\0'; // Try and locate the dSYM file on Mac OS X - ObjectFile * obj_file = module_sp->GetObjectFile(); - if (obj_file) - { - Timer scoped_timer2 ("SymbolVendorMacOSX::CreateInstance () locate dSYM", - "SymbolVendorMacOSX::CreateInstance (module = %s) locate dSYM", - module_sp->GetFileSpec().GetPath().c_str()); + Timer scoped_timer2 ("SymbolVendorMacOSX::CreateInstance () locate dSYM", + "SymbolVendorMacOSX::CreateInstance (module = %s) locate dSYM", + module_sp->GetFileSpec().GetPath().c_str()); - // First check to see if the module has a symbol file in mind already. - // If it does, then we MUST use that. - FileSpec dsym_fspec (module_sp->GetSymbolFileFileSpec()); + // First check to see if the module has a symbol file in mind already. + // If it does, then we MUST use that. + FileSpec dsym_fspec (module_sp->GetSymbolFileFileSpec()); - ObjectFileSP dsym_objfile_sp; - if (!dsym_fspec) - { - // No symbol file was specified in the module, lets try and find - // one ourselves. - FileSpec file_spec = obj_file->GetFileSpec(); - if (!file_spec) - file_spec = module_sp->GetFileSpec(); + ObjectFileSP dsym_objfile_sp; + if (!dsym_fspec) + { + // No symbol file was specified in the module, lets try and find + // one ourselves. + FileSpec file_spec = obj_file->GetFileSpec(); + if (!file_spec) + file_spec = module_sp->GetFileSpec(); - ModuleSpec module_spec(file_spec, module_sp->GetArchitecture()); - module_spec.GetUUID() = module_sp->GetUUID(); - dsym_fspec = Symbols::LocateExecutableSymbolFile (module_spec); - if (module_spec.GetSourceMappingList().GetSize()) - module_sp->GetSourceMappingList().Append (module_spec.GetSourceMappingList (), true); - } + ModuleSpec module_spec(file_spec, module_sp->GetArchitecture()); + module_spec.GetUUID() = module_sp->GetUUID(); + dsym_fspec = Symbols::LocateExecutableSymbolFile (module_spec); + if (module_spec.GetSourceMappingList().GetSize()) + module_sp->GetSourceMappingList().Append (module_spec.GetSourceMappingList (), true); + } - if (dsym_fspec) + if (dsym_fspec) + { + DataBufferSP dsym_file_data_sp; + lldb::offset_t dsym_file_data_offset = 0; + dsym_objfile_sp = ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(), dsym_file_data_sp, dsym_file_data_offset); + if (UUIDsMatch(module_sp.get(), dsym_objfile_sp.get(), feedback_strm)) { - DataBufferSP dsym_file_data_sp; - lldb::offset_t dsym_file_data_offset = 0; - dsym_objfile_sp = ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(), dsym_file_data_sp, dsym_file_data_offset); - if (UUIDsMatch(module_sp.get(), dsym_objfile_sp.get(), feedback_strm)) + char dsym_path[PATH_MAX]; + if (module_sp->GetSourceMappingList().IsEmpty() && dsym_fspec.GetPath(dsym_path, sizeof(dsym_path))) { - char dsym_path[PATH_MAX]; - if (module_sp->GetSourceMappingList().IsEmpty() && dsym_fspec.GetPath(dsym_path, sizeof(dsym_path))) + lldb_private::UUID dsym_uuid; + if (dsym_objfile_sp->GetUUID(&dsym_uuid)) { - lldb_private::UUID dsym_uuid; - if (dsym_objfile_sp->GetUUID(&dsym_uuid)) + std::string uuid_str = dsym_uuid.GetAsString (); + if (!uuid_str.empty()) { - std::string uuid_str = dsym_uuid.GetAsString (); - if (!uuid_str.empty()) + char *resources = strstr (dsym_path, "/Contents/Resources/"); + if (resources) { - char *resources = strstr (dsym_path, "/Contents/Resources/"); - if (resources) + char dsym_uuid_plist_path[PATH_MAX]; + resources[strlen("/Contents/Resources/")] = '\0'; + snprintf(dsym_uuid_plist_path, sizeof(dsym_uuid_plist_path), "%s%s.plist", dsym_path, uuid_str.c_str()); + FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path, false); + if (dsym_uuid_plist_spec.Exists()) { - char dsym_uuid_plist_path[PATH_MAX]; - resources[strlen("/Contents/Resources/")] = '\0'; - snprintf(dsym_uuid_plist_path, sizeof(dsym_uuid_plist_path), "%s%s.plist", dsym_path, uuid_str.c_str()); - FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path, false); - if (dsym_uuid_plist_spec.Exists()) + xmlDoc *doc = ::xmlReadFile (dsym_uuid_plist_path, NULL, 0); + if (doc) { - xmlDoc *doc = ::xmlReadFile (dsym_uuid_plist_path, NULL, 0); - if (doc) + char DBGBuildSourcePath[PATH_MAX]; + char DBGSourcePath[PATH_MAX]; + DBGBuildSourcePath[0] = '\0'; + DBGSourcePath[0] = '\0'; + for (xmlNode *node = doc->children; node; node = node ? node->next : NULL) { - char DBGBuildSourcePath[PATH_MAX]; - char DBGSourcePath[PATH_MAX]; - DBGBuildSourcePath[0] = '\0'; - DBGSourcePath[0] = '\0'; - for (xmlNode *node = doc->children; node; node = node ? node->next : NULL) + if (node->type == XML_ELEMENT_NODE) { - if (node->type == XML_ELEMENT_NODE) + if (node->name && strcmp((const char*)node->name, "plist") == 0) { - if (node->name && strcmp((const char*)node->name, "plist") == 0) + xmlNode *dict_node = node->children; + while (dict_node && dict_node->type != XML_ELEMENT_NODE) + dict_node = dict_node->next; + if (dict_node && dict_node->name && strcmp((const char *)dict_node->name, "dict") == 0) { - xmlNode *dict_node = node->children; - while (dict_node && dict_node->type != XML_ELEMENT_NODE) - dict_node = dict_node->next; - if (dict_node && dict_node->name && strcmp((const char *)dict_node->name, "dict") == 0) + for (xmlNode *key_node = dict_node->children; key_node; key_node = key_node->next) { - for (xmlNode *key_node = dict_node->children; key_node; key_node = key_node->next) + if (key_node && key_node->type == XML_ELEMENT_NODE && key_node->name) { - if (key_node && key_node->type == XML_ELEMENT_NODE && key_node->name) + if (strcmp((const char *)key_node->name, "key") == 0) { - if (strcmp((const char *)key_node->name, "key") == 0) + const char *key_name = (const char *)::xmlNodeGetContent(key_node); + if (strcmp(key_name, "DBGBuildSourcePath") == 0) { - const char *key_name = (const char *)::xmlNodeGetContent(key_node); - if (strcmp(key_name, "DBGBuildSourcePath") == 0) + xmlNode *value_node = key_node->next; + while (value_node && value_node->type != XML_ELEMENT_NODE) + value_node = value_node->next; + if (value_node && value_node->name) { - xmlNode *value_node = key_node->next; - while (value_node && value_node->type != XML_ELEMENT_NODE) - value_node = value_node->next; - if (value_node && value_node->name) + if (strcmp((const char *)value_node->name, "string") == 0) { - if (strcmp((const char *)value_node->name, "string") == 0) + const char *node_content = (const char *)::xmlNodeGetContent(value_node); + if (node_content) { - const char *node_content = (const char *)::xmlNodeGetContent(value_node); - if (node_content) - { - strncpy(DBGBuildSourcePath, node_content, sizeof(DBGBuildSourcePath)); - } + strncpy(DBGBuildSourcePath, node_content, sizeof(DBGBuildSourcePath)); } - key_node = value_node; } + key_node = value_node; } - else if (strcmp(key_name, "DBGSourcePath") == 0) + } + else if (strcmp(key_name, "DBGSourcePath") == 0) + { + xmlNode *value_node = key_node->next; + while (value_node && value_node->type != XML_ELEMENT_NODE) + value_node = value_node->next; + if (value_node && value_node->name) { - xmlNode *value_node = key_node->next; - while (value_node && value_node->type != XML_ELEMENT_NODE) - value_node = value_node->next; - if (value_node && value_node->name) + if (strcmp((const char *)value_node->name, "string") == 0) { - if (strcmp((const char *)value_node->name, "string") == 0) + const char *node_content = (const char *)::xmlNodeGetContent(value_node); + if (node_content) { - const char *node_content = (const char *)::xmlNodeGetContent(value_node); - if (node_content) - { - FileSpec resolved_source_path(node_content, true); - resolved_source_path.GetPath(DBGSourcePath, sizeof(DBGSourcePath)); - } + FileSpec resolved_source_path(node_content, true); + resolved_source_path.GetPath(DBGSourcePath, sizeof(DBGSourcePath)); } - key_node = value_node; } + key_node = value_node; } } } @@ -300,30 +307,39 @@ SymbolVendorMacOSX::CreateInstance (const lldb::ModuleSP &module_sp, lldb_privat } } } - ::xmlFreeDoc (doc); + } + ::xmlFreeDoc (doc); - if (DBGBuildSourcePath[0] && DBGSourcePath[0]) - { - module_sp->GetSourceMappingList().Append (ConstString(DBGBuildSourcePath), ConstString(DBGSourcePath), true); - } + if (DBGBuildSourcePath[0] && DBGSourcePath[0]) + { + module_sp->GetSourceMappingList().Append (ConstString(DBGBuildSourcePath), ConstString(DBGSourcePath), true); } } } } } } - - ReplaceDSYMSectionsWithExecutableSections (obj_file, dsym_objfile_sp.get()); - symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp); - return symbol_vendor; } - } - // Just create our symbol vendor using the current objfile as this is either - // an executable with no dSYM (that we could locate), an executable with - // a dSYM that has a UUID that doesn't match. - symbol_vendor->AddSymbolFileRepresentation(obj_file->shared_from_this()); + if (ReplaceDSYMSectionsWithExecutableSections (obj_file, dsym_objfile_sp.get())) + { + SectionList *section_list = dsym_objfile_sp.get()->GetSectionList(); + if (section_list) + { + section_list->Copy (module_sp->GetUnifiedSectionList()); + section_list->Finalize (); + } + } + + symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp); + return symbol_vendor; + } } + + // Just create our symbol vendor using the current objfile as this is either + // an executable with no dSYM (that we could locate), an executable with + // a dSYM that has a UUID that doesn't match. + symbol_vendor->AddSymbolFileRepresentation(obj_file->shared_from_this()); } return symbol_vendor; } diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp index c42b0cfd7701..594cb3922e60 100644 --- a/lldb/source/Symbol/Function.cpp +++ b/lldb/source/Symbol/Function.cpp @@ -568,9 +568,9 @@ Function::GetPrologueByteSize () // Check the first few instructions and look for one that has // is_prologue_end set to true. const uint32_t last_line_entry_idx = first_line_entry_idx + 6; - LineEntry line_entry; for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx) { + LineEntry line_entry; if (line_table->GetLineEntryAtIndex (idx, line_entry)) { if (line_entry.is_prologue_end) @@ -581,12 +581,31 @@ Function::GetPrologueByteSize () } } } - + // If we didn't find the end of the prologue in the line tables, // then just use the end address of the first line table entry if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) { - prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress() + first_line_entry.range.GetByteSize(); + // Check the first few instructions and look for one that has + // a line number that's different than the first entry. + const uint32_t last_line_entry_idx = first_line_entry_idx + 6; + for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx) + { + LineEntry line_entry; + if (line_table->GetLineEntryAtIndex (idx, line_entry)) + { + if (line_entry.line != first_line_entry.line) + { + prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress(); + break; + } + } + } + + if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) + { + prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress() + first_line_entry.range.GetByteSize(); + } } const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress(); const addr_t func_end_file_addr = func_start_file_addr + m_range.GetByteSize(); diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp index 759477dbe32f..dbfab614dfaa 100644 --- a/lldb/source/Symbol/ObjectFile.cpp +++ b/lldb/source/Symbol/ObjectFile.cpp @@ -244,7 +244,9 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, m_process_wp(), m_memory_addr (LLDB_INVALID_ADDRESS), m_sections_ap (), - m_symtab_ap () + m_symtab_ap (), + m_symtab_unified_ap (), + m_symtab_unified_revisionid (0) { if (file_spec_ptr) m_file = *file_spec_ptr; @@ -291,7 +293,9 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, m_process_wp (process_sp), m_memory_addr (header_addr), m_sections_ap (), - m_symtab_ap () + m_symtab_ap (), + m_symtab_unified_ap (), + m_symtab_unified_revisionid (0) { if (header_data_sp) m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize()); @@ -327,7 +331,7 @@ ObjectFile::SetModulesArchitecture (const ArchSpec &new_arch) AddressClass ObjectFile::GetAddressClass (addr_t file_addr) { - Symtab *symtab = GetSymtab(); + Symtab *symtab = GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList); if (symtab) { Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr); @@ -374,6 +378,10 @@ ObjectFile::GetAddressClass (addr_t file_addr) case eSectionTypeDWARFAppleObjC: return eAddressClassDebug; case eSectionTypeEHFrame: return eAddressClassRuntime; + case eSectionTypeELFSymbolTable: + case eSectionTypeELFDynamicSymbols: + case eSectionTypeELFRelocationEntries: + case eSectionTypeELFDynamicLinkInfo: case eSectionTypeOther: return eAddressClassUnknown; } } @@ -453,6 +461,10 @@ ObjectFile::CopyData (off_t offset, size_t length, void *dst) const size_t ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void *dst, size_t dst_len) const { + // If some other objectfile owns this data, pass this to them. + if (section->GetObjectFile() != this) + return section->GetObjectFile()->ReadSectionData (section, section_offset, dst, dst_len); + if (IsInMemory()) { ProcessSP process_sp (m_process_wp.lock()); @@ -498,6 +510,10 @@ ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void size_t ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const { + // If some other objectfile owns this data, pass this to them. + if (section->GetObjectFile() != this) + return section->GetObjectFile()->ReadSectionData (section, section_data); + if (IsInMemory()) { ProcessSP process_sp (m_process_wp.lock()); @@ -529,6 +545,10 @@ ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data size_t ObjectFile::MemoryMapSectionData (const Section *section, DataExtractor& section_data) const { + // If some other objectfile owns this data, pass this to them. + if (section->GetObjectFile() != this) + return section->GetObjectFile()->MemoryMapSectionData (section, section_data); + if (IsInMemory()) { return ReadSectionData (section, section_data); @@ -566,19 +586,29 @@ ObjectFile::SplitArchivePathWithObject (const char *path_with_object, FileSpec & } void -ObjectFile::ClearSymtab () +ObjectFile::ClearSymtab (uint32_t flags) { ModuleSP module_sp(GetModule()); if (module_sp) { lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + bool unified_section_list = !!(flags & ObjectFile::eSymtabFromUnifiedSectionList); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); if (log) { - log->Printf ("%p ObjectFile::ClearSymtab () symtab = %p", + log->Printf ("%p ObjectFile::ClearSymtab (%s) symtab = %p", this, - m_symtab_ap.get()); + unified_section_list ? "unified" : "", + unified_section_list ? m_symtab_unified_ap.get() : m_symtab_ap.get()); + } + if (unified_section_list) + { + m_symtab_unified_ap.reset(); + m_symtab_unified_revisionid = 0; + } + else + { + m_symtab_ap.reset(); } - m_symtab_ap.reset(); } } diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp index 905b6cb93bcb..ee447a11c2c0 100644 --- a/lldb/source/Symbol/Symbol.cpp +++ b/lldb/source/Symbol/Symbol.cpp @@ -16,6 +16,7 @@ #include "lldb/Symbol/Symtab.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Symbol/SymbolVendor.h" using namespace lldb; using namespace lldb_private; @@ -288,22 +289,59 @@ Symbol::GetPrologueByteSize () m_type_data_resolved = true; ModuleSP module_sp (m_addr_range.GetBaseAddress().GetModule()); SymbolContext sc; - if (module_sp && module_sp->ResolveSymbolContextForAddress (m_addr_range.GetBaseAddress(), - eSymbolContextLineEntry, - sc)) + if (module_sp) { - m_type_data = sc.line_entry.range.GetByteSize(); - // Sanity check - this may be a function in the middle of code that has debug information, but - // not for this symbol. So the line entries surrounding us won't lie inside our function. - // In that case, the line entry will be bigger than we are, so we do that quick check and - // if that is true, we just return 0. - if (m_type_data >= m_addr_range.GetByteSize()) + uint32_t resolved_flags = module_sp->ResolveSymbolContextForAddress (m_addr_range.GetBaseAddress(), + eSymbolContextLineEntry, + sc); + if (resolved_flags & eSymbolContextLineEntry) + { + // Default to the end of the first line entry. + m_type_data = sc.line_entry.range.GetByteSize(); + + // Set address for next line. + Address addr (m_addr_range.GetBaseAddress()); + addr.Slide (m_type_data); + + // Check the first few instructions and look for one that has a line number that is + // different than the first entry. This is also done in Function::GetPrologueByteSize(). + uint16_t total_offset = m_type_data; + for (int idx = 0; idx < 6; ++idx) + { + SymbolContext sc_temp; + resolved_flags = module_sp->ResolveSymbolContextForAddress (addr, eSymbolContextLineEntry, sc_temp); + // Make sure we got line number information... + if (!(resolved_flags & eSymbolContextLineEntry)) + break; + + // If this line number is different than our first one, use it and we're done. + if (sc_temp.line_entry.line != sc.line_entry.line) + { + m_type_data = total_offset; + break; + } + + // Slide addr up to the next line address. + addr.Slide (sc_temp.line_entry.range.GetByteSize()); + total_offset += sc_temp.line_entry.range.GetByteSize(); + // If we've gone too far, bail out. + if (total_offset >= m_addr_range.GetByteSize()) + break; + } + + // Sanity check - this may be a function in the middle of code that has debug information, but + // not for this symbol. So the line entries surrounding us won't lie inside our function. + // In that case, the line entry will be bigger than we are, so we do that quick check and + // if that is true, we just return 0. + if (m_type_data >= m_addr_range.GetByteSize()) + m_type_data = 0; + } + else + { + // TODO: expose something in Process to figure out the + // size of a function prologue. m_type_data = 0; - } - else - { - // TODO: expose something in Process to figure out the - // size of a function prologue. + } } } return m_type_data; @@ -418,10 +456,10 @@ Symbol::GetByteSize () const ModuleSP module_sp (GetAddress().GetModule()); if (module_sp) { - ObjectFile *objfile = module_sp->GetObjectFile(); - if (objfile) + SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); + if (sym_vendor) { - Symtab *symtab = objfile->GetSymtab(); + Symtab *symtab = sym_vendor->GetSymtab(); if (symtab) { const_cast(this)->SetByteSize (symtab->CalculateSymbolSize (const_cast(this))); diff --git a/lldb/source/Symbol/SymbolVendor.cpp b/lldb/source/Symbol/SymbolVendor.cpp index 7b49ab22feda..2ee00a7c3338 100644 --- a/lldb/source/Symbol/SymbolVendor.cpp +++ b/lldb/source/Symbol/SymbolVendor.cpp @@ -35,21 +35,14 @@ SymbolVendor* SymbolVendor::FindPlugin (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm) { std::unique_ptr instance_ap; - //---------------------------------------------------------------------- - // We currently only have one debug symbol parser... - //---------------------------------------------------------------------- SymbolVendorCreateInstance create_callback; + for (size_t idx = 0; (create_callback = PluginManager::GetSymbolVendorCreateCallbackAtIndex(idx)) != NULL; ++idx) { instance_ap.reset(create_callback(module_sp, feedback_strm)); if (instance_ap.get()) { - // TODO: make sure this symbol vendor is what we want. We - // currently are just returning the first one we find, but - // we may want to call this function only when we have our - // main executable module and then give all symbol vendor - // plug-ins a chance to compete for who wins. return instance_ap.release(); } } @@ -84,7 +77,7 @@ SymbolVendor::~SymbolVendor() } //---------------------------------------------------------------------- -// Add a represantion given an object file. +// Add a represention given an object file. //---------------------------------------------------------------------- void SymbolVendor::AddSymbolFileRepresentation(const ObjectFileSP &objfile_sp) @@ -444,6 +437,36 @@ SymbolVendor::GetCompileUnitAtIndex(size_t idx) return cu_sp; } +Symtab * +SymbolVendor::GetSymtab () +{ + ModuleSP module_sp(GetModule()); + if (module_sp) + { + ObjectFile *objfile = module_sp->GetObjectFile(); + if (objfile) + { + // Get symbol table from unified section list. + return objfile->GetSymtab (ObjectFile::eSymtabFromUnifiedSectionList); + } + } + return NULL; +} + +void +SymbolVendor::ClearSymtab() +{ + ModuleSP module_sp(GetModule()); + if (module_sp) + { + ObjectFile *objfile = module_sp->GetObjectFile(); + if (objfile) + { + // Clear symbol table from unified section list. + objfile->ClearSymtab (ObjectFile::eSymtabFromUnifiedSectionList); + } + } +} //------------------------------------------------------------------ // PluginInterface protocol diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 1c70d66e3d4e..064023e6b2e6 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -1775,6 +1775,15 @@ Target::GetDefaultExecutableSearchPaths () return FileSpecList(); } +FileSpecList +Target::GetDefaultDebugFileSearchPaths () +{ + TargetPropertiesSP properties_sp(Target::GetGlobalProperties()); + if (properties_sp) + return properties_sp->GetDebugFileSearchPaths(); + return FileSpecList(); +} + ArchSpec Target::GetDefaultArchitecture () { @@ -2305,6 +2314,7 @@ g_properties[] = "and the second is where the remainder of the original build hierarchy is rooted on the local system. " "Each element of the array is checked in order and the first one that results in a match wins." }, { "exec-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , NULL, NULL, "Executable search paths to use when locating executable files whose paths don't match the local file system." }, + { "debug-file-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , NULL, NULL, "List of directories to be searched when locating debug symbol files." }, { "max-children-count" , OptionValue::eTypeSInt64 , false, 256 , NULL, NULL, "Maximum number of children to expand in any level of depth." }, { "max-string-summary-length" , OptionValue::eTypeSInt64 , false, 1024 , NULL, NULL, "Maximum number of characters to show when using %s in summary strings." }, { "max-memory-read-size" , OptionValue::eTypeSInt64 , false, 1024 , NULL, NULL, "Maximum number of bytes that 'memory read' will fetch before --force must be specified." }, @@ -2340,6 +2350,7 @@ enum ePropertySkipPrologue, ePropertySourceMap, ePropertyExecutableSearchPaths, + ePropertyDebugFileSearchPaths, ePropertyMaxChildrenCount, ePropertyMaxSummaryLength, ePropertyMaxMemReadSize, @@ -2617,6 +2628,15 @@ TargetProperties::GetExecutableSearchPaths () return option_value->GetCurrentValue(); } +FileSpecList & +TargetProperties::GetDebugFileSearchPaths () +{ + const uint32_t idx = ePropertyDebugFileSearchPaths; + OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList (NULL, false, idx); + assert(option_value); + return option_value->GetCurrentValue(); +} + bool TargetProperties::GetEnableSyntheticValue () const { diff --git a/lldb/source/lldb.cpp b/lldb/source/lldb.cpp index 226206c1b361..f2dfdee96a09 100644 --- a/lldb/source/lldb.cpp +++ b/lldb/source/lldb.cpp @@ -30,6 +30,7 @@ #include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h" #include "Plugins/Instruction/ARM/EmulateInstructionARM.h" #include "Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h" +#include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h" #include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h" #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" @@ -98,6 +99,7 @@ lldb_private::Initialize () DisassemblerLLVMC::Initialize(); ObjectContainerBSDArchive::Initialize(); ObjectFileELF::Initialize(); + SymbolVendorELF::Initialize(); SymbolFileDWARF::Initialize(); SymbolFileSymtab::Initialize(); UnwindAssemblyInstEmulation::Initialize(); @@ -177,6 +179,7 @@ lldb_private::Terminate () DisassemblerLLVMC::Terminate(); ObjectContainerBSDArchive::Terminate(); ObjectFileELF::Terminate(); + SymbolVendorELF::Terminate(); SymbolFileDWARF::Terminate(); SymbolFileSymtab::Terminate(); UnwindAssembly_x86::Terminate(); @@ -361,6 +364,10 @@ lldb_private::GetSectionTypeAsCString (SectionType sect_type) case eSectionTypeDWARFDebugPubTypes: return "dwarf-pubtypes"; case eSectionTypeDWARFDebugRanges: return "dwarf-ranges"; case eSectionTypeDWARFDebugStr: return "dwarf-str"; + case eSectionTypeELFSymbolTable: return "elf-symbol-table"; + case eSectionTypeELFDynamicSymbols: return "elf-dynamic-symbols"; + case eSectionTypeELFRelocationEntries: return "elf-relocation-entries"; + case eSectionTypeELFDynamicLinkInfo: return "elf-dynamic-link-info"; case eSectionTypeDWARFAppleNames: return "apple-names"; case eSectionTypeDWARFAppleTypes: return "apple-types"; case eSectionTypeDWARFAppleNamespaces: return "apple-namespaces";