Skip to content

Commit

Permalink
wip: try to resolve symbols
Browse files Browse the repository at this point in the history
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
  • Loading branch information
maxgio92 committed Nov 7, 2023
1 parent 395bd4e commit 9cea4e8
Show file tree
Hide file tree
Showing 8 changed files with 311 additions and 55 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## Quickstart

```shell
$ go build ./toy_app/toy.go -o ./toy_app/toy
./toy_app/toy &
[1] 591488
$ sudo go run ./main.go --pid 591488 --duration 10
```
9 changes: 4 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
module github.com/maxgio92/perf-profiler-go

go 1.20
go 1.21.1

require (
github.com/iovisor/gobpf v0.2.1-0.20221005153822-16120a1bf4d4
github.com/maxgio92/gobpf v0.0.0-20231021162119-ff4afec32fd2
github.com/pkg/errors v0.9.1
github.com/tklauser/numcpus v0.6.1
golang.org/x/sys v0.8.0
modernc.org/libc v1.22.6
golang.org/x/sys v0.13.0
modernc.org/libc v1.27.0
)
14 changes: 6 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
github.com/iovisor/gobpf v0.2.1-0.20221005153822-16120a1bf4d4 h1:WpizD4VUT5V+VcaQSvW5BlvFpQYrd2974H9KbiGa5/0=
github.com/iovisor/gobpf v0.2.1-0.20221005153822-16120a1bf4d4/go.mod h1:WSY9Jj5RhdgC3ci1QaacvbFdQ8cbrEjrpiZbLHLt2s4=
github.com/maxgio92/gobpf v0.0.0-20231021162119-ff4afec32fd2 h1:ykUIr/kZLiGMlQFYZQBiJLtQYB7cMfvUaADuwPP1J5M=
github.com/maxgio92/gobpf v0.0.0-20231021162119-ff4afec32fd2/go.mod h1:4LyFQGAyzW0qdThO5Chz+Ay9mbITSh5WVUUYw6x3uk8=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
modernc.org/libc v1.22.6 h1:cbXU8R+A6aOjRuhsFh3nbDWXO/Hs4ClJRXYB11KmPDo=
modernc.org/libc v1.22.6/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
modernc.org/libc v1.27.0 h1:Z35IJO5v46n+d1RWRzCD3CiMYYc9TotabBDl75kRmdo=
modernc.org/libc v1.27.0/go.mod h1:DaG/4Q3LRRdqpiLyP0C2m1B8ZMGkQ+cCgOIjEtQlYhQ=
54 changes: 35 additions & 19 deletions kernel/perf_profiler.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ const int kNumMapEntries = 65536;
BPF_STACK_TRACE(stack_traces, kNumMapEntries);

/*
// libbpf way
* libbpf way
*
struct {
__uint(type, BPF_MAP_TYPE_STACK_TRACE);
__uint(max_entries, kNumMapEntries);
Expand All @@ -39,7 +40,8 @@ struct {
BPF_HASH(histogram, struct stack_trace_key_t, uint64_t, kNumMapEntries);

/*
// libbpf way
* libbpf way
*
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, kNumMapEntries);
Expand All @@ -62,33 +64,47 @@ int sample_stack_trace(struct bpf_perf_event_data* ctx) {
key.user_stack_id = user_stack_id;
key.kernel_stack_id = kernel_stack_id;

// BCC way
//u64 zero = 0;
//histogram.lookup_or_try_init(&key, &zero);
/*
* BCC way
*
u64 zero = 0;
histogram.lookup_or_try_init(&key, &zero);
*/
histogram.atomic_increment(key);

//// libbpf wa*y
//u64* count = bpf_map_lookup_elem(&histogram, &key);
//if(count){
// u64 c = *count;
// c++;
// bpf_map_update_elem(&histogram, &key, &c, BPF_EXIST);
//}else{
// u64 one = 1;
// bpf_map_update_elem(&histogram, &key, &one, BPF_NOEXIST);
//}

// DEBUG
//bpf_trace_printk("Stack trace id: tgid %d\n", sizeof("Stack trace id: tgid %d\n"), key.pid);
//bpf_trace_printk("Stack trace id: user stack id %d - kernel stack id %d \n", sizeof("Stack trace id: user stack id %d - kernel stack id %d \n"), key.user_stack_id);
/*
* libbpf way
*
u64* count = bpf_map_lookup_elem(&histogram, &key);
if(count){
u64 c = *count;
c++;
bpf_map_update_elem(&histogram, &key, &c, BPF_EXIST);
}else{
u64 one = 1;
bpf_map_update_elem(&histogram, &key, &one, BPF_NOEXIST);
}
*/

/*
* DEBUG
*
bpf_trace_printk("Stack trace id: tgid %d\n", sizeof("Stack trace id: tgid %d\n"), key.pid);
bpf_trace_printk("Stack trace id: user stack id %d - kernel stack id %d \n", sizeof("Stack trace id: user stack id %d - kernel stack id %d \n"), key.user_stack_id);
bpf_trace_printk("Key: Current tgid %d;", (u64)pid);
bpf_trace_printk("Key: User stack id is %d;", (u64)user_stack_id);
bpf_trace_printk("Key: Kernel stack id is %d;", (u64)kernel_stack_id);
*/

