From a2f63f1471461fcd73340e30976f8d7769b00610 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Sun, 26 Mar 2017 19:35:24 +0000 Subject: [PATCH] Remove MIPS-specific code from computeAddend. Previously, computeAddend had many parameters but most of them were used only for MIPS. The MIPS ABI is too odd that I don't want to mix it into the regular code path. Splitting the function into non-MIPS and MIPS parts makes the regular code path easy to follow. llvm-svn: 298817 --- lld/ELF/Relocations.cpp | 107 +++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 51 deletions(-) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 0db209cc583b..ea1184857fd5 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -237,9 +237,8 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C, return 0; } -template -static uint32_t getMipsPairType(const RelTy *Rel, const SymbolBody &Sym) { - switch (Rel->getType(Config->IsMips64EL)) { +static uint32_t getMipsPairType(uint32_t Type, const SymbolBody &Sym) { + switch (Type) { case R_MIPS_HI16: return R_MIPS_LO16; case R_MIPS_GOT16: @@ -253,37 +252,6 @@ static uint32_t getMipsPairType(const RelTy *Rel, const SymbolBody &Sym) { } } -template -static int32_t findMipsPairedAddend(const uint8_t *Buf, const uint8_t *BufLoc, - SymbolBody &Sym, const RelTy *Rel, - const RelTy *End) { - uint32_t SymIndex = Rel->getSymbol(Config->IsMips64EL); - uint32_t Type = getMipsPairType(Rel, Sym); - - // Some MIPS relocations use addend calculated from addend of the relocation - // itself and addend of paired relocation. ABI requires to compute such - // combined addend in case of REL relocation record format only. - // See p. 4-17 at ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - if (RelTy::IsRela || Type == R_MIPS_NONE) - return 0; - - for (const RelTy *RI = Rel; RI != End; ++RI) { - if (RI->getType(Config->IsMips64EL) != Type) - continue; - if (RI->getSymbol(Config->IsMips64EL) != SymIndex) - continue; - - endianness E = Config->Endianness; - int32_t Hi = (read32(BufLoc, E) & 0xffff) << 16; - int32_t Lo = SignExtend32<16>(read32(Buf + RI->r_offset, E)); - return Hi + Lo; - } - - warn("can't find matching " + toString(Type) + " relocation for " + - toString(Rel->getType(Config->IsMips64EL))); - return 0; -} - // True if non-preemptable symbol always has the same value regardless of where // the DSO is loaded. static bool isAbsolute(const SymbolBody &Body) { @@ -581,26 +549,62 @@ static RelExpr adjustExpr(SymbolBody &Body, RelExpr Expr, uint32_t Type, return Expr; } +// Returns an addend of a given relocation. If it is RELA, an addend +// is in a relocation itself. If it is REL, we need to read it from an +// input section. template -static int64_t computeAddend(const elf::ObjectFile &File, - const uint8_t *SectionData, const RelTy *End, - const RelTy &Rel, RelExpr Expr, SymbolBody &Body) { +static int64_t computeAddend(const RelTy &Rel, const uint8_t *Buf) { + int64_t A = getAddend(Rel); uint32_t Type = Rel.getType(Config->IsMips64EL); - int64_t Addend = getAddend(Rel); - const uint8_t *BufLoc = SectionData + Rel.r_offset; if (!RelTy::IsRela) - Addend += Target->getImplicitAddend(BufLoc, Type); + A += Target->getImplicitAddend(Buf + Rel.r_offset, Type); + if (Config->EMachine == EM_PPC64 && Config->Pic && Type == R_PPC64_TOC) + A += getPPC64TocBase(); + return A; +} - if (Config->EMachine == EM_MIPS) { - Addend += findMipsPairedAddend(SectionData, BufLoc, Body, &Rel, End); - if (Expr == R_MIPS_GOTREL && Body.isLocal()) - Addend += File.MipsGp0; +// MIPS has an odd notion of "paired" relocations to calculate addends. +// For example, if a relocation is of R_MIPS_HI16, there must be a +// R_MIPS_LO16 relocation after that, and an addend is calculated using +// the two relocations. +template +static int64_t computeMipsAddend(const RelTy &Rel, InputSectionBase &Sec, + RelExpr Expr, SymbolBody &Body, + const RelTy *End) { + if (Expr == R_MIPS_GOTREL && Body.isLocal()) + return Sec.getFile()->MipsGp0; + + // The ABI says that the paired relocation is used only for REL. + // See p. 4-17 at ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf + if (RelTy::IsRela) + return 0; + + uint32_t Type = Rel.getType(Config->IsMips64EL); + uint32_t PairTy = getMipsPairType(Type, Body); + if (PairTy == R_MIPS_NONE) + return 0; + + const uint8_t *Buf = Sec.Data.data(); + uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); + + // To make things worse, paired relocations might not be contiguous in + // the relocation table, so we need to do linear search. *sigh* + for (const RelTy *RI = &Rel; RI != End; ++RI) { + if (RI->getType(Config->IsMips64EL) != PairTy) + continue; + if (RI->getSymbol(Config->IsMips64EL) != SymIndex) + continue; + + endianness E = Config->Endianness; + int32_t Hi = (read32(Buf + Rel.r_offset, E) & 0xffff) << 16; + int32_t Lo = SignExtend32<16>(read32(Buf + RI->r_offset, E)); + return Hi + Lo; } - if (Config->Pic && Config->EMachine == EM_PPC64 && Type == R_PPC64_TOC) - Addend += getPPC64TocBase(); - return Addend; + warn("can't find matching " + toString(PairTy) + " relocation for " + + toString(Type)); + return 0; } template @@ -719,7 +723,7 @@ template static void scanRelocs(InputSectionBase &Sec, ArrayRef Rels) { OffsetGetter GetOffset(Sec); - for (auto I = Rels.begin(), E = Rels.end(); I != E; ++I) { + for (auto I = Rels.begin(), End = Rels.end(); I != End; ++I) { const RelTy &Rel = *I; SymbolBody &Body = Sec.getFile()->getRelocTargetSym(Rel); uint32_t Type = Rel.getType(Config->IsMips64EL); @@ -727,7 +731,7 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef Rels) { if (Config->MipsN32Abi) { uint32_t Processed; std::tie(Type, Processed) = - mergeMipsN32RelTypes(Type, Rel.r_offset, I + 1, E); + mergeMipsN32RelTypes(Type, Rel.r_offset, I + 1, End); I += Processed; } @@ -761,8 +765,9 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef Rels) { R_GOTREL_FROM_END, R_PPC_TOC>(Expr)) In::Got->HasGotOffRel = true; - int64_t Addend = computeAddend(*Sec.getFile(), Sec.Data.data(), E, - Rel, Expr, Body); + int64_t Addend = computeAddend(Rel, Sec.Data.data()); + if (Config->EMachine == EM_MIPS) + Addend += computeMipsAddend(Rel, Sec, Expr, Body, End); if (unsigned Processed = handleTlsRelocation(Type, Body, Sec, Offset, Addend, Expr)) {