summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2018-02-26 22:32:15 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2018-02-26 22:32:15 +0000
commit79c23eec04499933479874c0b06bc8d51914bde4 (patch)
tree49d9331cefbdcca8e14834cc8b2d514cec1df20a
parent6dcbc1dbb387cf465090cffece6fccc1564233ab (diff)
downloadbcm5719-llvm-79c23eec04499933479874c0b06bc8d51914bde4.tar.gz
bcm5719-llvm-79c23eec04499933479874c0b06bc8d51914bde4.zip
Keep flags from phantom synthetic sections.
This fixes pr36475. I think this code can be simplified a bit, but I would like to check in the more direct fix if we are in agreement on the direction and then refactor. This is not something that bfd does. The issue is not noticed in bfd because it keeps fewer sections from the linkerscript in the output. The reasons why it seems reasonable to do this: - As George noticed, we would still keep the flags if the output section had both an empty synthetic section and a regular section - We need an heuristic to find the flags of output sections. Using the flags of a synthetic section that would have been there seems a reasonable heuristic. llvm-svn: 326137
-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