[llvm-commits] Followon/Preceded-By reference support in lld
Shankar Easwaran
shankare at codeaurora.org
Tue Nov 6 10:09:49 PST 2012
Hi Nick, Michael,
I have incorporated your review comments in the attached diff to support
followon / preceded by reference in lld with
* 2 test cases for testing the Core functionality
* 1 test case for testing ReaderELF
Let me know if its ok to commit this change.
Thanks
Shankar Easwaran
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation
-------------- next part --------------
Index: test/followon-basic.objtxt
===================================================================
--- test/followon-basic.objtxt (revision 0)
+++ test/followon-basic.objtxt (revision 0)
@@ -0,0 +1,78 @@
+# RUN: lld-core %s -dead-strip | FileCheck %s
+
+#
+# Test follow on references
+#
+
+---
+atoms:
+ - name: A
+ scope: global
+ type: code
+ section-choice: custom-required
+ section-name: .text
+
+ - name: B
+ scope: global
+ type: code
+ section-choice: custom-required
+ section-name: .text
+ fixups:
+ - offset: 0
+ kind: follow-on
+ target: C
+
+ - name: C
+ scope: global
+ type: code
+ section-choice: custom-required
+ section-name: .text
+ content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
+
+ - name: D
+ scope: global
+ type: code
+ section-choice: custom-required
+ section-name: .text
+ content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
+ dead-strip: never
+ fixups:
+ - offset: 0
+ kind: call32
+ target: B
+
+ - name: 1.c
+ definition: absolute
+ value: 0x0
+...
+
+
+# CHECK: ---
+# CHECK: atoms:
+# CHECK: - name: B
+# CHECK: scope: global
+# CHECK: type: code
+# CHECK: section-choice: custom-required
+# CHECK: section-name: .text
+# CHECK: fixups:
+# CHECK: - offset: 0
+# CHECK: kind: follow-on
+# CHECK: target: C
+# CHECK: - name: C
+# CHECK: scope: global
+# CHECK: type: code
+# CHECK: section-choice: custom-required
+# CHECK: section-name: .text
+# CHECK: content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
+# CHECK: - name: D
+# CHECK: scope: global
+# CHECK: type: code
+# CHECK: dead-strip: never
+# CHECK: section-choice: custom-required
+# CHECK: section-name: .text
+# CHECK: content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
+# CHECK: fixups:
+# CHECK: - offset: 0
+# CHECK: kind: call32
+# CHECK: target: B
+# CHECK: ...
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,64 @@
+# 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
+YAML: - name: fn1
+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 ]
+YAML: fixups:
+YAML: - offset: 0
+YAML: kind: preceded-by
+YAML: target: fn
Index: test/preceded-by-basic.objtxt
===================================================================
--- test/preceded-by-basic.objtxt (revision 0)
+++ test/preceded-by-basic.objtxt (revision 0)
@@ -0,0 +1,68 @@
+# RUN: lld-core %s -dead-strip | FileCheck %s
+
+#
+# Test preceded by references
+#
+
+---
+atoms:
+ - name: A
+ scope: global
+ type: code
+ section-choice: custom-required
+ section-name: .text
+
+ - name: B
+ scope: global
+ type: code
+ section-choice: custom-required
+ section-name: .text
+ fixups:
+ - offset: 0
+ kind: preceded-by
+ target: A
+
+ - name: C
+ scope: global
+ type: code
+ section-choice: custom-required
+ section-name: .text
+ dead-strip: never
+ fixups:
+ - offset: 0
+ kind: preceded-by
+ target: B
+
+
+ - name: 1.c
+ definition: absolute
+ value: 0x0
+...
+
+# CHECK: ---
+# CHECK: atoms:
+# CHECK: - name: A
+# CHECK: scope: global
+# CHECK: type: code
+# CHECK: section-choice: custom-required
+# CHECK: section-name: .text
+# CHECK: - name: B
+# CHECK: scope: global
+# CHECK: type: code
+# CHECK: section-choice: custom-required
+# CHECK: section-name: .text
+# CHECK: fixups:
+# CHECK: - offset: 0
+# CHECK: kind: preceded-by
+# CHECK: target: A
+# CHECK: - name: C
+# CHECK: scope: global
+# CHECK: type: code
+# CHECK: dead-strip: never
+# CHECK: section-choice: custom-required
+# CHECK: section-name: .text
+# CHECK: fixups:
+# CHECK: - offset: 0
+# CHECK: kind: preceded-by
+# CHECK: target: B
+# CHECK: ...
Index: tools/lld-core/TestingHelpers.hpp
===================================================================
--- tools/lld-core/TestingHelpers.hpp (revision 167130)
+++ tools/lld-core/TestingHelpers.hpp (working copy)
@@ -271,6 +271,8 @@
// Table of fixup kinds in YAML documents used for testing
//
const TestingKindMapping sKinds[] = {
+ { "preceded-by", -2, true, false, false},
+ { "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)
@@ -11,6 +11,8 @@
#define LLD_CORE_REFERENCES_H_
#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/StringRef.h"
+#include <map>
namespace lld {
@@ -33,12 +35,29 @@
/// Negative kind values are architecture independent.
typedef int32_t Kind;
+ enum {
+ FollowOn = -1,
+ PrecededBy = -2,
+ LayoutBefore = -3,
+ LayoutAfter = -4
+ };
+
// A value to be added to the value of a target
typedef int64_t Addend;
/// What sort of reference this is.
virtual Kind kind() const = 0;
+ virtual StringRef kindToString() const {
+ if (kind() < 0)
+ return _kindToString.find(kind())->second;
+ return "unknown";
+ }
+
+ virtual int32_t stringToKind(StringRef kindString) const {
+ return _stringToKind.find(kindString)->second;
+ }
+
/// During linking, some optimizations may change the code gen and
/// hence the reference kind.
virtual void setKind(Kind) = 0;
@@ -63,15 +82,27 @@
protected:
/// Atom is an abstract base class. Only subclasses can access constructor.
- Reference() {}
+ Reference() {
+ _kindToString[-1] = "follow-on";
+ _kindToString[-2] = "preceded-by";
+ _kindToString[-3] = "layout-before";
+ _kindToString[-4] = "layout-after";
+ _stringToKind["follow-on"] = -1;
+ _stringToKind["preceded-by"] = -2;
+ _stringToKind["layout-before"] = -3;
+ _stringToKind["layout-after"] = -4;
+ }
/// The memory for Reference objects is always managed by the owning File
/// object. Therefore, no one but the owning File object should call
/// delete on an Reference. In fact, some File objects may bulk allocate
/// an array of References, so they cannot be individually deleted by anyone.
virtual ~Reference() {}
-};
+private:
+ std::map<int32_t, StringRef> _kindToString;
+ std::map<StringRef, int32_t> _stringToKind;
+};
} // namespace lld
Index: lib/ReaderWriter/ELF/ReaderELF.cpp
===================================================================
--- lib/ReaderWriter/ELF/ReaderELF.cpp (revision 167130)
+++ lib/ReaderWriter/ELF/ReaderELF.cpp (working copy)
@@ -58,14 +58,21 @@
, _targetSymbolIndex(rela->getSymbol())
, _offsetInAtom(offset)
, _addend(rela->r_addend)
- , _kind(rela->getType()) {}
+ , _kind((Kind)rela->getType()) {}
ELFReference(const Elf_Rel *rel, uint64_t offset, const Atom *target)
: _target(target)
, _targetSymbolIndex(rel->getSymbol())
, _offsetInAtom(offset)
, _addend(0)
- , _kind(rel->getType()) {}
+ , _kind((Kind)rel->getType()) {}
+
+ ELFReference(Kind kind)
+ : _target(nullptr)
+ , _targetSymbolIndex(0)
+ , _offsetInAtom(0)
+ , _addend(0)
+ , _kind(kind) {}
virtual uint64_t offsetInAtom() const {
@@ -428,6 +435,12 @@
It = reinterpret_cast<const void*>(index);
}
+ void updateReferences(std::vector<ELFReference<target_endianness, is64Bits> *>
+ &_references) {
+ _referenceList = _references;
+ _referenceEndIndex = _referenceList.size();
+ }
+
private:
const File &_owningFile;
@@ -606,6 +619,9 @@
return A->st_value < B->st_value;
}));
+ ELFDefinedAtom<target_endianness, is64Bits> *previous_atom = nullptr;
+ const Elf_Sym *previous_sym = nullptr;
+
// i.first is the section the symbol lives in
for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
@@ -640,6 +656,30 @@
symbolData = llvm::ArrayRef<uint8_t>((uint8_t *)symbolContents.data()
+ (*si)->st_value, contentSize);
+ // Check to see if we need to add the FollowOn Reference
+ // We dont want to do for symbols that are
+ // a) common symbols
+ // b) the atoms have the merge attribute set
+ // We add a follow on reference only if there is a gap
+ // in between two atoms, we dont know what the gap is
+ // so, lets add a follow-on reference from the previous atom to the
+ // current atom as well as lets add a preceded-by reference from the
+ // current atom to the previous atom, so that the previous atom
+ // is not removed in any case
+ ELFReference<target_endianness, is64Bits> *followOn = nullptr;
+ if (!isCommon &&
+ previous_atom &&
+ previous_atom->merge() == DefinedAtom::mergeNo) {
+ if (((*si)->st_value - (previous_sym->st_value +
+ previous_sym->st_size)) > 0) {
+ followOn = new (_readerStorage.Allocate
+ <ELFReference<target_endianness, is64Bits> > ())
+ ELFReference<target_endianness, is64Bits> (
+ lld::Reference::FollowOn);
+ _references.push_back(followOn);
+ previous_atom->updateReferences(_references);
+ }
+ }
unsigned int referenceStart = _references.size();
@@ -674,6 +714,18 @@
}
}
+ // If we are inserting a followOn reference, lets add a precededBy
+ // reference too
+ ELFReference<target_endianness, is64Bits> *precededBy = nullptr;
+ if (followOn) {
+ precededBy = new (_readerStorage.Allocate
+ <ELFReference<target_endianness, is64Bits> > ())
+ ELFReference<target_endianness, is64Bits> (
+ lld::Reference::PrecededBy);
+ precededBy->setTarget(previous_atom);
+ _references.push_back(precededBy);
+ }
+
// Create the DefinedAtom and add it to the list of DefinedAtoms.
auto *newAtom = new (_readerStorage.Allocate
<ELFDefinedAtom<target_endianness, is64Bits> > ())
@@ -682,6 +734,12 @@
*si, i.first, symbolData,
referenceStart, _references.size(), _references);
+ if (followOn) {
+ followOn->setTarget(newAtom);
+ }
+ previous_atom = newAtom;
+ previous_sym = *si;
+
_definedAtoms._atoms.push_back(newAtom);
_symbolToAtomMapping.insert(std::make_pair((*si), newAtom));
@@ -691,10 +749,12 @@
// All the Atoms and References are created. Now update each Reference's
// target with the Atom pointer it refers to.
for (auto &ri : _references) {
+ if (ri->kind() > lld::Reference::FollowOn) {
const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex());
ri->setTarget(findAtom (Symbol));
}
}
+ }
virtual void addAtom(const Atom&) {
llvm_unreachable("cannot add atoms to native .o files");
More information about the llvm-commits
mailing list