<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/54879>54879</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
SEH for Windows aarch64: invalid Packed unwind data detection with H=1
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
egelke
</td>
</tr>
</table>
<pre>
There is an issue with the the detection of "packed unwind data" when compiling aaarch64 asm with SEH directives on Windows, e.g.:
```
clang -g -c -target aarch64-pc-windows-msvc -o obj\main.obj main.asm
link /OUT:bin\program.exe "kernel32.lib" /DEBUG /MACHINE:ARM64 /SUBSYSTEM:CONSOLE /NOLOGO /NODEFAULTLIB /ENTRY:"_start" obj\main.obj
```
Everything works fine as long as you don't home the integer parameter registers. The below example results in a correctly packed unwind data.
```asm
.global func
func:
.seh_proc func
stp x19, x20,[sp,#-0x10]!
.seh_save_regp_x x19, 0x10
stp fp, lr, [sp, #-0x10]!
.seh_save_fplr_x 0x10
mov fp, sp
.seh_set_fp
.seh_endprologue
//return success
mov w0, wzr
.seh_startepilogue
ldp fp, lr, [sp], #0x10
.seh_save_fplr_x 0x10
ldp x19, x20, [sp], #0x10
.seh_save_regp_x x19, 0x10
.seh_endepilogue
ret
.seh_endfunclet
.seh_endproc
```
```
c:\> dumpbin /UNWINDINFO bin\program.exe
Begin Packed Function Name
00000010 00001038 Y func
Start=40001038 Flag=1 FuncLen=1C RegF=0 RegI=2 H=0 CR=3 FrameSize=0x20
[RawPdata=00001038 0162001D]
+0000 stp x19,x20,[sp,#-0x10]!; Actual=stp x19,x20,[sp,#-0x10]!
+0004 stp fp,lr,[sp,#-0x10]! ; Actual=stp fp,lr,[sp,#-0x10]!
+0008 mov fp,sp ; Actual=mov fp,sp
Epilog #1 unwind: (Offset=10)
+0010 ldp fp,lr,[sp],#0x10 ; Actual=ldp fp,lr,[sp],#0x10
+0014 ldp x19,x20,[sp],#0x10 ; Actual=ldp x19,x20,[sp],#0x10
+0018 ret ; Actual=ret
```
However, when you home the integer parameter registers, i.e. try to generate packed unwind data with H=1, it fails recognize that it's a packed format and generates an unpacked version instead:
```asm
.global func
func:
.seh_proc func
stp x19, x20,[sp,#-0x50]!
.seh_save_regp_x x19, 0x50
stp x0, x1, [sp, #0x10]
.seh_nop
stp x2, x3, [sp, #0x20]
.seh_nop
stp x4, x5, [sp, #0x30]
.seh_nop
stp x6, x7, [sp, #0x40]
.seh_nop
stp fp, lr, [sp, #-0x10]!
.seh_save_fplr_x 0x10
mov fp, sp
.seh_set_fp
.seh_endprologue
//return success
mov w0, wzr
.seh_startepilogue
ldp fp, lr, [sp], #0x10
.seh_save_fplr_x 0x10
ldp x19, x20, [sp], #0x50
.seh_save_regp_x x19, 0x50
.seh_endepilogue
ret
.seh_endfunclet
.seh_endproc
```
```
c:\> dumpbin /UNWINDINFO bin\program.exe
Begin Packed Function Name
00000010 00001038 N func
Start=40001038 Xdata=400032E8
[RawPdata=00001038 000032E8]
FuncLen=2C Vers=0 X=0 E=0 Epilogs=1 CodeWords=3
Prolog unwind:
06: 2A...... +0000 stp x19,x20,[sp,#-0x50]!; Actual=stp x19,x20,[sp,#-0x50]!
05: E3...... +0004 nop ; Actual=stp x0,x1,[sp,#0x10]
04: E3...... +0008 nop ; Actual=stp x2,x3,[sp,#0x20]
03: E3...... +000C nop ; Actual=stp x4,x5,[sp,#0x30]
02: E3...... +0010 nop ; Actual=stp x6,x7,[sp,#0x40]
01: 81...... +0014 stp fp,lr,[sp,#-0x10]! ; Actual=stp fp,lr,[sp,#-0x10]!
00: E1...... +0018 mov fp,sp ; Actual=mov fp,sp
+001C (end sequence)
Epilog #1 unwind: (Offset=10 Index=8)
08: 81...... +0020 ldp fp,lr,[sp],#0x10 ; Actual=ldp fp,lr,[sp],#0x10
09: 2A...... +0024 ldp x19,x20,[sp],#0x50 ; Actual=ldp x19,x20,[sp],#0x50
0A: E4...... +0028 end ; Actual=ret
+0030 (end sequence)
[RawXdata=1840000B 02000008 E3E381E1 E42AE3E3 E3E42A81]
```
If you however, repeat the "nop" seh directives with instructions into the unwind code, then you get an __incorrect__ packed unwind data as shows by the following example:
```asm
.global func
func:
.seh_proc func
stp x19, x20,[sp,#-0x50]!
.seh_save_regp_x x19, 0x50
stp x0, x1, [sp, #0x10]
.seh_nop
stp x2, x3, [sp, #0x20]
.seh_nop
stp x4, x5, [sp, #0x30]
.seh_nop
stp x6, x7, [sp, #0x40]
.seh_nop
stp fp, lr, [sp, #-0x10]!
.seh_save_fplr_x 0x10
mov fp, sp
.seh_set_fp
.seh_endprologue
//return success
mov w0, wzr
.seh_startepilogue
ldp fp, lr, [sp], #0x10
.seh_save_fplr_x 0x10
ldp x6, x7, [sp, 0x40]
.seh_nop
ldp x4, x5, [sp, 0x30]
.seh_nop
ldp x2, x3, [sp, 0x20]
.seh_nop
ldp x0, x1, [sp, 0x10]
.seh_nop
ldp x19, x20, [sp], #0x50
.seh_save_regp_x x19, 0x50
.seh_endepilogue
ret
.seh_endfunclet
.seh_endproc
```
```
00000010 00001038 Y func
Start=40001038 Flag=1 FuncLen=3C RegF=0 RegI=2 H=1 CR=3 FrameSize=0x60
[RawPdata=00001038 0372003D]
+0000 stp x19,x20,[sp,#-0x50]!; Actual=stp x19,x20,[sp,#-0x50]!
+0004 stp x0,x1,[sp,#0x10] ; Actual=stp x0,x1,[sp,#0x10]
+0008 stp x2,x3,[sp,#0x20] ; Actual=stp x2,x3,[sp,#0x20]
**** Expected opcode A90207E0
+000C stp x4,x5,[sp,#0x30] ; Actual=stp x4,x5,[sp,#0x30]
**** Expected opcode A90307E0
+0010 stp x6,x7,[sp,#0x40] ; Actual=stp x6,x7,[sp,#0x40]
**** Expected opcode A90407E0
+0014 stp fp,lr,[sp,#-0x10]! ; Actual=stp fp,lr,[sp,#-0x10]!
+0018 mov fp,sp ; Actual=mov fp,sp
Epilog #1 unwind: (Offset=30)
+0030 ldp fp,lr,[sp],#0x10 ; Actual=ldp x0,x1,[sp,#0x10]
**** Expected opcode A8C17BFD
+0034 ldp x19,x20,[sp],#0x50 ; Actual=ldp x19,x20,[sp],#0x50
+0038 ret ; Actual=ret
```
(please ignore the bug in MS dumpbin.exe, the opcode is correct it's just the check that is wrong since it expect x0 and x1 instead of x2 and x3)
Obviously, a NOP should _not_ be repeated in the unwind code. Instead, when clang encounters a .seh_nop directive in the prologue it should not expect any matching instruction in the epilogue in order for it to to generate a _packed_ unwind data.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJztWltzo7gS_jXOS1dcIMDBD36wHbKTqow9lcuZnSeXDDJmgsEHQezsr99uATEYgn0ys7t1aodKjBDqi9St7o-GZey9jh7XIhEQSOAR_spMwC5I15Cuhfr3RCrcNIgjiFfQY2zL3WfhQRbtgsgDj6ccO2G3FhG48WYbhEHkA-c8cdcDE7jc5OwenE_gBQmxehESkN1XpI93ssemIPp-v2eMe9p1Txv3Blrxpy7dkCPDSx_g0oXLlCe-SKFgf7l1L3c5m8uNfMH7McTL7z1ruuFB1McmqAZqkTND5Z5xEjfzp0eUtwwiHLpNYj_hm77YC5rfs0giERqsHwZLmhmOvnYmT79R4_N4-ul25iDp-P4zzg67Hp4mD98eHp3P2Dmdzx7mdw51z-Z389_meevauRk_3T3e3U7o2pk93n-jyTK2kDidlITUlW5dh_zXeRHJa7qmNd7FybOEVRAJXGUIY1p2Ca9xBl4c9dhVCut4k9swiFLhiwS2HCeK9kwgEX4gsSH7AOgAsBRhvAOx55ttKPCuzMJUIh1wtGpCZgtfoWn6fq4VHGn8tt5AR98P4yUPYZVFbt6tWqW91RAp1gs0hFsZRP0y3cJeH5KP7JmGp541kVs6M-NS2-taz7ruMf2IkeQvYoEz3C72JbUaW2O7IjYQJvRbcoXTbFfbMEG2dX6b-KXgh2yOiESKNEedIvJwsmHsZ6JqXLqPHoJ_iUizJAKZua6Qsi5oR-sAuz-SY9JcHrmUwG14YE73Qq9txjRLNen6dE7MlnjVjHIuty6TlOtSV_1wH1ekOZicJWy7Qa7UsYuOQwz5ojXtGQ542WaLYYHM8DT7eju7vp3dzKERKCrenR8T3E8RNb7kewRuUDUVNWe44-qT0dSha5CfDJvovik2Ne9_UNHBuDbfht2E3McOPWd_JyK6mALcC_8Gm5pq3WKLAXzKO6b3eDaQgHb-Q_CHoG4yW2UGaL57vvuiYjneLcVp-oBh85oMWx3NJjREbaLClp1705jA2E0zHiJvRVMcZ5A2pJq5VOXJypHbCXH4e1JPkTZl2mrX5YTywKgYUpWjxlXlVKKBo_yadodeBFB0OhJhz1crDBJkSVyJYUM--gltuIbiarcVm62hiaJ4Z8ZVwqY0M5fWNE5d3rvSugmb8mza2dB61GS87f_WDf0p3gnMjCowEhKhLHhO9iOCoC_6kCavkMbgi0gkPBUtqS6HMbSrdEWVwooHoURebuxHuLFQFk-xH1MvYqmSwypONtjNkUvJXCGtLCoGoNqS4kQQoUbcO8CgfyalWv9DSrWOUupeJYO9fpxSy91VZxnF2yNypsiNJjk7i9xU5FaT3DiLfKDIr5rk5jnkv-DEXwgnrLPgRGPUvxhOzPLQ3w0nfi8yPvUYzLHPwQTl0MqOOGARNAP8h8Kqgh6_5yenOClLyBy-TGNPfI0Tjy6NN0ZflBMf0mNVH21A-ZKN--qog5AOKGF9HIU0IyFqYZEWjlHTwgSMBmeksJpYkqciZUVoI06iQLNFoP0RgRRcVWytCWQNgUaLwOlHBFI4VtG4JtBoCGRNgejMHxBIAVzF75pAsyFQJ4G2XhNYAMvTyPKnAEtNU3Ouq1DgzHageTbObCyX4k1x1MZABlL8NxORK6pI8yxoCnCL0XSPbfsIpWp2cz1ZAVpPodYfBq3asBkWWIFhO7GopX0Mw1p18WNlSLMm3gZa6dPOW8tBbWYztC6z5RG6jOG6TVFcm-B-UvnAxi3lGLbu6KgeG9MF9WDT1t82RGs2u10V8PkNUidiKxDDEpbuMUbQhzFUaV0t6Cl0TBg2yVSiouIRAmqiKUC0izGfuKUlQFeFvAgWiyAqakyLRRvw5hIkaiNh-QqK4SoOw3hHNbCiYPULNP8Czf9C0Ny2-GesvKJts_sZRle0bS53hr8p2jZvP8PV_68fEuqXP7sAaHQUAPX3CoCDWhp7D-wbV5hMjA8WAH8y9K4VALvgcyPPfgR3l0A7l9aBnbulnQTdPXb4A2e_xSSI2S_eUrKE8RCT-ZXTrJohIM8V68DY3YqdBOenFDNaFdNLr-jA4t2KnQTxpxQz2xX7ByrH-t9WOTZaK8fGj1aOT2-WbmPYU_1qctPcV8YZRWbro0Vmq2l844eLzMxGlMmlgMCP4iQvKy8zn16Qfn4oqzyqkpMD3HIJAlm-Pi0Lw98zmSNpdy3c56JmjPA5ofe3EpGwoNKyUEuJBlCF471eVofpHfye5Z3Gm83z3_nyJYgzGb6SDhxm8y8Em7PQA0yl6QKWogDyaCHU-wiZ9-kBL69Al0X0_M07PnbEWUTFcmRaJuYD8i9ZlViKtC_EotRyIjx6hQ1PXfXiuvKUUFKXGZiu48QTCdXNiRU9QlTK8hwW-QPCovYW-sIbGd7QGPKLNEhDMaKPDYhB8YlB-bkA7ZsgeuFh4JWFtepzxuFLh0Op_yJLwtE6TbdSvbInXOjjzWzZd-MNXoThS3m6xCX4jgzwUn1GIbFhmfbV8GI9Yjq7GmjD5cq0uGkPTW9ge7a1MrTh0GWDgXkR8qUI5QidmZ6wxC7_EgPb6NkXwYhpjGmmzpDPQDf72koXpmu6g5XBdM1a9UxNbHgQ9kmPfpz4F8lIqYQ-KvFmGMhUHm5yKdGPhVDikD_P0nWcjIQvwmdxoSSPlOZ_ArA6Hvk">