1 //===-------------- COFF.cpp - JIT linker function for COFF -------------===//
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
7 //===----------------------------------------------------------------------===//
9 // COFF jit-link function.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ExecutionEngine/JITLink/COFF.h"
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"
24 #define DEBUG_TYPE "jitlink"
29 static StringRef
getMachineName(uint16_t Machine
) {
31 case COFF::IMAGE_FILE_MACHINE_I386
:
33 case COFF::IMAGE_FILE_MACHINE_AMD64
:
35 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
37 case COFF::IMAGE_FILE_MACHINE_ARM64
:
44 Expected
<std::unique_ptr
<LinkGraph
>>
45 createLinkGraphFromCOFFObject(MemoryBufferRef ObjectBuffer
) {
46 StringRef Data
= ObjectBuffer
.getBuffer();
49 auto Magic
= identify_magic(ObjectBuffer
.getBuffer());
50 if (Magic
!= file_magic::coff_object
)
51 return make_error
<JITLinkError
>("Invalid COFF buffer");
53 if (Data
.size() < sizeof(object::coff_file_header
))
54 return make_error
<JITLinkError
>("Truncated COFF buffer");
59 // Check if this is a PE/COFF file.
60 if (Data
.size() >= sizeof(object::dos_header
) + sizeof(COFF::PEMagic
)) {
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
)) !=
68 return make_error
<JITLinkError
>("Incorrect PE magic");
70 CurPtr
+= sizeof(COFF::PEMagic
);
74 if (Data
.size() < CurPtr
+ sizeof(object::coff_file_header
))
75 return make_error
<JITLinkError
>("Truncated COFF buffer");
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;
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");
89 reinterpret_cast<const object::coff_bigobj_file_header
*>(Data
.data() +
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) {
97 CurPtr
+= sizeof(object::coff_bigobj_file_header
);
99 COFFBigObjHeader
= nullptr;
103 COFFHeader
? COFFHeader
->Machine
: COFFBigObjHeader
->Machine
;
105 dbgs() << "jitLink_COFF: PE = " << (IsPE
? "yes" : "no")
106 << ", bigobj = " << (COFFBigObjHeader
? "yes" : "no")
107 << ", identifier = \"" << ObjectBuffer
.getBufferIdentifier() << "\" "
108 << "machine = " << getMachineName(Machine
) << "\n";
112 case COFF::IMAGE_FILE_MACHINE_AMD64
:
113 return createLinkGraphFromCOFFObject_x86_64(ObjectBuffer
);
115 return make_error
<JITLinkError
>(
116 "Unsupported target machine architecture in COFF object " +
117 ObjectBuffer
.getBufferIdentifier() + ": " + getMachineName(Machine
));
121 void link_COFF(std::unique_ptr
<LinkGraph
> G
,
122 std::unique_ptr
<JITLinkContext
> Ctx
) {
123 switch (G
->getTargetTriple().getArch()) {
125 link_COFF_x86_64(std::move(G
), std::move(Ctx
));
128 Ctx
->notifyFailed(make_error
<JITLinkError
>(
129 "Unsupported target machine architecture in COFF link graph " +
135 } // end namespace jitlink
136 } // end namespace llvm