1*9880d681SAndroid Build Coastguard Worker //===-- AArch64MachObjectWriter.cpp - ARM Mach Object Writer --------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AArch64FixupKinds.h"
11*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AArch64MCTargetDesc.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Twine.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmLayout.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAssembler.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCFixup.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCMachObjectWriter.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSectionMachO.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCValue.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MachO.h"
24*9880d681SAndroid Build Coastguard Worker using namespace llvm;
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Worker namespace {
27*9880d681SAndroid Build Coastguard Worker class AArch64MachObjectWriter : public MCMachObjectTargetWriter {
28*9880d681SAndroid Build Coastguard Worker bool getAArch64FixupKindMachOInfo(const MCFixup &Fixup, unsigned &RelocType,
29*9880d681SAndroid Build Coastguard Worker const MCSymbolRefExpr *Sym,
30*9880d681SAndroid Build Coastguard Worker unsigned &Log2Size, const MCAssembler &Asm);
31*9880d681SAndroid Build Coastguard Worker
32*9880d681SAndroid Build Coastguard Worker public:
AArch64MachObjectWriter(uint32_t CPUType,uint32_t CPUSubtype)33*9880d681SAndroid Build Coastguard Worker AArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype)
34*9880d681SAndroid Build Coastguard Worker : MCMachObjectTargetWriter(true /* is64Bit */, CPUType, CPUSubtype) {}
35*9880d681SAndroid Build Coastguard Worker
36*9880d681SAndroid Build Coastguard Worker void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
37*9880d681SAndroid Build Coastguard Worker const MCAsmLayout &Layout, const MCFragment *Fragment,
38*9880d681SAndroid Build Coastguard Worker const MCFixup &Fixup, MCValue Target,
39*9880d681SAndroid Build Coastguard Worker uint64_t &FixedValue) override;
40*9880d681SAndroid Build Coastguard Worker };
41*9880d681SAndroid Build Coastguard Worker }
42*9880d681SAndroid Build Coastguard Worker
getAArch64FixupKindMachOInfo(const MCFixup & Fixup,unsigned & RelocType,const MCSymbolRefExpr * Sym,unsigned & Log2Size,const MCAssembler & Asm)43*9880d681SAndroid Build Coastguard Worker bool AArch64MachObjectWriter::getAArch64FixupKindMachOInfo(
44*9880d681SAndroid Build Coastguard Worker const MCFixup &Fixup, unsigned &RelocType, const MCSymbolRefExpr *Sym,
45*9880d681SAndroid Build Coastguard Worker unsigned &Log2Size, const MCAssembler &Asm) {
46*9880d681SAndroid Build Coastguard Worker RelocType = unsigned(MachO::ARM64_RELOC_UNSIGNED);
47*9880d681SAndroid Build Coastguard Worker Log2Size = ~0U;
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker switch ((unsigned)Fixup.getKind()) {
50*9880d681SAndroid Build Coastguard Worker default:
51*9880d681SAndroid Build Coastguard Worker return false;
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard Worker case FK_Data_1:
54*9880d681SAndroid Build Coastguard Worker Log2Size = llvm::Log2_32(1);
55*9880d681SAndroid Build Coastguard Worker return true;
56*9880d681SAndroid Build Coastguard Worker case FK_Data_2:
57*9880d681SAndroid Build Coastguard Worker Log2Size = llvm::Log2_32(2);
58*9880d681SAndroid Build Coastguard Worker return true;
59*9880d681SAndroid Build Coastguard Worker case FK_Data_4:
60*9880d681SAndroid Build Coastguard Worker Log2Size = llvm::Log2_32(4);
61*9880d681SAndroid Build Coastguard Worker if (Sym->getKind() == MCSymbolRefExpr::VK_GOT)
62*9880d681SAndroid Build Coastguard Worker RelocType = unsigned(MachO::ARM64_RELOC_POINTER_TO_GOT);
63*9880d681SAndroid Build Coastguard Worker return true;
64*9880d681SAndroid Build Coastguard Worker case FK_Data_8:
65*9880d681SAndroid Build Coastguard Worker Log2Size = llvm::Log2_32(8);
66*9880d681SAndroid Build Coastguard Worker if (Sym->getKind() == MCSymbolRefExpr::VK_GOT)
67*9880d681SAndroid Build Coastguard Worker RelocType = unsigned(MachO::ARM64_RELOC_POINTER_TO_GOT);
68*9880d681SAndroid Build Coastguard Worker return true;
69*9880d681SAndroid Build Coastguard Worker case AArch64::fixup_aarch64_add_imm12:
70*9880d681SAndroid Build Coastguard Worker case AArch64::fixup_aarch64_ldst_imm12_scale1:
71*9880d681SAndroid Build Coastguard Worker case AArch64::fixup_aarch64_ldst_imm12_scale2:
72*9880d681SAndroid Build Coastguard Worker case AArch64::fixup_aarch64_ldst_imm12_scale4:
73*9880d681SAndroid Build Coastguard Worker case AArch64::fixup_aarch64_ldst_imm12_scale8:
74*9880d681SAndroid Build Coastguard Worker case AArch64::fixup_aarch64_ldst_imm12_scale16:
75*9880d681SAndroid Build Coastguard Worker Log2Size = llvm::Log2_32(4);
76*9880d681SAndroid Build Coastguard Worker switch (Sym->getKind()) {
77*9880d681SAndroid Build Coastguard Worker default:
78*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected symbol reference variant kind!");
79*9880d681SAndroid Build Coastguard Worker case MCSymbolRefExpr::VK_PAGEOFF:
80*9880d681SAndroid Build Coastguard Worker RelocType = unsigned(MachO::ARM64_RELOC_PAGEOFF12);
81*9880d681SAndroid Build Coastguard Worker return true;
82*9880d681SAndroid Build Coastguard Worker case MCSymbolRefExpr::VK_GOTPAGEOFF:
83*9880d681SAndroid Build Coastguard Worker RelocType = unsigned(MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12);
84*9880d681SAndroid Build Coastguard Worker return true;
85*9880d681SAndroid Build Coastguard Worker case MCSymbolRefExpr::VK_TLVPPAGEOFF:
86*9880d681SAndroid Build Coastguard Worker RelocType = unsigned(MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12);
87*9880d681SAndroid Build Coastguard Worker return true;
88*9880d681SAndroid Build Coastguard Worker }
89*9880d681SAndroid Build Coastguard Worker case AArch64::fixup_aarch64_pcrel_adrp_imm21:
90*9880d681SAndroid Build Coastguard Worker Log2Size = llvm::Log2_32(4);
91*9880d681SAndroid Build Coastguard Worker // This encompasses the relocation for the whole 21-bit value.
92*9880d681SAndroid Build Coastguard Worker switch (Sym->getKind()) {
93*9880d681SAndroid Build Coastguard Worker default: {
94*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(Fixup.getLoc(),
95*9880d681SAndroid Build Coastguard Worker "ADR/ADRP relocations must be GOT relative");
96*9880d681SAndroid Build Coastguard Worker return false;
97*9880d681SAndroid Build Coastguard Worker }
98*9880d681SAndroid Build Coastguard Worker case MCSymbolRefExpr::VK_PAGE:
99*9880d681SAndroid Build Coastguard Worker RelocType = unsigned(MachO::ARM64_RELOC_PAGE21);
100*9880d681SAndroid Build Coastguard Worker return true;
101*9880d681SAndroid Build Coastguard Worker case MCSymbolRefExpr::VK_GOTPAGE:
102*9880d681SAndroid Build Coastguard Worker RelocType = unsigned(MachO::ARM64_RELOC_GOT_LOAD_PAGE21);
103*9880d681SAndroid Build Coastguard Worker return true;
104*9880d681SAndroid Build Coastguard Worker case MCSymbolRefExpr::VK_TLVPPAGE:
105*9880d681SAndroid Build Coastguard Worker RelocType = unsigned(MachO::ARM64_RELOC_TLVP_LOAD_PAGE21);
106*9880d681SAndroid Build Coastguard Worker return true;
107*9880d681SAndroid Build Coastguard Worker }
108*9880d681SAndroid Build Coastguard Worker return true;
109*9880d681SAndroid Build Coastguard Worker case AArch64::fixup_aarch64_pcrel_branch26:
110*9880d681SAndroid Build Coastguard Worker case AArch64::fixup_aarch64_pcrel_call26:
111*9880d681SAndroid Build Coastguard Worker Log2Size = llvm::Log2_32(4);
112*9880d681SAndroid Build Coastguard Worker RelocType = unsigned(MachO::ARM64_RELOC_BRANCH26);
113*9880d681SAndroid Build Coastguard Worker return true;
114*9880d681SAndroid Build Coastguard Worker }
115*9880d681SAndroid Build Coastguard Worker }
116*9880d681SAndroid Build Coastguard Worker
canUseLocalRelocation(const MCSectionMachO & Section,const MCSymbol & Symbol,unsigned Log2Size)117*9880d681SAndroid Build Coastguard Worker static bool canUseLocalRelocation(const MCSectionMachO &Section,
118*9880d681SAndroid Build Coastguard Worker const MCSymbol &Symbol, unsigned Log2Size) {
119*9880d681SAndroid Build Coastguard Worker // Debug info sections can use local relocations.
120*9880d681SAndroid Build Coastguard Worker if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
121*9880d681SAndroid Build Coastguard Worker return true;
122*9880d681SAndroid Build Coastguard Worker
123*9880d681SAndroid Build Coastguard Worker // Otherwise, only pointer sized relocations are supported.
124*9880d681SAndroid Build Coastguard Worker if (Log2Size != 3)
125*9880d681SAndroid Build Coastguard Worker return false;
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker // But only if they don't point to a few forbidden sections.
128*9880d681SAndroid Build Coastguard Worker if (!Symbol.isInSection())
129*9880d681SAndroid Build Coastguard Worker return true;
130*9880d681SAndroid Build Coastguard Worker const MCSectionMachO &RefSec = cast<MCSectionMachO>(Symbol.getSection());
131*9880d681SAndroid Build Coastguard Worker if (RefSec.getType() == MachO::S_CSTRING_LITERALS)
132*9880d681SAndroid Build Coastguard Worker return false;
133*9880d681SAndroid Build Coastguard Worker
134*9880d681SAndroid Build Coastguard Worker if (RefSec.getSegmentName() == "__DATA" &&
135*9880d681SAndroid Build Coastguard Worker RefSec.getSectionName() == "__objc_classrefs")
136*9880d681SAndroid Build Coastguard Worker return false;
137*9880d681SAndroid Build Coastguard Worker
138*9880d681SAndroid Build Coastguard Worker // FIXME: ld64 currently handles internal pointer-sized relocations
139*9880d681SAndroid Build Coastguard Worker // incorrectly (applying the addend twice). We should be able to return true
140*9880d681SAndroid Build Coastguard Worker // unconditionally by this point when that's fixed.
141*9880d681SAndroid Build Coastguard Worker return false;
142*9880d681SAndroid Build Coastguard Worker }
143*9880d681SAndroid Build Coastguard Worker
recordRelocation(MachObjectWriter * Writer,MCAssembler & Asm,const MCAsmLayout & Layout,const MCFragment * Fragment,const MCFixup & Fixup,MCValue Target,uint64_t & FixedValue)144*9880d681SAndroid Build Coastguard Worker void AArch64MachObjectWriter::recordRelocation(
145*9880d681SAndroid Build Coastguard Worker MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout,
146*9880d681SAndroid Build Coastguard Worker const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
147*9880d681SAndroid Build Coastguard Worker uint64_t &FixedValue) {
148*9880d681SAndroid Build Coastguard Worker unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
149*9880d681SAndroid Build Coastguard Worker
150*9880d681SAndroid Build Coastguard Worker // See <reloc.h>.
151*9880d681SAndroid Build Coastguard Worker uint32_t FixupOffset = Layout.getFragmentOffset(Fragment);
152*9880d681SAndroid Build Coastguard Worker unsigned Log2Size = 0;
153*9880d681SAndroid Build Coastguard Worker int64_t Value = 0;
154*9880d681SAndroid Build Coastguard Worker unsigned Index = 0;
155*9880d681SAndroid Build Coastguard Worker unsigned Type = 0;
156*9880d681SAndroid Build Coastguard Worker unsigned Kind = Fixup.getKind();
157*9880d681SAndroid Build Coastguard Worker const MCSymbol *RelSymbol = nullptr;
158*9880d681SAndroid Build Coastguard Worker
159*9880d681SAndroid Build Coastguard Worker FixupOffset += Fixup.getOffset();
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Worker // AArch64 pcrel relocation addends do not include the section offset.
162*9880d681SAndroid Build Coastguard Worker if (IsPCRel)
163*9880d681SAndroid Build Coastguard Worker FixedValue += FixupOffset;
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker // ADRP fixups use relocations for the whole symbol value and only
166*9880d681SAndroid Build Coastguard Worker // put the addend in the instruction itself. Clear out any value the
167*9880d681SAndroid Build Coastguard Worker // generic code figured out from the sybmol definition.
168*9880d681SAndroid Build Coastguard Worker if (Kind == AArch64::fixup_aarch64_pcrel_adrp_imm21)
169*9880d681SAndroid Build Coastguard Worker FixedValue = 0;
170*9880d681SAndroid Build Coastguard Worker
171*9880d681SAndroid Build Coastguard Worker // imm19 relocations are for conditional branches, which require
172*9880d681SAndroid Build Coastguard Worker // assembler local symbols. If we got here, that's not what we have,
173*9880d681SAndroid Build Coastguard Worker // so complain loudly.
174*9880d681SAndroid Build Coastguard Worker if (Kind == AArch64::fixup_aarch64_pcrel_branch19) {
175*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(Fixup.getLoc(),
176*9880d681SAndroid Build Coastguard Worker "conditional branch requires assembler-local"
177*9880d681SAndroid Build Coastguard Worker " label. '" +
178*9880d681SAndroid Build Coastguard Worker Target.getSymA()->getSymbol().getName() +
179*9880d681SAndroid Build Coastguard Worker "' is external.");
180*9880d681SAndroid Build Coastguard Worker return;
181*9880d681SAndroid Build Coastguard Worker }
182*9880d681SAndroid Build Coastguard Worker
183*9880d681SAndroid Build Coastguard Worker // 14-bit branch relocations should only target internal labels, and so
184*9880d681SAndroid Build Coastguard Worker // should never get here.
185*9880d681SAndroid Build Coastguard Worker if (Kind == AArch64::fixup_aarch64_pcrel_branch14) {
186*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(Fixup.getLoc(),
187*9880d681SAndroid Build Coastguard Worker "Invalid relocation on conditional branch!");
188*9880d681SAndroid Build Coastguard Worker return;
189*9880d681SAndroid Build Coastguard Worker }
190*9880d681SAndroid Build Coastguard Worker
191*9880d681SAndroid Build Coastguard Worker if (!getAArch64FixupKindMachOInfo(Fixup, Type, Target.getSymA(), Log2Size,
192*9880d681SAndroid Build Coastguard Worker Asm)) {
193*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(Fixup.getLoc(), "unknown AArch64 fixup kind!");
194*9880d681SAndroid Build Coastguard Worker return;
195*9880d681SAndroid Build Coastguard Worker }
196*9880d681SAndroid Build Coastguard Worker
197*9880d681SAndroid Build Coastguard Worker Value = Target.getConstant();
198*9880d681SAndroid Build Coastguard Worker
199*9880d681SAndroid Build Coastguard Worker if (Target.isAbsolute()) { // constant
200*9880d681SAndroid Build Coastguard Worker // FIXME: Should this always be extern?
201*9880d681SAndroid Build Coastguard Worker // SymbolNum of 0 indicates the absolute section.
202*9880d681SAndroid Build Coastguard Worker Type = MachO::ARM64_RELOC_UNSIGNED;
203*9880d681SAndroid Build Coastguard Worker
204*9880d681SAndroid Build Coastguard Worker if (IsPCRel) {
205*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(Fixup.getLoc(),
206*9880d681SAndroid Build Coastguard Worker "PC relative absolute relocation!");
207*9880d681SAndroid Build Coastguard Worker return;
208*9880d681SAndroid Build Coastguard Worker
209*9880d681SAndroid Build Coastguard Worker // FIXME: x86_64 sets the type to a branch reloc here. Should we do
210*9880d681SAndroid Build Coastguard Worker // something similar?
211*9880d681SAndroid Build Coastguard Worker }
212*9880d681SAndroid Build Coastguard Worker } else if (Target.getSymB()) { // A - B + constant
213*9880d681SAndroid Build Coastguard Worker const MCSymbol *A = &Target.getSymA()->getSymbol();
214*9880d681SAndroid Build Coastguard Worker const MCSymbol *A_Base = Asm.getAtom(*A);
215*9880d681SAndroid Build Coastguard Worker
216*9880d681SAndroid Build Coastguard Worker const MCSymbol *B = &Target.getSymB()->getSymbol();
217*9880d681SAndroid Build Coastguard Worker const MCSymbol *B_Base = Asm.getAtom(*B);
218*9880d681SAndroid Build Coastguard Worker
219*9880d681SAndroid Build Coastguard Worker // Check for "_foo@got - .", which comes through here as:
220*9880d681SAndroid Build Coastguard Worker // Ltmp0:
221*9880d681SAndroid Build Coastguard Worker // ... _foo@got - Ltmp0
222*9880d681SAndroid Build Coastguard Worker if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOT &&
223*9880d681SAndroid Build Coastguard Worker Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None &&
224*9880d681SAndroid Build Coastguard Worker Layout.getSymbolOffset(*B) ==
225*9880d681SAndroid Build Coastguard Worker Layout.getFragmentOffset(Fragment) + Fixup.getOffset()) {
226*9880d681SAndroid Build Coastguard Worker // SymB is the PC, so use a PC-rel pointer-to-GOT relocation.
227*9880d681SAndroid Build Coastguard Worker Type = MachO::ARM64_RELOC_POINTER_TO_GOT;
228*9880d681SAndroid Build Coastguard Worker IsPCRel = 1;
229*9880d681SAndroid Build Coastguard Worker MachO::any_relocation_info MRE;
230*9880d681SAndroid Build Coastguard Worker MRE.r_word0 = FixupOffset;
231*9880d681SAndroid Build Coastguard Worker MRE.r_word1 = (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
232*9880d681SAndroid Build Coastguard Worker Writer->addRelocation(A_Base, Fragment->getParent(), MRE);
233*9880d681SAndroid Build Coastguard Worker return;
234*9880d681SAndroid Build Coastguard Worker } else if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
235*9880d681SAndroid Build Coastguard Worker Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None) {
236*9880d681SAndroid Build Coastguard Worker // Otherwise, neither symbol can be modified.
237*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(Fixup.getLoc(),
238*9880d681SAndroid Build Coastguard Worker "unsupported relocation of modified symbol");
239*9880d681SAndroid Build Coastguard Worker return;
240*9880d681SAndroid Build Coastguard Worker }
241*9880d681SAndroid Build Coastguard Worker
242*9880d681SAndroid Build Coastguard Worker // We don't support PCrel relocations of differences.
243*9880d681SAndroid Build Coastguard Worker if (IsPCRel) {
244*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(Fixup.getLoc(),
245*9880d681SAndroid Build Coastguard Worker "unsupported pc-relative relocation of "
246*9880d681SAndroid Build Coastguard Worker "difference");
247*9880d681SAndroid Build Coastguard Worker return;
248*9880d681SAndroid Build Coastguard Worker }
249*9880d681SAndroid Build Coastguard Worker
250*9880d681SAndroid Build Coastguard Worker // AArch64 always uses external relocations. If there is no symbol to use as
251*9880d681SAndroid Build Coastguard Worker // a base address (a local symbol with no preceding non-local symbol),
252*9880d681SAndroid Build Coastguard Worker // error out.
253*9880d681SAndroid Build Coastguard Worker //
254*9880d681SAndroid Build Coastguard Worker // FIXME: We should probably just synthesize an external symbol and use
255*9880d681SAndroid Build Coastguard Worker // that.
256*9880d681SAndroid Build Coastguard Worker if (!A_Base) {
257*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(
258*9880d681SAndroid Build Coastguard Worker Fixup.getLoc(),
259*9880d681SAndroid Build Coastguard Worker "unsupported relocation of local symbol '" + A->getName() +
260*9880d681SAndroid Build Coastguard Worker "'. Must have non-local symbol earlier in section.");
261*9880d681SAndroid Build Coastguard Worker return;
262*9880d681SAndroid Build Coastguard Worker }
263*9880d681SAndroid Build Coastguard Worker if (!B_Base) {
264*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(
265*9880d681SAndroid Build Coastguard Worker Fixup.getLoc(),
266*9880d681SAndroid Build Coastguard Worker "unsupported relocation of local symbol '" + B->getName() +
267*9880d681SAndroid Build Coastguard Worker "'. Must have non-local symbol earlier in section.");
268*9880d681SAndroid Build Coastguard Worker return;
269*9880d681SAndroid Build Coastguard Worker }
270*9880d681SAndroid Build Coastguard Worker
271*9880d681SAndroid Build Coastguard Worker if (A_Base == B_Base && A_Base) {
272*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(
273*9880d681SAndroid Build Coastguard Worker Fixup.getLoc(), "unsupported relocation with identical base");
274*9880d681SAndroid Build Coastguard Worker return;
275*9880d681SAndroid Build Coastguard Worker }
276*9880d681SAndroid Build Coastguard Worker
277*9880d681SAndroid Build Coastguard Worker Value += (!A->getFragment() ? 0 : Writer->getSymbolAddress(*A, Layout)) -
278*9880d681SAndroid Build Coastguard Worker (!A_Base || !A_Base->getFragment() ? 0 : Writer->getSymbolAddress(
279*9880d681SAndroid Build Coastguard Worker *A_Base, Layout));
280*9880d681SAndroid Build Coastguard Worker Value -= (!B->getFragment() ? 0 : Writer->getSymbolAddress(*B, Layout)) -
281*9880d681SAndroid Build Coastguard Worker (!B_Base || !B_Base->getFragment() ? 0 : Writer->getSymbolAddress(
282*9880d681SAndroid Build Coastguard Worker *B_Base, Layout));
283*9880d681SAndroid Build Coastguard Worker
284*9880d681SAndroid Build Coastguard Worker Type = MachO::ARM64_RELOC_UNSIGNED;
285*9880d681SAndroid Build Coastguard Worker
286*9880d681SAndroid Build Coastguard Worker MachO::any_relocation_info MRE;
287*9880d681SAndroid Build Coastguard Worker MRE.r_word0 = FixupOffset;
288*9880d681SAndroid Build Coastguard Worker MRE.r_word1 = (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
289*9880d681SAndroid Build Coastguard Worker Writer->addRelocation(A_Base, Fragment->getParent(), MRE);
290*9880d681SAndroid Build Coastguard Worker
291*9880d681SAndroid Build Coastguard Worker RelSymbol = B_Base;
292*9880d681SAndroid Build Coastguard Worker Type = MachO::ARM64_RELOC_SUBTRACTOR;
293*9880d681SAndroid Build Coastguard Worker } else { // A + constant
294*9880d681SAndroid Build Coastguard Worker const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
295*9880d681SAndroid Build Coastguard Worker const MCSectionMachO &Section =
296*9880d681SAndroid Build Coastguard Worker static_cast<const MCSectionMachO &>(*Fragment->getParent());
297*9880d681SAndroid Build Coastguard Worker
298*9880d681SAndroid Build Coastguard Worker bool CanUseLocalRelocation =
299*9880d681SAndroid Build Coastguard Worker canUseLocalRelocation(Section, *Symbol, Log2Size);
300*9880d681SAndroid Build Coastguard Worker if (Symbol->isTemporary() && (Value || !CanUseLocalRelocation)) {
301*9880d681SAndroid Build Coastguard Worker const MCSection &Sec = Symbol->getSection();
302*9880d681SAndroid Build Coastguard Worker if (!Asm.getContext().getAsmInfo()->isSectionAtomizableBySymbols(Sec))
303*9880d681SAndroid Build Coastguard Worker Symbol->setUsedInReloc();
304*9880d681SAndroid Build Coastguard Worker }
305*9880d681SAndroid Build Coastguard Worker
306*9880d681SAndroid Build Coastguard Worker const MCSymbol *Base = Asm.getAtom(*Symbol);
307*9880d681SAndroid Build Coastguard Worker
308*9880d681SAndroid Build Coastguard Worker // If the symbol is a variable and we weren't able to get a Base for it
309*9880d681SAndroid Build Coastguard Worker // (i.e., it's not in the symbol table associated with a section) resolve
310*9880d681SAndroid Build Coastguard Worker // the relocation based its expansion instead.
311*9880d681SAndroid Build Coastguard Worker if (Symbol->isVariable() && !Base) {
312*9880d681SAndroid Build Coastguard Worker // If the evaluation is an absolute value, just use that directly
313*9880d681SAndroid Build Coastguard Worker // to keep things easy.
314*9880d681SAndroid Build Coastguard Worker int64_t Res;
315*9880d681SAndroid Build Coastguard Worker if (Symbol->getVariableValue()->evaluateAsAbsolute(
316*9880d681SAndroid Build Coastguard Worker Res, Layout, Writer->getSectionAddressMap())) {
317*9880d681SAndroid Build Coastguard Worker FixedValue = Res;
318*9880d681SAndroid Build Coastguard Worker return;
319*9880d681SAndroid Build Coastguard Worker }
320*9880d681SAndroid Build Coastguard Worker
321*9880d681SAndroid Build Coastguard Worker // FIXME: Will the Target we already have ever have any data in it
322*9880d681SAndroid Build Coastguard Worker // we need to preserve and merge with the new Target? How about
323*9880d681SAndroid Build Coastguard Worker // the FixedValue?
324*9880d681SAndroid Build Coastguard Worker if (!Symbol->getVariableValue()->evaluateAsRelocatable(Target, &Layout,
325*9880d681SAndroid Build Coastguard Worker &Fixup)) {
326*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(Fixup.getLoc(),
327*9880d681SAndroid Build Coastguard Worker "unable to resolve variable '" +
328*9880d681SAndroid Build Coastguard Worker Symbol->getName() + "'");
329*9880d681SAndroid Build Coastguard Worker return;
330*9880d681SAndroid Build Coastguard Worker }
331*9880d681SAndroid Build Coastguard Worker return recordRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
332*9880d681SAndroid Build Coastguard Worker FixedValue);
333*9880d681SAndroid Build Coastguard Worker }
334*9880d681SAndroid Build Coastguard Worker
335*9880d681SAndroid Build Coastguard Worker // Relocations inside debug sections always use local relocations when
336*9880d681SAndroid Build Coastguard Worker // possible. This seems to be done because the debugger doesn't fully
337*9880d681SAndroid Build Coastguard Worker // understand relocation entries and expects to find values that
338*9880d681SAndroid Build Coastguard Worker // have already been fixed up.
339*9880d681SAndroid Build Coastguard Worker if (Symbol->isInSection()) {
340*9880d681SAndroid Build Coastguard Worker if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
341*9880d681SAndroid Build Coastguard Worker Base = nullptr;
342*9880d681SAndroid Build Coastguard Worker }
343*9880d681SAndroid Build Coastguard Worker
344*9880d681SAndroid Build Coastguard Worker // AArch64 uses external relocations as much as possible. For debug
345*9880d681SAndroid Build Coastguard Worker // sections, and for pointer-sized relocations (.quad), we allow section
346*9880d681SAndroid Build Coastguard Worker // relocations. It's code sections that run into trouble.
347*9880d681SAndroid Build Coastguard Worker if (Base) {
348*9880d681SAndroid Build Coastguard Worker RelSymbol = Base;
349*9880d681SAndroid Build Coastguard Worker
350*9880d681SAndroid Build Coastguard Worker // Add the local offset, if needed.
351*9880d681SAndroid Build Coastguard Worker if (Base != Symbol)
352*9880d681SAndroid Build Coastguard Worker Value +=
353*9880d681SAndroid Build Coastguard Worker Layout.getSymbolOffset(*Symbol) - Layout.getSymbolOffset(*Base);
354*9880d681SAndroid Build Coastguard Worker } else if (Symbol->isInSection()) {
355*9880d681SAndroid Build Coastguard Worker if (!CanUseLocalRelocation) {
356*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(
357*9880d681SAndroid Build Coastguard Worker Fixup.getLoc(),
358*9880d681SAndroid Build Coastguard Worker "unsupported relocation of local symbol '" + Symbol->getName() +
359*9880d681SAndroid Build Coastguard Worker "'. Must have non-local symbol earlier in section.");
360*9880d681SAndroid Build Coastguard Worker return;
361*9880d681SAndroid Build Coastguard Worker }
362*9880d681SAndroid Build Coastguard Worker // Adjust the relocation to be section-relative.
363*9880d681SAndroid Build Coastguard Worker // The index is the section ordinal (1-based).
364*9880d681SAndroid Build Coastguard Worker const MCSection &Sec = Symbol->getSection();
365*9880d681SAndroid Build Coastguard Worker Index = Sec.getOrdinal() + 1;
366*9880d681SAndroid Build Coastguard Worker Value += Writer->getSymbolAddress(*Symbol, Layout);
367*9880d681SAndroid Build Coastguard Worker
368*9880d681SAndroid Build Coastguard Worker if (IsPCRel)
369*9880d681SAndroid Build Coastguard Worker Value -= Writer->getFragmentAddress(Fragment, Layout) +
370*9880d681SAndroid Build Coastguard Worker Fixup.getOffset() + (1ULL << Log2Size);
371*9880d681SAndroid Build Coastguard Worker } else {
372*9880d681SAndroid Build Coastguard Worker // Resolve constant variables.
373*9880d681SAndroid Build Coastguard Worker if (Symbol->isVariable()) {
374*9880d681SAndroid Build Coastguard Worker int64_t Res;
375*9880d681SAndroid Build Coastguard Worker if (Symbol->getVariableValue()->evaluateAsAbsolute(
376*9880d681SAndroid Build Coastguard Worker Res, Layout, Writer->getSectionAddressMap())) {
377*9880d681SAndroid Build Coastguard Worker FixedValue = Res;
378*9880d681SAndroid Build Coastguard Worker return;
379*9880d681SAndroid Build Coastguard Worker }
380*9880d681SAndroid Build Coastguard Worker }
381*9880d681SAndroid Build Coastguard Worker Asm.getContext().reportError(Fixup.getLoc(),
382*9880d681SAndroid Build Coastguard Worker "unsupported relocation of variable '" +
383*9880d681SAndroid Build Coastguard Worker Symbol->getName() + "'");
384*9880d681SAndroid Build Coastguard Worker return;
385*9880d681SAndroid Build Coastguard Worker }
386*9880d681SAndroid Build Coastguard Worker }
387*9880d681SAndroid Build Coastguard Worker
388*9880d681SAndroid Build Coastguard Worker // If the relocation kind is Branch26, Page21, or Pageoff12, any addend
389*9880d681SAndroid Build Coastguard Worker // is represented via an Addend relocation, not encoded directly into
390*9880d681SAndroid Build Coastguard Worker // the instruction.
391*9880d681SAndroid Build Coastguard Worker if ((Type == MachO::ARM64_RELOC_BRANCH26 ||
392*9880d681SAndroid Build Coastguard Worker Type == MachO::ARM64_RELOC_PAGE21 ||
393*9880d681SAndroid Build Coastguard Worker Type == MachO::ARM64_RELOC_PAGEOFF12) &&
394*9880d681SAndroid Build Coastguard Worker Value) {
395*9880d681SAndroid Build Coastguard Worker assert((Value & 0xff000000) == 0 && "Added relocation out of range!");
396*9880d681SAndroid Build Coastguard Worker
397*9880d681SAndroid Build Coastguard Worker MachO::any_relocation_info MRE;
398*9880d681SAndroid Build Coastguard Worker MRE.r_word0 = FixupOffset;
399*9880d681SAndroid Build Coastguard Worker MRE.r_word1 =
400*9880d681SAndroid Build Coastguard Worker (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
401*9880d681SAndroid Build Coastguard Worker Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
402*9880d681SAndroid Build Coastguard Worker
403*9880d681SAndroid Build Coastguard Worker // Now set up the Addend relocation.
404*9880d681SAndroid Build Coastguard Worker Type = MachO::ARM64_RELOC_ADDEND;
405*9880d681SAndroid Build Coastguard Worker Index = Value;
406*9880d681SAndroid Build Coastguard Worker RelSymbol = nullptr;
407*9880d681SAndroid Build Coastguard Worker IsPCRel = 0;
408*9880d681SAndroid Build Coastguard Worker Log2Size = 2;
409*9880d681SAndroid Build Coastguard Worker
410*9880d681SAndroid Build Coastguard Worker // Put zero into the instruction itself. The addend is in the relocation.
411*9880d681SAndroid Build Coastguard Worker Value = 0;
412*9880d681SAndroid Build Coastguard Worker }
413*9880d681SAndroid Build Coastguard Worker
414*9880d681SAndroid Build Coastguard Worker // If there's any addend left to handle, encode it in the instruction.
415*9880d681SAndroid Build Coastguard Worker FixedValue = Value;
416*9880d681SAndroid Build Coastguard Worker
417*9880d681SAndroid Build Coastguard Worker // struct relocation_info (8 bytes)
418*9880d681SAndroid Build Coastguard Worker MachO::any_relocation_info MRE;
419*9880d681SAndroid Build Coastguard Worker MRE.r_word0 = FixupOffset;
420*9880d681SAndroid Build Coastguard Worker MRE.r_word1 =
421*9880d681SAndroid Build Coastguard Worker (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
422*9880d681SAndroid Build Coastguard Worker Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
423*9880d681SAndroid Build Coastguard Worker }
424*9880d681SAndroid Build Coastguard Worker
createAArch64MachObjectWriter(raw_pwrite_stream & OS,uint32_t CPUType,uint32_t CPUSubtype)425*9880d681SAndroid Build Coastguard Worker MCObjectWriter *llvm::createAArch64MachObjectWriter(raw_pwrite_stream &OS,
426*9880d681SAndroid Build Coastguard Worker uint32_t CPUType,
427*9880d681SAndroid Build Coastguard Worker uint32_t CPUSubtype) {
428*9880d681SAndroid Build Coastguard Worker return createMachObjectWriter(
429*9880d681SAndroid Build Coastguard Worker new AArch64MachObjectWriter(CPUType, CPUSubtype), OS,
430*9880d681SAndroid Build Coastguard Worker /*IsLittleEndian=*/true);
431*9880d681SAndroid Build Coastguard Worker }
432