u64 *count = histogram.lookup(&key);

/*
* DEBUG
*
if (count) {
bpf_trace_printk("Stack trace count is %llu\n", (u64*)*count);
}
*/

return 0;
}
54 changes: 31 additions & 23 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import (
"encoding/binary"
"flag"
"fmt"
"github.com/iovisor/gobpf/bcc"
"github.com/iovisor/gobpf/pkg/ksym"
"os"
"time"

"github.com/maxgio92/gobpf/bcc"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
libc "modernc.org/libc/sys/types"
"os"
"time"

. "github.com/maxgio92/perf-profiler-go/internal/utils"
)
Expand All @@ -23,18 +23,18 @@ type Options struct {
}

type HistogramKey struct {
Pid libc.Pid_t
Pid int32

// UserStackId, an index into the stack-traces map.
UserStackId libc.U_int32_t
UserStackId uint32

// KernelStackId, an index into the stack-traces map.
KernelStackId libc.U_int32_t
KernelStackId uint32
}

// StackTrace is an array of instruction pointers (IP).
// 127 is the size of the trace, as for the default PERF_MAX_STACK_DEPTH.
type StackTrace [127]libc.Ulong
type StackTrace [127]uint64

const (
probeFile = "kernel/perf_profiler.bpf.c"
Expand All @@ -45,8 +45,7 @@ const (

samplingPeriodMillis = 11

userSymUnknown = "[USER_UNKNOWN]"
kernelSymUnknown = "[KERN_UNKNOWN]"
symUnknown = "[UNKNOWN]"
)

func main() {
Expand Down Expand Up @@ -127,7 +126,8 @@ func main() {

time.Sleep(time.Duration(o.duration) * time.Second)

fmt.Println("Stack trace histogram map")
fmt.Printf("PID\t\tTIMES\tKERNEL STACK ID\tKERNEL STACK TRACE\tUSER STACK ID\tUSER STACK TRACE\n")

for it := histogram.Iter(); it.Next(); {
histogramKeyBin := it.Key()
count := it.Leaf()
Expand All @@ -142,27 +142,27 @@ func main() {

var symbolsStr string

fmt.Printf("\tmatched stack trace executed %d times\n\t\tpid: %v\n",
binary.LittleEndian.Uint64(count), histogramKey.Pid)
fmt.Printf("%v\t%v\t\t", histogramKey.Pid, binary.LittleEndian.Uint64(count))

fmt.Printf("\t\tkernel stack id: %v\n", histogramKey.KernelStackId)
fmt.Printf("%v\t\t", histogramKey.KernelStackId)

// Check if the trace is of kernel or user stack.
if histogramKey.KernelStackId != 0 {
stackTrace, err := getStackTrace(stackTraces, histogramKey.KernelStackId)
if err == nil && stackTrace != nil {
symbolsStr += getStackTraceSyms(stackTrace, kernelSymUnknown)
symbolsStr += getStackTraceSyms(bpfModule, int(histogramKey.Pid), stackTrace, false)
}
}
fmt.Printf("\t\tuser stack id: %v\n", histogramKey.UserStackId)
fmt.Printf("%v\t\t\t", histogramKey.UserStackId)

if histogramKey.UserStackId != 0 {
stackTrace, err := getStackTrace(stackTraces, histogramKey.UserStackId)
if err == nil && stackTrace != nil {
symbolsStr += getStackTraceSyms(stackTrace, userSymUnknown)
symbolsStr += getStackTraceSyms(bpfModule, int(histogramKey.Pid), stackTrace, true)
}
}

fmt.Printf("\n")

// Increment the result map value for the histogramKey stack symbol string (e.g. "main;subfunc;")
result[symbolsStr]++
}
Expand All @@ -186,18 +186,26 @@ func getStackTrace(stackTracesMap *bcc.Table, id libc.U_int32_t) (*StackTrace, e
return &stackTrace, nil
}

func getStackTraceSyms(stackTrace *StackTrace, unknown string) string {
func getStackTraceSyms(module *bcc.Module, pid int, stackTrace *StackTrace, user bool) string {
var symbolsStr string
if !user {
pid = -1
}
for _, ip := range stackTrace {
if ip != 0 {
sym, err := ksym.Ksym(fmt.Sprintf("%016x", ip))
if err != nil {
sym = unknown
sym := module.GetSymbolByAddr(ip, pid)
if sym == "" {
sym = symUnknown
fmt.Printf("%#016x %s; ", ip, sym)
} else {
fmt.Printf("%s; ", sym)
}
fmt.Printf("\t\t\t%#016x\t%s\n", ip, sym)
symbolsStr += sym
symbolsStr += ";"
}
}

fmt.Printf("\t")

return symbolsStr
}
8 changes: 8 additions & 0 deletions toy_app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## Stack walking

```
dlv debug ./toy.go
(dlv) source stackannotate.star
(dlv) continue toy.go:60
(dlv) stackannotate
```
Loading

0 comments on commit 9cea4e8

Please sign in to comment.