1//===- Target.cpp ---------------------------------------------------------===//
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// Machine-specific things, such as applying relocations, creation of
10// GOT or PLT entries, etc., are handled in this file.
11//
12// Refer the ELF spec for the single letter variables, S, A or P, used
13// in this file.
14//
15// Some functions defined in this file has "relaxTls" as part of their names.
16// They do peephole optimization for TLS variables by rewriting instructions.
17// They are not part of the ABI but optional optimization, so you can skip
18// them if you are not interested in how TLS variables are optimized.
19// See the following paper for the details.
20//
21// Ulrich Drepper, ELF Handling For Thread-Local Storage
22// http://www.akkadia.org/drepper/tls.pdf
23//
24//===----------------------------------------------------------------------===//
25
26#include "Target.h"
27#include "Arch/RISCVInternalRelocations.h"
28#include "InputFiles.h"
29#include "OutputSections.h"
30#include "RelocScan.h"
31#include "SymbolTable.h"
32#include "Symbols.h"
33#include "lld/Common/ErrorHandler.h"
34#include "llvm/Object/ELF.h"
35
36using namespace llvm;
37using namespace llvm::object;
38using namespace llvm::ELF;
39using namespace lld;
40using namespace lld::elf;
41
42std::string elf::toStr(Ctx &ctx, RelType type) {
43 StringRef s = getELFRelocationTypeName(Machine: ctx.arg.emachine, Type: type);
44 if (ctx.arg.emachine == EM_RISCV && s == "Unknown") {
45 auto VendorString = getRISCVVendorString(ty: type);
46 if (VendorString)
47 s = getRISCVVendorRelocationTypeName(Type: type & ~INTERNAL_RISCV_VENDOR_MASK,
48 Vendor: *VendorString);
49 if (s == "Unknown")
50 return ("Unknown vendor-specific (" + Twine(type) + ")").str();
51 }
52 if (s == "Unknown")
53 return ("Unknown (" + Twine(type) + ")").str();
54 return std::string(s);
55}
56
57const ELFSyncStream &elf::operator<<(const ELFSyncStream &s, RelType type) {
58 s << toStr(ctx&: s.ctx, type);
59 return s;
60}
61
62void elf::setTarget(Ctx &ctx) {
63 switch (ctx.arg.emachine) {
64 case EM_386:
65 case EM_IAMCU:
66 return setX86TargetInfo(ctx);
67 case EM_AARCH64:
68 return setAArch64TargetInfo(ctx);
69 case EM_AMDGPU:
70 return setAMDGPUTargetInfo(ctx);
71 case EM_ARM:
72 return setARMTargetInfo(ctx);
73 case EM_AVR:
74 return setAVRTargetInfo(ctx);
75 case EM_HEXAGON:
76 return setHexagonTargetInfo(ctx);
77 case EM_LOONGARCH:
78 return setLoongArchTargetInfo(ctx);
79 case EM_MIPS:
80 return setMipsTargetInfo(ctx);
81 case EM_MSP430:
82 return setMSP430TargetInfo(ctx);
83 case EM_PPC:
84 return setPPCTargetInfo(ctx);
85 case EM_PPC64:
86 return setPPC64TargetInfo(ctx);
87 case EM_RISCV:
88 return setRISCVTargetInfo(ctx);
89 case EM_SPARCV9:
90 return setSPARCV9TargetInfo(ctx);
91 case EM_S390:
92 return setSystemZTargetInfo(ctx);
93 case EM_X86_64:
94 return setX86_64TargetInfo(ctx);
95 default:
96 Fatal(ctx) << "unsupported e_machine value: " << ctx.arg.emachine;
97 }
98}
99
100ErrorPlace elf::getErrorPlace(Ctx &ctx, const uint8_t *loc) {
101 assert(loc != nullptr);
102 for (InputSectionBase *d : ctx.inputSections) {
103 auto *isec = dyn_cast<InputSection>(Val: d);
104 if (!isec || !isec->getParent() || (isec->type & SHT_NOBITS))
105 continue;
106
107 const uint8_t *isecLoc =
108 ctx.bufferStart
109 ? (ctx.bufferStart + isec->getParent()->offset + isec->outSecOff)
110 : isec->contentMaybeDecompress().data();
111 if (isecLoc == nullptr) {
112 assert(isa<SyntheticSection>(isec) && "No data but not synthetic?");
113 continue;
114 }
115 if (isecLoc <= loc && loc < isecLoc + isec->getSize()) {
116 std::string objLoc = isec->getLocation(offset: loc - isecLoc);
117 // Return object file location and source file location.
118 ELFSyncStream msg(ctx, DiagLevel::None);
119 if (isec->file)
120 msg << isec->getSrcMsg(sym: *ctx.dummySym, offset: loc - isecLoc);
121 return {.isec: isec, .loc: objLoc + ": ", .srcLoc: std::string(msg.str())};
122 }
123 }
124 return {};
125}
126
127TargetInfo::~TargetInfo() {}
128
129int64_t TargetInfo::getImplicitAddend(const uint8_t *buf, RelType type) const {
130 InternalErr(ctx, buf) << "cannot read addend for relocation " << type;
131 return 0;
132}
133
134bool TargetInfo::usesOnlyLowPageBits(RelType type) const { return false; }
135
136bool TargetInfo::needsThunk(RelExpr expr, RelType type, const InputFile *file,
137 uint64_t branchAddr, const Symbol &s,
138 int64_t a) const {
139 return false;
140}
141
142bool TargetInfo::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
143 uint8_t stOther) const {
144 Err(ctx) << "target doesn't support split stacks";
145 return false;
146}
147
148bool TargetInfo::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
149 return true;
150}
151
152RelExpr TargetInfo::adjustTlsExpr(RelType type, RelExpr expr) const {
153 return expr;
154}
155
156RelExpr TargetInfo::adjustGotPcExpr(RelType type, int64_t addend,
157 const uint8_t *data) const {
158 return R_GOT_PC;
159}
160
161static void relocateImpl(const TargetInfo &target, InputSectionBase &sec,
162 uint64_t secAddr, uint8_t *buf) {
163 auto &ctx = target.ctx;
164 const unsigned bits = ctx.arg.is64 ? 64 : 32;
165 for (const Relocation &rel : sec.relocs()) {
166 uint8_t *loc = buf + rel.offset;
167 const uint64_t val = SignExtend64(
168 X: sec.getRelocTargetVA(ctx, r: rel, p: secAddr + rel.offset), B: bits);
169 if (rel.expr != R_RELAX_HINT)
170 target.relocate(loc, rel, val);
171 }
172}
173
174void TargetInfo::relocateAlloc(InputSection &sec, uint8_t *buf) const {
175 uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff;
176 relocateImpl(target: *this, sec, secAddr, buf);
177}
178
179// A variant of relocateAlloc that processes an EhInputSection.
180void TargetInfo::relocateEh(EhInputSection &sec, uint8_t *buf) const {
181 uint64_t secAddr = sec.getOutputSection()->addr + sec.getParent()->outSecOff;
182 relocateImpl(target: *this, sec, secAddr, buf);
183}
184
185uint64_t TargetInfo::getImageBase() const {
186 // Use --image-base if set. Fall back to the target default if not.
187 if (ctx.arg.imageBase)
188 return *ctx.arg.imageBase;
189 return ctx.arg.isPic ? 0 : defaultImageBase;
190}
191