ZBLOG

10个ebpf uprobe golang的代码案例

以下是10个使用eBPF、uprobes和Golang的代码案例示例:

  1. 监控函数调用次数:
package main

import (
    "fmt"
    "github.com/iovisor/gobpf/bcc"
)

const program = `
#include <uapi/linux/ptrace.h>

BPF_HASH(counts, u64);

int count_calls(struct pt_regs *ctx) {
    u64 key = PT_REGS_IP(ctx);
    u64* val = counts.lookup_or_init(&key, 0);
    (*val)++;
    return 0;
}
`

func main() {
    module := bcc.NewModule(program, []string{})
    defer module.Close()

    uprobe, err := module.LoadUprobe("count_calls")
    if err != nil {
        fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
        os.Exit(1)
    }

    err = module.AttachUprobe("/path/to/binary", "function_name", uprobe, -1)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
        os.Exit(1)
    }

    perfMap, err := bcc.InitPerfMap(module.LookupTable("counts"), printOutput)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Failed to initialize perf map: %v\n", err)
        os.Exit(1)
    }
    
	perfMap.Start()
	defer perfMap.Stop()

	select {}
}

func printOutput() {
	fmt.Println("Function called!")
}
  1. 统计函数执行时间:
package main

import (
	"fmt"
	"github.com/iovisor/gobpf/bcc"
)

const program = `
#include <uapi/linux/ptrace.h>

struct data_t {
    u64 timestamp;
};

BPF_HASH(start, u32, struct data_t);

int trace_start(struct pt_regs *ctx) {
    u32 pid = bpf_get_current_pid_tgid();
    struct data_t data = {};
    data.timestamp = bpf_ktime_get_ns();
    start.update(&pid, &data);
    return 0;
}

int trace_end(struct pt_regs *ctx) {
    u32 pid = bpf_get_current_pid_tgid();
    struct data_t* start_data = start.lookup(&pid);
    
	if (start_data == 0) {
        return 0;
	}
	
    u64 delta = bpf_ktime_get_ns() - start_data->timestamp;
    
	bpf_trace_printk("%d: Execution time: %llu ns\\n", pid, delta / 1000);
	start.delete(&pid);
	return 0;
}
`

func main() {
	module := bcc.NewModule(program, []string{})
	defer module.Close()

	uprobeStart, err := module.LoadUprobe("trace_start")
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
		os.Exit(1)
	}

	err = module.AttachUprobe("/path/to/binary", "function_name", uprobeStart, -1)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
		os.Exit(1)
	}

	uprobeEnd, err := module.LoadUprobe("trace_end")
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
		os.Exit(1)
	}

	err = module.AttachUretprobe("/path/to/binary", "function_name", uprobeEnd, -1)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
		os.Exit(1)
	}

	bcc.NewTable(module.TableId("start"), module).SetMaxEntries(4096)

	table := bcc.NewTable(module.TableId("counts"), module)

	channel := make(chan []byte)
	module["output"].Attach(channel)
	defer module["output"].Detach()

	go func() {
		for {
			data := <-channel
			fmt.Println(string(data))
		}
	}()

	select {}
}
  1. 监控文件读写操作:
package main

import (
    "fmt"
    "github.com/iovisor/gobpf/bcc"
)

const program = `
#include <uapi/linux/ptrace.h>
#include <linux/fs.h>

BPF_HASH(counts, int);

int trace_read(struct pt_regs *ctx) {
    int pid = bpf_get_current_pid_tgid();
    counts.increment(pid);
    return 0;
}

int trace_write(struct pt_regs *ctx) {
    int pid = bpf_get_current_pid_tgid();
    counts.increment(pid);
    return 0;
}
`

