summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Writer.cpp64
1 files changed, 39 insertions, 25 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 1994e24a799..834ff0b6072 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -71,6 +71,10 @@ private:
void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec);
RelExpr adjustExpr(const elf::ObjectFile<ELFT> &File, SymbolBody &S,
bool IsWrite, RelExpr Expr, uint32_t Type);
+ template <class RelTy>
+ uintX_t computeAddend(const elf::ObjectFile<ELFT> &File,
+ const uint8_t *SectionData, const RelTy *End,
+ const RelTy &RI, RelExpr Expr, SymbolBody &Body);
void createPhdrs();
void assignAddresses();
void assignFileOffsets();
@@ -577,6 +581,39 @@ RelExpr Writer<ELFT>::adjustExpr(const elf::ObjectFile<ELFT> &File,
return Expr;
}
+template <class ELFT>
+template <class RelTy>
+typename ELFT::uint
+Writer<ELFT>::computeAddend(const elf::ObjectFile<ELFT> &File,
+ const uint8_t *SectionData, const RelTy *End,
+ const RelTy &RI, RelExpr Expr, SymbolBody &Body) {
+ uint32_t Type = RI.getType(Config->Mips64EL);
+ uintX_t Addend = getAddend<ELFT>(RI);
+ const uint8_t *BufLoc = SectionData + RI.r_offset;
+ if (!RelTy::IsRela)
+ 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_GOT_OFF)
+ Addend -= MipsGPOffset;
+ if (Expr == R_GOTREL) {
+ Addend -= MipsGPOffset;
+ if (Body.isLocal())
+ Addend += File.getMipsGp0();
+ }
+ }
+ if (Config->Pic && Config->EMachine == EM_PPC64 && Type == R_PPC64_TOC)
+ Addend += getPPC64TocBase();
+ return Addend;
+}
+
// The reason we have to do this early scan is as follows
// * To mmap the output file, we need to know the size
// * For that, we need to know how many dynamic relocs we will have.
@@ -627,20 +664,7 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
if (Expr == R_GOTONLY_PC || Expr == R_GOTREL || Expr == R_PPC_TOC)
HasGotOffRel = true;
- uintX_t Addend = getAddend<ELFT>(RI);
- const uint8_t *BufLoc = Buf + RI.r_offset;
- if (!RelTy::IsRela)
- Addend += Target->getImplicitAddend(BufLoc, Type);
- if (Config->EMachine == EM_MIPS) {
- Addend += findMipsPairedAddend<ELFT>(Buf, BufLoc, Body, &RI, E);
- 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;
- }
+ uintX_t Addend = computeAddend(File, Buf, E, RI, Expr, Body);
if (unsigned Processed =
handleTlsRelocation<ELFT>(Type, Body, C, Offset, Addend, Expr)) {
@@ -650,8 +674,7 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
if (Expr == R_GOT && !isStaticLinkTimeConstant<ELFT>(Expr, Type, Body) &&
Config->Shared)
- AddDyn({Target->RelativeRel, C.OutSec, Offset, true, &Body,
- getAddend<ELFT>(RI)});
+ AddDyn({Target->RelativeRel, C.OutSec, Offset, true, &Body, Addend});
// If a relocation needs PLT, we create a PLT and a GOT slot
// for the symbol.
@@ -690,8 +713,6 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
// If a relocation needs GOT, we create a GOT slot for the symbol.
if (refersToGotEntry(Expr)) {
- if (Config->EMachine == EM_MIPS && Expr == R_GOT_OFF)
- Addend -= MipsGPOffset;
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
if (Body.isInGot())
continue;
@@ -751,17 +772,10 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
// can process some of it and and just ask the dynamic linker to add the
// load address.
if (!Config->Pic || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body)) {
- if (Config->EMachine == EM_MIPS && Expr == R_GOTREL) {
- Addend -= MipsGPOffset;
- if (Body.isLocal())
- Addend += File.getMipsGp0();
- }
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
continue;
}
- if (Config->EMachine == EM_PPC64 && Type == R_PPC64_TOC)
- Addend += getPPC64TocBase();
AddDyn({Target->RelativeRel, C.OutSec, Offset, true, &Body, Addend});
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
}
OpenPOWER on IntegriCloud