aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2018-05-23 01:58:43 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2018-05-23 01:58:43 +0000
commitcc2395be7c7696f417cc9f3351211e06afc06909 (patch)
tree223749eae3ee6b085597817f33a18bca9805f869
parenta3c36404c94f96f8ba579cfd2f3eabb4a21ea281 (diff)
ELF: Do not ICF two sections with different output sections.
Note that this doesn't do the right thing in the case where there is a linker script. We probably need to move output section assignment before ICF to get the correct behaviour here. Differential Revision: https://reviews.llvm.org/D47241 git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@333052 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--ELF/ICF.cpp8
-rw-r--r--ELF/InputSection.cpp2
-rw-r--r--ELF/InputSection.h2
-rw-r--r--ELF/Writer.cpp2
-rw-r--r--ELF/Writer.h2
-rw-r--r--test/ELF/icf-different-output-sections.s9
6 files changed, 21 insertions, 4 deletions
diff --git a/ELF/ICF.cpp b/ELF/ICF.cpp
index 5d5cc8634..3e253a074 100644
--- a/ELF/ICF.cpp
+++ b/ELF/ICF.cpp
@@ -78,6 +78,7 @@
#include "SymbolTable.h"
#include "Symbols.h"
#include "SyntheticSections.h"
+#include "Writer.h"
#include "lld/Common/Threads.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/BinaryFormat/ELF.h"
@@ -302,6 +303,13 @@ bool ICF<ELFT>::equalsConstant(const InputSection *A, const InputSection *B) {
A->getSize() != B->getSize() || A->Data != B->Data)
return false;
+ // If two sections have different output sections, we cannot merge them.
+ // FIXME: This doesn't do the right thing in the case where there is a linker
+ // script. We probably need to move output section assignment before ICF to
+ // get the correct behaviour here.
+ if (getOutputSectionName(A) != getOutputSectionName(B))
+ return false;
+
if (A->AreRelocsRela)
return constantEq(A, A->template relas<ELFT>(), B,
B->template relas<ELFT>());
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
index b958f575d..11d46cf9c 100644
--- a/ELF/InputSection.cpp
+++ b/ELF/InputSection.cpp
@@ -325,7 +325,7 @@ template <class ELFT> void InputSection::copyShtGroup(uint8_t *Buf) {
*To++ = Sections[Idx]->getOutputSection()->SectionIndex;
}
-InputSectionBase *InputSection::getRelocatedSection() {
+InputSectionBase *InputSection::getRelocatedSection() const {
if (!File || (Type != SHT_RELA && Type != SHT_REL))
return nullptr;
ArrayRef<InputSectionBase *> Sections = File->getSections();
diff --git a/ELF/InputSection.h b/ELF/InputSection.h
index bc70baf8b..7a83bf9a1 100644
--- a/ELF/InputSection.h
+++ b/ELF/InputSection.h
@@ -317,7 +317,7 @@ public:
static bool classof(const SectionBase *S);
- InputSectionBase *getRelocatedSection();
+ InputSectionBase *getRelocatedSection() const;
template <class ELFT, class RelTy>
void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 8bf4d764a..13bba61bf 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -92,7 +92,7 @@ static bool isSectionPrefix(StringRef Prefix, StringRef Name) {
return Name.startswith(Prefix) || Name == Prefix.drop_back();
}
-StringRef elf::getOutputSectionName(InputSectionBase *S) {
+StringRef elf::getOutputSectionName(const InputSectionBase *S) {
if (Config->Relocatable)
return S->Name;
diff --git a/ELF/Writer.h b/ELF/Writer.h
index 41f1e550e..7806f824c 100644
--- a/ELF/Writer.h
+++ b/ELF/Writer.h
@@ -48,7 +48,7 @@ struct PhdrEntry {
};
void addReservedSymbols();
-llvm::StringRef getOutputSectionName(InputSectionBase *S);
+llvm::StringRef getOutputSectionName(const InputSectionBase *S);
template <class ELFT> uint32_t calcMipsEFlags();
diff --git a/test/ELF/icf-different-output-sections.s b/test/ELF/icf-different-output-sections.s
new file mode 100644
index 000000000..e66b102a1
--- /dev/null
+++ b/test/ELF/icf-different-output-sections.s
@@ -0,0 +1,9 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2 --icf=all --print-icf-sections | count 0
+
+.section foo,"ax"
+.byte 42
+
+.section bar,"ax"
+.byte 42