summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/LinkerScript.cpp21
-rw-r--r--lld/ELF/OutputSections.cpp19
-rw-r--r--lld/ELF/OutputSections.h2
-rw-r--r--lld/ELF/Writer.cpp6
-rw-r--r--lld/test/ELF/linkerscript/empty-synthetic-removed-flags.s22
-rw-r--r--lld/test/ELF/pr36475.s29
6 files changed, 69 insertions, 30 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 2b72a5b24bf..f1f4ca4782a 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -752,25 +752,6 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {
}
}
-static bool isAllSectionDescription(const OutputSection &Cmd) {
- // We do not remove empty sections that are explicitly
- // assigned to any segment.
- if (!Cmd.Phdrs.empty())
- return false;
-
- // We do not want to remove sections that have custom address or align
- // expressions set even if them are empty. We keep them because we
- // want to be sure that any expressions can be evaluated and report
- // an error otherwise.
- if (Cmd.AddrExpr || Cmd.AlignExpr || Cmd.LMAExpr)
- return false;
-
- for (BaseCommand *Base : Cmd.SectionCommands)
- if (!isa<InputSectionDescription>(*Base))
- return false;
- return true;
-}
-
void LinkerScript::adjustSectionsBeforeSorting() {
// If the output section contains only symbol assignments, create a
// corresponding output section. The issue is what to do with linker script
@@ -803,7 +784,7 @@ void LinkerScript::adjustSectionsBeforeSorting() {
continue;
}
- if (!isAllSectionDescription(*Sec))
+ if (!Sec->isAllSectionDescription())
Sec->Flags = Flags;
else
Cmd = nullptr;
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 6a893f03e85..4facba60e9e 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -76,6 +76,25 @@ OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)
Live = false;
}
+bool OutputSection::isAllSectionDescription() const {
+ // We do not remove empty sections that are explicitly
+ // assigned to any segment.
+ if (!Phdrs.empty())
+ return false;
+
+ // We do not want to remove sections that have custom address or align
+ // expressions set even if them are empty. We keep them because we
+ // want to be sure that any expressions can be evaluated and report
+ // an error otherwise.
+ if (AddrExpr || AlignExpr || LMAExpr)
+ return false;
+
+ for (BaseCommand *Base : SectionCommands)
+ if (!isa<InputSectionDescription>(*Base))
+ return false;
+ return true;
+}
+
// We allow sections of types listed below to merged into a
// single progbits section. This is typically done by linker
// scripts. Merging nobits and progbits will force disk space
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index 35a873488f2..597fd065a21 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -42,6 +42,8 @@ class OutputSection final : public BaseCommand, public SectionBase {
public:
OutputSection(StringRef Name, uint32_t Type, uint64_t Flags);
+ bool isAllSectionDescription() const;
+
static bool classof(const SectionBase *S) {
return S->kind() == SectionBase::Output;
}
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 19ab2cb0393..060f21adf06 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1383,9 +1383,9 @@ static void removeUnusedSyntheticSections() {
llvm::erase_if(ISD->Sections,
[=](InputSection *IS) { return IS == SS; });
- // If there are no other alive input sections left, we remove output
- // section from the output.
- if (getInputSections(OS).empty())
+ // If there are no other alive sections or commands left in the output
+ // section description, we remove it from the output.
+ if (getInputSections(OS).empty() && OS->isAllSectionDescription())
OS->Live = false;
}
}
diff --git a/lld/test/ELF/linkerscript/empty-synthetic-removed-flags.s b/lld/test/ELF/linkerscript/empty-synthetic-removed-flags.s
index c1dd245e420..54a8baba3be 100644
--- a/lld/test/ELF/linkerscript/empty-synthetic-removed-flags.s
+++ b/lld/test/ELF/linkerscript/empty-synthetic-removed-flags.s
@@ -5,10 +5,9 @@
# RUN: llvm-readobj -s %t | FileCheck %s
## We have ".got.plt" synthetic section with SHF_ALLOC|SHF_WRITE flags.
-## It is empty, so linker removes it, but it have to keep ".got.plt" output
-## section because of BYTE command. Here we check that result output section
-## gets the same flags as previous allocatable section and does not get
-## SHF_WRITE flag from removed syntethic input section.
+## It is empty, so linker removes it, but it has to keep ".got.plt" output
+## section because of the BYTE command. Here we check that the output section
+## still remembers what the flags of .got.plt are.
# CHECK: Section {
# CHECK: Index: 2
@@ -16,13 +15,22 @@
# CHECK-NEXT: Type: SHT_PROGBITS
# CHECK-NEXT: Flags [
# CHECK-NEXT: SHF_ALLOC
-# CHECK-NEXT: SHF_EXECINSTR
+# CHECK-NEXT: SHF_WRITE
# CHECK-NEXT: ]
-## Check flags are the same if we omit empty synthetic section in script.
+## Check flags are not the same if we omit empty synthetic section in script.
# RUN: echo "SECTIONS { .foo : { *(.foo) } .bar : { BYTE(0x11) }}" > %t.script
# RUN: ld.lld -o %t --script %t.script %t.o
-# RUN: llvm-readobj -s %t | FileCheck %s
+# RUN: llvm-readobj -s %t | FileCheck --check-prefix=EMPTY %s
+
+# EMPTY: Section {
+# EMPTY: Index: 2
+# EMPTY: Name: .bar
+# EMPTY-NEXT: Type: SHT_PROGBITS
+# EMPTY-NEXT: Flags [
+# EMPTY-NEXT: SHF_ALLOC
+# EMPTY-NEXT: SHF_EXECINSTR
+# EMPTY-NEXT: ]
.section .foo,"ax"
.quad 0
diff --git a/lld/test/ELF/pr36475.s b/lld/test/ELF/pr36475.s
new file mode 100644
index 00000000000..2ce240c6c65
--- /dev/null
+++ b/lld/test/ELF/pr36475.s
@@ -0,0 +1,29 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo "PHDRS {" > %t.script
+# RUN: echo " ph_text PT_LOAD FLAGS (0x1 | 0x4);" >> %t.script
+# RUN: echo " ph_data PT_LOAD FLAGS (0x2 | 0x4);" >> %t.script
+# RUN: echo "}" >> %t.script
+# RUN: echo "SECTIONS {" >> %t.script
+# RUN: echo " .text : { *(.text*) } : ph_text" >> %t.script
+# RUN: echo " . = ALIGN(0x4000);" >> %t.script
+# RUN: echo " .got.plt : { BYTE(42); *(.got); } : ph_data" >> %t.script
+# RUN: echo "}" >> %t.script
+# RUN: ld.lld -T %t.script %t.o -o %t.elf
+# RUN: llvm-readobj -l -elf-output-style=GNU %t.elf | FileCheck %s
+
+# CHECK: Section to Segment mapping:
+# CHECK-NEXT: Segment Sections...
+# CHECK-NEXT: 00 .text executable
+# CHECK-NEXT: 01 .got.plt
+
+.text
+.globl _start
+.type _start,@function
+_start:
+ callq custom_func
+ ret
+
+.section executable,"ax",@progbits
+.type custom_func,@function
+custom_func:
+ ret
OpenPOWER on IntegriCloud