From 58cd5db4effb68dfe889f28d9f53801dac0a280d Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 19 Apr 2016 22:46:03 +0000 Subject: [PATCH] Simplify mips got handling. This avoids computing the address of a position in the got just to then subtract got->getva(). llvm-svn: 266831 --- lld/ELF/InputSection.cpp | 6 ++++-- lld/ELF/InputSection.h | 1 + lld/ELF/OutputSections.cpp | 8 ++++---- lld/ELF/OutputSections.h | 4 ++-- lld/ELF/Target.cpp | 12 +++++------- lld/ELF/Writer.cpp | 7 +++++-- 6 files changed, 21 insertions(+), 17 deletions(-) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 82b5f98..3df6cf00 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -211,18 +211,20 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, // relocations because they use the following expression to calculate // the relocation's result for local symbol: S + A + GP0 - G. return Body.getVA(A) + File.getMipsGp0(); + case R_GOT_OFF: + return Body.getGotOffset() + A; case R_MIPS_GOT_LOCAL: // If relocation against MIPS local symbol requires GOT entry, this entry // should be initialized by 'page address'. This address is high 16-bits // of sum the symbol's value and the addend. - return Out::Got->getMipsLocalPageAddr(Body.getVA(A)); + return Out::Got->getMipsLocalPageOffset(Body.getVA(A)); case R_MIPS_GOT: // For non-local symbols GOT entries should contain their full // addresses. But if such symbol cannot be preempted, we do not // have to put them into the "global" part of GOT and use dynamic // linker to determine their actual addresses. That is why we // create GOT entries for them in the "local" part of GOT. - return Out::Got->getMipsLocalEntryAddr(Body.getVA(A)); + return Out::Got->getMipsLocalEntryOffset(Body.getVA(A)); case R_PPC_OPD: { uint64_t SymVA = Body.getVA(A); // If we have an undefined weak symbol, we might get here with a symbol diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 57725733..c34c94d 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -31,6 +31,7 @@ enum RelExpr { R_GOT, R_GOTONLY_PC, R_GOTREL, + R_GOT_OFF, R_GOT_FROM_END, R_GOT_PAGE_PC, R_GOT_PC, diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 96505b2..08fed9a 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -165,19 +165,19 @@ template bool GotSection::addTlsIndex() { template typename GotSection::uintX_t -GotSection::getMipsLocalPageAddr(uintX_t EntryValue) { +GotSection::getMipsLocalPageOffset(uintX_t EntryValue) { // Initialize the entry by the %hi(EntryValue) expression // but without right-shifting. - return getMipsLocalEntryAddr((EntryValue + 0x8000) & ~0xffff); + return getMipsLocalEntryOffset((EntryValue + 0x8000) & ~0xffff); } template typename GotSection::uintX_t -GotSection::getMipsLocalEntryAddr(uintX_t EntryValue) { +GotSection::getMipsLocalEntryOffset(uintX_t EntryValue) { size_t NewIndex = Target->GotHeaderEntriesNum + MipsLocalGotPos.size(); auto P = MipsLocalGotPos.insert(std::make_pair(EntryValue, NewIndex)); assert(!P.second || MipsLocalGotPos.size() <= MipsLocalEntries); - return this->getVA() + P.first->second * sizeof(uintX_t); + return P.first->second * sizeof(uintX_t) - MipsGPOffset; } template diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 54685a8..85808a8 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -112,8 +112,8 @@ public: bool addDynTlsEntry(SymbolBody &Sym); bool addTlsIndex(); bool empty() const { return MipsLocalEntries == 0 && Entries.empty(); } - uintX_t getMipsLocalEntryAddr(uintX_t EntryValue); - uintX_t getMipsLocalPageAddr(uintX_t Addr); + uintX_t getMipsLocalEntryOffset(uintX_t EntryValue); + uintX_t getMipsLocalPageOffset(uintX_t Addr); uintX_t getGlobalDynAddr(const SymbolBody &B) const; uintX_t getGlobalDynOffset(const SymbolBody &B) const; uintX_t getNumEntries() const { return Entries.size(); } diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 0e07fae..48c5f6a 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -1510,7 +1510,7 @@ RelExpr MipsTargetInfo::getRelExpr(uint32_t Type, return R_MIPS_GOT_LOCAL; if (!S.isPreemptible()) return R_MIPS_GOT; - return R_GOT; + return R_GOT_OFF; } } @@ -1726,14 +1726,12 @@ void MipsTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, write32(Loc, (Instr & ~0x3ffffff) | (Val >> 2)); break; } + case R_MIPS_GOT16: + checkInt<16>(Val, Type); + // fallthrough case R_MIPS_CALL16: - case R_MIPS_GOT16: { - int64_t V = Val - getMipsGpAddr(); - if (Type == R_MIPS_GOT16) - checkInt<16>(V, Type); - writeMipsLo16(Loc, V); + writeMipsLo16(Loc, Val); break; - } case R_MIPS_GPREL16: { int64_t V = Val - getMipsGpAddr(); checkInt<16>(V, Type); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 3421eb3..71b2664 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -566,9 +566,12 @@ void Writer::scanRelocs(InputSectionBase &C, ArrayRef Rels) { } // If a relocation needs GOT, we create a GOT slot for the symbol. - if (Expr == R_GOT || Expr == R_MIPS_GOT || Expr == R_MIPS_GOT_LOCAL || - Expr == R_GOT_PAGE_PC || Expr == R_GOT_PC || Expr == R_GOT_FROM_END) { + if (Expr == R_GOT || Expr == R_GOT_OFF || Expr == R_MIPS_GOT || + Expr == R_MIPS_GOT_LOCAL || Expr == R_GOT_PAGE_PC || Expr == R_GOT_PC || + Expr == R_GOT_FROM_END) { uint32_t T = Body.isTls() ? Target->getTlsGotRel(Type) : Type; + if (Config->EMachine == EM_MIPS && Expr == R_GOT_OFF) + Addend -= MipsGPOffset; C.Relocations.push_back({Expr, T, Offset, Addend, &Body}); if (Body.isInGot()) continue; -- 2.7.4