diff options
author | Michael Sartain <mikesart@valvesoftware.com> | 2013-07-01 19:45:50 +0000 |
---|---|---|
committer | Michael Sartain <mikesart@valvesoftware.com> | 2013-07-01 19:45:50 +0000 |
commit | 68bcc4ed1fc3ff53a3d3c396ff8fc8eef713ccbc (patch) | |
tree | 1fc57486f1c015cf48e7f38985954d0bb9bba7cd /lldb/source/Plugins/SymbolVendor | |
parent | 27528ef81d80cf9185ac2b981988061539918015 (diff) |
Split symbol support for ELF and Linux.
Diffstat (limited to 'lldb/source/Plugins/SymbolVendor')
6 files changed, 392 insertions, 97 deletions
diff --git a/lldb/source/Plugins/SymbolVendor/CMakeLists.txt b/lldb/source/Plugins/SymbolVendor/CMakeLists.txt index 5bd3ac342ea..9f5c6311b22 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 00000000000..2401b76a342 --- /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 00000000000..47c24a2bda3 --- /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 00000000000..2dd2cea6ca9 --- /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 <libxml/parser.h> +// #include <libxml/tree.h> +#include <string.h> + +// #include <AvailabilityMacros.h> + +#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 00000000000..acd62b6cc3a --- /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 a598cf7d889..ab8c4e7d5ca 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; + 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 (); + } } - } - // 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()); + 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; } |