Home | History | Annotate | Download | only in testprogcgo
      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // The __attribute__((weak)) used below doesn't seem to work on Windows.
      6 
      7 package main
      8 
      9 // Test the context argument to SetCgoTraceback.
     10 // Use fake context, traceback, and symbolizer functions.
     11 
     12 /*
     13 // Defined in tracebackctxt_c.c.
     14 extern void C1(void);
     15 extern void C2(void);
     16 extern void tcContext(void*);
     17 extern void tcTraceback(void*);
     18 extern void tcSymbolizer(void*);
     19 extern int getContextCount(void);
     20 */
     21 import "C"
     22 
     23 import (
     24 	"fmt"
     25 	"runtime"
     26 	"unsafe"
     27 )
     28 
     29 func init() {
     30 	register("TracebackContext", TracebackContext)
     31 }
     32 
     33 var tracebackOK bool
     34 
     35 func TracebackContext() {
     36 	runtime.SetCgoTraceback(0, unsafe.Pointer(C.tcTraceback), unsafe.Pointer(C.tcContext), unsafe.Pointer(C.tcSymbolizer))
     37 	C.C1()
     38 	if got := C.getContextCount(); got != 0 {
     39 		fmt.Printf("at end contextCount == %d, expected 0\n", got)
     40 		tracebackOK = false
     41 	}
     42 	if tracebackOK {
     43 		fmt.Println("OK")
     44 	}
     45 }
     46 
     47 //export G1
     48 func G1() {
     49 	C.C2()
     50 }
     51 
     52 //export G2
     53 func G2() {
     54 	pc := make([]uintptr, 32)
     55 	n := runtime.Callers(0, pc)
     56 	cf := runtime.CallersFrames(pc[:n])
     57 	var frames []runtime.Frame
     58 	for {
     59 		frame, more := cf.Next()
     60 		frames = append(frames, frame)
     61 		if !more {
     62 			break
     63 		}
     64 	}
     65 
     66 	want := []struct {
     67 		function string
     68 		line     int
     69 	}{
     70 		{"main.G2", 0},
     71 		{"cFunction", 0x10200},
     72 		{"cFunction", 0x200},
     73 		{"cFunction", 0x10201},
     74 		{"cFunction", 0x201},
     75 		{"main.G1", 0},
     76 		{"cFunction", 0x10100},
     77 		{"cFunction", 0x100},
     78 		{"main.TracebackContext", 0},
     79 	}
     80 
     81 	ok := true
     82 	i := 0
     83 wantLoop:
     84 	for _, w := range want {
     85 		for ; i < len(frames); i++ {
     86 			if w.function == frames[i].Function {
     87 				if w.line != 0 && w.line != frames[i].Line {
     88 					fmt.Printf("found function %s at wrong line %#x (expected %#x)\n", w.function, frames[i].Line, w.line)
     89 					ok = false
     90 				}
     91 				i++
     92 				continue wantLoop
     93 			}
     94 		}
     95 		fmt.Printf("did not find function %s in\n", w.function)
     96 		for _, f := range frames {
     97 			fmt.Println(f)
     98 		}
     99 		ok = false
    100 		break
    101 	}
    102 	tracebackOK = ok
    103 	if got := C.getContextCount(); got != 2 {
    104 		fmt.Printf("at bottom contextCount == %d, expected 2\n", got)
    105 		tracebackOK = false
    106 	}
    107 }
    108