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