src/cmd/cgo/internal/testcarchive/carchive_test.go | 32 ++++++++++++++++++++++++++++++++ src/runtime/cgo/asm_386.s | 7 ++++++- src/runtime/cgo/asm_amd64.s | 7 ++++++- src/runtime/cgo/asm_arm.s | 7 ++++++- src/runtime/cgo/asm_arm64.s | 7 ++++++- src/runtime/cgo/asm_loong64.s | 7 ++++++- src/runtime/cgo/asm_mips64x.s | 7 ++++++- src/runtime/cgo/asm_mipsx.s | 7 ++++++- src/runtime/cgo/asm_ppc64x.s | 7 ++++++- src/runtime/cgo/asm_riscv64.s | 7 ++++++- src/runtime/cgo/asm_s390x.s | 7 ++++++- diff --git a/src/cmd/cgo/internal/testcarchive/carchive_test.go b/src/cmd/cgo/internal/testcarchive/carchive_test.go index cc810f9d3e255198889d8ec50e51616b2580c6a5..b140a9c61378a76cc0b28101a4a6add84c7845d8 100644 --- a/src/cmd/cgo/internal/testcarchive/carchive_test.go +++ b/src/cmd/cgo/internal/testcarchive/carchive_test.go @@ -1365,3 +1365,35 @@ if err != nil { t.Error(err) } } + +func TestSharedObject(t *testing.T) { + // Test that we can put a Go c-archive into a C shared object. + globalSkip(t) + testenv.MustHaveGoBuild(t) + testenv.MustHaveCGO(t) + testenv.MustHaveBuildMode(t, "c-archive") + + t.Parallel() + + if !testWork { + defer func() { + os.Remove("libgo_s.a") + os.Remove("libgo_s.h") + os.Remove("libgo_s.so") + }() + } + + cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo_s.a", "./libgo") + out, err := cmd.CombinedOutput() + t.Logf("%v\n%s", cmd.Args, out) + if err != nil { + t.Fatal(err) + } + + ccArgs := append(cc, "-shared", "-o", "libgo_s.so", "libgo_s.a") + out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput() + t.Logf("%v\n%s", ccArgs, out) + if err != nil { + t.Fatal(err) + } +} diff --git a/src/runtime/cgo/asm_386.s b/src/runtime/cgo/asm_386.s index 086e20b02f50c3eb9eda89ac5053367ed8ce65b0..f9a662aa88f485f94cfe2a6d5b24a8a0753dcb48 100644 --- a/src/runtime/cgo/asm_386.s +++ b/src/runtime/cgo/asm_386.s @@ -6,11 +6,16 @@ #include "textflag.h" // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 +// Use a local trampoline, to avoid taking the address of a dynamically exported +// function. TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOVL _crosscall2_ptr(SB), AX - MOVL $crosscall2(SB), BX + MOVL $crosscall2_trampoline<>(SB), BX MOVL BX, (AX) RET + +TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 + JMP crosscall2(SB) // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) diff --git a/src/runtime/cgo/asm_amd64.s b/src/runtime/cgo/asm_amd64.s index f254622f231f504ff62468d79abec7820d9ae4b3..e319094a456ba4118445e7e579c9bf2196867b7a 100644 --- a/src/runtime/cgo/asm_amd64.s +++ b/src/runtime/cgo/asm_amd64.s @@ -7,11 +7,16 @@ #include "abi_amd64.h" // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 +// Use a local trampoline, to avoid taking the address of a dynamically exported +// function. TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOVQ _crosscall2_ptr(SB), AX - MOVQ $crosscall2(SB), BX + MOVQ $crosscall2_trampoline<>(SB), BX MOVQ BX, (AX) RET + +TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 + JMP crosscall2(SB) // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) diff --git a/src/runtime/cgo/asm_arm.s b/src/runtime/cgo/asm_arm.s index f7f99772a6ce88b12bc16db01c69390d8220204e..095e9c06c9bf0a81c2cf0b8f5a34b575a3bd538e 100644 --- a/src/runtime/cgo/asm_arm.s +++ b/src/runtime/cgo/asm_arm.s @@ -6,11 +6,16 @@ #include "textflag.h" // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 +// Use a local trampoline, to avoid taking the address of a dynamically exported +// function. TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOVW _crosscall2_ptr(SB), R1 - MOVW $crosscall2(SB), R2 + MOVW $crosscall2_trampoline<>(SB), R2 MOVW R2, (R1) RET + +TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 + JMP crosscall2(SB) // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) diff --git a/src/runtime/cgo/asm_arm64.s b/src/runtime/cgo/asm_arm64.s index ce8909b49273e51e0f498468af172b8e125a887c..5492dc142c842abfa0a26bc9e729ff20666a25db 100644 --- a/src/runtime/cgo/asm_arm64.s +++ b/src/runtime/cgo/asm_arm64.s @@ -7,11 +7,16 @@ #include "abi_arm64.h" // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 +// Use a local trampoline, to avoid taking the address of a dynamically exported +// function. TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOVD _crosscall2_ptr(SB), R1 - MOVD $crosscall2(SB), R2 + MOVD $crosscall2_trampoline<>(SB), R2 MOVD R2, (R1) RET + +TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 + JMP crosscall2(SB) // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) diff --git a/src/runtime/cgo/asm_loong64.s b/src/runtime/cgo/asm_loong64.s index 3b514ffc4a195345087621abb5c92e47e9475653..19c8d743341a0b9d7893c2c448010af97b4e4dca 100644 --- a/src/runtime/cgo/asm_loong64.s +++ b/src/runtime/cgo/asm_loong64.s @@ -7,11 +7,16 @@ #include "abi_loong64.h" // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 +// Use a local trampoline, to avoid taking the address of a dynamically exported +// function. TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOVV _crosscall2_ptr(SB), R5 - MOVV $crosscall2(SB), R6 + MOVV $crosscall2_trampoline<>(SB), R6 MOVV R6, (R5) RET + +TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 + JMP crosscall2(SB) // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) diff --git a/src/runtime/cgo/asm_mips64x.s b/src/runtime/cgo/asm_mips64x.s index 0a8fbbbef05d11e2f68b72b7ce56746dbafa8fec..af817d5ea6ed3bf0d6ac0b370b09ff338ada0ace 100644 --- a/src/runtime/cgo/asm_mips64x.s +++ b/src/runtime/cgo/asm_mips64x.s @@ -8,11 +8,16 @@ #include "textflag.h" // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 +// Use a local trampoline, to avoid taking the address of a dynamically exported +// function. TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOVV _crosscall2_ptr(SB), R5 - MOVV $crosscall2(SB), R6 + MOVV $crosscall2_trampoline<>(SB), R6 MOVV R6, (R5) RET + +TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 + JMP crosscall2(SB) // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) diff --git a/src/runtime/cgo/asm_mipsx.s b/src/runtime/cgo/asm_mipsx.s index a57ae97d7e96a19f0db77ffa026a43ad0fab773b..198c59a33e7a0c61e8f48e5c3c2dd783b41d847a 100644 --- a/src/runtime/cgo/asm_mipsx.s +++ b/src/runtime/cgo/asm_mipsx.s @@ -8,11 +8,16 @@ #include "textflag.h" // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 +// Use a local trampoline, to avoid taking the address of a dynamically exported +// function. TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOVW _crosscall2_ptr(SB), R5 - MOVW $crosscall2(SB), R6 + MOVW $crosscall2_trampoline<>(SB), R6 MOVW R6, (R5) RET + +TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 + JMP crosscall2(SB) // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) diff --git a/src/runtime/cgo/asm_ppc64x.s b/src/runtime/cgo/asm_ppc64x.s index c258c7c2a080fd8e89df0f70171e1aca2649d29a..a3897459f5047e9e1b6598511938881deb71ec92 100644 --- a/src/runtime/cgo/asm_ppc64x.s +++ b/src/runtime/cgo/asm_ppc64x.s @@ -16,7 +16,9 @@ // to workaround this. DEFINE_PPC64X_FUNCDESC(_crosscall2<>, crosscall2) #define CROSSCALL2_FPTR $_crosscall2<>(SB) #else -#define CROSSCALL2_FPTR $crosscall2(SB) +// Use a local trampoline, to avoid taking the address of a dynamically exported +// function. +#define CROSSCALL2_FPTR $crosscall2_trampoline<>(SB) #endif // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. @@ -26,6 +28,9 @@ MOVD _crosscall2_ptr(SB), R5 MOVD CROSSCALL2_FPTR, R6 MOVD R6, (R5) RET + +TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 + JMP crosscall2(SB) // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) diff --git a/src/runtime/cgo/asm_riscv64.s b/src/runtime/cgo/asm_riscv64.s index 08c4ed846671da32b10428d272307e7bce14d6a4..d75a5438429e9d62f0bf1b6a5779593ccfe67fce 100644 --- a/src/runtime/cgo/asm_riscv64.s +++ b/src/runtime/cgo/asm_riscv64.s @@ -6,11 +6,16 @@ #include "textflag.h" // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 +// Use a local trampoline, to avoid taking the address of a dynamically exported +// function. TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOV _crosscall2_ptr(SB), X7 - MOV $crosscall2(SB), X8 + MOV $crosscall2_trampoline<>(SB), X8 MOV X8, (X7) RET + +TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 + JMP crosscall2(SB) // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) diff --git a/src/runtime/cgo/asm_s390x.s b/src/runtime/cgo/asm_s390x.s index bb0dfc1e313d9a747a7c961a431a32fd4e8a3aae..8f74fd5fe7810e44f0b3afd9489836d4e73dab60 100644 --- a/src/runtime/cgo/asm_s390x.s +++ b/src/runtime/cgo/asm_s390x.s @@ -6,11 +6,16 @@ #include "textflag.h" // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 +// Use a local trampoline, to avoid taking the address of a dynamically exported +// function. TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOVD _crosscall2_ptr(SB), R1 - MOVD $crosscall2(SB), R2 + MOVD $crosscall2_trampoline<>(SB), R2 MOVD R2, (R1) RET + +TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 + JMP crosscall2(SB) // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)