Skip to content

Commit

Permalink
Merge pull request #9 from jschwinger233/pr/gray/attach-by-calls
Browse files Browse the repository at this point in the history
Attach all insns matching the same line, output with CALL
  • Loading branch information
jschwinger233 authored Jan 12, 2025
2 parents f8c27ac + e3b7545 commit 2a83bd5
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 40 deletions.
1 change: 1 addition & 0 deletions bpf/bpf_x86_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified bpf/bpf_x86_bpfel.o
Binary file not shown.
56 changes: 56 additions & 0 deletions bpf/ktcpdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct event {
u64 skb;
u32 skb_len;
u32 data_len;
u64 call;
u16 protocol;
u8 has_mac;
};
Expand Down Expand Up @@ -131,6 +132,60 @@ kprobe_pcap_filter(struct sk_buff *skb, u8 *has_mac)
data, data_end);
}

static __always_inline void
get_call_target(struct pt_regs *ctx, u64 *call, u64 cookie)
{
switch (cookie) {
case 1:
BPF_CORE_READ_INTO(call, ctx, r15);
break;
case 2:
BPF_CORE_READ_INTO(call, ctx, r14);
break;
case 3:
BPF_CORE_READ_INTO(call, ctx, r13);
break;
case 4:
BPF_CORE_READ_INTO(call, ctx, r12);
break;
case 5:
BPF_CORE_READ_INTO(call, ctx, bp);
break;
case 6:
BPF_CORE_READ_INTO(call, ctx, bx);
break;
case 7:
BPF_CORE_READ_INTO(call, ctx, r11);
break;
case 8:
BPF_CORE_READ_INTO(call, ctx, r10);
break;
case 9:
BPF_CORE_READ_INTO(call, ctx, r9);
break;
case 10:
BPF_CORE_READ_INTO(call, ctx, r8);
break;
case 11:
BPF_CORE_READ_INTO(call, ctx, ax);
break;
case 12:
BPF_CORE_READ_INTO(call, ctx, cx);
break;
case 13:
BPF_CORE_READ_INTO(call, ctx, dx);
break;
case 14:
BPF_CORE_READ_INTO(call, ctx, si);
break;
case 15:
BPF_CORE_READ_INTO(call, ctx, di);
break;
default:
*call = 0;
}
}

