LLDB  mainline
ObjectFilePDB.cpp
Go to the documentation of this file.
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"
13 #include "lldb/Core/Section.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 
29 
30 static UUID GetPDBUUID(InfoStream &IS) {
31  UUID::CvRecordPdb70 debug_info;
32  memcpy(&debug_info.Uuid, IS.getGuid().Guid, sizeof(debug_info.Uuid));
33  debug_info.Age = IS.getAge();
34  return UUID::fromCvRecord(debug_info);
35 }
36 
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 ConstString ObjectFilePDB::GetPluginNameStatic() {
50  static ConstString g_name("pdb");
51  return g_name;
52 }
53 
54 ArchSpec ObjectFilePDB::GetArchitecture() {
55  auto dbi_stream = m_file_up->getPDBDbiStream();
56  if (!dbi_stream) {
57  llvm::consumeError(dbi_stream.takeError());
58  return ArchSpec();
59  }
60 
61  PDB_Machine machine = dbi_stream->getMachineType();
62  switch (machine) {
63  default:
64  break;
65  case PDB_Machine::Amd64:
66  case PDB_Machine::x86:
67  case PDB_Machine::PowerPC:
68  case PDB_Machine::PowerPCFP:
69  case PDB_Machine::Arm:
70  case PDB_Machine::ArmNT:
71  case PDB_Machine::Thumb:
72  case PDB_Machine::Arm64:
73  ArchSpec arch;
74  arch.SetArchitecture(eArchTypeCOFF, static_cast<int>(machine),
76  return arch;
77  }
78  return ArchSpec();
79 }
80 
81 bool ObjectFilePDB::initPDBFile() {
82  m_file_up = loadPDBFile(m_file.GetPath(), m_allocator);
83  if (!m_file_up)
84  return false;
85  auto info_stream = m_file_up->getPDBInfoStream();
86  if (!info_stream) {
87  llvm::consumeError(info_stream.takeError());
88  return false;
89  }
90  m_uuid = GetPDBUUID(*info_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  DataBufferSP &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);
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  module_arch.SetTriple("i686-pc-windows");
146  specs.Append(module_spec);
147  break;
148  case PDB_Machine::ArmNT:
149  module_arch.SetTriple("armv7-pc-windows");
150  specs.Append(module_spec);
151  break;
152  case PDB_Machine::Arm64:
153  module_arch.SetTriple("aarch64-pc-windows");
154  specs.Append(module_spec);
155  break;
156  default:
157  break;
158  }
159 
160  return specs.GetSize() - initial_count;
161 }
162 
163 ObjectFilePDB::ObjectFilePDB(const ModuleSP &module_sp, DataBufferSP &data_sp,
164  offset_t data_offset, const FileSpec *file,
165  offset_t offset, offset_t length)
166  : ObjectFile(module_sp, file, offset, length, data_sp, data_offset) {}
167 
168 std::unique_ptr<PDBFile>
170  llvm::BumpPtrAllocator &Allocator) {
171  llvm::file_magic magic;
172  auto ec = llvm::identify_magic(PdbPath, magic);
173  if (ec || magic != llvm::file_magic::pdb)
174  return nullptr;
175  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer =
176  llvm::MemoryBuffer::getFile(PdbPath, /*IsText=*/false,
177  /*RequiresNullTerminator=*/false);
178  if (!ErrorOrBuffer)
179  return nullptr;
180  std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
181 
182  llvm::StringRef Path = Buffer->getBufferIdentifier();
183  auto Stream = std::make_unique<llvm::MemoryBufferByteStream>(
184  std::move(Buffer), llvm::support::little);
185 
186  auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator);
187  if (auto EC = File->parseFileHeaders()) {
188  llvm::consumeError(std::move(EC));
189  return nullptr;
190  }
191  if (auto EC = File->parseStreamData()) {
192  llvm::consumeError(std::move(EC));
193  return nullptr;
194  }
195 
196  return File;
197 }
lldb_private::UUID::CvRecordPdb70::Age
llvm::support::ulittle32_t Age
Definition: UUID.h:36
lldb_private::UUID
Definition: UUID.h:23
lldb_private::ArchSpec
Definition: ArchSpec.h:33
lldb_private::eArchTypeCOFF
@ eArchTypeCOFF
Definition: lldb-private-enumerations.h:65
lldb_private::UUID::CvRecordPdb70::Uuid
struct lldb_private::UUID::CvRecordPdb70::@45 Uuid
ModuleSpec.h
lldb_private::ModuleSpecList
Definition: ModuleSpec.h:280
lldb_private::ModuleSpecList::Append
void Append(const ModuleSpec &spec)
Definition: ModuleSpec.h:313
Module.h
lldb::offset_t
uint64_t offset_t
Definition: lldb-types.h:87
lldb_private::Stream
Definition: Stream.h:28
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
LLDB_INVALID_CPUTYPE
#define LLDB_INVALID_CPUTYPE
Definition: lldb-defines.h:106
Section.h
lldb_private::ModuleSpec::GetUUID
UUID & GetUUID()
Definition: ModuleSpec.h:104
lldb_private::FileSpec
Definition: FileSpec.h:56
ID
static char ID
Definition: IRDynamicChecks.cpp:32
lldb_private::ArchSpec::SetTriple
bool SetTriple(const llvm::Triple &triple)
Architecture triple setter.
Definition: ArchSpec.cpp:739
StreamString.h
llvm::pdb
Definition: DWARFLocationExpression.h:21
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::File
Definition: File.h:34
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
GetPDBUUID
static UUID GetPDBUUID(InfoStream &IS)
Definition: ObjectFilePDB.cpp:30
lldb_private::ArchSpec::SetArchitecture
bool SetArchitecture(ArchitectureType arch_type, uint32_t cpu, uint32_t sub, uint32_t os=0)
Change the architecture object type, CPU type and OS type.
Definition: ArchSpec.cpp:843
lldb_private::ModuleSpec
Definition: ModuleSpec.h:26
lldb_private::UUID::CvRecordPdb70
Definition: UUID.h:29
lldb_private::ObjectFilePDB
Definition: ObjectFilePDB.h:19
ObjectFilePDB.h
PluginManager.h
lldb_private::ModuleSpec::GetArchitecture
ArchSpec & GetArchitecture()
Definition: ModuleSpec.h:94
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
llvm::codeview
Definition: DWARFLocationExpression.h:18
lldb_private::ObjectFilePDB::loadPDBFile
static std::unique_ptr< llvm::pdb::PDBFile > loadPDBFile(std::string PdbPath, llvm::BumpPtrAllocator &Allocator)
Definition: ObjectFilePDB.cpp:169
lldb_private::ModuleSpecList::GetSize
size_t GetSize() const
Definition: ModuleSpec.h:303
LLDB_PLUGIN_DEFINE
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
lldb_private::FileSpec::GetPath
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:348
lldb
Definition: SBAddress.h:15
lldb_private::ObjectFile
Definition: ObjectFile.h:58