<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/59639>59639</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
lld-link.exe does not provide unwind information on Windows x64 for tailMergeX64 code when using /delayload
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
yjugl
</td>
</tr>
</table>
<pre>
Hello,
As described below, `lld-link.exe` adds no unwind information for [the `tailMergeX64` code](https://github.com/llvm/llvm-project/blob/7c26641d9dcea70a75ca48d2e3a5bf6ca7a925bb/lld/COFF/DLL.cpp#L198) when using `lld-link.exe` with `/delayload`, even though this code includes a `call` instruction. As stated [in Microsoft documentation](https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64):
> Table-based exception handling requires a table entry for all functions that allocate stack space or call another function (for example, nonleaf functions). [...] Failure to do so will result in unreliable exception handling and debugging of processes.
This missing unwind information currently has the following real-world impact in the Firefox web browser for Windows x64, when an exception is raised with a return address pointing to `tailMergeX64` stored on the stack:
- this can prevent the crash reporter from being reached, because Microsoft's internal code in `ntdll` that unwinds structured exception handlers may stop at `tailMergeX64`, resulting in no crash dump being created (see [bug 1801322 comment 1](https://bugzilla.mozilla.org/show_bug.cgi?id=1801322#c1));
- when we somehow succeed to get a crash dump, our crash analyzer generates garbage once it reaches `tailMergeX64`, resulting in hard-to-triage crashes (see [bug 1740094](https://bugzilla.mozilla.org/show_bug.cgi?id=1740094)).
Now I will provide more details with a simple example that reproduces the issue. When using the latest LLVM Windows x64 public release:
```powershell
>"C:\Program Files\LLVM\bin\clang.exe" --version
clang version 15.0.6
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin
>"C:\Program Files\LLVM\bin\lld-link.exe" --version
LLD 15.0.6
```
To compile the following program into an object file:
```c++
#include <windows.h>
int main(void) {
MessageBoxW(NULL, L"Hello", L"Hello", MB_OK);
return 0;
}
```
Then link it with `lld-link.exe` using `/delayload`:
```powershell
> "C:\Program Files\LLVM\bin\clang.exe" -c main.cpp
> "C:\Program Files\LLVM\bin\lld-link.exe" main.o /defaultlib:libcmt.lib /defaultlib:user32.lib /defaultlib:delayimp.lib /delayload:user32.dll
```
The `tailMergeX64` code is added at the end of the `.text` section to handle delay-loading, but there is not associated unwind information for this function in the `.pdata` (`RUNTIME_FUNCTION`) and `.xdata` (`UNWIND_INFO`) sections.
This can be verified with a script that I provide [here](https://github.com/yjugl/unwindchecker/):
```powershell
> python show_missing_unwind_info.py main.exe
Loading 'main.exe', please wait...
Section .text: unwind information covers 94.00% of 51712 bytes.
Looking for call instructions in the parts not covered by unwind information...
0x14000d8af: e8903dffff call 0x140001644
0x14000d8b4: 660f6f0424 movdqa xmm0, xmmword ptr [rsp]
0x14000d8b9: 660f6f4c2410 movdqa xmm1, xmmword ptr [rsp + 0x10]
0x14000d8bf: 660f6f542420 movdqa xmm2, xmmword ptr [rsp + 0x20]
Found 1 call instructions without unwind information in section .text.
Note that some of those may be false positives.
```
Or with a debug session, here in WinDbg:
```powershell
# This is the entry in the import address table for MessageBoxW
0:000> dq main+179f0 L1
00007ff6`afde79f0 00007ff6`afddd878
# This is the delay-load jumper for MessageBoxW
0:000> u main+d878 L0x18
main+0xd878:
00007ff6`afddd878 488d0571a10000 lea rax,[main+0x179f0 (00007ff6`afde79f0)]
00007ff6`afddd87f e900000000 jmp main+0xd884 (00007ff6`afddd884)
# This is the tailMergeX64 function for delay-loaded user32.dll
00007ff6`afddd884 51 push rcx
00007ff6`afddd885 52 push rdx
00007ff6`afddd886 4150 push r8
00007ff6`afddd888 4151 push r9
00007ff6`afddd88a 4883ec48 sub rsp,48h
00007ff6`afddd88e 660f7f0424 movdqa xmmword ptr [rsp],xmm0
00007ff6`afddd893 660f7f4c2410 movdqa xmmword ptr [rsp+10h],xmm1
00007ff6`afddd899 660f7f542420 movdqa xmmword ptr [rsp+20h],xmm2
00007ff6`afddd89f 660f7f5c2430 movdqa xmmword ptr [rsp+30h],xmm3
00007ff6`afddd8a5 488bd0 mov rdx,rax
00007ff6`afddd8a8 488d0d817c0000 lea rcx,[main+0x15530 (00007ff6`afde5530)]
# This calls __delayLoadHelper2
00007ff6`afddd8af e8903dffff call main+0x1644 (00007ff6`afdd1644)
00007ff6`afddd8b4 660f6f0424 movdqa xmm0,xmmword ptr [rsp]
00007ff6`afddd8b9 660f6f4c2410 movdqa xmm1,xmmword ptr [rsp+10h]
00007ff6`afddd8bf 660f6f542420 movdqa xmm2,xmmword ptr [rsp+20h]
00007ff6`afddd8c5 660f6f5c2430 movdqa xmm3,xmmword ptr [rsp+30h]
00007ff6`afddd8cb 4883c448 add rsp,48h
00007ff6`afddd8cf 4159 pop r9
00007ff6`afddd8d1 4158 pop r8
00007ff6`afddd8d3 5a pop rdx
00007ff6`afddd8d4 59 pop rcx
00007ff6`afddd8d5 ffe0 jmp rax
# Displaying full contents of the .pdata section (which is sorted)
0:000> dt ntdll!_IMAGE_RUNTIME_FUNCTION_ENTRY[0x128] main+0x19000
[...]
+0x000 BeginAddress : 0xd81b
+0x004 EndAddress : 0xd834
+0x008 UnwindInfoAddress : 0x15ff8
+0x008 UnwindData : 0x15ff8
+0x000 BeginAddress : 0xd834
+0x004 EndAddress : 0xd84c
+0x008 UnwindInfoAddress : 0x15ff8
+0x008 UnwindData : 0x15ff8
+0x000 BeginAddress : 0xd84c
+0x004 EndAddress : 0xd878
+0x008 UnwindInfoAddress : 0x15ff8
+0x008 UnwindData : 0x15ff8
# There should be an entry here for the tailMergeX64 function (BeginAddress: 0xd884),
# but the unwind information ends here
+0x000 BeginAddress : 0
+0x004 EndAddress : 0
+0x008 UnwindInfoAddress : 0
+0x008 UnwindData : 0
```
The expected result is the one obtained when linking with MSVC's `link.exe` instead:
```
> link.exe .\main.o libcmt.lib user32.lib delayimp.lib /DELAYLOAD:user32.dll
Microsoft (R) Incremental Linker Version 14.33.31630.0
Copyright (C) Microsoft Corporation. All rights reserved.
```
Or using `clang-cl.exe` to do compile and link at the same time, although I'm not sure what this does under the hood:
```powershell
"C:\Program Files\LLVM\bin\clang-cl.exe" main.cpp user32.lib delayimp.lib /link/DELAYLOAD:user32.dll
```
In both cases, unwind information is present for the `tailMergeX64` code; note that this code also differs slightly from the one added by `lld-link.exe`.
This can be seen with the script:
```powershell
> python show_missing_unwind_info.py main.exe
Loading 'main.exe', please wait...
Section .text: unwind information covers 94.23% of 51712 bytes.
Looking for call instructions in the parts not covered by unwind information...
Found no call instructions without unwind information in section .text.
```
Or, in a debug session:
```powershell
# This is the entry in the import address table for MessageBoxW
0:000> dq main+0x18a10
00007ff7`2fcd8a10 00007ff7`2fcc1030
# This is the delay-load jumper for MessageBoxW
0:000> u main+0x1030 L0x1C
main+0x1030:
00007ff7`2fcc1030 488d05d9790100 lea rax,[main+0x18a10 (00007ff7`2fcd8a10)]
00007ff7`2fcc1037 e900000000 jmp main+0x103c (00007ff7`2fcc103c)
# This is the tailMergeX64 function for delay-loaded user32.dll
00007ff7`2fcc103c 48894c2408 mov qword ptr [rsp+8],rcx
00007ff7`2fcc1041 4889542410 mov qword ptr [rsp+10h],rdx
00007ff7`2fcc1046 4c89442418 mov qword ptr [rsp+18h],r8
00007ff7`2fcc104b 4c894c2420 mov qword ptr [rsp+20h],r9
00007ff7`2fcc1050 4883ec68 sub rsp,68h
00007ff7`2fcc1054 660f7f442420 movdqa xmmword ptr [rsp+20h],xmm0
00007ff7`2fcc105a 660f7f4c2430 movdqa xmmword ptr [rsp+30h],xmm1
00007ff7`2fcc1060 660f7f542440 movdqa xmmword ptr [rsp+40h],xmm2
00007ff7`2fcc1066 660f7f5c2450 movdqa xmmword ptr [rsp+50h],xmm3
00007ff7`2fcc106c 488bd0 mov rdx,rax
00007ff7`2fcc106f 488d0df2570100 lea rcx,[main+0x16868 (00007ff7`2fcd6868)]
# This calls __delayLoadHelper2
00007ff7`2fcc1076 e8e1030000 call main+0x145c (00007ff7`2fcc145c)
00007ff7`2fcc107b 660f6f442420 movdqa xmm0,xmmword ptr [rsp+20h]
00007ff7`2fcc1081 660f6f4c2430 movdqa xmm1,xmmword ptr [rsp+30h]
00007ff7`2fcc1087 660f6f542440 movdqa xmm2,xmmword ptr [rsp+40h]
00007ff7`2fcc108d 660f6f5c2450 movdqa xmm3,xmmword ptr [rsp+50h]
00007ff7`2fcc1093 488b4c2470 mov rcx,qword ptr [rsp+70h]
00007ff7`2fcc1098 488b542478 mov rdx,qword ptr [rsp+78h]
00007ff7`2fcc109d 4c8b842480000000 mov r8,qword ptr [rsp+80h]
00007ff7`2fcc10a5 4c8b8c2488000000 mov r9,qword ptr [rsp+88h]
00007ff7`2fcc10ad 4883c468 add rsp,68h
00007ff7`2fcc10b1 eb00 jmp main+0x10b3 (00007ff7`2fcc10b3)
00007ff7`2fcc10b3 ffe0 jmp rax
00007ff7`2fcc10b5 cc int 3
00007ff7`2fcc10b6 cc int 3
00007ff7`2fcc10b7 cc int 3
# Displaying contents of the .pdata section (which is sorted)
0:000> dt ntdll!_IMAGE_RUNTIME_FUNCTION_ENTRY[4] main+0x1a000
[4] +0x000 BeginAddress : 0x1000
+0x004 EndAddress : 0x102a
+0x008 UnwindInfoAddress : 0x15cd0
+0x008 UnwindData : 0x15cd0
-> +0x000 BeginAddress : 0x103c
+0x004 EndAddress : 0x10b3
+0x008 UnwindInfoAddress : 0x15cd8
+0x008 UnwindData : 0x15cd8 <-
+0x000 BeginAddress : 0x10b8
+0x004 EndAddress : 0x1162
+0x008 UnwindInfoAddress : 0x15d18
+0x008 UnwindData : 0x15d18
+0x000 BeginAddress : 0x1164
+0x004 EndAddress : 0x1202
+0x008 UnwindInfoAddress : 0x15ce0
+0x008 UnwindData : 0x15ce0
[...]
# This is the unwind information for the tailMergeX64 function,
# stored in the .xdata section
0:000> db main+0x15cd8 L8
00007ff7`2fcd5cd8 01 18 01 00 18 c2 00 00
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzUWktz4ziS_jX0JcMKEnyIOvhgy6Udx7qqNma6undODhAAJXRBBBsALXl-_UaCpERJpGz3zuxD4ZBtEviQSOTzI6m1cl0JcRekD0H6eEMbt9Hm7u33Zq1uCs3f7v4ilNIBWQbhYxDet9_3FriwzMhCcCiE0ruALCHIQqX4rZLVz5nYiyALgXJuodLQVDtZcZBVqc2WOqkrKLWBIH1wG4ETHZXqqzBr8Z9ZghOZ5iJIHwOSb5yrbRDfB2QVkNVauk1TzJjeBmSl1Gv_67Y2-nfBXEBWhdJFQFZzRrIsifiCM0HnIZ2njCY5JyKmaVFmjM7pgqRF4QF4QFbL7ytc4fH5ecbqOiDxc7TIA7KA3UZU0FhZrce2uJNug9cDsuJC0TelKff_LkG8igrcRjfrDbiNtH5XICumGi4sUJzGqFIIIyvrTMNQNTO4t2AddYKjhmQFXyUz2urSAdes2YrKeR2OKUgJaqrZtp_QaUpUt40NyMpvbFU00u9Y7JmoEeh2QyuuZLW-3WdJQBaINjjuIP4Cv9BCiduCWsHhMA_6eWDEH400flMOR4KonHnzh0yVgrKp_NYsuA11eEkz6gTukv0EW1MmQBtAZQCttNsIc5gDAckRR-zptlYCFVvpSglaHmEDspihrmazWZA-wopK1RgBTgPXYDXspFJghG2UA1lBUxmhZCvn5V5oxYGLolmv8T9dQm00E9YKOxtq5Rc80a203jBGDJw1xojKqTfYUNy3gFIrpXetuqi63WmjOMhtTZmXCoespBGl3sNOFFAYvbOoCG3gN1lxvbPgz2fZmiStBtJLC4ZKPB1vkBSMcI2p0AONsBZqLSuHSzs95m_WaSM46FYKfywHI7jtjJdWUBu0aecHMUPtBoyotXEopdFbKES3O7YRHAUtBKONFUcLDsjcgqycMBVVvUOgRJXjrSd4C2n1iW6ATtGYS6sTxsKWvqHkNVA3silcvz1zFEpWGIhaoXmzrTtZmRGto5HcCoE2VDRriPIwigkBprfobRCNuVrRrP8hlaKzrW5_a7MOyMpu9O6laNYztpZBvJI8iB87vIDELEL_Qhd76LXrD3MnwOqt2Ogd2IYxITie1Fo4oAOhcUu6Md0VWlH19g9hYC0qYagTFtbUFHQtQFdMgHTdUdiPaGdDDb91-tYZiQh-CZx5qph5EoaL5L-rjg7Fa-LEqb7pHTy17lob_Sq5gK02ArhA8W1v3FZiKOhDQmsyRtRG84aJ1tmktY2YwW_H4I1XFWrJwfPzr1-HPgV1UyjJwAglqBXn8S8L259a74SxG6HUITAGhCxxeLr8D6PXhm5hJZWwQbrENYJ0WcgqSJdM0WrtUwYhcHv7KozFAO5R_D3oLkGUzsJZ1oUYatbCBfE97PPsJUtua3a7a6W-3dpX1gciIyiHreZC4dhaW7lvbz1V1lGlBH-UBm-9L-pp2P_g7k5y4uUGn58fT7Z10OdJONXobbX0xzmMlXW3sqycxpinC0z0UEo1eU4sIA_4014lcZdyIYiXnfpmG9zdYK6sHGyprAKSv2rJMe8H8w4B4Kuwlq7Fg97_FpD824_nZ3Sf54CQrjwiY_9_fXj5_u9DX4c-KoeHS8H88ZpS0HpRs-jLfaVxXoEcSpPzEuTjVgx_yoyZ15ivlj4LdG4xHkiD30FJG-WULIL4XsmCbd1MyeLiVmOFicnoLa8Eua2PN3ulHKbxw-Yn1D5VlGKipZwLjjkHDVVUHGuEro6dObF3PqGKtnhxuktX4KW4RTFktfa5sfEIxmNW2gG1VjPp09FEwewT8aEw6moGXLbm1FFcNyB5kIV__fHtl6evX15WP74tf3n6_s0bx8JXNjh6fzr6x7ffnr49vjx9W33vBnbSjxQ8WAUUAqOVLOWx2sBmoHZtIH46hO4gfcD9vVvI-3YjIKt212wj2E9h_LiLUvSaEddvbqMr8BmnK8xeWsgXVOSsfmvtDG2uDUztYUBA5ocbZI5nU_s8ADsqHdaUAwn-1h1se9Lx_WjppzH-wSKZhWFAUrSPNJpHBIo3d1ZFPmv9E0Uo-_J30AjY_oRralxrIh4Zm663kXXPJA33URKGIc9piXICgMgXYczLsizBf_yC3bAoS5KzeUXSzcuysMzKMCFJO2-rX_kfFGC_3fo6Yr_d7rThUDvf0xlb45GfgS1OwBJGkig8A4vGwSAgDyhmOIJanqCmCUnIOSq5ikqOqO33SjcVh2jkNNDWdePGTlxWB4_3hjHryxnXVSdY3LVxQlvhC9dCQEmVFT5fO_l6NIyxkPTd9K7mWxOwwvoES5bQhpAK65nHYv1hhyExeI-Wtotj2LB1Bie3WNUfmoe2pUMTHSbC9iSC-D4MQ3Q__keXQR-i-aIM4TnqhoRhOC_LLMhCWnLh78HpRc7zeT4u1zFswu_Ntu76oWtyNL0YCArP4T7qoLvL4d6v1utpRBJI8pyH6TyiEd4FUIKCofuALIP04QDTbjMg-cgOMXQdrPVihRLEIuw-8Pu2br3qKF6eXMJyvIywo2oa5qpjhkBVHRWIeeUs_Y0sAWkEdWM3KJJh-6lxKaQETj5-kuGTMzJIojS8mIHL5FNzcpwzkGcxNZDimcWCJXkPbpsCMBKRZZJvpqYJHzjm47FtJKaRpY9542iLuEMbDW7naOQhCjcHzFFfQcxFhzka2i4xyQCTTGGWPSYjSfw-ZjzAjCcwaYoHUPDB-W71qzcHskTXmZjW-RrPozk7-lpve2f-lqbxmL_h5aG_HXwDQ7iFlxfvApjs_yJULcyUXmg5niGHvolpcsQ3ffYkU9ZZJO-l0GsZ9AJt8V4OvWZtE5jlexn0mrWNY7K0xxwzs3gKM76KWXg_Z8nRzynnrb284-usxFiyOIk_up4OKTzC8fn5-KvxiseQ0uOwyVjIEziVpJNlMtzyFMpSnATPPm0cnAvN_lHaGpsfrCgbpYDpyonK2b5FaRuFQ60SkHy3kWyDWcRq4wQ_GvEgsTto2TkSvTx9vf-3Ly_n_cXLl2-__PXvQYoOQvIgfRw4DCa6TsCeoO27YfAj0OsfxFpW9125gR8s6zATRsX54AS-VHw49Dg4Ts4H5_DDF2tPVan7Oe3oKC3LfGr4IyppiD0Y3c15X_RLaa6InrBT3H-d4B_R-kGacdH7YfNJOf6M2BMCt9Eca1y70Y3iWDjTqqtX_fW2M56qgQKSD_fZy97WUofnWiTu-_Gx8l5U3Pq1PqrDj578Bw_9o8f9Dqch9rVgTvDDo5C2dtSVAF04Kits6HvKCWOIbzm-_u3Xpaftgywc8k7YGwlPqow2HMe-vJ8EsyBddkzPgNkZMDnnzM3jl-f7vz9_v38cYW6OD8UCkv81IAt4qpgR_umYgmdZ_RQGfu1Z1WQWx7M4yuJw1km21PWbkeuNn7_E-UfEpTa1Nm1TDXCvFPiRFhUnzKvg77RqB0rOE2a3TPU6a59I9UQnrXjL7nVckqVbAU5u_UMuqrpHh08BmW99928bI2C38aOlBa6FhabiojX_jdaTh3HZ_X2c7-vF72k6VtfXzgw39M7RjartqYJCuw0waoVFBYy12RZqPILKHZx-6uFx_IAq67rv49NXqqwGLstSGAtW4amqt_bhVe8KLb1XvI1wrZN8mBWiar3Fn6Nnw_6fU1ck_t-jrloOptL_FBJmwklRV7K6IFT-D9An4T7KaXTaZc6DLCQl43jjwJ50F1kUxuE_nT0J9wjr-ZPlGX_i1zvjT4aydPwJX8wXYXSFP_GbOTZTwz2O8CeDFeZX-ZMojNklLM5j_yL-ZLgEbn6BrVmYH_vgPy77nLztqc9r_iNUEnko7Mii8AiFnxG4A5lw3nUMADNIWL5IEDB_HzDvAfMpvKLFY33LeBXvwEycdVxHvDTsSJxshMTJzhq7wbSkp10-T5GMOhli0gGV80mKJJrAzMIBlZO8j5lMUjkDzGxA5aTvY6aTVM4Ak32CyhlMKzsqpyTp_Oj2ME7lZHmWj7g-Xv7zVM5RmHkGIhcYizynBKNUTpKOhokkZedUzgC46MmXMWOboHJGiZIjZh4NCJ0LY5skdEaIkgHmfEDoXBjbJKGTXMXkA0LnwtgmCZ30GuYi9saGO5-fxZDWakYiyfwqoGcUC9z2_CzItRY8BphfA-QY5Yo8IUnep5wDYj4OmF-TkKYtICNJnp8DLiYAr0lIeUeKZfkZGzYdNIsIRBFeEEqDHFrEozm0iKedo4hHWarpmFGkwBicfGTl_O-p6FRkOOXdUfP3gM_Ysv9poiw5JcnokCTz9z7A00SHSR-gmKKQ0M-wNYx_mHUYjm6_b9tXQd4TP75OM52KX8QfZ8gY_wxDxngOQby8_SRNFoXFxSrT8kcZ-Yz6efQxsuww7uNiR9l1YrIbRsJPCczEp-xFhOdin5LD5_X55AsxE6X7CbPXvd3adWft6y-9a186cTHwS28bz6MFMPf3IIwgyvE7DPEPRvCP8JyJu-F3MV_EC3oj7qJsHmVxGCXhzeYuJDFJFgnJo4iRPOZpXCZiMWcRi2mal-WNvCMhIREhURQnhISzmC8IyficJRktRESDJBRbKtVMqdftTJv1jX_18S5dZPHiRtFCKOtf7yekErv2vciAkCB9vDF3_t35olnbIAmVtM4eUZx0StwNCZCWcMJevn_BZ-RUdHXyYqU_pOEBeRZm-Er94P2sm8aou0-_8O93ZAOy8jv-rwAAAP__Tj9Hzw">