SEC("kprobe/skb_by_search")
int kprobe_skb_by_search(struct pt_regs *ctx)
{
Expand All @@ -154,6 +209,7 @@ int kprobe_skb_by_search(struct pt_regs *ctx)
event->skb = (u64)skb;
event->skb_len = BPF_CORE_READ(skb, len);
event->protocol = BPF_CORE_READ(skb, protocol);
get_call_target(ctx, &event->call, bpf_get_attach_cookie(ctx));

u16 off_l2_or_l3 = event->has_mac
? BPF_CORE_READ(skb, mac_header)
Expand Down
43 changes: 38 additions & 5 deletions kcore.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ type Kcore struct {
elf *elf.File
}

type Instruction struct {
Symbol string
Offset uint64
Call bool
CallTarget string
*LineInfo
}

func NewKcore() (*Kcore, error) {
file, err := os.Open(kcorePath)
if err != nil {
Expand All @@ -47,9 +55,8 @@ func GetKcore() (_ *Kcore, err error) {
return kcore, err
}

func (k *Kcore) FindLines(symbol string) (lineInfos map[LineInfo][]uint64, err error) {
lineInfos = make(map[LineInfo][]uint64)

func (k *Kcore) ParseInsns(symbol string) (insns map[uint64]*Instruction, err error) {
insns = make(map[uint64]*Instruction)
kdwarf, err := GetKdwarf()
if err != nil {
return
Expand Down Expand Up @@ -79,10 +86,37 @@ func (k *Kcore) FindLines(symbol string) (lineInfos map[LineInfo][]uint64, err e
inst = x86asm.Inst{Len: 1}
off += 1
} else {
insn := Instruction{
Symbol: symbol,
Offset: uint64(off),
}
if inst.Op == x86asm.CALL {
insn.Call = true
for _, arg := range inst.Args {
if arg == nil {
break
}
rel, ok := arg.(x86asm.Rel)
if !ok {
reg, ok := arg.(x86asm.Reg)
if ok {
insn.CallTarget = reg.String()
break
}
}
callee := addr + uint64(off) + uint64(rel) + uint64(inst.Len)
ksym, err := KsymByAddr(callee)
if err == nil {
insn.CallTarget = ksym.Name
}
break
}
}
lineInfo, err := kdwarf.GetLineInfo(symbol, uint64(off))
if err == nil {
lineInfos[*lineInfo] = append(lineInfos[*lineInfo], uint64(off))
insn.LineInfo = lineInfo
}
insns[uint64(off)] = &insn
}

bytes = bytes[inst.Len:]
Expand All @@ -91,7 +125,6 @@ func (k *Kcore) FindLines(symbol string) (lineInfos map[LineInfo][]uint64, err e
break
}
}

}
}

Expand Down
70 changes: 37 additions & 33 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func main() {
defer k.Close()

var attachByLine bool
allInsns := map[string]map[uint64]*Instruction{}
for _, target := range config.Targets {
match := targetPattern.FindStringSubmatch(target)
result := make(map[string]string)
Expand Down Expand Up @@ -164,23 +165,24 @@ func main() {
log.Error("Failed to new kcore", "err", err)
return
}
jumps, err := kcore.FindLines(symbol)
insns, err := kcore.ParseInsns(symbol)
if err != nil {
log.Error("Failed to find jumps", "symbol", symbol, "err", err)
log.Error("Failed to find lines", "symbol", symbol, "err", err)
return
}
for _, js := range jumps {
for _, j := range js {
log.Debug("Attaching", "symbol", symbol, "offset", j)
k, err := link.Kprobe(symbol, objs.KprobeSkbBySearch, &link.KprobeOptions{Offset: j})
if err != nil {
log.Debug("Failed to attach targets", "symbol", symbol, "offset", j, "err", err)
continue
}
defer k.Close()
break
allInsns[symbol] = insns

for _, ins := range insns {
cookie := RegisterToCookie(ins.CallTarget)
log.Debug("Attaching", "symbol", ins.Symbol, "offset", ins.Offset, "cookie", cookie)
k, err := link.Kprobe(symbol, objs.KprobeSkbBySearch, &link.KprobeOptions{Offset: ins.Offset, Cookie: cookie})
if err != nil {
log.Debug("Failed to attach targets", "symbol", symbol, "offset", ins.Offset, "err", err)
continue
}
defer k.Close()
}

} else {
k, err = link.Kprobe(symbol, objs.KprobeSkbBySearch, &link.KprobeOptions{Offset: offset})
if err != nil {
Expand All @@ -191,15 +193,6 @@ func main() {
}
}

var kdwarf *Kdwarf
if attachByLine {
kdwarf, err = GetKdwarf()
if err != nil {
log.Error("Failed to get kdwarf", "err", err)
return
}
}

skbBuildFuncs := []string{}
btfSpec, err := btf.LoadKernelSpec()
if err != nil {
Expand Down Expand Up @@ -275,11 +268,7 @@ func main() {
return
}

fmt.Printf("%-4s %-18s %-10s %-18s %-16s", "no", "skb", "skb->len", "pc", "ksym")
if attachByLine {
fmt.Printf(" addr2line")
}
fmt.Println()
fmt.Printf("%-4s %-18s %-10s %-18s %-16s\n", "no", "skb", "skb->len", "pc", "ksym")
i := 0

for {
Expand All @@ -303,19 +292,34 @@ func main() {
log.Error("Failed to get dwarf", "err", err)
return
}
sym, _ := NearestKsym(event.At)
ksym, _ := NearestKsym(event.At)

var lineInfo *LineInfo
var insn *Instruction
if attachByLine {
lineInfo, err = kdwarf.GetLineInfo(sym.Name, event.At-sym.Addr-1)
if err != nil {
lineInfo, err = kdwarf.GetLineInfo(sym.Name, event.At-sym.Addr-4)
var ok bool
insn, ok = allInsns[ksym.Name][event.At-ksym.Addr-1]
if !ok {
insn, ok = allInsns[ksym.Name][event.At-ksym.Addr-4]
if !ok {
log.Error("Failed to find insn", "symbol", ksym.Name, "offset", event.At-ksym.Addr)
return
}
}
}

fmt.Printf("%-4d %-18x %-10d %-18x %-16s", i, event.Skb, event.SkbLen, event.At, fmt.Sprintf("%s+%d", sym.Name, event.At-sym.Addr))
fmt.Printf("%-4d %-18x %-10d %-18x %-16s", i, event.Skb, event.SkbLen, event.At, fmt.Sprintf("%s+%d", ksym.Name, event.At-ksym.Addr))
if attachByLine {
fmt.Printf(" %s:%d", lineInfo.Filename, lineInfo.Line)
if insn.LineInfo != nil {
fmt.Printf(" %s:%d", insn.Filename, insn.Line)
}
if insn.Call {
ksym, err := KsymByAddr(event.Call)
if event.Call != 0 && err == nil {
fmt.Printf(" // CALL %s", ksym.Name)
} else {
fmt.Printf(" // CALL %s", insn.CallTarget)
}
}
}
fmt.Println()

Expand Down
40 changes: 38 additions & 2 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,51 @@ func IsDigit(c string) (uint64, bool) {
}
}

address, err := strconv.ParseUint(c, 16, 64)
address, err := strconv.ParseUint(c, 10, 64)
if err == nil {
return address, true
}

address, err = strconv.ParseUint(c, 10, 64)
address, err = strconv.ParseUint(c, 16, 64)
if err == nil {
return address, true
}

return 0, false
}

func RegisterToCookie(register string) (cookie uint64) {
switch register {
case "R15":
cookie = 1
case "R14":
cookie = 2
case "R13":
cookie = 3
case "R12":
cookie = 4
case "RBP":
cookie = 5
case "RBX":
cookie = 6
case "R11":
cookie = 7
case "R10":
cookie = 8
case "R9":
cookie = 9
case "R8":
cookie = 10
case "RAX":
cookie = 11
case "RCX":
cookie = 12
case "RDX":
cookie = 13
case "RSI":
cookie = 14
case "RDI":
cookie = 15
}
return
}

0 comments on commit 2a83bd5

Please sign in to comment.