c/debug: StackTrace
This commit is contained in:
26
c/debug/_demo/stacktrace/main.go
Normal file
26
c/debug/_demo/stacktrace/main.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c/debug"
|
||||||
|
)
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
n int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Demo() {
|
||||||
|
println(t.n)
|
||||||
|
debug.StackTrace(0, func(fr *debug.Frame) bool {
|
||||||
|
var info debug.Info
|
||||||
|
debug.Addrinfo(unsafe.Pointer(fr.PC), &info)
|
||||||
|
println("[", fr.PC, "]", fr.Name, "+", fr.Offset, ", SP =", fr.SP)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := &T{100}
|
||||||
|
t.Demo()
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <libunwind.h>
|
||||||
|
|
||||||
void *llgo_address() {
|
void *llgo_address() {
|
||||||
return __builtin_return_address(0);
|
return __builtin_return_address(0);
|
||||||
@@ -12,3 +13,26 @@ void *llgo_address() {
|
|||||||
int llgo_addrinfo(void *addr, Dl_info *info) {
|
int llgo_addrinfo(void *addr, Dl_info *info) {
|
||||||
return dladdr(addr, info);
|
return dladdr(addr, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void llgo_stacktrace(int skip, void *ctx, int (*fn)(void *ctx, void *pc, void *offset, void *sp, char *name)) {
|
||||||
|
unw_cursor_t cursor;
|
||||||
|
unw_context_t context;
|
||||||
|
unw_word_t offset, pc, sp;
|
||||||
|
char fname[256];
|
||||||
|
unw_getcontext(&context);
|
||||||
|
unw_init_local(&cursor, &context);
|
||||||
|
int depth = 0;
|
||||||
|
while (unw_step(&cursor) > 0) {
|
||||||
|
if (depth < skip) {
|
||||||
|
depth++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (unw_get_reg(&cursor, UNW_REG_IP, &pc) == 0) {
|
||||||
|
unw_get_proc_name(&cursor, fname, sizeof(fname), &offset);
|
||||||
|
unw_get_reg(&cursor, UNW_REG_SP, &sp);
|
||||||
|
if (fn(ctx, (void*)pc, (void*)offset, (void*)sp, fname) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,3 +23,23 @@ func Address() unsafe.Pointer
|
|||||||
|
|
||||||
//go:linkname Addrinfo C.llgo_addrinfo
|
//go:linkname Addrinfo C.llgo_addrinfo
|
||||||
func Addrinfo(addr unsafe.Pointer, info *Info) c.Int
|
func Addrinfo(addr unsafe.Pointer, info *Info) c.Int
|
||||||
|
|
||||||
|
//go:linkname stacktrace C.llgo_stacktrace
|
||||||
|
func stacktrace(skip c.Int, ctx unsafe.Pointer, fn func(ctx, pc, offset, sp unsafe.Pointer, name *c.Char) c.Int)
|
||||||
|
|
||||||
|
type Frame struct {
|
||||||
|
PC uintptr
|
||||||
|
Offset uintptr
|
||||||
|
SP unsafe.Pointer
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func StackTrace(skip int, fn func(fr *Frame) bool) {
|
||||||
|
stacktrace(c.Int(1+skip), unsafe.Pointer(&fn), func(ctx, pc, offset, sp unsafe.Pointer, name *c.Char) c.Int {
|
||||||
|
fn := *(*func(fr *Frame) bool)(ctx)
|
||||||
|
if !fn(&Frame{uintptr(pc), uintptr(offset), sp, c.GoString(name)}) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user