[llvm-commits] [lld] add support for followon references
Shankar Easwaran
shankare at codeaurora.org
Thu Nov 1 07:24:12 PDT 2012
Hi,
Can you please review the patch to add support for followon references
in lld. The patch includes a test case for the changes done in ReaderELF.
Thanks
Shankar Easwaran
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation
-------------- next part --------------
Index: test/elf/Inputs/followon-reference-test.elf-i386
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: test/elf/Inputs/followon-reference-test.elf-i386
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: test/elf/followon-reference.objtxt
===================================================================
--- test/elf/followon-reference.objtxt (revision 0)
+++ test/elf/followon-reference.objtxt (revision 0)
@@ -0,0 +1,54 @@
+# Test generated by using the following
+# .file "1.c"
+# .text
+# .globl fn
+# .type fn, @function
+#fn:
+#.LFB0:
+# .cfi_startproc
+# pushq %rbp
+# .cfi_def_cfa_offset 16
+# .cfi_offset 6, -16
+# movq %rsp, %rbp
+# .cfi_def_cfa_register 6
+# movl $0, %eax
+# popq %rbp
+# .cfi_def_cfa 7, 8
+# ret
+# .cfi_endproc
+#.LFE0:
+# .size fn, .-fn
+# .align 32
+# .globl fn1
+# .type fn1, @function
+#fn1:
+#.LFB1:
+# .cfi_startproc
+# pushq %rbp
+# .cfi_def_cfa_offset 16
+# .cfi_offset 6, -16
+# movq %rsp, %rbp
+# .cfi_def_cfa_register 6
+# movl $0, %eax
+# popq %rbp
+# .cfi_def_cfa 7, 8
+# ret
+# .cfi_endproc
+#.LFE1:
+# .size fn1, .-fn1
+# .section .note.GNU-stack,"", at progbits
+
+RUN: lld-core -reader ELF %p/Inputs/followon-reference-test.elf-i386 | FileCheck -check-prefix=YAML %s
+
+YAML: - name: fn
+YAML: scope: global
+YAML: type: code
+YAML: section-choice: custom-required
+YAML: section-name: .text
+YAML: content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3, 66,
+YAML: 0F, 1F, 44, 00, 00, 66, 66, 66, 66, 66, 66, 2E,
+YAML: 0F, 1F, 84, 00, 00, 00, 00, 00 ]
+YAML: fixups:
+YAML: - offset: 0
+YAML: kind: follow-on
+YAML: target: fn1
Index: tools/lld-core/TestingHelpers.hpp
===================================================================
--- tools/lld-core/TestingHelpers.hpp (revision 167130)
+++ tools/lld-core/TestingHelpers.hpp (working copy)
@@ -271,6 +271,7 @@
// Table of fixup kinds in YAML documents used for testing
//
const TestingKindMapping sKinds[] = {
+ { "follow-on", -1, true, false, false},
{ "call32", 2, true, false, false},
{ "pcrel32", 3, false, false, false },
{ "gotLoad32", 7, false, true, true },
Index: include/lld/Core/Reference.h
===================================================================
--- include/lld/Core/Reference.h (revision 167130)
+++ include/lld/Core/Reference.h (working copy)
@@ -36,6 +36,10 @@
// A value to be added to the value of a target
typedef int64_t Addend;
+ enum {
+ kindFollowOnReference = -1,
+ };
+
/// What sort of reference this is.
virtual Kind kind() const = 0;
@@ -72,7 +76,44 @@
virtual ~Reference() {}
};
+/// FollowOnReference supports forcing layout of atoms, that one atom must
+/// follow another atom.
+class FollowOnReference : public Reference {
+public:
+ /// Return the reference is of type FollowOnReference
+ virtual Kind kind() const { return _kind; }
+ virtual void setKind(Kind) { _kind = kindFollowOnReference; }
+
+ virtual uint64_t offsetInAtom() const { return 0; }
+
+ /// If the reference is an edge to another Atom, then this returns the
+ /// other Atom. Otherwise, it returns nullptr.
+ virtual const class Atom * target() const { return _targetAtom; }
+
+ /// Set the followon Atom
+ virtual void setTarget(const class Atom *atom) { _targetAtom = atom; }
+
+ /// Some relocations require a symbol and a value (e.g. foo + 4).
+ virtual Addend addend() const { return 0; }
+
+ /// During linking, some optimzations may change addend value.
+ virtual void setAddend(Addend) { }
+
+public:
+ FollowOnReference():Reference(),
+ _targetAtom(NULL),
+ _kind(kindFollowOnReference)
+ {}
+
+ virtual ~FollowOnReference() {}
+
+private:
+ const Atom *_targetAtom;
+ Kind _kind;
+};
+
+
} // namespace lld
#endif // LLD_CORE_REFERENCES_H_
Index: lib/ReaderWriter/ELF/ReaderELF.cpp
===================================================================
--- lib/ReaderWriter/ELF/ReaderELF.cpp (revision 167130)
+++ lib/ReaderWriter/ELF/ReaderELF.cpp (working copy)
@@ -84,6 +84,10 @@
return _target;
}
+ static bool classof(const Reference *S) {
+ return true;
+ }
+
/// \brief targetSymbolIndex: This is the symbol table index that contains
/// the target reference.
uint64_t targetSymbolIndex() const {
@@ -220,8 +224,7 @@
llvm::ArrayRef<uint8_t> contentData,
unsigned int referenceStart,
unsigned int referenceEnd,
- std::vector<ELFReference
- <target_endianness, is64Bits> *> &referenceList)
+ std::vector<Reference *> &referenceList)
: _owningFile(file)
, _symbolName(symbolName)
@@ -403,6 +406,12 @@
return _contentData;
}
+ void updateReferences(std::vector<Reference *> &referenceList)
+ {
+ _referenceList = referenceList;
+ _referenceEndIndex = referenceList.size();
+ }
+
DefinedAtom::reference_iterator begin() const {
uintptr_t index = _referenceStartIndex;
const void *it = reinterpret_cast<const void*>(index);
@@ -441,7 +450,7 @@
uint64_t _ordinal;
unsigned int _referenceStartIndex;
unsigned int _referenceEndIndex;
- std::vector<ELFReference<target_endianness, is64Bits> *> &_referenceList;
+ std::vector<Reference *> &_referenceList;
};
@@ -606,6 +615,9 @@
return A->st_value < B->st_value;
}));
+ ELFDefinedAtom<target_endianness, is64Bits> *previous_atom = NULL;
+ const Elf_Sym *previous_sym = NULL;
+
// i.first is the section the symbol lives in
for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
@@ -640,7 +652,24 @@
symbolData = llvm::ArrayRef<uint8_t>((uint8_t *)symbolContents.data()
+ (*si)->st_value, contentSize);
+ Reference *followOn = NULL;
+ // Check to see if we need to add the FollowOn Reference
+ // We add a follow on reference only if current_symbol_value -
+ // previous_symbol_value + previous_symbol_size > 0
+ if (!isCommon && previous_sym) {
+ if (((*si)->st_value - (previous_sym->st_value +
+ previous_sym->st_size)) > 0) {
+
+ followOn = new (_readerStorage.Allocate<FollowOnReference>())
+ FollowOnReference();
+
+ _references.push_back(followOn);
+
+ previous_atom->updateReferences(_references);
+ }
+ }
+
unsigned int referenceStart = _references.size();
// Only relocations that are inside the domain of the atom are
@@ -682,6 +711,17 @@
*si, i.first, symbolData,
referenceStart, _references.size(), _references);
+ // Check to see if we need to add the FollowOn Reference
+ // We add a follow on reference only if current_symbol_value -
+ // previous_symbol_value + previous_symbol_size > 0
+ if (followOn) {
+ fprintf(stderr, "adding a followon reference\n");
+ followOn->setTarget(newAtom);
+ }
+
+ previous_atom = newAtom;
+ previous_sym = *si;
+
_definedAtoms._atoms.push_back(newAtom);
_symbolToAtomMapping.insert(std::make_pair((*si), newAtom));
@@ -691,8 +731,11 @@
// All the Atoms and References are created. Now update each Reference's
// target with the Atom pointer it refers to.
for (auto &ri : _references) {
- const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex());
- ri->setTarget(findAtom (Symbol));
+ if (ri->kind() != Reference::kindFollowOnReference) {
+ ELFReference<target_endianness, is64Bits> *eri = (llvm::dyn_cast<ELFReference<target_endianness,is64Bits>>(ri));
+ const Elf_Sym *Symbol = _objFile->getElfSymbol(eri->targetSymbolIndex());
+ ri->setTarget(findAtom (Symbol));
+ }
}
}
@@ -740,7 +783,7 @@
std::map<llvm::StringRef, std::vector<const Elf_Rel *> >
_relocationReferences;
- std::vector<ELFReference<target_endianness, is64Bits> *> _references;
+ std::vector<Reference *> _references;
llvm::DenseMap<const Elf_Sym *, Atom *> _symbolToAtomMapping;
llvm::BumpPtrAllocator _readerStorage;
More information about the llvm-commits
mailing list