Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFF.cpp
35271 views
1
//===-------------- COFF.cpp - JIT linker function for COFF -------------===//
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
// COFF jit-link function.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "llvm/ExecutionEngine/JITLink/COFF.h"
14
15
#include "llvm/BinaryFormat/COFF.h"
16
#include "llvm/ExecutionEngine/JITLink/COFF_x86_64.h"
17
#include "llvm/Object/COFF.h"
18
#include "llvm/Support/Format.h"
19
#include "llvm/Support/MemoryBuffer.h"
20
#include <cstring>
21
22
using namespace llvm;
23
24
#define DEBUG_TYPE "jitlink"
25
26
namespace llvm {
27
namespace jitlink {
28
29
static StringRef getMachineName(uint16_t Machine) {
30
switch (Machine) {
31
case COFF::IMAGE_FILE_MACHINE_I386:
32
return "i386";
33
case COFF::IMAGE_FILE_MACHINE_AMD64:
34
return "x86_64";
35
case COFF::IMAGE_FILE_MACHINE_ARMNT:
36
return "ARM";
37
case COFF::IMAGE_FILE_MACHINE_ARM64:
38
return "ARM64";
39
default:
40
return "unknown";
41
}
42
}
43
44
Expected<std::unique_ptr<LinkGraph>>
45
createLinkGraphFromCOFFObject(MemoryBufferRef ObjectBuffer) {
46
StringRef Data = ObjectBuffer.getBuffer();
47
48
// Check magic
49
auto Magic = identify_magic(ObjectBuffer.getBuffer());
50
if (Magic != file_magic::coff_object)
51
return make_error<JITLinkError>("Invalid COFF buffer");
52
53
if (Data.size() < sizeof(object::coff_file_header))
54
return make_error<JITLinkError>("Truncated COFF buffer");
55
56
uint64_t CurPtr = 0;
57
bool IsPE = false;
58
59
// Check if this is a PE/COFF file.
60
if (Data.size() >= sizeof(object::dos_header) + sizeof(COFF::PEMagic)) {
61
const auto *DH =
62
reinterpret_cast<const object::dos_header *>(Data.data() + CurPtr);
63
if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
64
// Check the PE magic bytes. ("PE\0\0")
65
CurPtr = DH->AddressOfNewExeHeader;
66
if (memcmp(Data.data() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) !=
67
0) {
68
return make_error<JITLinkError>("Incorrect PE magic");
69
}
70
CurPtr += sizeof(COFF::PEMagic);
71
IsPE = true;
72
}
73
}
74
if (Data.size() < CurPtr + sizeof(object::coff_file_header))
75
return make_error<JITLinkError>("Truncated COFF buffer");
76
77
const object::coff_file_header *COFFHeader =
78
reinterpret_cast<const object::coff_file_header *>(Data.data() + CurPtr);
79
const object::coff_bigobj_file_header *COFFBigObjHeader = nullptr;
80
81
// Deal with bigobj file
82
if (!IsPE && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
83
COFFHeader->NumberOfSections == uint16_t(0xffff) &&
84
Data.size() >= sizeof(object::coff_bigobj_file_header)) {
85
if (Data.size() < sizeof(object::coff_file_header)) {
86
return make_error<JITLinkError>("Truncated COFF buffer");
87
}
88
COFFBigObjHeader =
89
reinterpret_cast<const object::coff_bigobj_file_header *>(Data.data() +
90
CurPtr);
91
92
// Verify that we are dealing with bigobj.
93
if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
94
std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
95
sizeof(COFF::BigObjMagic)) == 0) {
96
COFFHeader = nullptr;
97
CurPtr += sizeof(object::coff_bigobj_file_header);
98
} else
99
COFFBigObjHeader = nullptr;
100
}
101
102
uint16_t Machine =
103
COFFHeader ? COFFHeader->Machine : COFFBigObjHeader->Machine;
104
LLVM_DEBUG({
105
dbgs() << "jitLink_COFF: PE = " << (IsPE ? "yes" : "no")
106
<< ", bigobj = " << (COFFBigObjHeader ? "yes" : "no")
107
<< ", identifier = \"" << ObjectBuffer.getBufferIdentifier() << "\" "
108
<< "machine = " << getMachineName(Machine) << "\n";
109
});
110
111
switch (Machine) {
112
case COFF::IMAGE_FILE_MACHINE_AMD64:
113
return createLinkGraphFromCOFFObject_x86_64(ObjectBuffer);
114
default:
115
return make_error<JITLinkError>(
116
"Unsupported target machine architecture in COFF object " +
117
ObjectBuffer.getBufferIdentifier() + ": " + getMachineName(Machine));
118
}
119
}
120
121
void link_COFF(std::unique_ptr<LinkGraph> G,
122
std::unique_ptr<JITLinkContext> Ctx) {
123
switch (G->getTargetTriple().getArch()) {
124
case Triple::x86_64:
125
link_COFF_x86_64(std::move(G), std::move(Ctx));
126
return;
127
default:
128
Ctx->notifyFailed(make_error<JITLinkError>(
129
"Unsupported target machine architecture in COFF link graph " +
130
G->getName()));
131
return;
132
}
133
}
134
135
} // end namespace jitlink
136
} // end namespace llvm
137
138