//===- Target.cpp ---------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Machine-specific things, such as applying relocations, creation of // GOT or PLT entries, etc., are handled in this file. // // Refer the ELF spec for the single letter variables, S, A or P, used // in this file. // // Some functions defined in this file has "relaxTls" as part of their names. // They do peephole optimization for TLS variables by rewriting instructions. // They are not part of the ABI but optional optimization, so you can skip // them if you are not interested in how TLS variables are optimized. // See the following paper for the details. // // Ulrich Drepper, ELF Handling For Thread-Local Storage // http://www.akkadia.org/drepper/tls.pdf // //===----------------------------------------------------------------------===// #include "Target.h" #include "Error.h" #include "InputFiles.h" #include "OutputSections.h" #include "SymbolTable.h" #include "Symbols.h" #include "llvm/Object/ELF.h" using namespace llvm; using namespace llvm::object; using namespace llvm::ELF; using namespace lld; using namespace lld::elf; TargetInfo *elf::Target; std::string lld::toString(uint32_t Type) { StringRef S = getELFRelocationTypeName(elf::Config->EMachine, Type); if (S == "Unknown") return ("Unknown (" + Twine(Type) + ")").str(); return S; } TargetInfo *elf::createTarget() { switch (Config->EMachine) { case EM_386: case EM_IAMCU: return createX86TargetInfo(); case EM_AARCH64: return createAArch64TargetInfo(); case EM_AMDGPU: return createAMDGPUTargetInfo(); case EM_ARM: return createARMTargetInfo(); case EM_AVR: return createAVRTargetInfo(); case EM_MIPS: switch (Config->EKind) { case ELF32LEKind: return createMipsTargetInfo(); case ELF32BEKind: return createMipsTargetInfo(); case ELF64LEKind: return createMipsTargetInfo(); case ELF64BEKind: return createMipsTargetInfo(); default: fatal("unsupported MIPS target"); } case EM_PPC: return createPPCTargetInfo(); case EM_PPC64: return createPPC64TargetInfo(); case EM_X86_64: if (Config->EKind == ELF32LEKind) return createX32TargetInfo(); return createX86_64TargetInfo(); } fatal("unknown target machine"); } template static std::string getErrorLoc(const uint8_t *Loc) { for (InputSectionBase *D : InputSections) { auto *IS = dyn_cast_or_null(D); if (!IS || !IS->getParent()) continue; uint8_t *ISLoc = IS->getParent()->Loc + IS->OutSecOff; if (ISLoc <= Loc && Loc < ISLoc + IS->getSize()) return IS->template getLocation(Loc - ISLoc) + ": "; } return ""; } std::string elf::getErrorLocation(const uint8_t *Loc) { switch (Config->EKind) { case ELF32LEKind: return getErrorLoc(Loc); case ELF32BEKind: return getErrorLoc(Loc); case ELF64LEKind: return getErrorLoc(Loc); case ELF64BEKind: return getErrorLoc(Loc); default: llvm_unreachable("unknown ELF type"); } } TargetInfo::~TargetInfo() {} int64_t TargetInfo::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { return 0; } bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return false; } bool TargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, const SymbolBody &S) const { return false; } void TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const { writeGotPlt(Buf, S); } RelExpr TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, RelExpr Expr) const { return Expr; } void TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const { llvm_unreachable("Should not have claimed to be relaxable"); } void TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { llvm_unreachable("Should not have claimed to be relaxable"); } void TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { llvm_unreachable("Should not have claimed to be relaxable"); } void TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { llvm_unreachable("Should not have claimed to be relaxable"); } void TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { llvm_unreachable("Should not have claimed to be relaxable"); }