hc
2023-11-07 f45e756958099c35d6afb746df1d40a1c6302cfc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* Copyright (c) 2016 Facebook
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <linux/bpf.h>
#include <string.h>
#include <linux/perf_event.h>
#include <errno.h>
#include <assert.h>
#include <stdbool.h>
#include <sys/resource.h>
#include "libbpf.h"
#include "bpf_load.h"
#include "trace_helpers.h"
 
#define PRINT_RAW_ADDR 0
 
static void print_ksym(__u64 addr)
{
   struct ksym *sym;
 
   if (!addr)
       return;
   sym = ksym_search(addr);
   if (PRINT_RAW_ADDR)
       printf("%s/%llx;", sym->name, addr);
   else
       printf("%s;", sym->name);
}
 
#define TASK_COMM_LEN 16
 
struct key_t {
   char waker[TASK_COMM_LEN];
   char target[TASK_COMM_LEN];
   __u32 wret;
   __u32 tret;
};
 
static void print_stack(struct key_t *key, __u64 count)
{
   __u64 ip[PERF_MAX_STACK_DEPTH] = {};
   static bool warned;
   int i;
 
   printf("%s;", key->target);
   if (bpf_map_lookup_elem(map_fd[3], &key->tret, ip) != 0) {
       printf("---;");
   } else {
       for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--)
           print_ksym(ip[i]);
   }
   printf("-;");
   if (bpf_map_lookup_elem(map_fd[3], &key->wret, ip) != 0) {
       printf("---;");
   } else {
       for (i = 0; i < PERF_MAX_STACK_DEPTH; i++)
           print_ksym(ip[i]);
   }
   printf(";%s %lld\n", key->waker, count);
 
   if ((key->tret == -EEXIST || key->wret == -EEXIST) && !warned) {
       printf("stackmap collisions seen. Consider increasing size\n");
       warned = true;
   } else if (((int)(key->tret) < 0 || (int)(key->wret) < 0)) {
       printf("err stackid %d %d\n", key->tret, key->wret);
   }
}
 
static void print_stacks(int fd)
{
   struct key_t key = {}, next_key;
   __u64 value;
 
   while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
       bpf_map_lookup_elem(fd, &next_key, &value);
       print_stack(&next_key, value);
       key = next_key;
   }
}
 
static void int_exit(int sig)
{
   print_stacks(map_fd[0]);
   exit(0);
}
 
int main(int argc, char **argv)
{
   struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
   char filename[256];
   int delay = 1;
 
   snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
   setrlimit(RLIMIT_MEMLOCK, &r);
 
   signal(SIGINT, int_exit);
   signal(SIGTERM, int_exit);
 
   if (load_kallsyms()) {
       printf("failed to process /proc/kallsyms\n");
       return 2;
   }
 
   if (load_bpf_file(filename)) {
       printf("%s", bpf_log_buf);
       return 1;
   }
 
   if (argc > 1)
       delay = atoi(argv[1]);
   sleep(delay);
   print_stacks(map_fd[0]);
 
   return 0;
}