From 25832ede03654c8e6cc2dfd6fa8244db3fe44051 Mon Sep 17 00:00:00 2001 From: Shankar Easwaran Date: Wed, 20 Feb 2013 17:38:37 +0000 Subject: [PATCH] functionality to handle global atoms in Merge sections llvm-svn: 175636 --- lld/lib/ReaderWriter/ELF/File.h | 41 ++++++++++++++------- lld/lib/ReaderWriter/ELF/TargetHandler.h | 14 ++++--- .../ELF/X86_64/X86_64TargetHandler.cpp | 10 +++++ .../ReaderWriter/ELF/X86_64/X86_64TargetHandler.h | 8 ++-- lld/test/elf/Inputs/globalconst.c | 2 + lld/test/elf/Inputs/globalconst.o.x86-64 | Bin 0 -> 1072 bytes lld/test/elf/mergeglobalatoms.test | 10 +++++ 7 files changed, 63 insertions(+), 22 deletions(-) create mode 100644 lld/test/elf/Inputs/globalconst.c create mode 100644 lld/test/elf/Inputs/globalconst.o.x86-64 create mode 100644 lld/test/elf/mergeglobalatoms.test diff --git a/lld/lib/ReaderWriter/ELF/File.h b/lld/lib/ReaderWriter/ELF/File.h index 7b80e8c..98cfe44 100644 --- a/lld/lib/ReaderWriter/ELF/File.h +++ b/lld/lib/ReaderWriter/ELF/File.h @@ -274,17 +274,6 @@ public: const Elf_Shdr *section = _objFile->getElfSection(sit); const Elf_Sym *symbol = _objFile->getElfSymbol(it); - // If its a merge section, the atoms have already - // been created, lets not create the atoms again - if (doStringsMerge) { - int64_t sectionFlags = section->sh_flags; - sectionFlags &= ~llvm::ELF::SHF_ALLOC; - if ((section->sh_entsize < 2) && - (sectionFlags == (llvm::ELF::SHF_MERGE | llvm::ELF::SHF_STRINGS))) { - continue; - } - } - StringRef symbolName; if ((EC = _objFile->getSymbolName(section, symbol, symbolName))) return; @@ -364,6 +353,8 @@ public: if ((EC = _objFile->getSymbolName(i.first, *si, symbolName))) return; + const Elf_Shdr *section = _objFile->getSection(*si); + bool isCommon = (*si)->getType() == llvm::ELF::STT_COMMON || (*si)->st_shndx == llvm::ELF::SHN_COMMON; @@ -423,6 +414,25 @@ public: previous_atom->addReference(followOn); } + // If the linker finds that a section has global atoms that are in a + // mergeable section, treat them as defined atoms as they shouldnt be + // merged away as well as these symbols have to be part of symbol + // resolution + int64_t sectionFlags = 0; + if (section) + sectionFlags = section->sh_flags; + sectionFlags &= ~llvm::ELF::SHF_ALLOC; + if (doStringsMerge && section && (section->sh_entsize < 2) && + (sectionFlags == (llvm::ELF::SHF_MERGE | llvm::ELF::SHF_STRINGS))) { + if ((*si)->getBinding() == llvm::ELF::STB_GLOBAL) { + auto definedMergeAtom = new (_readerStorage) ELFDefinedAtom( + *this, symbolName, sectionName, (*si), section, symbolData, + _references.size(), _references.size(), _references); + _definedAtoms._atoms.push_back(definedMergeAtom); + } + continue; + } + auto newAtom = createDefinedAtomAndAssignRelocations( symbolName, sectionName, *si, i.first, symbolData); @@ -468,11 +478,14 @@ public: // refer to the MergeAtom to allow deduping if (doStringsMerge && shdr && (shdr->sh_entsize < 2) && (sectionFlags == (llvm::ELF::SHF_MERGE | llvm::ELF::SHF_STRINGS))) { - const MergeSectionKey ms(shdr, ri->addend()); + const TargetRelocationHandler &relHandler = _elfTargetInfo + .template getTargetHandler().getRelocationHandler(); + int64_t relocAddend = relHandler.relocAddend(*ri); + uint64_t addend = ri->addend() + relocAddend; + const MergeSectionKey ms(shdr, addend); if (_mergedSectionMap.find(ms) == _mergedSectionMap.end()) { - uint64_t addend = ri->addend(); if (Symbol->getType() != llvm::ELF::STT_SECTION) - addend = Symbol->st_value + ri->addend(); + addend = Symbol->st_value + addend; MergeAtomsIter mai = findMergeAtom(shdr, addend); if (mai != _mergeAtoms.end()) { ri->setOffset(addend - ((*mai)->offset())); diff --git a/lld/lib/ReaderWriter/ELF/TargetHandler.h b/lld/lib/ReaderWriter/ELF/TargetHandler.h index b2a5cdd..58fd77f 100644 --- a/lld/lib/ReaderWriter/ELF/TargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/TargetHandler.h @@ -33,6 +33,7 @@ namespace lld { namespace elf { template class ELFDefinedAtom; +template class ELFReference; class ELFWriter; template class Header; template class Section; @@ -54,17 +55,20 @@ public: return DefinedAtom::typeZeroFill; } - virtual DefinedAtom::ContentPermissions contentPermissions( - const ELFDefinedAtom *atom) const { + virtual DefinedAtom::ContentPermissions + contentPermissions(const ELFDefinedAtom *atom) const { return atom->permissions(); } + }; template class TargetRelocationHandler { public: - virtual ErrorOr applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, - const AtomLayout &, - const Reference &)const = 0; + virtual ErrorOr + applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const AtomLayout &, + const Reference &)const = 0; + + virtual int64_t relocAddend(const Reference &)const { return 0; } }; /// \brief An interface to override functions that are provided by the diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp index bad758c..95a0fd9 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp @@ -52,6 +52,16 @@ void reloc32S(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { } } // end anon namespace +int64_t X86_64TargetRelocationHandler::fixupAddend(const Reference &ref) const { + switch (ref.kind()) { + case R_X86_64_PC32: + return 4; + default: + return 0; + } + return 0; +} + ErrorOr X86_64TargetRelocationHandler::applyRelocation( ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom, const Reference &ref) const { diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h index c18e8f9..714f8b9 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h @@ -26,9 +26,11 @@ public: X86_64TargetRelocationHandler(const X86_64TargetInfo &ti) : _tlsSize(0), _targetInfo(ti) {} - virtual ErrorOr applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, - const AtomLayout &, - const Reference &)const; + virtual ErrorOr + applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const AtomLayout &, + const Reference &)const; + + virtual int64_t fixupAddend(const Reference &)const; private: // Cached size of the TLS segment. diff --git a/lld/test/elf/Inputs/globalconst.c b/lld/test/elf/Inputs/globalconst.c new file mode 100644 index 0000000..08395a8 --- /dev/null +++ b/lld/test/elf/Inputs/globalconst.c @@ -0,0 +1,2 @@ +/* compile the code with -fmerge-all-constants */ +const char mystr[] = "foobar"; diff --git a/lld/test/elf/Inputs/globalconst.o.x86-64 b/lld/test/elf/Inputs/globalconst.o.x86-64 new file mode 100644 index 0000000000000000000000000000000000000000..d8e266e76334879c22b6f7b0933b240eae85ed1c GIT binary patch literal 1072 zcmbVL%}#?r5FSdk+LOJRc)^nz?JCv8L=!_&6%UOk`v5>OHVP!LB=+R%`3Sy-PoOif zBV^>%NtW-2Z+2N&KJI4sJ<9?v3vQrM>;il?6ugRiFoXd-XIU8J0RD7({_+5iq1Udi}76qt0BSA@5xuBvf zN#YbEX{KZ4KhDR64x-oAv#m?_u#xt?DJJlQX4z+Aa37KSZQ*-Dvy}Y@cw-C4y8S2E zOY2W?w97MM&^D1%mWuJ(@UzNoF2141ja4!3W4uL|c{_?nqqAgogekdqYUKVWF^lXc z-4hv-4`$LYb8j1w-ZKrV-5P-WuJs-Bp>|A;L9WlfM9THy`$zhu?antwe%DUO?|MS= h3kgV`8gkQpCIqU!c literal 0 HcmV?d00001 diff --git a/lld/test/elf/mergeglobalatoms.test b/lld/test/elf/mergeglobalatoms.test new file mode 100644 index 0000000..10d7036 --- /dev/null +++ b/lld/test/elf/mergeglobalatoms.test @@ -0,0 +1,10 @@ +# ELF files can have mergeable strings which are global!, treat them as global +# defined atoms +RUN: lld-core -merge-strings=true -reader ELF %p/Inputs/globalconst.o.x86-64 | FileCheck -check-prefix=globalatoms %s + +globalatoms: - name: mystr +globalatoms: scope: global +globalatoms: type: constant +globalatoms: content: [ 66, 6F, 6F, 62, 61, 72, 00 ] +globalatoms: section-choice: custom-required +globalatoms: section-name: .rodata.str1.1 -- 2.7.4