diff options
| author | Shankar Easwaran <shankare@codeaurora.org> | 2013-02-20 17:38:37 +0000 |
|---|---|---|
| committer | Shankar Easwaran <shankare@codeaurora.org> | 2013-02-20 17:38:37 +0000 |
| commit | 25832ede03654c8e6cc2dfd6fa8244db3fe44051 (patch) | |
| tree | f14268b5f7872785e3195c3179bc95c28c0dfa1f | |
| parent | 6631e948385b2aa8e292ae85f7f55b2adb2814ae (diff) | |
| download | bcm5719-llvm-25832ede03654c8e6cc2dfd6fa8244db3fe44051.tar.gz bcm5719-llvm-25832ede03654c8e6cc2dfd6fa8244db3fe44051.zip | |
functionality to handle global atoms in Merge sections
llvm-svn: 175636
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/File.h | 41 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/TargetHandler.h | 14 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp | 10 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h | 8 | ||||
| -rw-r--r-- | lld/test/elf/Inputs/globalconst.c | 2 | ||||
| -rw-r--r-- | lld/test/elf/Inputs/globalconst.o.x86-64 | bin | 0 -> 1072 bytes | |||
| -rw-r--r-- | lld/test/elf/mergeglobalatoms.test | 10 |
7 files changed, 63 insertions, 22 deletions
diff --git a/lld/lib/ReaderWriter/ELF/File.h b/lld/lib/ReaderWriter/ELF/File.h index 7b80e8c6c9e..98cfe44b7c2 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<ELFT>( + *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<ELFT> &relHandler = _elfTargetInfo + .template getTargetHandler<ELFT>().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 b2a5cddcf04..58fd77fa372 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 ELFT> class ELFDefinedAtom; +template <class ELFT> class ELFReference; class ELFWriter; template <class ELFT> class Header; template <class ELFT> class Section; @@ -54,17 +55,20 @@ public: return DefinedAtom::typeZeroFill; } - virtual DefinedAtom::ContentPermissions contentPermissions( - const ELFDefinedAtom<ELFT> *atom) const { + virtual DefinedAtom::ContentPermissions + contentPermissions(const ELFDefinedAtom<ELFT> *atom) const { return atom->permissions(); } + }; template <class ELFT> class TargetRelocationHandler { public: - virtual ErrorOr<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, - const AtomLayout &, - const Reference &)const = 0; + virtual ErrorOr<void> + 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 bad758c5497..95a0fd9e828 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<void> 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 c18e8f9c9c1..714f8b960c8 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<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, - const AtomLayout &, - const Reference &)const; + virtual ErrorOr<void> + 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 00000000000..08395a88e7c --- /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 Binary files differnew file mode 100644 index 00000000000..d8e266e7633 --- /dev/null +++ b/lld/test/elf/Inputs/globalconst.o.x86-64 diff --git a/lld/test/elf/mergeglobalatoms.test b/lld/test/elf/mergeglobalatoms.test new file mode 100644 index 00000000000..10d70363b4b --- /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 |

