[ELF][MIPS] Put local GOT entries accessed via a 16-bit index first
Some MIPS relocations used to access GOT entries are able to manipulate
16-bit index. The other ones like R_MIPS_CALL_HI16/LO16 can handle
32-bit indexes. 16-bit relocations are generated by default. The 32-bit
relocations are generated by -mxgot flag passed to compiler. Usually
these relocation are not mixed in the same code but files like crt*.o
contain 16-bit relocations so even if all "user's" code compiled with
-mxgot flag a few 16-bit relocations might come to the linking phase.
Now LLD does not differentiate local GOT entries accessed via a 16-bit
and 32-bit indexes. That might lead to relocation's overflow if 16-bit
entries are allocated to far from the beginning of the GOT.
The patch introduces new "part" of MIPS GOT dedicated to the local GOT
entries accessed by 32-bit relocations. That allows to put local GOT
entries accessed via a 16-bit index first and escape relocation's overflow.
Differential revision: https://reviews.llvm.org/D25833
llvm-svn: 284809
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 2f7757a..62f81f7 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -62,10 +62,11 @@
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_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;
+ 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;
}
static bool isPreemptible(const SymbolBody &Body, uint32_t Type) {
@@ -303,11 +304,11 @@
const SymbolBody &Body) {
// 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_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)
+ 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)
return true;
// These never do, except if the entire file is position dependent or if