ZBLOG

10个ebpf uprobe golang的代码案例

这里给你提供10个使用eBPF和uprobes的Golang代码案例:

  1. 监控函数调用次数:
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. bpf "github.com/iovisor/gobpf/bcc"
  6. )
  7. const source string = `
  8. #include <uapi/linux/ptrace.h>
  9. BPF_HASH(counts, u64);
  10. int count_calls(struct pt_regs *ctx) {
  11. u64 key = PT_REGS_IP(ctx);
  12. u64 *val = counts.lookup(&key);
  13. if (val) {
  14. (*val)++;
  15. } else {
  16. counts.update(&key, &(u64){1});
  17. }
  18. return 0;
  19. }
  20. `
  21. func main() {
  22. m := bpf.NewModule(source, []string{})
  23. defer m.Close()
  24. uprobeFD, err := m.LoadUprobe("count_calls")
  25. if err != nil {
  26. fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
  27. os.Exit(1)
  28. }
  29. err = m.AttachUprobe("/path/to/binary", "function_name", uprobeFD)
  30. if err != nil {
  31. fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
  32. os.Exit(1)
  33. }
  34. table := bpf.NewTable(m.TableId("counts"), m)
  35. it := table.Iter()
  36. for it.Next() {
  37. key := binary.LittleEndian.Uint64(it.Key())
  38. val := binary.LittleEndian.Uint64(it.Leaf())
  39. fmt.Printf("Function at address 0x%x was called %d times\n", key, val)
  40. }
  41. }
  1. 统计函数执行时间:
  1. package main
  2. import (
  3. "fmt"
  4. bpf "github.com/iovisor/gobpf/bcc"
  5. )
  6. const source string = `
  7. #include <uapi/linux/ptrace.h>
  8. BPF_HASH(start, u32);
  9. BPF_HISTOGRAM(dist);
  10. int trace_entry(struct pt_regs *ctx) {
  11. u32 pid = bpf_get_current_pid_tgid();
  12. u64 ts = bpf_ktime_get_ns();
  13. start.update(&pid, &ts);
  14. return 0;
  15. }
  16. int trace_return(struct pt_regs *ctx) {
  17. u32 pid = bpf_get_current_pid_tgid();
  18. u64 *tsp, delta;
  19. tsp = start.lookup(&pid);
  20. if (tsp != 0) {
  21. delta = bpf_ktime_get_ns() - *tsp;
  22. dist.increment(bpf_log2l(delta));
  23. start.delete(&pid);
  24. }
  25. return 0;
  26. }
  27. `
  28. func main() {
  29. m := bpf.NewModule(source, []string{})
  30. defer m.Close()
  31. entryFD, err := m.LoadUprobe("trace_entry")
  32. if err != nil {
  33. fmt.Println(err)
  34. return
  35. }
  36. returnFD, err := m.LoadUprobe("trace_return")
  37. if err != nil {
  38. fmt.Println(err)
  39. return
  40. }
  41. err = m.AttachUprobe("/path/to/binary", "function_name", entryFD)
  42. if err != nil {
  43. fmt.Println(err)
  44. return
  45. }
  46. err = m.AttachUretprobe("/path/to/binary", "function_name", returnFD)
  47. if err != nil {
  48. fmt.Println(err)
  49. return
  50. }
  51. table := bpf.NewTable(m.TableId("dist"), m)
  52. buckets := table.HistogramRead()
  53. for i, count := range buckets {
  54. if count == 0 {
  55. continue
  56. }
  57. lower := 1 << uint32(i)
  58. upper := lower << 1
  59. fmt.Printf("[%d-%d] ns: %d\n", lower, upper, count)
  60. }
  61. }
  1. 监控文件IO调用:
  1. package main
  2. import (
  3. "fmt"
  4. bpf "github.com/iovisor/gobpf/bcc"
  5. )
  6. const source string = `
  7. #include <uapi/linux/ptrace.h>
  8. struct data_t {
  9. u64 ts;
  10. char name[TASK_COMM_LEN];
  11. };
  12. BPF_HASH(start, u32);
  13. BPF_PERF_OUTPUT(events);
  14. int trace_entry(struct pt_regs *ctx) {
  15. struct data_t data = {};
  16. u32 pid = bpf_get_current_pid_tgid();
  17. if (bpf_get_current_comm(&data.name, sizeof(data.name)) == 0) {
  18. data.ts = bpf_ktime_get_ns();
  19. start.update(&pid, &data);
  20. }
  21. return 0;
  22. }
  23. int trace_return(struct pt_regs *ctx) {
  24. struct data_t *datap;
  25. u32 pid = bpf_get_current_pid_tgid();
  26. datap = start.lookup(&pid);
  27. if (datap != 0) {
  28. u64 delta;
  29. delta = bpf_ktime_get_ns() - datap->ts;
  30. events.perf_submit(ctx, datap, sizeof(*datap));
  31. start.delete(&pid);
  32. }
  33. return 0;
  34. }
  35. `
  36. type eventData struct {
  37. Timestamp uint64
  38. Name [16]byte
  39. }
  40. func main() {
  41. m := bpf.NewModule(source, []string{})
  42. defer m.Close()
  43. entryFD, err := m.LoadUprobe("trace_entry")
  44. if err != nil {
  45. fmt.Println(err)
  46. return
  47. }
  48. returnFD, err := m.LoadUprobe("trace_return")
  49. if err != nil {
  50. fmt.Println(err)
  51. return
  52. }
  53. err = m.AttachUprobe("/path/to/binary", "function_name", entryFD)
  54. if err != nil {
  55. fmt.Println(err)
  56. return
  57. }
  58. err = m.AttachUretprobe("/path/to/binary", "function_name", returnFD)
  59. if err != nil {
  60. fmt.Println(err)
  61. return
  62. }
  63. table := bpf.NewTable(m.TableId("events"), m)
  64. channel := make(chan []byte)
  65. perfMap, err := bpf.InitPerfMap(table, channel)
  66. if err != nil {
  67. fmt.Println(err)
  68. return
  69. }
  70. go func() {
  71. for data := range channel {
  72. var event eventData
  73. err = binary.Read(bytes.NewBuffer(data), binary.LittleEndian, &event)
  74. if err != nil {
  75. fmt.Println(err)
  76. continue
  77. }
  78. fmt.Printf("Process: %s, Timestamp: %d\n", string(event.Name[:]), event.Timestamp)
  79. }
  80. }()
  81. select {}
  82. }
  1. 监控系统调用:
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. bpf "github.com/iovisor/gobpf/bcc"
  6. )
  7. const source string = `
  8. #include <uapi/linux/ptrace.h>
  9. BPF_HASH(syscall_counts, u32);
  10. int count_syscalls(struct pt_regs *ctx) {
  11. u32 pid = bpf_get_current_pid_tgid();
  12. u64 *count = syscall_counts.lookup(&pid);
  13. if (count) {
  14. (*count)++;
  15. } else {
  16. syscall_counts.update(&pid, &(u64){1});
  17. }
  18. return 0;
  19. }
  20. `
  21. func main() {
  22. m := bpf.NewModule(source, []string{})
  23. defer m.Close()
  24. syscallFD, err := m.LoadUprobe("count_syscalls")
  25. if err != nil {
  26. fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
  27. os.Exit(1)
  28. }
  29. err = m.AttachUprobe("", "__x64_sys_read", syscallFD)
  30. if err != nil {
  31. fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
  32. os.Exit(1)
  33. }
  34. table := bpf.NewTable(m.TableId("syscall_counts"), m)
  35. it := table.Iter()
  36. for it.Next() {
  37. pid := binary.LittleEndian.Uint32(it.Key())
  38. count := binary.LittleEndian.Uint64(it.Leaf())
  39. fmt.Printf("Process with PID %d made %d syscalls\n", pid, count)
  40. }
  41. }
  1. 拦截网络数据包:
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. bpf "github.com/iovisor/gobpf/bcc"
  6. )
  7. const source string = `
  8. #include <uapi/linux/ptrace.h>
  9. #include <bcc/proto.h>
  10. BPF_PERF_OUTPUT(events);
  11. int trace_packet(struct __sk_buff *skb) {
  12. u8 *cursor = 0;
  13. struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
  14. if (ethernet->type == ETH_P_IP) {
  15. struct ip_t *ip = cursor_advance(cursor, sizeof(*ip));
  16. if (ip->protocol == IPPROTO_TCP) {
  17. struct tcp_t *tcp = cursor_advance(cursor, sizeof(*tcp));
  18. if (tcp->dest == bpf_htons(80)) { // HTTP traffic
  19. events.perf_submit(skb, skb->len);
  20. }
  21. }
  22. }
  23. return 0;
  24. }
  25. `
  26. func main() {
  27. m := bpf.NewModule(source, []string{})
  28. defer m.Close()
  29. uprobeFD, err := m.LoadUprobe("trace_packet")
  30. if err != nil {
  31. fmt.Fprintf(os.Stderr, "Failed to load uprobe: %v\n", err)
  32. os.Exit(1)
  33. }
  34. err = m.AttachUprobe("tcp_sendmsg", uprobeFD)
  35. if err != nil {
  36. fmt.Fprintf(os.Stderr, "Failed to attach uprobe: %v\n", err)
  37. os.Exit(1)
  38. }
  39. perfMap, err := bpf.InitPerfMap(m.TableId("events"), printPacketSize)
  40. if err != nil {
  41. fmt.Fprintf(os.Stderr, "Failed to initialize perf map: %v\n", err)
  42. os.Exit(1)
  43. }
  44. perfMap.Start()
  45. select {}
  46. }
  47. func printPacketSize(data []byte) {
  48. fmt.Printf("Received packet of size %d bytes\n", len(data))
  49. }
  1. 拦截文件读写操作:
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. bpf "github.com/iovisor/gobpf/bcc"
  6. )
  7. const source string = `
  8. #include <uapi/linux/ptrace.h>
  9. #include <linux/sched.h>
  10. struct key_t {
  11. int id;
  12. u64 inode;
  13. char name[TASK_COMM_LEN];
  14. };
  15. BPF_HASH(open_files, struct key_t);
  16. int trace_open(struct pt_regs *ctx) {
  17. struct key_t key = {};
  18. u64 id = bpf_get_current_pid_tgid();
  19. key.id = id >> 32;
  20. key.inode = PT_REGS_RC(ctx);
  21. bpf_get_current_comm(&key.name, sizeof(key.name));
  22. open_files.update(&key, &id);
  23. return 0;
  24. }
  25. int trace_close(struct pt_regs *ctx) {
  26. struct key_t key = {};
  27. u64 id = bpf_get_current_pid_tgid();
  28. key.id = id >> 32;
  29. key.inode = PT_REGS_RC(ctx);
  30. bpf_get_current_comm(&key.name, sizeof(key.name));
  31. open_files.delete(&key);
  32. return 0;
  33. }
  34. `
  35. type fileKey struct {
  36. ID int32
  37. Inode uint64
  38. Name [16]byte
  39. }
  40. func main() {
  41. m := bpf.NewModule(source, []string{})
  42. defer m.Close()
  43. openFD, err := m.LoadUprobe("trace_open")
  44. if err != nil {
  45. fmt.Println(err)
  46. return
  47. }
  48. closeFD, err := m.LoadUprobe("trace_close")
  49. if err != nil {
  50. fmt.Println(err)
  51. return
  52. }
  53. err = m.AttachUprobe("/path/to/binary", "open", openFD)
  54. if err != nil {
  55. fmt.Println(err)
  56. return
  57. }
  58. err = m.AttachUretprobe("/path/to/binary", "close", closeFD)
  59. if err != nil {
  60. fmt.Println(err)
  61. return
  62. }
  63. table := bpf.NewTable(m.TableId("open_files"), m)
  64. channel := make(chan []byte)
  65. perfMap, err := bpf.InitPerfMap(table, channel)
  66. if err != nil {
  67. fmt.Println(err)
  68. return
  69. }
  70. go func() {
  71. for data := range channel {
  72. var key fileKey
  73. err = binary.Read(bytes.NewBuffer(data), binary.LittleEndian, &key)
  74. if err != nil {
  75. fmt.Println(err)
  76. continue
  77. }
  78. fmt.Printf("Process: %s opened file with inode %d\n", string(key.Name[:]), key.Inode)
  79. }
  80. }()
  81. select {}
  82. }
  1. 监控TCP连接:
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. bpf "github.com/iovisor/gobpf/bcc"
  6. )
  7. const source string = `
  8. #include <uapi/linux/ptrace.h>
  9. #include <linux/sched.h>
  10. struct key_t {
  11. u64 ip;
  12. u64 pid;
  13. };
  14. BPF_HASH(tcp_connections, struct key_t);
  15. int trace_connect(struct pt_regs *ctx) {
  16. struct key_t key = {};
  17. u64 ip = PT_REGS_RC(ctx);
  18. u64 pid = bpf_get_current_pid_tgid();
  19. key.ip = ip;
  20. key.pid = pid;
  21. tcp_connections.update(&key, &ip);
  22. return 0;
  23. }
  24. int trace_accept(struct pt_regs *ctx) {
  25. struct key_t key = {};
  26. u64 ip = PT_REGS_RC(ctx);
  27. u64 pid = bpf_get_current_pid_tgid();
  28. key.ip = ip;
  29. key.pid = pid;
  30. tcp_connections.update(&key, &ip);
  31. return 0;
  32. }
  33. `
  34. type connectionKey struct {
  35. IP uint64
  36. PID uint64
  37. }
  38. func main() {
  39. m := bpf.NewModule(source, []string{})
  40. defer m.Close()
  41. connectFD, err := m.LoadUprobe("trace_connect")
  42. if err != nil {
  43. fmt.Println(err)
  44. return
  45. }
  46. acceptFD, err := m.LoadUprobe("trace_accept")
  47. if err != nil {
  48. fmt.Println(err)
  49. return
  50. }
  51. err = m.AttachUprobe("/path/to/binary", "connect", connectFD)
  52. if err != nil {
  53. fmt.Println(err)
  54. return
  55. }
  56. err = m.AttachUprobe("/path/to/binary", "accept", acceptFD)
  57. if err != nil {
  58. fmt.Println(err)
  59. return
  60. }
  61. table := bpf.NewTable(m.TableId("tcp_connections"), m)
  62. it := table.Iter()
  63. for it.Next() {
  64. var key connectionKey
  65. var ip uint64
  66. if binary.Read(bytes.NewBuffer(it.Key()), binary.LittleEndian, &key) == nil &&
  67. binary.Read(bytes.NewBuffer(it.Leaf()), binary.LittleEndian, &ip) == nil {
  68. fmt.Printf("Process with PID %d connected to IP %d\n", key.PID, ip)
  69. }
  70. }
  71. }
  1. 监控内存分配:

”`go package main

import (

  1. "fmt"
  2. "os"
  3. bpf "github.com/iovisor/gobpf/bcc"

)

const source string = ` #include

BPF_HASH(allocations, u64);

int trace


内容由零声教学AI助手提供,问题来源于学员提问

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

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

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

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?