xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
181ad6265SDimitry Andric //===-- SymbolVendorPECOFF.cpp --------------------------------------------===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #include "SymbolVendorPECOFF.h"
1081ad6265SDimitry Andric 
1181ad6265SDimitry Andric #include <cstring>
1281ad6265SDimitry Andric 
1381ad6265SDimitry Andric #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
1481ad6265SDimitry Andric #include "lldb/Core/Module.h"
1581ad6265SDimitry Andric #include "lldb/Core/ModuleSpec.h"
1681ad6265SDimitry Andric #include "lldb/Core/PluginManager.h"
1781ad6265SDimitry Andric #include "lldb/Core/Section.h"
1881ad6265SDimitry Andric #include "lldb/Host/Host.h"
1981ad6265SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
2081ad6265SDimitry Andric #include "lldb/Target/Target.h"
2181ad6265SDimitry Andric #include "lldb/Utility/StreamString.h"
2281ad6265SDimitry Andric #include "lldb/Utility/Timer.h"
2381ad6265SDimitry Andric 
2481ad6265SDimitry Andric using namespace lldb;
2581ad6265SDimitry Andric using namespace lldb_private;
2681ad6265SDimitry Andric 
LLDB_PLUGIN_DEFINE(SymbolVendorPECOFF)2781ad6265SDimitry Andric LLDB_PLUGIN_DEFINE(SymbolVendorPECOFF)
2881ad6265SDimitry Andric 
2981ad6265SDimitry Andric // SymbolVendorPECOFF constructor
3081ad6265SDimitry Andric SymbolVendorPECOFF::SymbolVendorPECOFF(const lldb::ModuleSP &module_sp)
3181ad6265SDimitry Andric     : SymbolVendor(module_sp) {}
3281ad6265SDimitry Andric 
Initialize()3381ad6265SDimitry Andric void SymbolVendorPECOFF::Initialize() {
3481ad6265SDimitry Andric   PluginManager::RegisterPlugin(GetPluginNameStatic(),
3581ad6265SDimitry Andric                                 GetPluginDescriptionStatic(), CreateInstance);
3681ad6265SDimitry Andric }
3781ad6265SDimitry Andric 
Terminate()3881ad6265SDimitry Andric void SymbolVendorPECOFF::Terminate() {
3981ad6265SDimitry Andric   PluginManager::UnregisterPlugin(CreateInstance);
4081ad6265SDimitry Andric }
4181ad6265SDimitry Andric 
GetPluginDescriptionStatic()4281ad6265SDimitry Andric llvm::StringRef SymbolVendorPECOFF::GetPluginDescriptionStatic() {
4381ad6265SDimitry Andric   return "Symbol vendor for PE/COFF that looks for dSYM files that match "
4481ad6265SDimitry Andric          "executables.";
4581ad6265SDimitry Andric }
4681ad6265SDimitry Andric 
4781ad6265SDimitry Andric // CreateInstance
4881ad6265SDimitry Andric //
4981ad6265SDimitry Andric // Platforms can register a callback to use when creating symbol vendors to
5081ad6265SDimitry Andric // allow for complex debug information file setups, and to also allow for
5181ad6265SDimitry Andric // finding separate debug information files.
5281ad6265SDimitry Andric SymbolVendor *
CreateInstance(const lldb::ModuleSP & module_sp,lldb_private::Stream * feedback_strm)5381ad6265SDimitry Andric SymbolVendorPECOFF::CreateInstance(const lldb::ModuleSP &module_sp,
5481ad6265SDimitry Andric                                    lldb_private::Stream *feedback_strm) {
5581ad6265SDimitry Andric   if (!module_sp)
5681ad6265SDimitry Andric     return nullptr;
5781ad6265SDimitry Andric 
5881ad6265SDimitry Andric   ObjectFilePECOFF *obj_file =
5981ad6265SDimitry Andric       llvm::dyn_cast_or_null<ObjectFilePECOFF>(module_sp->GetObjectFile());
6081ad6265SDimitry Andric   if (!obj_file)
6181ad6265SDimitry Andric     return nullptr;
6281ad6265SDimitry Andric 
6381ad6265SDimitry Andric   lldb_private::UUID uuid = obj_file->GetUUID();
6481ad6265SDimitry Andric   if (!uuid)
6581ad6265SDimitry Andric     return nullptr;
6681ad6265SDimitry Andric 
6781ad6265SDimitry Andric   // If the main object file already contains debug info, then we are done.
6881ad6265SDimitry Andric   if (obj_file->GetSectionList()->FindSectionByType(
6981ad6265SDimitry Andric           lldb::eSectionTypeDWARFDebugInfo, true))
7081ad6265SDimitry Andric     return nullptr;
7181ad6265SDimitry Andric 
7281ad6265SDimitry Andric   // If the module specified a filespec, use that.
7381ad6265SDimitry Andric   FileSpec fspec = module_sp->GetSymbolFileFileSpec();
7481ad6265SDimitry Andric   // Otherwise, try gnu_debuglink, if one exists.
7581ad6265SDimitry Andric   if (!fspec)
7681ad6265SDimitry Andric     fspec = obj_file->GetDebugLink().value_or(FileSpec());
7781ad6265SDimitry Andric 
7881ad6265SDimitry Andric   LLDB_SCOPED_TIMERF("SymbolVendorPECOFF::CreateInstance (module = %s)",
7981ad6265SDimitry Andric                      module_sp->GetFileSpec().GetPath().c_str());
8081ad6265SDimitry Andric 
8181ad6265SDimitry Andric   ModuleSpec module_spec;
8281ad6265SDimitry Andric 
8381ad6265SDimitry Andric   module_spec.GetFileSpec() = obj_file->GetFileSpec();
8481ad6265SDimitry Andric   FileSystem::Instance().Resolve(module_spec.GetFileSpec());
8581ad6265SDimitry Andric   module_spec.GetSymbolFileSpec() = fspec;
8681ad6265SDimitry Andric   module_spec.GetUUID() = uuid;
8781ad6265SDimitry Andric   FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
8881ad6265SDimitry Andric   FileSpec dsym_fspec =
89*5f757f3fSDimitry Andric       PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
9081ad6265SDimitry Andric   if (!dsym_fspec)
9181ad6265SDimitry Andric     return nullptr;
9281ad6265SDimitry Andric 
9381ad6265SDimitry Andric   DataBufferSP dsym_file_data_sp;
9481ad6265SDimitry Andric   lldb::offset_t dsym_file_data_offset = 0;
9581ad6265SDimitry Andric   ObjectFileSP dsym_objfile_sp = ObjectFile::FindPlugin(
9681ad6265SDimitry Andric       module_sp, &dsym_fspec, 0, FileSystem::Instance().GetByteSize(dsym_fspec),
9781ad6265SDimitry Andric       dsym_file_data_sp, dsym_file_data_offset);
9881ad6265SDimitry Andric   if (!dsym_objfile_sp)
9981ad6265SDimitry Andric     return nullptr;
10081ad6265SDimitry Andric 
10181ad6265SDimitry Andric   // This objfile is for debugging purposes.
10281ad6265SDimitry Andric   dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo);
10381ad6265SDimitry Andric 
10481ad6265SDimitry Andric   // Get the module unified section list and add our debug sections to
10581ad6265SDimitry Andric   // that.
10681ad6265SDimitry Andric   SectionList *module_section_list = module_sp->GetSectionList();
10781ad6265SDimitry Andric   SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList();
10881ad6265SDimitry Andric   if (!objfile_section_list || !module_section_list)
10981ad6265SDimitry Andric     return nullptr;
11081ad6265SDimitry Andric 
11181ad6265SDimitry Andric   static const SectionType g_sections[] = {
11281ad6265SDimitry Andric       eSectionTypeDWARFDebugAbbrev,   eSectionTypeDWARFDebugAranges,
11381ad6265SDimitry Andric       eSectionTypeDWARFDebugFrame,    eSectionTypeDWARFDebugInfo,
11481ad6265SDimitry Andric       eSectionTypeDWARFDebugLine,     eSectionTypeDWARFDebugLoc,
11581ad6265SDimitry Andric       eSectionTypeDWARFDebugLocLists, eSectionTypeDWARFDebugMacInfo,
11681ad6265SDimitry Andric       eSectionTypeDWARFDebugNames,    eSectionTypeDWARFDebugPubNames,
11781ad6265SDimitry Andric       eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,
11881ad6265SDimitry Andric       eSectionTypeDWARFDebugStr,      eSectionTypeDWARFDebugTypes,
11981ad6265SDimitry Andric   };
12081ad6265SDimitry Andric   for (SectionType section_type : g_sections) {
12181ad6265SDimitry Andric     if (SectionSP section_sp =
12281ad6265SDimitry Andric             objfile_section_list->FindSectionByType(section_type, true)) {
12381ad6265SDimitry Andric       if (SectionSP module_section_sp =
12481ad6265SDimitry Andric               module_section_list->FindSectionByType(section_type, true))
12581ad6265SDimitry Andric         module_section_list->ReplaceSection(module_section_sp->GetID(),
12681ad6265SDimitry Andric                                             section_sp);
12781ad6265SDimitry Andric       else
12881ad6265SDimitry Andric         module_section_list->AddSection(section_sp);
12981ad6265SDimitry Andric     }
13081ad6265SDimitry Andric   }
13181ad6265SDimitry Andric 
132bdd1243dSDimitry Andric   SymbolVendorPECOFF *symbol_vendor = new SymbolVendorPECOFF(module_sp);
13381ad6265SDimitry Andric   symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp);
13481ad6265SDimitry Andric   return symbol_vendor;
13581ad6265SDimitry Andric }
136