173 lines · cpp
1//===-- SymbolVendorELF.cpp -----------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "SymbolVendorELF.h"10 11#include <cstring>12 13#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"14#include "lldb/Core/Module.h"15#include "lldb/Core/ModuleSpec.h"16#include "lldb/Core/PluginManager.h"17#include "lldb/Core/Section.h"18#include "lldb/Host/Host.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 24using namespace lldb;25using namespace lldb_private;26 27LLDB_PLUGIN_DEFINE(SymbolVendorELF)28 29// SymbolVendorELF constructor30SymbolVendorELF::SymbolVendorELF(const lldb::ModuleSP &module_sp)31 : SymbolVendor(module_sp) {}32 33void SymbolVendorELF::Initialize() {34 PluginManager::RegisterPlugin(GetPluginNameStatic(),35 GetPluginDescriptionStatic(), CreateInstance);36}37 38void SymbolVendorELF::Terminate() {39 PluginManager::UnregisterPlugin(CreateInstance);40}41 42llvm::StringRef SymbolVendorELF::GetPluginDescriptionStatic() {43 return "Symbol vendor for ELF that looks for dSYM files that match "44 "executables.";45}46 47// If this is needed elsewhere, it can be exported/moved.48static bool IsDwpSymbolFile(const lldb::ModuleSP &module_sp,49 const FileSpec &file_spec) {50 DataBufferSP dwp_file_data_sp;51 lldb::offset_t dwp_file_data_offset = 0;52 // Try to create an ObjectFile from the file_spec.53 ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin(54 module_sp, &file_spec, 0, FileSystem::Instance().GetByteSize(file_spec),55 dwp_file_data_sp, dwp_file_data_offset);56 // The presence of a debug_cu_index section is the key identifying feature of57 // a DWP file. Make sure we don't fill in the section list on dwp_obj_file58 // (by calling GetSectionList(false)) as this function could be called before59 // we may have all the symbol files collected and available.60 return dwp_obj_file && ObjectFileELF::classof(dwp_obj_file.get()) &&61 dwp_obj_file->GetSectionList(false)->FindSectionByType(62 eSectionTypeDWARFDebugCuIndex, false);63}64 65// CreateInstance66//67// Platforms can register a callback to use when creating symbol vendors to68// allow for complex debug information file setups, and to also allow for69// finding separate debug information files.70SymbolVendor *71SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,72 lldb_private::Stream *feedback_strm) {73 if (!module_sp)74 return nullptr;75 76 ObjectFileELF *obj_file =77 llvm::dyn_cast_or_null<ObjectFileELF>(module_sp->GetObjectFile());78 if (!obj_file)79 return nullptr;80 81 lldb_private::UUID uuid = obj_file->GetUUID();82 if (!uuid)83 return nullptr;84 85 // If the main object file already contains debug info, then we are done.86 if (obj_file->GetSectionList()->FindSectionByType(87 lldb::eSectionTypeDWARFDebugInfo, true))88 return nullptr;89 90 // If the module specified a filespec, use that.91 FileSpec fspec = module_sp->GetSymbolFileFileSpec();92 // Otherwise, try gnu_debuglink, if one exists.93 if (!fspec)94 fspec = obj_file->GetDebugLink().value_or(FileSpec());95 96 LLDB_SCOPED_TIMERF("SymbolVendorELF::CreateInstance (module = %s)",97 module_sp->GetFileSpec().GetPath().c_str());98 99 ModuleSpec module_spec;100 101 module_spec.GetFileSpec() = obj_file->GetFileSpec();102 FileSystem::Instance().Resolve(module_spec.GetFileSpec());103 module_spec.GetSymbolFileSpec() = fspec;104 module_spec.GetUUID() = uuid;105 FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();106 FileSpec dsym_fspec = PluginManager::LocateExecutableSymbolFile(107 module_spec, search_paths, module_sp->GetSymbolLocatorStatistics());108 if (!dsym_fspec || IsDwpSymbolFile(module_sp, dsym_fspec)) {109 // If we have a stripped binary or if we have a DWP file, SymbolLocator110 // plugins may be able to give us an unstripped binary or an111 // 'only-keep-debug' stripped file.112 ModuleSpec unstripped_spec = PluginManager::LocateExecutableObjectFile(113 module_spec, module_sp->GetSymbolLocatorStatistics());114 if (!unstripped_spec)115 return nullptr;116 // The default SymbolLocator plugin returns the original binary if no other117 // plugin finds something better.118 if (unstripped_spec.GetFileSpec() == module_spec.GetFileSpec())119 return nullptr;120 dsym_fspec = unstripped_spec.GetFileSpec();121 }122 123 DataBufferSP dsym_file_data_sp;124 lldb::offset_t dsym_file_data_offset = 0;125 ObjectFileSP dsym_objfile_sp = ObjectFile::FindPlugin(126 module_sp, &dsym_fspec, 0, FileSystem::Instance().GetByteSize(dsym_fspec),127 dsym_file_data_sp, dsym_file_data_offset);128 if (!dsym_objfile_sp)129 return nullptr;130 // This objfile is for debugging purposes. Sadly, ObjectFileELF won't131 // be able to figure this out consistently as the symbol file may not132 // have stripped the code sections, etc.133 dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo);134 135 SymbolVendorELF *symbol_vendor = new SymbolVendorELF(module_sp);136 137 // Get the module unified section list and add our debug sections to138 // that.139 SectionList *module_section_list = module_sp->GetSectionList();140 SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList();141 142 if (!module_section_list || !objfile_section_list)143 return nullptr;144 145 static const SectionType g_sections[] = {146 eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr,147 eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex,148 eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo,149 eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLineStr,150 eSectionTypeDWARFDebugLoc, eSectionTypeDWARFDebugLocLists,151 eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugMacro,152 eSectionTypeDWARFDebugNames, eSectionTypeDWARFDebugPubNames,153 eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,154 eSectionTypeDWARFDebugRngLists, eSectionTypeDWARFDebugStr,155 eSectionTypeDWARFDebugStrOffsets, eSectionTypeDWARFDebugTypes,156 eSectionTypeELFSymbolTable, eSectionTypeDWARFGNUDebugAltLink,157 };158 for (SectionType section_type : g_sections) {159 if (SectionSP section_sp =160 objfile_section_list->FindSectionByType(section_type, true)) {161 if (SectionSP module_section_sp =162 module_section_list->FindSectionByType(section_type, true))163 module_section_list->ReplaceSection(module_section_sp->GetID(),164 section_sp);165 else166 module_section_list->AddSection(section_sp);167 }168 }169 170 symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp);171 return symbol_vendor;172}173