Index: lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h =================================================================== --- lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h +++ lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h @@ -97,6 +97,12 @@ OMAGIC, }; + /// \brief ELF DT_FLAGS. + enum DTFlag : uint32_t { + DT_NOW = 1 << 1, + DT_ORIGIN = 1 << 2, + }; + llvm::Triple getTriple() const { return _triple; } uint64_t getPageSize() const { return _maxPageSize; } @@ -329,6 +335,10 @@ // --wrap option. void addWrapForSymbol(StringRef sym) { _wrapCalls.insert(sym); } + // \brief Set DT_FLAGS flag. + void setDTFlag(DTFlag f) { _dtFlags |= f; }; + bool getDTFlag(DTFlag f) { return (_dtFlags & f); }; + const llvm::StringSet<> &wrapCalls() const { return _wrapCalls; } void setUndefinesResolver(std::unique_ptr resolver); @@ -383,6 +393,7 @@ bool _armTarget1Rel = false; bool _mipsPcRelEhRel = false; uint64_t _maxPageSize = 0x1000; + uint32_t _dtFlags = 0; OutputMagic _outputMagic = OutputMagic::DEFAULT; StringRefVector _inputSearchPaths; Index: lld/trunk/lib/Driver/GnuLdDriver.cpp =================================================================== --- lld/trunk/lib/Driver/GnuLdDriver.cpp +++ lld/trunk/lib/Driver/GnuLdDriver.cpp @@ -584,9 +584,13 @@ for (auto *arg : parsedArgs->filtered(OPT_z)) { StringRef opt = arg->getValue(); - if (opt == "muldefs") { + if (opt == "muldefs") ctx->setAllowDuplicates(true); - } else if (opt.startswith("max-page-size")) { + else if (opt == "now") + ctx->setDTFlag(ELFLinkingContext::DTFlag::DT_NOW); + else if (opt == "origin") + ctx->setDTFlag(ELFLinkingContext::DTFlag::DT_ORIGIN); + else if (opt.startswith("max-page-size")) { // Parse -z max-page-size option. // The default page size is considered the minimum page size the user // can set, check the user input if its atleast the minimum page size Index: lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.cpp =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.cpp +++ lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.cpp @@ -140,6 +140,21 @@ if (!soname.empty() && _ctx.getOutputELFType() == llvm::ELF::ET_DYN) _dynamicTable->addEntry(DT_SONAME, _dynamicStringTable->addString(soname)); + // Add DT_FLAGS/DT_FLAGS_1 entries if necessary. + uint32_t dtflags = 0, dt1flags = 0; + if (_ctx.getDTFlag(ELFLinkingContext::DTFlag::DT_NOW)) { + dtflags |= DF_BIND_NOW; + dt1flags |= DF_1_NOW; + } + if (_ctx.getDTFlag(ELFLinkingContext::DTFlag::DT_ORIGIN)) { + dtflags |= DF_ORIGIN; + dt1flags |= DF_1_ORIGIN; + } + if (dtflags != 0) + _dynamicTable->addEntry(DT_FLAGS, dtflags); + if (dt1flags != 0) + _dynamicTable->addEntry(DT_FLAGS_1, dt1flags); + // The dynamic symbol table need to be sorted earlier because the hash // table needs to be built using the dynamic symbol table. It would be // late to sort the symbols due to that in finalize. In the dynamic symbol Index: lld/trunk/test/elf/zoption_dtflags.test =================================================================== --- lld/trunk/test/elf/zoption_dtflags.test +++ lld/trunk/test/elf/zoption_dtflags.test @@ -0,0 +1,90 @@ +# Test that -z {origin, now} options work. +# +#RUN: yaml2obj -format=elf %s -o=%t.o +#RUN: lld -flavor gnu -target x86_64 %t.o -e=main -z now -z origin -o %t1 +#RUN: llvm-readobj -dynamic-table %t1 | FileCheck %s +# +#CHECK: 0x000000000000001E FLAGS ORIGIN BIND_NOW +#CHECK: 0x000000006FFFFFFB FLAGS_1 NOW ORIGIN + +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_FREEBSD + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000010 + Content: 554889E54883EC10C745FC00000000E81C000000B9000000008945F889C84883C4105DC36666662E0F1F840000000000554889E58B45FC5DC3 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .comment + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x0000000000000001 + Content: 004672656542534420636C616E672076657273696F6E20332E342E312028746167732F52454C454153455F33342F646F74312D66696E616C203230383033322920323031343035313200 + - Name: .note.GNU-stack + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .eh_frame + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + AddressAlign: 0x0000000000000008 + Content: 1400000000000000017A5200017810011B0C070890010000180000001C000000000000002400000000410E108602430D060000001800000038000000000000000900000000410E108602430D06000000 + - Name: .rela.eh_frame + Type: SHT_RELA + Link: .symtab + AddressAlign: 0x0000000000000008 + Info: .eh_frame + Relocations: + - Offset: 0x0000000000000020 + Symbol: .text + Type: R_X86_64_PC32 + - Offset: 0x000000000000003C + Symbol: .text + Type: R_X86_64_PC32 + Addend: 48 +Symbols: + Local: + - Name: local + Type: STT_FUNC + Section: .text + Value: 0x0000000000000030 + Size: 0x0000000000000009 + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .comment + Type: STT_SECTION + Section: .comment + - Name: .note.GNU-stack + Type: STT_SECTION + Section: .note.GNU-stack + - Name: .eh_frame + Type: STT_SECTION + Section: .eh_frame + Global: + - Name: main + Type: STT_FUNC + Section: .text + Size: 0x0000000000000024 +...