func main() {
    module := bcc.NewModule(program, []string{})
    defer module.Close()

    uprobeRead, err := module.LoadUprobe("trace_read")
    if err != nil {
        fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
        os.Exit(1)
    }

    err = module.AttachUprobe("/path/to/binary", "read_function_name", uprobeRead, -1)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
        os.Exit(1)
    }

	uprobeWrite, err := module.LoadUprobe("trace_write")
	if err != nil {
	    fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
	    os.Exit(1)
	}

	err = module.AttachUprobe("/path/to/binary", "write_function_name", uprobeWrite, -1)
	if err != nil {
	    fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
	    os.Exit(1)
	}

	table := bcc.NewTable(module.TableId("counts"), module)

	channel := make(chan []byte)
	module["output"].Attach(channel)
	defer module["output"].Detach()

	go func() {
	    for {
	        data := <-channel
	        fmt.Println(string(data))
	    }
	}()

	select {}
}
  1. 检测网络数据包:
package main

import (
    "fmt"
    "github.com/iovisor/gobpf/bcc"
)

const program = `
#include <uapi/linux/ptrace.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>

BPF_PERF_OUTPUT(events);

int trace_packet(struct __sk_buff *skb) {
    u8* cursor = 0;
    struct ethhdr* eth = bpf_hdr_pointer(skb);
    
    if (eth->h_proto == htons(ETH_P_IP)) {
        struct iphdr* ip = (struct iphdr *)(cursor + sizeof(struct ethhdr));
        
        if (ip->protocol == IPPROTO_TCP) {
            struct tcphdr* tcp = (struct tcphdr *)(cursor + sizeof(struct ethhdr) + sizeof(struct iphdr));
            
            events.perf_submit(skb, skb->len);
        }
    }

    return 0;
}
`

func main() {
    module := bcc.NewModule(program, []string{})
    defer module.Close()

	uprobePacket, err := module.LoadUprobe("trace_packet")
	if err != nil {
	    fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
	    os.Exit(1)
	}

	err = module.AttachUprobe("/path/to/binary", "packet_function_name", uprobePacket, -1)
	if err != nil {
	    fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
	    os.Exit(1)
	}

	table := bcc.NewTable(module.TableId("events"), module)

	channel := make(chan []byte)
	module["output"].Attach(channel)
	defer module["output"].Detach()

	go func() {
	    for {
	        data := <-channel
	        fmt.Println(string(data))
	    }
	}()

	select {}
}
  1. 监控文件IO耗时:
package main

import (
    "fmt"
    "github.com/iovisor/gobpf/bcc"
)

const program = `
#include <uapi/linux/ptrace.h>
#include <linux/blkdev.h>

BPF_HASH(start, u64);

int trace_start(struct pt_regs *ctx) {
    u64 timestamp = bpf_ktime_get_ns();
    start.update(&ctx->pid, &timestamp);
    return 0;
}

int trace_end(struct pt_regs *ctx) {
    u64* timestamp_ptr = start.lookup(&ctx->pid);
    
	if (timestamp_ptr == NULL) {
        return 0;
	}
	
    u64 delta = bpf_ktime_get_ns() - *timestamp_ptr;
    
	bpf_trace_printk("%d: IO Time: %llu ns\\n", ctx->pid, delta / 1000);
	start.delete(&ctx->pid);
	return 0;
}
`

func main() {
	module := bcc.NewModule(program, []string{})
	defer module.Close()

	uprobeStart, err := module.LoadUprobe("trace_start")
	if err != nil {
	    fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
	    os.Exit(1)
	}

	err = module.AttachUprobe("/path/to/binary", "start_function_name", uprobeStart, -1)
	if err != nil {
	    fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
	    os.Exit(1)
	}

	uprobeEnd, err := module.LoadUprobe("trace_end")
	if err != nil {
	    fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
	    os.Exit(1)
	}

	err = module.AttachUretprobe("/path/to/binary", "end_function_name", uprobeEnd, -1)
	if err != nil {
	    fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
	    os.Exit(1)
	}

	table := bcc.NewTable(module.TableId("counts"), module)

	channel := make(chan []byte)
	module["output"].Attach(channel)
	defer module["output"].Detach()

	go func() {
	    for {
	        data := <-channel
	        fmt.Println(string(data))
	    }
	}()

	select {}
}
  1. 检测TCP连接状态:
