diff options
author | Nick Kledzik <kledzik@apple.com> | 2013-01-23 22:32:56 +0000 |
---|---|---|
committer | Nick Kledzik <kledzik@apple.com> | 2013-01-23 22:32:56 +0000 |
commit | 36293f6512a25fe312e8e54e70e64928f3771c84 (patch) | |
tree | f94df5c5178cb000883f3fc843019344d3b68152 | |
parent | 563d33a6f1157c90d29fde58e8b368c86dd1eacc (diff) | |
download | bcm5719-llvm-36293f6512a25fe312e8e54e70e64928f3771c84.tar.gz bcm5719-llvm-36293f6512a25fe312e8e54e70e64928f3771c84.zip |
Add SectionPosition and OrderPass
llvm-svn: 173300
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(); |