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