[lld] r256416 - [ELF][MIPS] Implement R_MIPS_GPREL16/R_MIPS_GPREL32 relocations
Simon Atanasyan via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 25 05:02:16 PST 2015
Author: atanasyan
Date: Fri Dec 25 07:02:13 2015
New Revision: 256416
URL: http://llvm.org/viewvc/llvm-project?rev=256416&view=rev
Log:
[ELF][MIPS] Implement R_MIPS_GPREL16/R_MIPS_GPREL32 relocations
The R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations use the following
expressions for calculations:
```
local symbol: S + A + GP0 - GP
global symbol: S + A - GP
GP - Represents the final gp value, i.e. _gp symbol
GP0 - Represents the gp value used to create the relocatable object
```
The GP0 value is taken from the .reginfo data section defined by an object
file. To implement that I keep a reference to `MipsReginfoInputSection`
in the `ObjectFile` class. This reference is used by the
`ObjectFile::getMipsGp0` method to return the GP0 value.
Differential Revision: http://reviews.llvm.org/D15760
Added:
lld/trunk/test/ELF/mips-gprel32-relocs.test
Modified:
lld/trunk/ELF/InputFiles.cpp
lld/trunk/ELF/InputFiles.h
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/InputSection.h
lld/trunk/ELF/Target.cpp
Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=256416&r1=256415&r2=256416&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Fri Dec 25 07:02:13 2015
@@ -93,6 +93,10 @@ typename ObjectFile<ELFT>::Elf_Sym_Range
return this->getSymbolsHelper(true);
}
+template <class ELFT> uint32_t ObjectFile<ELFT>::getMipsGp0() const {
+ return MipsReginfo ? MipsReginfo->getGp0() : 0;
+}
+
template <class ELFT>
const typename ObjectFile<ELFT>::Elf_Sym *
ObjectFile<ELFT>::getLocalSymbol(uintX_t SymIndex) {
@@ -245,8 +249,10 @@ elf2::ObjectFile<ELFT>::createInputSecti
// A MIPS object file has a special section that contains register
// usage info, which needs to be handled by the linker specially.
- if (Config->EMachine == EM_MIPS && Name == ".reginfo")
- return new (this->Alloc) MipsReginfoInputSection<ELFT>(this, &Sec);
+ if (Config->EMachine == EM_MIPS && Name == ".reginfo") {
+ MipsReginfo = new (this->Alloc) MipsReginfoInputSection<ELFT>(this, &Sec);
+ return MipsReginfo;
+ }
if (Name == ".eh_frame")
return new (this->EHAlloc.Allocate()) EHInputSection<ELFT>(this, &Sec);
Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=256416&r1=256415&r2=256416&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Fri Dec 25 07:02:13 2015
@@ -121,6 +121,11 @@ public:
const Elf_Shdr *getSymbolTable() const { return this->Symtab; };
+ // Get MIPS GP0 value defined by this file. This value represents the gp value
+ // used to create the relocatable object and required to support
+ // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
+ uint32_t getMipsGp0() const;
+
private:
void initializeSections(llvm::DenseSet<StringRef> &Comdats);
void initializeSymbols();
@@ -134,6 +139,9 @@ private:
// List of all symbols referenced or defined by this file.
std::vector<SymbolBody *> SymbolBodies;
+ // MIPS .reginfo section defined by this file.
+ MipsReginfoInputSection<ELFT> *MipsReginfo = nullptr;
+
llvm::BumpPtrAllocator Alloc;
llvm::SpecificBumpPtrAllocator<MergeInputSection<ELFT>> MAlloc;
llvm::SpecificBumpPtrAllocator<EHInputSection<ELFT>> EHAlloc;
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=256416&r1=256415&r2=256416&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Fri Dec 25 07:02:13 2015
@@ -187,6 +187,12 @@ void InputSectionBase<ELFT>::relocate(ui
uintX_t A = getAddend<ELFT>(RI);
if (!Body) {
uintX_t SymVA = getLocalRelTarget(*File, RI, A);
+ // We need to adjust SymVA value in case of R_MIPS_GPREL16/32 relocations
+ // because they use the following expression to calculate the relocation's
+ // result for local symbol: S + A + GP0 - G.
+ if (Config->EMachine == EM_MIPS &&
+ (Type == R_MIPS_GPREL16 || Type == R_MIPS_GPREL32))
+ SymVA += File->getMipsGp0();
Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA, 0,
findMipsPairedReloc(Buf, SymIndex, Type, NextRelocs));
continue;
@@ -351,6 +357,13 @@ uint32_t MipsReginfoInputSection<ELFT>::
return reinterpret_cast<const Elf_Mips_RegInfo *>(D.data())->ri_gprmask;
}
+template <class ELFT> uint32_t MipsReginfoInputSection<ELFT>::getGp0() const {
+ ArrayRef<uint8_t> D = this->getSectionData();
+ if (D.size() != sizeof(Elf_Mips_RegInfo))
+ error("Invalid size of .reginfo section");
+ return reinterpret_cast<const Elf_Mips_RegInfo *>(D.data())->ri_gp_value;
+}
+
template <class ELFT>
bool MipsReginfoInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
return S->SectionKind == InputSectionBase<ELFT>::MipsReginfo;
Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=256416&r1=256415&r2=256416&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Fri Dec 25 07:02:13 2015
@@ -176,6 +176,7 @@ public:
MipsReginfoInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
uint32_t getGeneralMask() const;
+ uint32_t getGp0() const;
static bool classof(const InputSectionBase<ELFT> *S);
};
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=256416&r1=256415&r2=256416&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Fri Dec 25 07:02:13 2015
@@ -1382,6 +1382,16 @@ void MipsTargetInfo<ELFT>::relocateOne(u
write32<E>(Loc, (read32<E>(Loc) & 0xffff0000) | (V & 0xffff));
break;
}
+ case R_MIPS_GPREL16: {
+ uint32_t Instr = read32<E>(Loc);
+ int64_t V = SA + SignExtend64<16>(Instr & 0xffff) - getMipsGpAddr<ELFT>();
+ checkInt<16>(V, Type);
+ write32<E>(Loc, (Instr & 0xffff0000) | (V & 0xffff));
+ break;
+ }
+ case R_MIPS_GPREL32:
+ write32<E>(Loc, SA + int32_t(read32<E>(Loc)) - getMipsGpAddr<ELFT>());
+ break;
case R_MIPS_HI16: {
uint32_t Instr = read32<E>(Loc);
if (PairedLoc) {
Added: lld/trunk/test/ELF/mips-gprel32-relocs.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-gprel32-relocs.test?rev=256416&view=auto
==============================================================================
--- lld/trunk/test/ELF/mips-gprel32-relocs.test (added)
+++ lld/trunk/test/ELF/mips-gprel32-relocs.test Fri Dec 25 07:02:13 2015
@@ -0,0 +1,31 @@
+# Check R_MIPS_GPREL32 relocation calculation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared -o %t.so %t.o
+# RUN: llvm-objdump -s -section=.rodata -t %t.so | FileCheck %s
+
+# REQUIRES: mips
+
+ .text
+ .globl __start
+__start:
+ lw $t0,%call16(__start)($gp)
+foo:
+ nop
+bar:
+ nop
+
+ .section .rodata, "a"
+v1:
+ .gpword foo
+ .gpword bar
+
+# CHECK: Contents of section .rodata:
+# CHECK: 0114 fffe8014 fffe8018
+# ^ 0x10004 - 0x27ff0
+# ^ 0x10008 - 0x27ff0
+
+# CHECK: SYMBOL TABLE:
+# CHECK: 00010008 .text 00000000 bar
+# CHECK: 00010004 .text 00000000 foo
+# CHECK: 00027ff0 *ABS* 00000000 _gp
More information about the llvm-commits
mailing list