1 //===-- SymbolVendorPECOFF.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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "SymbolVendorPECOFF.h" 10 11 #include <cstring> 12 13 #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.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/LocateSymbolFile.h" 20 #include "lldb/Symbol/ObjectFile.h" 21 #include "lldb/Target/Target.h" 22 #include "lldb/Utility/StreamString.h" 23 #include "lldb/Utility/Timer.h" 24 25 using namespace lldb; 26 using namespace lldb_private; 27 28 LLDB_PLUGIN_DEFINE(SymbolVendorPECOFF) 29 30 // SymbolVendorPECOFF constructor 31 SymbolVendorPECOFF::SymbolVendorPECOFF(const lldb::ModuleSP &module_sp) 32 : SymbolVendor(module_sp) {} 33 34 void SymbolVendorPECOFF::Initialize() { 35 PluginManager::RegisterPlugin(GetPluginNameStatic(), 36 GetPluginDescriptionStatic(), CreateInstance); 37 } 38 39 void SymbolVendorPECOFF::Terminate() { 40 PluginManager::UnregisterPlugin(CreateInstance); 41 } 42 43 llvm::StringRef SymbolVendorPECOFF::GetPluginDescriptionStatic() { 44 return "Symbol vendor for PE/COFF that looks for dSYM files that match " 45 "executables."; 46 } 47 48 // CreateInstance 49 // 50 // Platforms can register a callback to use when creating symbol vendors to 51 // allow for complex debug information file setups, and to also allow for 52 // finding separate debug information files. 53 SymbolVendor * 54 SymbolVendorPECOFF::CreateInstance(const lldb::ModuleSP &module_sp, 55 lldb_private::Stream *feedback_strm) { 56 if (!module_sp) 57 return nullptr; 58 59 ObjectFilePECOFF *obj_file = 60 llvm::dyn_cast_or_null<ObjectFilePECOFF>(module_sp->GetObjectFile()); 61 if (!obj_file) 62 return nullptr; 63 64 lldb_private::UUID uuid = obj_file->GetUUID(); 65 if (!uuid) 66 return nullptr; 67 68 // If the main object file already contains debug info, then we are done. 69 if (obj_file->GetSectionList()->FindSectionByType( 70 lldb::eSectionTypeDWARFDebugInfo, true)) 71 return nullptr; 72 73 // If the module specified a filespec, use that. 74 FileSpec fspec = module_sp->GetSymbolFileFileSpec(); 75 // Otherwise, try gnu_debuglink, if one exists. 76 if (!fspec) 77 fspec = obj_file->GetDebugLink().value_or(FileSpec()); 78 79 LLDB_SCOPED_TIMERF("SymbolVendorPECOFF::CreateInstance (module = %s)", 80 module_sp->GetFileSpec().GetPath().c_str()); 81 82 ModuleSpec module_spec; 83 84 module_spec.GetFileSpec() = obj_file->GetFileSpec(); 85 FileSystem::Instance().Resolve(module_spec.GetFileSpec()); 86 module_spec.GetSymbolFileSpec() = fspec; 87 module_spec.GetUUID() = uuid; 88 FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); 89 FileSpec dsym_fspec = 90 Symbols::LocateExecutableSymbolFile(module_spec, search_paths); 91 if (!dsym_fspec) 92 return nullptr; 93 94 DataBufferSP dsym_file_data_sp; 95 lldb::offset_t dsym_file_data_offset = 0; 96 ObjectFileSP dsym_objfile_sp = ObjectFile::FindPlugin( 97 module_sp, &dsym_fspec, 0, FileSystem::Instance().GetByteSize(dsym_fspec), 98 dsym_file_data_sp, dsym_file_data_offset); 99 if (!dsym_objfile_sp) 100 return nullptr; 101 102 // This objfile is for debugging purposes. 103 dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo); 104 105 SymbolVendorPECOFF *symbol_vendor = new SymbolVendorPECOFF(module_sp); 106 107 // Get the module unified section list and add our debug sections to 108 // that. 109 SectionList *module_section_list = module_sp->GetSectionList(); 110 SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList(); 111 if (!objfile_section_list || !module_section_list) 112 return nullptr; 113 114 static const SectionType g_sections[] = { 115 eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAranges, 116 eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo, 117 eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc, 118 eSectionTypeDWARFDebugLocLists, eSectionTypeDWARFDebugMacInfo, 119 eSectionTypeDWARFDebugNames, eSectionTypeDWARFDebugPubNames, 120 eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges, 121 eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugTypes, 122 }; 123 for (SectionType section_type : g_sections) { 124 if (SectionSP section_sp = 125 objfile_section_list->FindSectionByType(section_type, true)) { 126 if (SectionSP module_section_sp = 127 module_section_list->FindSectionByType(section_type, true)) 128 module_section_list->ReplaceSection(module_section_sp->GetID(), 129 section_sp); 130 else 131 module_section_list->AddSection(section_sp); 132 } 133 } 134 135 symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp); 136 return symbol_vendor; 137 } 138