mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-06 01:19:28 +00:00
[ELF] add -u/--undefined option, to define undefined symbols
llvm-svn: 184266
This commit is contained in:
parent
9ac21aef9b
commit
53caafebdb
@ -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<StringRef> 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<const StringRef *> undefinedSymbols() const {
|
||||
return _undefinedSymbols;
|
||||
}
|
||||
|
||||
private:
|
||||
ELFTargetInfo() LLVM_DELETED_FUNCTION;
|
||||
protected:
|
||||
@ -174,12 +191,13 @@ protected:
|
||||
bool _dynamicLinkerArg;
|
||||
bool _noAllowDynamicLibraries;
|
||||
OutputMagic _outputMagic;
|
||||
std::vector<StringRef> _inputSearchPaths;
|
||||
StringRefVector _inputSearchPaths;
|
||||
llvm::BumpPtrAllocator _extraStrings;
|
||||
std::unique_ptr<Reader> _elfReader;
|
||||
std::unique_ptr<Writer> _writer;
|
||||
std::unique_ptr<Reader> _linkerScriptReader;
|
||||
StringRef _dynamicLinkerPath;
|
||||
StringRefVector _undefinedSymbols;
|
||||
};
|
||||
} // end namespace lld
|
||||
|
||||
|
@ -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();
|
||||
|
@ -72,6 +72,14 @@ def omagic_alias : Flag<["-"], "N">, Alias<omagic>;
|
||||
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<u>;
|
||||
def u_equal : Joined<["-"], "u=">, Alias<u>;
|
||||
def undefined_equal : Joined<["--"], "undefined=">, Alias<u>;
|
||||
|
||||
// extensions
|
||||
def emit_yaml : Flag<["-"], "emit-yaml">,
|
||||
HelpText<"Write YAML instead of ELF">;
|
||||
|
@ -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<ELFT>::buildDynamicSymbolTable(const File &file) {
|
||||
template<class ELFT>
|
||||
void DynamicLibraryWriter<ELFT>::addDefaultAtoms() { }
|
||||
|
||||
template <class ELFT>
|
||||
void DynamicLibraryWriter<ELFT>::addFiles(InputFiles &inputFiles) {
|
||||
this->_targetHandler.addFiles(inputFiles);
|
||||
}
|
||||
|
||||
template<class ELFT>
|
||||
void DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() {
|
||||
this->_targetHandler.finalizeSymbolValues();
|
||||
|
@ -64,10 +64,13 @@ void ExecutableWriter<ELFT>::addDefaultAtoms() {
|
||||
/// \brief Hook in lld to add CRuntime file
|
||||
template <class ELFT>
|
||||
void ExecutableWriter<ELFT>::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<ELFT>::addFiles(inputFiles);
|
||||
}
|
||||
|
||||
template <class ELFT> void ExecutableWriter<ELFT>::createDefaultSections() {
|
||||
@ -120,11 +123,14 @@ template <class ELFT> void ExecutableWriter<ELFT>::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();
|
||||
|
@ -28,6 +28,15 @@ using namespace llvm::object;
|
||||
template<class ELFT>
|
||||
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 ELFT> class LinkerInternalFile : public CRuntimeFile<ELFT> {
|
||||
public:
|
||||
LinkerInternalFile(const ELFTargetInfo &ti)
|
||||
: CRuntimeFile<ELFT>(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<ELFT>) _hashTable;
|
||||
llvm::StringSet<> _soNeeded;
|
||||
/// @}
|
||||
LinkerInternalFile<ELFT> _linkerInternalFile;
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -121,7 +131,8 @@ protected:
|
||||
//===----------------------------------------------------------------------===//
|
||||
template <class ELFT>
|
||||
OutputELFWriter<ELFT>::OutputELFWriter(const ELFTargetInfo &ti)
|
||||
: _targetInfo(ti), _targetHandler(ti.getTargetHandler<ELFT>()) {
|
||||
: _targetInfo(ti), _targetHandler(ti.getTargetHandler<ELFT>()),
|
||||
_linkerInternalFile(ti) {
|
||||
_layout = &_targetHandler.targetLayout();
|
||||
}
|
||||
|
||||
@ -223,8 +234,19 @@ void OutputELFWriter<ELFT>::assignSectionsWithNoSegments() {
|
||||
_shdrtab->updateSection(section);
|
||||
}
|
||||
|
||||
template<class ELFT>
|
||||
void OutputELFWriter<ELFT>::createDefaultSections() {
|
||||
template <class ELFT>
|
||||
void OutputELFWriter<ELFT>::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 <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
|
||||
_Header.reset(new (_alloc) Header<ELFT>(_targetInfo));
|
||||
_programHeader.reset(new (_alloc) ProgramHeader<ELFT>(_targetInfo));
|
||||
_layout->setHeader(_Header.get());
|
||||
|
BIN
lld/test/elf/X86_64/Inputs/libfn.a
Normal file
BIN
lld/test/elf/X86_64/Inputs/libfn.a
Normal file
Binary file not shown.
19
lld/test/elf/X86_64/undef.test
Normal file
19
lld/test/elf/X86_64/undef.test
Normal file
@ -0,0 +1,19 @@
|
||||
# This tests the functionality that an undefined symbol thats defined in the
|
||||
# commmand line pulls in the required object file from the archive library
|
||||
# which is usually the usecase for it
|
||||
RUN: lld -flavor gnu -target x86_64 -u fn %p/Inputs/libfn.a -o %t --noinhibit-exec
|
||||
RUN: llvm-readobj -symbols %t | FileCheck -check-prefix=SYMFROMARCHIVE %s
|
||||
RUN: lld -flavor gnu -target x86_64 %p/Inputs/libfn.a -o %t --noinhibit-exec
|
||||
RUN: llvm-readobj -symbols %t | FileCheck %s
|
||||
|
||||
SYMFROMARCHIVE: Symbol {
|
||||
SYMFROMARCHIVE: Name: fn (16)
|
||||
SYMFROMARCHIVE: Value: 0x4001A4
|
||||
SYMFROMARCHIVE: Size: 11
|
||||
SYMFROMARCHIVE: Binding: Global (0x1)
|
||||
SYMFROMARCHIVE: Type: Function (0x2)
|
||||
SYMFROMARCHIVE: Other: 0
|
||||
SYMFROMARCHIVE: Section: .text (0x5)
|
||||
SYMFROMARCHIVE: }
|
||||
|
||||
CHECK-NOT: Name: fn
|
Loading…
x
Reference in New Issue
Block a user