| // Copyright 2016 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| // The __attribute__((weak)) used below doesn't seem to work on Windows. | |
| package main | |
| // Test the context argument to SetCgoTraceback. | |
| // Use fake context, traceback, and symbolizer functions. | |
| /* | |
| // Defined in tracebackctxt_c.c. | |
| extern void C1(void); | |
| extern void C2(void); | |
| extern void tcContext(void*); | |
| extern void tcTraceback(void*); | |
| extern void tcSymbolizer(void*); | |
| extern int getContextCount(void); | |
| */ | |
| import "C" | |
| import ( | |
| "fmt" | |
| "runtime" | |
| "unsafe" | |
| ) | |
| func init() { | |
| register("TracebackContext", TracebackContext) | |
| } | |
| var tracebackOK bool | |
| func TracebackContext() { | |
| runtime.SetCgoTraceback(0, unsafe.Pointer(C.tcTraceback), unsafe.Pointer(C.tcContext), unsafe.Pointer(C.tcSymbolizer)) | |
| C.C1() | |
| if got := C.getContextCount(); got != 0 { | |
| fmt.Printf("at end contextCount == %d, expected 0\n", got) | |
| tracebackOK = false | |
| } | |
| if tracebackOK { | |
| fmt.Println("OK") | |
| } | |
| } | |
| //export G1 | |
| func G1() { | |
| C.C2() | |
| } | |
| //export G2 | |
| func G2() { | |
| pc := make([]uintptr, 32) | |
| n := runtime.Callers(0, pc) | |
| cf := runtime.CallersFrames(pc[:n]) | |
| var frames []runtime.Frame | |
| for { | |
| frame, more := cf.Next() | |
| frames = append(frames, frame) | |
| if !more { | |
| break | |
| } | |
| } | |
| want := []struct { | |
| function string | |
| line int | |
| }{ | |
| {"main.G2", 0}, | |
| {"cFunction", 0x10200}, | |
| {"cFunction", 0x200}, | |
| {"cFunction", 0x10201}, | |
| {"cFunction", 0x201}, | |
| {"main.G1", 0}, | |
| {"cFunction", 0x10100}, | |
| {"cFunction", 0x100}, | |
| {"main.TracebackContext", 0}, | |
| } | |
| ok := true | |
| i := 0 | |
| wantLoop: | |
| for _, w := range want { | |
| for ; i < len(frames); i++ { | |
| if w.function == frames[i].Function { | |
| if w.line != 0 && w.line != frames[i].Line { | |
| fmt.Printf("found function %s at wrong line %#x (expected %#x)\n", w.function, frames[i].Line, w.line) | |
| ok = false | |
| } | |
| i++ | |
| continue wantLoop | |
| } | |
| } | |
| fmt.Printf("did not find function %s in\n", w.function) | |
| for _, f := range frames { | |
| fmt.Println(f) | |
| } | |
| ok = false | |
| break | |
| } | |
| tracebackOK = ok | |
| if got := C.getContextCount(); got != 2 { | |
| fmt.Printf("at bottom contextCount == %d, expected 2\n", got) | |
| tracebackOK = false | |
| } | |
| } |