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