[lld] r206102 - [ELF] Regroup code creates ELF relocations references ELFReference into
Simon Atanasyan
simon at atanasyan.com
Fri Apr 11 20:59:47 PDT 2014
Author: atanasyan
Date: Fri Apr 11 22:59:46 2014
New Revision: 206102
URL: http://llvm.org/viewvc/llvm-project?rev=206102&view=rev
Log:
[ELF] Regroup code creates ELF relocations references ELFReference into
a couple of new virtual functions.
Follow-up to the rL203408. Two virtual functions `createRelocationReference()`
responsible for creation of `ELFReference` have been replaced by a couple of
new virtual functions `createRelocationReferences()` (plural). Each former
function creates a //single// ELFReference for a specified `Elf_Rela`
or `Elf_Rel` relocation records. The new functions responsible for creation
of //all// relocation references for provided symbol.
For all targets except MIPS there are no functional changes.
MIPS ABI has a notion of //paired// relocations. An effective addend of such
relocations are calculated using addends of both pair's members.
Each `R_MIPS_HI16` and `R_MIPS_GOT16` (for local symbols) relocations must have
an associated `R_MIPS_LO16` entry immediately following it in the list
of relocations. Immediately does not mean "next record" in relocations section
but "next record referenced the same symbol". Moreover a single `R_MIPS_LO16`
relocation can be paired with multiple preceding `R_MIPS_HI16/R_MIPS_GOT16`
relocations.
The paired relocation can have offsets belong to the different symbols.
That is why we need to have access to list of all relocations during
construction of `ELFReference` for MIPS target.
The patch reviewed by Shankar Easwaran.
Modified:
lld/trunk/lib/ReaderWriter/ELF/ELFFile.h
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
lld/trunk/test/elf/Mips/hilo16-4.test
Modified: lld/trunk/lib/ReaderWriter/ELF/ELFFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFFile.h?rev=206102&r1=206101&r2=206102&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFFile.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFFile.h Fri Apr 11 22:59:46 2014
@@ -166,17 +166,19 @@ public:
protected:
ELFDefinedAtom<ELFT> *createDefinedAtomAndAssignRelocations(
StringRef symbolName, StringRef sectionName, const Elf_Sym *symbol,
- const Elf_Shdr *section, ArrayRef<uint8_t> content);
+ const Elf_Shdr *section, ArrayRef<uint8_t> symContent,
+ ArrayRef<uint8_t> secContent);
- /// \brief Create a reference for the Elf_Sym symbol
- /// and Elf_Rela relocation entry.
- virtual ELFReference<ELFT> *createRelocationReference(const Elf_Sym &symbol,
- const Elf_Rela &rai);
- /// \brief Create a reference for the Elf_Sym symbol
- /// and Elf_Rel relocation entry.
- virtual ELFReference<ELFT> *
- createRelocationReference(const Elf_Sym &symbol, const Elf_Rel &ri,
- ArrayRef<uint8_t> content);
+ /// \brief Iterate over Elf_Rela relocations list and create references.
+ virtual void createRelocationReferences(const Elf_Sym &symbol,
+ ArrayRef<uint8_t> content,
+ range<Elf_Rela_Iter> rels);
+
+ /// \brief Iterate over Elf_Rel relocations list and create references.
+ virtual void createRelocationReferences(const Elf_Sym &symbol,
+ ArrayRef<uint8_t> symContent,
+ ArrayRef<uint8_t> secContent,
+ range<Elf_Rel_Iter> rels);
/// \brief After all the Atoms and References are created, update each
/// Reference's target with the Atom pointer it refers to.
@@ -688,8 +690,8 @@ template <class ELFT> error_code ELFFile
// data.
auto sym = new (_readerStorage) Elf_Sym(*symbol);
sym->setBinding(llvm::ELF::STB_GLOBAL);
- anonAtom = createDefinedAtomAndAssignRelocations("", *sectionName, sym,
- section, symbolData);
+ anonAtom = createDefinedAtomAndAssignRelocations(
+ "", *sectionName, sym, section, symbolData, *sectionContents);
anonAtom->setOrdinal(++_ordinal);
symbolData = ArrayRef<uint8_t>();
@@ -702,7 +704,8 @@ template <class ELFT> error_code ELFFile
}
ELFDefinedAtom<ELFT> *newAtom = createDefinedAtomAndAssignRelocations(
- symbolName, *sectionName, &*symbol, section, symbolData);
+ symbolName, *sectionName, &*symbol, section, symbolData,
+ *sectionContents);
newAtom->setOrdinal(++_ordinal);
// If the atom was a weak symbol, let's create a followon reference to
@@ -742,56 +745,57 @@ template <class ELFT> error_code ELFFile
template <class ELFT>
ELFDefinedAtom<ELFT> *ELFFile<ELFT>::createDefinedAtomAndAssignRelocations(
StringRef symbolName, StringRef sectionName, const Elf_Sym *symbol,
- const Elf_Shdr *section, ArrayRef<uint8_t> content) {
+ const Elf_Shdr *section, ArrayRef<uint8_t> symContent,
+ ArrayRef<uint8_t> secContent) {
unsigned int referenceStart = _references.size();
- // Only relocations that are inside the domain of the atom are added.
-
// Add Rela (those with r_addend) references:
auto rari = _relocationAddendReferences.find(sectionName);
- if (rari != _relocationAddendReferences.end()) {
- for (const Elf_Rela &rai : rari->second) {
- if (symbol->st_value <= rai.r_offset &&
- rai.r_offset < symbol->st_value + content.size())
- _references.push_back(createRelocationReference(*symbol, rai));
- }
- }
+ if (rari != _relocationAddendReferences.end())
+ createRelocationReferences(*symbol, symContent, rari->second);
// Add Rel references.
auto rri = _relocationReferences.find(sectionName);
- if (rri != _relocationReferences.end()) {
- for (const Elf_Rel &ri : rri->second) {
- if (symbol->st_value <= ri.r_offset &&
- ri.r_offset < symbol->st_value + content.size())
- _references.push_back(createRelocationReference(*symbol, ri, content));
- }
- }
+ if (rri != _relocationReferences.end())
+ createRelocationReferences(*symbol, symContent, secContent, rri->second);
// Create the DefinedAtom and add it to the list of DefinedAtoms.
- return *handleDefinedSymbol(symbolName, sectionName, symbol, section, content,
- referenceStart, _references.size(), _references);
+ return *handleDefinedSymbol(symbolName, sectionName, symbol, section,
+ symContent, referenceStart, _references.size(),
+ _references);
}
template <class ELFT>
-ELFReference<ELFT> *
-ELFFile<ELFT>::createRelocationReference(const Elf_Sym &symbol,
- const Elf_Rela &rai) {
+void ELFFile<ELFT>::createRelocationReferences(const Elf_Sym &symbol,
+ ArrayRef<uint8_t> content,
+ range<Elf_Rela_Iter> rels) {
bool isMips64EL = _objFile->isMips64EL();
- return new (_readerStorage)
- ELFReference<ELFT>(&rai, rai.r_offset - symbol.st_value, kindArch(),
- rai.getType(isMips64EL), rai.getSymbol(isMips64EL));
+ for (const auto &rel : rels) {
+ if (rel.r_offset < symbol.st_value ||
+ symbol.st_value + content.size() <= rel.r_offset)
+ continue;
+ _references.push_back(new (_readerStorage) ELFReference<ELFT>(
+ &rel, rel.r_offset - symbol.st_value, kindArch(),
+ rel.getType(isMips64EL), rel.getSymbol(isMips64EL)));
+ }
}
template <class ELFT>
-ELFReference<ELFT> *ELFFile<ELFT>::createRelocationReference(
- const Elf_Sym &symbol, const Elf_Rel &ri, ArrayRef<uint8_t> content) {
+void ELFFile<ELFT>::createRelocationReferences(const Elf_Sym &symbol,
+ ArrayRef<uint8_t> symContent,
+ ArrayRef<uint8_t> secContent,
+ range<Elf_Rel_Iter> rels) {
bool isMips64EL = _objFile->isMips64EL();
- auto *ref = new (_readerStorage)
- ELFReference<ELFT>(&ri, ri.r_offset - symbol.st_value, kindArch(),
- ri.getType(isMips64EL), ri.getSymbol(isMips64EL));
- int32_t addend = *(content.data() + ri.r_offset - symbol.st_value);
- ref->setAddend(addend);
- return ref;
+ for (const auto &rel : rels) {
+ if (rel.r_offset < symbol.st_value ||
+ symbol.st_value + symContent.size() <= rel.r_offset)
+ continue;
+ _references.push_back(new (_readerStorage) ELFReference<ELFT>(
+ &rel, rel.r_offset - symbol.st_value, kindArch(),
+ rel.getType(isMips64EL), rel.getSymbol(isMips64EL)));
+ int32_t addend = *(symContent.data() + rel.r_offset - symbol.st_value);
+ _references.back()->setAddend(addend);
+ }
}
template <class ELFT>
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=206102&r1=206101&r2=206102&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h Fri Apr 11 22:59:46 2014
@@ -87,6 +87,7 @@ 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;
ErrorOr<ELFDefinedAtom<ELFT> *> handleDefinedSymbol(
StringRef symName, StringRef sectionName, const Elf_Sym *sym,
@@ -98,21 +99,35 @@ private:
referenceStart, referenceEnd, referenceList);
}
- ELFReference<ELFT> *
- createRelocationReference(const Elf_Sym &symbol, const Elf_Rel &ri,
- ArrayRef<uint8_t> content) override {
- bool isMips64EL = this->_objFile->isMips64EL();
- auto *ref = new (this->_readerStorage)
- ELFReference<ELFT>(&ri, ri.r_offset - symbol.st_value, this->kindArch(),
- ri.getType(isMips64EL), ri.getSymbol(isMips64EL));
- ref->setAddend(readAddend(symbol, ri, content));
- return ref;
+ void createRelocationReferences(const Elf_Sym &symbol,
+ ArrayRef<uint8_t> symContent,
+ ArrayRef<uint8_t> secContent,
+ range<Elf_Rel_Iter> rels) override {
+ for (Elf_Rel_Iter rit = rels.begin(), eit = rels.end(); rit != eit; ++rit) {
+ if (rit->r_offset < symbol.st_value ||
+ symbol.st_value + symContent.size() <= rit->r_offset)
+ continue;
+
+ this->_references.push_back(new (this->_readerStorage) ELFReference<ELFT>(
+ &*rit, rit->r_offset - symbol.st_value, this->kindArch(),
+ rit->getType(isMips64EL()), rit->getSymbol(isMips64EL())));
+
+ auto addend = readAddend(*rit, secContent);
+ if (needsMatchingRelocation(*rit)) {
+ auto mit = findMatchingRelocation(rit, eit);
+ // FIXME (simon): Handle this condition in a more user friendly way.
+ assert(mit != eit && "There is no paired R_MIPS_LO16 relocation");
+ auto matchingAddend = readAddend(*mit, secContent);
+ addend = (addend << 16) + int16_t(matchingAddend);
+ }
+ this->_references.back()->setAddend(addend);
+ }
}
- Reference::Addend readAddend(const Elf_Sym &symbol, const Elf_Rel &ri,
- ArrayRef<uint8_t> content) const {
- const uint8_t *ap = content.data() + ri.r_offset - symbol.st_value;
- switch (ri.getType(this->_objFile->isMips64EL())) {
+ Reference::Addend readAddend(const Elf_Rel &ri,
+ const ArrayRef<uint8_t> content) const {
+ const uint8_t *ap = content.data() + ri.r_offset;
+ switch (ri.getType(isMips64EL())) {
case llvm::ELF::R_MIPS_32:
case llvm::ELF::R_MIPS_PC32:
return *(int32_t *)ap;
@@ -126,6 +141,27 @@ private:
return 0;
}
}
+
+ bool needsMatchingRelocation(const Elf_Rel &rel) {
+ auto rType = rel.getType(isMips64EL());
+ if (rType == llvm::ELF::R_MIPS_HI16)
+ return true;
+ if (rType == llvm::ELF::R_MIPS_GOT16) {
+ const Elf_Sym *symbol =
+ this->_objFile->getSymbol(rel.getSymbol(isMips64EL()));
+ return symbol->getBinding() == llvm::ELF::STB_LOCAL;
+ }
+ return false;
+ }
+
+ Elf_Rel_Iter findMatchingRelocation(Elf_Rel_Iter rit, Elf_Rel_Iter eit) {
+ return std::find_if(rit, eit, [&](const Elf_Rel &rel) {
+ return rel.getType(isMips64EL()) == llvm::ELF::R_MIPS_LO16 &&
+ rel.getSymbol(isMips64EL()) == rit->getSymbol(isMips64EL());
+ });
+ }
+
+ bool isMips64EL() const { return this->_objFile->isMips64EL(); }
};
} // elf
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=206102&r1=206101&r2=206102&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp Fri Apr 11 22:59:46 2014
@@ -181,9 +181,6 @@ private:
/// \brief Handle a specific reference.
void handleReference(Reference &ref);
- /// \brief Calculate AHL addendums for the atom's references.
- void calculateAHLs(const DefinedAtom &atom);
-
void handlePlain(Reference &ref);
void handlePLT(Reference &ref);
void handleGOT(Reference &ref);
@@ -210,11 +207,9 @@ RelocationPass<ELFT>::RelocationPass(Mip
template <typename ELFT>
void RelocationPass<ELFT>::perform(std::unique_ptr<MutableFile> &mf) {
// Process all references.
- for (const auto &atom : mf->defined()) {
- calculateAHLs(*atom);
+ for (const auto &atom : mf->defined())
for (const auto &ref : *atom)
handleReference(const_cast<Reference &>(*ref));
- }
uint64_t ordinal = 0;
@@ -257,58 +252,6 @@ void RelocationPass<ELFT>::perform(std::
}
}
-/// \brief Calculate AHL value combines addends from 'hi' and 'lo' relocations.
-inline int64_t calcAHL(int64_t AHI, int64_t ALO) {
- AHI &= 0xffff;
- ALO &= 0xffff;
- return (AHI << 16) + (int16_t)ALO;
-}
-
-template <typename ELFT>
-void RelocationPass<ELFT>::calculateAHLs(const DefinedAtom &atom) {
- std::vector<const Reference *> lo16Refs;
- std::vector<Reference *> hi16Refs;
- for (const auto &ref : atom) {
- if (ref->kindNamespace() != lld::Reference::KindNamespace::ELF)
- continue;
- assert(ref->kindArch() == Reference::KindArch::Mips);
- switch (ref->kindValue()) {
- case R_MIPS_HI16:
- hi16Refs.push_back(const_cast<Reference *>(ref));
- case R_MIPS_LO16:
- lo16Refs.push_back(ref);
- break;
- case R_MIPS_GOT16:
- if (isLocal(ref->target()))
- hi16Refs.push_back(const_cast<Reference *>(ref));
- break;
- }
- }
-
- std::sort(lo16Refs.begin(), lo16Refs.end(),
- [](const Reference *a, const Reference *b) {
- return a->offsetInAtom() < b->offsetInAtom();
- });
- std::sort(hi16Refs.begin(), hi16Refs.end(),
- [](const Reference *a, const Reference *b) {
- return a->offsetInAtom() < b->offsetInAtom();
- });
-
- // Iterate over R_MIPS_LO16 relocations sorted by theirs offsets in the atom.
- // Calculate AHL addend for each R_MIPS_HI16 amd R_MIPS_GOT16 relocation
- // precedes the current R_MIPS_LO16 one.
-
- auto hic = hi16Refs.begin();
- for (const auto &lo : lo16Refs) {
- for (; hic != hi16Refs.end(); ++hic) {
- if ((*hic)->offsetInAtom() > lo->offsetInAtom())
- break;
- (*hic)->setAddend(calcAHL((*hic)->addend(), lo->addend()));
- }
- }
- assert(hic == hi16Refs.end());
-}
-
template <typename ELFT>
void RelocationPass<ELFT>::handleReference(Reference &ref) {
if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
Modified: lld/trunk/test/elf/Mips/hilo16-4.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/hilo16-4.test?rev=206102&r1=206101&r2=206102&view=diff
==============================================================================
--- lld/trunk/test/elf/Mips/hilo16-4.test (original)
+++ lld/trunk/test/elf/Mips/hilo16-4.test Fri Apr 11 22:59:46 2014
@@ -1,40 +1,90 @@
-# Check handling HI16/LO16 relocations go in mixed order.
-#
-# RUN: llvm-mc -triple=mipsel -filetype=obj -o=%t-obj %s
-# RUN: lld -flavor gnu -target mipsel -e A -o %t-exe %t-obj
+# Check pairing of R_MIPS_HI16 and R_MIPS_LO16 relocations.
+# RUN: yaml2obj -format=elf %s > %t-obj
+# RUN: lld -flavor gnu -target mipsel -e glob1 -o %t-exe %t-obj
# RUN: llvm-objdump -t -disassemble %t-exe | FileCheck %s
# CHECK: Disassembly of section .text:
-# CHECK: A:
-# CHECK-NEXT: 400128: 42 00 08 3c lui $8, 66
-# CHECK-NEXT: 40012c: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: 400130: 28 01 08 85 lh $8, 296($8)
-# CHECK-NEXT: 400134: 38 01 08 85 lh $8, 312($8)
-
-# CHECK: B:
-# CHECK-NEXT: 400138: 42 00 08 3c lui $8, 66
-# CHECK-NEXT: 40013c: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: 400140: 38 01 08 85 lh $8, 312($8)
-# CHECK-NEXT: 400144: 28 01 08 85 lh $8, 296($8)
+# CHECK: glob1:
+# CHECK-NEXT: 400140: 40 00 04 3c lui $4, 64
+# CHECK-NEXT: 400144: ff 9f a6 8c lw $6, -24577($5)
+
+# CHECK: glob2:
+# CHECK-NEXT: 400148: 00 20 c7 80 lb $7, 8192($6)
+# CHECK-NEXT: 40014c: 04 20 c8 80 lb $8, 8196($6)
+
+# CHECK: glob3:
+# CHECK-NEXT: 400150: 40 80 05 3c lui $5, 32832
# CHECK: SYMBOL TABLE:
-# CHECK: 00400128 g F .text 00000010 A
-# CHECK: 00400138 g F .text 00000010 B
+# CHECK: 00400140 g F .text 00000008 glob1
+# CHECK: 00400148 g F .text 00000008 glob2
+# CHECK: 00400150 g F .text 00000004 glob3
+# CHECK: 00402000 g .data 0000000c X
+
+!ELF
+FileHeader: !FileHeader
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+
+Sections:
+- Name: .text
+ Type: SHT_PROGBITS
+# glob1:
+# lui $4,%hi(X) # rel A
+# lw $6,%lo(X+32767)($5) # rel B
+# glob2:
+# lb $7,%lo(X)($6) # rel C
+# lb $8,%lo(X+4)($6) # rel D
+# glob3:
+# lui $5,%hi(X+32767) # rel E
+ Content: "0000043CFF7FA68C0000C7800400C880FF7F053C"
+ AddressAlign: 16
+ Flags: [SHF_EXECINSTR, SHF_ALLOC]
+
+- Name: .data
+ Type: SHT_PROGBITS
+ Content: "000000000000000000000000"
+ AddressAlign: 16
+ Flags: [SHF_WRITE, SHF_ALLOC]
+
+- Name: .rel.text
+ Type: SHT_REL
+ Info: .text
+ AddressAlign: 4
+ Relocations:
+ - Offset: 0x10 # rel E
+ Symbol: X
+ Type: R_MIPS_HI16
+ - Offset: 0x04 # rel B
+ Symbol: X
+ Type: R_MIPS_LO16
+ - Offset: 0x00 # rel A
+ Symbol: X
+ Type: R_MIPS_HI16
+ - Offset: 0x0C # rel D
+ Symbol: X
+ Type: R_MIPS_LO16
+ - Offset: 0x08 # rel C
+ Symbol: X
+ Type: R_MIPS_LO16
- .global A
- .ent A
-A:
- lui $t0,%hi(A+0x1ffff)
- lui $t0,%hi(B)
- lh $t0,%lo(A)($t0)
- lh $t0,%lo(B)($t0)
- .end A
-
- .global B
- .ent B
-B:
- lui $t0,%hi(A+0x1ffff)
- lui $t0,%hi(B)
- lh $t0,%lo(B)($t0)
- lh $t0,%lo(A)($t0)
- .end B
+Symbols:
+ Global:
+ - Name: glob1
+ Section: .text
+ Value: 0x0
+ Size: 8
+ - Name: glob2
+ Section: .text
+ Value: 0x8
+ Size: 8
+ - Name: glob3
+ Section: .text
+ Value: 0x10
+ Size: 4
+ - Name: X
+ Section: .data
+ Value: 0x0
+ Size: 12
More information about the llvm-commits
mailing list