1 //===-- SymbolVendorELF.cpp ----------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "SymbolVendorELF.h" 10 11 #include <string.h> 12 13 #include "lldb/Core/Module.h" 14 #include "lldb/Core/ModuleSpec.h" 15 #include "lldb/Core/PluginManager.h" 16 #include "lldb/Core/Section.h" 17 #include "lldb/Host/Host.h" 18 #include "lldb/Symbol/LocateSymbolFile.h" 19 #include "lldb/Symbol/ObjectFile.h" 20 #include "lldb/Target/Target.h" 21 #include "lldb/Utility/StreamString.h" 22 #include "lldb/Utility/Timer.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 // SymbolVendorELF constructor 28 SymbolVendorELF::SymbolVendorELF(const lldb::ModuleSP &module_sp) 29 : SymbolVendor(module_sp) {} 30 31 // Destructor 32 SymbolVendorELF::~SymbolVendorELF() {} 33 34 void SymbolVendorELF::Initialize() { 35 PluginManager::RegisterPlugin(GetPluginNameStatic(), 36 GetPluginDescriptionStatic(), CreateInstance); 37 } 38 39 void SymbolVendorELF::Terminate() { 40 PluginManager::UnregisterPlugin(CreateInstance); 41 } 42 43 lldb_private::ConstString SymbolVendorELF::GetPluginNameStatic() { 44 static ConstString g_name("ELF"); 45 return g_name; 46 } 47 48 const char *SymbolVendorELF::GetPluginDescriptionStatic() { 49 return "Symbol vendor for ELF that looks for dSYM files that match " 50 "executables."; 51 } 52 53 // CreateInstance 54 // 55 // Platforms can register a callback to use when creating symbol vendors to 56 // allow for complex debug information file setups, and to also allow for 57 // finding separate debug information files. 58 SymbolVendor * 59 SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp, 60 lldb_private::Stream *feedback_strm) { 61 if (!module_sp) 62 return nullptr; 63 64 ObjectFile *obj_file = module_sp->GetObjectFile(); 65 if (!obj_file) 66 return nullptr; 67 68 static ConstString obj_file_elf("elf"); 69 ConstString obj_name = obj_file->GetPluginName(); 70 if (obj_name != obj_file_elf) 71 return nullptr; 72 73 lldb_private::UUID uuid = obj_file->GetUUID(); 74 if (!uuid) 75 return nullptr; 76 77 // Get the .gnu_debuglink file (if specified). 78 FileSpecList file_spec_list = obj_file->GetDebugSymbolFilePaths(); 79 80 // If the module specified a filespec, use it first. 81 FileSpec debug_symbol_fspec(module_sp->GetSymbolFileFileSpec()); 82 if (debug_symbol_fspec) 83 file_spec_list.Insert(0, debug_symbol_fspec); 84 85 // If we have no debug symbol files, then nothing to do. 86 if (file_spec_list.IsEmpty()) 87 return nullptr; 88 89 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 90 Timer scoped_timer(func_cat, "SymbolVendorELF::CreateInstance (module = %s)", 91 module_sp->GetFileSpec().GetPath().c_str()); 92 93 for (size_t idx = 0; idx < file_spec_list.GetSize(); ++idx) { 94 ModuleSpec module_spec; 95 const FileSpec fspec = file_spec_list.GetFileSpecAtIndex(idx); 96 97 module_spec.GetFileSpec() = obj_file->GetFileSpec(); 98 FileSystem::Instance().Resolve(module_spec.GetFileSpec()); 99 module_spec.GetSymbolFileSpec() = fspec; 100 module_spec.GetUUID() = uuid; 101 FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); 102 FileSpec dsym_fspec = 103 Symbols::LocateExecutableSymbolFile(module_spec, search_paths); 104 if (dsym_fspec) { 105 DataBufferSP dsym_file_data_sp; 106 lldb::offset_t dsym_file_data_offset = 0; 107 ObjectFileSP dsym_objfile_sp = 108 ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, 109 FileSystem::Instance().GetByteSize(dsym_fspec), 110 dsym_file_data_sp, dsym_file_data_offset); 111 if (dsym_objfile_sp) { 112 // This objfile is for debugging purposes. Sadly, ObjectFileELF won't 113 // be able to figure this out consistently as the symbol file may not 114 // have stripped the code sections, etc. 115 dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo); 116 117 SymbolVendorELF *symbol_vendor = new SymbolVendorELF(module_sp); 118 if (symbol_vendor) { 119 // Get the module unified section list and add our debug sections to 120 // that. 121 SectionList *module_section_list = module_sp->GetSectionList(); 122 SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList(); 123 124 static const SectionType g_sections[] = { 125 eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr, 126 eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex, 127 eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo, 128 eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc, 129 eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames, 130 eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges, 131 eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets, 132 eSectionTypeELFSymbolTable, eSectionTypeDWARFGNUDebugAltLink, 133 }; 134 for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); 135 ++idx) { 136 SectionType section_type = g_sections[idx]; 137 SectionSP section_sp( 138 objfile_section_list->FindSectionByType(section_type, true)); 139 if (section_sp) { 140 SectionSP module_section_sp( 141 module_section_list->FindSectionByType(section_type, true)); 142 if (module_section_sp) 143 module_section_list->ReplaceSection(module_section_sp->GetID(), 144 section_sp); 145 else 146 module_section_list->AddSection(section_sp); 147 } 148 } 149 150 symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp); 151 return symbol_vendor; 152 } 153 } 154 } 155 } 156 return nullptr; 157 } 158 159 // PluginInterface protocol 160 ConstString SymbolVendorELF::GetPluginName() { return GetPluginNameStatic(); } 161 162 uint32_t SymbolVendorELF::GetPluginVersion() { return 1; } 163