LLVM  16.0.0git
COFF.cpp
Go to the documentation of this file.
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 
14 
15 #include "llvm/BinaryFormat/COFF.h"
17 #include "llvm/Object/COFF.h"
18 #include "llvm/Support/Endian.h"
19 #include "llvm/Support/Format.h"
21 #include <cstring>
22 
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "jitlink"
26 
27 namespace llvm {
28 namespace jitlink {
29 
31  switch (Machine) {
33  return "i386";
35  return "x86_64";
37  return "ARM";
39  return "ARM64";
40  default:
41  return "unknown";
42  }
43 }
44 
47  StringRef Data = ObjectBuffer.getBuffer();
48 
49  // Check magic
50  auto Magic = identify_magic(ObjectBuffer.getBuffer());
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 && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
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({
106  dbgs() << "jitLink_COFF: PE = " << (IsPE ? "yes" : "no")
107  << ", bigobj = " << (COFFBigObjHeader ? "yes" : "no")
108  << ", identifier = \"" << ObjectBuffer.getBufferIdentifier() << "\" "
109  << "machine = " << getMachineName(Machine) << "\n";
110  });
111 
112  switch (Machine) {
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:
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
MemoryBuffer.h
llvm::COFF::BigObjHeader::MinBigObjectVersion
@ MinBigObjectVersion
Definition: COFF.h:75
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::object::coff_file_header::Machine
support::ulittle16_t Machine
Definition: COFF.h:76
llvm::COFF::IMAGE_FILE_MACHINE_AMD64
@ IMAGE_FILE_MACHINE_AMD64
Definition: COFF.h:97
llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN
@ IMAGE_FILE_MACHINE_UNKNOWN
Definition: COFF.h:95
memcmp
Merge contiguous icmps into a memcmp
Definition: MergeICmps.cpp:903
COFF.h
llvm::Triple::x86_64
@ x86_64
Definition: Triple.h:86
llvm::COFF::IMAGE_FILE_MACHINE_ARMNT
@ IMAGE_FILE_MACHINE_ARMNT
Definition: COFF.h:99
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
Format.h
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::MemoryBufferRef
Definition: MemoryBufferRef.h:22
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::object::coff_file_header::NumberOfSections
support::ulittle16_t NumberOfSections
Definition: COFF.h:77
llvm::COFF::PEMagic
static const char PEMagic[]
Definition: COFF.h:35
llvm::object::dos_header
The DOS compatible header at the front of all PE/COFF executables.
Definition: COFF.h:53
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::object::coff_file_header
Definition: COFF.h:75
llvm::COFF::IMAGE_FILE_MACHINE_I386
@ IMAGE_FILE_MACHINE_I386
Definition: COFF.h:103
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:200
llvm::object::coff_bigobj_file_header::UUID
uint8_t UUID[16]
Definition: COFF.h:93
uint64_t
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::file_magic::coff_object
@ coff_object
COFF object file.
Definition: Magic.h:46
llvm::MemoryBufferRef::getBuffer
StringRef getBuffer() const
Definition: MemoryBufferRef.h:32
llvm::object::coff_bigobj_file_header::Version
support::ulittle16_t Version
Definition: COFF.h:90
llvm::object::coff_bigobj_file_header
Definition: COFF.h:87
llvm::COFF::BigObjMagic
static const char BigObjMagic[]
Definition: COFF.h:37
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::msf::Magic
static const char Magic[]
Definition: MSFCommon.h:23
llvm::COFF::IMAGE_FILE_MACHINE_ARM64
@ IMAGE_FILE_MACHINE_ARM64
Definition: COFF.h:100
uint16_t
COFF_x86_64.h
Machine
COFF::MachineTypes Machine
Definition: COFFYAML.cpp:370
COFF.h
llvm::MemoryBufferRef::getBufferIdentifier
StringRef getBufferIdentifier() const
Definition: MemoryBufferRef.h:33
llvm::object::coff_bigobj_file_header::Machine
support::ulittle16_t Machine
Definition: COFF.h:91
llvm::identify_magic
file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Definition: Magic.cpp:33
Endian.h