Skip to content

Commit 343ffa7

Browse files
committed
[LLD] [COFF] Fix mingw comdat associativity for leader symbols with a different name
For a weak symbol func in a comdat, the actual leader symbol ends up named like .weak.func.default*. Likewise, for stdcall on i386, the symbol may be named _func@4, while the section suffix only is "func", which the previous implementation didn't handle. This fixes unwinding through weak functions when using -ffunction-sections in mingw environments. Differential Revision: https://reviews.llvm.org/D84607
1 parent a7044ed commit 343ffa7

File tree

3 files changed

+87
-5
lines changed

3 files changed

+87
-5
lines changed

lld/COFF/InputFiles.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -348,13 +348,13 @@ void ObjFile::recordPrevailingSymbolForMingw(
348348
// of the section chunk we actually include instead of discarding it,
349349
// add the symbol to a map to allow using it for implicitly
350350
// associating .[px]data$<func> sections to it.
351+
// Use the suffix from the .text$<func> instead of the leader symbol
352+
// name, for cases where the names differ (i386 mangling/decorations,
353+
// cases where the leader is a weak symbol named .weak.func.default*).
351354
int32_t sectionNumber = sym.getSectionNumber();
352355
SectionChunk *sc = sparseChunks[sectionNumber];
353356
if (sc && sc->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) {
354-
StringRef name;
355-
name = check(coffObj->getSymbolName(sym));
356-
if (getMachineType() == I386)
357-
name.consume_front("_");
357+
StringRef name = sc->getSectionName().split('$').second;
358358
prevailingSectionMap[name] = sectionNumber;
359359
}
360360
}

lld/test/COFF/associative-comdat-mingw-i386.s

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
# REQUIRES: x86
22

3-
# RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.obj
3+
# RUN: llvm-mc -triple=i686-windows-gnu %s -defsym stdcall=0 -filetype=obj -o %t.obj
44

55
# RUN: lld-link -lldmingw -entry:main %t.obj -out:%t.exe
66
# RUN: llvm-objdump -s %t.exe | FileCheck %s
77

8+
# RUN: llvm-mc -triple=i686-windows-gnu %s -defsym stdcall=1 -filetype=obj -o %t.stdcall.obj
9+
# RUN: lld-link -lldmingw -entry:main %t.stdcall.obj -out:%t.stdcall.exe
10+
# RUN: llvm-objdump -s %t.stdcall.exe | FileCheck %s
11+
812
# Check that the .eh_frame comdat was included, even if it had no symbols,
913
# due to associativity with the symbol _foo.
1014

@@ -19,19 +23,34 @@
1923
.globl _main
2024
.p2align 4, 0x90
2125
_main:
26+
.if stdcall==0
2227
call _foo
28+
.else
29+
call _foo@0
30+
.endif
2331
ret
2432

2533
.section .eh_frame$foo,"dr"
2634
.linkonce discard
2735
.byte 0x42
2836

37+
.if stdcall==0
2938
.def _foo;
39+
.else
40+
.def _foo@0;
41+
.endif
3042
.scl 2;
3143
.type 32;
3244
.endef
45+
.if stdcall==0
3346
.section .text$foo,"xr",discard,_foo
3447
.globl _foo
3548
.p2align 4
3649
_foo:
50+
.else
51+
.section .text$foo,"xr",discard,_foo@0
52+
.globl _foo@0
53+
.p2align 4
54+
_foo@0:
55+
.endif
3756
ret
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# REQUIRES: x86
2+
3+
# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj
4+
# RUN: llvm-readobj --symbols %t.obj | FileCheck %s --check-prefix=SYMBOL
5+
6+
# RUN: lld-link -lldmingw -entry:main %t.obj -out:%t.exe -lldmap:%t.map -verbose
7+
# RUN: llvm-readobj --sections %t.exe | FileCheck %s
8+
9+
# CHECK: Sections [
10+
# CHECK: Section {
11+
# CHECK: Number: 2
12+
# CHECK-LABEL: Name: .rdata (2E 72 64 61 74 61 00 00)
13+
# This is the critical check to show that .xdata$foo was
14+
# retained, while .xdata$bar wasn't. This *must* be 0x24
15+
# (0x4 for the .xdata section and 0x20 for the
16+
# .ctors/.dtors headers/ends).
17+
# CHECK-NEXT: VirtualSize: 0x24
18+
19+
# Check that the weak symbols still are emitted as it was when the test was
20+
# written, to make sure the test still actually tests what was intended.
21+
22+
# SYMBOL: Symbol {
23+
# SYMBOL: Name: foo
24+
# SYMBOL-NEXT: Value: 0
25+
# SYMBOL-NEXT: Section: IMAGE_SYM_UNDEFINED (0)
26+
# SYMBOL-NEXT: BaseType: Null (0x0)
27+
# SYMBOL-NEXT: ComplexType: Null (0x0)
28+
# SYMBOL-NEXT: StorageClass: WeakExternal (0x69)
29+
# SYMBOL-NEXT: AuxSymbolCount: 1
30+
# SYMBOL-NEXT: AuxWeakExternal {
31+
# SYMBOL-NEXT: Linked: .weak.foo.default.main (19)
32+
# SYMBOL-NEXT: Search: Alias (0x3)
33+
# SYMBOL-NEXT: }
34+
# SYMBOL-NEXT: }
35+
36+
.text
37+
.globl main
38+
main:
39+
call foo
40+
retq
41+
42+
# See associative-comdat-mingw.s for the general setup. Here, the leader
43+
# symbols are weak, which causes the functions foo and bar to be undefined
44+
# weak externals, while the actual leader symbols are named like
45+
# .weak.foo.default.main.
46+
47+
.section .xdata$foo,"dr"
48+
.linkonce discard
49+
.long 42
50+
51+
.section .xdata$bar,"dr"
52+
.linkonce discard
53+
.long 43
54+
55+
.section .text$foo,"xr",discard,foo
56+
.weak foo
57+
foo:
58+
ret
59+
60+
.section .text$bar,"xr",discard,bar
61+
.weak bar
62+
bar:
63+
ret

0 commit comments

Comments
 (0)