diff options
| author | Simon Atanasyan <simon@atanasyan.com> | 2015-04-13 08:20:34 +0000 |
|---|---|---|
| committer | Simon Atanasyan <simon@atanasyan.com> | 2015-04-13 08:20:34 +0000 |
| commit | 077372889bb8c3dfe9fd9549fdce41f14610fc56 (patch) | |
| tree | b811b43545520905f08cc6ea882ba756a5f2c5b0 /lld/lib | |
| parent | 4b115813d29d440a35616166c7c7f75d4a675ce0 (diff) | |
| download | bcm5719-llvm-077372889bb8c3dfe9fd9549fdce41f14610fc56.tar.gz bcm5719-llvm-077372889bb8c3dfe9fd9549fdce41f14610fc56.zip | |
[Mips] Support R_MIPS_GOT_HI16 / R_MIPS_GOT_LO16 relocations handling
llvm-svn: 234724
Diffstat (limited to 'lld/lib')
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp | 18 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp | 10 |
2 files changed, 26 insertions, 2 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp index c4c8cba9633..018f54cbb22 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp @@ -82,6 +82,8 @@ static MipsRelocationParams getRelocationParams(uint32_t rType) { case R_MIPS_GOT_DISP: case R_MIPS_GOT_PAGE: case R_MIPS_GOT_OFST: + case R_MIPS_GOT_HI16: + case R_MIPS_GOT_LO16: case R_MIPS_TLS_DTPREL_HI16: case R_MIPS_TLS_DTPREL_LO16: case R_MIPS_TLS_TPREL_HI16: @@ -221,6 +223,18 @@ static uint64_t relocGOT(uint64_t S, uint64_t GP) { return G; } +/// \brief R_MIPS_GOT_LO16 +/// rel16 G (truncate) +static uint64_t relocGOTLo16(uint64_t S, uint64_t GP) { + return S - GP; +} + +/// \brief R_MIPS_GOT_HI16 +/// rel16 %high(G) (truncate) +static uint64_t relocGOTHi16(uint64_t S, uint64_t GP) { + return (S - GP + 0x8000) >> 16; +} + /// R_MIPS_GOT_OFST /// rel16 offset of (S+A) from the page pointer (verify) static uint32_t relocGOTOfst(uint64_t S, int64_t A) { @@ -402,6 +416,10 @@ static ErrorOr<uint64_t> calculateRelocation(Reference::KindValue kind, return relocPcLo16(relAddr, tgtAddr, addend); case R_MICROMIPS_LO16: return relocLo16(relAddr, tgtAddr, addend, isGP, true); + case R_MIPS_GOT_LO16: + return relocGOTLo16(tgtAddr, gpAddr); + case R_MIPS_GOT_HI16: + return relocGOTHi16(tgtAddr, gpAddr); case R_MIPS_EH: case R_MIPS_GOT16: case R_MIPS_CALL16: diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp index 31db87a2a81..3afa3dd73f3 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp @@ -530,6 +530,8 @@ void RelocationPass<ELFT>::handleReference(const MipsELFDefinedAtom<ELFT> &atom, case R_MIPS_EH: case R_MIPS_GOT16: case R_MIPS_CALL16: + case R_MIPS_GOT_HI16: + case R_MIPS_GOT_LO16: case R_MICROMIPS_GOT16: case R_MICROMIPS_CALL16: case R_MIPS_GOT_DISP: @@ -612,6 +614,7 @@ void RelocationPass<ELFT>::collectReferenceInfo( if (refKind != R_MIPS_CALL16 && refKind != R_MICROMIPS_CALL16 && refKind != R_MIPS_26 && refKind != R_MICROMIPS_26_S1 && + refKind != R_MIPS_GOT_HI16 && refKind != R_MIPS_GOT_LO16 && refKind != R_MIPS_EH) _requiresPtrEquality.insert(ref.target()); } @@ -641,7 +644,8 @@ template <typename ELFT> bool RelocationPass<ELFT>::mightBeDynamic(const MipsELFDefinedAtom<ELFT> &atom, Reference::KindValue refKind) const { if (refKind == R_MIPS_CALL16 || refKind == R_MIPS_GOT16 || - refKind == R_MICROMIPS_CALL16 || refKind == R_MICROMIPS_GOT16) + refKind == R_MICROMIPS_CALL16 || refKind == R_MICROMIPS_GOT16 || + refKind == R_MIPS_GOT_HI16 || refKind == R_MIPS_GOT_LO16) return true; if (refKind != R_MIPS_32 && refKind != R_MIPS_64) @@ -792,7 +796,9 @@ template <typename ELFT> void RelocationPass<ELFT>::handleGOT(Reference &ref) { if (ref.kindValue() == R_MIPS_GOT_PAGE) ref.setTarget(getLocalGOTPageEntry(ref)); - else if (ref.kindValue() == R_MIPS_GOT_DISP || ref.kindValue() == R_MIPS_EH) + else if (ref.kindValue() == R_MIPS_GOT_DISP || + ref.kindValue() == R_MIPS_GOT_HI16 || + ref.kindValue() == R_MIPS_GOT_LO16 || ref.kindValue() == R_MIPS_EH) ref.setTarget(getLocalGOTEntry(ref)); else if (isLocal(ref.target())) ref.setTarget(getLocalGOTPageEntry(ref)); |

