Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -19,60 +19,38 @@ template class InputSection; template class InputSectionBase; +// There must be less than 2^PredicateShift RelExpr's. +// Bits beyond the low PredicateShift bits each encode a predicate +// that lets us efficiently do a test of the form +// `E == R_FOO || E == R_BAR || ...` with a single expression `E & RPRED_BAZ`. +enum { PredicateShift = 6 }; + +constexpr uint32_t predicateBit(int N) { return 1 << (N + PredicateShift); } + +enum RelExprPredicateBit { + RPRED_NEEDS_PLT = predicateBit(0), + RPRED_ALWAYS_CONSTANT = predicateBit(1), + RPRED_REFERS_TO_GOT = predicateBit(2), + RPRED_RELAX_MARKER = predicateBit(3), + RPRED_RELATIVE = predicateBit(4), +}; + // List of target-independent relocation types. Relocations read // from files are converted to these types so that the main code // doesn't have to know about architecture-specific details. enum RelExpr { - R_ABS, - R_GOT, - R_GOTONLY_PC, - R_GOTONLY_PC_FROM_END, - R_GOTREL, - R_GOTREL_FROM_END, - R_GOT_FROM_END, - R_GOT_OFF, - R_GOT_PAGE_PC, - R_GOT_PC, - R_HINT, - R_MIPS_GOT_LOCAL_PAGE, - R_MIPS_GOT_OFF, - R_MIPS_GOT_OFF32, - R_MIPS_GOTREL, - R_MIPS_TLSGD, - R_MIPS_TLSLD, - R_NEG_TLS, - R_PAGE_PC, - R_PC, - R_PLT, - R_PLT_PC, - R_PLT_PAGE_PC, - R_PPC_OPD, - R_PPC_PLT_OPD, - R_PPC_TOC, - R_RELAX_GOT_PC, - R_RELAX_GOT_PC_NOPIC, - R_RELAX_TLS_GD_TO_IE, - R_RELAX_TLS_GD_TO_IE_END, - R_RELAX_TLS_GD_TO_IE_ABS, - R_RELAX_TLS_GD_TO_IE_PAGE_PC, - R_RELAX_TLS_GD_TO_LE, - R_RELAX_TLS_GD_TO_LE_NEG, - R_RELAX_TLS_IE_TO_LE, - R_RELAX_TLS_LD_TO_LE, - R_SIZE, - R_THUNK_ABS, - R_THUNK_PC, - R_THUNK_PLT_PC, - R_TLS, - R_TLSDESC, - R_TLSDESC_PAGE, - R_TLSDESC_CALL, - R_TLSGD, - R_TLSGD_PC, - R_TLSLD, - R_TLSLD_PC, +#define RELOCATION(Name, Index, PredicateBits) Name = (Index | PredicateBits), +#include "Relocations.def" }; +// Sanity-check that all relocation indices are in-bounds. +// If this ever fails, just increase PredicateShift above. +#define RELOCATION(Name, Index, PredicateBits) \ + static_assert(Index < (1 << PredicateShift), \ + "Increase PredicateShift so that all relocs fit!"); +#include "Relocations.def" + + // Architecture-neutral representation of relocation. struct Relocation { RelExpr Expr; Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -62,12 +62,7 @@ namespace elf { static bool refersToGotEntry(RelExpr Expr) { - return Expr == R_GOT || Expr == R_GOT_OFF || Expr == R_MIPS_GOT_LOCAL_PAGE || - Expr == R_MIPS_GOT_OFF || Expr == R_MIPS_GOT_OFF32 || - Expr == R_MIPS_TLSGD || Expr == R_MIPS_TLSLD || - Expr == R_GOT_PAGE_PC || Expr == R_GOT_PC || Expr == R_GOT_FROM_END || - Expr == R_TLSGD || Expr == R_TLSGD_PC || Expr == R_TLSDESC || - Expr == R_TLSDESC_PAGE; + return Expr & RPRED_REFERS_TO_GOT; } static bool isPreemptible(const SymbolBody &Body, uint32_t Type) { @@ -290,18 +285,11 @@ return isAbsolute(Body) || Body.isTls(); } -static bool needsPlt(RelExpr Expr) { - return Expr == R_PLT_PC || Expr == R_PPC_PLT_OPD || Expr == R_PLT || - Expr == R_PLT_PAGE_PC || Expr == R_THUNK_PLT_PC; -} +static bool needsPlt(RelExpr Expr) { return Expr & RPRED_NEEDS_PLT; } // True if this expression is of the form Sym - X, where X is a position in the // file (PC, or GOT for example). -static bool isRelExpr(RelExpr Expr) { - return Expr == R_PC || Expr == R_GOTREL || Expr == R_GOTREL_FROM_END || - Expr == R_MIPS_GOTREL || Expr == R_PAGE_PC || Expr == R_RELAX_GOT_PC || - Expr == R_THUNK_PC || Expr == R_THUNK_PLT_PC; -} +static bool isRelExpr(RelExpr Expr) { return Expr & RPRED_RELATIVE; } template static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, @@ -309,12 +297,7 @@ InputSectionBase &S, typename ELFT::uint RelOff) { // These expressions always compute a constant - if (E == R_SIZE || E == R_GOT_FROM_END || E == R_GOT_OFF || - E == R_MIPS_GOT_LOCAL_PAGE || E == R_MIPS_GOT_OFF || - E == R_MIPS_GOT_OFF32 || E == R_MIPS_TLSGD || E == R_GOT_PAGE_PC || - E == R_GOT_PC || E == R_PLT_PC || E == R_TLSGD_PC || E == R_TLSGD || - E == R_PPC_PLT_OPD || E == R_TLSDESC_CALL || E == R_TLSDESC_PAGE || - E == R_HINT || E == R_THUNK_PC || E == R_THUNK_PLT_PC) + if (E & RPRED_ALWAYS_CONSTANT) return true; // These never do, except if the entire file is position dependent or if @@ -648,7 +631,7 @@ // Ignore "hint" and TLS Descriptor call relocation because they are // only markers for relaxation. - if (Expr == R_HINT || Expr == R_TLSDESC_CALL) + if (Expr & RPRED_RELAX_MARKER) continue; if (needsPlt(Expr) || Expr == R_THUNK_ABS || Expr == R_THUNK_PC || Index: ELF/Relocations.def =================================================================== --- /dev/null +++ ELF/Relocations.def @@ -0,0 +1,76 @@ +//===- Relocations.def -----------------------------------------*- C++ -*-===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// NOTE: No include guard desired! + +#ifndef RELOCATION +#define RELOCATION(Name, Index, PredicateBits) +#endif + +// RELOCATION(Name, Index, PredicateBits) +// +// Index and PredicateBits are just OR'd together to get the RelExpr +// value, but they are kept separate here so that we can do a +// compile-time check that the Index values don't collide with the +// PredicateBits values. +RELOCATION(R_ABS , 0, 0) +RELOCATION(R_GOT , 1, RPRED_REFERS_TO_GOT) +RELOCATION(R_GOTONLY_PC , 2, 0) +RELOCATION(R_GOTONLY_PC_FROM_END , 3, 0) +RELOCATION(R_GOTREL , 4, RPRED_RELATIVE) +RELOCATION(R_GOTREL_FROM_END , 5, RPRED_RELATIVE) +RELOCATION(R_GOT_FROM_END , 6, RPRED_ALWAYS_CONSTANT | RPRED_REFERS_TO_GOT) +RELOCATION(R_GOT_OFF , 7, RPRED_ALWAYS_CONSTANT | RPRED_REFERS_TO_GOT) +RELOCATION(R_GOT_PAGE_PC , 8, RPRED_ALWAYS_CONSTANT | RPRED_REFERS_TO_GOT) +RELOCATION(R_GOT_PC , 9, RPRED_ALWAYS_CONSTANT | RPRED_REFERS_TO_GOT) +RELOCATION(R_HINT , 10, RPRED_ALWAYS_CONSTANT | RPRED_RELAX_MARKER) +RELOCATION(R_MIPS_GOT_LOCAL_PAGE , 11, RPRED_ALWAYS_CONSTANT | RPRED_REFERS_TO_GOT) +RELOCATION(R_MIPS_GOT_OFF , 12, RPRED_ALWAYS_CONSTANT | RPRED_REFERS_TO_GOT) +RELOCATION(R_MIPS_GOT_OFF32 , 13, RPRED_ALWAYS_CONSTANT | RPRED_REFERS_TO_GOT) +RELOCATION(R_MIPS_GOTREL , 14, RPRED_RELATIVE) +RELOCATION(R_MIPS_TLSGD , 15, RPRED_ALWAYS_CONSTANT | RPRED_REFERS_TO_GOT) +RELOCATION(R_MIPS_TLSLD , 16, RPRED_REFERS_TO_GOT) +RELOCATION(R_NEG_TLS , 17, 0) +RELOCATION(R_PAGE_PC , 18, RPRED_RELATIVE) +RELOCATION(R_PC , 19, RPRED_RELATIVE) +RELOCATION(R_PLT , 20, RPRED_NEEDS_PLT) +RELOCATION(R_PLT_PC , 21, RPRED_NEEDS_PLT | RPRED_ALWAYS_CONSTANT) +RELOCATION(R_PLT_PAGE_PC , 22, RPRED_NEEDS_PLT) +RELOCATION(R_PPC_OPD , 23, 0) +RELOCATION(R_PPC_PLT_OPD , 24, RPRED_NEEDS_PLT | RPRED_ALWAYS_CONSTANT) +RELOCATION(R_PPC_TOC , 25, 0) +RELOCATION(R_RELAX_GOT_PC , 26, RPRED_RELATIVE) +RELOCATION(R_RELAX_GOT_PC_NOPIC , 27, 0) +RELOCATION(R_RELAX_TLS_GD_TO_IE , 28, 0) +RELOCATION(R_RELAX_TLS_GD_TO_IE_END , 29, 0) +RELOCATION(R_RELAX_TLS_GD_TO_IE_ABS , 30, 0) +RELOCATION(R_RELAX_TLS_GD_TO_IE_PAGE_PC , 31, 0) +RELOCATION(R_RELAX_TLS_GD_TO_LE , 32, 0) +RELOCATION(R_RELAX_TLS_GD_TO_LE_NEG , 33, 0) +RELOCATION(R_RELAX_TLS_IE_TO_LE , 34, 0) +RELOCATION(R_RELAX_TLS_LD_TO_LE , 35, 0) +RELOCATION(R_SIZE , 36, RPRED_ALWAYS_CONSTANT) +RELOCATION(R_THUNK_ABS , 37, 0) +RELOCATION(R_THUNK_PC , 38, RPRED_ALWAYS_CONSTANT | RPRED_RELATIVE) +RELOCATION(R_THUNK_PLT_PC , 39, RPRED_NEEDS_PLT | RPRED_ALWAYS_CONSTANT | RPRED_RELATIVE) +RELOCATION(R_TLS , 40, 0) +RELOCATION(R_TLSDESC , 41, RPRED_REFERS_TO_GOT) +RELOCATION(R_TLSDESC_PAGE , 42, RPRED_ALWAYS_CONSTANT | RPRED_REFERS_TO_GOT) +RELOCATION(R_TLSDESC_CALL , 43, RPRED_ALWAYS_CONSTANT | RPRED_RELAX_MARKER) +RELOCATION(R_TLSGD , 44, RPRED_ALWAYS_CONSTANT | RPRED_REFERS_TO_GOT) +RELOCATION(R_TLSGD_PC , 45, RPRED_ALWAYS_CONSTANT | RPRED_REFERS_TO_GOT) +RELOCATION(R_TLSLD , 46, 0) +RELOCATION(R_TLSLD_PC , 47, 0) + +// Undefine macros so that users of this .def file don't have to do so +// themselves. + +#ifdef RELOCATION +#undef RELOCATION +#endif