2015-09-22 18:19:46 +00:00
|
|
|
//===- Target.cpp ---------------------------------------------------------===//
|
|
|
|
|
//
|
|
|
|
|
// The LLVM Linker
|
|
|
|
|
//
|
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
2015-10-13 19:51:57 +00:00
|
|
|
//
|
2015-10-15 19:52:27 +00:00
|
|
|
// Machine-specific things, such as applying relocations, creation of
|
|
|
|
|
// GOT or PLT entries, etc., are handled in this file.
|
|
|
|
|
//
|
2016-08-24 16:36:41 +00:00
|
|
|
// Refer the ELF spec for the single letter variables, S, A or P, used
|
2016-04-13 01:40:19 +00:00
|
|
|
// in this file.
|
2015-10-13 19:51:57 +00:00
|
|
|
//
|
2016-04-23 01:10:15 +00:00
|
|
|
// 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
|
|
|
|
|
//
|
2015-10-13 19:51:57 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
2015-09-22 18:19:46 +00:00
|
|
|
|
|
|
|
|
#include "Target.h"
|
2015-09-22 20:54:08 +00:00
|
|
|
#include "Error.h"
|
2016-03-31 21:26:23 +00:00
|
|
|
#include "InputFiles.h"
|
2015-10-08 20:06:07 +00:00
|
|
|
#include "OutputSections.h"
|
2016-12-21 00:05:39 +00:00
|
|
|
#include "SymbolTable.h"
|
2015-09-29 23:22:16 +00:00
|
|
|
#include "Symbols.h"
|
2015-09-22 20:54:08 +00:00
|
|
|
#include "llvm/Object/ELF.h"
|
2015-09-22 18:19:46 +00:00
|
|
|
|
|
|
|
|
using namespace llvm;
|
2015-09-22 20:54:08 +00:00
|
|
|
using namespace llvm::object;
|
2015-09-22 18:19:46 +00:00
|
|
|
using namespace llvm::ELF;
|
2017-06-16 17:32:43 +00:00
|
|
|
using namespace lld;
|
|
|
|
|
using namespace lld::elf;
|
|
|
|
|
|
|
|
|
|
TargetInfo *elf::Target;
|
2015-09-22 18:19:46 +00:00
|
|
|
|
2017-01-06 10:04:08 +00:00
|
|
|
std::string lld::toString(uint32_t Type) {
|
2017-01-25 21:27:59 +00:00
|
|
|
StringRef S = getELFRelocationTypeName(elf::Config->EMachine, Type);
|
|
|
|
|
if (S == "Unknown")
|
|
|
|
|
return ("Unknown (" + Twine(Type) + ")").str();
|
|
|
|
|
return S;
|
2017-01-06 10:04:08 +00:00
|
|
|
}
|
|
|
|
|
|
2017-06-16 20:15:03 +00:00
|
|
|
TargetInfo *elf::getTarget() {
|
2017-06-16 17:32:43 +00:00
|
|
|
switch (Config->EMachine) {
|
|
|
|
|
case EM_386:
|
|
|
|
|
case EM_IAMCU:
|
2017-06-16 20:15:03 +00:00
|
|
|
return getX86TargetInfo();
|
2017-06-16 17:32:43 +00:00
|
|
|
case EM_AARCH64:
|
2017-06-16 20:15:03 +00:00
|
|
|
return getAArch64TargetInfo();
|
2017-06-16 17:32:43 +00:00
|
|
|
case EM_AMDGPU:
|
2017-06-16 20:15:03 +00:00
|
|
|
return getAMDGPUTargetInfo();
|
2017-06-16 17:32:43 +00:00
|
|
|
case EM_ARM:
|
2017-06-16 20:15:03 +00:00
|
|
|
return getARMTargetInfo();
|
2017-06-16 17:32:43 +00:00
|
|
|
case EM_AVR:
|
2017-06-16 20:15:03 +00:00
|
|
|
return getAVRTargetInfo();
|
2017-06-16 17:32:43 +00:00
|
|
|
case EM_MIPS:
|
|
|
|
|
switch (Config->EKind) {
|
|
|
|
|
case ELF32LEKind:
|
2017-06-16 20:15:03 +00:00
|
|
|
return getMipsTargetInfo<ELF32LE>();
|
2017-06-16 17:32:43 +00:00
|
|
|
case ELF32BEKind:
|
2017-06-16 20:15:03 +00:00
|
|
|
return getMipsTargetInfo<ELF32BE>();
|
2017-06-16 17:32:43 +00:00
|
|
|
case ELF64LEKind:
|
2017-06-16 20:15:03 +00:00
|
|
|
return getMipsTargetInfo<ELF64LE>();
|
2017-06-16 17:32:43 +00:00
|
|
|
case ELF64BEKind:
|
2017-06-16 20:15:03 +00:00
|
|
|
return getMipsTargetInfo<ELF64BE>();
|
2017-06-16 17:32:43 +00:00
|
|
|
default:
|
|
|
|
|
fatal("unsupported MIPS target");
|
|
|
|
|
}
|
|
|
|
|
case EM_PPC:
|
2017-06-16 20:15:03 +00:00
|
|
|
return getPPCTargetInfo();
|
2017-06-16 17:32:43 +00:00
|
|
|
case EM_PPC64:
|
2017-06-16 20:15:03 +00:00
|
|
|
return getPPC64TargetInfo();
|
2017-06-28 17:05:39 +00:00
|
|
|
case EM_SPARCV9:
|
|
|
|
|
return getSPARCV9TargetInfo();
|
2017-06-16 17:32:43 +00:00
|
|
|
case EM_X86_64:
|
|
|
|
|
if (Config->EKind == ELF32LEKind)
|
2017-06-16 20:15:03 +00:00
|
|
|
return getX32TargetInfo();
|
|
|
|
|
return getX86_64TargetInfo();
|
2017-06-16 17:32:43 +00:00
|
|
|
}
|
|
|
|
|
fatal("unknown target machine");
|
|
|
|
|
}
|
2015-10-14 21:30:32 +00:00
|
|
|
|
2017-04-08 06:14:14 +00:00
|
|
|
template <class ELFT> static std::string getErrorLoc(const uint8_t *Loc) {
|
2017-02-27 02:32:08 +00:00
|
|
|
for (InputSectionBase *D : InputSections) {
|
2017-02-23 16:49:07 +00:00
|
|
|
auto *IS = dyn_cast_or_null<InputSection>(D);
|
2017-05-31 20:17:44 +00:00
|
|
|
if (!IS || !IS->getParent())
|
2016-12-21 00:05:39 +00:00
|
|
|
continue;
|
|
|
|
|
|
2017-05-31 20:17:44 +00:00
|
|
|
uint8_t *ISLoc = IS->getParent()->Loc + IS->OutSecOff;
|
2017-03-08 15:44:30 +00:00
|
|
|
if (ISLoc <= Loc && Loc < ISLoc + IS->getSize())
|
2017-02-23 02:28:28 +00:00
|
|
|
return IS->template getLocation<ELFT>(Loc - ISLoc) + ": ";
|
2016-12-21 00:05:39 +00:00
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-16 17:32:43 +00:00
|
|
|
std::string elf::getErrorLocation(const uint8_t *Loc) {
|
2016-12-21 00:05:39 +00:00
|
|
|
switch (Config->EKind) {
|
|
|
|
|
case ELF32LEKind:
|
|
|
|
|
return getErrorLoc<ELF32LE>(Loc);
|
|
|
|
|
case ELF32BEKind:
|
|
|
|
|
return getErrorLoc<ELF32BE>(Loc);
|
|
|
|
|
case ELF64LEKind:
|
|
|
|
|
return getErrorLoc<ELF64LE>(Loc);
|
|
|
|
|
case ELF64BEKind:
|
|
|
|
|
return getErrorLoc<ELF64BE>(Loc);
|
|
|
|
|
default:
|
|
|
|
|
llvm_unreachable("unknown ELF type");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-22 18:19:46 +00:00
|
|
|
TargetInfo::~TargetInfo() {}
|
|
|
|
|
|
2017-02-06 22:32:45 +00:00
|
|
|
int64_t TargetInfo::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const {
|
2016-03-30 12:40:38 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-28 14:34:39 +00:00
|
|
|
bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return false; }
|
2015-12-11 08:59:37 +00:00
|
|
|
|
2017-02-01 10:26:03 +00:00
|
|
|
bool TargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType,
|
|
|
|
|
const InputFile *File, const SymbolBody &S) const {
|
|
|
|
|
return false;
|
2016-03-31 21:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
2017-07-17 16:54:29 +00:00
|
|
|
bool TargetInfo::inBranchRange(uint32_t RelocType, uint64_t Src,
|
|
|
|
|
uint64_t Dst) const {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-09 09:59:54 +00:00
|
|
|
void TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
|
|
|
|
|
writeGotPlt(Buf, S);
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-04 22:58:54 +00:00
|
|
|
RelExpr TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
|
|
|
|
|
RelExpr Expr) const {
|
[ELF] - Implemented support for test/binop relaxations from latest ABI.
Patch implements next relaxation from latest ABI:
"Convert memory operand of test and binop into immediate operand, where binop is one of adc, add, and, cmp, or,
sbb, sub, xor instructions, when position-independent code is disabled."
It is described in System V Application Binary Interface AMD64 Architecture Processor
Supplement Draft Version 0.99.8 (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-r249.pdf,
B.2 "B.2 Optimize GOTPCRELX Relocations").
Differential revision: http://reviews.llvm.org/D20793
llvm-svn: 271405
2016-06-01 16:45:30 +00:00
|
|
|
return Expr;
|
2016-05-25 14:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const {
|
|
|
|
|
llvm_unreachable("Should not have claimed to be relaxable");
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-13 01:40:19 +00:00
|
|
|
void TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type,
|
|
|
|
|
uint64_t Val) const {
|
2016-03-16 19:03:58 +00:00
|
|
|
llvm_unreachable("Should not have claimed to be relaxable");
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-13 01:40:19 +00:00
|
|
|
void TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type,
|
|
|
|
|
uint64_t Val) const {
|
2016-03-16 19:03:58 +00:00
|
|
|
llvm_unreachable("Should not have claimed to be relaxable");
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-13 01:40:19 +00:00
|
|
|
void TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type,
|
|
|
|
|
uint64_t Val) const {
|
2016-03-16 19:03:58 +00:00
|
|
|
llvm_unreachable("Should not have claimed to be relaxable");
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-13 01:40:19 +00:00
|
|
|
void TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type,
|
|
|
|
|
uint64_t Val) const {
|
2016-03-16 19:03:58 +00:00
|
|
|
llvm_unreachable("Should not have claimed to be relaxable");
|
2015-11-25 21:46:05 +00:00
|
|
|
}
|