4ad/go.arm64

liblink: in newproc1, fn is in the wrong place on the stack

4ad opened this issue · 1 comments

4ad commented

Very strange, programs crash with:

: xgene:1; 7.out
fatal error: go of nil func value

runtime stack:
runtime.throw(0x7, 0x8)
    /home/aram/go/src/runtime/panic.go:508 +0xf0
: xgene:1;

So we attach gdb:

runtime.newproc1 (fn=0xb5d50 <runtime.g0>, argp=0x7ffffff488 "", narg=-3233, 
    nret=127, callerpc=10, ~r5=0x86ae0)
    at /home/aram/go/src/runtime/proc1.go:1943
1943        if fn == nil {
(gdb) disas
Dump of assembler code for function runtime.newproc1:
   0x0000000000042b70 <+0>: str x30, [sp,#-160]!
   0x0000000000042b74 <+4>: mov x7, #0x0                    // #0
   0x0000000000042b78 <+8>: bl  0x663b0 <runtime.getg>
   0x0000000000042b7c <+12>:    ldr x7, [sp,#8]
   0x0000000000042b80 <+16>:    str x7, [sp,#104]
   0x0000000000042b84 <+20>:    ldr x7, [sp,#104]
   0x0000000000042b88 <+24>:    str x7, [sp,#120]
=> 0x0000000000042b8c <+28>:    ldr x7, [sp,#168]
   0x0000000000042b90 <+32>:    mov x8, #0x0                    // #0
   0x0000000000042b94 <+36>:    cmp x7, x8
   0x0000000000042b98 <+40>:    b.ne    0x42bcc <runtime.newproc1+92>
   0x0000000000042b9c <+44>:    ldr x7, 0x43160 <runtime.newproc1+1520>
   0x0000000000042ba0 <+48>:    mov x7, x7
   0x0000000000042ba4 <+52>:    mov x8, x7
   0x0000000000042ba8 <+56>:    add x7, sp, #0x8
   0x0000000000042bac <+60>:    mov x7, x7
   0x0000000000042bb0 <+64>:    sub x8, x8, #0x8
   0x0000000000042bb4 <+68>:    sub x7, x7, #0x8
   0x0000000000042bb8 <+72>:    ldr x9, [x8,#8]!
   0x0000000000042bbc <+76>:    str x9, [x7,#8]!
   0x0000000000042bc0 <+80>:    ldr x9, [x8,#8]!
   0x0000000000042bc4 <+84>:    str x9, [x7,#8]!
   0x0000000000042bc8 <+88>:    bl  0x38850 <runtime.throw>
(gdb) si
0x0000000000042b90  1943        if fn == nil {
(gdb) p $x7
$3 = 0
(gdb) x/xg $sp+168
0x7ffffff598:   0x0000000000000000
(gdb) x/xg $sp+8
0x7ffffff4f8:   0x00000000000b5d50
(gdb) p fn
$4 = (struct runtime.funcval *) 0xb5d50 <runtime.g0>
(gdb) 

Very strange, gdb says fn is not nil. If we look at the code closely, we see fn is at 168(R31); the code looks correct. But there's nothing there, instead, fn is at 8(R31). How did it get there, and more importantly, hoes does gdb know it's there?

(gdb) p &fn
$5 = (struct runtime.funcval **) 0x7ffffff4f8

Yep, gdb knows fn is at 8(R31).

I have no idea what is going on, but I observe that the delta between expected stack offset and real stack offset is exactly equal with the frame size (160 bytes).

4ad commented

Michael did all the job, thanks.