Skip to content

Commit 72b2ca5

Browse files
committed
[COFF] Respect weak externals for mangled symbol searching
We were previously ignoring weak externals during these searches (which are used for the entry point, exports, and subsystem inference), which differed from link.exe behavior. It also meant that we could get different behavior when linking an object file directly vs. packaging it into a static library, because static library symbol name directories include weak externals. Reviewed By: mstorsjo, yozhu Differential Revision: https://reviews.llvm.org/D139764
1 parent 658dc6e commit 72b2ca5

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

lld/COFF/SymbolTable.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -809,9 +809,17 @@ std::vector<Symbol *> SymbolTable::getSymsWithPrefix(StringRef prefix) {
809809
}
810810

811811
Symbol *SymbolTable::findMangle(StringRef name) {
812-
if (Symbol *sym = find(name))
813-
if (!isa<Undefined>(sym))
812+
if (Symbol *sym = find(name)) {
813+
if (auto *u = dyn_cast<Undefined>(sym)) {
814+
// We're specifically looking for weak aliases that ultimately resolve to
815+
// defined symbols, hence the call to getWeakAlias() instead of just using
816+
// the weakAlias member variable. This matches link.exe's behavior.
817+
if (Symbol *weakAlias = u->getWeakAlias())
818+
return weakAlias;
819+
} else {
814820
return sym;
821+
}
822+
}
815823

816824
// Efficient fuzzy string lookup is impossible with a hash table, so iterate
817825
// the symbol table once and collect all possibly matching symbols into this
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# REQUIRES: x86
2+
# RUN: rm -rf %t && split-file %s %t
3+
4+
## Ensure that we resolve the entry point to the unmangled weak alias instead of
5+
## the mangled library definition (which would fail with an undefined symbol).
6+
7+
# RUN: llvm-mc -triple x86_64-windows-msvc -filetype obj -o %t/entry-weak.obj %t/entry-weak.s
8+
# RUN: llvm-mc -triple x86_64-windows-msvc -filetype obj -o %t/entry-mangled.obj %t/entry-mangled.s
9+
# RUN: llvm-lib -out:%t/entry-mangled.lib %t/entry-mangled.obj
10+
# RUN: lld-link -subsystem:console -entry:entry -out:%t/entry-weak-external.exe %t/entry-weak.obj %t/entry-mangled.lib
11+
# RUN: llvm-readobj --file-headers %t/entry-weak-external.exe | FileCheck %s
12+
13+
## Ensure that we don't resolve the entry point to a weak alias pointing to an
14+
## undefined symbol (which would have caused the entry point to be 0 instead of
15+
## an actual address). I can't think of a way of triggering this edge case
16+
## without using /force:unresolved, which means it likely doesn't matter in
17+
## practice, but we still match link.exe's behavior for it.
18+
19+
# RUN: llvm-mc -triple x86_64-windows-msvc -filetype obj -o %t/entry-weak-undefined.obj %t/entry-weak-undefined.s
20+
# RUN: lld-link -subsystem:console -entry:entry -force:unresolved -out:%t/entry-undefined-weak-external.exe \
21+
# RUN: %t/entry-weak-undefined.obj %t/entry-mangled.lib
22+
# RUN: llvm-readobj --file-headers %t/entry-undefined-weak-external.exe | FileCheck %s
23+
24+
# CHECK: AddressOfEntryPoint: 0x1000
25+
26+
#--- entry-weak.s
27+
.globl default_entry
28+
default_entry:
29+
ret
30+
31+
.weak entry
32+
entry = default_entry
33+
34+
#--- entry-mangled.s
35+
.globl "?entry@@YAHXZ"
36+
"?entry@@YAHXZ":
37+
jmp does_not_exist
38+
39+
#--- entry-weak-undefined.s
40+
.weak entry
41+
entry = does_not_exist
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# REQUIRES: x86
2+
# RUN: rm -rf %t && split-file %s %t
3+
4+
## Ensure that weak externals are considered during subsystem inference.
5+
6+
# RUN: llvm-mc -triple x86_64-windows-msvc -filetype obj -o %t/cui.obj %t/cui.s
7+
# RUN: lld-link -out:%t/cui.exe %t/cui.obj
8+
# RUN: llvm-readobj --file-headers %t/cui.exe | FileCheck --check-prefix=CUI %s
9+
# RUN: llvm-mc -triple x86_64-windows-msvc -filetype obj -o %t/gui.obj %t/gui.s
10+
# RUN: lld-link -out:%t/gui.exe %t/gui.obj
11+
# RUN: llvm-readobj --file-headers %t/gui.exe | FileCheck --check-prefix=GUI %s
12+
13+
# CUI: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
14+
# GUI: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI
15+
16+
#--- cui.s
17+
.global default_main
18+
default_main:
19+
ret
20+
21+
.weak main
22+
main = default_main
23+
24+
.global mainCRTStartup
25+
mainCRTStartup:
26+
ret
27+
28+
#--- gui.s
29+
.global default_WinMain
30+
default_WinMain:
31+
ret
32+
33+
.weak WinMain
34+
WinMain = default_WinMain
35+
36+
.global WinMainCRTStartup
37+
WinMainCRTStartup:
38+
ret

0 commit comments

Comments
 (0)