Path: blob/main/contrib/llvm-project/lld/ELF/Target.cpp
34878 views
//===- Target.cpp ---------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Machine-specific things, such as applying relocations, creation of9// GOT or PLT entries, etc., are handled in this file.10//11// Refer the ELF spec for the single letter variables, S, A or P, used12// in this file.13//14// Some functions defined in this file has "relaxTls" as part of their names.15// They do peephole optimization for TLS variables by rewriting instructions.16// They are not part of the ABI but optional optimization, so you can skip17// them if you are not interested in how TLS variables are optimized.18// See the following paper for the details.19//20// Ulrich Drepper, ELF Handling For Thread-Local Storage21// http://www.akkadia.org/drepper/tls.pdf22//23//===----------------------------------------------------------------------===//2425#include "Target.h"26#include "InputFiles.h"27#include "OutputSections.h"28#include "SymbolTable.h"29#include "Symbols.h"30#include "SyntheticSections.h"31#include "lld/Common/ErrorHandler.h"32#include "llvm/Object/ELF.h"3334using namespace llvm;35using namespace llvm::object;36using namespace llvm::ELF;37using namespace lld;38using namespace lld::elf;3940const TargetInfo *elf::target;4142std::string lld::toString(RelType type) {43StringRef s = getELFRelocationTypeName(elf::config->emachine, type);44if (s == "Unknown")45return ("Unknown (" + Twine(type) + ")").str();46return std::string(s);47}4849TargetInfo *elf::getTarget() {50switch (config->emachine) {51case EM_386:52case EM_IAMCU:53return getX86TargetInfo();54case EM_AARCH64:55return getAArch64TargetInfo();56case EM_AMDGPU:57return getAMDGPUTargetInfo();58case EM_ARM:59return getARMTargetInfo();60case EM_AVR:61return getAVRTargetInfo();62case EM_HEXAGON:63return getHexagonTargetInfo();64case EM_LOONGARCH:65return getLoongArchTargetInfo();66case EM_MIPS:67switch (config->ekind) {68case ELF32LEKind:69return getMipsTargetInfo<ELF32LE>();70case ELF32BEKind:71return getMipsTargetInfo<ELF32BE>();72case ELF64LEKind:73return getMipsTargetInfo<ELF64LE>();74case ELF64BEKind:75return getMipsTargetInfo<ELF64BE>();76default:77llvm_unreachable("unsupported MIPS target");78}79case EM_MSP430:80return getMSP430TargetInfo();81case EM_PPC:82return getPPCTargetInfo();83case EM_PPC64:84return getPPC64TargetInfo();85case EM_RISCV:86return getRISCVTargetInfo();87case EM_SPARCV9:88return getSPARCV9TargetInfo();89case EM_S390:90return getSystemZTargetInfo();91case EM_X86_64:92return getX86_64TargetInfo();93default:94fatal("unsupported e_machine value: " + Twine(config->emachine));95}96}9798ErrorPlace elf::getErrorPlace(const uint8_t *loc) {99assert(loc != nullptr);100for (InputSectionBase *d : ctx.inputSections) {101auto *isec = dyn_cast<InputSection>(d);102if (!isec || !isec->getParent() || (isec->type & SHT_NOBITS))103continue;104105const uint8_t *isecLoc =106Out::bufferStart107? (Out::bufferStart + isec->getParent()->offset + isec->outSecOff)108: isec->contentMaybeDecompress().data();109if (isecLoc == nullptr) {110assert(isa<SyntheticSection>(isec) && "No data but not synthetic?");111continue;112}113if (isecLoc <= loc && loc < isecLoc + isec->getSize()) {114std::string objLoc = isec->getLocation(loc - isecLoc);115// Return object file location and source file location.116// TODO: Refactor getSrcMsg not to take a variable.117Undefined dummy(ctx.internalFile, "", STB_LOCAL, 0, 0);118return {isec, objLoc + ": ",119isec->file ? isec->getSrcMsg(dummy, loc - isecLoc) : ""};120}121}122return {};123}124125TargetInfo::~TargetInfo() {}126127int64_t TargetInfo::getImplicitAddend(const uint8_t *buf, RelType type) const {128internalLinkerError(getErrorLocation(buf),129"cannot read addend for relocation " + toString(type));130return 0;131}132133bool TargetInfo::usesOnlyLowPageBits(RelType type) const { return false; }134135bool TargetInfo::needsThunk(RelExpr expr, RelType type, const InputFile *file,136uint64_t branchAddr, const Symbol &s,137int64_t a) const {138return false;139}140141bool TargetInfo::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,142uint8_t stOther) const {143fatal("target doesn't support split stacks");144}145146bool TargetInfo::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {147return true;148}149150RelExpr TargetInfo::adjustTlsExpr(RelType type, RelExpr expr) const {151return expr;152}153154RelExpr TargetInfo::adjustGotPcExpr(RelType type, int64_t addend,155const uint8_t *data) const {156return R_GOT_PC;157}158159void TargetInfo::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {160const unsigned bits = config->is64 ? 64 : 32;161uint64_t secAddr = sec.getOutputSection()->addr;162if (auto *s = dyn_cast<InputSection>(&sec))163secAddr += s->outSecOff;164else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))165secAddr += ehIn->getParent()->outSecOff;166for (const Relocation &rel : sec.relocs()) {167uint8_t *loc = buf + rel.offset;168const uint64_t val = SignExtend64(169sec.getRelocTargetVA(sec.file, rel.type, rel.addend,170secAddr + rel.offset, *rel.sym, rel.expr),171bits);172if (rel.expr != R_RELAX_HINT)173relocate(loc, rel, val);174}175}176177uint64_t TargetInfo::getImageBase() const {178// Use --image-base if set. Fall back to the target default if not.179if (config->imageBase)180return *config->imageBase;181return config->isPic ? 0 : defaultImageBase;182}183184185