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 selrefsVA
,
38 uint64_t selectorIndex
, uint64_t gotAddr
,
39 uint64_t msgSendIndex
) const override
;
44 // These are very similar to ARM64's relocation attributes, except that we don't
45 // have the BYTE8 flag set.
46 static constexpr std::array
<RelocAttrs
, 11> relocAttrsArray
{{
47 #define B(x) RelocAttrBits::x
48 {"UNSIGNED", B(UNSIGNED
) | B(ABSOLUTE
) | B(EXTERN
) | B(LOCAL
) | B(BYTE4
)},
49 {"SUBTRACTOR", B(SUBTRAHEND
) | B(EXTERN
) | B(BYTE4
)},
50 {"BRANCH26", B(PCREL
) | B(EXTERN
) | B(BRANCH
) | B(BYTE4
)},
51 {"PAGE21", B(PCREL
) | B(EXTERN
) | B(BYTE4
)},
52 {"PAGEOFF12", B(ABSOLUTE
) | B(EXTERN
) | B(BYTE4
)},
53 {"GOT_LOAD_PAGE21", B(PCREL
) | B(EXTERN
) | B(GOT
) | B(BYTE4
)},
54 {"GOT_LOAD_PAGEOFF12",
55 B(ABSOLUTE
) | B(EXTERN
) | B(GOT
) | B(LOAD
) | B(BYTE4
)},
56 {"POINTER_TO_GOT", B(PCREL
) | B(EXTERN
) | B(GOT
) | B(POINTER
) | B(BYTE4
)},
57 {"TLVP_LOAD_PAGE21", B(PCREL
) | B(EXTERN
) | B(TLV
) | B(BYTE4
)},
58 {"TLVP_LOAD_PAGEOFF12",
59 B(ABSOLUTE
) | B(EXTERN
) | B(TLV
) | B(LOAD
) | B(BYTE4
)},
60 {"ADDEND", B(ADDEND
)},
64 // The stub code is fairly similar to ARM64's, except that we load pointers into
65 // 32-bit 'w' registers, instead of the 64-bit 'x' ones.
67 static constexpr uint32_t stubCode
[] = {
68 0x90000010, // 00: adrp x16, __la_symbol_ptr@page
69 0xb9400210, // 04: ldr w16, [x16, __la_symbol_ptr@pageoff]
70 0xd61f0200, // 08: br x16
73 void ARM64_32::writeStub(uint8_t *buf8
, const Symbol
&sym
,
74 uint64_t pointerVA
) const {
75 ::writeStub(buf8
, stubCode
, sym
, pointerVA
);
78 static constexpr uint32_t stubHelperHeaderCode
[] = {
79 0x90000011, // 00: adrp x17, _dyld_private@page
80 0x91000231, // 04: add x17, x17, _dyld_private@pageoff
81 0xa9bf47f0, // 08: stp x16/x17, [sp, #-16]!
82 0x90000010, // 0c: adrp x16, dyld_stub_binder@page
83 0xb9400210, // 10: ldr w16, [x16, dyld_stub_binder@pageoff]
84 0xd61f0200, // 14: br x16
87 void ARM64_32::writeStubHelperHeader(uint8_t *buf8
) const {
88 ::writeStubHelperHeader
<ILP32
>(buf8
, stubHelperHeaderCode
);
91 static constexpr uint32_t stubHelperEntryCode
[] = {
92 0x18000050, // 00: ldr w16, l0
93 0x14000000, // 04: b stubHelperHeader
94 0x00000000, // 08: l0: .long 0
97 void ARM64_32::writeStubHelperEntry(uint8_t *buf8
, const Symbol
&sym
,
98 uint64_t entryVA
) const {
99 ::writeStubHelperEntry(buf8
, stubHelperEntryCode
, sym
, entryVA
);
102 void ARM64_32::writeObjCMsgSendStub(uint8_t *buf
, Symbol
*sym
,
103 uint64_t stubsAddr
, uint64_t stubOffset
,
104 uint64_t selrefsVA
, uint64_t selectorIndex
,
106 uint64_t msgSendIndex
) const {
107 fatal("TODO: implement this");
110 ARM64_32::ARM64_32() : ARM64Common(ILP32()) {
111 cpuType
= CPU_TYPE_ARM64_32
;
112 cpuSubtype
= CPU_SUBTYPE_ARM64_V8
;
114 modeDwarfEncoding
= 0x04000000; // UNWIND_ARM_MODE_DWARF
115 subtractorRelocType
= GENERIC_RELOC_INVALID
; // FIXME
116 unsignedRelocType
= GENERIC_RELOC_INVALID
; // FIXME
118 stubSize
= sizeof(stubCode
);
119 stubHelperHeaderSize
= sizeof(stubHelperHeaderCode
);
120 stubHelperEntrySize
= sizeof(stubHelperEntryCode
);
122 relocAttrs
= {relocAttrsArray
.data(), relocAttrsArray
.size()};
125 TargetInfo
*macho::createARM64_32TargetInfo() {