aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2019-07-23 15:22:25 +0000
committerHans Wennborg <hans@hanshq.net>2019-07-23 15:22:25 +0000
commitceda1b7a5d1caee63925896e50b707aa321438dd (patch)
tree365c2978d5190e3b15630e22f82d19aca8dbc1dc
parent0ccd1d3519e4586303351eff7d605dceeab8af0f (diff)
Merging r366780 and r366784:
------------------------------------------------------------------------ r366780 | mstorsjo | 2019-07-23 08:38:04 +0200 (Tue, 23 Jul 2019) | 21 lines [COFF] Unbreak sorting of mingw comdat .tls sections after SVN r363457 Code built for mingw with -fdata-sections will store each TLS variable in a comdat section, named .tls$$<varname>. Normal TLS variables are stored in sections named .tls$ with a trailing dollar, which are sorted after a starter marker (in a later linked object file) in a section named ".tls" (with no dollar suffix), before an ending marker in a section named ".tls$ZZZ". The mingw comdat section suffix stripping introduced in SVN r363457 broke sorting of such tls sections, ending up sorting the stripped .tls$$<varname> sections (stripped to ".tls") before the start marker in the section named ".tls". We could add exceptions to the section name suffix stripping for .tls (and .CRT, where suffixes always should be honored), but the more conservative option is probably the reverse; to only apply the stripping for the normal sections where sorting shouldn't have any effect. Differential Revision: https://reviews.llvm.org/D65018 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r366784 | mstorsjo | 2019-07-23 09:28:23 +0200 (Tue, 23 Jul 2019) | 4 lines [test] Fix the test from the previous commit when run on windows. NFC. Apparently the escaped dollar sign didn't work the same way in "echo -e" on windows buildbots. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/lld/branches/release_90@366816 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--COFF/Writer.cpp27
-rw-r--r--test/COFF/Inputs/tlssup.s10
-rw-r--r--test/COFF/tls_suffix_sorting.s27
3 files changed, 60 insertions, 4 deletions
diff --git a/COFF/Writer.cpp b/COFF/Writer.cpp
index 36ef87de4..3da8b98d3 100644
--- a/COFF/Writer.cpp
+++ b/COFF/Writer.cpp
@@ -762,6 +762,28 @@ void Writer::locateImportTables() {
}
}
+// Return whether a SectionChunk's suffix (the dollar and any trailing
+// suffix) should be removed and sorted into the main suffixless
+// PartialSection.
+static bool shouldStripSectionSuffix(SectionChunk *sc, StringRef name) {
+ // On MinGW, comdat groups are formed by putting the comdat group name
+ // after the '$' in the section name. For .eh_frame$<symbol>, that must
+ // still be sorted before the .eh_frame trailer from crtend.o, thus just
+ // strip the section name trailer. For other sections, such as
+ // .tls$$<symbol> (where non-comdat .tls symbols are otherwise stored in
+ // ".tls$"), they must be strictly sorted after .tls. And for the
+ // hypothetical case of comdat .CRT$XCU, we definitely need to keep the
+ // suffix for sorting. Thus, to play it safe, only strip the suffix for
+ // the standard sections.
+ if (!config->mingw)
+ return false;
+ if (!sc || !sc->isCOMDAT())
+ return false;
+ return name.startswith(".text$") || name.startswith(".data$") ||
+ name.startswith(".rdata$") || name.startswith(".pdata$") ||
+ name.startswith(".xdata$") || name.startswith(".eh_frame$");
+}
+
// Create output section objects and add them to OutputSections.
void Writer::createSections() {
// First, create the builtin sections.
@@ -807,10 +829,7 @@ void Writer::createSections() {
continue;
}
StringRef name = c->getSectionName();
- // On MinGW, comdat groups are formed by putting the comdat group name
- // after the '$' in the section name. Such a section name suffix shouldn't
- // imply separate alphabetical sorting of those section chunks though.
- if (config->mingw && sc && sc->isCOMDAT())
+ if (shouldStripSectionSuffix(sc, name))
name = name.split('$').first;
PartialSection *pSec = createPartialSection(name,
c->getOutputCharacteristics());
diff --git a/test/COFF/Inputs/tlssup.s b/test/COFF/Inputs/tlssup.s
new file mode 100644
index 000000000..ca61c9dda
--- /dev/null
+++ b/test/COFF/Inputs/tlssup.s
@@ -0,0 +1,10 @@
+ .section .tls,"dw"
+ .byte 0xaa
+
+ .section .tls$ZZZ,"dw"
+ .byte 0xff
+
+ .globl _tls_index
+ .data
+_tls_index:
+ .int 0
diff --git a/test/COFF/tls_suffix_sorting.s b/test/COFF/tls_suffix_sorting.s
new file mode 100644
index 000000000..d426ac1fe
--- /dev/null
+++ b/test/COFF/tls_suffix_sorting.s
@@ -0,0 +1,27 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -triple=x86_64-windows-gnu %S/Inputs/tlssup.s -filetype=obj -o %t.tlssup.o
+# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.main.o
+
+# RUN: lld-link -lldmingw -entry:main %t.main.o %t.tlssup.o -out:%t.exe
+# RUN: llvm-objdump -s %t.exe | FileCheck %s
+
+# Check that .tls$$foo is sorted after the start marker (aa) and before the
+# end marker (ff).
+
+# CHECK: Contents of section .tls:
+# CHECK: 140004000 aabbff
+
+ .text
+ .globl main
+main:
+ movl _tls_index(%rip), %eax
+ movq %gs:88, %rcx
+ movq (%rcx,%rax,8), %rax
+ movb foo@SECREL32(%rax), %al
+ ret
+
+ .section .tls$$foo,"dw"
+ .linkonce discard
+foo:
+ .byte 0xbb