summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2013-01-23 22:32:56 +0000
committerNick Kledzik <kledzik@apple.com>2013-01-23 22:32:56 +0000
commit36293f6512a25fe312e8e54e70e64928f3771c84 (patch)
treef94df5c5178cb000883f3fc843019344d3b68152
parent563d33a6f1157c90d29fde58e8b368c86dd1eacc (diff)
downloadbcm5719-llvm-36293f6512a25fe312e8e54e70e64928f3771c84.tar.gz
bcm5719-llvm-36293f6512a25fe312e8e54e70e64928f3771c84.zip
Add SectionPosition and OrderPass
llvm-svn: 173300
-rw-r--r--lld/include/lld/Core/DefinedAtom.h12
-rw-r--r--lld/include/lld/Core/File.h23
-rw-r--r--lld/include/lld/Core/InputFiles.h3
-rw-r--r--lld/include/lld/Core/Pass.h11
-rw-r--r--lld/include/lld/Core/Resolver.h1
-rw-r--r--lld/lib/Core/DefinedAtom.cpp2
-rw-r--r--lld/lib/Core/File.cpp5
-rw-r--r--lld/lib/Core/InputFiles.cpp7
-rw-r--r--lld/lib/Core/Resolver.cpp23
-rw-r--r--lld/lib/Passes/CMakeLists.txt1
-rw-r--r--lld/lib/Passes/OrderPass.cpp84
-rw-r--r--lld/lib/ReaderWriter/ELF/AtomsELF.h4
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp1
-rw-r--r--lld/lib/ReaderWriter/MachO/SimpleAtoms.hpp5
-rw-r--r--lld/lib/ReaderWriter/Native/NativeFileFormat.h2
-rw-r--r--lld/lib/ReaderWriter/Native/ReaderNative.cpp8
-rw-r--r--lld/lib/ReaderWriter/Native/WriterNative.cpp3
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp4
-rw-r--r--lld/lib/ReaderWriter/ReaderArchive.cpp11
-rw-r--r--lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp33
-rw-r--r--lld/test/section-position.objtxt85
-rw-r--r--lld/tools/lld-core/TestingHelpers.hpp14
-rw-r--r--lld/tools/lld-core/lld-core.cpp17
23 files changed, 341 insertions, 18 deletions
diff --git a/lld/include/lld/Core/DefinedAtom.h b/lld/include/lld/Core/DefinedAtom.h
index f3ab5434a1e..8870f863347 100644
--- a/lld/include/lld/Core/DefinedAtom.h
+++ b/lld/include/lld/Core/DefinedAtom.h
@@ -142,8 +142,6 @@ public:
typeTLVInitialData, // initial data for a TLV [Darwin]
typeTLVInitialZeroFill, // TLV initial zero fill data [Darwin]
typeTLVInitializerPtr, // pointer to thread local initializer [Darwin]
- typeFirstInSection, // label for boundary of section [Darwin]
- typeLastInSection, // label for boundary of section [Darwin]
};
enum ContentPermissions {
@@ -163,6 +161,13 @@ public:
sectionCustomRequired // linker must place in specific section
};
+ enum SectionPosition {
+ sectionPositionStart, // atom must be at start of section (and zero size)
+ sectionPositionEarly, // atom should be near start of section
+ sectionPositionAny, // atom can be anywhere in section
+ sectionPositionEnd // atom must be at end of section (and zero size)
+ };
+
enum DeadStripKind {
deadStripNormal, // linker may dead strip this atom
deadStripNever, // linker must never dead strip this atom
@@ -226,6 +231,9 @@ public:
virtual StringRef customSectionName() const = 0;
/// \brief constraints on whether the linker may dead strip away this atom.
+ virtual SectionPosition sectionPosition() const = 0;
+
+ /// \brief constraints on whether the linker may dead strip away this atom.
virtual DeadStripKind deadStrip() const = 0;
/// \brief Returns the OS memory protections required for this atom's content
diff --git a/lld/include/lld/Core/File.h b/lld/include/lld/Core/File.h
index d403da00445..5b183d5906b 100644
--- a/lld/include/lld/Core/File.h
+++ b/lld/include/lld/Core/File.h
@@ -12,6 +12,7 @@
#include "lld/Core/AbsoluteAtom.h"
#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/range.h"
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/UndefinedAtom.h"
@@ -61,6 +62,19 @@ public:
/// be ascertained, this method returns the empty string.
virtual StringRef translationUnitSource() const;
+ /// Returns the command line order of the file.
+ uint64_t ordinal() const {
+ assert(_ordinal != UINT64_MAX);
+ return _ordinal;
+ }
+
+ /// Sets the command line order of the file. The parameter must
+ /// also be incremented to the next available ordinal number.
+ virtual void setOrdinalAndIncrement(uint64_t &ordinal) const {
+ _ordinal = ordinal;
+ ++ordinal;
+ }
+
public:
template <typename T> class atom_iterator; // forward reference
@@ -140,7 +154,7 @@ public:
protected:
/// \brief only subclasses of File can be instantiated
- File(StringRef p) : _path(p) {}
+ File(StringRef p) : _path(p), _ordinal(UINT64_MAX) {}
/// \brief This is a convenience class for File subclasses which manage their
@@ -193,7 +207,8 @@ protected:
static atom_collection_empty<SharedLibraryAtom> _noSharedLibaryAtoms;
static atom_collection_empty<AbsoluteAtom> _noAbsoluteAtoms;
- StringRef _path;
+ StringRef _path;
+ mutable uint64_t _ordinal;
};
/// \brief A mutable File.
@@ -202,6 +217,10 @@ public:
/// \brief Add an atom to the file. Invalidates iterators for all returned
/// containters.
virtual void addAtom(const Atom&) = 0;
+
+ typedef range<std::vector<const DefinedAtom*>::iterator> DefinedAtomRange;
+ virtual DefinedAtomRange definedAtoms() = 0;
+
protected:
/// \brief only subclasses of MutableFile can be instantiated
diff --git a/lld/include/lld/Core/InputFiles.h b/lld/include/lld/Core/InputFiles.h
index 2605a30817e..9802cb1704f 100644
--- a/lld/include/lld/Core/InputFiles.h
+++ b/lld/include/lld/Core/InputFiles.h
@@ -46,6 +46,9 @@ public:
/// Transfers ownership of a vector of Files to this InputFile object.
virtual void appendFiles(std::vector<std::unique_ptr<File>> &files);
+
+ /// Assigns an ordinal to each File for use by sort().
+ virtual void assignFileOrdinals();
/// @brief iterates all atoms in initial files
virtual void forEachInitialAtom(Handler &) const;
diff --git a/lld/include/lld/Core/Pass.h b/lld/include/lld/Core/Pass.h
index 7458d49de59..4ad57857dcb 100644
--- a/lld/include/lld/Core/Pass.h
+++ b/lld/include/lld/Core/Pass.h
@@ -110,6 +110,17 @@ public:
/// the specified atom.
virtual const DefinedAtom *makeGOTEntry(const Atom &target) = 0;
};
+
+/// Pass for sorting atoms.
+class OrderPass : public Pass {
+public:
+ OrderPass() : Pass() {}
+
+ /// Sorts atoms in mergedFile by content type then by command line order.
+ virtual void perform(MutableFile &mergedFile);
+};
+
+
} // namespace lld
#endif // LLD_CORE_PASS_H_
diff --git a/lld/include/lld/Core/Resolver.h b/lld/include/lld/Core/Resolver.h
index 4dafaf44105..95ccd2c9e81 100644
--- a/lld/include/lld/Core/Resolver.h
+++ b/lld/include/lld/Core/Resolver.h
@@ -86,6 +86,7 @@ private:
void addAtoms(std::vector<const Atom*>& atoms);
virtual void addAtom(const Atom& atom);
+ virtual DefinedAtomRange definedAtoms();
private:
friend class Resolver;
diff --git a/lld/lib/Core/DefinedAtom.cpp b/lld/lib/Core/DefinedAtom.cpp
index 191f12c96fd..609f151acec 100644
--- a/lld/lib/Core/DefinedAtom.cpp
+++ b/lld/lib/Core/DefinedAtom.cpp
@@ -66,8 +66,6 @@ DefinedAtom::ContentPermissions DefinedAtom::permissions(ContentType type) {
case typeUnknown:
case typeTempLTO:
- case typeFirstInSection:
- case typeLastInSection:
return permUnknown;
}
llvm_unreachable("unknown content type");
diff --git a/lld/lib/Core/File.cpp b/lld/lib/Core/File.cpp
index 402dfad0d55..a4148554410 100644
--- a/lld/lib/Core/File.cpp
+++ b/lld/lib/Core/File.cpp
@@ -24,4 +24,7 @@ File::atom_collection_empty<UndefinedAtom> File::_noUndefinedAtoms;
File::atom_collection_empty<SharedLibraryAtom> File::_noSharedLibaryAtoms;
File::atom_collection_empty<AbsoluteAtom> File::_noAbsoluteAtoms;
-}
+
+
+
+} // namespace lld
diff --git a/lld/lib/Core/InputFiles.cpp b/lld/lib/Core/InputFiles.cpp
index 78c8405c5ed..0c964d9af0c 100644
--- a/lld/lib/Core/InputFiles.cpp
+++ b/lld/lib/Core/InputFiles.cpp
@@ -41,6 +41,13 @@ void InputFiles::appendFiles(std::vector<std::unique_ptr<File>> &files) {
}
}
+void InputFiles::assignFileOrdinals() {
+ uint64_t i = 0;
+ for ( const File *file : _files ) {
+ file->setOrdinalAndIncrement(i);
+ }
+}
+
bool InputFiles::searchLibraries(StringRef name, bool searchSharedLibs,
bool searchArchives, bool dataSymbolOnly,
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index f53152b2ec9..b80a2214173 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -104,10 +104,25 @@ void Resolver::doDefinedAtom(const DefinedAtom &atom) {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
<< " DefinedAtom: "
<< llvm::format("0x%09lX", &atom)
+ << ", file=#"
+ << atom.file().ordinal()
+ << ", atom=#"
+ << atom.ordinal()
<< ", name="
<< atom.name()
<< "\n");
+ // Verify on zero-size atoms are pinned to start or end of section.
+ switch ( atom.sectionPosition() ) {
+ case DefinedAtom::sectionPositionStart:
+ case DefinedAtom::sectionPositionEnd:
+ assert(atom.size() == 0);
+ break;
+ case DefinedAtom::sectionPositionEarly:
+ case DefinedAtom::sectionPositionAny:
+ break;
+ }
+
// add to list of known atoms
_atoms.push_back(&atom);
@@ -364,6 +379,14 @@ void Resolver::MergedFile::addAtom(const Atom& atom) {
}
}
+
+MutableFile::DefinedAtomRange Resolver::MergedFile::definedAtoms() {
+ return range<std::vector<const DefinedAtom*>::iterator>(
+ _definedAtoms._atoms.begin(), _definedAtoms._atoms.end());
+}
+
+
+
void Resolver::MergedFile::addAtoms(std::vector<const Atom*>& all) {
DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
for ( const Atom *atom : all ) {
diff --git a/lld/lib/Passes/CMakeLists.txt b/lld/lib/Passes/CMakeLists.txt
index a96676e2c0b..b35bdc4f685 100644
--- a/lld/lib/Passes/CMakeLists.txt
+++ b/lld/lib/Passes/CMakeLists.txt
@@ -1,4 +1,5 @@
add_lld_library(lldPasses
GOTPass.cpp
+ OrderPass.cpp
StubsPass.cpp
)
diff --git a/lld/lib/Passes/OrderPass.cpp b/lld/lib/Passes/OrderPass.cpp
new file mode 100644
index 00000000000..60d52682267
--- /dev/null
+++ b/lld/lib/Passes/OrderPass.cpp
@@ -0,0 +1,84 @@
+//===- Passes/OrderPass.cpp - sort atoms ----------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This linker pass sorts atoms. By default atoms are sort first by the
+// order their .o files were found on the command line, then by order of the
+// atoms (address) in the .o file. But some atoms have a prefered location
+// in their section (such as pinned to the start or end of the section), so
+// the sort must take that into account too.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Pass.h"
+#include "lld/Core/Reference.h"
+#include "llvm/ADT/DenseMap.h"
+
+
+namespace lld {
+
+static bool compare(const DefinedAtom *left, const DefinedAtom *right) {
+ if ( left == right )
+ return false;
+
+ // Sort same permissions together.
+ DefinedAtom::ContentPermissions leftPerms = left->permissions();
+ DefinedAtom::ContentPermissions rightPerms = right->permissions();
+ if (leftPerms != rightPerms)
+ return leftPerms < rightPerms;
+
+
+ // Sort same content types together.
+ DefinedAtom::ContentType leftType = left->contentType();
+ DefinedAtom::ContentType rightType = right->contentType();
+ if (leftType != rightType)
+ return leftType < rightType;
+
+
+ // TO DO: Sort atoms in customs sections together.
+
+
+ // Sort by section position preference.
+ DefinedAtom::SectionPosition leftPos = left->sectionPosition();
+ DefinedAtom::SectionPosition rightPos = right->sectionPosition();
+ bool leftSpecialPos = (leftPos != DefinedAtom::sectionPositionAny);
+ bool rightSpecialPos = (rightPos != DefinedAtom::sectionPositionAny);
+ if (leftSpecialPos || rightSpecialPos) {
+ if (leftPos != rightPos)
+ return leftPos < rightPos;
+ }
+
+ // Sort by .o order.
+ const File *leftFile = &left->file();
+ const File *rightFile = &right->file();
+ if ( leftFile != rightFile )
+ return leftFile->ordinal() < rightFile->ordinal();
+
+ // Sort by atom order with .o file.
+ uint64_t leftOrdinal = left->ordinal();
+ uint64_t rightOrdinal = right->ordinal();
+ if ( leftOrdinal != rightOrdinal )
+ return leftOrdinal < rightOrdinal;
+
+ return false;
+}
+
+
+
+void OrderPass::perform(MutableFile &mergedFile) {
+
+ MutableFile::DefinedAtomRange atomRange = mergedFile.definedAtoms();
+
+ std::sort(atomRange.begin(), atomRange.end(), compare);
+}
+
+} // namespace
diff --git a/lld/lib/ReaderWriter/ELF/AtomsELF.h b/lld/lib/ReaderWriter/ELF/AtomsELF.h
index e184d37f985..b4f0a5d0614 100644
--- a/lld/lib/ReaderWriter/ELF/AtomsELF.h
+++ b/lld/lib/ReaderWriter/ELF/AtomsELF.h
@@ -305,6 +305,10 @@ public:
return _sectionName;
}
+ virtual SectionPosition sectionPosition() const {
+ return sectionPositionAny;
+ }
+
// It isn't clear that __attribute__((used)) is transmitted to the ELF object
// file.
virtual DeadStripKind deadStrip() const {
diff --git a/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
index f116716e796..fd5728d864d 100644
--- a/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
@@ -80,6 +80,7 @@ public:
virtual void addPasses(PassManager &pm) const {
pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
+ pm.add(std::unique_ptr<Pass>(new OrderPass()));
}
};
diff --git a/lld/lib/ReaderWriter/MachO/SimpleAtoms.hpp b/lld/lib/ReaderWriter/MachO/SimpleAtoms.hpp
index 0db2e055afe..1b7f1b57bbf 100644
--- a/lld/lib/ReaderWriter/MachO/SimpleAtoms.hpp
+++ b/lld/lib/ReaderWriter/MachO/SimpleAtoms.hpp
@@ -160,6 +160,11 @@ public:
virtual StringRef customSectionName() const {
return StringRef();
}
+
+ virtual SectionPosition sectionPosition() const {
+ return DefinedAtom::sectionPositionAny;
+ }
+
virtual DeadStripKind deadStrip() const {
return DefinedAtom::deadStripNormal;
}
diff --git a/lld/lib/ReaderWriter/Native/NativeFileFormat.h b/lld/lib/ReaderWriter/Native/NativeFileFormat.h
index d43236fd88f..5a715e54e37 100644
--- a/lld/lib/ReaderWriter/Native/NativeFileFormat.h
+++ b/lld/lib/ReaderWriter/Native/NativeFileFormat.h
@@ -150,7 +150,7 @@ struct NativeAtomAttributesV1 {
uint8_t interposable;
uint8_t merge;
uint8_t contentType;
- uint8_t sectionChoice;
+ uint8_t sectionChoiceAndPosition; // high nibble is choice, low is position
uint8_t deadStrip;
uint8_t permissions;
uint8_t alias;
diff --git a/lld/lib/ReaderWriter/Native/ReaderNative.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
index 0a69ae4171d..814215fea52 100644
--- a/lld/lib/ReaderWriter/Native/ReaderNative.cpp
+++ b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
@@ -75,11 +75,17 @@ public:
}
virtual DefinedAtom::SectionChoice sectionChoice() const {
- return (DefinedAtom::SectionChoice)(attributes().sectionChoice);
+ return (DefinedAtom::SectionChoice)(
+ attributes().sectionChoiceAndPosition >> 4);
}
virtual StringRef customSectionName() const;
+ virtual SectionPosition sectionPosition() const {
+ return (DefinedAtom::SectionPosition)(
+ attributes().sectionChoiceAndPosition & 0xF);
+ }
+
virtual DefinedAtom::DeadStripKind deadStrip() const {
return (DefinedAtom::DeadStripKind)(attributes().deadStrip);
}
diff --git a/lld/lib/ReaderWriter/Native/WriterNative.cpp b/lld/lib/ReaderWriter/Native/WriterNative.cpp
index 8b7026d50da..9b6587fe59b 100644
--- a/lld/lib/ReaderWriter/Native/WriterNative.cpp
+++ b/lld/lib/ReaderWriter/Native/WriterNative.cpp
@@ -436,7 +436,8 @@ private:
attrs.interposable = atom.interposable();
attrs.merge = atom.merge();
attrs.contentType = atom.contentType();
- attrs.sectionChoice = atom.sectionChoice();
+ attrs.sectionChoiceAndPosition
+ = atom.sectionChoice() << 4 | atom.sectionPosition();
attrs.deadStrip = atom.deadStrip();
attrs.permissions = atom.permissions();
//attrs.thumb = atom.isThumb();
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
index f9e473e31cc..db63830c13b 100644
--- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
@@ -153,6 +153,10 @@ public:
return "";
}
+ virtual SectionPosition sectionPosition() const {
+ return sectionPositionAny;
+ }
+
virtual DeadStripKind deadStrip() const {
return deadStripNormal;
}
diff --git a/lld/lib/ReaderWriter/ReaderArchive.cpp b/lld/lib/ReaderWriter/ReaderArchive.cpp
index 0fe4c2d1930..6dcde18a81c 100644
--- a/lld/lib/ReaderWriter/ReaderArchive.cpp
+++ b/lld/lib/ReaderWriter/ReaderArchive.cpp
@@ -56,10 +56,21 @@ public:
assert(result.size() == 1);
+ // TO DO: set ordinal of child just loaded
+
// give up the pointer so that this object no longer manages it
return result[0].release();
}
+ virtual void setOrdinalAndIncrement(uint64_t &ordinal) const {
+ _ordinal = ordinal++;
+ // Leave space in ordinal range for all children
+ for (auto mf = _archive->begin_children(),
+ me = _archive->end_children(); mf != me; ++mf) {
+ ordinal++;
+ }
+ }
+
virtual const atom_collection<DefinedAtom> &defined() const {
return _definedAtoms;
}
diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
index 7d702c51e8d..c17240e7369 100644
--- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
+++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
@@ -335,6 +335,16 @@ struct ScalarEnumerationTraits<lld::DefinedAtom::SectionChoice> {
};
template <>
+struct ScalarEnumerationTraits<lld::DefinedAtom::SectionPosition> {
+ static void enumeration(IO &io, lld::DefinedAtom::SectionPosition &value) {
+ io.enumCase(value, "start", lld::DefinedAtom::sectionPositionStart);
+ io.enumCase(value, "early", lld::DefinedAtom::sectionPositionEarly);
+ io.enumCase(value, "any", lld::DefinedAtom::sectionPositionAny);
+ io.enumCase(value, "end", lld::DefinedAtom::sectionPositionEnd);
+ }
+};
+
+template <>
struct ScalarEnumerationTraits<lld::DefinedAtom::Interposable> {
static void enumeration(IO &io, lld::DefinedAtom::Interposable &value) {
io.enumCase(value, "no", lld::DefinedAtom::interposeNo);
@@ -451,10 +461,6 @@ struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> {
lld::DefinedAtom::typeTLVInitialZeroFill);
io.enumCase(value, "tlv-initializer-ptr",
lld::DefinedAtom::typeTLVInitializerPtr);
- io.enumCase(value, "first-in-section",
- lld::DefinedAtom::typeFirstInSection);
- io.enumCase(value, "last-in-section",
- lld::DefinedAtom::typeLastInSection);
}
};
@@ -617,6 +623,14 @@ struct MappingTraits<const lld::File*> {
return this;
}
+ virtual void setOrdinalAndIncrement(uint64_t &ordinal) const {
+ _ordinal = ordinal++;
+ // Assign sequential ordinals to member files
+ for (const ArchMember &member : _members) {
+ member._content->setOrdinalAndIncrement(ordinal);
+ }
+ }
+
virtual const atom_collection<lld::DefinedAtom> &defined() const {
return _noDefinedAtoms;
}
@@ -824,6 +838,8 @@ struct MappingTraits<const lld::DefinedAtom*> {
NormalizedAtom(IO &io)
: _file(fileFromContext(io)), _name(), _refName(),
_alignment(0), _content(), _references() {
+ static uint32_t ordinalCounter = 1;
+ _ordinal = ordinalCounter++;
}
NormalizedAtom(IO &io, const lld::DefinedAtom *atom)
: _file(fileFromContext(io)),
@@ -835,6 +851,7 @@ struct MappingTraits<const lld::DefinedAtom*> {
_contentType(atom->contentType()),
_alignment(atom->alignment()),
_sectionChoice(atom->sectionChoice()),
+ _sectionPosition(atom->sectionPosition()),
_deadStrip(atom->deadStrip()),
_permissions(atom->permissions()),
_size(atom->size()),
@@ -882,6 +899,7 @@ struct MappingTraits<const lld::DefinedAtom*> {
virtual Alignment alignment() const { return _alignment; }
virtual SectionChoice sectionChoice() const { return _sectionChoice; }
virtual StringRef customSectionName() const { return _sectionName;}
+ virtual SectionPosition sectionPosition() const{return _sectionPosition;}
virtual DeadStripKind deadStrip() const { return _deadStrip; }
virtual ContentPermissions permissions() const { return _permissions; }
virtual bool isThumb() const { return false; }
@@ -891,7 +909,7 @@ struct MappingTraits<const lld::DefinedAtom*> {
reinterpret_cast<const uint8_t *>(_content.data()), _content.size());
}
- virtual uint64_t ordinal() const { return 0; }
+ virtual uint64_t ordinal() const { return _ordinal; }
reference_iterator begin() const {
uintptr_t index = 0;
@@ -923,8 +941,10 @@ struct MappingTraits<const lld::DefinedAtom*> {
ContentType _contentType;
Alignment _alignment;
SectionChoice _sectionChoice;
+ SectionPosition _sectionPosition;
DeadStripKind _deadStrip;
ContentPermissions _permissions;
+ uint32_t _ordinal;
std::vector<ImplicitHex8> _content;
uint64_t _size;
StringRef _sectionName;
@@ -968,6 +988,8 @@ struct MappingTraits<const lld::DefinedAtom*> {
lld::DefinedAtom::sectionBasedOnContent);
io.mapOptional("section-name", keys->_sectionName,
StringRef());
+ io.mapOptional("section-position",keys->_sectionPosition,
+ lld::DefinedAtom::sectionPositionAny);
io.mapOptional("dead-strip", keys->_deadStrip,
lld::DefinedAtom::deadStripNormal);
// default permissions based on content type
@@ -1038,6 +1060,7 @@ struct MappingTraits<const lld::UndefinedAtom*> {
};
+
// YAML conversion for const lld::SharedLibraryAtom*
template <>
struct MappingTraits<const lld::SharedLibraryAtom*> {
diff --git a/lld/test/section-position.objtxt b/lld/test/section-position.objtxt
new file mode 100644
index 00000000000..0eeb08bcf88
--- /dev/null
+++ b/lld/test/section-position.objtxt
@@ -0,0 +1,85 @@
+# RUN: lld-core -order-pass=true %s | FileCheck %s -check-prefix=CHKORDER
+# RUN: lld-core -order-pass=false %s | FileCheck %s -check-prefix=CHKUNORD
+
+#
+# Test that atoms with section position requirements are sorted properly.
+#
+
+---
+defined-atoms:
+ - name: data_end
+ type: data
+ section-position: end
+
+ - name: some_data
+ type: data
+ content: [ 01, 02 ]
+
+ - name: early_data
+ type: data
+ section-position: early
+ content: [ 00, 00, 00, 00 ]
+
+ - name: data_start
+ type: data
+ section-position: start
+
+---
+defined-atoms:
+ - name: data_end_too
+ type: data
+ section-position: end
+
+ - name: some_more_data
+ type: data
+ content: [ 03, 04 ]
+
+---
+defined-atoms:
+ - name: early_data_too
+ type: data
+ section-position: early
+ content: [ 00, 00, 00, 01 ]
+
+...
+
+
+# CHKUNORD: defined-atoms:
+# CHKUNORD: - name: data_end
+# CHKUNORD: section-position: end
+# CHKUNORD: - name: some_data
+# CHKUNORD: content: [ 01, 02 ]
+# CHKUNORD: - name: early_data
+# CHKUNORD: content: [ 00, 00, 00, 00 ]
+# CHKUNORD: section-position: early
+# CHKUNORD: - name: data_start
+# CHKUNORD: section-position: start
+# CHKUNORD: - name: data_end_too
+# CHKUNORD: section-position: end
+# CHKUNORD: - name: some_more_data
+# CHKUNORD: content: [ 03, 04 ]
+# CHKUNORD: - name: early_data_too
+# CHKUNORD: content: [ 00, 00, 00, 01 ]
+# CHKUNORD: section-position: early
+# CHKUNORD: ...
+
+# CHKORDER: defined-atoms:
+# CHKORDER: - name: data_start
+# CHKORDER: section-position: start
+# CHKORDER: - name: early_data
+# CHKORDER: content: [ 00, 00, 00, 00 ]
+# CHKORDER: section-position: early
+# CHKORDER: - name: early_data_too
+# CHKORDER: content: [ 00, 00, 00, 01 ]
+# CHKORDER: section-position: early
+# CHKORDER: - name: some_data
+# CHKORDER: content: [ 01, 02 ]
+# CHKORDER: - name: some_more_data
+# CHKORDER: content: [ 03, 04 ]
+# CHKORDER: - name: data_end
+# CHKORDER: section-position: end
+# CHKORDER: - name: data_end_too
+# CHKORDER: section-position: end
+# CHKORDER: ...
+
+
diff --git a/lld/tools/lld-core/TestingHelpers.hpp b/lld/tools/lld-core/TestingHelpers.hpp
index 68e7c3a534f..f7c0aa87d4d 100644
--- a/lld/tools/lld-core/TestingHelpers.hpp
+++ b/lld/tools/lld-core/TestingHelpers.hpp
@@ -81,6 +81,11 @@ public:
virtual StringRef customSectionName() const {
return StringRef();
}
+
+ virtual SectionPosition sectionPosition() const {
+ return sectionPositionAny;
+ }
+
virtual DeadStripKind deadStrip() const {
return DefinedAtom::deadStripNormal;
}
@@ -173,6 +178,10 @@ public:
return StringRef();
}
+ virtual SectionPosition sectionPosition() const {
+ return sectionPositionAny;
+ }
+
virtual DeadStripKind deadStrip() const {
return DefinedAtom::deadStripNormal;
}
@@ -224,6 +233,11 @@ public:
llvm_unreachable("atom has unknown definition kind");
}
+ virtual DefinedAtomRange definedAtoms() {
+ return range<std::vector<const DefinedAtom*>::iterator>(
+ _definedAtoms._atoms.begin(), _definedAtoms._atoms.end());
+ }
+
virtual const atom_collection<DefinedAtom> &defined() const {
return _definedAtoms;
}
diff --git a/lld/tools/lld-core/lld-core.cpp b/lld/tools/lld-core/lld-core.cpp
index 74a657af967..22cd570bdf2 100644
--- a/lld/tools/lld-core/lld-core.cpp
+++ b/lld/tools/lld-core/lld-core.cpp
@@ -69,6 +69,10 @@ cmdLineDoGotPass("got-pass",
llvm::cl::desc("Run pass to create GOT atoms"));
llvm::cl::opt<bool>
+cmdLineDoOrderPass("order-pass",
+ llvm::cl::desc("Run pass to sort atoms"));
+
+llvm::cl::opt<bool>
cmdLineUndefinesIsError("undefines-are-errors",
llvm::cl::desc("Any undefined symbols at end is an error"));
@@ -155,8 +159,8 @@ endianSelected("endian",
class TestingTargetInfo : public TargetInfo {
public:
- TestingTargetInfo(const LinkerOptions &lo, bool stubs, bool got)
- : TargetInfo(lo), _doStubs(stubs), _doGOT(got) {}
+ TestingTargetInfo(const LinkerOptions &lo, bool stubs, bool got, bool order)
+ : TargetInfo(lo), _doStubs(stubs), _doGOT(got), _doOrder(order) {}
virtual uint64_t getPageSize() const { return 0x1000; }
@@ -165,6 +169,8 @@ public:
pm.add(std::unique_ptr<Pass>(new TestingStubsPass));
if (_doGOT)
pm.add(std::unique_ptr<Pass>(new TestingGOTPass));
+ if (_doOrder)
+ pm.add(std::unique_ptr<Pass>(new OrderPass));
}
virtual ErrorOr<int32_t> relocKindFromString(StringRef str) const {
@@ -187,6 +193,7 @@ public:
private:
bool _doStubs;
bool _doGOT;
+ bool _doOrder;
};
int main(int argc, char *argv[]) {
@@ -230,7 +237,8 @@ int main(int argc, char *argv[]) {
break;
}
- TestingTargetInfo tti(lo, cmdLineDoStubsPass, cmdLineDoGotPass);
+ TestingTargetInfo tti(lo, cmdLineDoStubsPass, cmdLineDoGotPass,
+ cmdLineDoOrderPass);
std::unique_ptr<ELFTargetInfo> eti = ELFTargetInfo::create(lo);
std::unique_ptr<MachOTargetInfo> mti = MachOTargetInfo::create(lo);
@@ -296,6 +304,9 @@ int main(int argc, char *argv[]) {
// given writer a chance to add files
writer->addFiles(inputFiles);
+ // assign an ordinal to each file so sort() can preserve command line order
+ inputFiles.assignFileOrdinals();
+
// merge all atom graphs
Resolver resolver(tti, inputFiles);
resolver.resolve();
OpenPOWER on IntegriCloud