Merge tag 'perf-urgent-2020-08-23' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / tools / testing / selftests / bpf / trace_helpers.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <assert.h>
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <poll.h>
9 #include <unistd.h>
10 #include <linux/perf_event.h>
11 #include <sys/mman.h>
12 #include "trace_helpers.h"
13
14 #define DEBUGFS "/sys/kernel/debug/tracing/"
15
16 #define MAX_SYMS 300000
17 static struct ksym syms[MAX_SYMS];
18 static int sym_cnt;
19
20 static int ksym_cmp(const void *p1, const void *p2)
21 {
22         return ((struct ksym *)p1)->addr - ((struct ksym *)p2)->addr;
23 }
24
25 int load_kallsyms(void)
26 {
27         FILE *f = fopen("/proc/kallsyms", "r");
28         char func[256], buf[256];
29         char symbol;
30         void *addr;
31         int i = 0;
32
33         if (!f)
34                 return -ENOENT;
35
36         while (fgets(buf, sizeof(buf), f)) {
37                 if (sscanf(buf, "%p %c %s", &addr, &symbol, func) != 3)
38                         break;
39                 if (!addr)
40                         continue;
41                 syms[i].addr = (long) addr;
42                 syms[i].name = strdup(func);
43                 i++;
44         }
45         fclose(f);
46         sym_cnt = i;
47         qsort(syms, sym_cnt, sizeof(struct ksym), ksym_cmp);
48         return 0;
49 }
50
51 struct ksym *ksym_search(long key)
52 {
53         int start = 0, end = sym_cnt;
54         int result;
55
56         /* kallsyms not loaded. return NULL */
57         if (sym_cnt <= 0)
58                 return NULL;
59
60         while (start < end) {
61                 size_t mid = start + (end - start) / 2;
62
63                 result = key - syms[mid].addr;
64                 if (result < 0)
65                         end = mid;
66                 else if (result > 0)
67                         start = mid + 1;
68                 else
69                         return &syms[mid];
70         }
71
72         if (start >= 1 && syms[start - 1].addr < key &&
73             key < syms[start].addr)
74                 /* valid ksym */
75                 return &syms[start - 1];
76
77         /* out of range. return _stext */
78         return &syms[0];
79 }
80
81 long ksym_get_addr(const char *name)
82 {
83         int i;
84
85         for (i = 0; i < sym_cnt; i++) {
86                 if (strcmp(syms[i].name, name) == 0)
87                         return syms[i].addr;
88         }
89
90         return 0;
91 }
92
93 void read_trace_pipe(void)
94 {
95         int trace_fd;
96
97         trace_fd = open(DEBUGFS "trace_pipe", O_RDONLY, 0);
98         if (trace_fd < 0)
99                 return;
100
101         while (1) {
102                 static char buf[4096];
103                 ssize_t sz;
104
105                 sz = read(trace_fd, buf, sizeof(buf) - 1);
106                 if (sz > 0) {
107                         buf[sz] = 0;
108                         puts(buf);
109                 }
110         }
111 }