runtime/arm64: use ABIInternal convention in cgocallbackg

This change follows from CL 765581.

As expected, the program panics when an unpinned pointed is passed from Go to C.

The stack trace showing an autogenerated frame by the linker.

    # cat -n main.c
         1  #include <stdio.h>
         2  #include "parse.h"
         3
         4  int main(void) {
         5          GoMap m = GoFoo();
         6          (void)m;
         7          return 0;
         8  }

    # cat -n callbackErr.go
         1  package main
         2
         3  import (
         4          "C"
         5  )
         6
         7  //export GoFoo
         8  func GoFoo() map[int]int {
         9          return map[int]int{0: 1,}
        10  }
        11
        12  func main() {
        13  }

    # GOOS=linux GOARCH=arm64 CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc go build -buildmode=c-shared -o callbackErr.so callbackErr.go
    # aarch64-linux-gnu-gcc -o main main.c callbackErr.so -Wl,-rpath,'$ORIGIN'
    # qemu-aarch64-static -L /usr/aarch64-linux-gnu ./main
    [...]
    goroutine 17 [running, locked to thread]:
    panic({0x74edf75f1300?, 0x2e980159a010?})
            /usr/lib/go/src/runtime/panic.go:879 +0x15c
    runtime.cgoCheckArg(0x74edf75f2580, 0x2e9801598060, 0x0?, 0x0, 0x1)
            /usr/lib/go/src/runtime/cgocall.go:659 +0x45c
    runtime.cgoCheckResult({0x74edf75f2580, 0x2e9801598060})
            /usr/lib/go/src/runtime/cgocall.go:829 +0x48
    _cgoexp_35a35dd190e3_GoFoo(0x74edf7e9fb78)
            /mnt/tmp/callbackErr.go:8 +0x7c
    runtime.cgocallbackg1(0x74edf75535a0, 0x74edf7e9fb78, 0x0)
            /usr/lib/go/src/runtime/cgocall.go:466 +0x2a8
    runtime.cgocallbackg(0x74edf75535a0, 0x74edf7e9fb78, 0x0)
            /usr/lib/go/src/runtime/cgocall.go:362 +0x104
    runtime.cgocallbackg(0x74edf75535a0, 0x74edf7e9fb78, 0x0)
            <autogenerated>:1 +0x1c
    runtime.cgocallback(0x0, 0x0, 0x0)
            /usr/lib/go/src/runtime/asm_arm64.s:1359 +0xb0
    runtime.goexit({})
            /usr/lib/go/src/runtime/asm_arm64.s:1447 +0x4
    qemu: uncaught target signal 6 (Aborted) - core dumped
    Aborted                    (core dumped) qemu-aarch64-static -L /usr/aarch64-linux-gnu ./main

Load the cgocallbackg arguments into the registers expected by ABIInternal.

Restore BP after switching back to curg.

    [...]
    goroutine 17 [running, locked to thread]:
    panic({0x7be74abd6d38?, 0x7561e2902030?})
            /mnt/go/src/runtime/panic.go:878 +0x150
    runtime.cgoCheckArg(0x7be74abd15e8, 0x7561e2928060, 0x0?, 0x0, 0x1)
            /mnt/go/src/runtime/cgocall.go:667 +0x460
    runtime.cgoCheckResult({0x7be74abd15e8, 0x7561e2928060})
            /mnt/go/src/runtime/cgocall.go:837 +0x48
    _cgoexp_187a5a3ff50c_GoFoo(0x7be74bc7fbb8)
            /mnt/tmp/callbackErr.go:6 +0x7c
    runtime.cgocallbackg1(0x7be74ab32fd0, 0x7be74bc7fbb8, 0x0)
            /mnt/go/src/runtime/cgocall.go:474 +0x2bc
    runtime.cgocallbackg(0x7be74ab32fd0, 0x7be74bc7fbb8, 0x0)
            /mnt/go/src/runtime/cgocall.go:362 +0x100
    runtime.cgocallback(0x0, 0x0, 0x0)
            /mnt/go/src/runtime/asm_arm64.s:1334 +0xa4
    runtime.goexit({})
            /mnt/go/src/runtime/asm_arm64.s:1424 +0x4
    qemu: uncaught target signal 6 (Aborted) - core dumped
    Aborted                    (core dumped) qemu-aarch64-static -L /usr/aarch64-linux-gnu ./main

Change-Id: I959a756a8bde3baa94b19c1634fc2b46d8eea07d
GitHub-Last-Rev: 221ee88762
GitHub-Pull-Request: golang/go#78850
Reviewed-on: https://go-review.googlesource.com/c/go/+/768780
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
Ariel Otilibili 2026-04-23 00:06:03 +00:00 committed by Gopher Robot
parent 2bb808bfc2
commit d44e4e062b

View file

@ -1320,23 +1320,24 @@ havem:
MOVD (g_sched+gobuf_sp)(g), R4 // prepare stack as R4
MOVD (g_sched+gobuf_pc)(g), R5
MOVD R5, -48(R4)
MOVD (g_sched+gobuf_bp)(g), R5
MOVD R5, -56(R4)
MOVD (g_sched+gobuf_bp)(g), R6
MOVD R6, -56(R4)
// Gather our arguments into registers.
MOVD fn+0(FP), R1
MOVD frame+8(FP), R2
MOVD ctxt+16(FP), R3
MOVD $-48(R4), R0 // maintain 16-byte SP alignment
MOVD R0, RSP // switch stack
MOVD R1, 8(RSP)
MOVD R2, 16(RSP)
MOVD R3, 24(RSP)
MOVD $runtime·cgocallbackg(SB), R0
CALL (R0) // indirect call to bypass nosplit check. We're on a different stack now.
MOVD fn+0(FP), R0
MOVD frame+8(FP), R1
MOVD ctxt+16(FP), R2
SUB $48, R4 // Allocate the same frame size on the g stack
MOVD R4, RSP // switch stack
MOVD $runtime·cgocallbackg<ABIInternal>(SB), R11
CALL (R11) // indirect call to bypass nosplit check. We're on a different stack now.
// Restore g->sched (== m->curg->sched) from saved values.
MOVD 0(RSP), R5
MOVD R5, (g_sched+gobuf_pc)(g)
MOVD -8(RSP), R6
MOVD R6, (g_sched+gobuf_bp)(g)
MOVD RSP, R4
ADD $48, R4, R4
MOVD R4, (g_sched+gobuf_sp)(g)