[lld] r179257 - This adds functionality for undefined atoms from dynamic libraries to be added
Nick Kledzik
kledzik at apple.com
Wed Apr 10 22:11:36 PDT 2013
There is a ton of gratuitous whitespace changes. During review, you said you were going to correct that before committing.
-Nick
On Apr 10, 2013, at 7:56 PM, Shankar Easwaran wrote:
> Author: shankare
> Date: Wed Apr 10 21:56:30 2013
> New Revision: 179257
>
> URL: http://llvm.org/viewvc/llvm-project?rev=179257&view=rev
> Log:
> This adds functionality for undefined atoms from dynamic libraries to be added
> to the list of undefined atoms.
>
> The processing of undefined atoms from dynamic libraries is controlled by
> use-shlib-undefines command line option.
>
> This patch also adds additional command line arguments to allow/disallow
> unresolved symbols from shared libraries and mimics GNU ld behavior.
>
>
> Added:
> lld/trunk/test/elf/dynamic-undef.test
> Modified:
> lld/trunk/include/lld/Core/Resolver.h
> lld/trunk/include/lld/Core/TargetInfo.h
> lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h
> lld/trunk/lib/Core/Resolver.cpp
> lld/trunk/lib/Core/TargetInfo.cpp
> lld/trunk/lib/Driver/GnuLdDriver.cpp
> lld/trunk/lib/Driver/LDOptions.td
> lld/trunk/lib/ReaderWriter/ELF/Atoms.h
> lld/trunk/lib/ReaderWriter/ELF/DynamicFile.h
> lld/trunk/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
> lld/trunk/test/elf/dynamic-segorder.test
> lld/trunk/test/elf/dynamic.test
>
> Modified: lld/trunk/include/lld/Core/Resolver.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=179257&r1=179256&r2=179257&view=diff
> ==============================================================================
> --- lld/trunk/include/lld/Core/Resolver.h (original)
> +++ lld/trunk/include/lld/Core/Resolver.h Wed Apr 10 21:56:30 2013
> @@ -12,6 +12,7 @@
>
> #include "lld/Core/File.h"
> #include "lld/Core/InputFiles.h"
> +#include "lld/Core/SharedLibraryFile.h"
> #include "lld/Core/SymbolTable.h"
>
> #include "llvm/ADT/DenseSet.h"
>
> Modified: lld/trunk/include/lld/Core/TargetInfo.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/TargetInfo.h?rev=179257&r1=179256&r2=179257&view=diff
> ==============================================================================
> --- lld/trunk/include/lld/Core/TargetInfo.h (original)
> +++ lld/trunk/include/lld/Core/TargetInfo.h Wed Apr 10 21:56:30 2013
> @@ -35,44 +35,44 @@ class InputFiles;
>
> /// \brief The TargetInfo class encapsulates "what and how" to link.
> ///
> -/// The base class TargetInfo contains the options needed by core linking.
> -/// Subclasses of TargetInfo have additional options needed by specific Readers
> -/// and Writers. For example, ELFTargetInfo has methods that supplies options
> +/// The base class TargetInfo contains the options needed by core linking.
> +/// Subclasses of TargetInfo have additional options needed by specific Readers
> +/// and Writers. For example, ELFTargetInfo has methods that supplies options
> /// to the ELF Reader and Writer.
> ///
> -/// \todo Consider renaming to something like "LinkingOptions".
> +/// \todo Consider renaming to something like "LinkingOptions".
> class TargetInfo : public Reader {
> public:
> virtual ~TargetInfo();
>
> /// \name Methods needed by core linking
> /// @{
> -
> - /// Name of symbol linker should use as "entry point" to program,
> +
> + /// Name of symbol linker should use as "entry point" to program,
> /// usually "main" or "start".
> - StringRef entrySymbolName() const {
> - return _entrySymbolName;
> + StringRef entrySymbolName() const {
> + return _entrySymbolName;
> }
> -
> - /// Whether core linking should remove Atoms not reachable by following
> +
> + /// Whether core linking should remove Atoms not reachable by following
> /// References from the entry point Atom or from all global scope Atoms
> /// if globalsAreDeadStripRoots() is true.
> - bool deadStrip() const {
> - return _deadStrip;
> + bool deadStrip() const {
> + return _deadStrip;
> }
> -
> +
> /// Only used if deadStrip() returns true. Means all global scope Atoms
> /// should be marked live (along with all Atoms they reference). Usually
> /// this method returns false for main executables, but true for dynamic
> /// shared libraries.
> bool globalsAreDeadStripRoots() const {
> assert(_deadStrip && "only applicable when deadstripping enabled");
> - return _globalsAreDeadStripRoots;
> + return _globalsAreDeadStripRoots;
> }
> -
> +
> /// Only used if deadStrip() returns true. This method returns the names
> - /// of DefinedAtoms that should be marked live (along with all Atoms they
> - /// reference). Only Atoms with scope scopeLinkageUnit or scopeGlobal can
> + /// of DefinedAtoms that should be marked live (along with all Atoms they
> + /// reference). Only Atoms with scope scopeLinkageUnit or scopeGlobal can
> /// be kept live using this method.
> const std::vector<StringRef> &deadStripRoots() const {
> return _deadStripRoots;
> @@ -80,51 +80,51 @@ public:
>
> /// Archive files (aka static libraries) are normally lazily loaded. That is,
> /// object files within an archive are only loaded and linked in, if the
> - /// object file contains a DefinedAtom which will replace an existing
> + /// object file contains a DefinedAtom which will replace an existing
> /// UndefinedAtom. If this method returns true, core linking will actively
> /// load every member object file from every archive.
> - bool forceLoadAllArchives() const {
> - return _forceLoadAllArchives;
> + bool forceLoadAllArchives() const {
> + return _forceLoadAllArchives;
> }
> -
> +
> /// Archive files (aka static libraries) are normally lazily loaded. That is,
> /// object files within an archive are only loaded and linked in, if the
> - /// object file contains a DefinedAtom which will replace an existing
> + /// object file contains a DefinedAtom which will replace an existing
> /// UndefinedAtom. If this method returns true, core linking will also look
> /// for archive members to replace existing tentative definitions in addition
> /// to replacing undefines. Note: a "tentative definition" (also called a
> /// "common" symbols) is a C (but not C++) concept. They are modeled in lld
> /// as a DefinedAtom with merge() of mergeAsTentative.
> - bool searchArchivesToOverrideTentativeDefinitions() const {
> - return _searchArchivesToOverrideTentativeDefinitions;
> + bool searchArchivesToOverrideTentativeDefinitions() const {
> + return _searchArchivesToOverrideTentativeDefinitions;
> }
> -
> +
> /// Normally core linking will turn a tentative definition into a real
> /// definition if not replaced by a real DefinedAtom from some object file.
> /// If this method returns true, core linking will search all supplied
> /// dynamic shared libraries for symbol names that match remaining tentative
> /// definitions. If any are found, the corresponding tentative definition
> - /// atom is replaced with SharedLibraryAtom.
> - bool searchSharedLibrariesToOverrideTentativeDefinitions() const {
> - return _searchSharedLibrariesToOverrideTentativeDefinitions;
> + /// atom is replaced with SharedLibraryAtom.
> + bool searchSharedLibrariesToOverrideTentativeDefinitions() const {
> + return _searchSharedLibrariesToOverrideTentativeDefinitions;
> }
> -
> +
> /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a
> /// SharedLibraryAtom for the link to be successful. This method controls
> /// whether core linking prints out a list of remaining UndefinedAtoms.
> ///
> - /// \todo This should be a method core linking calls with a list of the
> + /// \todo This should be a method core linking calls with a list of the
> /// UndefinedAtoms so that different drivers can format the error message
> /// as needed.
> - bool printRemainingUndefines() const {
> - return _printRemainingUndefines;
> + bool printRemainingUndefines() const {
> + return _printRemainingUndefines;
> }
>
> /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a
> /// SharedLibraryAtom for the link to be successful. This method controls
> /// whether core linking considers remaining undefines to be an error.
> - bool allowRemainingUndefines() const {
> - return _allowRemainingUndefines;
> + bool allowRemainingUndefines() const {
> + return _allowRemainingUndefines;
> }
>
> /// In the lld model, a SharedLibraryAtom is a proxy atom for something
> @@ -135,48 +135,56 @@ public:
> /// when merging core linking will also verify that they both have the same
> /// loadName() and if not print a warning.
> ///
> - /// \todo This should be a method core linking calls so that drivers can
> + /// \todo This should be a method core linking calls so that drivers can
> /// format the warning as needed.
> - bool warnIfCoalesableAtomsHaveDifferentLoadName() const {
> - return _warnIfCoalesableAtomsHaveDifferentLoadName;
> + bool warnIfCoalesableAtomsHaveDifferentLoadName() const {
> + return _warnIfCoalesableAtomsHaveDifferentLoadName;
> }
> -
> - /// In C/C++ you can mark a function's prototype with
> - /// __attribute__((weak_import)) or __attribute__((weak)) to say the function
> +
> + /// In C/C++ you can mark a function's prototype with
> + /// __attribute__((weak_import)) or __attribute__((weak)) to say the function
> /// may not be available at runtime and/or build time and in which case its
> - /// address will evaluate to NULL. In lld this is modeled using the
> + /// address will evaluate to NULL. In lld this is modeled using the
> /// UndefinedAtom::canBeNull() method. During core linking, UndefinedAtom
> /// with the same name are automatically merged. If this method returns
> /// true, core link also verfies that the canBeNull() value for merged
> /// UndefinedAtoms are the same and warns if not.
> ///
> - /// \todo This should be a method core linking calls so that drivers can
> + /// \todo This should be a method core linking calls so that drivers can
> /// format the warning as needed.
> - bool warnIfCoalesableAtomsHaveDifferentCanBeNull() const {
> - return _warnIfCoalesableAtomsHaveDifferentCanBeNull;
> + bool warnIfCoalesableAtomsHaveDifferentCanBeNull() const {
> + return _warnIfCoalesableAtomsHaveDifferentCanBeNull;
> + }
> +
> + /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a
> + /// SharedLibraryAtom for the link to be successful. This method controls
> + /// whether core linking considers remaining undefines from the shared library
> + /// to be an error.
> + bool allowShlibUndefines() const {
> + return _allowShlibUndefines;
> }
> -
> +
> /// If true, core linking will write the path to each input file to stdout
> /// (i.e. llvm::outs()) as it is used. This is used to implement the -t
> /// linker option.
> ///
> - /// \todo This should be a method core linking calls so that drivers can
> + /// \todo This should be a method core linking calls so that drivers can
> /// format the line as needed.
> bool logInputFiles() const {
> - return _logInputFiles;
> + return _logInputFiles;
> }
> -
> +
> /// Parts of LLVM use global variables which are bound to command line
> /// options (see llvm::cl::Options). This method returns "command line"
> - /// options which are used to configure LLVM's command line settings.
> + /// options which are used to configure LLVM's command line settings.
> /// For instance the -debug-only XXX option can be used to dynamically
> /// trace different parts of LLVM and lld.
> const std::vector<const char*> &llvmOptions() const {
> return _llvmOptions;
> }
> -
> +
> /// This method returns the sequence of input files for core linking to
> - /// process.
> + /// process.
> ///
> /// \todo Consider moving this out of TargetInfo so that the same TargetInfo
> /// object can be reused for different links.
> @@ -184,85 +192,88 @@ public:
> return _inputFiles;
> }
> /// @}
> -
> -
> +
> +
> /// \name Methods used by Drivers to configure TargetInfo
> /// @{
> void setOutputPath(StringRef str) { _outputPath = str; }
> void setEntrySymbolName(StringRef name) { _entrySymbolName = name; }
> void setDeadStripping(bool enable) { _deadStrip = enable; }
> void setGlobalsAreDeadStripRoots(bool v) { _globalsAreDeadStripRoots = v; }
> - void setSearchArchivesToOverrideTentativeDefinitions(bool search) {
> - _searchArchivesToOverrideTentativeDefinitions = search;
> + void setSearchArchivesToOverrideTentativeDefinitions(bool search) {
> + _searchArchivesToOverrideTentativeDefinitions = search;
> }
> - void setSearchSharedLibrariesToOverrideTentativeDefinitions(bool search) {
> - _searchSharedLibrariesToOverrideTentativeDefinitions = search;
> + void setSearchSharedLibrariesToOverrideTentativeDefinitions(bool search) {
> + _searchSharedLibrariesToOverrideTentativeDefinitions = search;
> }
> - void setWarnIfCoalesableAtomsHaveDifferentCanBeNull(bool warn) {
> - _warnIfCoalesableAtomsHaveDifferentCanBeNull = warn;
> + void setWarnIfCoalesableAtomsHaveDifferentCanBeNull(bool warn) {
> + _warnIfCoalesableAtomsHaveDifferentCanBeNull = warn;
> }
> - void setWarnIfCoalesableAtomsHaveDifferentLoadName(bool warn) {
> - _warnIfCoalesableAtomsHaveDifferentLoadName = warn;
> + void setWarnIfCoalesableAtomsHaveDifferentLoadName(bool warn) {
> + _warnIfCoalesableAtomsHaveDifferentLoadName = warn;
> }
> - void setForceLoadAllArchives(bool force) {
> - _forceLoadAllArchives = force;
> + void setForceLoadAllArchives(bool force) {
> + _forceLoadAllArchives = force;
> }
> - void setPrintRemainingUndefines(bool print) {
> - _printRemainingUndefines = print;
> + void setPrintRemainingUndefines(bool print) {
> + _printRemainingUndefines = print;
> }
> - void setAllowRemainingUndefines(bool allow) {
> - _allowRemainingUndefines = allow;
> + void setAllowRemainingUndefines(bool allow) {
> + _allowRemainingUndefines = allow;
> }
> - void setLogInputFiles(bool log) {
> - _logInputFiles = log;
> + void setAllowShlibUndefines(bool allow) {
> + _allowShlibUndefines = allow;
> }
> - void appendInputFile(StringRef path) {
> + void setLogInputFiles(bool log) {
> + _logInputFiles = log;
> + }
> + void appendInputFile(StringRef path) {
> _inputFiles.emplace_back(LinkerInput(path));
> }
> - void appendInputFile(std::unique_ptr<llvm::MemoryBuffer> buffer) {
> + void appendInputFile(std::unique_ptr<llvm::MemoryBuffer> buffer) {
> _inputFiles.emplace_back(LinkerInput(std::move(buffer)));
> }
> - void appendLLVMOption(const char *opt) {
> + void appendLLVMOption(const char *opt) {
> _llvmOptions.push_back(opt);
> }
> -
> +
> /// After all set* methods are called, the Driver calls this method
> /// to validate that there are no missing options or invalid combinations
> /// of options. If there is a problem, a description of the problem
> /// is written to the supplied stream.
> ///
> - /// \returns true if there is an error with the current settings.
> + /// \returns true if there is an error with the current settings.
> virtual bool validate(raw_ostream &diagnostics) = 0;
>
>
> /// @}
> /// \name Methods used by Driver::link()
> /// @{
> -
> +
> /// Returns the file system path to which the linked output should be written.
> ///
> /// \todo To support in-memory linking, we need an abstraction that allows
> /// the linker to write to an in-memory buffer.
> - StringRef outputPath() const {
> - return _outputPath;
> + StringRef outputPath() const {
> + return _outputPath;
> }
> -
> +
> /// Abstract method to parse a supplied input file buffer into one or
> - /// more lld::File objects. Subclasses of TargetInfo must implement this
> - /// method.
> + /// more lld::File objects. Subclasses of TargetInfo must implement this
> + /// method.
> ///
> /// \param inputBuff This is an in-memory read-only copy of the input file.
> /// If the resulting lld::File object will contain pointers into
> /// this memory buffer, the lld::File object should take ownership
> - /// of the buffer. Otherwise core linking will maintain ownership of the
> - /// buffer and delete it at some point.
> + /// of the buffer. Otherwise core linking will maintain ownership of the
> + /// buffer and delete it at some point.
> ///
> /// \param [out] result The instantiated lld::File object is returned here.
> /// The \p result is a vector because some input files parse into more than
> - /// one lld::File (e.g. YAML).
> + /// one lld::File (e.g. YAML).
> virtual error_code parseFile(std::unique_ptr<MemoryBuffer> &inputBuff,
> std::vector<std::unique_ptr<File>> &result) const = 0;
> -
> +
> /// This is a wrapper around parseFile() where the input file is specified
> /// by file system path. The default implementation reads the input file
> /// into a memory buffer and calls parseFile().
> @@ -276,12 +287,12 @@ public:
> /// to add file format specific "files" to set of files to be linked. This is
> /// how file format specific atoms can be added to the link.
> virtual void addImplicitFiles(InputFiles&) const;
> -
> +
> /// This method is called by core linking to build the list of Passes to be
> /// run on the merged/linked graph of all input files.
> virtual void addPasses(PassManager &pm) const;
>
> - /// Calls through to the writeFile() method on the specified Writer.
> + /// Calls through to the writeFile() method on the specified Writer.
> ///
> /// \param linkedFile This is the merged/linked graph of all input file Atoms.
> virtual error_code writeFile(const File &linkedFile) const;
> @@ -289,18 +300,18 @@ public:
> /// @}
>
>
> - /// \name Methods needed by YAML I/O and error messages to convert Kind values
> + /// \name Methods needed by YAML I/O and error messages to convert Kind values
> /// to and from strings.
> /// @{
> -
> - /// Abstract method to parse a kind name string into an integral
> +
> + /// Abstract method to parse a kind name string into an integral
> /// Reference::Kind
> virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const = 0;
>
> - /// Abstract method to return the name for a given integral
> + /// Abstract method to return the name for a given integral
> /// Reference::Kind.
> virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind k) const = 0;
> -
> +
> /// @}
>
>
> @@ -310,7 +321,7 @@ protected:
>
> /// Abstract method to lazily instantiate the Writer.
> virtual Writer &writer() const = 0;
> -
> +
>
> StringRef _outputPath;
> StringRef _entrySymbolName;
> @@ -324,6 +335,7 @@ protected:
> bool _printRemainingUndefines;
> bool _allowRemainingUndefines;
> bool _logInputFiles;
> + bool _allowShlibUndefines;
> std::vector<StringRef> _deadStripRoots;
> std::vector<LinkerInput> _inputFiles;
> std::vector<const char*> _llvmOptions;
>
> Modified: lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h?rev=179257&r1=179256&r2=179257&view=diff
> ==============================================================================
> --- lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h (original)
> +++ lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h Wed Apr 10 21:56:30 2013
> @@ -45,6 +45,13 @@ public:
> bool mergeCommonStrings() const { return _mergeCommonStrings; }
> virtual uint64_t getBaseAddress() const { return _baseAddress; }
>
> + /// This controls if undefined atoms need to be created for undefines that are
> + /// present in a SharedLibrary. If this option is set, undefined atoms are
> + /// created for every undefined symbol that are present in the dynamic table
> + /// in the shared library
> + bool useShlibUndefines() const { return _useShlibUndefines; }
> + /// @}
> +
> /// \brief Does this relocation belong in the dynamic relocation table?
> ///
> /// This table is evaluated at loadtime by the dynamic loader and is
> @@ -60,7 +67,7 @@ public:
>
> virtual error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
> std::vector<std::unique_ptr<File>> &result) const;
> -
> +
> static std::unique_ptr<ELFTargetInfo> create(llvm::Triple);
>
> /// \brief Does this relocation belong in the dynamic plt relocation table?
> @@ -79,7 +86,7 @@ public:
> }
>
> /// \brief Does the output have dynamic sections.
> - bool isDynamic() const;
> + bool isDynamic() const;
>
> template <typename ELFT>
> lld::elf::TargetHandler<ELFT> &getTargetHandler() const {
> @@ -95,16 +102,17 @@ public:
> void setNoInhibitExec(bool v) { _noInhibitExec = v; }
> void setIsStaticExecutable(bool v) { _isStaticExecutable = v; }
> void setMergeCommonStrings(bool v) { _mergeCommonStrings = v; }
> - void appendSearchPath(StringRef dirPath) {
> + void setUseShlibUndefines(bool use) { _useShlibUndefines = use; }
> + void appendSearchPath(StringRef dirPath) {
> _inputSearchPaths.push_back(dirPath);
> }
> /// Searches directories then calls appendInputFile()
> bool appendLibrary(StringRef libName);
> -
> +
> private:
> ELFTargetInfo() LLVM_DELETED_FUNCTION;
> protected:
> - ELFTargetInfo(llvm::Triple);
> + ELFTargetInfo(llvm::Triple);
>
> virtual Writer &writer() const;
>
> @@ -117,6 +125,7 @@ protected:
> bool _noInhibitExec;
> bool _mergeCommonStrings;
> bool _runLayoutPass;
> + bool _useShlibUndefines;
> std::vector<StringRef> _inputSearchPaths;
> llvm::BumpPtrAllocator _extraStrings;
> mutable std::unique_ptr<Reader> _elfReader;
>
> Modified: lld/trunk/lib/Core/Resolver.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=179257&r1=179256&r2=179257&view=diff
> ==============================================================================
> --- lld/trunk/lib/Core/Resolver.cpp (original)
> +++ lld/trunk/lib/Core/Resolver.cpp Wed Apr 10 21:56:30 2013
> @@ -181,11 +181,11 @@ void Resolver::addAtoms(const std::vecto
> // ask symbol table if any definitionUndefined atoms still exist
> // if so, keep searching libraries until no more atoms being added
> void Resolver::resolveUndefines() {
> - const bool searchArchives =
> - _targetInfo.searchArchivesToOverrideTentativeDefinitions();
> - const bool searchSharedLibs =
> - _targetInfo.searchSharedLibrariesToOverrideTentativeDefinitions();
> -
> + const bool searchArchives =
> + _targetInfo.searchArchivesToOverrideTentativeDefinitions();
> + const bool searchSharedLibs =
> + _targetInfo.searchSharedLibrariesToOverrideTentativeDefinitions();
> +
> // keep looping until no more undefines were added in last loop
> unsigned int undefineGenCount = 0xFFFFFFFF;
> while (undefineGenCount != _symbolTable.size()) {
> @@ -311,15 +311,23 @@ bool Resolver::checkUndefines(bool final
>
> // error message about missing symbols
> if (!undefinedAtoms.empty()) {
> - // FIXME: need diagonstics interface for writing error messages
> + // FIXME: need diagnostics interface for writing error messages
> bool foundUndefines = false;
> for (const UndefinedAtom *undefAtom : undefinedAtoms) {
> - if (undefAtom->canBeNull() == UndefinedAtom::canBeNullNever) {
> - foundUndefines = true;
> - if (_targetInfo.printRemainingUndefines()) {
> - llvm::errs() << "Undefined Symbol: " << undefAtom->file().path()
> - << " : " << undefAtom->name() << "\n";
> + const File &f = undefAtom->file();
> + bool isAtomUndefined = false;
> + if (isa<SharedLibraryFile>(f)) {
> + if (!_targetInfo.allowShlibUndefines()) {
> + foundUndefines = true;
> + isAtomUndefined = true;
> }
> + } else if (undefAtom->canBeNull() == UndefinedAtom::canBeNullNever) {
> + foundUndefines = true;
> + isAtomUndefined = true;
> + }
> + if (isAtomUndefined && _targetInfo.printRemainingUndefines()) {
> + llvm::errs() << "Undefined Symbol: " << undefAtom->file().path()
> + << " : " << undefAtom->name() << "\n";
> }
> }
> if (foundUndefines) {
>
> Modified: lld/trunk/lib/Core/TargetInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/TargetInfo.cpp?rev=179257&r1=179256&r2=179257&view=diff
> ==============================================================================
> --- lld/trunk/lib/Core/TargetInfo.cpp (original)
> +++ lld/trunk/lib/Core/TargetInfo.cpp Wed Apr 10 21:56:30 2013
> @@ -15,23 +15,17 @@
> namespace lld {
>
> TargetInfo::TargetInfo()
> - : Reader(*this)
> - , _deadStrip(false)
> - , _globalsAreDeadStripRoots(false)
> - , _searchArchivesToOverrideTentativeDefinitions(false)
> - , _searchSharedLibrariesToOverrideTentativeDefinitions(false)
> - , _warnIfCoalesableAtomsHaveDifferentCanBeNull(false)
> - , _warnIfCoalesableAtomsHaveDifferentLoadName(false)
> - , _forceLoadAllArchives(false)
> - , _printRemainingUndefines(true)
> - , _allowRemainingUndefines(false)
> - , _logInputFiles(false)
> -{
> -}
> + : Reader(*this), _deadStrip(false), _globalsAreDeadStripRoots(false),
> + _searchArchivesToOverrideTentativeDefinitions(false),
> + _searchSharedLibrariesToOverrideTentativeDefinitions(false),
> + _warnIfCoalesableAtomsHaveDifferentCanBeNull(false),
> + _warnIfCoalesableAtomsHaveDifferentLoadName(false),
> + _forceLoadAllArchives(false), _printRemainingUndefines(true),
> + _allowRemainingUndefines(false), _logInputFiles(false),
> + _allowShlibUndefines(false) {}
>
> TargetInfo::~TargetInfo() {}
>
> -
> error_code TargetInfo::readFile(StringRef path,
> std::vector<std::unique_ptr<File>> &result) const {
> OwningPtr<llvm::MemoryBuffer> opmb;
>
> Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=179257&r1=179256&r2=179257&view=diff
> ==============================================================================
> --- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
> +++ lld/trunk/lib/Driver/GnuLdDriver.cpp Wed Apr 10 21:56:30 2013
> @@ -77,33 +77,33 @@ bool GnuLdDriver::linkELF(int argc, cons
> std::unique_ptr<ELFTargetInfo> options(parse(argc, argv, diagnostics));
> if (!options)
> return true;
> -
> +
> return link(*options, diagnostics);
> }
>
> -
> -std::unique_ptr<ELFTargetInfo> GnuLdDriver::parse(int argc, const char *argv[],
> - raw_ostream &diagnostics) {
> +std::unique_ptr<ELFTargetInfo>
> +GnuLdDriver::parse(int argc, const char *argv[], raw_ostream &diagnostics) {
> // Parse command line options using LDOptions.td
> std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
> GnuLdOptTable table;
> unsigned missingIndex;
> unsigned missingCount;
> - parsedArgs.reset(table.ParseArgs(&argv[1], &argv[argc],
> - missingIndex, missingCount));
> + parsedArgs.reset(
> + table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));
> if (missingCount) {
> - diagnostics << "error: missing arg value for '"
> - << parsedArgs->getArgString(missingIndex)
> - << "' expected " << missingCount << " argument(s).\n";
> + diagnostics << "error: missing arg value for '"
> + << parsedArgs->getArgString(missingIndex) << "' expected "
> + << missingCount << " argument(s).\n";
> return nullptr;
> }
>
> for (auto it = parsedArgs->filtered_begin(OPT_UNKNOWN),
> ie = parsedArgs->filtered_end(); it != ie; ++it) {
> - diagnostics << "warning: ignoring unknown argument: "
> - << (*it)->getAsString(*parsedArgs) << "\n";
> + diagnostics << "warning: ignoring unknown argument: " << (*it)->getAsString(
> + *parsedArgs)
> + << "\n";
> }
> -
> +
> // Handle --help
> if (parsedArgs->getLastArg(OPT_help)) {
> table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
> @@ -112,37 +112,36 @@ std::unique_ptr<ELFTargetInfo> GnuLdDriv
>
> // Use -target or use default target triple to instantiate TargetInfo
> llvm::Triple triple;
> - if (llvm::opt::Arg *trip = parsedArgs->getLastArg(OPT_target))
> + if (llvm::opt::Arg *trip = parsedArgs->getLastArg(OPT_target))
> triple = llvm::Triple(trip->getValue());
> else
> triple = getDefaultTarget(argv[0]);
> std::unique_ptr<ELFTargetInfo> options(ELFTargetInfo::create(triple));
> -
> +
> if (!options) {
> diagnostics << "unknown target triple\n";
> return nullptr;
> }
> -
> +
> // Handle -e xxx
> if (llvm::opt::Arg *entry = parsedArgs->getLastArg(OPT_entry))
> options->setEntrySymbolName(entry->getValue());
> -
> +
> // Handle -emit-yaml
> if (parsedArgs->getLastArg(OPT_emit_yaml))
> options->setOutputYAML(true);
> -
> +
> // Handle -o xxx
> - if (llvm::opt::Arg *output = parsedArgs->getLastArg(OPT_output))
> + if (llvm::opt::Arg *output = parsedArgs->getLastArg(OPT_output))
> options->setOutputPath(output->getValue());
> else if (options->outputYAML())
> - options->setOutputPath("-"); // yaml writes to stdout by default
> + options->setOutputPath("-"); // yaml writes to stdout by default
> else
> options->setOutputPath("a.out");
> -
> +
> // Handle -r, -shared, or -static
> - if ( llvm::opt::Arg *kind = parsedArgs->getLastArg(OPT_relocatable,
> - OPT_shared,
> - OPT_static)) {
> + if (llvm::opt::Arg *kind =
> + parsedArgs->getLastArg(OPT_relocatable, OPT_shared, OPT_static)) {
> switch (kind->getOption().getID()) {
> case OPT_relocatable:
> options->setOutputFileType(llvm::ELF::ET_REL);
> @@ -151,60 +150,76 @@ std::unique_ptr<ELFTargetInfo> GnuLdDriv
> break;
> case OPT_shared:
> options->setOutputFileType(llvm::ELF::ET_DYN);
> + options->setAllowShlibUndefines(true);
> + options->setUseShlibUndefines(false);
> break;
> case OPT_static:
> options->setOutputFileType(llvm::ELF::ET_EXEC);
> options->setIsStaticExecutable(true);
> break;
> }
> + } else {
> + options->setOutputFileType(llvm::ELF::ET_EXEC);
> + options->setIsStaticExecutable(false);
> + options->setAllowShlibUndefines(false);
> + options->setUseShlibUndefines(true);
> }
> - else {
> - options->setOutputFileType(llvm::ELF::ET_EXEC);
> - options->setIsStaticExecutable(false);
> - }
> -
> +
> // Handle --noinhibit-exec
> - if (parsedArgs->getLastArg(OPT_noinhibit_exec))
> + if (parsedArgs->getLastArg(OPT_noinhibit_exec))
> options->setAllowRemainingUndefines(true);
> -
> +
> // Handle --force-load
> if (parsedArgs->getLastArg(OPT_force_load))
> options->setForceLoadAllArchives(true);
> -
> +
> // Handle --merge-strings
> if (parsedArgs->getLastArg(OPT_merge_strings))
> options->setMergeCommonStrings(true);
> -
> +
> // Handle -t
> if (parsedArgs->getLastArg(OPT_t))
> options->setLogInputFiles(true);
> -
> +
> + // Handle --no-allow-shlib-undefined
> + if (parsedArgs->getLastArg(OPT_no_allow_shlib_undefs))
> + options->setAllowShlibUndefines(false);
> +
> + // Handle --allow-shlib-undefined
> + if (parsedArgs->getLastArg(OPT_allow_shlib_undefs))
> + options->setAllowShlibUndefines(true);
> +
> + // Handle --use-shlib-undefs
> + if (parsedArgs->getLastArg(OPT_use_shlib_undefs))
> + options->setUseShlibUndefines(true);
> +
> // Handle -Lxxx
> for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_L),
> ie = parsedArgs->filtered_end();
> - it != ie; ++it) {
> + it != ie; ++it) {
> options->appendSearchPath((*it)->getValue());
> }
> -
> +
> // Copy mllvm
> for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_mllvm),
> ie = parsedArgs->filtered_end();
> - it != ie; ++it) {
> - options->appendLLVMOption((*it)->getValue());
> + it != ie; ++it) {
> + options->appendLLVMOption((*it)->getValue());
> }
> -
> +
> // Handle input files (full paths and -lxxx)
> - for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_INPUT,OPT_l),
> - ie = parsedArgs->filtered_end();
> - it != ie; ++it) {
> + for (llvm::opt::arg_iterator
> + it = parsedArgs->filtered_begin(OPT_INPUT, OPT_l),
> + ie = parsedArgs->filtered_end();
> + it != ie; ++it) {
> switch ((*it)->getOption().getID()) {
> case OPT_INPUT:
> options->appendInputFile((*it)->getValue());
> break;
> case OPT_l:
> if (options->appendLibrary((*it)->getValue())) {
> - diagnostics << "Failed to find library for "
> - << (*it)->getValue() << "\n";
> + diagnostics << "Failed to find library for " << (*it)->getValue()
> + << "\n";
> return nullptr;
> }
> break;
> @@ -212,7 +227,7 @@ std::unique_ptr<ELFTargetInfo> GnuLdDriv
> llvm_unreachable("input option type not handled");
> }
> }
> -
> +
> // Validate the combination of options used.
> if (options->validate(diagnostics))
> return nullptr;
> @@ -220,22 +235,20 @@ std::unique_ptr<ELFTargetInfo> GnuLdDriv
> return options;
> }
>
> -
> -/// Get the default target triple based on either the program name
> +/// Get the default target triple based on either the program name
> /// (e.g. "x86-ibm-linux-lld") or the primary target llvm was configured for.
> llvm::Triple GnuLdDriver::getDefaultTarget(const char *progName) {
> SmallVector<StringRef, 4> components;
> llvm::SplitString(llvm::sys::path::stem(progName), components, "-");
> // If has enough parts to be start with a triple.
> if (components.size() >= 4) {
> - llvm::Triple triple(components[0], components[1], components[2],
> - components[3]);
> + llvm::Triple triple(components[0], components[1], components[2],
> + components[3]);
> // If first component looks like an arch.
> if (triple.getArch() != llvm::Triple::UnknownArch)
> return triple;
> }
> -
> +
> // Fallback to use whatever default triple llvm was configured for.
> return llvm::Triple(llvm::sys::getDefaultTargetTriple());
> }
> -
>
> Modified: lld/trunk/lib/Driver/LDOptions.td
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/LDOptions.td?rev=179257&r1=179256&r2=179257&view=diff
> ==============================================================================
> --- lld/trunk/lib/Driver/LDOptions.td (original)
> +++ lld/trunk/lib/Driver/LDOptions.td Wed Apr 10 21:56:30 2013
> @@ -51,6 +51,15 @@ def merge_strings : Flag<["--"], "merge-
> HelpText<"Merge common strings across mergeable sections">;
>
>
> +def no_allow_shlib_undefs : Flag<["--"], "no-allow-shlib-undefined">,
> + HelpText<"Donot allow undefined symbols from dynamic library when creating executables">;
> +
> +def allow_shlib_undefs : Flag<["--"], "allow-shlib-undefined">,
> + HelpText<"Allow undefined symbols from dynamic library when creating executables">;
> +
> +def use_shlib_undefs: Flag<["--"], "use-shlib-undefines">,
> + HelpText<"Resolve undefined symbols from dynamic libraries">;
> +
> // extensions
> def emit_yaml : Flag<["-"], "emit-yaml">,
> HelpText<"Write YAML instead of ELF">;
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/Atoms.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Atoms.h?rev=179257&r1=179256&r2=179257&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/Atoms.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/Atoms.h Wed Apr 10 21:56:30 2013
> @@ -126,17 +126,12 @@ class ELFUndefinedAtom LLVM_FINAL : publ
> typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
>
> public:
> - ELFUndefinedAtom(const ELFFile<ELFT> &file, StringRef name,
> - const Elf_Sym *symbol)
> + ELFUndefinedAtom(const File &file, StringRef name, const Elf_Sym *symbol)
> : _owningFile(file), _name(name), _symbol(symbol) {}
>
> - virtual const ELFFile<ELFT> &file() const {
> - return _owningFile;
> - }
> + virtual const File &file() const { return _owningFile; }
>
> - virtual StringRef name() const {
> - return _name;
> - }
> + virtual StringRef name() const { return _name; }
>
> // FIXME: What distinguishes a symbol in ELF that can help decide if the
> // symbol is undefined only during build and not runtime? This will make us
> @@ -149,7 +144,7 @@ public:
> }
>
> private:
> - const ELFFile<ELFT> &_owningFile;
> + const File &_owningFile;
> StringRef _name;
> const Elf_Sym *_symbol;
> };
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/DynamicFile.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/DynamicFile.h?rev=179257&r1=179256&r2=179257&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/DynamicFile.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/DynamicFile.h Wed Apr 10 21:56:30 2013
> @@ -10,6 +10,8 @@
> #ifndef LLD_READER_WRITER_ELF_DYNAMIC_FILE_H
> #define LLD_READER_WRITER_ELF_DYNAMIC_FILE_H
>
> +#include "Atoms.h"
> +
> #include "lld/Core/SharedLibraryFile.h"
> #include "lld/ReaderWriter/ELFTargetInfo.h"
>
> @@ -27,6 +29,8 @@ public:
> std::unique_ptr<DynamicFile> file(
> new DynamicFile(ti, mb->getBufferIdentifier()));
> llvm::OwningPtr<llvm::object::Binary> binaryFile;
> + bool useShlibUndefines = ti.useShlibUndefines();
> +
> if (error_code ec = createBinary(mb.release(), binaryFile))
> return ec;
>
> @@ -51,18 +55,25 @@ public:
> for (auto i = obj.begin_elf_dynamic_symbols(),
> e = obj.end_elf_dynamic_symbols();
> i != e; ++i) {
> - // Don't expose undefined or absolute symbols to export.
> - if (i->st_shndx == llvm::ELF::SHN_ABS ||
> - i->st_shndx == llvm::ELF::SHN_UNDEF)
> - continue;
> StringRef name;
> - if (error_code ec =
> - obj.getSymbolName(obj.getDynamicSymbolTableSectionHeader(), &*i,
> - name))
> + if (error_code ec = obj.getSymbolName(
> + obj.getDynamicSymbolTableSectionHeader(), &*i, name))
> return ec;
> - file->_nameToSym[name]._symbol = &*i;
>
> - // TODO: Read undefined dynamic symbols into _undefinedAtoms.
> + // TODO: Add absolute symbols
> + if (i->st_shndx == llvm::ELF::SHN_ABS)
> + continue;
> +
> + if (useShlibUndefines && (i->st_shndx == llvm::ELF::SHN_UNDEF)) {
> + // Create an undefined atom.
> + if (!name.empty()) {
> + auto *newAtom =
> + new (file->_alloc) ELFUndefinedAtom<ELFT>(*file.get(), name, &*i);
> + file->_undefinedAtoms._atoms.push_back(newAtom);
> + }
> + continue;
> + }
> + file->_nameToSym[name]._symbol = &*i;
> }
>
> return std::move(file);
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFTargetInfo.cpp?rev=179257&r1=179256&r2=179257&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/ELFTargetInfo.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/ELFTargetInfo.cpp Wed Apr 10 21:56:30 2013
> @@ -29,7 +29,8 @@ ELFTargetInfo::ELFTargetInfo(llvm::Tripl
> , _outputYAML(false)
> , _noInhibitExec(false)
> , _mergeCommonStrings(false)
> - , _runLayoutPass(true) {
> + , _runLayoutPass(true)
> + , _useShlibUndefines(false) {
> }
>
> bool ELFTargetInfo::is64Bits() const {
>
> Modified: lld/trunk/test/elf/dynamic-segorder.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/dynamic-segorder.test?rev=179257&r1=179256&r2=179257&view=diff
> ==============================================================================
> --- lld/trunk/test/elf/dynamic-segorder.test (original)
> +++ lld/trunk/test/elf/dynamic-segorder.test Wed Apr 10 21:56:30 2013
> @@ -1,5 +1,5 @@
> RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
> -RUN: %p/Inputs/shared.so-x86-64 -o %t -e main
> +RUN: %p/Inputs/shared.so-x86-64 -o %t -e main --allow-shlib-undefined
> RUN: llvm-objdump -p %t | FileCheck %s
>
> CHECK: PHDR
>
> Added: lld/trunk/test/elf/dynamic-undef.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/dynamic-undef.test?rev=179257&view=auto
> ==============================================================================
> --- lld/trunk/test/elf/dynamic-undef.test (added)
> +++ lld/trunk/test/elf/dynamic-undef.test Wed Apr 10 21:56:30 2013
> @@ -0,0 +1,27 @@
> +#
> +# This test creates a executable and tests the options that are used to
> +# to create an executable and a shared library
> +#
> +# This test will fail because there are unresolved symbols from the shared
> +# library and we are not passing --allow-shlib-undefined
> +RUN: not lld -flavor gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
> +RUN: %p/Inputs/shared.so-x86-64 -o %t -e main 2> %t1
> +RUN: FileCheck -check-prefix=EXEC %s < %t1
> +# This test will pass because of --allow-shlib-undefined
> +RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
> +RUN: %p/Inputs/shared.so-x86-64 -o %t -e main --allow-shlib-undefined
> +# Test creation of shared library, this should pass because we are using
> +# shared option and by default, dynamic library wouldnot create undefined atoms
> +# from the input shared library
> +RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
> +RUN: %p/Inputs/shared.so-x86-64 -o %t -e main -shared
> +# Test creation of shared library, this should fail because we are using
> +# shared option setting the options to use the shared library undefines to
> +# create undefined atoms from the input shared library
> +RUN: not lld -flavor gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
> +RUN: %p/Inputs/shared.so-x86-64 -o %t -e main -shared \
> +RUN: --use-shlib-undefines --no-allow-shlib-undefined 2> %t2
> +RUN: FileCheck -check-prefix=SHLIB %s < %t2
> +
> +EXEC: Undefined Symbol: {{[Ia-z.\/]+}}shared.so-x86-64 : puts
> +SHLIB: Undefined Symbol: {{[Ia-z.\/]+}}shared.so-x86-64 : puts
>
> Modified: lld/trunk/test/elf/dynamic.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/dynamic.test?rev=179257&r1=179256&r2=179257&view=diff
> ==============================================================================
> --- lld/trunk/test/elf/dynamic.test (original)
> +++ lld/trunk/test/elf/dynamic.test Wed Apr 10 21:56:30 2013
> @@ -1,7 +1,8 @@
> RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/use-shared.x86-64 \
> -RUN: %p/Inputs/shared.so-x86-64 -o %t -e main
> +RUN: %p/Inputs/shared.so-x86-64 -o %t -e main --allow-shlib-undefined
> RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/use-shared.x86-64 \
> -RUN: %p/Inputs/shared.so-x86-64 -emit-yaml -o %t2 --noinhibit-exec
> +RUN: %p/Inputs/shared.so-x86-64 -emit-yaml -o %t2 --allow-shlib-undefined \
> +RUN: --noinhibit-exec
> RUN: llvm-objdump -p %t >> %t2
> RUN: llvm-readobj -s -dyn-symbols -dynamic-table %t >> %t2
> RUN: FileCheck %s < %t2
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list