package main

import (
    "fmt"
    "github.com/iovisor/gobpf/bcc"
)

const program = `
#include <uapi/linux/ptrace.h>
#include <linux/tcp.h>

BPF_HASH(counts, u32);

int trace_tcp_state(struct pt_regs *ctx) {
    u32 pid = bpf_get_current_pid_tgid();
    struct tcp_sock* tp = (struct tcp_sock*)bpf_get_smp_processor_id();

    if (tp == NULL) {
        return 0;
    }

    u32 state = tp->state;
    counts.increment(state);

    return 0;
}
`

func main() {
	module := bcc.NewModule(program, []string{})
	defer module.Close()

	uprobeState, err := module.LoadUprobe("trace_tcp_state")
	if err != nil {
	    fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
	    os.Exit(1)
	}

	err = module.AttachUprobe("/path/to/binary", "tcp_function_name", uprobeState, -1)
	if err != nil {
	    fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
	    os.Exit(1)
	}

	table := bcc.NewTable(module.TableId("counts"), module)

	channel := make(chan []byte)
	module["output"].Attach(channel)
	defer module["output"].Detach()

	go func() {
	    for {
	        data := <-channel
	        fmt.Println(string(data))
	    }
	}()

	select {}
}
  1. 监控系统调用:
package main

import (
    "fmt"
    "github.com/iovisor/gobpf/bcc"
)

const program = `
#include <uapi/linux/ptrace.h>

BPF_HASH(counts, int);

int trace_syscall_entry(struct pt_regs *ctx) {
    int pid = bpf_get_current_pid_tgid();
    counts.increment(pid);
    
	return 0;
}
`

func main() {
	module := bcc.NewModule(program, []string{})
	defer module.Close()

	uprobeSyscallEntry, err := module.LoadUprobe("trace_syscall_entry")
	if err != nil {
	    fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
	    os.Exit(1)
	}

	err = module.AttachUprobe("/path/to/binary", "__x64_sys_function_name", uprobeSyscallEntry, -1)
	if err != nil {
	    fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
	    os.Exit(1)
	}

	table := bcc.NewTable(module.TableId("counts"), module)

	channel := make(chan []byte)
	module["output"].Attach(channel)
	defer module["output"].Detach()

	go func() {
	    for {
	        data := <-channel
	        fmt.Println(string(data))
	    }
	}()

	select {}
}
  1. 跟踪内存分配和释放:

”`go package main

import (

"fmt"
"github.com/iovisor/gobpf/bcc"

)

const program = ` #include

BPF_HASH(counts, u64);

int trace_alloc(struct pt_regs *ctx) {

counts.increment(0);
return 0;

}

int trace_free(struct pt_regs *ctx) {

counts.decrement(0);
return 0;

} `

func main() {

module := bcc.NewModule(program, []string{})
defer module.Close()

uprobeAlloc, err := module.LoadUprobe("trace_alloc")
if err != nil {
    fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
    os.Exit(1)
}

err = module.AttachUprobe("/path/to/binary", "alloc_function_name", uprobeAlloc, -1)
if err != nil {
    fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
    os.Exit(1)
}

uprobeFree, err := module.LoadUprobe("trace_free")
if err != nil {
    fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
    os.Exit(1)
}

err = module.AttachUprobe("/path/to/binary", "free_function_name", uprobeFree, -1)
if err != nil {
    fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
    os.Exit(1)
}

table := bcc.NewTable(module.TableId("counts"), module)

channel := make(chan []byte)
module["output"].Attach(channel)
defer module["output"].Detach<br/><br/><br/><font size=1 color=#CCCCCC>内容由零声教学AI助手提供,问题来源于学员提问</font>

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=18473

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?