xref: /llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp (revision b8885926f8115d5fe2c06907e066cae061d5f230)
1242e1e99SZequan Wu //===-- ObjectFilePDB.cpp -------------------------------------------------===//
2242e1e99SZequan Wu //
3242e1e99SZequan Wu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4242e1e99SZequan Wu // See https://llvm.org/LICENSE.txt for license information.
5242e1e99SZequan Wu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6242e1e99SZequan Wu //
7242e1e99SZequan Wu //===----------------------------------------------------------------------===//
8242e1e99SZequan Wu 
9242e1e99SZequan Wu #include "ObjectFilePDB.h"
10242e1e99SZequan Wu #include "lldb/Core/Module.h"
11242e1e99SZequan Wu #include "lldb/Core/ModuleSpec.h"
12242e1e99SZequan Wu #include "lldb/Core/PluginManager.h"
13242e1e99SZequan Wu #include "lldb/Core/Section.h"
14242e1e99SZequan Wu #include "lldb/Utility/StreamString.h"
15242e1e99SZequan Wu #include "llvm/BinaryFormat/Magic.h"
16242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
17242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
18242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
19242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
20242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/PDB.h"
21242e1e99SZequan Wu #include "llvm/Support/BinaryByteStream.h"
22242e1e99SZequan Wu 
23242e1e99SZequan Wu using namespace lldb;
24242e1e99SZequan Wu using namespace lldb_private;
25242e1e99SZequan Wu using namespace llvm::pdb;
26242e1e99SZequan Wu using namespace llvm::codeview;
27242e1e99SZequan Wu 
LLDB_PLUGIN_DEFINE(ObjectFilePDB)28242e1e99SZequan Wu LLDB_PLUGIN_DEFINE(ObjectFilePDB)
29242e1e99SZequan Wu 
30cb9a7c22SZequan Wu static UUID GetPDBUUID(InfoStream &IS, DbiStream &DS) {
314348e0eeSZequan Wu   UUID::CvRecordPdb70 debug_info;
324348e0eeSZequan Wu   memcpy(&debug_info.Uuid, IS.getGuid().Guid, sizeof(debug_info.Uuid));
33cb9a7c22SZequan Wu   debug_info.Age = DS.getAge();
345ad6ed0eSJim Ingham   return UUID(debug_info);
35242e1e99SZequan Wu }
36242e1e99SZequan Wu 
37242e1e99SZequan Wu char ObjectFilePDB::ID;
38242e1e99SZequan Wu 
Initialize()39242e1e99SZequan Wu void ObjectFilePDB::Initialize() {
40242e1e99SZequan Wu   PluginManager::RegisterPlugin(GetPluginNameStatic(),
41242e1e99SZequan Wu                                 GetPluginDescriptionStatic(), CreateInstance,
42242e1e99SZequan Wu                                 CreateMemoryInstance, GetModuleSpecifications);
43242e1e99SZequan Wu }
44242e1e99SZequan Wu 
Terminate()45242e1e99SZequan Wu void ObjectFilePDB::Terminate() {
46242e1e99SZequan Wu   PluginManager::UnregisterPlugin(CreateInstance);
47242e1e99SZequan Wu }
48242e1e99SZequan Wu 
GetArchitecture()49242e1e99SZequan Wu ArchSpec ObjectFilePDB::GetArchitecture() {
50242e1e99SZequan Wu   auto dbi_stream = m_file_up->getPDBDbiStream();
51242e1e99SZequan Wu   if (!dbi_stream) {
52242e1e99SZequan Wu     llvm::consumeError(dbi_stream.takeError());
53242e1e99SZequan Wu     return ArchSpec();
54242e1e99SZequan Wu   }
55242e1e99SZequan Wu 
56242e1e99SZequan Wu   PDB_Machine machine = dbi_stream->getMachineType();
57242e1e99SZequan Wu   switch (machine) {
58242e1e99SZequan Wu   default:
59242e1e99SZequan Wu     break;
60242e1e99SZequan Wu   case PDB_Machine::Amd64:
61242e1e99SZequan Wu   case PDB_Machine::x86:
62242e1e99SZequan Wu   case PDB_Machine::PowerPC:
63242e1e99SZequan Wu   case PDB_Machine::PowerPCFP:
64242e1e99SZequan Wu   case PDB_Machine::Arm:
65242e1e99SZequan Wu   case PDB_Machine::ArmNT:
66242e1e99SZequan Wu   case PDB_Machine::Thumb:
67242e1e99SZequan Wu   case PDB_Machine::Arm64:
68242e1e99SZequan Wu     ArchSpec arch;
69242e1e99SZequan Wu     arch.SetArchitecture(eArchTypeCOFF, static_cast<int>(machine),
70242e1e99SZequan Wu                          LLDB_INVALID_CPUTYPE);
71242e1e99SZequan Wu     return arch;
72242e1e99SZequan Wu   }
73242e1e99SZequan Wu   return ArchSpec();
74242e1e99SZequan Wu }
75242e1e99SZequan Wu 
initPDBFile()76242e1e99SZequan Wu bool ObjectFilePDB::initPDBFile() {
77242e1e99SZequan Wu   m_file_up = loadPDBFile(m_file.GetPath(), m_allocator);
78242e1e99SZequan Wu   if (!m_file_up)
79242e1e99SZequan Wu     return false;
80242e1e99SZequan Wu   auto info_stream = m_file_up->getPDBInfoStream();
81242e1e99SZequan Wu   if (!info_stream) {
82242e1e99SZequan Wu     llvm::consumeError(info_stream.takeError());
83242e1e99SZequan Wu     return false;
84242e1e99SZequan Wu   }
85cb9a7c22SZequan Wu   auto dbi_stream = m_file_up->getPDBDbiStream();
86cb9a7c22SZequan Wu   if (!dbi_stream) {
87cb9a7c22SZequan Wu     llvm::consumeError(dbi_stream.takeError());
88cb9a7c22SZequan Wu     return false;
89cb9a7c22SZequan Wu   }
90cb9a7c22SZequan Wu   m_uuid = GetPDBUUID(*info_stream, *dbi_stream);
91242e1e99SZequan Wu   return true;
92242e1e99SZequan Wu }
93242e1e99SZequan Wu 
94242e1e99SZequan Wu ObjectFile *
CreateInstance(const ModuleSP & module_sp,DataBufferSP data_sp,offset_t data_offset,const FileSpec * file,offset_t file_offset,offset_t length)95c69307e5SJonas Devlieghere ObjectFilePDB::CreateInstance(const ModuleSP &module_sp, DataBufferSP data_sp,
96242e1e99SZequan Wu                               offset_t data_offset, const FileSpec *file,
97242e1e99SZequan Wu                               offset_t file_offset, offset_t length) {
98242e1e99SZequan Wu   auto objfile_up = std::make_unique<ObjectFilePDB>(
99242e1e99SZequan Wu       module_sp, data_sp, data_offset, file, file_offset, length);
100242e1e99SZequan Wu   if (!objfile_up->initPDBFile())
101242e1e99SZequan Wu     return nullptr;
102242e1e99SZequan Wu   return objfile_up.release();
103242e1e99SZequan Wu }
104242e1e99SZequan Wu 
CreateMemoryInstance(const ModuleSP & module_sp,WritableDataBufferSP data_sp,const ProcessSP & process_sp,addr_t header_addr)105242e1e99SZequan Wu ObjectFile *ObjectFilePDB::CreateMemoryInstance(const ModuleSP &module_sp,
106f2ea125eSJonas Devlieghere                                                 WritableDataBufferSP data_sp,
107242e1e99SZequan Wu                                                 const ProcessSP &process_sp,
108242e1e99SZequan Wu                                                 addr_t header_addr) {
109242e1e99SZequan Wu   return nullptr;
110242e1e99SZequan Wu }
111242e1e99SZequan Wu 
GetModuleSpecifications(const FileSpec & file,DataBufferSP & data_sp,offset_t data_offset,offset_t file_offset,offset_t length,ModuleSpecList & specs)112242e1e99SZequan Wu size_t ObjectFilePDB::GetModuleSpecifications(
113242e1e99SZequan Wu     const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
114242e1e99SZequan Wu     offset_t file_offset, offset_t length, ModuleSpecList &specs) {
115242e1e99SZequan Wu   const size_t initial_count = specs.GetSize();
116242e1e99SZequan Wu   ModuleSpec module_spec(file);
117242e1e99SZequan Wu   llvm::BumpPtrAllocator allocator;
118242e1e99SZequan Wu   std::unique_ptr<PDBFile> pdb_file = loadPDBFile(file.GetPath(), allocator);
119242e1e99SZequan Wu   if (!pdb_file)
120242e1e99SZequan Wu     return initial_count;
121242e1e99SZequan Wu 
122242e1e99SZequan Wu   auto info_stream = pdb_file->getPDBInfoStream();
123242e1e99SZequan Wu   if (!info_stream) {
124242e1e99SZequan Wu     llvm::consumeError(info_stream.takeError());
125242e1e99SZequan Wu     return initial_count;
126242e1e99SZequan Wu   }
127242e1e99SZequan Wu   auto dbi_stream = pdb_file->getPDBDbiStream();
128242e1e99SZequan Wu   if (!dbi_stream) {
129242e1e99SZequan Wu     llvm::consumeError(dbi_stream.takeError());
130242e1e99SZequan Wu     return initial_count;
131242e1e99SZequan Wu   }
132242e1e99SZequan Wu 
133242e1e99SZequan Wu   lldb_private::UUID &uuid = module_spec.GetUUID();
134cb9a7c22SZequan Wu   uuid = GetPDBUUID(*info_stream, *dbi_stream);
135242e1e99SZequan Wu 
136242e1e99SZequan Wu   ArchSpec &module_arch = module_spec.GetArchitecture();
137242e1e99SZequan Wu   switch (dbi_stream->getMachineType()) {
138242e1e99SZequan Wu   case PDB_Machine::Amd64:
139242e1e99SZequan Wu     module_arch.SetTriple("x86_64-pc-windows");
140242e1e99SZequan Wu     specs.Append(module_spec);
141242e1e99SZequan Wu     break;
142242e1e99SZequan Wu   case PDB_Machine::x86:
143242e1e99SZequan Wu     module_arch.SetTriple("i386-pc-windows");
144242e1e99SZequan Wu     specs.Append(module_spec);
145242e1e99SZequan Wu     break;
146242e1e99SZequan Wu   case PDB_Machine::ArmNT:
147242e1e99SZequan Wu     module_arch.SetTriple("armv7-pc-windows");
148242e1e99SZequan Wu     specs.Append(module_spec);
149242e1e99SZequan Wu     break;
150242e1e99SZequan Wu   case PDB_Machine::Arm64:
151242e1e99SZequan Wu     module_arch.SetTriple("aarch64-pc-windows");
152242e1e99SZequan Wu     specs.Append(module_spec);
153242e1e99SZequan Wu     break;
154242e1e99SZequan Wu   default:
155242e1e99SZequan Wu     break;
156242e1e99SZequan Wu   }
157242e1e99SZequan Wu 
158242e1e99SZequan Wu   return specs.GetSize() - initial_count;
159242e1e99SZequan Wu }
160242e1e99SZequan Wu 
ObjectFilePDB(const ModuleSP & module_sp,DataBufferSP & data_sp,offset_t data_offset,const FileSpec * file,offset_t offset,offset_t length)161242e1e99SZequan Wu ObjectFilePDB::ObjectFilePDB(const ModuleSP &module_sp, DataBufferSP &data_sp,
162242e1e99SZequan Wu                              offset_t data_offset, const FileSpec *file,
163242e1e99SZequan Wu                              offset_t offset, offset_t length)
164242e1e99SZequan Wu     : ObjectFile(module_sp, file, offset, length, data_sp, data_offset) {}
165242e1e99SZequan Wu 
166242e1e99SZequan Wu std::unique_ptr<PDBFile>
loadPDBFile(std::string PdbPath,llvm::BumpPtrAllocator & Allocator)167242e1e99SZequan Wu ObjectFilePDB::loadPDBFile(std::string PdbPath,
168242e1e99SZequan Wu                            llvm::BumpPtrAllocator &Allocator) {
169242e1e99SZequan Wu   llvm::file_magic magic;
170242e1e99SZequan Wu   auto ec = llvm::identify_magic(PdbPath, magic);
171242e1e99SZequan Wu   if (ec || magic != llvm::file_magic::pdb)
172242e1e99SZequan Wu     return nullptr;
173242e1e99SZequan Wu   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer =
174c83cd8feSAbhina Sreeskantharajan       llvm::MemoryBuffer::getFile(PdbPath, /*IsText=*/false,
175242e1e99SZequan Wu                                   /*RequiresNullTerminator=*/false);
176242e1e99SZequan Wu   if (!ErrorOrBuffer)
177242e1e99SZequan Wu     return nullptr;
178242e1e99SZequan Wu   std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
179242e1e99SZequan Wu 
180242e1e99SZequan Wu   llvm::StringRef Path = Buffer->getBufferIdentifier();
181242e1e99SZequan Wu   auto Stream = std::make_unique<llvm::MemoryBufferByteStream>(
182*b8885926SKazu Hirata       std::move(Buffer), llvm::endianness::little);
183242e1e99SZequan Wu 
184242e1e99SZequan Wu   auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator);
185242e1e99SZequan Wu   if (auto EC = File->parseFileHeaders()) {
186242e1e99SZequan Wu     llvm::consumeError(std::move(EC));
187242e1e99SZequan Wu     return nullptr;
188242e1e99SZequan Wu   }
189242e1e99SZequan Wu   if (auto EC = File->parseStreamData()) {
190242e1e99SZequan Wu     llvm::consumeError(std::move(EC));
191242e1e99SZequan Wu     return nullptr;
192242e1e99SZequan Wu   }
193242e1e99SZequan Wu 
194242e1e99SZequan Wu   return File;
195242e1e99SZequan Wu }
196