summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShankar Easwaran <shankare@codeaurora.org>2013-02-20 17:38:37 +0000
committerShankar Easwaran <shankare@codeaurora.org>2013-02-20 17:38:37 +0000
commit25832ede03654c8e6cc2dfd6fa8244db3fe44051 (patch)
treef14268b5f7872785e3195c3179bc95c28c0dfa1f
parent6631e948385b2aa8e292ae85f7f55b2adb2814ae (diff)
downloadbcm5719-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.h41
-rw-r--r--lld/lib/ReaderWriter/ELF/TargetHandler.h14
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp10
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h8
-rw-r--r--lld/test/elf/Inputs/globalconst.c2
-rw-r--r--lld/test/elf/Inputs/globalconst.o.x86-64bin0 -> 1072 bytes
-rw-r--r--lld/test/elf/mergeglobalatoms.test10
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
new file mode 100644
index 00000000000..d8e266e7633
--- /dev/null
+++ b/lld/test/elf/Inputs/globalconst.o.x86-64
Binary files differ
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
OpenPOWER on IntegriCloud