Coverage Report

Created: 2022-01-25 06:29

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
Line
Count
Source (jump to first uncovered line)
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
2
static UUID GetPDBUUID(InfoStream &IS) {
31
2
  UUID::CvRecordPdb70 debug_info;
32
2
  memcpy(&debug_info.Uuid, IS.getGuid().Guid, sizeof(debug_info.Uuid));
33
2
  debug_info.Age = IS.getAge();
34
2
  return UUID::fromCvRecord(debug_info);
35
2
}
36
37
char ObjectFilePDB::ID;
38
39
3.44k
void ObjectFilePDB::Initialize() {
40
3.44k
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
41
3.44k
                                GetPluginDescriptionStatic(), CreateInstance,
42
3.44k
                                CreateMemoryInstance, GetModuleSpecifications);
43
3.44k
}
44
45
3.43k
void ObjectFilePDB::Terminate() {
46
3.43k
  PluginManager::UnregisterPlugin(CreateInstance);
47
3.43k
}
48
49
1
ArchSpec ObjectFilePDB::GetArchitecture() {
50
1
  auto dbi_stream = m_file_up->getPDBDbiStream();
51
1
  if (!dbi_stream) {
52
0
    llvm::consumeError(dbi_stream.takeError());
53
0
    return ArchSpec();
54
0
  }
55
56
1
  PDB_Machine machine = dbi_stream->getMachineType();
57
1
  switch (machine) {
58
0
  default:
59
0
    break;
60
1
  case PDB_Machine::Amd64:
61
1
  case PDB_Machine::x86:
62
1
  case PDB_Machine::PowerPC:
63
1
  case PDB_Machine::PowerPCFP:
64
1
  case PDB_Machine::Arm:
65
1
  case PDB_Machine::ArmNT:
66
1
  case PDB_Machine::Thumb:
67
1
  case PDB_Machine::Arm64:
68
1
    ArchSpec arch;
69
1
    arch.SetArchitecture(eArchTypeCOFF, static_cast<int>(machine),
70
1
                         LLDB_INVALID_CPUTYPE);
71
1
    return arch;
72
1
  }
73
0
  return ArchSpec();
74
1
}
75
76
226
bool ObjectFilePDB::initPDBFile() {
77
226
  m_file_up = loadPDBFile(m_file.GetPath(), m_allocator);
78
226
  if (!m_file_up)
79
225
    return false;
80
1
  auto info_stream = m_file_up->getPDBInfoStream();
81
1
  if (!info_stream) {
82
0
    llvm::consumeError(info_stream.takeError());
83
0
    return false;
84
0
  }
85
1
  m_uuid = GetPDBUUID(*info_stream);
86
1
  return true;
87
1
}
88
89
ObjectFile *
90
ObjectFilePDB::CreateInstance(const ModuleSP &module_sp, DataBufferSP &data_sp,
91
                              offset_t data_offset, const FileSpec *file,
92
226
                              offset_t file_offset, offset_t length) {
93
226
  auto objfile_up = std::make_unique<ObjectFilePDB>(
94
226
      module_sp, data_sp, data_offset, file, file_offset, length);
95
226
  if (!objfile_up->initPDBFile())
96
225
    return nullptr;
97
1
  return objfile_up.release();
98
226
}
99
100
ObjectFile *ObjectFilePDB::CreateMemoryInstance(const ModuleSP &module_sp,
101
                                                DataBufferSP &data_sp,
102
                                                const ProcessSP &process_sp,
103
2
                                                addr_t header_addr) {
104
2
  return nullptr;
105
2
}
106
107
size_t ObjectFilePDB::GetModuleSpecifications(
108
    const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
109
2.71k
    offset_t file_offset, offset_t length, ModuleSpecList &specs) {
110
2.71k
  const size_t initial_count = specs.GetSize();
111
2.71k
  ModuleSpec module_spec(file);
112
2.71k
  llvm::BumpPtrAllocator allocator;
113
2.71k
  std::unique_ptr<PDBFile> pdb_file = loadPDBFile(file.GetPath(), allocator);
114
2.71k
  if (!pdb_file)
115
2.70k
    return initial_count;
116
117
1
  auto info_stream = pdb_file->getPDBInfoStream();
118
1
  if (!info_stream) {
119
0
    llvm::consumeError(info_stream.takeError());
120
0
    return initial_count;
121
0
  }
122
1
  auto dbi_stream = pdb_file->getPDBDbiStream();
123
1
  if (!dbi_stream) {
124
0
    llvm::consumeError(dbi_stream.takeError());
125
0
    return initial_count;
126
0
  }
127
128
1
  lldb_private::UUID &uuid = module_spec.GetUUID();
129
1
  uuid = GetPDBUUID(*info_stream);
130
131
1
  ArchSpec &module_arch = module_spec.GetArchitecture();
132
1
  switch (dbi_stream->getMachineType()) {
133
1
  case PDB_Machine::Amd64:
134
1
    module_arch.SetTriple("x86_64-pc-windows");
135
1
    specs.Append(module_spec);
136
1
    break;
137
0
  case PDB_Machine::x86:
138
0
    module_arch.SetTriple("i386-pc-windows");
139
0
    specs.Append(module_spec);
140
0
    module_arch.SetTriple("i686-pc-windows");
141
0
    specs.Append(module_spec);
142
0
    break;
143
0
  case PDB_Machine::ArmNT:
144
0
    module_arch.SetTriple("armv7-pc-windows");
145
0
    specs.Append(module_spec);
146
0
    break;
147
0
  case PDB_Machine::Arm64:
148
0
    module_arch.SetTriple("aarch64-pc-windows");
149
0
    specs.Append(module_spec);
150
0
    break;
151
0
  default:
152
0
    break;
153
1
  }
154
155
1
  return specs.GetSize() - initial_count;
156
1
}
157
158
ObjectFilePDB::ObjectFilePDB(const ModuleSP &module_sp, DataBufferSP &data_sp,
159
                             offset_t data_offset, const FileSpec *file,
160
                             offset_t offset, offset_t length)
161
226
    : ObjectFile(module_sp, file, offset, length, data_sp, data_offset) {}
162
163
std::unique_ptr<PDBFile>
164
ObjectFilePDB::loadPDBFile(std::string PdbPath,
165
2.94k
                           llvm::BumpPtrAllocator &Allocator) {
166
2.94k
  llvm::file_magic magic;
167
2.94k
  auto ec = llvm::identify_magic(PdbPath, magic);
168
2.94k
  if (ec || 
magic != llvm::file_magic::pdb2.93k
)
169
2.94k
    return nullptr;
170
2
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer =
171
2
      llvm::MemoryBuffer::getFile(PdbPath, /*IsText=*/false,
172
2
                                  /*RequiresNullTerminator=*/false);
173
2
  if (!ErrorOrBuffer)
174
0
    return nullptr;
175
2
  std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
176
177
2
  llvm::StringRef Path = Buffer->getBufferIdentifier();
178
2
  auto Stream = std::make_unique<llvm::MemoryBufferByteStream>(
179
2
      std::move(Buffer), llvm::support::little);
180
181
2
  auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator);
182
2
  if (auto EC = File->parseFileHeaders()) {
183
0
    llvm::consumeError(std::move(EC));
184
0
    return nullptr;
185
0
  }
186
2
  if (auto EC = File->parseStreamData()) {
187
0
    llvm::consumeError(std::move(EC));
188
0
    return nullptr;
189
0
  }
190
191
2
  return File;
192
2
}