github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/runtime/testdata/testprogcgo/tracebackctxt.go (about)

     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  }