summaryrefslogtreecommitdiff
path: root/ELF/Target.h
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/Target.h')
-rw-r--r--ELF/Target.h111
1 files changed, 67 insertions, 44 deletions
diff --git a/ELF/Target.h b/ELF/Target.h
index 1658a81c9b71..2902dbc99149 100644
--- a/ELF/Target.h
+++ b/ELF/Target.h
@@ -10,25 +10,27 @@
#ifndef LLD_ELF_TARGET_H
#define LLD_ELF_TARGET_H
-#include "Error.h"
#include "InputSection.h"
+#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/ELF.h"
namespace lld {
-std::string toString(uint32_t RelType);
+std::string toString(elf::RelType Type);
namespace elf {
+class Defined;
class InputFile;
-class SymbolBody;
+class Symbol;
class TargetInfo {
public:
- virtual bool isPicRel(uint32_t Type) const { return true; }
- virtual uint32_t getDynRel(uint32_t Type) const { return Type; }
+ virtual uint32_t calcEFlags() const { return 0; }
+ virtual bool isPicRel(RelType Type) const { return true; }
+ virtual RelType getDynRel(RelType Type) const { return Type; }
virtual void writeGotPltHeader(uint8_t *Buf) const {}
- virtual void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const {};
- virtual void writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const;
- virtual int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const;
+ virtual void writeGotPlt(uint8_t *Buf, const Symbol &S) const {};
+ virtual void writeIgotPlt(uint8_t *Buf, const Symbol &S) const;
+ virtual int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const;
// If lazy binding is supported, the first entry of the PLT has code
// to call the dynamic linker to resolve PLT entries the first time
@@ -40,48 +42,52 @@ public:
unsigned RelOff) const {}
virtual void addPltHeaderSymbols(InputSectionBase *IS) const {}
virtual void addPltSymbols(InputSectionBase *IS, uint64_t Off) const {}
+
// Returns true if a relocation only uses the low bits of a value such that
// all those bits are in in the same page. For example, if the relocation
// only uses the low 12 bits in a system with 4k pages. If this is true, the
// bits will always have the same value at runtime and we don't have to emit
// a dynamic relocation.
- virtual bool usesOnlyLowPageBits(uint32_t Type) const;
+ virtual bool usesOnlyLowPageBits(RelType Type) const;
// Decide whether a Thunk is needed for the relocation from File
// targeting S.
- virtual bool needsThunk(RelExpr Expr, uint32_t RelocType,
- const InputFile *File, const SymbolBody &S) const;
+ virtual bool needsThunk(RelExpr Expr, RelType RelocType,
+ const InputFile *File, uint64_t BranchAddr,
+ const Symbol &S) const;
// Return true if we can reach Dst from Src with Relocation RelocType
- virtual bool inBranchRange(uint32_t RelocType, uint64_t Src,
+ virtual bool inBranchRange(RelType Type, uint64_t Src,
uint64_t Dst) const;
- virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S,
+ virtual RelExpr getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const = 0;
- virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const = 0;
+
+ virtual void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const = 0;
+
virtual ~TargetInfo();
unsigned TlsGdRelaxSkip = 1;
unsigned PageSize = 4096;
unsigned DefaultMaxPageSize = 4096;
- // On FreeBSD x86_64 the first page cannot be mmaped.
- // On Linux that is controled by vm.mmap_min_addr. At least on some x86_64
- // installs that is 65536, so the first 15 pages cannot be used.
- // Given that, the smallest value that can be used in here is 0x10000.
- uint64_t DefaultImageBase = 0x10000;
+ uint64_t getImageBase();
// Offset of _GLOBAL_OFFSET_TABLE_ from base of .got section. Use -1 for
// end of .got
uint64_t GotBaseSymOff = 0;
- uint32_t CopyRel;
- uint32_t GotRel;
- uint32_t PltRel;
- uint32_t RelativeRel;
- uint32_t IRelativeRel;
- uint32_t TlsDescRel;
- uint32_t TlsGotRel;
- uint32_t TlsModuleIndexRel;
- uint32_t TlsOffsetRel;
+ // On systems with range extensions we place collections of Thunks at
+ // regular spacings that enable the majority of branches reach the Thunks.
+ uint32_t ThunkSectionSpacing = 0;
+
+ RelType CopyRel;
+ RelType GotRel;
+ RelType PltRel;
+ RelType RelativeRel;
+ RelType IRelativeRel;
+ RelType TlsDescRel;
+ RelType TlsGotRel;
+ RelType TlsModuleIndexRel;
+ RelType TlsOffsetRel;
unsigned GotEntrySize = 0;
unsigned GotPltEntrySize = 0;
unsigned PltEntrySize;
@@ -100,13 +106,20 @@ public:
// executable OutputSections.
uint32_t TrapInstr = 0;
- virtual RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
+ virtual RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data,
RelExpr Expr) const;
virtual void relaxGot(uint8_t *Loc, uint64_t Val) const;
- virtual void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
- virtual void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
- virtual void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
- virtual void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
+ virtual void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const;
+ virtual void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const;
+ virtual void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const;
+ virtual void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const;
+
+protected:
+ // On FreeBSD x86_64 the first page cannot be mmaped.
+ // On Linux that is controled by vm.mmap_min_addr. At least on some x86_64
+ // installs that is 65536, so the first 15 pages cannot be used.
+ // Given that, the smallest value that can be used in here is 0x10000.
+ uint64_t DefaultImageBase = 0x10000;
};
TargetInfo *getAArch64TargetInfo();
@@ -129,32 +142,42 @@ uint64_t getAArch64Page(uint64_t Expr);
extern TargetInfo *Target;
TargetInfo *getTarget();
+template <class ELFT> bool isMipsPIC(const Defined *Sym);
+
+static inline void reportRangeError(uint8_t *Loc, RelType Type, const Twine &V,
+ int64_t Min, uint64_t Max) {
+ error(getErrorLocation(Loc) + "relocation " + lld::toString(Type) +
+ " out of range: " + V + " is not in [" + Twine(Min) + ", " +
+ Twine(Max) + "]");
+}
+
template <unsigned N>
-static void checkInt(uint8_t *Loc, int64_t V, uint32_t Type) {
+static void checkInt(uint8_t *Loc, int64_t V, RelType Type) {
if (!llvm::isInt<N>(V))
- error(getErrorLocation(Loc) + "relocation " + lld::toString(Type) +
- " out of range");
+ reportRangeError(Loc, Type, Twine(V), llvm::minIntN(N), llvm::maxIntN(N));
}
template <unsigned N>
-static void checkUInt(uint8_t *Loc, uint64_t V, uint32_t Type) {
+static void checkUInt(uint8_t *Loc, uint64_t V, RelType Type) {
if (!llvm::isUInt<N>(V))
- error(getErrorLocation(Loc) + "relocation " + lld::toString(Type) +
- " out of range");
+ reportRangeError(Loc, Type, Twine(V), 0, llvm::maxUIntN(N));
}
template <unsigned N>
-static void checkIntUInt(uint8_t *Loc, uint64_t V, uint32_t Type) {
+static void checkIntUInt(uint8_t *Loc, uint64_t V, RelType Type) {
if (!llvm::isInt<N>(V) && !llvm::isUInt<N>(V))
- error(getErrorLocation(Loc) + "relocation " + lld::toString(Type) +
- " out of range");
+ // For the error message we should cast V to a signed integer so that error
+ // messages show a small negative value rather than an extremely large one
+ reportRangeError(Loc, Type, Twine((int64_t)V), llvm::minIntN(N),
+ llvm::maxUIntN(N));
}
template <unsigned N>
-static void checkAlignment(uint8_t *Loc, uint64_t V, uint32_t Type) {
+static void checkAlignment(uint8_t *Loc, uint64_t V, RelType Type) {
if ((V & (N - 1)) != 0)
error(getErrorLocation(Loc) + "improper alignment for relocation " +
- lld::toString(Type));
+ lld::toString(Type) + ": 0x" + llvm::utohexstr(V) +
+ " is not aligned to " + Twine(N) + " bytes");
}
} // namespace elf
} // namespace lld