Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
39642 views
1
//===-- ObjectFilePDB.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 "ObjectFilePDB.h"
10
#include "lldb/Core/Module.h"
11
#include "lldb/Core/ModuleSpec.h"
12
#include "lldb/Core/PluginManager.h"
13
#include "lldb/Core/Section.h"
14
#include "lldb/Utility/StreamString.h"
15
#include "llvm/BinaryFormat/Magic.h"
16
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
17
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
18
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
19
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
20
#include "llvm/DebugInfo/PDB/PDB.h"
21
#include "llvm/Support/BinaryByteStream.h"
22
23
using namespace lldb;
24
using namespace lldb_private;
25
using namespace llvm::pdb;
26
using namespace llvm::codeview;
27
28
LLDB_PLUGIN_DEFINE(ObjectFilePDB)
29
30
static UUID GetPDBUUID(InfoStream &IS, DbiStream &DS) {
31
UUID::CvRecordPdb70 debug_info;
32
memcpy(&debug_info.Uuid, IS.getGuid().Guid, sizeof(debug_info.Uuid));
33
debug_info.Age = DS.getAge();
34
return UUID(debug_info);
35
}
36
37
char ObjectFilePDB::ID;
38
39
void ObjectFilePDB::Initialize() {
40
PluginManager::RegisterPlugin(GetPluginNameStatic(),
41
GetPluginDescriptionStatic(), CreateInstance,
42
CreateMemoryInstance, GetModuleSpecifications);
43
}
44
45
void ObjectFilePDB::Terminate() {
46
PluginManager::UnregisterPlugin(CreateInstance);
47
}
48
49
ArchSpec ObjectFilePDB::GetArchitecture() {
50
auto dbi_stream = m_file_up->getPDBDbiStream();
51
if (!dbi_stream) {
52
llvm::consumeError(dbi_stream.takeError());
53
return ArchSpec();
54
}
55
56
PDB_Machine machine = dbi_stream->getMachineType();
57
switch (machine) {
58
default:
59
break;
60
case PDB_Machine::Amd64:
61
case PDB_Machine::x86:
62
case PDB_Machine::PowerPC:
63
case PDB_Machine::PowerPCFP:
64
case PDB_Machine::Arm:
65
case PDB_Machine::ArmNT:
66
case PDB_Machine::Thumb:
67
case PDB_Machine::Arm64:
68
ArchSpec arch;
69
arch.SetArchitecture(eArchTypeCOFF, static_cast<int>(machine),
70
LLDB_INVALID_CPUTYPE);
71
return arch;
72
}
73
return ArchSpec();
74
}
75
76
bool ObjectFilePDB::initPDBFile() {
77
m_file_up = loadPDBFile(m_file.GetPath(), m_allocator);
78
if (!m_file_up)
79
return false;
80
auto info_stream = m_file_up->getPDBInfoStream();
81
if (!info_stream) {
82
llvm::consumeError(info_stream.takeError());
83
return false;
84
}
85
auto dbi_stream = m_file_up->getPDBDbiStream();
86
if (!dbi_stream) {
87
llvm::consumeError(dbi_stream.takeError());
88
return false;
89
}
90
m_uuid = GetPDBUUID(*info_stream, *dbi_stream);
91
return true;
92
}
93
94
ObjectFile *
95
ObjectFilePDB::CreateInstance(const ModuleSP &module_sp, DataBufferSP data_sp,
96
offset_t data_offset, const FileSpec *file,
97
offset_t file_offset, offset_t length) {
98
auto objfile_up = std::make_unique<ObjectFilePDB>(
99
module_sp, data_sp, data_offset, file, file_offset, length);
100
if (!objfile_up->initPDBFile())
101
return nullptr;
102
return objfile_up.release();
103
}
104
105
ObjectFile *ObjectFilePDB::CreateMemoryInstance(const ModuleSP &module_sp,
106
WritableDataBufferSP data_sp,
107
const ProcessSP &process_sp,
108
addr_t header_addr) {
109
return nullptr;
110
}
111
112
size_t ObjectFilePDB::GetModuleSpecifications(
113
const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
114
offset_t file_offset, offset_t length, ModuleSpecList &specs) {
115
const size_t initial_count = specs.GetSize();
116
ModuleSpec module_spec(file);
117
llvm::BumpPtrAllocator allocator;
118
std::unique_ptr<PDBFile> pdb_file = loadPDBFile(file.GetPath(), allocator);
119
if (!pdb_file)
120
return initial_count;
121
122
auto info_stream = pdb_file->getPDBInfoStream();
123
if (!info_stream) {
124
llvm::consumeError(info_stream.takeError());
125
return initial_count;
126
}
127
auto dbi_stream = pdb_file->getPDBDbiStream();
128
if (!dbi_stream) {
129
llvm::consumeError(dbi_stream.takeError());
130
return initial_count;
131
}
132
133
lldb_private::UUID &uuid = module_spec.GetUUID();
134
uuid = GetPDBUUID(*info_stream, *dbi_stream);
135
136
ArchSpec &module_arch = module_spec.GetArchitecture();
137
switch (dbi_stream->getMachineType()) {
138
case PDB_Machine::Amd64:
139
module_arch.SetTriple("x86_64-pc-windows");
140
specs.Append(module_spec);
141
break;
142
case PDB_Machine::x86:
143
module_arch.SetTriple("i386-pc-windows");
144
specs.Append(module_spec);
145
break;
146
case PDB_Machine::ArmNT:
147
module_arch.SetTriple("armv7-pc-windows");
148
specs.Append(module_spec);
149
break;
150
case PDB_Machine::Arm64:
151
module_arch.SetTriple("aarch64-pc-windows");
152
specs.Append(module_spec);
153
break;
154
default:
155
break;
156
}
157
158
return specs.GetSize() - initial_count;
159
}
160
161
ObjectFilePDB::ObjectFilePDB(const ModuleSP &module_sp, DataBufferSP &data_sp,
162
offset_t data_offset, const FileSpec *file,
163
offset_t offset, offset_t length)
164
: ObjectFile(module_sp, file, offset, length, data_sp, data_offset) {}
165
166
std::unique_ptr<PDBFile>
167
ObjectFilePDB::loadPDBFile(std::string PdbPath,
168
llvm::BumpPtrAllocator &Allocator) {
169
llvm::file_magic magic;
170
auto ec = llvm::identify_magic(PdbPath, magic);
171
if (ec || magic != llvm::file_magic::pdb)
172
return nullptr;
173
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer =
174
llvm::MemoryBuffer::getFile(PdbPath, /*IsText=*/false,
175
/*RequiresNullTerminator=*/false);
176
if (!ErrorOrBuffer)
177
return nullptr;
178
std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
179
180
llvm::StringRef Path = Buffer->getBufferIdentifier();
181
auto Stream = std::make_unique<llvm::MemoryBufferByteStream>(
182
std::move(Buffer), llvm::endianness::little);
183
184
auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator);
185
if (auto EC = File->parseFileHeaders()) {
186
llvm::consumeError(std::move(EC));
187
return nullptr;
188
}
189
if (auto EC = File->parseStreamData()) {
190
llvm::consumeError(std::move(EC));
191
return nullptr;
192
}
193
194
return File;
195
}
196
197