From 0fe935763404d30cb1f0e04b6b515fcba4b64972 Mon Sep 17 00:00:00 2001 From: Leon Hwang Date: Wed, 20 Nov 2024 21:52:18 +0800 Subject: [PATCH] bpflbr: Dump line info for call/jmp insn Signed-off-by: Leon Hwang --- internal/bpflbr/dump.go | 43 +++++++++++++++++++++++++++++++----- internal/bpflbr/lbr.go | 1 + internal/bpflbr/lbr_stack.go | 1 + 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/internal/bpflbr/dump.go b/internal/bpflbr/dump.go index f90cb91..4302276 100644 --- a/internal/bpflbr/dump.go +++ b/internal/bpflbr/dump.go @@ -7,6 +7,7 @@ import ( "fmt" "log" "os" + "strconv" "strings" "github.com/cilium/ebpf" @@ -31,6 +32,26 @@ func DumpProg(pf []ProgFlag) { log.Fatalf("No prog found") } + kallsyms, err := NewKallsyms() + assert.NoErr(err, "Failed to read /proc/kallsyms: %v") + + vmlinux, err := FindVmlinux() + assert.NoErr(err, "Failed to find vmlinux: %v") + + textAddr, err := ReadTextAddrFromVmlinux(vmlinux) + assert.NoErr(err, "Failed to read .text address from vmlinux: %v") + + kaslrOffset := textAddr - kallsyms.Stext() + addr2line, err := NewAddr2Line(vmlinux, kaslrOffset, kallsyms.SysBPF()) + assert.NoErr(err, "Failed to create addr2line: %v") + + engine, err := gapstone.New(int(gapstone.CS_ARCH_X86), int(gapstone.CS_MODE_64)) + assert.NoErr(err, "Failed to create engine: %v") + defer engine.Close() + + bpfProgs, err := NewBPFProgs(engine, nil, false) + assert.NoErr(err, "Failed to get bpf progs: %v") + info, err := prog.Info() assert.NoErr(err, "Failed to get prog info: %v") @@ -63,10 +84,6 @@ func DumpProg(pf []ProgFlag) { jited2LineInfos[kaddr] = lines[i] } - engine, err := gapstone.New(int(gapstone.CS_ARCH_X86), int(gapstone.CS_MODE_64)) - assert.NoErr(err, "Failed to create engine: %v") - defer engine.Close() - intelSyntax := os.Getenv("BPFLBR_DUMP_INTEL_SYNTAX") == "1" if !intelSyntax { err = engine.SetOption(uint(gapstone.CS_OPT_SYNTAX), uint(gapstone.CS_OPT_SYNTAX_ATT)) @@ -98,7 +115,23 @@ func DumpProg(pf []ProgFlag) { opcodes = append(opcodes, fmt.Sprintf("%02x", insn)) } opcode := strings.Join(opcodes, " ") - fmt.Fprintf(&sb, "%#x: %-19s\t%s\t%s\n", kaddr, opcode, inst[0].Mnemonic, inst[0].OpStr) + opstr := inst[0].OpStr + fmt.Fprintf(&sb, "%#x: %-19s\t%s\t%s", kaddr, opcode, inst[0].Mnemonic, opstr) + + var endpoint *branchEndpoint + if strings.HasPrefix(opstr, "0x") { + n, err := strconv.ParseUint(opstr, 0, 64) + if err == nil { + endpoint = getLineInfo(uintptr(n), bpfProgs, addr2line, kallsyms) + } + } + if endpoint != nil { + fmt.Fprintf(&sb, "\t; %s+%#x %s:%d", endpoint.funcName, endpoint.offset, endpoint.fileName, endpoint.fileLine) + if endpoint.isProg { + fmt.Fprintf(&sb, " [bpf]") + } + } + fmt.Fprintln(&sb) insnSize := uint64(inst[0].Size) pc += insnSize diff --git a/internal/bpflbr/lbr.go b/internal/bpflbr/lbr.go index 06607b5..c5486f1 100644 --- a/internal/bpflbr/lbr.go +++ b/internal/bpflbr/lbr.go @@ -130,6 +130,7 @@ func getLineInfo(addr uintptr, progs *bpfProgs, a2l *Addr2Line, ksyms *Kallsyms) ep.funcName = li.funcName ep.fileName = li.fileName ep.fileLine = li.fileLine + ep.isProg = true ep.updateInfo() return &ep } diff --git a/internal/bpflbr/lbr_stack.go b/internal/bpflbr/lbr_stack.go index fc49638..d47c1f4 100644 --- a/internal/bpflbr/lbr_stack.go +++ b/internal/bpflbr/lbr_stack.go @@ -18,6 +18,7 @@ type branchEndpoint struct { fileName string fileLine uint32 lineInfo string // (${fileName}:${fileLine}) + isProg bool } func (b *branchEndpoint) updateInfo() {