Skip to content

Commit 872d718

Browse files
committed
runtime/cgo: avoid taking the address of crosscall2 in code
Currently, set_crosscall2 takes the address of crosscall2 without using the GOT, which, on some architectures, results in a PC-relative relocation (e.g. R_AARCH64_ADR_PREL_PG_HI21 on ARM64) to the crosscall2 symbol. But crosscall2 is dynamically exported, so the C linker thinks it may bind to a symbol from a different DSO. Some C linker may not like a PC-relative relocation to such a symbol. Using a local trampoline to avoid taking the address of a dynamically exported symbol. It may be possible to not dynamically export crosscall2. But this CL is safer for backport. Later we may remove the trampolines after unexport crosscall2, if they are not needed. Fixes #62556. Change-Id: Id28457f65ef121d3f87d8189803abc65ed453283 Reviewed-on: https://go-review.googlesource.com/c/go/+/533535 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 3b0fc5a commit 872d718

11 files changed

Lines changed: 92 additions & 10 deletions

File tree

src/cmd/cgo/internal/testcarchive/carchive_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,3 +1365,35 @@ func TestDeepStack(t *testing.T) {
13651365
t.Error(err)
13661366
}
13671367
}
1368+
1369+
func TestSharedObject(t *testing.T) {
1370+
// Test that we can put a Go c-archive into a C shared object.
1371+
globalSkip(t)
1372+
testenv.MustHaveGoBuild(t)
1373+
testenv.MustHaveCGO(t)
1374+
testenv.MustHaveBuildMode(t, "c-archive")
1375+
1376+
t.Parallel()
1377+
1378+
if !testWork {
1379+
defer func() {
1380+
os.Remove("libgo_s.a")
1381+
os.Remove("libgo_s.h")
1382+
os.Remove("libgo_s.so")
1383+
}()
1384+
}
1385+
1386+
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo_s.a", "./libgo")
1387+
out, err := cmd.CombinedOutput()
1388+
t.Logf("%v\n%s", cmd.Args, out)
1389+
if err != nil {
1390+
t.Fatal(err)
1391+
}
1392+
1393+
ccArgs := append(cc, "-shared", "-o", "libgo_s.so", "libgo_s.a")
1394+
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
1395+
t.Logf("%v\n%s", ccArgs, out)
1396+
if err != nil {
1397+
t.Fatal(err)
1398+
}
1399+
}

src/runtime/cgo/asm_386.s

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66

77
// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
88
// It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2
9+
// Use a local trampoline, to avoid taking the address of a dynamically exported
10+
// function.
911
TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
1012
MOVL _crosscall2_ptr(SB), AX
11-
MOVL $crosscall2(SB), BX
13+
MOVL $crosscall2_trampoline<>(SB), BX
1214
MOVL BX, (AX)
1315
RET
1416

17+
TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
18+
JMP crosscall2(SB)
19+
1520
// Called by C code generated by cmd/cgo.
1621
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
1722
// Saves C callee-saved registers and calls cgocallback with three arguments.

src/runtime/cgo/asm_amd64.s

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@
77

88
// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
99
// It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2
10+
// Use a local trampoline, to avoid taking the address of a dynamically exported
11+
// function.
1012
TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
1113
MOVQ _crosscall2_ptr(SB), AX
12-
MOVQ $crosscall2(SB), BX
14+
MOVQ $crosscall2_trampoline<>(SB), BX
1315
MOVQ BX, (AX)
1416
RET
1517

18+
TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
19+
JMP crosscall2(SB)
20+
1621
// Called by C code generated by cmd/cgo.
1722
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
1823
// Saves C callee-saved registers and calls cgocallback with three arguments.

src/runtime/cgo/asm_arm.s

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66

77
// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
88
// It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2
9+
// Use a local trampoline, to avoid taking the address of a dynamically exported
10+
// function.
911
TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
1012
MOVW _crosscall2_ptr(SB), R1
11-
MOVW $crosscall2(SB), R2
13+
MOVW $crosscall2_trampoline<>(SB), R2
1214
MOVW R2, (R1)
1315
RET
1416

17+
TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
18+
JMP crosscall2(SB)
19+
1520
// Called by C code generated by cmd/cgo.
1621
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
1722
// Saves C callee-saved registers and calls cgocallback with three arguments.

