[lld] r298306 - [ELF][MIPS] Calculate relocations agains _gp_disp / __gnu_local_gp using dedicated 'expressions'
Simon Atanasyan via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 20 14:03:44 PDT 2017
Author: atanasyan
Date: Mon Mar 20 16:03:43 2017
New Revision: 298306
URL: http://llvm.org/viewvc/llvm-project?rev=298306&view=rev
Log:
[ELF][MIPS] Calculate relocations agains _gp_disp / __gnu_local_gp using dedicated 'expressions'
The patch introduces two new relocations expressions R_MIPS_GOT_GP and
R_MIPS_GOT_GP_PC. The first one represents a current value of `_gp`
pointer and used to calculate relocations against the `__gnu_local_gp`
symbol. The second one represents the offset between the beginning of
the function and the `_gp` pointer's value.
There are two motivations for introducing new expressions:
- It's better to keep all non-trivial relocation calculations in the
single place - `getRelocTargetVA` function.
- Relocations against both `_gp_disp` and `__gnu_local_gp` symbols
depend on the `_gp` value. It's a magical value points to the "middle"
of GOT. Now all relocations use a common `_gp` value. But in fact,
under some conditions each input file might require its own `_gp`
value. I'm going to implement it in the future patches. So it's
better to make `MipsGotSection` responsible for calculation of
the `_gp` value.
Modified:
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/Relocations.cpp
lld/trunk/ELF/Relocations.h
lld/trunk/ELF/Target.cpp
lld/trunk/ELF/Writer.cpp
lld/trunk/test/ELF/mips-gp-ext.s
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=298306&r1=298305&r2=298306&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Mon Mar 20 16:03:43 2017
@@ -410,6 +410,18 @@ getRelocTargetVA(uint32_t Type, int64_t
In<ELFT>::MipsGot->getGp();
case R_MIPS_GOTREL:
return Body.getVA(A) - In<ELFT>::MipsGot->getGp();
+ case R_MIPS_GOT_GP:
+ return In<ELFT>::MipsGot->getGp() + A;
+ case R_MIPS_GOT_GP_PC: {
+ // R_MIPS_LO16 expression has R_MIPS_GOT_GP_PC type iif the target
+ // is _gp_disp symbol. In that case we should use the following
+ // formula for calculation "AHL + GP - P + 4". For details see p. 4-19 at
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ uint64_t V = In<ELFT>::MipsGot->getGp() + A - P;
+ if (Type == R_MIPS_LO16)
+ V += 4;
+ return V;
+ }
case R_MIPS_TLSGD:
return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getTlsOffset() +
In<ELFT>::MipsGot->getGlobalDynOffset(Body) -
Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=298306&r1=298305&r2=298306&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Mon Mar 20 16:03:43 2017
@@ -317,9 +317,10 @@ isStaticLinkTimeConstant(RelExpr E, uint
InputSectionBase &S, typename ELFT::uint RelOff) {
// These expressions always compute a constant
if (isRelExprOneOf<R_SIZE, R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
- R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_TLSGD,
- R_GOT_PAGE_PC, R_GOT_PC, R_PLT_PC, R_TLSGD_PC, R_TLSGD,
- R_PPC_PLT_OPD, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(E))
+ R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
+ R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_PLT_PC,
+ R_TLSGD_PC, R_TLSGD, R_PPC_PLT_OPD, R_TLSDESC_CALL,
+ R_TLSDESC_PAGE, R_HINT>(E))
return true;
// These never do, except if the entire file is position dependent or if
@@ -351,8 +352,6 @@ isStaticLinkTimeConstant(RelExpr E, uint
if (AbsVal && RelE) {
if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak())
return true;
- if (&Body == ElfSym::MipsGpDisp)
- return true;
error(S.getLocation<ELFT>(RelOff) + ": relocation " + toString(Type) +
" cannot refer to absolute symbol '" + toString(Body) +
"' defined in " + toString(Body.File));
@@ -582,13 +581,6 @@ static int64_t computeAddend(const elf::
Addend += Target->getImplicitAddend(BufLoc, Type);
if (Config->EMachine == EM_MIPS) {
Addend += findMipsPairedAddend<ELFT>(SectionData, BufLoc, Body, &RI, End);
- if (Type == R_MIPS_LO16 && Expr == R_PC)
- // R_MIPS_LO16 expression has R_PC type iif the target is _gp_disp
- // symbol. In that case we should use the following formula for
- // calculation "AHL + GP - P + 4". Let's add 4 right here.
- // For details see p. 4-19 at
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- Addend += 4;
if (Expr == R_MIPS_GOTREL && Body.isLocal())
Addend += File.MipsGp0;
}
Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=298306&r1=298305&r2=298306&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Mon Mar 20 16:03:43 2017
@@ -38,6 +38,8 @@ enum RelExpr {
R_MIPS_GOT_OFF,
R_MIPS_GOT_OFF32,
R_MIPS_GOTREL,
+ R_MIPS_GOT_GP,
+ R_MIPS_GOT_GP_PC,
R_MIPS_TLSGD,
R_MIPS_TLSLD,
R_NEG_TLS,
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=298306&r1=298305&r2=298306&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Mon Mar 20 16:03:43 2017
@@ -2083,13 +2083,16 @@ RelExpr MipsTargetInfo<ELFT>::getRelExpr
return R_PLT;
case R_MIPS_HI16:
case R_MIPS_LO16:
- case R_MIPS_GOT_OFST:
// R_MIPS_HI16/R_MIPS_LO16 relocations against _gp_disp calculate
// offset between start of function and 'gp' value which by default
// equal to the start of .got section. In that case we consider these
// relocations as relative.
if (&S == ElfSym::MipsGpDisp)
- return R_PC;
+ return R_MIPS_GOT_GP_PC;
+ if (&S == ElfSym::MipsLocalGp)
+ return R_MIPS_GOT_GP;
+ // fallthrough
+ case R_MIPS_GOT_OFST:
return R_ABS;
case R_MIPS_PC32:
case R_MIPS_PC16:
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=298306&r1=298305&r2=298306&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Mar 20 16:03:43 2017
@@ -802,9 +802,7 @@ template <class ELFT> void Writer<ELFT>:
ElfSym::MipsGp = Symtab<ELFT>::X->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL);
// On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
- // start of function and 'gp' pointer into GOT. To simplify relocation
- // calculation we assign _gp value to it and calculate corresponding
- // relocations as relative to this value.
+ // start of function and 'gp' pointer into GOT.
if (Symtab<ELFT>::X->find("_gp_disp"))
ElfSym::MipsGpDisp =
Symtab<ELFT>::X->addAbsolute("_gp_disp", STV_HIDDEN, STB_LOCAL);
@@ -1692,10 +1690,6 @@ template <class ELFT> void Writer<ELFT>:
if (Gp != (uintX_t)-1)
ElfSym::MipsGp->Value = Gp + 0x7ff0;
}
- if (ElfSym::MipsGpDisp)
- ElfSym::MipsGpDisp->Value = ElfSym::MipsGp->Value;
- if (ElfSym::MipsLocalGp)
- ElfSym::MipsLocalGp->Value = ElfSym::MipsGp->Value;
}
}
Modified: lld/trunk/test/ELF/mips-gp-ext.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-gp-ext.s?rev=298306&r1=298305&r2=298306&view=diff
==============================================================================
--- lld/trunk/test/ELF/mips-gp-ext.s (original)
+++ lld/trunk/test/ELF/mips-gp-ext.s Mon Mar 20 16:03:43 2017
@@ -36,7 +36,7 @@
# ^-- 0-0x10c
# REL: 00000000 .text 00000000 foo
-# REL: 0000010c *ABS* 00000000 .hidden _gp_disp
+# REL: 00000000 *ABS* 00000000 .hidden _gp_disp
# REL: 0000010c *ABS* 00000000 .hidden _gp
# ABS: Contents of section .text:
@@ -56,7 +56,7 @@
# ^-- 0-0x200
# ABS: 00000000 .text 00000000 foo
-# ABS: 00000200 *ABS* 00000000 .hidden _gp_disp
+# ABS: 00000000 *ABS* 00000000 .hidden _gp_disp
# ABS: 00000200 *ABS* 00000000 .hidden _gp
.text
More information about the llvm-commits
mailing list