2015-09-23 02:19:46 +08: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-14 03:51:57 +08:00
|
|
|
//
|
2015-10-16 03:52:27 +08:00
|
|
|
// Machine-specific things, such as applying relocations, creation of
|
|
|
|
// GOT or PLT entries, etc., are handled in this file.
|
|
|
|
//
|
2016-08-25 00:36:41 +08:00
|
|
|
// Refer the ELF spec for the single letter variables, S, A or P, used
|
2016-04-13 09:40:19 +08:00
|
|
|
// in this file.
|
2015-10-14 03:51:57 +08:00
|
|
|
//
|
2016-04-23 09:10:15 +08: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-14 03:51:57 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2015-09-23 02:19:46 +08:00
|
|
|
|
|
|
|
#include "Target.h"
|
2015-09-23 04:54:08 +08:00
|
|
|
#include "Error.h"
|
2016-04-01 05:26:23 +08:00
|
|
|
#include "InputFiles.h"
|
2015-10-09 04:06:07 +08:00
|
|
|
#include "OutputSections.h"
|
2016-12-21 08:05:39 +08:00
|
|
|
#include "SymbolTable.h"
|
2015-09-30 07:22:16 +08:00
|
|
|
#include "Symbols.h"
|
2015-09-23 04:54:08 +08:00
|
|
|
#include "llvm/Object/ELF.h"
|
2015-09-23 02:19:46 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
2015-09-23 04:54:08 +08:00
|
|
|
using namespace llvm::object;
|
2015-09-23 02:19:46 +08:00
|
|
|
using namespace llvm::ELF;
|
2017-06-17 01:32:43 +08:00
|
|
|
using namespace lld;
|
|
|
|
using namespace lld::elf;
|
|
|
|
|
|
|
|
TargetInfo *elf::Target;
|
2015-09-23 02:19:46 +08:00
|
|
|
|
2017-01-06 18:04:08 +08:00
|
|
|
std::string lld::toString(uint32_t Type) {
|
2017-01-26 05:27:59 +08:00
|
|
|
StringRef S = getELFRelocationTypeName(elf::Config->EMachine, Type);
|
|
|
|
if (S == "Unknown")
|
|
|
|
return ("Unknown (" + Twine(Type) + ")").str();
|
|
|
|
return S;
|
2017-01-06 18:04:08 +08:00
|
|
|
}
|
|
|
|
|
2017-06-17 04:15:03 +08:00
|
|
|
TargetInfo *elf::getTarget() {
|
2017-06-17 01:32:43 +08:00
|
|
|
switch (Config->EMachine) {
|
|
|
|
case EM_386:
|
|
|
|
case EM_IAMCU:
|
2017-06-17 04:15:03 +08:00
|
|
|
return getX86TargetInfo();
|
2017-06-17 01:32:43 +08:00
|
|
|
case EM_AARCH64:
|
2017-06-17 04:15:03 +08:00
|
|
|
return getAArch64TargetInfo();
|
2017-06-17 01:32:43 +08:00
|
|
|
case EM_AMDGPU:
|
2017-06-17 04:15:03 +08:00
|
|
|
return getAMDGPUTargetInfo();
|
2017-06-17 01:32:43 +08:00
|
|
|
case EM_ARM:
|
2017-06-17 04:15:03 +08:00
|
|
|
return getARMTargetInfo();
|
2017-06-17 01:32:43 +08:00
|
|
|
case EM_AVR:
|
2017-06-17 04:15:03 +08:00
|
|
|
return getAVRTargetInfo();
|
2017-06-17 01:32:43 +08:00
|
|
|
case EM_MIPS:
|
|
|
|
switch (Config->EKind) {
|
|
|
|
case ELF32LEKind:
|
2017-06-17 04:15:03 +08:00
|
|
|
return getMipsTargetInfo<ELF32LE>();
|
2017-06-17 01:32:43 +08:00
|
|
|
case ELF32BEKind:
|
2017-06-17 04:15:03 +08:00
|
|
|
return getMipsTargetInfo<ELF32BE>();
|
2017-06-17 01:32:43 +08:00
|
|
|
case ELF64LEKind:
|
2017-06-17 04:15:03 +08:00
|
|
|
return getMipsTargetInfo<ELF64LE>();
|
2017-06-17 01:32:43 +08:00
|
|
|
case ELF64BEKind:
|
2017-06-17 04:15:03 +08:00
|
|
|
return getMipsTargetInfo<ELF64BE>();
|
2017-06-17 01:32:43 +08:00
|
|
|
default:
|
|
|
|
fatal("unsupported MIPS target");
|
|
|
|
}
|
|
|
|
case EM_PPC:
|
2017-06-17 04:15:03 +08:00
|
|
|
return getPPCTargetInfo();
|
2017-06-17 01:32:43 +08:00
|
|
|
case EM_PPC64:
|
2017-06-17 04:15:03 +08:00
|
|
|
return getPPC64TargetInfo();
|
2017-06-29 01:05:39 +08:00
|
|
|
case EM_SPARCV9:
|
|
|
|
return getSPARCV9TargetInfo();
|
2017-06-17 01:32:43 +08:00
|
|
|
case EM_X86_64:
|
|
|
|
if (Config->EKind == ELF32LEKind)
|
2017-06-17 04:15:03 +08:00
|
|
|
return getX32TargetInfo();
|
|
|
|
return getX86_64TargetInfo();
|
2017-06-17 01:32:43 +08:00
|
|
|
}
|
|
|
|
fatal("unknown target machine");
|
|
|
|
}
|
2015-10-15 05:30:32 +08:00
|
|
|
|
2017-04-08 14:14:14 +08:00
|
|
|
template <class ELFT> static std::string getErrorLoc(const uint8_t *Loc) {
|
2017-02-27 10:32:08 +08:00
|
|
|
for (InputSectionBase *D : InputSections) {
|
2017-02-24 00:49:07 +08:00
|
|
|
auto *IS = dyn_cast_or_null<InputSection>(D);
|
2017-06-01 04:17:44 +08:00
|
|
|
if (!IS || !IS->getParent())
|
2016-12-21 08:05:39 +08:00
|
|
|
continue;
|
|
|
|
|
2017-06-01 04:17:44 +08:00
|
|
|
uint8_t *ISLoc = IS->getParent()->Loc + IS->OutSecOff;
|
2017-03-08 23:44:30 +08:00
|
|
|
if (ISLoc <= Loc && Loc < ISLoc + IS->getSize())
|
2017-02-23 10:28:28 +08:00
|
|
|
return IS->template getLocation<ELFT>(Loc - ISLoc) + ": ";
|
2016-12-21 08:05:39 +08:00
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2017-06-17 01:32:43 +08:00
|
|
|
std::string elf::getErrorLocation(const uint8_t *Loc) {
|
2016-12-21 08:05:39 +08: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-23 02:19:46 +08:00
|
|
|
TargetInfo::~TargetInfo() {}
|
|
|
|
|
2017-02-07 06:32:45 +08:00
|
|
|
int64_t TargetInfo::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const {
|
2016-03-30 20:40:38 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-28 22:34:39 +08:00
|
|
|
bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return false; }
|
2015-12-11 16:59:37 +08:00
|
|
|
|
2017-02-01 18:26:03 +08:00
|
|
|
bool TargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType,
|
|
|
|
const InputFile *File, const SymbolBody &S) const {
|
|
|
|
return false;
|
2016-04-01 05:26:23 +08:00
|
|
|
}
|
|
|
|
|
2017-07-18 00:54:29 +08:00
|
|
|
bool TargetInfo::inBranchRange(uint32_t RelocType, uint64_t Src,
|
|
|
|
uint64_t Dst) const {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-12-09 17:59:54 +08:00
|
|
|
void TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
|
|
|
|
writeGotPlt(Buf, S);
|
|
|
|
}
|
|
|
|
|
2016-06-05 06:58:54 +08: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-02 00:45:30 +08:00
|
|
|
return Expr;
|
2016-05-25 22:31:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const {
|
|
|
|
llvm_unreachable("Should not have claimed to be relaxable");
|
|
|
|
}
|
|
|
|
|
2016-04-13 09:40:19 +08:00
|
|
|
void TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type,
|
|
|
|
uint64_t Val) const {
|
2016-03-17 03:03:58 +08:00
|
|
|
llvm_unreachable("Should not have claimed to be relaxable");
|
|
|
|
}
|
|
|
|
|
2016-04-13 09:40:19 +08:00
|
|
|
void TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type,
|
|
|
|
uint64_t Val) const {
|
2016-03-17 03:03:58 +08:00
|
|
|
llvm_unreachable("Should not have claimed to be relaxable");
|
|
|
|
}
|
|
|
|
|
2016-04-13 09:40:19 +08:00
|
|
|
void TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type,
|
|
|
|
uint64_t Val) const {
|
2016-03-17 03:03:58 +08:00
|
|
|
llvm_unreachable("Should not have claimed to be relaxable");
|
|
|
|
}
|
|
|
|
|
2016-04-13 09:40:19 +08:00
|
|
|
void TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type,
|
|
|
|
uint64_t Val) const {
|
2016-03-17 03:03:58 +08:00
|
|
|
llvm_unreachable("Should not have claimed to be relaxable");
|
2015-11-26 05:46:05 +08:00
|
|
|
}
|