| //===-- 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 <string.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->GetSectionList(); |
| 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); |
| } |
| } |
| |
| symbol_vendor->AddSymbolFileRepresentation (dsym_objfile_sp); |
| return symbol_vendor; |
| } |
| } |
| } |
| } |
| return NULL; |
| } |
| |
| //------------------------------------------------------------------ |
| // PluginInterface protocol |
| //------------------------------------------------------------------ |
| ConstString |
| SymbolVendorELF::GetPluginName() |
| { |
| return GetPluginNameStatic(); |
| } |
| |
| uint32_t |
| SymbolVendorELF::GetPluginVersion() |
| { |
| return 1; |
| } |
| |