<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">