1 | //===-------------- MachO.cpp - JIT linker function for MachO -------------===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // MachO jit-link function. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/ExecutionEngine/JITLink/MachO.h" |
15 | |
16 | #include "llvm/BinaryFormat/MachO.h" |
17 | #include "llvm/ExecutionEngine/JITLink/MachO_arm64.h" |
18 | #include "llvm/ExecutionEngine/JITLink/MachO_x86_64.h" |
19 | #include "llvm/Support/Format.h" |
20 | #include "llvm/Support/MemoryBuffer.h" |
21 | #include "llvm/Support/SwapByteOrder.h" |
22 | |
23 | using namespace llvm; |
24 | |
25 | #define DEBUG_TYPE "jitlink" |
26 | |
27 | namespace llvm { |
28 | namespace jitlink { |
29 | |
30 | Expected<std::unique_ptr<LinkGraph>> |
31 | createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer) { |
32 | StringRef Data = ObjectBuffer.getBuffer(); |
33 | if (Data.size() < 4) |
34 | return make_error<JITLinkError>("Truncated MachO buffer \"" + |
35 | ObjectBuffer.getBufferIdentifier() + "\"" ); |
36 | |
37 | uint32_t Magic; |
38 | memcpy(&Magic, Data.data(), sizeof(uint32_t)); |
39 | LLVM_DEBUG({ |
40 | dbgs() << "jitLink_MachO: magic = " << format("0x%08" PRIx32, Magic) |
41 | << ", identifier = \"" << ObjectBuffer.getBufferIdentifier() |
42 | << "\"\n" ; |
43 | }); |
44 | |
45 | if (Magic == MachO::MH_MAGIC || Magic == MachO::MH_CIGAM) |
46 | return make_error<JITLinkError>("MachO 32-bit platforms not supported" ); |
47 | else if (Magic == MachO::MH_MAGIC_64 || Magic == MachO::MH_CIGAM_64) { |
48 | |
49 | if (Data.size() < sizeof(MachO::mach_header_64)) |
50 | return make_error<JITLinkError>("Truncated MachO buffer \"" + |
51 | ObjectBuffer.getBufferIdentifier() + |
52 | "\"" ); |
53 | |
54 | // Read the CPU type from the header. |
55 | uint32_t CPUType; |
56 | memcpy(&CPUType, Data.data() + 4, sizeof(uint32_t)); |
57 | if (Magic == MachO::MH_CIGAM_64) |
58 | CPUType = ByteSwap_32(CPUType); |
59 | |
60 | LLVM_DEBUG({ |
61 | dbgs() << "jitLink_MachO: cputype = " << format("0x%08" PRIx32, CPUType) |
62 | << "\n" ; |
63 | }); |
64 | |
65 | switch (CPUType) { |
66 | case MachO::CPU_TYPE_ARM64: |
67 | return createLinkGraphFromMachOObject_arm64(ObjectBuffer); |
68 | case MachO::CPU_TYPE_X86_64: |
69 | return createLinkGraphFromMachOObject_x86_64(ObjectBuffer); |
70 | } |
71 | return make_error<JITLinkError>("MachO-64 CPU type not valid" ); |
72 | } else |
73 | return make_error<JITLinkError>("Unrecognized MachO magic value" ); |
74 | } |
75 | |
76 | void link_MachO(std::unique_ptr<LinkGraph> G, |
77 | std::unique_ptr<JITLinkContext> Ctx) { |
78 | |
79 | switch (G->getTargetTriple().getArch()) { |
80 | case Triple::aarch64: |
81 | return link_MachO_arm64(std::move(G), std::move(Ctx)); |
82 | case Triple::x86_64: |
83 | return link_MachO_x86_64(std::move(G), std::move(Ctx)); |
84 | default: |
85 | Ctx->notifyFailed(make_error<JITLinkError>("MachO-64 CPU type not valid" )); |
86 | return; |
87 | } |
88 | } |
89 | |
90 | } // end namespace jitlink |
91 | } // end namespace llvm |
92 | |