src/runtime/cgo/asm_arm64.s

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@
77

88
// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
99
// It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2
10+
// Use a local trampoline, to avoid taking the address of a dynamically exported
11+
// function.
1012
TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
1113
MOVD _crosscall2_ptr(SB), R1
12-
MOVD $crosscall2(SB), R2
14+
MOVD $crosscall2_trampoline<>(SB), R2
1315
MOVD R2, (R1)
1416
RET
1517

18+
TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
19+
JMP crosscall2(SB)
20+
1621
// Called by C code generated by cmd/cgo.
1722
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
1823
// Saves C callee-saved registers and calls cgocallback with three arguments.

src/runtime/cgo/asm_loong64.s

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@
77

88
// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
99
// It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2
10+
// Use a local trampoline, to avoid taking the address of a dynamically exported
11+
// function.
1012
TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
1113
MOVV _crosscall2_ptr(SB), R5
12-
MOVV $crosscall2(SB), R6
14+
MOVV $crosscall2_trampoline<>(SB), R6
1315
MOVV R6, (R5)
1416
RET
1517

18+
TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
19+
JMP crosscall2(SB)
20+
1621
// Called by C code generated by cmd/cgo.
1722
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
1823
// Saves C callee-saved registers and calls cgocallback with three arguments.

src/runtime/cgo/asm_mips64x.s

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@
88

99
// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
1010
// It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2
11+
// Use a local trampoline, to avoid taking the address of a dynamically exported
12+
// function.
1113
TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
1214
MOVV _crosscall2_ptr(SB), R5
13-
MOVV $crosscall2(SB), R6
15+
MOVV $crosscall2_trampoline<>(SB), R6
1416
MOVV R6, (R5)
1517
RET
1618

19+
TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
20+
JMP crosscall2(SB)
21+
1722
// Called by C code generated by cmd/cgo.
1823
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
1924
// Saves C callee-saved registers and calls cgocallback with three arguments.

src/runtime/cgo/asm_mipsx.s

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@
88

99
// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
1010
// It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2
11+
// Use a local trampoline, to avoid taking the address of a dynamically exported
12+
// function.
1113
TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
1214
MOVW _crosscall2_ptr(SB), R5
13-
MOVW $crosscall2(SB), R6
15+
MOVW $crosscall2_trampoline<>(SB), R6
1416
MOVW R6, (R5)
1517
RET
1618

19+
TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
20+
JMP crosscall2(SB)
21+
1722
// Called by C code generated by cmd/cgo.
1823
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
1924
// Saves C callee-saved registers and calls cgocallback with three arguments.

src/runtime/cgo/asm_ppc64x.s

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
DEFINE_PPC64X_FUNCDESC(_crosscall2<>, crosscall2)
1717
#define CROSSCALL2_FPTR $_crosscall2<>(SB)
1818
#else
19-
#define CROSSCALL2_FPTR $crosscall2(SB)
19+
// Use a local trampoline, to avoid taking the address of a dynamically exported
20+
// function.
21+
#define CROSSCALL2_FPTR $crosscall2_trampoline<>(SB)
2022
#endif
2123

2224
// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
@@ -27,6 +29,9 @@ TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
2729
MOVD R6, (R5)
2830
RET
2931

32+
TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
33+
JMP crosscall2(SB)
34+
3035
// Called by C code generated by cmd/cgo.
3136
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
3237
// Saves C callee-saved registers and calls cgocallback with three arguments.

src/runtime/cgo/asm_riscv64.s

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66

77
// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
88
// It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2
9+
// Use a local trampoline, to avoid taking the address of a dynamically exported
10+
// function.
911
TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
1012
MOV _crosscall2_ptr(SB), X7
11-
MOV $crosscall2(SB), X8
13+
MOV $crosscall2_trampoline<>(SB), X8
1214
MOV X8, (X7)
1315
RET
1416

17+
TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
18+
JMP crosscall2(SB)
19+
1520
// Called by C code generated by cmd/cgo.
1621
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
1722
// Saves C callee-saved registers and calls cgocallback with three arguments.

0 commit comments

Comments
 (0)