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/COFF/ObjectFileCOFF.cpp
39644 views
1
//===-- ObjectFileCOFF.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 "ObjectFileCOFF.h"
10
11
#include "lldb/Core/Module.h"
12
#include "lldb/Core/ModuleSpec.h"
13
#include "lldb/Core/PluginManager.h"
14
#include "lldb/Utility/LLDBLog.h"
15
16
#include "llvm/Support/Error.h"
17
#include "llvm/Support/FormatAdapters.h"
18
19
using namespace lldb;
20
using namespace lldb_private;
21
22
using namespace llvm;
23
using namespace llvm::object;
24
25
static bool IsCOFFObjectFile(const DataBufferSP &data) {
26
return identify_magic(toStringRef(data->GetData())) ==
27
file_magic::coff_object;
28
}
29
30
LLDB_PLUGIN_DEFINE(ObjectFileCOFF)
31
32
char ObjectFileCOFF::ID;
33
34
ObjectFileCOFF::~ObjectFileCOFF() = default;
35
36
void ObjectFileCOFF::Initialize() {
37
PluginManager::RegisterPlugin(GetPluginNameStatic(),
38
GetPluginDescriptionStatic(), CreateInstance,
39
CreateMemoryInstance, GetModuleSpecifications);
40
}
41
42
void ObjectFileCOFF::Terminate() {
43
PluginManager::UnregisterPlugin(CreateInstance);
44
}
45
46
lldb_private::ObjectFile *
47
ObjectFileCOFF::CreateInstance(const ModuleSP &module_sp, DataBufferSP data_sp,
48
offset_t data_offset, const FileSpec *file,
49
offset_t file_offset, offset_t length) {
50
Log *log = GetLog(LLDBLog::Object);
51
52
if (!data_sp) {
53
data_sp = MapFileData(*file, length, file_offset);
54
if (!data_sp) {
55
LLDB_LOG(log,
56
"Failed to create ObjectFileCOFF instance: cannot read file {0}",
57
file->GetPath());
58
return nullptr;
59
}
60
data_offset = 0;
61
}
62
63
assert(data_sp && "must have mapped file at this point");
64
65
if (!IsCOFFObjectFile(data_sp))
66
return nullptr;
67
68
if (data_sp->GetByteSize() < length) {
69
data_sp = MapFileData(*file, length, file_offset);
70
if (!data_sp) {
71
LLDB_LOG(log,
72
"Failed to create ObjectFileCOFF instance: cannot read file {0}",
73
file->GetPath());
74
return nullptr;
75
}
76
data_offset = 0;
77
}
78
79
80
MemoryBufferRef buffer{toStringRef(data_sp->GetData()),
81
file->GetFilename().GetStringRef()};
82
83
Expected<std::unique_ptr<Binary>> binary = createBinary(buffer);
84
if (!binary) {
85
LLDB_LOG_ERROR(log, binary.takeError(),
86
"Failed to create binary for file ({1}): {0}",
87
file->GetPath());
88
return nullptr;
89
}
90
91
LLDB_LOG(log, "ObjectFileCOFF::ObjectFileCOFF module = {1} ({2}), file = {3}",
92
module_sp.get(), module_sp->GetSpecificationDescription(),
93
file->GetPath());
94
95
return new ObjectFileCOFF(unique_dyn_cast<COFFObjectFile>(std::move(*binary)),
96
module_sp, data_sp, data_offset, file, file_offset,
97
length);
98
}
99
100
lldb_private::ObjectFile *ObjectFileCOFF::CreateMemoryInstance(
101
const ModuleSP &module_sp, WritableDataBufferSP data_sp,
102
const ProcessSP &process_sp, addr_t header) {
103
// FIXME: do we need to worry about construction from a memory region?
104
return nullptr;
105
}
106
107
size_t ObjectFileCOFF::GetModuleSpecifications(
108
const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
109
offset_t file_offset, offset_t length, ModuleSpecList &specs) {
110
if (!IsCOFFObjectFile(data_sp))
111
return 0;
112
113
MemoryBufferRef buffer{toStringRef(data_sp->GetData()),
114
file.GetFilename().GetStringRef()};
115
Expected<std::unique_ptr<Binary>> binary = createBinary(buffer);
116
if (!binary) {
117
Log *log = GetLog(LLDBLog::Object);
118
LLDB_LOG_ERROR(log, binary.takeError(),
119
"Failed to create binary for file ({1}): {0}",
120
file.GetFilename());
121
return 0;
122
}
123
124
std::unique_ptr<COFFObjectFile> object =
125
unique_dyn_cast<COFFObjectFile>(std::move(*binary));
126
switch (static_cast<COFF::MachineTypes>(object->getMachine())) {
127
case COFF::IMAGE_FILE_MACHINE_I386:
128
specs.Append(ModuleSpec(file, ArchSpec("i686-unknown-windows-msvc")));
129
return 1;
130
case COFF::IMAGE_FILE_MACHINE_AMD64:
131
specs.Append(ModuleSpec(file, ArchSpec("x86_64-unknown-windows-msvc")));
132
return 1;
133
case COFF::IMAGE_FILE_MACHINE_ARMNT:
134
specs.Append(ModuleSpec(file, ArchSpec("armv7-unknown-windows-msvc")));
135
return 1;
136
case COFF::IMAGE_FILE_MACHINE_ARM64:
137
specs.Append(ModuleSpec(file, ArchSpec("aarch64-unknown-windows-msvc")));
138
return 1;
139
default:
140
return 0;
141
}
142
}
143
144
void ObjectFileCOFF::Dump(Stream *stream) {
145
ModuleSP module(GetModule());
146
if (!module)
147
return;
148
149
std::lock_guard<std::recursive_mutex> guard(module->GetMutex());
150
151
stream->Printf("%p: ", static_cast<void *>(this));
152
stream->Indent();
153
stream->PutCString("ObjectFileCOFF");
154
*stream << ", file = '" << m_file
155
<< "', arch = " << GetArchitecture().GetArchitectureName() << '\n';
156
157
if (SectionList *sections = GetSectionList())
158
sections->Dump(stream->AsRawOstream(), stream->GetIndentLevel(), nullptr,
159
true, std::numeric_limits<uint32_t>::max());
160
}
161
162
uint32_t ObjectFileCOFF::GetAddressByteSize() const {
163
return const_cast<ObjectFileCOFF *>(this)->GetArchitecture().GetAddressByteSize();
164
}
165
166
ArchSpec ObjectFileCOFF::GetArchitecture() {
167
switch (static_cast<COFF::MachineTypes>(m_object->getMachine())) {
168
case COFF::IMAGE_FILE_MACHINE_I386:
169
return ArchSpec("i686-unknown-windows-msvc");
170
case COFF::IMAGE_FILE_MACHINE_AMD64:
171
return ArchSpec("x86_64-unknown-windows-msvc");
172
case COFF::IMAGE_FILE_MACHINE_ARMNT:
173
return ArchSpec("armv7-unknown-windows-msvc");
174
case COFF::IMAGE_FILE_MACHINE_ARM64:
175
return ArchSpec("aarch64-unknown-windows-msvc");
176
default:
177
return ArchSpec();
178
}
179
}
180
181
void ObjectFileCOFF::CreateSections(lldb_private::SectionList &sections) {
182
if (m_sections_up)
183
return;
184
185
m_sections_up = std::make_unique<SectionList>();
186
ModuleSP module(GetModule());
187
if (!module)
188
return;
189
190
std::lock_guard<std::recursive_mutex> guard(module->GetMutex());
191
192
auto SectionType = [](StringRef Name,
193
const coff_section *Section) -> lldb::SectionType {
194
lldb::SectionType type =
195
StringSwitch<lldb::SectionType>(Name)
196
// DWARF Debug Sections
197
.Case(".debug_abbrev", eSectionTypeDWARFDebugAbbrev)
198
.Case(".debug_info", eSectionTypeDWARFDebugInfo)
199
.Case(".debug_line", eSectionTypeDWARFDebugLine)
200
.Case(".debug_pubnames", eSectionTypeDWARFDebugPubNames)
201
.Case(".debug_pubtypes", eSectionTypeDWARFDebugPubTypes)
202
.Case(".debug_str", eSectionTypeDWARFDebugStr)
203
// CodeView Debug Sections: .debug$S, .debug$T
204
.StartsWith(".debug$", eSectionTypeDebug)
205
.Case("clangast", eSectionTypeOther)
206
.Default(eSectionTypeInvalid);
207
if (type != eSectionTypeInvalid)
208
return type;
209
210
if (Section->Characteristics & COFF::IMAGE_SCN_CNT_CODE)
211
return eSectionTypeCode;
212
if (Section->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
213
return eSectionTypeData;
214
if (Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
215
return Section->SizeOfRawData ? eSectionTypeData : eSectionTypeZeroFill;
216
return eSectionTypeOther;
217
};
218
auto Permissions = [](const object::coff_section *Section) -> uint32_t {
219
uint32_t permissions = 0;
220
if (Section->Characteristics & COFF::IMAGE_SCN_MEM_EXECUTE)
221
permissions |= lldb::ePermissionsExecutable;
222
if (Section->Characteristics & COFF::IMAGE_SCN_MEM_READ)
223
permissions |= lldb::ePermissionsReadable;
224
if (Section->Characteristics & COFF::IMAGE_SCN_MEM_WRITE)
225
permissions |= lldb::ePermissionsWritable;
226
return permissions;
227
};
228
229
for (const auto &SecRef : m_object->sections()) {
230
const auto COFFSection = m_object->getCOFFSection(SecRef);
231
232
llvm::Expected<StringRef> Name = SecRef.getName();
233
StringRef SectionName = Name ? *Name : COFFSection->Name;
234
if (!Name)
235
consumeError(Name.takeError());
236
237
SectionSP section =
238
std::make_unique<Section>(module, this,
239
static_cast<user_id_t>(SecRef.getIndex()),
240
ConstString(SectionName),
241
SectionType(SectionName, COFFSection),
242
COFFSection->VirtualAddress,
243
COFFSection->VirtualSize,
244
COFFSection->PointerToRawData,
245
COFFSection->SizeOfRawData,
246
COFFSection->getAlignment(),
247
0);
248
section->SetPermissions(Permissions(COFFSection));
249
250
m_sections_up->AddSection(section);
251
sections.AddSection(section);
252
}
253
}
254
255
void ObjectFileCOFF::ParseSymtab(lldb_private::Symtab &symtab) {
256
Log *log = GetLog(LLDBLog::Object);
257
258
SectionList *sections = GetSectionList();
259
symtab.Reserve(symtab.GetNumSymbols() + m_object->getNumberOfSymbols());
260
261
auto SymbolType = [](const COFFSymbolRef &Symbol) -> lldb::SymbolType {
262
if (Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
263
return eSymbolTypeCode;
264
if (Symbol.getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
265
Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_NULL)
266
return eSymbolTypeData;
267
return eSymbolTypeInvalid;
268
};
269
270
for (const auto &SymRef : m_object->symbols()) {
271
const auto COFFSymRef = m_object->getCOFFSymbol(SymRef);
272
273
Expected<StringRef> NameOrErr = SymRef.getName();
274
if (!NameOrErr) {
275
LLDB_LOG_ERROR(log, NameOrErr.takeError(),
276
"ObjectFileCOFF: failed to get symbol name: {0}");
277
continue;
278
}
279
280
Symbol symbol;
281
symbol.GetMangled().SetValue(ConstString(*NameOrErr));
282
283
int16_t SecIdx = static_cast<int16_t>(COFFSymRef.getSectionNumber());
284
if (SecIdx == COFF::IMAGE_SYM_ABSOLUTE) {
285
symbol.GetAddressRef() = Address{COFFSymRef.getValue()};
286
symbol.SetType(eSymbolTypeAbsolute);
287
} else if (SecIdx >= 1) {
288
symbol.GetAddressRef() = Address(sections->GetSectionAtIndex(SecIdx - 1),
289
COFFSymRef.getValue());
290
symbol.SetType(SymbolType(COFFSymRef));
291
}
292
293
symtab.AddSymbol(symbol);
294
}
295
296
LLDB_LOG(log, "ObjectFileCOFF::ParseSymtab processed {0} symbols",
297
m_object->getNumberOfSymbols());
298
}
299
300
bool ObjectFileCOFF::ParseHeader() {
301
ModuleSP module(GetModule());
302
if (!module)
303
return false;
304
305
std::lock_guard<std::recursive_mutex> guard(module->GetMutex());
306
307
m_data.SetByteOrder(eByteOrderLittle);
308
m_data.SetAddressByteSize(GetAddressByteSize());
309
310
return true;
311
}
312
313