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