From 53caafebdb47f04ffbd7bde4f8d259d588a24542 Mon Sep 17 00:00:00 2001 From: Shankar Easwaran Date: Wed, 19 Jun 2013 00:31:09 +0000 Subject: [PATCH] [ELF] add -u/--undefined option, to define undefined symbols llvm-svn: 184266 --- lld/include/lld/ReaderWriter/ELFTargetInfo.h | 20 +++++++++++- lld/lib/Driver/GnuLdDriver.cpp | 7 ++++ lld/lib/Driver/LDOptions.td | 8 +++++ .../ReaderWriter/ELF/DynamicLibraryWriter.h | 6 ---- lld/lib/ReaderWriter/ELF/ExecutableWriter.h | 20 ++++++++---- lld/lib/ReaderWriter/ELF/OutputELFWriter.h | 30 +++++++++++++++--- lld/test/elf/X86_64/Inputs/libfn.a | Bin 0 -> 1364 bytes lld/test/elf/X86_64/undef.test | 19 +++++++++++ 8 files changed, 92 insertions(+), 18 deletions(-) create mode 100644 lld/test/elf/X86_64/Inputs/libfn.a create mode 100644 lld/test/elf/X86_64/undef.test diff --git a/lld/include/lld/ReaderWriter/ELFTargetInfo.h b/lld/include/lld/ReaderWriter/ELFTargetInfo.h index af8e00df1183..b8f7da89fe9d 100644 --- a/lld/include/lld/ReaderWriter/ELFTargetInfo.h +++ b/lld/include/lld/ReaderWriter/ELFTargetInfo.h @@ -12,6 +12,7 @@ #include "lld/Core/PassManager.h" #include "lld/Core/Pass.h" +#include "lld/Core/range.h" #include "lld/Core/TargetInfo.h" #include "lld/ReaderWriter/Reader.h" #include "lld/ReaderWriter/Writer.h" @@ -154,6 +155,22 @@ public: /// Searches directories then calls appendInputFile() bool appendLibrary(StringRef libName); + /// adds undefined symbols that are specified in the command line + void addUndefinedSymbol(StringRef symbolName) { + _undefinedSymbols.push_back(symbolName); + } + + /// Iterators for symbols that appear on the command line + typedef std::vector StringRefVector; + typedef StringRefVector::iterator StringRefVectorIter; + typedef StringRefVector::const_iterator StringRefVectorConstIter; + + /// Return the list of undefined symbols that are specified in the + /// linker command line, using the -u option. + range undefinedSymbols() const { + return _undefinedSymbols; + } + private: ELFTargetInfo() LLVM_DELETED_FUNCTION; protected: @@ -174,12 +191,13 @@ protected: bool _dynamicLinkerArg; bool _noAllowDynamicLibraries; OutputMagic _outputMagic; - std::vector _inputSearchPaths; + StringRefVector _inputSearchPaths; llvm::BumpPtrAllocator _extraStrings; std::unique_ptr _elfReader; std::unique_ptr _writer; std::unique_ptr _linkerScriptReader; StringRef _dynamicLinkerPath; + StringRefVector _undefinedSymbols; }; } // end namespace lld diff --git a/lld/lib/Driver/GnuLdDriver.cpp b/lld/lib/Driver/GnuLdDriver.cpp index 57ee99b0fc20..0f8df29fc603 100644 --- a/lld/lib/Driver/GnuLdDriver.cpp +++ b/lld/lib/Driver/GnuLdDriver.cpp @@ -217,6 +217,13 @@ GnuLdDriver::parse(int argc, const char *argv[], raw_ostream &diagnostics) { if (!options->allowLinkWithDynamicLibraries()) options->setIsStaticExecutable(true); + // Handle -u, --undefined option + for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_u), + ie = parsedArgs->filtered_end(); + it != ie; ++it) { + options->addUndefinedSymbol((*it)->getValue()); + } + // Handle -Lxxx for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_L), ie = parsedArgs->filtered_end(); diff --git a/lld/lib/Driver/LDOptions.td b/lld/lib/Driver/LDOptions.td index ef605aed55f6..e941d547c9b1 100644 --- a/lld/lib/Driver/LDOptions.td +++ b/lld/lib/Driver/LDOptions.td @@ -72,6 +72,14 @@ def omagic_alias : Flag<["-"], "N">, Alias; def no_omagic : Flag<["--"], "no-omagic">, HelpText<"This option negates most of the effects of the -N option. Disable linking with shared libraries">; +// TODO: remove the options with the = sign, once the change in the OptionParser +// is done to recognize the allowed suffixes for an argument. +def u : Separate<["-"], "u">, + HelpText<"Force symbol to be entered in the output file as an undefined symbol">; +def undefined : Separate<["--"], "undefined">, Alias; +def u_equal : Joined<["-"], "u=">, Alias; +def undefined_equal : Joined<["--"], "undefined=">, Alias; + // extensions def emit_yaml : Flag<["-"], "emit-yaml">, HelpText<"Write YAML instead of ELF">; diff --git a/lld/lib/ReaderWriter/ELF/DynamicLibraryWriter.h b/lld/lib/ReaderWriter/ELF/DynamicLibraryWriter.h index ef084d4c735c..4eda0adc3c43 100644 --- a/lld/lib/ReaderWriter/ELF/DynamicLibraryWriter.h +++ b/lld/lib/ReaderWriter/ELF/DynamicLibraryWriter.h @@ -31,7 +31,6 @@ public: private: void buildDynamicSymbolTable(const File &file); void addDefaultAtoms(); - void addFiles(InputFiles&); void finalizeDefaultAtomValues(); llvm::BumpPtrAllocator _alloc; @@ -63,11 +62,6 @@ void DynamicLibraryWriter::buildDynamicSymbolTable(const File &file) { template void DynamicLibraryWriter::addDefaultAtoms() { } -template -void DynamicLibraryWriter::addFiles(InputFiles &inputFiles) { - this->_targetHandler.addFiles(inputFiles); -} - template void DynamicLibraryWriter::finalizeDefaultAtomValues() { this->_targetHandler.finalizeSymbolValues(); diff --git a/lld/lib/ReaderWriter/ELF/ExecutableWriter.h b/lld/lib/ReaderWriter/ELF/ExecutableWriter.h index 735627c34dcf..de688c6280e8 100644 --- a/lld/lib/ReaderWriter/ELF/ExecutableWriter.h +++ b/lld/lib/ReaderWriter/ELF/ExecutableWriter.h @@ -64,10 +64,13 @@ void ExecutableWriter::addDefaultAtoms() { /// \brief Hook in lld to add CRuntime file template void ExecutableWriter::addFiles(InputFiles &inputFiles) { + // Add the default atoms as defined by executables addDefaultAtoms(); + // Add the runtime file inputFiles.prependFile(_runtimeFile); - // Give a chance for the target to add atoms - this->_targetHandler.addFiles(inputFiles); + // Add the Linker internal file for symbols that are defined by + // command line options + OutputELFWriter::addFiles(inputFiles); } template void ExecutableWriter::createDefaultSections() { @@ -120,11 +123,14 @@ template void ExecutableWriter::finalizeDefaultAtomValues() { auto bssSection = this->_layout->findOutputSection(".bss"); - (*bssStartAtomIter)->_virtualAddr = bssSection->virtualAddr(); - (*bssEndAtomIter)->_virtualAddr = - bssSection->virtualAddr() + bssSection->memSize(); - (*underScoreEndAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr; - (*endAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr; + // If we dont find a bss section, then dont set these values + if (bssSection) { + (*bssStartAtomIter)->_virtualAddr = bssSection->virtualAddr(); + (*bssEndAtomIter)->_virtualAddr = + bssSection->virtualAddr() + bssSection->memSize(); + (*underScoreEndAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr; + (*endAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr; + } // Give a chance for the target to finalize its atom values this->_targetHandler.finalizeSymbolValues(); diff --git a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h index 32bc12c9e7b5..90788f4274fa 100644 --- a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h +++ b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h @@ -28,6 +28,15 @@ using namespace llvm::object; template class OutputELFWriter; +/// \brief This acts as a internal file that the linker uses to add +/// undefined symbols that are defined by using the linker options such +/// as -u, or --defsym option. +template class LinkerInternalFile : public CRuntimeFile { +public: + LinkerInternalFile(const ELFTargetInfo &ti) + : CRuntimeFile(ti, "Linker Internal File") {}; +}; + //===----------------------------------------------------------------------===// // OutputELFWriter Class //===----------------------------------------------------------------------===// @@ -78,7 +87,7 @@ protected: virtual void addDefaultAtoms() = 0; // Add any runtime files and their atoms to the output - virtual void addFiles(InputFiles&) = 0; + virtual void addFiles(InputFiles &); // Finalize the default atom values virtual void finalizeDefaultAtomValues() = 0; @@ -114,6 +123,7 @@ protected: LLD_UNIQUE_BUMP_PTR(HashSection) _hashTable; llvm::StringSet<> _soNeeded; /// @} + LinkerInternalFile _linkerInternalFile; }; //===----------------------------------------------------------------------===// @@ -121,7 +131,8 @@ protected: //===----------------------------------------------------------------------===// template OutputELFWriter::OutputELFWriter(const ELFTargetInfo &ti) - : _targetInfo(ti), _targetHandler(ti.getTargetHandler()) { + : _targetInfo(ti), _targetHandler(ti.getTargetHandler()), + _linkerInternalFile(ti) { _layout = &_targetHandler.targetLayout(); } @@ -223,8 +234,19 @@ void OutputELFWriter::assignSectionsWithNoSegments() { _shdrtab->updateSection(section); } -template -void OutputELFWriter::createDefaultSections() { +template +void OutputELFWriter::addFiles(InputFiles &inputFiles) { + // Add all input Files that are defined by the target + _targetHandler.addFiles(inputFiles); + // Add all symbols that are specified by the -u option + // as part of the command line argument to lld + for (auto ai : _targetInfo.undefinedSymbols()) + _linkerInternalFile.addUndefinedAtom(ai); + // Make the linker internal file to be the first file + inputFiles.prependFile(_linkerInternalFile); +} + +template void OutputELFWriter::createDefaultSections() { _Header.reset(new (_alloc) Header(_targetInfo)); _programHeader.reset(new (_alloc) ProgramHeader(_targetInfo)); _layout->setHeader(_Header.get()); diff --git a/lld/test/elf/X86_64/Inputs/libfn.a b/lld/test/elf/X86_64/Inputs/libfn.a new file mode 100644 index 0000000000000000000000000000000000000000..380844b0838da463178e84692cd1660c59dea6d0 GIT binary patch literal 1364 zcmbtU%}(1u5FRHK(m*Rf94f(KIRPpxwv&*gLMSNWM<_y7MUE9X#!(Q&ksL>aUV5w4 zTOWZ(;K-c|kH8D?06YQA*t=nHa-t*c&dfJE-;DRii?*mR3fkflaPV>{@=%2@_*g|>{YAZ#B#mS^TXbH?aX(Aj>yZRwAU=_ zqUWBS=2l`KU@qdokNEWijQ+GSKQ)p0hcy-ur$I7F)Ar}-KdI`c@m*X%zU*GLL#Kf{ z3}W5VR_OIZkf%=QfNXTTAl**8?fHoLozRnehxN5?=(y(~1Mk9-UhB9SIBkzu|6Asf zfwpKo!BkOx^erql#%wYdaZrAm940kpb2FL0ghAS$_vWu+F4Z@2aMAU@au97=OQLmw z*-=1Em)v2t&ePBV8ib`Zpmbm9QUZ_e0>gIDPVNbXZxr}Nt^J6a&PeBLd