trace_event_kern.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /* Copyright (c) 2016 Facebook
  2. *
  3. * This program is free software; you can redistribute it and/or
  4. * modify it under the terms of version 2 of the GNU General Public
  5. * License as published by the Free Software Foundation.
  6. */
  7. #include <linux/ptrace.h>
  8. #include <uapi/linux/bpf.h>
  9. #include <uapi/linux/bpf_perf_event.h>
  10. #include <uapi/linux/perf_event.h>
  11. #include <bpf/bpf_helpers.h>
  12. #include <bpf/bpf_tracing.h>
  13. struct key_t {
  14. char comm[TASK_COMM_LEN];
  15. u32 kernstack;
  16. u32 userstack;
  17. };
  18. struct {
  19. __uint(type, BPF_MAP_TYPE_HASH);
  20. __type(key, struct key_t);
  21. __type(value, u64);
  22. __uint(max_entries, 10000);
  23. } counts SEC(".maps");
  24. struct {
  25. __uint(type, BPF_MAP_TYPE_STACK_TRACE);
  26. __uint(key_size, sizeof(u32));
  27. __uint(value_size, PERF_MAX_STACK_DEPTH * sizeof(u64));
  28. __uint(max_entries, 10000);
  29. } stackmap SEC(".maps");
  30. #define KERN_STACKID_FLAGS (0 | BPF_F_FAST_STACK_CMP)
  31. #define USER_STACKID_FLAGS (0 | BPF_F_FAST_STACK_CMP | BPF_F_USER_STACK)
  32. SEC("perf_event")
  33. int bpf_prog1(struct bpf_perf_event_data *ctx)
  34. {
  35. char time_fmt1[] = "Time Enabled: %llu, Time Running: %llu";
  36. char time_fmt2[] = "Get Time Failed, ErrCode: %d";
  37. char addr_fmt[] = "Address recorded on event: %llx";
  38. char fmt[] = "CPU-%d period %lld ip %llx";
  39. u32 cpu = bpf_get_smp_processor_id();
  40. struct bpf_perf_event_value value_buf;
  41. struct key_t key;
  42. u64 *val, one = 1;
  43. int ret;
  44. if (ctx->sample_period < 10000)
  45. /* ignore warmup */
  46. return 0;
  47. bpf_get_current_comm(&key.comm, sizeof(key.comm));
  48. key.kernstack = bpf_get_stackid(ctx, &stackmap, KERN_STACKID_FLAGS);
  49. key.userstack = bpf_get_stackid(ctx, &stackmap, USER_STACKID_FLAGS);
  50. if ((int)key.kernstack < 0 && (int)key.userstack < 0) {
  51. bpf_trace_printk(fmt, sizeof(fmt), cpu, ctx->sample_period,
  52. PT_REGS_IP(&ctx->regs));
  53. return 0;
  54. }
  55. ret = bpf_perf_prog_read_value(ctx, (void *)&value_buf, sizeof(struct bpf_perf_event_value));
  56. if (!ret)
  57. bpf_trace_printk(time_fmt1, sizeof(time_fmt1), value_buf.enabled, value_buf.running);
  58. else
  59. bpf_trace_printk(time_fmt2, sizeof(time_fmt2), ret);
  60. if (ctx->addr != 0)
  61. bpf_trace_printk(addr_fmt, sizeof(addr_fmt), ctx->addr);
  62. val = bpf_map_lookup_elem(&counts, &key);
  63. if (val)
  64. (*val)++;
  65. else
  66. bpf_map_update_elem(&counts, &key, &one, BPF_NOEXIST);
  67. return 0;
  68. }
  69. char _license[] SEC("license") = "GPL";