From 67f9580c5d9279f5b8ffbc90f810068cada28483 Mon Sep 17 00:00:00 2001 From: visualfc Date: Thu, 28 Nov 2024 12:01:11 +0800 Subject: [PATCH 1/2] c/debug: func addr and info --- c/debug/_demo/funcinfo/main.go | 27 +++++++++++++++++++++++++++ c/debug/_wrap/debug.c | 14 ++++++++++++++ c/debug/debug.go | 25 +++++++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 c/debug/_demo/funcinfo/main.go create mode 100644 c/debug/_wrap/debug.c create mode 100644 c/debug/debug.go diff --git a/c/debug/_demo/funcinfo/main.go b/c/debug/_demo/funcinfo/main.go new file mode 100644 index 00000000..8b0d9a91 --- /dev/null +++ b/c/debug/_demo/funcinfo/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/c/debug" +) + +type T struct { + n int +} + +func (t *T) Demo() { + println(t.n) + addr := debug.Address() + c.Printf(c.Str("addr:0x%x\n"), addr) + var info debug.Info + r := debug.Addrinfo(addr, &info) + if r == 0 { + panic("not found info") + } + c.Printf(c.Str("func file:%s name:%s base:0x%x addr:0x%x\n"), info.Fname, info.Sname, info.Fbase, info.Saddr) +} + +func main() { + t := &T{100} + t.Demo() +} diff --git a/c/debug/_wrap/debug.c b/c/debug/_wrap/debug.c new file mode 100644 index 00000000..7c785919 --- /dev/null +++ b/c/debug/_wrap/debug.c @@ -0,0 +1,14 @@ +#if defined(__linux__) +#define _GNU_SOURCE +#include +#endif + +#include + +void *llgo_address() { + return __builtin_return_address(0); +} + +int llgo_addrinfo(void *addr, Dl_info *info) { + return dladdr(addr, info); +} diff --git a/c/debug/debug.go b/c/debug/debug.go new file mode 100644 index 00000000..8170e373 --- /dev/null +++ b/c/debug/debug.go @@ -0,0 +1,25 @@ +package debug + +import ( + "unsafe" + + "github.com/goplus/llgo/c" +) + +const ( + LLGoPackage = "link" + LLGoFiles = "_wrap/debug.c" +) + +type Info struct { + Fname *c.Char + Fbase c.Pointer + Sname *c.Char + Saddr c.Pointer +} + +//go:linkname Address C.llgo_address +func Address() unsafe.Pointer + +//go:linkname Addrinfo C.llgo_addrinfo +func Addrinfo(addr unsafe.Pointer, info *Info) c.Int From 7b6b8b0eeb84fb1fc9720fbb05e1c2b13600e0c1 Mon Sep 17 00:00:00 2001 From: visualfc Date: Fri, 29 Nov 2024 11:27:56 +0800 Subject: [PATCH 2/2] c/debug: StackTrace --- c/debug/_demo/stacktrace/main.go | 26 ++++++++++++++++++++++++++ c/debug/_wrap/debug.c | 24 ++++++++++++++++++++++++ c/debug/debug.go | 20 ++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 c/debug/_demo/stacktrace/main.go diff --git a/c/debug/_demo/stacktrace/main.go b/c/debug/_demo/stacktrace/main.go new file mode 100644 index 00000000..30339209 --- /dev/null +++ b/c/debug/_demo/stacktrace/main.go @@ -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() +} diff --git a/c/debug/_wrap/debug.c b/c/debug/_wrap/debug.c index 7c785919..51cdde32 100644 --- a/c/debug/_wrap/debug.c +++ b/c/debug/_wrap/debug.c @@ -4,6 +4,7 @@ #endif #include +#include void *llgo_address() { return __builtin_return_address(0); @@ -12,3 +13,26 @@ void *llgo_address() { int llgo_addrinfo(void *addr, Dl_info *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; + } + } + } +} diff --git a/c/debug/debug.go b/c/debug/debug.go index 8170e373..c208d3c4 100644 --- a/c/debug/debug.go +++ b/c/debug/debug.go @@ -23,3 +23,23 @@ func Address() unsafe.Pointer //go:linkname Addrinfo C.llgo_addrinfo 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 + }) +}