[lld] r209582 - [Mips] Handle R_MIPS_TLS_TPREL_HI16 / R_MIPS_TLS_TPREL_LO16 relocations.
Simon Atanasyan
simon at atanasyan.com
Sat May 24 09:45:32 PDT 2014
Author: atanasyan
Date: Sat May 24 11:45:31 2014
New Revision: 209582
URL: http://llvm.org/viewvc/llvm-project?rev=209582&view=rev
Log:
[Mips] Handle R_MIPS_TLS_TPREL_HI16 / R_MIPS_TLS_TPREL_LO16 relocations.
Added:
lld/trunk/test/elf/Mips/tls-1.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=209582&r1=209581&r2=209582&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h Sat May 24 11:45:31 2014
@@ -69,7 +69,7 @@ public:
MipsELFFile(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings,
error_code &ec)
- : ELFFile<ELFT>(std::move(mb), atomizeStrings, ec), _gp0(0) {}
+ : ELFFile<ELFT>(std::move(mb), atomizeStrings, ec) {}
static ErrorOr<std::unique_ptr<MipsELFFile>>
create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) {
@@ -101,8 +101,9 @@ public:
if ((ec = file->createAtoms()))
return ec;
- // Retrieve registry usage descriptor and GP value.
- if ((ec = file->readRegInfo()))
+ // Retrieve some auxiliary data like GP value, TLS section address etc
+ // from the object file.
+ if ((ec = file->readAuxData()))
return ec;
return std::move(file);
@@ -113,7 +114,10 @@ public:
}
/// \brief gp register value stored in the .reginfo section.
- int64_t getGP0() const { return _gp0; }
+ int64_t getGP0() const { return *_gp0; }
+
+ /// \brief .tdata section address plus fixed offset.
+ uint64_t getTPOffset() const { return *_tpOff; }
private:
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
@@ -121,7 +125,10 @@ private:
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;
+ enum { TP_OFFSET = 0x7000 };
+
+ llvm::Optional<int64_t> _gp0;
+ llvm::Optional<uint64_t> _tpOff;
ErrorOr<ELFDefinedAtom<ELFT> *> handleDefinedSymbol(
StringRef symName, StringRef sectionName, const Elf_Sym *sym,
@@ -133,24 +140,23 @@ private:
referenceStart, referenceEnd, referenceList);
}
- error_code readRegInfo() {
+ error_code readAuxData() {
typedef llvm::object::Elf_RegInfo<ELFT> Elf_RegInfo;
for (const Elf_Shdr §ion : this->_objFile->sections()) {
- if (section.sh_type != llvm::ELF::SHT_MIPS_REGINFO)
- continue;
-
- auto contents = this->getSectionContents(§ion);
- 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;
+ if (!_gp0.hasValue() && section.sh_type == llvm::ELF::SHT_MIPS_REGINFO) {
+ auto contents = this->getSectionContents(§ion);
+ if (error_code ec = contents.getError())
+ return ec;
+
+ ArrayRef<uint8_t> raw = contents.get();
+
+ // FIXME (simon): Show error in case of invalid section size.
+ assert(raw.size() == sizeof(Elf_RegInfo) &&
+ "Invalid size of RegInfo section");
+ _gp0 = reinterpret_cast<const Elf_RegInfo *>(raw.data())->ri_gp_value;
+ } else if (!_tpOff.hasValue() && section.sh_flags & llvm::ELF::SHF_TLS)
+ _tpOff = section.sh_addr + TP_OFFSET;
}
return error_code::success();
}
@@ -195,6 +201,8 @@ private:
case llvm::ELF::R_MIPS_HI16:
case llvm::ELF::R_MIPS_LO16:
case llvm::ELF::R_MIPS_GOT16:
+ case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
+ case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
return *(int16_t *)ap;
default:
return 0;
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=209582&r1=209581&r2=209582&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp Sat May 24 11:45:31 2014
@@ -101,6 +101,20 @@ static void relocCall16(uint8_t *locatio
applyReloc(location, G, 0xffff);
}
+/// \brief R_MIPS_TLS_TPREL_HI16
+/// (S + A) >> 16
+static void relocTLSTpRelHi16(uint8_t *location, uint64_t S, int64_t A) {
+ int32_t result = S + A + 0x8000;
+ applyReloc(location, result >> 16, 0xffff);
+}
+
+/// \brief R_MIPS_TLS_TPREL_LO16
+/// S + A
+static void relocTLSTpRelLo16(uint8_t *location, uint64_t S, int64_t A) {
+ int32_t result = S + A;
+ applyReloc(location, result, 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,
@@ -162,6 +176,12 @@ error_code MipsTargetRelocationHandler::
case R_MIPS_CALL16:
relocCall16(location, relocVAddress, targetVAddress, ref.addend(), gpAddr);
break;
+ case R_MIPS_TLS_TPREL_HI16:
+ relocTLSTpRelHi16(location, targetVAddress, ref.addend());
+ break;
+ case R_MIPS_TLS_TPREL_LO16:
+ relocTLSTpRelLo16(location, targetVAddress, ref.addend());
+ break;
case R_MIPS_GPREL32:
relocGPRel32(location, relocVAddress, targetVAddress, ref.addend(), gpAddr);
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=209582&r1=209581&r2=209582&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp Sat May 24 11:45:31 2014
@@ -205,6 +205,7 @@ private:
void handle26(Reference &ref);
void handleGOT(Reference &ref);
void handleGPRel(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
+ void handleTLS(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
const GOTAtom *getLocalGOTEntry(const Reference &ref);
const GOTAtom *getGlobalGOTEntry(const Atom *a);
@@ -325,6 +326,10 @@ void RelocationPass<ELFT>::handleReferen
case R_MIPS_GPREL32:
handleGPRel(atom, ref);
break;
+ case R_MIPS_TLS_TPREL_HI16:
+ case R_MIPS_TLS_TPREL_LO16:
+ handleTLS(atom, ref);
+ break;
}
}
@@ -508,6 +513,15 @@ void RelocationPass<ELFT>::handleGPRel(c
}
template <typename ELFT>
+void RelocationPass<ELFT>::handleTLS(const MipsELFDefinedAtom<ELFT> &atom,
+ Reference &ref) {
+ assert((ref.kindValue() == R_MIPS_TLS_TPREL_HI16 ||
+ ref.kindValue() == R_MIPS_TLS_TPREL_LO16) &&
+ "Unexpected kind of relocation");
+ ref.setAddend(ref.addend() - atom.file().getTPOffset());
+}
+
+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=209582&r1=209581&r2=209582&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp Sat May 24 11:45:31 2014
@@ -57,6 +57,8 @@ const Registry::KindStrings MipsTargetHa
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_TLS_TPREL_HI16),
+ LLD_KIND_STRING_ENTRY(R_MIPS_TLS_TPREL_LO16),
LLD_KIND_STRING_ENTRY(R_MIPS_COPY),
LLD_KIND_STRING_ENTRY(R_MIPS_JUMP_SLOT),
LLD_KIND_STRING_ENTRY(R_MIPS_PC32),
Added: lld/trunk/test/elf/Mips/tls-1.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/tls-1.test?rev=209582&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/tls-1.test (added)
+++ lld/trunk/test/elf/Mips/tls-1.test Sat May 24 11:45:31 2014
@@ -0,0 +1,63 @@
+# Check handling of R_MIPS_TLS_TPREL_HI16 / R_MIPS_TLS_TPREL_LO16 relocations.
+
+# RUN: yaml2obj -format=elf -o %t.o %s
+# RUN: lld -flavor gnu -target mipsel -e L0 -o %t.exe %t.o
+# RUN: llvm-objdump -s %t.exe | FileCheck %s
+
+# CHECK: Contents of section .text:
+# CHECK: 400160 00000000 01000000 03800000 04800000 ................
+
+!ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
+ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x10
+ Content: '01000000020000000300000004000000'
+ - Name: .rel.text
+ Type: SHT_REL
+ Info: .text
+ AddressAlign: 0x04
+ Relocations:
+ - Offset: 0x00
+ Symbol: L1
+ Type: R_MIPS_TLS_TPREL_HI16
+ - Offset: 0x04
+ Symbol: L2
+ Type: R_MIPS_TLS_TPREL_HI16
+ - Offset: 0x08
+ Symbol: L2
+ Type: R_MIPS_TLS_TPREL_LO16
+ - Offset: 0x0C
+ Symbol: L1
+ Type: R_MIPS_TLS_TPREL_LO16
+ - Name: .tdata
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
+ AddressAlign: 0x04
+ Address: 0x1000
+ Size: 0x20000
+
+Symbols:
+ Global:
+ - Name: L0
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x58
+ - Name: L1
+ Type: STT_TLS
+ Section: .tdata
+ Value: 0x00
+ Size: 0x04
+ - Name: L2
+ Type: STT_TLS
+ Section: .tdata
+ Value: 0x10000
+ Size: 0x04
More information about the llvm-commits
mailing list