Skip to content

REG_SECRET_STUB_PARAM restore from stack #100301

Closed
@t-mustafin

Description

@t-mustafin

Currently during dynamicClass::IL_STUB_PInvoke methods holds StubSecretArg in caller-saved registers: x12 for arm64 and t2 for riscv64. Later this register value is used for CORINFO_HELP_INIT_PINVOKE_FRAME call as arg. But in the middle there are may appear some call which may trash this register. Check arm64 listing below for x12:

G_M9476_IG01:        ; offs=0x000000, size=0x005C, bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, nogc <-- Prolog IG
IN0060: 000000      stp     x19, x20, [sp, #-0x50]!
IN0061: 000004      stp     x21, x22, [sp, #0x10]
IN0062: 000008      stp     x23, x24, [sp, #0x20]
IN0063: 00000C      stp     x25, x26, [sp, #0x30]
IN0064: 000010      stp     x27, x28, [sp, #0x40]
IN0065: 000014      stp     fp, lr, [sp, #-0x1F0]!
IN0066: 000018      mov     fp, sp
IN0067: 00001C      str     x12, [fp, #0x60]    // [V06 tmp1]    // x12 has correct StubSecretArg value which is pMethodDesc
IN0068: 000020      movi    v16.16b, #0
IN0069: 000024      add     x9, fp, #184
IN006a: 000028      add     x10, fp, #408
IN006b: 00002C      stp     q16, q16, [x9, #-0x40]
IN006c: 000030      stp     q16, q16, [x9, #-0x20]
IN006d: 000034      bfm     x9, xzr, #0, #5
IN006e: 000038      dczva   x9
IN006f: 00003C      add     x9, x9, #64
IN0070: 000040      cmp     x9, x10
IN0071: 000044      blo     pc-16 (-4 instructions)
IN0072: 000048      stp     q16, q16, [x10]
IN0073: 00004C      stp     q16, q16, [x10, #0x20]
IN0074: 000050      add     x1, sp, #576
IN0075: 000054      str     x1, [fp, #0x1E8]    // [V10 PSPSym]
IN0076: 000058      str     x0, [fp, #0x1E0]    // [V00 arg0]
                        ;; size=92 bbWeight=1 PerfScore 19.50
G_M9476_IG02:        ; offs=0x00005C, size=0x0040, bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, BB09 [0008], BB01 [0000], byref
IN0001: 00005C      add     x0, fp, #128    // [V03 loc2]
IN0002: 000060      movn    w1, #50
IN0003: 000064      mov     x2, #296
recordRelocation: 0x7f6e000280 (rw: 0x7f6e000280) => 0x7fae164630, type 3 (IMAGE_REL_ARM64_BRANCH26), delta 0
IN0004: 000068      bl      CORINFO_HELP_MEMSET             // x12 is caller-saved register, so it may trashed inside.
                             ; gcr arg pop 0
IN0005: 00006C      add     x0, fp, #32 // [V09 PInvokeFrame+0x08]
IN0006: 000070      mov     x1, x12                 // correct x12 with StubSecretArg is used here, however need to restore value from stack because have calls `bl` before
recordRelocation: 0x7f6e00028c (rw: 0x7f6e00028c) => 0x7fadfcc6a4, type 3 (IMAGE_REL_ARM64_BRANCH26), delta 0
IN0007: 000074      bl      CORINFO_HELP_INIT_PINVOKE_FRAME 
IN0008: 000078      str     x0, [fp, #0x68] // [V08 FramesRoot]

For riscv64 assert appears with DOTNET_GCStress=0x1 on test JIT/SIMD/Vector3Interop_r/Vector3Interop_r.dll. Check t2 register and comments in asm:

(gdb) dism 0x0000003f78281dd0
Disassemble for  0x3f78281d20 ,+ 0x388   void [Vector3Interop_r] dynamicClass::IL_STUB_PInvoke(valuetype ComplexDT&)[MinOptJitted]
Dump of assembler code from 0x3f78281d20 to 0x3f782820a8:
   0x0000003f78281d20:  addi    sp,sp,-576
   0x0000003f78281d24:  sd      s0,0(sp)
   0x0000003f78281d28:  sd      ra,8(sp)
   0x0000003f78281d2c:  sd      s1,488(sp)
   0x0000003f78281d30:  sd      s2,496(sp)
   0x0000003f78281d34:  sd      s3,504(sp)
   0x0000003f78281d38:  sd      s4,512(sp)
   0x0000003f78281d3c:  sd      s5,520(sp)
   0x0000003f78281d40:  sd      s6,528(sp)
   0x0000003f78281d44:  sd      s7,536(sp)
   0x0000003f78281d48:  sd      s8,544(sp)
   0x0000003f78281d4c:  sd      s9,552(sp)
   0x0000003f78281d50:  sd      s10,560(sp)
   0x0000003f78281d54:  sd      s11,568(sp)
   0x0000003f78281d58:  mv      s0,sp
   0x0000003f78281d5c:  sd      t2,88(s0)             // t2 has correct StubSecretArg value which is pMethodDesc
   0x0000003f78281d60:  addi    s1,s0,112
   0x0000003f78281d64:  li      t0,22
   0x0000003f78281d68:  sd      zero,8(s1)
   0x0000003f78281d6c:  sd      zero,0(s1)
   0x0000003f78281d70:  addi    t0,t0,-1
   0x0000003f78281d74:  addi    s1,s1,16
   0x0000003f78281d78:  bnez    t0,0x3f78281d68
   0x0000003f78281d7c:  addi    s1,sp,576
   0x0000003f78281d80:  sd      s1,480(s0)
   0x0000003f78281d84:  sd      a0,472(s0)
   0x0000003f78281d88:  addi    a0,s0,120
   0x0000003f78281d8c:  li      a1,-51
   0x0000003f78281d90:  li      a2,296
   0x0000003f78281d94:  lui     t2,0x0               // t2 is used as tmp addr to call native JIT_MemSet
   0x0000003f78281d98:  addi    t2,t2,63 # 0x3f
   0x0000003f78281d9c:  slli    t2,t2,0xb
   0x0000003f78281da0:  addi    t2,t2,1978
   0x0000003f78281da4:  slli    t2,t2,0xb
   0x0000003f78281da8:  addi    t2,t2,1499
   0x0000003f78281dac:  slli    t2,t2,0xa
   0x0000003f78281db0:  jalr    968(t2)
   0x0000003f78281db4:  addi    a0,s0,24
   0x0000003f78281db8:  mv      a1,t2              // corrupted t2 is used like StubSecretArg, need to restore value from stack here, ld a1, 88(s0) instead mv
   0x0000003f78281dbc:  lui     a2,0x7fee6
   0x0000003f78281dc0:  addiw   a2,a2,196 # 0x7fee60c4
   0x0000003f78281dc4:  slli    a2,a2,0x7
   0x0000003f78281dc8:  addi    a2,a2,36
   0x0000003f78281dcc:  jalr    a2                     // JIT_InitPInvokeFrame called with trashed StubSecretArg arg, and trashed StubSecretArg get stored in pFrame 
   0x0000003f78281dd0:  sd      a0,96(s0)
   0x0000003f78281dd4:  mv      a0,sp
   0x0000003f78281dd8:  sd      a0,56(s0)
   0x0000003f78281ddc:  mv      a0,s0
   0x0000003f78281de0:  sd      a0,72(s0)
   0x0000003f78281de4:  ld      a0,96(s0)
   0x0000003f78281de8:  addi    a1,s0,24
   0x0000003f78281dec:  sd      a1,16(a0)
   0x0000003f78281df0:  sw      zero,468(s0)
   0x0000003f78281df4:  nop
   0x0000003f78281df8:  ld      a0,472(s0)
   0x0000003f78281dfc:  ld      a1,0(a0)
   0x0000003f78281e00:  ld      ra,8(a0)
   0x0000003f78281e04:  sd      a1,416(s0)
   0x0000003f78281e08:  sd      ra,424(s0)
   0x0000003f78281e0c:  ld      a1,16(a0)
   0x0000003f78281e10:  ld      ra,24(a0)
   0x0000003f78281e14:  sd      a1,432(s0)
   0x0000003f78281e18:  sd      ra,440(s0)
   0x0000003f78281e1c:  ld      a1,32(a0)
   0x0000003f78281e20:  ld      ra,40(a0)
   0x0000003f78281e24:  sd      a1,448(s0)
   0x0000003f78281e28:  sd      ra,456(s0)
   0x0000003f78281e2c:  addi    a0,s0,416
   0x0000003f78281e30:  addi    a1,s0,120
   0x0000003f78281e34:  addi    a3,s0,112
   0x0000003f78281e38:  li      a2,0
   0x0000003f78281e3c:  lui     a4,0x7ef0d
   0x0000003f78281e40:  addiw   a4,a4,1895 # 0x7ef0d767
   0x0000003f78281e44:  slli    a4,a4,0x7
   0x0000003f78281e48:  mv      a4,a4
   0x0000003f78281e4c:  jalr    a4                       // call ThePreStub, StackFrameIterator::CheckForSkippedFrames and m_crawl.pFunc->SanityCheck() inside. trashed StubSecretArg dereference leads to assert.
   0x0000003f78281e50:  li      a0,1
...

Should StubSecretArg restored from the stack before JIT_InitPInvokeFrame for all architectures?
cc @jkotas @jakobbotsch @dotnet/samsung

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions