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(name: GetPluginNameStatic(),
35 description: GetPluginDescriptionStatic(), create_callback: CreateInstance);
36}
37
38void SymbolVendorPECOFF::Terminate() {
39 PluginManager::UnregisterPlugin(create_callback: 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>(Val: 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 sect_type: lldb::eSectionTypeDWARFDebugInfo, check_children: 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(u: 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(file_spec&: 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, default_search_paths: 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, file_spec: &dsym_fspec, file_offset: 0, file_size: FileSystem::Instance().GetByteSize(file_spec: dsym_fspec),
97 data_sp&: dsym_file_data_sp, data_offset&: 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(sect_type: section_type, check_children: true)) {
123 if (SectionSP module_section_sp =
124 module_section_list->FindSectionByType(sect_type: section_type, check_children: true))
125 module_section_list->ReplaceSection(sect_id: 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(objfile_sp: dsym_objfile_sp);
134 return symbol_vendor;
135}
136

source code of lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp