[lld] r298817 - Remove MIPS-specific code from computeAddend.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 26 12:35:25 PDT 2017


Author: ruiu
Date: Sun Mar 26 14:35:24 2017
New Revision: 298817

URL: http://llvm.org/viewvc/llvm-project?rev=298817&view=rev
Log:
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.

Modified:
    lld/trunk/ELF/Relocations.cpp

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=298817&r1=298816&r2=298817&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Sun Mar 26 14:35:24 2017
@@ -237,9 +237,8 @@ handleTlsRelocation(uint32_t Type, Symbo
   return 0;
 }
 
-template <class RelTy>
-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 Re
   }
 }
 
-template <class RelTy>
-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 &Bo
   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 <class ELFT, class RelTy>
-static int64_t computeAddend(const elf::ObjectFile<ELFT> &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<ELFT>(Rel);
   uint32_t Type = Rel.getType(Config->IsMips64EL);
-  int64_t Addend = getAddend<ELFT>(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 <class ELFT, class RelTy>
+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<ELFT>()->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 <class ELFT>
@@ -719,7 +723,7 @@ template <class ELFT, class RelTy>
 static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> 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<ELFT>()->getRelocTargetSym(Rel);
     uint32_t Type = Rel.getType(Config->IsMips64EL);
@@ -727,7 +731,7 @@ static void scanRelocs(InputSectionBase
     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
                        R_GOTREL_FROM_END, R_PPC_TOC>(Expr))
       In<ELFT>::Got->HasGotOffRel = true;
 
-    int64_t Addend = computeAddend(*Sec.getFile<ELFT>(), Sec.Data.data(), E,
-                                   Rel, Expr, Body);
+    int64_t Addend = computeAddend<ELFT>(Rel, Sec.Data.data());
+    if (Config->EMachine == EM_MIPS)
+      Addend += computeMipsAddend<ELFT>(Rel, Sec, Expr, Body, End);
 
     if (unsigned Processed =
             handleTlsRelocation<ELFT>(Type, Body, Sec, Offset, Addend, Expr)) {




More information about the llvm-commits mailing list