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