[lld] r207949 - [Mips] R_MIPS_GPREL32 relocation support.
Simon Atanasyan
simon at atanasyan.com
Sun May 4 22:56:06 PDT 2014
Author: atanasyan
Date: Mon May 5 00:56:06 2014
New Revision: 207949
URL: http://llvm.org/viewvc/llvm-project?rev=207949&view=rev
Log:
[Mips] R_MIPS_GPREL32 relocation support.
Added:
lld/trunk/test/elf/Mips/rel-gprel32.test
Modified:
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h?rev=207949&r1=207948&r2=207949&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h Mon May 5 00:56:06 2014
@@ -12,6 +12,31 @@
#include "ELFReader.h"
#include "MipsLinkingContext.h"
+namespace llvm {
+namespace object {
+
+template <class ELFT>
+struct Elf_RegInfo;
+
+template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign>
+struct Elf_RegInfo<ELFType<TargetEndianness, MaxAlign, false>> {
+ LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
+ Elf_Word ri_gprmask; // bit-mask of used general registers
+ Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
+ Elf_Sword ri_gp_value; // gp register value
+};
+
+template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign>
+struct Elf_RegInfo<ELFType<TargetEndianness, MaxAlign, true>> {
+ LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
+ Elf_Word ri_gprmask; // bit-mask of used general registers
+ Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
+ Elf_Sword ri_gp_value; // gp register value
+};
+
+} // end namespace object.
+} // end namespace llvm.
+
namespace lld {
namespace elf {
@@ -44,7 +69,7 @@ public:
MipsELFFile(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings,
error_code &ec)
- : ELFFile<ELFT>(std::move(mb), atomizeStrings, ec) {}
+ : ELFFile<ELFT>(std::move(mb), atomizeStrings, ec), _gp0(0) {}
static ErrorOr<std::unique_ptr<MipsELFFile>>
create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) {
@@ -76,6 +101,10 @@ public:
if ((ec = file->createAtoms()))
return ec;
+ // Retrieve registry usage descriptor and GP value.
+ if ((ec = file->readRegInfo()))
+ return ec;
+
return std::move(file);
}
@@ -83,12 +112,17 @@ public:
return this->_objFile->getHeader()->e_flags & llvm::ELF::EF_MIPS_PIC;
}
+ /// \brief gp register value stored in the .reginfo section.
+ int64_t getGP0() const { return _gp0; }
+
private:
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel_Iter Elf_Rel_Iter;
+ int64_t _gp0;
+
ErrorOr<ELFDefinedAtom<ELFT> *> handleDefinedSymbol(
StringRef symName, StringRef sectionName, const Elf_Sym *sym,
const Elf_Shdr *sectionHdr, ArrayRef<uint8_t> contentData,
@@ -99,6 +133,30 @@ private:
referenceStart, referenceEnd, referenceList);
}
+ error_code readRegInfo() {
+ typedef llvm::object::Elf_RegInfo<ELFT> Elf_RegInfo;
+
+ for (auto sit = this->_objFile->begin_sections(),
+ sie = this->_objFile->end_sections();
+ sit != sie; ++sit) {
+ if (sit->sh_type != llvm::ELF::SHT_MIPS_REGINFO)
+ continue;
+
+ auto contents = this->getSectionContents(&*sit);
+ if (error_code ec = contents.getError())
+ return ec;
+
+ // FIXME (simon): Show error in case of invalid section size.
+ if (contents.get().size() == sizeof(Elf_RegInfo)) {
+ const auto *regInfo =
+ reinterpret_cast<const Elf_RegInfo *>(contents.get().data());
+ _gp0 = regInfo->ri_gp_value;
+ }
+ break;
+ }
+ return error_code::success();
+ }
+
void createRelocationReferences(const Elf_Sym &symbol,
ArrayRef<uint8_t> symContent,
ArrayRef<uint8_t> secContent,
@@ -129,6 +187,7 @@ private:
const uint8_t *ap = content.data() + ri.r_offset;
switch (ri.getType(isMips64EL())) {
case llvm::ELF::R_MIPS_32:
+ case llvm::ELF::R_MIPS_GPREL32:
case llvm::ELF::R_MIPS_PC32:
return *(int32_t *)ap;
case llvm::ELF::R_MIPS_26:
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp?rev=207949&r1=207948&r2=207949&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp Mon May 5 00:56:06 2014
@@ -101,6 +101,14 @@ static void relocCall16(uint8_t *locatio
applyReloc(location, G, 0xffff);
}
+/// \brief R_MIPS_GPREL32
+/// local: rel32 A + S + GP0 â GP (truncate)
+static void relocGPRel32(uint8_t *location, uint64_t P, uint64_t S, int64_t A,
+ uint64_t GP) {
+ int32_t result = A + S + 0 - GP;
+ applyReloc(location, result, 0xffffffff);
+}
+
/// \brief LLD_R_MIPS_32_HI16
static void reloc32hi16(uint8_t *location, uint64_t S, int64_t A) {
applyReloc(location, (S + A) & 0xffff0000, 0xffffffff);
@@ -154,6 +162,9 @@ error_code MipsTargetRelocationHandler::
case R_MIPS_CALL16:
relocCall16(location, relocVAddress, targetVAddress, ref.addend(), gpAddr);
break;
+ case R_MIPS_GPREL32:
+ relocGPRel32(location, relocVAddress, targetVAddress, ref.addend(), gpAddr);
+ break;
case R_MIPS_JALR:
// We do not do JALR optimization now.
break;
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp?rev=207949&r1=207948&r2=207949&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp Mon May 5 00:56:06 2014
@@ -194,7 +194,7 @@ private:
std::vector<LA25Atom *> _la25Vector;
/// \brief Handle a specific reference.
- void handleReference(Reference &ref);
+ void handleReference(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
/// \brief Collect information about the reference to use it
/// later in the handleReference() routine.
@@ -204,6 +204,7 @@ private:
void handlePlain(Reference &ref);
void handle26(Reference &ref);
void handleGOT(Reference &ref);
+ void handleGPRel(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
const GOTAtom *getLocalGOTEntry(const Reference &ref);
const GOTAtom *getGlobalGOTEntry(const Atom *a);
@@ -243,7 +244,8 @@ void RelocationPass<ELFT>::perform(std::
// Process all references.
for (const auto &atom : mf->defined())
for (const auto &ref : *atom)
- handleReference(const_cast<Reference &>(*ref));
+ handleReference(*cast<MipsELFDefinedAtom<ELFT>>(atom),
+ const_cast<Reference &>(*ref));
// Create R_MIPS_REL32 relocations.
for (auto *ref : _rel32Candidates) {
@@ -298,7 +300,8 @@ void RelocationPass<ELFT>::perform(std::
}
template <typename ELFT>
-void RelocationPass<ELFT>::handleReference(Reference &ref) {
+void RelocationPass<ELFT>::handleReference(const MipsELFDefinedAtom<ELFT> &atom,
+ Reference &ref) {
if (!ref.target())
return;
if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
@@ -319,6 +322,23 @@ void RelocationPass<ELFT>::handleReferen
case R_MIPS_CALL16:
handleGOT(ref);
break;
+ case R_MIPS_GPREL32:
+ handleGPRel(atom, ref);
+ break;
+ }
+}
+
+template <typename ELFT>
+static bool isConstrainSym(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref) {
+ if ((atom.section()->sh_flags & SHF_ALLOC) == 0)
+ return false;
+ switch (ref.kindValue()) {
+ case R_MIPS_NONE:
+ case R_MIPS_JALR:
+ case R_MIPS_GPREL32:
+ return false;
+ default:
+ return true;
}
}
@@ -330,7 +350,7 @@ RelocationPass<ELFT>::collectReferenceIn
return;
if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
return;
- if ((atom.section()->sh_flags & SHF_ALLOC) == 0)
+ if (!isConstrainSym(atom, ref))
return;
if (mightBeDynamic(atom, ref))
@@ -481,6 +501,13 @@ template <typename ELFT> void Relocation
}
template <typename ELFT>
+void RelocationPass<ELFT>::handleGPRel(const MipsELFDefinedAtom<ELFT> &atom,
+ Reference &ref) {
+ assert(ref.kindValue() == R_MIPS_GPREL32);
+ ref.setAddend(ref.addend() + atom.file().getGP0());
+}
+
+template <typename ELFT>
bool RelocationPass<ELFT>::isLocalCall(const Atom *a) const {
Atom::Scope scope;
if (auto *da = dyn_cast<DefinedAtom>(a))
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp?rev=207949&r1=207948&r2=207949&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp Mon May 5 00:56:06 2014
@@ -55,6 +55,7 @@ const Registry::KindStrings MipsTargetHa
LLD_KIND_STRING_ENTRY(R_MIPS_LO16),
LLD_KIND_STRING_ENTRY(R_MIPS_GOT16),
LLD_KIND_STRING_ENTRY(R_MIPS_CALL16),
+ LLD_KIND_STRING_ENTRY(R_MIPS_GPREL32),
LLD_KIND_STRING_ENTRY(R_MIPS_JALR),
LLD_KIND_STRING_ENTRY(R_MIPS_COPY),
LLD_KIND_STRING_ENTRY(R_MIPS_JUMP_SLOT),
Added: lld/trunk/test/elf/Mips/rel-gprel32.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/rel-gprel32.test?rev=207949&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/rel-gprel32.test (added)
+++ lld/trunk/test/elf/Mips/rel-gprel32.test Mon May 5 00:56:06 2014
@@ -0,0 +1,84 @@
+# Check R_MIPS_GPREL32 relocation handling.
+#
+# RUN: yaml2obj -format=elf %s > %t-obj
+# RUN: lld -flavor gnu -target mipsel -o %t-exe %t-obj
+# RUN: llvm-readobj -symbols %t-exe | FileCheck -check-prefix=SYM %s
+# RUN: llvm-objdump -s %t-exe | FileCheck -check-prefix=SEC %s
+
+# SYM: Name: $L1 (1)
+# SYM-NEXT: Value: 0x400108
+# SYM-NEXT: Size: 4
+# SYM-NEXT: Binding: Local (0x0)
+# SYM-NEXT: Type: Function (0x2)
+# SYM-NEXT: Other: 0
+# SYM-NEXT: Section: .text (0x5)
+#
+# SYM: Name: _gp (212)
+# SYM-NEXT: Value: 0x408FF0
+# SYM-NEXT: Size: 0
+# SYM-NEXT: Binding: Global (0x1)
+# SYM-NEXT: Type: Object (0x1)
+# SYM-NEXT: Other: 0
+# SYM-NEXT: Section: Absolute (0xFFF1)
+
+# 0x08FF711B == 0x8000001 (addend) + 0x400108 ($L1) +
+# 0x1000002 (GP0) - 0x408FF0 (_gp)
+# SEC: Contents of section .rodata:
+# SEC-NEXT: 400118 1b71ff08 00000000 00000000 00000000 .q..............
+
+!ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
+ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
+Sections:
+- Type: SHT_PROGBITS
+ Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Content: 00000000000000000000000000000000
+
+- Type: SHT_PROGBITS
+ Name: .rodata
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 0x04
+ Content: 01000008000000000000000000000000
+
+- Type: SHT_REL
+ Name: .rel.rodata
+ Type: SHT_REL
+ Link: .symtab
+ Info: .rodata
+ AddressAlign: 0x04
+ Relocations:
+ - Offset: 0
+ Symbol: $L1
+ Type: R_MIPS_GPREL32
+
+- Type: SHT_MIPS_REGINFO
+ Name: .reginfo
+ Type: SHT_MIPS_REGINFO
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 0x01
+ Content: 000000000000000000000000000000000000000002000001
+
+Symbols:
+ Local:
+ - Name: $L1
+ Section: .text
+ Value: 0x00
+ - Name: .rodata
+ Type: STT_SECTION
+ Section: .rodata
+ Global:
+ - Name: __start
+ Section: .text
+ Type: STT_FUNC
+ Value: 0x04
+ Size: 12
+ - Name: _gp_disp
More information about the llvm-commits
mailing list