src/cmd/cgo/internal/test/callback_windows.go GO 111 lines View on github.com → Search inside
1// Copyright 2023 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.45package cgotest67/*8#include <windows.h>9USHORT backtrace(ULONG FramesToCapture, PVOID *BackTrace) {10#ifdef _AMD64_11	CONTEXT context;12	RtlCaptureContext(&context);13	ULONG64 ControlPc;14	ControlPc = context.Rip;15	int i;16	for (i = 0; i < FramesToCapture; i++) {17		PRUNTIME_FUNCTION FunctionEntry;18		ULONG64 ImageBase;19		VOID *HandlerData;20		ULONG64 EstablisherFrame;2122		FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL);2324		if (!FunctionEntry) {25			// For simplicity, don't unwind leaf entries, which are not used in this test.26			break;27		} else {28			RtlVirtualUnwind(0, ImageBase, ControlPc, FunctionEntry, &context, &HandlerData, &EstablisherFrame, NULL);29		}3031		ControlPc = context.Rip;32		// Check if we left the user range.33		if (ControlPc < 0x10000) {34			break;35		}3637		BackTrace[i] = (PVOID)(ControlPc);38	}39	return i;40#else41	return 0;42#endif43}44*/45import "C"4647import (48	"internal/testenv"49	"reflect"50	"runtime"51	"strings"52	"testing"53	"unsafe"54)5556// Test that the stack can be unwound through a call out and call back57// into Go.58func testCallbackCallersSEH(t *testing.T) {59	testenv.SkipIfOptimizationOff(t) // This test requires inlining.60	if runtime.Compiler != "gc" {61		// The exact function names are not going to be the same.62		t.Skip("skipping for non-gc toolchain")63	}64	if runtime.GOARCH != "amd64" {65		// TODO: support SEH on other architectures.66		t.Skip("skipping on non-amd64")67	}68	// Only frames in the test package are checked.69	want := []string{70		"test._Cfunc_backtrace",71		"test.testCallbackCallersSEH.func1.1",72		// "test.testCallbackCallersSEH.func1", // hidden by inlining73		"test.goCallback",74		"test._Cfunc_callback",75		"test.nestedCall.func1",76		// "test.nestedCall", // hidden by inlining77		"test.testCallbackCallersSEH",78		"test.TestCallbackCallersSEH",79	}80	pc := make([]uintptr, 100)81	n := 082	nestedCall(func() {83		n = int(C.backtrace(C.DWORD(len(pc)), (*C.PVOID)(unsafe.Pointer(&pc[0]))))84	})85	got := make([]string, 0, n)86	for i := 0; i < n; i++ {87		// This test is brittle in the face of inliner changes88		f := runtime.FuncForPC(pc[i] - 1)89		if f == nil {90			continue91		}92		fname := f.Name()93		switch fname {94		case "goCallback":95			// TODO(qmuntal): investigate why this function doesn't appear96			// when using the external linker.97			continue98		}99		// In module mode, this package has a fully-qualified import path.100		// Remove it if present.101		fname = strings.TrimPrefix(fname, "cmd/cgo/internal/")102		if !strings.HasPrefix(fname, "test.") {103			continue104		}105		got = append(got, fname)106	}107	if !reflect.DeepEqual(want, got) {108		t.Errorf("incorrect backtrace:\nwant:\t%v\ngot:\t%v", want, got)109	}110}

Code quality findings 1

Use of unsafe package detected; ensure it’s necessary, justified in comments, and bounds-checked to avoid memory corruption
warning safety unsafe-package
n = int(C.backtrace(C.DWORD(len(pc)), (*C.PVOID)(unsafe.Pointer(&pc[0]))))

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.