functionality to handle global atoms in Merge sections

llvm-svn: 175636
This commit is contained in:
Shankar Easwaran 2013-02-20 17:38:37 +00:00
parent 6631e94838
commit 25832ede03
7 changed files with 63 additions and 22 deletions

View File

@ -274,17 +274,6 @@ public:
const Elf_Shdr *section = _objFile->getElfSection(sit); const Elf_Shdr *section = _objFile->getElfSection(sit);
const Elf_Sym *symbol = _objFile->getElfSymbol(it); 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; StringRef symbolName;
if ((EC = _objFile->getSymbolName(section, symbol, symbolName))) if ((EC = _objFile->getSymbolName(section, symbol, symbolName)))
return; return;
@ -364,6 +353,8 @@ public:
if ((EC = _objFile->getSymbolName(i.first, *si, symbolName))) if ((EC = _objFile->getSymbolName(i.first, *si, symbolName)))
return; return;
const Elf_Shdr *section = _objFile->getSection(*si);
bool isCommon = (*si)->getType() == llvm::ELF::STT_COMMON || bool isCommon = (*si)->getType() == llvm::ELF::STT_COMMON ||
(*si)->st_shndx == llvm::ELF::SHN_COMMON; (*si)->st_shndx == llvm::ELF::SHN_COMMON;
@ -423,6 +414,25 @@ public:
previous_atom->addReference(followOn); 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( auto newAtom = createDefinedAtomAndAssignRelocations(
symbolName, sectionName, *si, i.first, symbolData); symbolName, sectionName, *si, i.first, symbolData);
@ -468,11 +478,14 @@ public:
// refer to the MergeAtom to allow deduping // refer to the MergeAtom to allow deduping
if (doStringsMerge && shdr && (shdr->sh_entsize < 2) && if (doStringsMerge && shdr && (shdr->sh_entsize < 2) &&
(sectionFlags == (llvm::ELF::SHF_MERGE | llvm::ELF::SHF_STRINGS))) { (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()) { if (_mergedSectionMap.find(ms) == _mergedSectionMap.end()) {
uint64_t addend = ri->addend();
if (Symbol->getType() != llvm::ELF::STT_SECTION) if (Symbol->getType() != llvm::ELF::STT_SECTION)
addend = Symbol->st_value + ri->addend(); addend = Symbol->st_value + addend;
MergeAtomsIter mai = findMergeAtom(shdr, addend); MergeAtomsIter mai = findMergeAtom(shdr, addend);
if (mai != _mergeAtoms.end()) { if (mai != _mergeAtoms.end()) {
ri->setOffset(addend - ((*mai)->offset())); ri->setOffset(addend - ((*mai)->offset()));

View File

@ -33,6 +33,7 @@
namespace lld { namespace lld {
namespace elf { namespace elf {
template <class ELFT> class ELFDefinedAtom; template <class ELFT> class ELFDefinedAtom;
template <class ELFT> class ELFReference;
class ELFWriter; class ELFWriter;
template <class ELFT> class Header; template <class ELFT> class Header;
template <class ELFT> class Section; template <class ELFT> class Section;
@ -54,17 +55,20 @@ public:
return DefinedAtom::typeZeroFill; return DefinedAtom::typeZeroFill;
} }
virtual DefinedAtom::ContentPermissions contentPermissions( virtual DefinedAtom::ContentPermissions
const ELFDefinedAtom<ELFT> *atom) const { contentPermissions(const ELFDefinedAtom<ELFT> *atom) const {
return atom->permissions(); return atom->permissions();
} }
}; };
template <class ELFT> class TargetRelocationHandler { template <class ELFT> class TargetRelocationHandler {
public: public:
virtual ErrorOr<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, virtual ErrorOr<void>
const AtomLayout &, applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const AtomLayout &,
const Reference &)const = 0; const Reference &)const = 0;
virtual int64_t relocAddend(const Reference &)const { return 0; }
}; };
/// \brief An interface to override functions that are provided by the /// \brief An interface to override functions that are provided by the

View File

@ -52,6 +52,16 @@ void reloc32S(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
} }
} // end anon namespace } // 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( ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom, ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
const Reference &ref) const { const Reference &ref) const {

View File

@ -26,9 +26,11 @@ public:
X86_64TargetRelocationHandler(const X86_64TargetInfo &ti) X86_64TargetRelocationHandler(const X86_64TargetInfo &ti)
: _tlsSize(0), _targetInfo(ti) {} : _tlsSize(0), _targetInfo(ti) {}
virtual ErrorOr<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, virtual ErrorOr<void>
const AtomLayout &, applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const AtomLayout &,
const Reference &)const; const Reference &)const;
virtual int64_t fixupAddend(const Reference &)const;
private: private:
// Cached size of the TLS segment. // Cached size of the TLS segment.

View File

@ -0,0 +1,2 @@
/* compile the code with -fmerge-all-constants */
const char mystr[] = "foobar";

Binary file not shown.

View File

@ -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