Index: include/lld/ReaderWriter/ELFLinkingContext.h =================================================================== --- include/lld/ReaderWriter/ELFLinkingContext.h +++ include/lld/ReaderWriter/ELFLinkingContext.h @@ -112,7 +112,6 @@ OutputMagic getOutputMagic() const { return _outputMagic; } uint16_t getOutputELFType() const { return _outputELFType; } uint16_t getOutputMachine() const; - bool mergeCommonStrings() const { return _mergeCommonStrings; } virtual int getMachineType() const = 0; virtual uint64_t getBaseAddress() const { return _baseAddress; } virtual void setBaseAddress(uint64_t address) { _baseAddress = address; } @@ -201,7 +200,6 @@ void setNoInhibitExec(bool v) { _noInhibitExec = v; } void setExportDynamic(bool v) { _exportDynamic = v; } void setIsStaticExecutable(bool v) { _isStaticExecutable = v; } - void setMergeCommonStrings(bool v) { _mergeCommonStrings = v; } void setUseShlibUndefines(bool use) { _useShlibUndefines = use; } void setOutputELFType(uint32_t type) { _outputELFType = type; } @@ -378,7 +376,6 @@ bool _isStaticExecutable = false; bool _noInhibitExec = false; bool _exportDynamic = false; - bool _mergeCommonStrings = false; bool _useShlibUndefines = true; bool _dynamicLinkerArg = false; bool _noAllowDynamicLibraries = false; Index: lib/Driver/GnuLdDriver.cpp =================================================================== --- lib/Driver/GnuLdDriver.cpp +++ lib/Driver/GnuLdDriver.cpp @@ -478,9 +478,6 @@ ctx->setBaseAddress(baseAddress); } - if (parsedArgs.hasArg(OPT_merge_strings)) - ctx->setMergeCommonStrings(true); - if (parsedArgs.hasArg(OPT_t)) ctx->setLogInputFiles(true); Index: lib/Driver/GnuLdOptions.td =================================================================== --- lib/Driver/GnuLdOptions.td +++ lib/Driver/GnuLdOptions.td @@ -298,9 +298,6 @@ def hash_style : Joined <["--"], "hash-style=">, HelpText<"Set the type of linker's hash table(s)">, Group; -def merge_strings : Flag<["--"], "merge-strings">, - HelpText<"Merge common strings across mergeable sections">, - Group; def eh_frame_hdr : Flag<["--"], "eh-frame-hdr">, HelpText<"Request creation of .eh_frame_hdr section and ELF " " PT_GNU_EH_FRAME segment header">, Index: lib/ReaderWriter/ELF/Atoms.h =================================================================== --- lib/ReaderWriter/ELF/Atoms.h +++ lib/ReaderWriter/ELF/Atoms.h @@ -199,68 +199,6 @@ mutable ContentPermissions _permissions; }; -/// \brief This atom stores mergeable Strings -template class ELFMergeAtom : public DefinedAtom { - typedef llvm::object::Elf_Shdr_Impl Elf_Shdr; - -public: - ELFMergeAtom(const ELFFile &file, StringRef sectionName, - const Elf_Shdr *section, ArrayRef contentData, - uint64_t offset) - : _owningFile(file), _sectionName(sectionName), _section(section), - _contentData(contentData), _offset(offset) { - } - - const ELFFile &file() const override { return _owningFile; } - StringRef name() const override { return ""; } - virtual uint64_t section() const { return _section->sh_name; } - virtual uint64_t offset() const { return _offset; } - virtual void setOrdinal(uint64_t ord) { _ordinal = ord; } - uint64_t ordinal() const override { return _ordinal; } - uint64_t size() const override { return _contentData.size(); } - Scope scope() const override { return scopeTranslationUnit; } - Interposable interposable() const override { return interposeNo; } - Merge merge() const override { return mergeByContent; } - ContentType contentType() const override { return typeConstant; } - - Alignment alignment() const override { - return Alignment(_section->sh_addralign); - } - - SectionChoice sectionChoice() const override { return sectionCustomRequired; } - StringRef customSectionName() const override { return _sectionName; } - DeadStripKind deadStrip() const override { return deadStripNormal; } - ContentPermissions permissions() const override { return permR__; } - ArrayRef rawContent() const override { return _contentData; } - - DefinedAtom::reference_iterator begin() const override { - uintptr_t index = 0; - const void *it = reinterpret_cast(index); - return reference_iterator(*this, it); - } - - DefinedAtom::reference_iterator end() const override { - uintptr_t index = 0; - const void *it = reinterpret_cast(index); - return reference_iterator(*this, it); - } - - const Reference *derefIterator(const void *It) const override { - return nullptr; - } - - void incrementIterator(const void *&It) const override {} - -private: - const ELFFile &_owningFile; - StringRef _sectionName; - const Elf_Shdr *_section; - /// \brief Holds the bits that make up the atom. - ArrayRef _contentData; - uint64_t _ordinal; - uint64_t _offset; -}; - template class ELFCommonAtom : public DefinedAtom { typedef llvm::object::Elf_Sym_Impl Elf_Sym; public: Index: lib/ReaderWriter/ELF/ELFFile.h =================================================================== --- lib/ReaderWriter/ELF/ELFFile.h +++ lib/ReaderWriter/ELF/ELFFile.h @@ -28,61 +28,6 @@ typedef llvm::object::Elf_Rel_Impl Elf_Rela; typedef typename llvm::object::ELFFile::Elf_Word Elf_Word; - // A Map is used to hold the atoms that have been divided up - // after reading the section that contains Merge String attributes - struct MergeSectionKey { - const Elf_Shdr *_shdr; - int64_t _offset; - }; - - struct MergeSectionEq { - int64_t operator()(const MergeSectionKey &k) const { - return llvm::hash_combine((int64_t)(k._shdr->sh_name), - (int64_t)k._offset); - } - bool operator()(const MergeSectionKey &lhs, - const MergeSectionKey &rhs) const { - return ((lhs._shdr->sh_name == rhs._shdr->sh_name) && - (lhs._offset == rhs._offset)); - } - }; - - struct MergeString { - MergeString(int64_t offset, StringRef str, const Elf_Shdr *shdr, - StringRef sectionName) - : _offset(offset), _string(str), _shdr(shdr), - _sectionName(sectionName) {} - // the offset of this atom - int64_t _offset; - // The content - StringRef _string; - // Section header - const Elf_Shdr *_shdr; - // Section name - StringRef _sectionName; - }; - - // This is used to find the MergeAtom given a relocation - // offset - typedef std::vector *> MergeAtomsT; - - /// \brief find a merge atom given a offset - ELFMergeAtom *findMergeAtom(const Elf_Shdr *shdr, int64_t offset) { - auto it = std::find_if(_mergeAtoms.begin(), _mergeAtoms.end(), - [=](const ELFMergeAtom *a) { - int64_t off = a->offset(); - return shdr->sh_name == a->section() && - offset >= off && - offset <= off + (int64_t)a->size(); - }); - assert(it != _mergeAtoms.end()); - return *it; - } - - typedef std::unordered_map MergedSectionMapT; - typedef typename MergedSectionMapT::iterator MergedSectionMapIterT; - public: ELFFile(StringRef name, ELFLinkingContext &ctx); ELFFile(std::unique_ptr mb, ELFLinkingContext &ctx); @@ -103,10 +48,6 @@ /// to read them later and create atoms std::error_code createAtomizableSections(); - /// \brief Create mergeable atoms from sections that have the merge attribute - /// set - std::error_code createMergeableAtoms(); - /// \brief Add the symbols that the sections contain. The symbols will be /// converted to atoms for /// Undefined symbols, absolute symbols @@ -147,22 +88,11 @@ /// Reference's target with the Atom pointer it refers to. void updateReferences(); - /// \brief Update the reference if the access corresponds to a merge string - /// section. - void updateReferenceForMergeStringAccess(ELFReference *ref, - const Elf_Sym *symbol, - const Elf_Shdr *shdr); /// \brief Do we want to ignore the section. Ignored sections are /// not processed to create atoms bool isIgnoredSection(const Elf_Shdr *section); - /// \brief Is the current section be treated as a mergeable string section. - /// The contents of a mergeable string section are null-terminated strings. - /// If the section have mergeable strings, the linker would need to split - /// the section into multiple atoms and mark them mergeByContent. - bool isMergeableStringSection(const Elf_Shdr *section); - /// \brief Returns a new anonymous atom whose size is equal to the /// section size. That atom will be used to represent the entire /// section that have no symbols. @@ -286,19 +216,6 @@ referenceStart, referenceEnd, referenceList); } - /// Process the Merge string and create an atom for it. - ELFMergeAtom *createMergedString(StringRef sectionName, - const Elf_Shdr *sectionHdr, - ArrayRef contentData, - unsigned int offset) { - ELFMergeAtom *mergeAtom = new (_readerStorage) - ELFMergeAtom(*this, sectionName, sectionHdr, contentData, offset); - const MergeSectionKey mergedSectionKey = {sectionHdr, offset}; - if (_mergedSectionMap.find(mergedSectionKey) == _mergedSectionMap.end()) - _mergedSectionMap.insert(std::make_pair(mergedSectionKey, mergeAtom)); - return mergeAtom; - } - /// References to the sections comprising a group, from sections /// outside the group, must be made via global UNDEF symbols, /// referencing global symbols defined as addresses in the group @@ -331,7 +248,6 @@ /// which will hold the entries. std::unordered_map> _relocationAddendReferences; - MergedSectionMapT _mergedSectionMap; std::unordered_map _relocationReferences; std::vector *> _references; llvm::DenseMap _symbolToAtomMapping; @@ -343,24 +259,14 @@ _groupChild; llvm::StringMap _undefAtomsForGroupChild; - /// \brief Atoms that are created for a section that has the merge property - /// set - MergeAtomsT _mergeAtoms; - /// \brief the section and the symbols that are contained within it to create /// used to create atoms llvm::MapVector> _sectionSymbols; - /// \brief Sections that have merge string property - std::vector _mergeStringSections; - std::unique_ptr _mb; int64_t _ordinal; - /// \brief the cached options relevant while reading the ELF File - bool _doStringsMerge; - /// \brief Is --wrap on? bool _useWrap; Index: lib/ReaderWriter/ELF/ELFFile.cpp =================================================================== --- lib/ReaderWriter/ELF/ELFFile.cpp +++ lib/ReaderWriter/ELF/ELFFile.cpp @@ -16,15 +16,13 @@ template ELFFile::ELFFile(StringRef name, ELFLinkingContext &ctx) - : SimpleFile(name), _ordinal(0), _doStringsMerge(ctx.mergeCommonStrings()), - _useWrap(false), _ctx(ctx) { + : SimpleFile(name), _ordinal(0), _useWrap(false), _ctx(ctx) { setLastError(std::error_code()); } template ELFFile::ELFFile(std::unique_ptr mb, ELFLinkingContext &ctx) : SimpleFile(mb->getBufferIdentifier()), _mb(std::move(mb)), _ordinal(0), - _doStringsMerge(ctx.mergeCommonStrings()), _useWrap(ctx.wrapCalls().size()), _ctx(ctx) {} template @@ -83,11 +81,6 @@ if ((ec = createAtomizableSections())) return ec; - // For mergeable strings, we would need to split the section into various - // atoms - if ((ec = createMergeableAtoms())) - return ec; - // Create the necessary symbols that are part of the section that we // created in createAtomizableSections function if ((ec = createSymbolsFromAtomizableSections())) @@ -141,11 +134,6 @@ if (isIgnoredSection(§ion)) continue; - if (isMergeableStringSection(§ion)) { - _mergeStringSections.push_back(§ion); - continue; - } - if (section.sh_type == llvm::ELF::SHT_RELA) { auto sHdrOrErr = _objFile->getSection(section.sh_info); if (std::error_code ec = sHdrOrErr.getError()) @@ -176,47 +164,6 @@ return std::error_code(); } -template std::error_code ELFFile::createMergeableAtoms() { - // Divide the section that contains mergeable strings into tokens - // TODO - // a) add resolver support to recognize multibyte chars - // b) Create a separate section chunk to write mergeable atoms - std::vector tokens; - for (const Elf_Shdr *msi : _mergeStringSections) { - auto sectionName = getSectionName(msi); - if (std::error_code ec = sectionName.getError()) - return ec; - - auto sectionContents = getSectionContents(msi); - if (std::error_code ec = sectionContents.getError()) - return ec; - - StringRef secCont(reinterpret_cast(sectionContents->begin()), - sectionContents->size()); - - unsigned int prev = 0; - for (std::size_t i = 0, e = sectionContents->size(); i != e; ++i) { - if ((*sectionContents)[i] == '\0') { - tokens.push_back(new (_readerStorage) MergeString( - prev, secCont.slice(prev, i + 1), msi, *sectionName)); - prev = i + 1; - } - } - } - - // Create Mergeable atoms - for (const MergeString *tai : tokens) { - ArrayRef content((const uint8_t *)tai->_string.data(), - tai->_string.size()); - ELFMergeAtom *atom = createMergedString(tai->_sectionName, tai->_shdr, - content, tai->_offset); - atom->setOrdinal(++_ordinal); - addAtom(*atom); - _mergeAtoms.push_back(atom); - } - return std::error_code(); -} - template std::error_code ELFFile::createSymbolsFromAtomizableSections() { // Increment over all the symbols collecting atoms and symbol names for @@ -362,24 +309,6 @@ getSymbolValue(&*symbol), contentSize); - // If the linker finds that a section has global atoms that are in a - // mergeable section, treat them as defined atoms as they shouldn't be - // merged away as well as these symbols have to be part of symbol - // resolution - if (isMergeableStringSection(section)) { - if (symbol->getBinding() != llvm::ELF::STB_GLOBAL) - continue; - ELFDefinedAtom *atom = createDefinedAtom( - symbolName, *sectionName, &**si, section, symbolData, - _references.size(), _references.size(), _references); - atom->setOrdinal(++_ordinal); - if (addAtoms) - addAtom(*atom); - else - atomsForSection[*sectionName].push_back(atom); - continue; - } - // Don't allocate content to a weak symbol, as they may be merged away. // Create an anonymous atom to hold the data. ELFDefinedAtom *anonAtom = nullptr; @@ -647,35 +576,6 @@ } } -template -void ELFFile::updateReferenceForMergeStringAccess(ELFReference *ref, - const Elf_Sym *symbol, - const Elf_Shdr *shdr) { - // If the target atom is mergeable strefng atom, the atom might have been - // merged with other atom having the same contents. Try to find the - // merged one if that's the case. - int64_t addend = ref->addend(); - if (addend < 0) - addend = 0; - - const MergeSectionKey ms = {shdr, addend}; - auto msec = _mergedSectionMap.find(ms); - if (msec != _mergedSectionMap.end()) { - ref->setTarget(msec->second); - return; - } - - // The target atom was not merged. Mergeable atoms are not in - // _symbolToAtomMapping, so we cannot find it by calling findAtom(). We - // instead call findMergeAtom(). - if (symbol->getType() != llvm::ELF::STT_SECTION) - addend = getSymbolValue(symbol) + addend; - ELFMergeAtom *mergedAtom = findMergeAtom(shdr, addend); - ref->setOffset(addend - mergedAtom->offset()); - ref->setAddend(0); - ref->setTarget(mergedAtom); -} - template void ELFFile::updateReferences() { for (auto &ri : _references) { if (ri->kindNamespace() != Reference::KindNamespace::ELF) @@ -685,12 +585,7 @@ ErrorOr shdr = _objFile->getSection(symbol, _symtab, _shndxTable); - // If the atom is not in mergeable string section, the target atom is - // simply that atom. - if (isMergeableStringSection(*shdr)) - updateReferenceForMergeStringAccess(ri, symbol, *shdr); - else - ri->setTarget(findAtom(findSymbolForReference(ri), symbol)); + ri->setTarget(findAtom(findSymbolForReference(ri), symbol)); } } @@ -707,22 +602,6 @@ } return false; } - -template -bool ELFFile::isMergeableStringSection(const Elf_Shdr *section) { - if (_doStringsMerge && section) { - int64_t sectionFlags = section->sh_flags; - sectionFlags &= ~llvm::ELF::SHF_ALLOC; - // Mergeable string sections have both SHF_MERGE and SHF_STRINGS flags - // set. sh_entsize is the size of each character which is normally 1. - if ((section->sh_entsize < 2) && - (sectionFlags == (llvm::ELF::SHF_MERGE | llvm::ELF::SHF_STRINGS))) { - return true; - } - } - return false; -} - template ELFDefinedAtom * ELFFile::createSectionAtom(const Elf_Shdr *section, StringRef sectionName, Index: test/elf/mergeatoms.test =================================================================== --- test/elf/mergeatoms.test +++ /dev/null @@ -1,6 +0,0 @@ -# Tests that atoms are merged by testing it with --merge-strings option -RUN: lld -flavor gnu -target x86_64-linux --merge-strings -o %t1 \ -RUN: %p/Inputs/foo.o.x86-64 %p/Inputs/bar.o.x86-64 -e bar1 -RUN: llvm-objdump -s %t1 | FileCheck -check-prefix=mergeAtoms %s - -mergeAtoms: 62617200 666f6f00 bar.foo. Index: test/elf/mergeconstants.test =================================================================== --- test/elf/mergeconstants.test +++ /dev/null @@ -1,20 +0,0 @@ -# The test checks for mergeable strings that appear in the object file -RUN: lld -flavor gnu --merge-strings --output-filetype=yaml -target x86_64 \ -RUN: %p/Inputs/constants-merge.x86-64 --noinhibit-exec \ -RUN: | FileCheck -check-prefix=mergeAtoms %s - -mergeAtoms: - ref-name: [[CONSTANT:[-a-zA-Z0-9_]+]] -mergeAtoms: type: constant -mergeAtoms: content: [ 62, 61, 72, 66, 6F, 6F, 00 ] -mergeAtoms: merge: by-content -mergeAtoms: section-choice: custom-required -mergeAtoms: section-name: .rodata.str1.1 -mergeAtoms: - name: foo -mergeAtoms: scope: global -mergeAtoms: type: data -mergeAtoms: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ] -mergeAtoms: alignment: 8 -mergeAtoms: references: -mergeAtoms: - kind: R_X86_64_64 -mergeAtoms: offset: 3 -mergeAtoms: target: [[CONSTANT]] Index: test/elf/reloc.test =================================================================== --- test/elf/reloc.test +++ /dev/null @@ -1,38 +0,0 @@ -RUN: lld -flavor gnu -target i386 --merge-strings -r --output-filetype=yaml \ -RUN: %p/Inputs/reloc-test.elf-i386 | FileCheck %s -check-prefix ELF-i386 - -ELF-i386: defined-atoms: -ELF-i386: - ref-name: [[STRNAMEA:[-a-zA-Z0-9_]+]] -ELF-i386: type: constant -ELF-i386: content: [ 68, 65, 6C, 6C, 6F, 20, 77, 6F, 72, 6C, 64, 00 ] -ELF-i386: merge: by-content -ELF-i386: - ref-name: [[STRNAMEB:[-a-zA-Z0-9_]+]] -ELF-i386: alignment: 16 -ELF-i386: section-choice: custom-required -ELF-i386: section-name: .text.startup -ELF-i386: references: -ELF-i386: - kind: layout-after -ELF-i386: offset: 0 -ELF-i386: target: main -ELF-i386: - name: main -ELF-i386: scope: global -ELF-i386: content: [ 55, 89, E5, 83, E4, F0, 83, EC, 10, C7, 04, 24, -ELF-i386: 00, 00, 00, 00, E8, FC, FF, FF, FF, 31, C0, C9, -ELF-i386: C3 ] -ELF-i386: alignment: 16 -ELF-i386: section-choice: custom-required -ELF-i386: section-name: .text.startup -ELF-i386: references: -ELF-i386: - kind: R_386_32 -ELF-i386: offset: 12 -ELF-i386: target: [[STRNAMEA]] -ELF-i386: - kind: R_386_PC32 -ELF-i386: offset: 17 -ELF-i386: target: puts -ELF-i386: addend: 252 -ELF-i386: undefined-atoms: -ELF-i386: - name: puts -ELF-i386: absolute-atoms: -ELF-i386: - name: test.c -ELF-i386: scope: static -ELF-i386: value: 0x0000000000000000