xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
1 //===-- AArch64TargetObjectFile.cpp - AArch64 Object Info -----------------===//
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 #include "AArch64TargetObjectFile.h"
10 #include "AArch64TargetMachine.h"
11 #include "MCTargetDesc/AArch64MCAsmInfo.h"
12 #include "MCTargetDesc/AArch64TargetStreamer.h"
13 #include "llvm/BinaryFormat/Dwarf.h"
14 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
15 #include "llvm/IR/Mangler.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCSectionELF.h"
20 #include "llvm/MC/MCStreamer.h"
21 #include "llvm/MC/MCValue.h"
22 using namespace llvm;
23 using namespace dwarf;
24 
25 void AArch64_ELFTargetObjectFile::Initialize(MCContext &Ctx,
26                                              const TargetMachine &TM) {
27   TargetLoweringObjectFileELF::Initialize(Ctx, TM);
28   PLTRelativeSpecifier = AArch64::S_PLT;
29   SupportIndirectSymViaGOTPCRel = true;
30 
31   // AARCH64 ELF ABI does not define static relocation type for TLS offset
32   // within a module.  Do not generate AT_location for TLS variables.
33   SupportDebugThreadLocalLocation = false;
34 
35   // Make sure the implicitly created empty .text section has the
36   // SHF_AARCH64_PURECODE flag set if the "+execute-only" target feature is
37   // present.
38   if (TM.getMCSubtargetInfo()->hasFeature(AArch64::FeatureExecuteOnly)) {
39     auto *Text = cast<MCSectionELF>(TextSection);
40     Text->setFlags(Text->getFlags() | ELF::SHF_AARCH64_PURECODE);
41   }
42 }
43 
44 void AArch64_ELFTargetObjectFile::emitPersonalityValueImpl(
45     MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
46     const MachineModuleInfo *MMI) const {
47   if (!MMI->getObjFileInfo<MachineModuleInfoELF>().hasSignedPersonality()) {
48     TargetLoweringObjectFileELF::emitPersonalityValueImpl(Streamer, DL, Sym,
49                                                           MMI);
50     return;
51   }
52   auto *TS = static_cast<AArch64TargetStreamer *>(Streamer.getTargetStreamer());
53   // The value is ptrauth_string_discriminator("personality")
54   constexpr uint16_t Discriminator = 0x7EAD;
55   TS->emitAuthValue(MCSymbolRefExpr::create(Sym, getContext()), Discriminator,
56                     AArch64PACKey::IA, /*HasAddressDiversity=*/true);
57 }
58 
59 const MCExpr *AArch64_ELFTargetObjectFile::getIndirectSymViaGOTPCRel(
60     const GlobalValue *GV, const MCSymbol *Sym, const MCValue &MV,
61     int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const {
62   int64_t FinalOffset = Offset + MV.getConstant();
63   const MCExpr *Res =
64       MCSymbolRefExpr::create(Sym, AArch64::S_GOTPCREL, getContext());
65   const MCExpr *Off = MCConstantExpr::create(FinalOffset, getContext());
66   return MCBinaryExpr::createAdd(Res, Off, getContext());
67 }
68 
69 AArch64_MachoTargetObjectFile::AArch64_MachoTargetObjectFile() {
70   SupportGOTPCRelWithOffset = false;
71 }
72 
73 const MCExpr *AArch64_MachoTargetObjectFile::getTTypeGlobalReference(
74     const GlobalValue *GV, unsigned Encoding, const TargetMachine &TM,
75     MachineModuleInfo *MMI, MCStreamer &Streamer) const {
76   // On Darwin, we can reference dwarf symbols with foo@GOT-., which
77   // is an indirect pc-relative reference. The default implementation
78   // won't reference using the GOT, so we need this target-specific
79   // version.
80   if (Encoding & (DW_EH_PE_indirect | DW_EH_PE_pcrel)) {
81     const MCSymbol *Sym = TM.getSymbol(GV);
82     const MCExpr *Res =
83         MCSymbolRefExpr::create(Sym, AArch64::S_MACHO_GOT, getContext());
84     MCSymbol *PCSym = getContext().createTempSymbol();
85     Streamer.emitLabel(PCSym);
86     const MCExpr *PC = MCSymbolRefExpr::create(PCSym, getContext());
87     return MCBinaryExpr::createSub(Res, PC, getContext());
88   }
89 
90   return TargetLoweringObjectFileMachO::getTTypeGlobalReference(
91       GV, Encoding, TM, MMI, Streamer);
92 }
93 
94 MCSymbol *AArch64_MachoTargetObjectFile::getCFIPersonalitySymbol(
95     const GlobalValue *GV, const TargetMachine &TM,
96     MachineModuleInfo *MMI) const {
97   return TM.getSymbol(GV);
98 }
99 
100 const MCExpr *AArch64_MachoTargetObjectFile::getIndirectSymViaGOTPCRel(
101     const GlobalValue *GV, const MCSymbol *Sym, const MCValue &MV,
102     int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const {
103   assert((Offset+MV.getConstant() == 0) &&
104          "Arch64 does not support GOT PC rel with extra offset");
105   // On ARM64 Darwin, we can reference symbols with foo@GOT-., which
106   // is an indirect pc-relative reference.
107   const MCExpr *Res =
108       MCSymbolRefExpr::create(Sym, AArch64::S_MACHO_GOT, getContext());
109   MCSymbol *PCSym = getContext().createTempSymbol();
110   Streamer.emitLabel(PCSym);
111   const MCExpr *PC = MCSymbolRefExpr::create(PCSym, getContext());
112   return MCBinaryExpr::createSub(Res, PC, getContext());
113 }
114 
115 void AArch64_MachoTargetObjectFile::getNameWithPrefix(
116     SmallVectorImpl<char> &OutName, const GlobalValue *GV,
117     const TargetMachine &TM) const {
118   // AArch64 does not use section-relative relocations so any global symbol must
119   // be accessed via at least a linker-private symbol.
120   getMangler().getNameWithPrefix(OutName, GV, /* CannotUsePrivateLabel */ true);
121 }
122 
123 template <typename MachineModuleInfoTarget>
124 static MCSymbol *getAuthPtrSlotSymbolHelper(
125     MCContext &Ctx, const TargetMachine &TM, MachineModuleInfo *MMI,
126     MachineModuleInfoTarget &TargetMMI, const MCSymbol *RawSym,
127     AArch64PACKey::ID Key, uint16_t Discriminator) {
128   const DataLayout &DL = MMI->getModule()->getDataLayout();
129 
130   MCSymbol *StubSym = Ctx.getOrCreateSymbol(
131       DL.getLinkerPrivateGlobalPrefix() + RawSym->getName() +
132       Twine("$auth_ptr$") + AArch64PACKeyIDToString(Key) + Twine('$') +
133       Twine(Discriminator));
134 
135   const MCExpr *&StubAuthPtrRef = TargetMMI.getAuthPtrStubEntry(StubSym);
136 
137   if (StubAuthPtrRef)
138     return StubSym;
139 
140   const MCExpr *Sym = MCSymbolRefExpr::create(RawSym, Ctx);
141 
142   StubAuthPtrRef =
143       AArch64AuthMCExpr::create(Sym, Discriminator, Key,
144                                 /*HasAddressDiversity=*/false, Ctx);
145   return StubSym;
146 }
147 
148 MCSymbol *AArch64_ELFTargetObjectFile::getAuthPtrSlotSymbol(
149     const TargetMachine &TM, MachineModuleInfo *MMI, const MCSymbol *RawSym,
150     AArch64PACKey::ID Key, uint16_t Discriminator) const {
151   auto &ELFMMI = MMI->getObjFileInfo<MachineModuleInfoELF>();
152   return getAuthPtrSlotSymbolHelper(getContext(), TM, MMI, ELFMMI, RawSym, Key,
153                                     Discriminator);
154 }
155 
156 MCSymbol *AArch64_MachoTargetObjectFile::getAuthPtrSlotSymbol(
157     const TargetMachine &TM, MachineModuleInfo *MMI, const MCSymbol *RawSym,
158     AArch64PACKey::ID Key, uint16_t Discriminator) const {
159   auto &MachOMMI = MMI->getObjFileInfo<MachineModuleInfoMachO>();
160   return getAuthPtrSlotSymbolHelper(getContext(), TM, MMI, MachOMMI, RawSym,
161                                     Key, Discriminator);
162 }
163 
164 static bool isExecuteOnlyFunction(const GlobalObject *GO, SectionKind Kind,
165                                   const TargetMachine &TM) {
166   if (const Function *F = dyn_cast<Function>(GO))
167     if (TM.getSubtarget<AArch64Subtarget>(*F).genExecuteOnly() && Kind.isText())
168       return true;
169   return false;
170 }
171 
172 MCSection *AArch64_ELFTargetObjectFile::getExplicitSectionGlobal(
173     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
174   // Set execute-only access for the explicit section
175   if (isExecuteOnlyFunction(GO, Kind, TM))
176     Kind = SectionKind::getExecuteOnly();
177 
178   return TargetLoweringObjectFileELF::getExplicitSectionGlobal(GO, Kind, TM);
179 }
180 
181 MCSection *AArch64_ELFTargetObjectFile::SelectSectionForGlobal(
182     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
183   // Set execute-only access for the explicit section
184   if (isExecuteOnlyFunction(GO, Kind, TM))
185     Kind = SectionKind::getExecuteOnly();
186 
187   return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);
188 }
189