-
Notifications
You must be signed in to change notification settings - Fork 0
/
uv_uprobe.c
156 lines (137 loc) · 3.85 KB
/
uv_uprobe.c
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
/* Copyright (c) 2020 Facebook */
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
#include "uv_uprobe.skel.h"
#include "uprobe_helper.h"
#include <signal.h>
#include <bpf/bpf.h>
#include "uv_uprobe.h"
#define PERF_BUFFER_PAGES 16
#define PERF_POLL_TIMEOUT_MS 100
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
return vfprintf(stderr, format, args);
}
static void bump_memlock_rlimit(void)
{
struct rlimit rlim_new = {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
};
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
exit(1);
}
}
static int exiting = 0;
static void sig_int(int signo)
{
exiting = 1;
}
static void handle_event(void *ctx, int cpu, void *data, __u32 data_sz)
{
const struct event *e = (const struct event *)data;
printf("%s %llu\n", e->name, (e->end_time - e->start_time) / 1000 / 1000);
}
static void handle_lost_events(void *ctx, int cpu, __u64 lost_cnt)
{
//
}
int main(int argc, char **argv)
{
struct uv_uprobe_bpf *skel;
long base_addr, uprobe_offset;
int err, i;
struct perf_buffer_opts pb_opts;
struct perf_buffer *pb = NULL;
char * pid_str = argv[1];
if (!pid_str) {
fprintf(stderr, "please input pid");
return;
}
pid_t pid = (pid_t)atoi(pid_str);
char execpath[500];
int ret = get_pid_binary_path(pid, execpath, 500);
if (ret == -1) {
fprintf(stderr, "invalid pid: %ld\n", pid);
return;
}
fprintf(stderr, "uprobe_execpath: %s\n", execpath);
/* Set up libbpf errors and debug info callback */
libbpf_set_print(libbpf_print_fn);
/* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */
bump_memlock_rlimit();
/* Load and verify BPF application */
skel = uv_uprobe_bpf__open();
if (!skel) {
fprintf(stderr, "Failed to open and load BPF skeleton\n");
return 1;
}
err = uv_uprobe_bpf__load(skel);
if (err) {
warn("failed to load BPF object: %d\n", err);
goto cleanup;
}
/* Attach tracepoint handler */
// get function str by readelf -s | grep your functionname
#define ATTACH_UPROBE(type) \
do \
{ char * func_##type = #type; \
uprobe_offset = get_elf_func_offset(execpath, func_##type); \
if (uprobe_offset == -1) { \
fprintf(stderr, "invalid function &s: %s\n", func_##type); \
break; \
} \
fprintf(stderr, "uprobe_offset: %ld\n", uprobe_offset);\
skel->links.uprobe_##type = bpf_program__attach_uprobe(skel->progs.uprobe_##type,\
false /* not uretprobe */,\
pid,\
execpath,\
uprobe_offset);\
err = libbpf_get_error(skel->links.uprobe_##type);\
if (err) {\
fprintf(stderr, "Failed to attach uprobe: %d\n", err);\
goto cleanup;\
}\
skel->links.uretprobe_##type = bpf_program__attach_uprobe(skel->progs.uretprobe_##type,\
true /* uretprobe */,\
pid /* any pid */,\
execpath,\
uprobe_offset);\
err = libbpf_get_error(skel->links.uretprobe_##type);\
if (err) {\
fprintf(stderr, "Failed to attach uprobe: %d\n", err);\
goto cleanup;\
}\
} while(false);
PHASE(ATTACH_UPROBE)
if (signal(SIGINT, sig_int) == SIG_ERR) {
printf("can't set signal handler: %s\n", strerror(errno));
err = 1;
goto cleanup;
}
pb_opts.sample_cb = handle_event;
pb_opts.lost_cb = handle_lost_events;
pb = perf_buffer__new(bpf_map__fd(skel->maps.events), PERF_BUFFER_PAGES,
&pb_opts);
printf("%-7s %-7s\n", "phase", "interval");
for (i = 0; ; i++) {
if (exiting) {
break;
}
err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
if (err < 0 && errno != EINTR) {
printf("error polling perf buffer: %s\n", strerror(errno));
goto cleanup;
}
/* reset err to return 0 if exiting */
err = 0;
}
cleanup:
uv_uprobe_bpf__destroy(skel);
return -err;
}