Index: lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h =================================================================== --- lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h +++ lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h @@ -204,27 +204,25 @@ /// Get the entry symbol name StringRef entrySymbolName() const override; - /// add to the list of initializer functions - void addInitFunction(StringRef name) { _initFunctions.push_back(name); } + /// \brief Set new initializer function + void setInitFunction(StringRef name) { _initFunction = name; } - /// add to the list of finalizer functions - void addFiniFunction(StringRef name) { _finiFunctions.push_back(name); } + /// \brief Return an initializer function name. + /// Either default "_init" or configured by the -init command line option. + StringRef initFunction() const { return _initFunction; } + + /// \brief Set new finalizer function + void setFiniFunction(StringRef name) { _finiFunction = name; } + + /// \brief Return a finalizer function name. + /// Either default "_fini" or configured by the -fini command line option. + StringRef finiFunction() const { return _finiFunction; } /// Add an absolute symbol. Used for --defsym. void addInitialAbsoluteSymbol(StringRef name, uint64_t addr) { _absoluteSymbols[name] = addr; } - /// Return the list of initializer symbols that are specified in the - /// linker command line, using the -init option. - range initFunctions() const { - return _initFunctions; - } - - /// Return the list of finalizer symbols that are specified in the - /// linker command line, using the -fini option. - range finiFunctions() const { return _finiFunctions; } - void setSharedObjectName(StringRef soname) { _soname = soname; } @@ -324,8 +322,8 @@ StringRefVector _inputSearchPaths; std::unique_ptr _writer; StringRef _dynamicLinkerPath; - StringRefVector _initFunctions; - StringRefVector _finiFunctions; + StringRef _initFunction; + StringRef _finiFunction; StringRef _sysrootPath; StringRef _soname; StringRefVector _rpathList; Index: lld/trunk/lib/Driver/GnuLdDriver.cpp =================================================================== --- lld/trunk/lib/Driver/GnuLdDriver.cpp +++ lld/trunk/lib/Driver/GnuLdDriver.cpp @@ -428,11 +428,11 @@ break; case OPT_init: - ctx->addInitFunction(inputArg->getValue()); + ctx->setInitFunction(inputArg->getValue()); break; case OPT_fini: - ctx->addFiniFunction(inputArg->getValue()); + ctx->setFiniFunction(inputArg->getValue()); break; case OPT_output_filetype: Index: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h +++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h @@ -92,9 +92,6 @@ return false; } } - - /// \brief Create Internal files for Init/Fini - void createInternalFiles(std::vector> &) const override; }; } // end namespace elf } // end namespace lld Index: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp +++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp @@ -9,85 +9,8 @@ #include "AArch64LinkingContext.h" #include "AArch64RelocationPass.h" -#include "Atoms.h" -#include "lld/Core/File.h" -#include "lld/Core/Instrumentation.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringSwitch.h" using namespace lld; -using namespace lld::elf; - -using llvm::makeArrayRef; - -namespace { -using namespace llvm::ELF; - -const uint8_t AArch64InitFiniAtomContent[8] = {0}; - -// AArch64InitFini Atom -class AArch64InitAtom : public InitFiniAtom { -public: - AArch64InitAtom(const File &f, StringRef function) - : InitFiniAtom(f, ".init_array") { -#ifndef NDEBUG - _name = "__init_fn_"; - _name += function; -#endif - } - ArrayRef rawContent() const override { - return makeArrayRef(AArch64InitFiniAtomContent); - } - Alignment alignment() const override { return Alignment(3); } -}; - -class AArch64FiniAtom : public InitFiniAtom { -public: - AArch64FiniAtom(const File &f, StringRef function) - : InitFiniAtom(f, ".fini_array") { -#ifndef NDEBUG - _name = "__fini_fn_"; - _name += function; -#endif - } - ArrayRef rawContent() const override { - return makeArrayRef(AArch64InitFiniAtomContent); - } - - Alignment alignment() const override { return Alignment(3); } -}; - -class AArch64InitFiniFile : public SimpleFile { -public: - AArch64InitFiniFile(const ELFLinkingContext &context) - : SimpleFile("command line option -init/-fini"), _ordinal(0) {} - - void addInitFunction(StringRef name) { - Atom *initFunctionAtom = new (_allocator) SimpleUndefinedAtom(*this, name); - AArch64InitAtom *initAtom = (new (_allocator) AArch64InitAtom(*this, name)); - initAtom->addReferenceELF_AArch64(llvm::ELF::R_AARCH64_ABS64, 0, - initFunctionAtom, 0); - initAtom->setOrdinal(_ordinal++); - addAtom(*initFunctionAtom); - addAtom(*initAtom); - } - - void addFiniFunction(StringRef name) { - Atom *finiFunctionAtom = new (_allocator) SimpleUndefinedAtom(*this, name); - AArch64FiniAtom *finiAtom = (new (_allocator) AArch64FiniAtom(*this, name)); - finiAtom->addReferenceELF_AArch64(llvm::ELF::R_AARCH64_ABS64, 0, - finiFunctionAtom, 0); - finiAtom->setOrdinal(_ordinal++); - addAtom(*finiFunctionAtom); - addAtom(*finiAtom); - } - -private: - llvm::BumpPtrAllocator _allocator; - uint64_t _ordinal; -}; - -} // end anon namespace void elf::AArch64LinkingContext::addPasses(PassManager &pm) { auto pass = createAArch64RelocationPass(*this); @@ -95,15 +18,3 @@ pm.add(std::move(pass)); ELFLinkingContext::addPasses(pm); } - -void elf::AArch64LinkingContext::createInternalFiles( - std::vector> &result) const { - ELFLinkingContext::createInternalFiles(result); - std::unique_ptr initFiniFile( - new AArch64InitFiniFile(*this)); - for (auto ai : initFunctions()) - initFiniFile->addInitFunction(ai); - for (auto ai : finiFunctions()) - initFiniFile->addFiniFunction(ai); - result.push_back(std::move(initFiniFile)); -} Index: lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp +++ lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp @@ -63,7 +63,7 @@ _useShlibUndefines(true), _dynamicLinkerArg(false), _noAllowDynamicLibraries(false), _mergeRODataToTextSegment(true), _demangle(true), _alignSegments(true), _outputMagic(OutputMagic::DEFAULT), - _sysrootPath("") {} + _initFunction("_init"), _finiFunction("_fini"), _sysrootPath("") {} void ELFLinkingContext::addPasses(PassManager &pm) { if (_runLayoutPass) Index: lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h +++ lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h @@ -61,10 +61,6 @@ return false; } } - - /// \brief Create Internal files for Init/Fini - void createInternalFiles( - std::vector> &result) const override; }; } // elf Index: lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp +++ lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp @@ -7,100 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "Atoms.h" #include "HexagonLinkingContext.h" #include "HexagonTargetHandler.h" -#include "lld/Core/File.h" -#include "lld/Core/Pass.h" -#include "lld/Core/PassManager.h" -#include "lld/Core/Simple.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringSwitch.h" -using namespace lld; using namespace lld::elf; -namespace { - -const uint8_t hexagonInitFiniAtomContent[4] = { 0 }; - -// HexagonInitFini Atom -class HexagonInitAtom : public InitFiniAtom { -public: - HexagonInitAtom(const File &f, StringRef function) - : InitFiniAtom(f, ".init_array") { -#ifndef NDEBUG - _name = "__init_fn_"; - _name += function; -#endif - } - ArrayRef rawContent() const override { - return ArrayRef(hexagonInitFiniAtomContent, 4); - } - - Alignment alignment() const override { return Alignment(2); } -}; - -class HexagonFiniAtom : public InitFiniAtom { -public: - HexagonFiniAtom(const File &f, StringRef function) - : InitFiniAtom(f, ".fini_array") { -#ifndef NDEBUG - _name = "__fini_fn_"; - _name += function; -#endif - } - ArrayRef rawContent() const override { - return ArrayRef(hexagonInitFiniAtomContent, 4); - } - Alignment alignment() const override { return Alignment(2); } -}; - -class HexagonInitFiniFile : public SimpleFile { -public: - HexagonInitFiniFile(const ELFLinkingContext &context) - : SimpleFile("command line option -init/-fini"), _ordinal(0) {} - - void addInitFunction(StringRef name) { - Atom *initFuncAtom = new (_allocator) SimpleUndefinedAtom(*this, name); - HexagonInitAtom *initAtom = - (new (_allocator) HexagonInitAtom(*this, name)); - initAtom->addReferenceELF_Hexagon(llvm::ELF::R_HEX_32, 0, initFuncAtom, 0); - initAtom->setOrdinal(_ordinal++); - addAtom(*initFuncAtom); - addAtom(*initAtom); - } - - void addFiniFunction(StringRef name) { - Atom *finiFunctionAtom = new (_allocator) SimpleUndefinedAtom(*this, name); - HexagonFiniAtom *finiAtom = - (new (_allocator) HexagonFiniAtom(*this, name)); - finiAtom->addReferenceELF_Hexagon(llvm::ELF::R_HEX_32, 0, finiFunctionAtom, - 0); - finiAtom->setOrdinal(_ordinal++); - addAtom(*finiFunctionAtom); - addAtom(*finiAtom); - } - -private: - llvm::BumpPtrAllocator _allocator; - uint64_t _ordinal; -}; -} - -void elf::HexagonLinkingContext::createInternalFiles( - std::vector > &result) const { - ELFLinkingContext::createInternalFiles(result); - std::unique_ptr initFiniFile( - new HexagonInitFiniFile(*this)); - for (auto ai : initFunctions()) - initFiniFile->addInitFunction(ai); - for (auto ai:finiFunctions()) - initFiniFile->addFiniFunction(ai); - result.push_back(std::move(initFiniFile)); -} - HexagonLinkingContext::HexagonLinkingContext(llvm::Triple triple) : ELFLinkingContext(triple, std::unique_ptr( new HexagonTargetHandler(*this))) {} Index: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h +++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h @@ -1134,6 +1134,14 @@ dyn.d_tag = DT_FINI_ARRAYSZ; _dt_fini_arraysz = addEntry(dyn); } + if (getInitAtomLayout()) { + dyn.d_tag = DT_INIT; + _dt_init = addEntry(dyn); + } + if (getFiniAtomLayout()) { + dyn.d_tag = DT_FINI; + _dt_fini = addEntry(dyn); + } } /// \brief Dynamic table tag for .got.plt section referencing. @@ -1179,6 +1187,10 @@ _entries[_dt_fini_array].d_un.d_val = finiArray->virtualAddr(); _entries[_dt_fini_arraysz].d_un.d_val = finiArray->memSize(); } + if (const auto *al = getInitAtomLayout()) + _entries[_dt_init].d_un.d_val = al->_virtualAddr; + if (const auto *al = getFiniAtomLayout()) + _entries[_dt_fini].d_un.d_val = al->_virtualAddr; if (_layout.hasDynamicRelocationTable()) { auto relaTbl = _layout.getDynamicRelocationTable(); _entries[_dt_rela].d_un.d_val = relaTbl->virtualAddr(); @@ -1215,9 +1227,25 @@ std::size_t _dt_fini_array; std::size_t _dt_fini_arraysz; std::size_t _dt_textrel; + std::size_t _dt_init; + std::size_t _dt_fini; TargetLayout &_layout; DynamicSymbolTable *_dynamicSymbolTable; HashSection *_hashTable; + + const AtomLayout *getInitAtomLayout() { + auto al = _layout.findAtomLayoutByName(this->_context.initFunction()); + if (al && isa(al->_atom)) + return al; + return nullptr; + } + + const AtomLayout *getFiniAtomLayout() { + auto al = _layout.findAtomLayoutByName(this->_context.finiFunction()); + if (al && isa(al->_atom)) + return al; + return nullptr; + } }; template class InterpSection : public Section { Index: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h +++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h @@ -94,9 +94,6 @@ return false; } } - - /// \brief Create Internal files for Init/Fini - void createInternalFiles(std::vector> &) const override; }; } // end namespace elf } // end namespace lld Index: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp +++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp @@ -8,88 +8,9 @@ //===----------------------------------------------------------------------===// #include "X86_64LinkingContext.h" -#include "Atoms.h" #include "X86_64RelocationPass.h" -#include "lld/Core/File.h" -#include "lld/Core/Instrumentation.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringSwitch.h" using namespace lld; -using namespace lld::elf; - -using llvm::makeArrayRef; - -namespace { -using namespace llvm::ELF; - -const uint8_t x86_64InitFiniAtomContent[8] = { 0 }; - -// X86_64InitFini Atom -class X86_64InitAtom : public InitFiniAtom { -public: - X86_64InitAtom(const File &f, StringRef function) - : InitFiniAtom(f, ".init_array") { -#ifndef NDEBUG - _name = "__init_fn_"; - _name += function; -#endif - } - ArrayRef rawContent() const override { - return makeArrayRef(x86_64InitFiniAtomContent); - } - Alignment alignment() const override { return Alignment(3); } -}; - -class X86_64FiniAtom : public InitFiniAtom { -public: - X86_64FiniAtom(const File &f, StringRef function) - : InitFiniAtom(f, ".fini_array") { -#ifndef NDEBUG - _name = "__fini_fn_"; - _name += function; -#endif - } - ArrayRef rawContent() const override { - return makeArrayRef(x86_64InitFiniAtomContent); - } - - Alignment alignment() const override { return Alignment(3); } -}; - -class X86_64InitFiniFile : public SimpleFile { -public: - X86_64InitFiniFile(const ELFLinkingContext &context) - : SimpleFile("command line option -init/-fini"), _ordinal(0) {} - - void addInitFunction(StringRef name) { - Atom *initFunctionAtom = new (_allocator) SimpleUndefinedAtom(*this, name); - X86_64InitAtom *initAtom = - (new (_allocator) X86_64InitAtom(*this, name)); - initAtom->addReferenceELF_x86_64(llvm::ELF::R_X86_64_64, 0, - initFunctionAtom, 0); - initAtom->setOrdinal(_ordinal++); - addAtom(*initFunctionAtom); - addAtom(*initAtom); - } - - void addFiniFunction(StringRef name) { - Atom *finiFunctionAtom = new (_allocator) SimpleUndefinedAtom(*this, name); - X86_64FiniAtom *finiAtom = - (new (_allocator) X86_64FiniAtom(*this, name)); - finiAtom->addReferenceELF_x86_64(llvm::ELF::R_X86_64_64, 0, - finiFunctionAtom, 0); - finiAtom->setOrdinal(_ordinal++); - addAtom(*finiFunctionAtom); - addAtom(*finiAtom); - } - -private: - llvm::BumpPtrAllocator _allocator; - uint64_t _ordinal; -}; - -} // end anon namespace void elf::X86_64LinkingContext::addPasses(PassManager &pm) { auto pass = createX86_64RelocationPass(*this); @@ -97,16 +18,3 @@ pm.add(std::move(pass)); ELFLinkingContext::addPasses(pm); } - -void elf::X86_64LinkingContext::createInternalFiles( - std::vector > &result) const { - ELFLinkingContext::createInternalFiles(result); - std::unique_ptr initFiniFile( - new X86_64InitFiniFile(*this)); - for (auto ai : initFunctions()) - initFiniFile->addInitFunction(ai); - for (auto ai:finiFunctions()) - initFiniFile->addFiniFunction(ai); - result.push_back(std::move(initFiniFile)); -} - Index: lld/trunk/test/elf/AArch64/initfini-alignment.test =================================================================== --- lld/trunk/test/elf/AArch64/initfini-alignment.test +++ lld/trunk/test/elf/AArch64/initfini-alignment.test @@ -1,12 +0,0 @@ -# This tests the functionality that lld is able to create -# init_array/fini_array sections in the output ELF with the -# right alignment - -RUN: lld -flavor gnu -target aarch64--linux-gnu %p/Inputs/initfini-option.o \ -RUN: -init init -fini fini --noinhibit-exec -o %t -RUN: llvm-readobj -s %t | FileCheck %s - -CHECK: Name: .init_array -CHECK: AddressAlignment: 8 -CHECK: Name: .fini_array -CHECK: AddressAlignment: 8 Index: lld/trunk/test/elf/AArch64/initfini-option.test =================================================================== --- lld/trunk/test/elf/AArch64/initfini-option.test +++ lld/trunk/test/elf/AArch64/initfini-option.test @@ -1,21 +0,0 @@ -# This tests the functionality that lld is able to create -# init_array/fini_array sections in the output ELF. This -# corresponds to the the .init_array/.fini_array sections -# in the output ELF. - -RUN: lld -flavor gnu -target aarch64--linux-gnu %p/Inputs/initfini-option.o \ -RUN: -init init -fini fini --noinhibit-exec --output-filetype=yaml -static -o %t -RUN: FileCheck %s < %t - -CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ] -CHECK: section-name: .init_array -CHECK: references: -CHECK: - kind: R_AARCH64_ABS64 -CHECK: offset: 0 -CHECK: target: init -CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ] -CHECK: section-name: .fini_array -CHECK: references: -CHECK: - kind: R_AARCH64_ABS64 -CHECK: offset: 0 -CHECK: target: fini Index: lld/trunk/test/elf/Hexagon/Inputs/initfini-option.c =================================================================== --- lld/trunk/test/elf/Hexagon/Inputs/initfini-option.c +++ lld/trunk/test/elf/Hexagon/Inputs/initfini-option.c @@ -1,13 +0,0 @@ -#include - -void init() { - printf("%s\n", __FUNCTION__); -} - -void fini() { - printf("%s\n", __FUNCTION__); -} - -int main() { -} - Index: lld/trunk/test/elf/Hexagon/initfini-option.test =================================================================== --- lld/trunk/test/elf/Hexagon/initfini-option.test +++ lld/trunk/test/elf/Hexagon/initfini-option.test @@ -1,21 +0,0 @@ -# This tests the functionality that lld is able to create -# init_array/fini_array sections in the output ELF. This -# corresponds to the the .init_array/.fini_array sections -# in the output ELF. - -RUN: lld -flavor gnu -target hexagon %p/Inputs/initfini-option.o \ -RUN: -init init -fini fini --noinhibit-exec --output-filetype=yaml -static -o %t -RUN: FileCheck %s < %t - -CHECK: content: [ 00, 00, 00, 00 ] -CHECK: section-name: .init_array -CHECK: references: -CHECK: - kind: R_HEX_32 -CHECK: offset: 0 -CHECK: target: init -CHECK: content: [ 00, 00, 00, 00 ] -CHECK: section-name: .fini_array -CHECK: references: -CHECK: - kind: R_HEX_32 -CHECK: offset: 0 -CHECK: target: fini Index: lld/trunk/test/elf/X86_64/initfini-alignment.test =================================================================== --- lld/trunk/test/elf/X86_64/initfini-alignment.test +++ lld/trunk/test/elf/X86_64/initfini-alignment.test @@ -1,12 +0,0 @@ -# This tests the functionality that lld is able to create -# init_array/fini_array sections in the output ELF with the -# right alignment - -RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/initfini-option.o \ -RUN: -init init -fini fini --noinhibit-exec -o %t -RUN: llvm-readobj -s %t | FileCheck %s - -CHECK: Name: .init_array -CHECK: AddressAlignment: 8 -CHECK: Name: .fini_array -CHECK: AddressAlignment: 8 Index: lld/trunk/test/elf/X86_64/initfini-option.test =================================================================== --- lld/trunk/test/elf/X86_64/initfini-option.test +++ lld/trunk/test/elf/X86_64/initfini-option.test @@ -1,21 +0,0 @@ -# This tests the functionality that lld is able to create -# init_array/fini_array sections in the output ELF. This -# corresponds to the the .init_array/.fini_array sections -# in the output ELF. - -RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/initfini-option.o \ -RUN: -init init -fini fini --noinhibit-exec --output-filetype=yaml -o %t -RUN: FileCheck %s < %t - -CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ] -CHECK: section-name: .init_array -CHECK: references: -CHECK: - kind: R_X86_64_64 -CHECK: offset: 0 -CHECK: target: init -CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ] -CHECK: section-name: .fini_array -CHECK: references: -CHECK: - kind: R_X86_64_64 -CHECK: offset: 0 -CHECK: target: fini Index: lld/trunk/test/elf/initfini-options.test-1.test =================================================================== --- lld/trunk/test/elf/initfini-options.test-1.test +++ lld/trunk/test/elf/initfini-options.test-1.test @@ -0,0 +1,33 @@ +# Check that if there are no -init/-fini options and _init/_fini symbols +# are undefined the linker does not emit DT_INIT/DT_FINI tags. + +# RUN: yaml2obj -format=elf %s > %t.o +# RUN: lld -flavor gnu -target x86_64 -shared --noinhibit-exec -o %t.so %t.o +# RUN: llvm-readobj -dynamic-table %t.so | FileCheck %s + +# CHECK-NOT: 0x000000000000000C INIT 0x{{[0-9A-F]+}} +# CHECK-NOT: 0x000000000000000D FINI 0x{{[0-9A-F]+}} + +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x04 + Size: 0x08 + +Symbols: + Global: + - Name: _start + Type: STT_FUNC + Section: .text + Size: 0x08 + - Name: _init + - Name: _fini +... Index: lld/trunk/test/elf/initfini-options.test-2.test =================================================================== --- lld/trunk/test/elf/initfini-options.test-2.test +++ lld/trunk/test/elf/initfini-options.test-2.test @@ -0,0 +1,47 @@ +# Check that if _init/_fini symbols are defined the linker emits +# DT_INIT/DT_FINI tags point to these symbols. + +# RUN: yaml2obj -format=elf %s > %t.o +# RUN: lld -flavor gnu -target x86_64 -shared -o %t.so %t.o +# RUN: llvm-readobj -symbols -dynamic-table %t.so | FileCheck %s + +# CHECK: Name: _init (8) +# CHECK-NEXT: Value: 0x4001E4 +# CHECK: Name: _fini (14) +# CHECK-NEXT: Value: 0x4001EB +# +# CHECK: 0x000000000000000C INIT 0x4001E4 +# CHECK: 0x000000000000000D FINI 0x4001EB + +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x04 + Size: 0x18 + +Symbols: + Global: + - Name: _start + Type: STT_FUNC + Section: .text + Value: 0x0 + Size: 0x8 + - Name: _init + Type: STT_FUNC + Section: .text + Value: 0x8 + Size: 0x8 + - Name: _fini + Type: STT_FUNC + Section: .text + Value: 0xF + Size: 0x8 +... Index: lld/trunk/test/elf/initfini-options.test-3.test =================================================================== --- lld/trunk/test/elf/initfini-options.test-3.test +++ lld/trunk/test/elf/initfini-options.test-3.test @@ -0,0 +1,53 @@ +# Check that -init/-fini command line options override default function names +# and the linker uses these name to search symbols and setup DT_INIT/DT_FINI. + +# RUN: yaml2obj -format=elf %s > %t.o +# RUN: lld -flavor gnu -target x86_64 -shared -o %t.so %t.o \ +# RUN: -init _init -init _start -fini _fini -fini _stop +# RUN: llvm-readobj -symbols -dynamic-table %t.so | FileCheck %s + +# CHECK: Name: _start (1) +# CHECK-NEXT: Value: 0x4001FC +# CHECK: Name: _stop (8) +# CHECK-NEXT: Value: 0x400204 +# +# CHECK: 0x000000000000000C INIT 0x4001FC +# CHECK: 0x000000000000000D FINI 0x400204 + +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x04 + Size: 0x20 + +Symbols: + Global: + - Name: _start + Type: STT_FUNC + Section: .text + Value: 0x0 + Size: 0x8 + - Name: _stop + Type: STT_FUNC + Section: .text + Value: 0x8 + Size: 0x8 + - Name: _init + Type: STT_FUNC + Section: .text + Value: 0xF + Size: 0x8 + - Name: _fini + Type: STT_FUNC + Section: .text + Value: 0x18 + Size: 0x8 +... Index: lld/trunk/unittests/DriverTests/GnuLdDriverTest.cpp =================================================================== --- lld/trunk/unittests/DriverTests/GnuLdDriverTest.cpp +++ lld/trunk/unittests/DriverTests/GnuLdDriverTest.cpp @@ -80,16 +80,13 @@ TEST_F(GnuLdParserTest, Init) { EXPECT_TRUE(parse("ld", "--start-group", "--end-group", "-init", "foo", "-init", "bar", nullptr)); - EXPECT_EQ(2, _context->initFunctions().size()); - EXPECT_EQ("foo", _context->initFunctions()[0]); - EXPECT_EQ("bar", _context->initFunctions()[1]); + EXPECT_EQ("bar", _context->initFunction()); } TEST_F(GnuLdParserTest, InitJoined) { EXPECT_TRUE(parse("ld", "--start-group", "--end-group", "-init=foo", nullptr)); - EXPECT_EQ(1, _context->initFunctions().size()); - EXPECT_EQ("foo", _context->initFunctions()[0]); + EXPECT_EQ("foo", _context->initFunction()); } // --soname