2 //----------------------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #include "Arch/ARM64Common.h"
11 #include "InputFiles.h"
13 #include "SyntheticSections.h"
16 #include "lld/Common/ErrorHandler.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/BinaryFormat/MachO.h"
20 #include "llvm/Support/Endian.h"
21 #include "llvm/Support/MathExtras.h"
23 using namespace llvm::MachO
;
24 using namespace llvm::support::endian
;
26 using namespace lld::macho
;
30 struct ARM64_32
: ARM64Common
{
32 void writeStub(uint8_t *buf
, const Symbol
&, uint64_t) const override
;
33 void writeStubHelperHeader(uint8_t *buf
) const override
;
34 void writeStubHelperEntry(uint8_t *buf
, const Symbol
&,
35 uint64_t entryAddr
) const override
;
36 void writeObjCMsgSendStub(uint8_t *buf
, Symbol
*sym
, uint64_t stubsAddr
,
37 uint64_t &stubOffset
, uint64_t selrefVA
,
38 Symbol
*objcMsgSend
) const override
;
43 // These are very similar to ARM64's relocation attributes, except that we don't
44 // have the BYTE8 flag set.
45 static constexpr std::array
<RelocAttrs
, 11> relocAttrsArray
{{
46 #define B(x) RelocAttrBits::x
47 {"UNSIGNED", B(UNSIGNED
) | B(ABSOLUTE
) | B(EXTERN
) | B(LOCAL
) | B(BYTE4
)},
48 {"SUBTRACTOR", B(SUBTRAHEND
) | B(EXTERN
) | B(BYTE4
)},
49 {"BRANCH26", B(PCREL
) | B(EXTERN
) | B(BRANCH
) | B(BYTE4
)},
50 {"PAGE21", B(PCREL
) | B(EXTERN
) | B(BYTE4
)},
51 {"PAGEOFF12", B(ABSOLUTE
) | B(EXTERN
) | B(BYTE4
)},
52 {"GOT_LOAD_PAGE21", B(PCREL
) | B(EXTERN
) | B(GOT
) | B(BYTE4
)},
53 {"GOT_LOAD_PAGEOFF12",
54 B(ABSOLUTE
) | B(EXTERN
) | B(GOT
) | B(LOAD
) | B(BYTE4
)},
55 {"POINTER_TO_GOT", B(PCREL
) | B(EXTERN
) | B(GOT
) | B(POINTER
) | B(BYTE4
)},
56 {"TLVP_LOAD_PAGE21", B(PCREL
) | B(EXTERN
) | B(TLV
) | B(BYTE4
)},
57 {"TLVP_LOAD_PAGEOFF12",
58 B(ABSOLUTE
) | B(EXTERN
) | B(TLV
) | B(LOAD
) | B(BYTE4
)},
59 {"ADDEND", B(ADDEND
)},
63 // The stub code is fairly similar to ARM64's, except that we load pointers into
64 // 32-bit 'w' registers, instead of the 64-bit 'x' ones.
66 static constexpr uint32_t stubCode
[] = {
67 0x90000010, // 00: adrp x16, __la_symbol_ptr@page
68 0xb9400210, // 04: ldr w16, [x16, __la_symbol_ptr@pageoff]
69 0xd61f0200, // 08: br x16
72 void ARM64_32::writeStub(uint8_t *buf8
, const Symbol
&sym
,
73 uint64_t pointerVA
) const {
74 ::writeStub(buf8
, stubCode
, sym
, pointerVA
);
77 static constexpr uint32_t stubHelperHeaderCode
[] = {
78 0x90000011, // 00: adrp x17, _dyld_private@page
79 0x91000231, // 04: add x17, x17, _dyld_private@pageoff
80 0xa9bf47f0, // 08: stp x16/x17, [sp, #-16]!
81 0x90000010, // 0c: adrp x16, dyld_stub_binder@page
82 0xb9400210, // 10: ldr w16, [x16, dyld_stub_binder@pageoff]
83 0xd61f0200, // 14: br x16
86 void ARM64_32::writeStubHelperHeader(uint8_t *buf8
) const {
87 ::writeStubHelperHeader
<ILP32
>(buf8
, stubHelperHeaderCode
);
90 static constexpr uint32_t stubHelperEntryCode
[] = {
91 0x18000050, // 00: ldr w16, l0
92 0x14000000, // 04: b stubHelperHeader
93 0x00000000, // 08: l0: .long 0
96 void ARM64_32::writeStubHelperEntry(uint8_t *buf8
, const Symbol
&sym
,
97 uint64_t entryVA
) const {
98 ::writeStubHelperEntry(buf8
, stubHelperEntryCode
, sym
, entryVA
);
101 void ARM64_32::writeObjCMsgSendStub(uint8_t *buf
, Symbol
*sym
,
102 uint64_t stubsAddr
, uint64_t &stubOffset
,
104 Symbol
*objcMsgSend
) const {
105 fatal("TODO: implement this");
108 ARM64_32::ARM64_32() : ARM64Common(ILP32()) {
109 cpuType
= CPU_TYPE_ARM64_32
;
110 cpuSubtype
= CPU_SUBTYPE_ARM64_V8
;
112 modeDwarfEncoding
= 0x04000000; // UNWIND_ARM_MODE_DWARF
113 subtractorRelocType
= GENERIC_RELOC_INVALID
; // FIXME
114 unsignedRelocType
= GENERIC_RELOC_INVALID
; // FIXME
116 stubSize
= sizeof(stubCode
);
117 stubHelperHeaderSize
= sizeof(stubHelperHeaderCode
);
118 stubHelperEntrySize
= sizeof(stubHelperEntryCode
);
120 relocAttrs
= {relocAttrsArray
.data(), relocAttrsArray
.size()};
123 TargetInfo
*macho::createARM64_32TargetInfo() {