1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker * Copyright (c) 2015 PLUMgrid, Inc.
3*387f9dfdSAndroid Build Coastguard Worker *
4*387f9dfdSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*387f9dfdSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*387f9dfdSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*387f9dfdSAndroid Build Coastguard Worker *
8*387f9dfdSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*387f9dfdSAndroid Build Coastguard Worker *
10*387f9dfdSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*387f9dfdSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*387f9dfdSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*387f9dfdSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*387f9dfdSAndroid Build Coastguard Worker * limitations under the License.
15*387f9dfdSAndroid Build Coastguard Worker */
16*387f9dfdSAndroid Build Coastguard Worker #ifndef _GNU_SOURCE
17*387f9dfdSAndroid Build Coastguard Worker #define _GNU_SOURCE
18*387f9dfdSAndroid Build Coastguard Worker #endif
19*387f9dfdSAndroid Build Coastguard Worker
20*387f9dfdSAndroid Build Coastguard Worker #include "libbpf.h"
21*387f9dfdSAndroid Build Coastguard Worker
22*387f9dfdSAndroid Build Coastguard Worker #include <arpa/inet.h>
23*387f9dfdSAndroid Build Coastguard Worker #include <errno.h>
24*387f9dfdSAndroid Build Coastguard Worker #include <fcntl.h>
25*387f9dfdSAndroid Build Coastguard Worker #include <inttypes.h>
26*387f9dfdSAndroid Build Coastguard Worker #include <libgen.h>
27*387f9dfdSAndroid Build Coastguard Worker #include <limits.h>
28*387f9dfdSAndroid Build Coastguard Worker #include <linux/bpf.h>
29*387f9dfdSAndroid Build Coastguard Worker #include <linux/bpf_common.h>
30*387f9dfdSAndroid Build Coastguard Worker #include <linux/if_alg.h>
31*387f9dfdSAndroid Build Coastguard Worker #include <linux/if_packet.h>
32*387f9dfdSAndroid Build Coastguard Worker #include <linux/perf_event.h>
33*387f9dfdSAndroid Build Coastguard Worker #include <linux/pkt_cls.h>
34*387f9dfdSAndroid Build Coastguard Worker #include <linux/rtnetlink.h>
35*387f9dfdSAndroid Build Coastguard Worker #include <linux/sched.h>
36*387f9dfdSAndroid Build Coastguard Worker #include <linux/types.h>
37*387f9dfdSAndroid Build Coastguard Worker #include <linux/unistd.h>
38*387f9dfdSAndroid Build Coastguard Worker #include <linux/version.h>
39*387f9dfdSAndroid Build Coastguard Worker #include <net/ethernet.h>
40*387f9dfdSAndroid Build Coastguard Worker #include <net/if.h>
41*387f9dfdSAndroid Build Coastguard Worker #include <sched.h>
42*387f9dfdSAndroid Build Coastguard Worker #include <stdbool.h>
43*387f9dfdSAndroid Build Coastguard Worker #include <stdio.h>
44*387f9dfdSAndroid Build Coastguard Worker #include <stdlib.h>
45*387f9dfdSAndroid Build Coastguard Worker #include <string.h>
46*387f9dfdSAndroid Build Coastguard Worker #include <sys/ioctl.h>
47*387f9dfdSAndroid Build Coastguard Worker #include <sys/resource.h>
48*387f9dfdSAndroid Build Coastguard Worker #include <sys/stat.h>
49*387f9dfdSAndroid Build Coastguard Worker #include <sys/types.h>
50*387f9dfdSAndroid Build Coastguard Worker #include <sys/vfs.h>
51*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h>
52*387f9dfdSAndroid Build Coastguard Worker
53*387f9dfdSAndroid Build Coastguard Worker #include "bcc_zip.h"
54*387f9dfdSAndroid Build Coastguard Worker #include "perf_reader.h"
55*387f9dfdSAndroid Build Coastguard Worker
56*387f9dfdSAndroid Build Coastguard Worker // TODO: Remove this when CentOS 6 support is not needed anymore
57*387f9dfdSAndroid Build Coastguard Worker #include "setns.h"
58*387f9dfdSAndroid Build Coastguard Worker
59*387f9dfdSAndroid Build Coastguard Worker #include "bcc_libbpf_inc.h"
60*387f9dfdSAndroid Build Coastguard Worker
61*387f9dfdSAndroid Build Coastguard Worker // TODO: remove these defines when linux-libc-dev exports them properly
62*387f9dfdSAndroid Build Coastguard Worker
63*387f9dfdSAndroid Build Coastguard Worker #ifndef __NR_bpf
64*387f9dfdSAndroid Build Coastguard Worker #if defined(__powerpc64__)
65*387f9dfdSAndroid Build Coastguard Worker #define __NR_bpf 361
66*387f9dfdSAndroid Build Coastguard Worker #elif defined(__s390x__)
67*387f9dfdSAndroid Build Coastguard Worker #define __NR_bpf 351
68*387f9dfdSAndroid Build Coastguard Worker #elif defined(__aarch64__)
69*387f9dfdSAndroid Build Coastguard Worker #define __NR_bpf 280
70*387f9dfdSAndroid Build Coastguard Worker #else
71*387f9dfdSAndroid Build Coastguard Worker #define __NR_bpf 321
72*387f9dfdSAndroid Build Coastguard Worker #endif
73*387f9dfdSAndroid Build Coastguard Worker #endif
74*387f9dfdSAndroid Build Coastguard Worker
75*387f9dfdSAndroid Build Coastguard Worker #ifndef SO_ATTACH_BPF
76*387f9dfdSAndroid Build Coastguard Worker #define SO_ATTACH_BPF 50
77*387f9dfdSAndroid Build Coastguard Worker #endif
78*387f9dfdSAndroid Build Coastguard Worker
79*387f9dfdSAndroid Build Coastguard Worker #ifndef PERF_EVENT_IOC_SET_BPF
80*387f9dfdSAndroid Build Coastguard Worker #define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)
81*387f9dfdSAndroid Build Coastguard Worker #endif
82*387f9dfdSAndroid Build Coastguard Worker
83*387f9dfdSAndroid Build Coastguard Worker #ifndef PERF_FLAG_FD_CLOEXEC
84*387f9dfdSAndroid Build Coastguard Worker #define PERF_FLAG_FD_CLOEXEC (1UL << 3)
85*387f9dfdSAndroid Build Coastguard Worker #endif
86*387f9dfdSAndroid Build Coastguard Worker
87*387f9dfdSAndroid Build Coastguard Worker // TODO: Remove this when CentOS 6 support is not needed anymore
88*387f9dfdSAndroid Build Coastguard Worker #ifndef AF_ALG
89*387f9dfdSAndroid Build Coastguard Worker #define AF_ALG 38
90*387f9dfdSAndroid Build Coastguard Worker #endif
91*387f9dfdSAndroid Build Coastguard Worker
92*387f9dfdSAndroid Build Coastguard Worker #ifndef min
93*387f9dfdSAndroid Build Coastguard Worker #define min(x, y) ((x) < (y) ? (x) : (y))
94*387f9dfdSAndroid Build Coastguard Worker #endif
95*387f9dfdSAndroid Build Coastguard Worker
96*387f9dfdSAndroid Build Coastguard Worker #define UNUSED(expr) do { (void)(expr); } while (0)
97*387f9dfdSAndroid Build Coastguard Worker
98*387f9dfdSAndroid Build Coastguard Worker #define PERF_UPROBE_REF_CTR_OFFSET_SHIFT 32
99*387f9dfdSAndroid Build Coastguard Worker
100*387f9dfdSAndroid Build Coastguard Worker #ifndef BPF_FS_MAGIC
101*387f9dfdSAndroid Build Coastguard Worker #define BPF_FS_MAGIC 0xcafe4a11
102*387f9dfdSAndroid Build Coastguard Worker #endif
103*387f9dfdSAndroid Build Coastguard Worker
104*387f9dfdSAndroid Build Coastguard Worker struct bpf_helper {
105*387f9dfdSAndroid Build Coastguard Worker char *name;
106*387f9dfdSAndroid Build Coastguard Worker char *required_version;
107*387f9dfdSAndroid Build Coastguard Worker };
108*387f9dfdSAndroid Build Coastguard Worker
109*387f9dfdSAndroid Build Coastguard Worker static struct bpf_helper helpers[] = {
110*387f9dfdSAndroid Build Coastguard Worker {"map_lookup_elem", "3.19"},
111*387f9dfdSAndroid Build Coastguard Worker {"map_update_elem", "3.19"},
112*387f9dfdSAndroid Build Coastguard Worker {"map_delete_elem", "3.19"},
113*387f9dfdSAndroid Build Coastguard Worker {"probe_read", "4.1"},
114*387f9dfdSAndroid Build Coastguard Worker {"ktime_get_ns", "4.1"},
115*387f9dfdSAndroid Build Coastguard Worker {"trace_printk", "4.1"},
116*387f9dfdSAndroid Build Coastguard Worker {"get_prandom_u32", "4.1"},
117*387f9dfdSAndroid Build Coastguard Worker {"get_smp_processor_id", "4.1"},
118*387f9dfdSAndroid Build Coastguard Worker {"skb_store_bytes", "4.1"},
119*387f9dfdSAndroid Build Coastguard Worker {"l3_csum_replace", "4.1"},
120*387f9dfdSAndroid Build Coastguard Worker {"l4_csum_replace", "4.1"},
121*387f9dfdSAndroid Build Coastguard Worker {"tail_call", "4.2"},
122*387f9dfdSAndroid Build Coastguard Worker {"clone_redirect", "4.2"},
123*387f9dfdSAndroid Build Coastguard Worker {"get_current_pid_tgid", "4.2"},
124*387f9dfdSAndroid Build Coastguard Worker {"get_current_uid_gid", "4.2"},
125*387f9dfdSAndroid Build Coastguard Worker {"get_current_comm", "4.2"},
126*387f9dfdSAndroid Build Coastguard Worker {"get_cgroup_classid", "4.3"},
127*387f9dfdSAndroid Build Coastguard Worker {"skb_vlan_push", "4.3"},
128*387f9dfdSAndroid Build Coastguard Worker {"skb_vlan_pop", "4.3"},
129*387f9dfdSAndroid Build Coastguard Worker {"skb_get_tunnel_key", "4.3"},
130*387f9dfdSAndroid Build Coastguard Worker {"skb_set_tunnel_key", "4.3"},
131*387f9dfdSAndroid Build Coastguard Worker {"perf_event_read", "4.3"},
132*387f9dfdSAndroid Build Coastguard Worker {"redirect", "4.4"},
133*387f9dfdSAndroid Build Coastguard Worker {"get_route_realm", "4.4"},
134*387f9dfdSAndroid Build Coastguard Worker {"perf_event_output", "4.4"},
135*387f9dfdSAndroid Build Coastguard Worker {"skb_load_bytes", "4.5"},
136*387f9dfdSAndroid Build Coastguard Worker {"get_stackid", "4.6"},
137*387f9dfdSAndroid Build Coastguard Worker {"csum_diff", "4.6"},
138*387f9dfdSAndroid Build Coastguard Worker {"skb_get_tunnel_opt", "4.6"},
139*387f9dfdSAndroid Build Coastguard Worker {"skb_set_tunnel_opt", "4.6"},
140*387f9dfdSAndroid Build Coastguard Worker {"skb_change_proto", "4.8"},
141*387f9dfdSAndroid Build Coastguard Worker {"skb_change_type", "4.8"},
142*387f9dfdSAndroid Build Coastguard Worker {"skb_under_cgroup", "4.8"},
143*387f9dfdSAndroid Build Coastguard Worker {"get_hash_recalc", "4.8"},
144*387f9dfdSAndroid Build Coastguard Worker {"get_current_task", "4.8"},
145*387f9dfdSAndroid Build Coastguard Worker {"probe_write_user", "4.8"},
146*387f9dfdSAndroid Build Coastguard Worker {"current_task_under_cgroup", "4.9"},
147*387f9dfdSAndroid Build Coastguard Worker {"skb_change_tail", "4.9"},
148*387f9dfdSAndroid Build Coastguard Worker {"skb_pull_data", "4.9"},
149*387f9dfdSAndroid Build Coastguard Worker {"csum_update", "4.9"},
150*387f9dfdSAndroid Build Coastguard Worker {"set_hash_invalid", "4.9"},
151*387f9dfdSAndroid Build Coastguard Worker {"get_numa_node_id", "4.10"},
152*387f9dfdSAndroid Build Coastguard Worker {"skb_change_head", "4.10"},
153*387f9dfdSAndroid Build Coastguard Worker {"xdp_adjust_head", "4.10"},
154*387f9dfdSAndroid Build Coastguard Worker {"probe_read_str", "4.11"},
155*387f9dfdSAndroid Build Coastguard Worker {"get_socket_cookie", "4.12"},
156*387f9dfdSAndroid Build Coastguard Worker {"get_socket_uid", "4.12"},
157*387f9dfdSAndroid Build Coastguard Worker {"set_hash", "4.13"},
158*387f9dfdSAndroid Build Coastguard Worker {"setsockopt", "4.13"},
159*387f9dfdSAndroid Build Coastguard Worker {"skb_adjust_room", "4.13"},
160*387f9dfdSAndroid Build Coastguard Worker {"redirect_map", "4.14"},
161*387f9dfdSAndroid Build Coastguard Worker {"sk_redirect_map", "4.14"},
162*387f9dfdSAndroid Build Coastguard Worker {"sock_map_update", "4.14"},
163*387f9dfdSAndroid Build Coastguard Worker {"xdp_adjust_meta", "4.15"},
164*387f9dfdSAndroid Build Coastguard Worker {"perf_event_read_value", "4.15"},
165*387f9dfdSAndroid Build Coastguard Worker {"perf_prog_read_value", "4.15"},
166*387f9dfdSAndroid Build Coastguard Worker {"getsockopt", "4.15"},
167*387f9dfdSAndroid Build Coastguard Worker {"override_return", "4.16"},
168*387f9dfdSAndroid Build Coastguard Worker {"sock_ops_cb_flags_set", "4.16"},
169*387f9dfdSAndroid Build Coastguard Worker {"msg_redirect_map", "4.17"},
170*387f9dfdSAndroid Build Coastguard Worker {"msg_apply_bytes", "4.17"},
171*387f9dfdSAndroid Build Coastguard Worker {"msg_cork_bytes", "4.17"},
172*387f9dfdSAndroid Build Coastguard Worker {"msg_pull_data", "4.17"},
173*387f9dfdSAndroid Build Coastguard Worker {"bind", "4.17"},
174*387f9dfdSAndroid Build Coastguard Worker {"xdp_adjust_tail", "4.18"},
175*387f9dfdSAndroid Build Coastguard Worker {"skb_get_xfrm_state", "4.18"},
176*387f9dfdSAndroid Build Coastguard Worker {"get_stack", "4.18"},
177*387f9dfdSAndroid Build Coastguard Worker {"skb_load_bytes_relative", "4.18"},
178*387f9dfdSAndroid Build Coastguard Worker {"fib_lookup", "4.18"},
179*387f9dfdSAndroid Build Coastguard Worker {"sock_hash_update", "4.18"},
180*387f9dfdSAndroid Build Coastguard Worker {"msg_redirect_hash", "4.18"},
181*387f9dfdSAndroid Build Coastguard Worker {"sk_redirect_hash", "4.18"},
182*387f9dfdSAndroid Build Coastguard Worker {"lwt_push_encap", "4.18"},
183*387f9dfdSAndroid Build Coastguard Worker {"lwt_seg6_store_bytes", "4.18"},
184*387f9dfdSAndroid Build Coastguard Worker {"lwt_seg6_adjust_srh", "4.18"},
185*387f9dfdSAndroid Build Coastguard Worker {"lwt_seg6_action", "4.18"},
186*387f9dfdSAndroid Build Coastguard Worker {"rc_repeat", "4.18"},
187*387f9dfdSAndroid Build Coastguard Worker {"rc_keydown", "4.18"},
188*387f9dfdSAndroid Build Coastguard Worker {"skb_cgroup_id", "4.18"},
189*387f9dfdSAndroid Build Coastguard Worker {"get_current_cgroup_id", "4.18"},
190*387f9dfdSAndroid Build Coastguard Worker {"get_local_storage", "4.19"},
191*387f9dfdSAndroid Build Coastguard Worker {"sk_select_reuseport", "4.19"},
192*387f9dfdSAndroid Build Coastguard Worker {"skb_ancestor_cgroup_id", "4.19"},
193*387f9dfdSAndroid Build Coastguard Worker {"sk_lookup_tcp", "4.20"},
194*387f9dfdSAndroid Build Coastguard Worker {"sk_lookup_udp", "4.20"},
195*387f9dfdSAndroid Build Coastguard Worker {"sk_release", "4.20"},
196*387f9dfdSAndroid Build Coastguard Worker {"map_push_elem", "4.20"},
197*387f9dfdSAndroid Build Coastguard Worker {"map_pop_elem", "4.20"},
198*387f9dfdSAndroid Build Coastguard Worker {"map_peak_elem", "4.20"},
199*387f9dfdSAndroid Build Coastguard Worker {"msg_push_data", "4.20"},
200*387f9dfdSAndroid Build Coastguard Worker {"msg_pop_data", "5.0"},
201*387f9dfdSAndroid Build Coastguard Worker {"rc_pointer_rel", "5.0"},
202*387f9dfdSAndroid Build Coastguard Worker {"spin_lock", "5.1"},
203*387f9dfdSAndroid Build Coastguard Worker {"spin_unlock", "5.1"},
204*387f9dfdSAndroid Build Coastguard Worker {"sk_fullsock", "5.1"},
205*387f9dfdSAndroid Build Coastguard Worker {"tcp_sock", "5.1"},
206*387f9dfdSAndroid Build Coastguard Worker {"skb_ecn_set_ce", "5.1"},
207*387f9dfdSAndroid Build Coastguard Worker {"get_listener_sock", "5.1"},
208*387f9dfdSAndroid Build Coastguard Worker {"skc_lookup_tcp", "5.2"},
209*387f9dfdSAndroid Build Coastguard Worker {"tcp_check_syncookie", "5.2"},
210*387f9dfdSAndroid Build Coastguard Worker {"sysctl_get_name", "5.2"},
211*387f9dfdSAndroid Build Coastguard Worker {"sysctl_get_current_value", "5.2"},
212*387f9dfdSAndroid Build Coastguard Worker {"sysctl_get_new_value", "5.2"},
213*387f9dfdSAndroid Build Coastguard Worker {"sysctl_set_new_value", "5.2"},
214*387f9dfdSAndroid Build Coastguard Worker {"strtol", "5.2"},
215*387f9dfdSAndroid Build Coastguard Worker {"strtoul", "5.2"},
216*387f9dfdSAndroid Build Coastguard Worker {"sk_storage_get", "5.2"},
217*387f9dfdSAndroid Build Coastguard Worker {"sk_storage_delete", "5.2"},
218*387f9dfdSAndroid Build Coastguard Worker {"send_signal", "5.3"},
219*387f9dfdSAndroid Build Coastguard Worker {"tcp_gen_syncookie", "5.3"},
220*387f9dfdSAndroid Build Coastguard Worker {"skb_output", "5.5"},
221*387f9dfdSAndroid Build Coastguard Worker {"probe_read_user", "5.5"},
222*387f9dfdSAndroid Build Coastguard Worker {"probe_read_kernel", "5.5"},
223*387f9dfdSAndroid Build Coastguard Worker {"probe_read_user_str", "5.5"},
224*387f9dfdSAndroid Build Coastguard Worker {"probe_read_kernel_str", "5.5"},
225*387f9dfdSAndroid Build Coastguard Worker {"tcp_send_ack", "5.5"},
226*387f9dfdSAndroid Build Coastguard Worker {"send_signal_thread", "5.5"},
227*387f9dfdSAndroid Build Coastguard Worker {"jiffies64", "5.5"},
228*387f9dfdSAndroid Build Coastguard Worker {"read_branch_records", "5.6"},
229*387f9dfdSAndroid Build Coastguard Worker {"get_ns_current_pid_tgid", "5.6"},
230*387f9dfdSAndroid Build Coastguard Worker {"xdp_output", "5.6"},
231*387f9dfdSAndroid Build Coastguard Worker {"get_netns_cookie", "5.6"},
232*387f9dfdSAndroid Build Coastguard Worker {"get_current_ancestor_cgroup_id", "5.6"},
233*387f9dfdSAndroid Build Coastguard Worker {"sk_assign", "5.6"},
234*387f9dfdSAndroid Build Coastguard Worker {"ktime_get_boot_ns", "5.7"},
235*387f9dfdSAndroid Build Coastguard Worker {"seq_printf", "5.7"},
236*387f9dfdSAndroid Build Coastguard Worker {"seq_write", "5.7"},
237*387f9dfdSAndroid Build Coastguard Worker {"sk_cgroup_id", "5.7"},
238*387f9dfdSAndroid Build Coastguard Worker {"sk_ancestor_cgroup_id", "5.7"},
239*387f9dfdSAndroid Build Coastguard Worker {"csum_level", "5.7"},
240*387f9dfdSAndroid Build Coastguard Worker {"ringbuf_output", "5.8"},
241*387f9dfdSAndroid Build Coastguard Worker {"ringbuf_reserve", "5.8"},
242*387f9dfdSAndroid Build Coastguard Worker {"ringbuf_submit", "5.8"},
243*387f9dfdSAndroid Build Coastguard Worker {"ringbuf_discard", "5.8"},
244*387f9dfdSAndroid Build Coastguard Worker {"ringbuf_query", "5.8"},
245*387f9dfdSAndroid Build Coastguard Worker {"skc_to_tcp6_sock", "5.9"},
246*387f9dfdSAndroid Build Coastguard Worker {"skc_to_tcp_sock", "5.9"},
247*387f9dfdSAndroid Build Coastguard Worker {"skc_to_tcp_timewait_sock", "5.9"},
248*387f9dfdSAndroid Build Coastguard Worker {"skc_to_tcp_request_sock", "5.9"},
249*387f9dfdSAndroid Build Coastguard Worker {"skc_to_udp6_sock", "5.9"},
250*387f9dfdSAndroid Build Coastguard Worker {"get_task_stack", "5.9"},
251*387f9dfdSAndroid Build Coastguard Worker {"load_hdr_opt", "5.10"},
252*387f9dfdSAndroid Build Coastguard Worker {"store_hdr_opt", "5.10"},
253*387f9dfdSAndroid Build Coastguard Worker {"reserve_hdr_opt", "5.10"},
254*387f9dfdSAndroid Build Coastguard Worker {"inode_storage_get", "5.10"},
255*387f9dfdSAndroid Build Coastguard Worker {"inode_storage_delete", "5.10"},
256*387f9dfdSAndroid Build Coastguard Worker {"d_path", "5.10"},
257*387f9dfdSAndroid Build Coastguard Worker {"copy_from_user", "5.10"},
258*387f9dfdSAndroid Build Coastguard Worker {"snprintf_btf", "5.10"},
259*387f9dfdSAndroid Build Coastguard Worker {"seq_printf_btf", "5.10"},
260*387f9dfdSAndroid Build Coastguard Worker {"skb_cgroup_classid", "5.10"},
261*387f9dfdSAndroid Build Coastguard Worker {"redirect_neigh", "5.10"},
262*387f9dfdSAndroid Build Coastguard Worker {"per_cpu_ptr", "5.10"},
263*387f9dfdSAndroid Build Coastguard Worker {"this_cpu_ptr", "5.10"},
264*387f9dfdSAndroid Build Coastguard Worker {"redirect_peer", "5.10"},
265*387f9dfdSAndroid Build Coastguard Worker {"task_storage_get", "5.11"},
266*387f9dfdSAndroid Build Coastguard Worker {"task_storage_delete", "5.11"},
267*387f9dfdSAndroid Build Coastguard Worker {"get_current_task_btf", "5.11"},
268*387f9dfdSAndroid Build Coastguard Worker {"bprm_opts_set", "5.11"},
269*387f9dfdSAndroid Build Coastguard Worker {"ktime_get_coarse_ns", "5.11"},
270*387f9dfdSAndroid Build Coastguard Worker {"ima_inode_hash", "5.11"},
271*387f9dfdSAndroid Build Coastguard Worker {"sock_from_file", "5.11"},
272*387f9dfdSAndroid Build Coastguard Worker {"check_mtu", "5.12"},
273*387f9dfdSAndroid Build Coastguard Worker {"for_each_map_elem", "5.13"},
274*387f9dfdSAndroid Build Coastguard Worker {"snprintf", "5.13"},
275*387f9dfdSAndroid Build Coastguard Worker {"sys_bpf", "5.14"},
276*387f9dfdSAndroid Build Coastguard Worker {"btf_find_by_name_kind", "5.14"},
277*387f9dfdSAndroid Build Coastguard Worker {"sys_close", "5.14"},
278*387f9dfdSAndroid Build Coastguard Worker {"timer_init", "5.15"},
279*387f9dfdSAndroid Build Coastguard Worker {"timer_set_callback", "5.15"},
280*387f9dfdSAndroid Build Coastguard Worker {"timer_start", "5.15"},
281*387f9dfdSAndroid Build Coastguard Worker {"timer_cancel", "5.15"},
282*387f9dfdSAndroid Build Coastguard Worker {"get_func_ip", "5.15"},
283*387f9dfdSAndroid Build Coastguard Worker {"get_attach_cookie", "5.15"},
284*387f9dfdSAndroid Build Coastguard Worker {"task_pt_regs", "5.15"},
285*387f9dfdSAndroid Build Coastguard Worker {"get_branch_snapshot", "5.16"},
286*387f9dfdSAndroid Build Coastguard Worker {"trace_vprintk", "5.16"},
287*387f9dfdSAndroid Build Coastguard Worker {"skc_to_unix_sock", "5.16"},
288*387f9dfdSAndroid Build Coastguard Worker {"kallsyms_lookup_name", "5.16"},
289*387f9dfdSAndroid Build Coastguard Worker {"find_vma", "5.17"},
290*387f9dfdSAndroid Build Coastguard Worker {"loop", "5.17"},
291*387f9dfdSAndroid Build Coastguard Worker {"strncmp", "5.17"},
292*387f9dfdSAndroid Build Coastguard Worker {"get_func_arg", "5.17"},
293*387f9dfdSAndroid Build Coastguard Worker {"get_func_ret", "5.17"},
294*387f9dfdSAndroid Build Coastguard Worker {"get_func_ret", "5.17"},
295*387f9dfdSAndroid Build Coastguard Worker {"get_retval", "5.18"},
296*387f9dfdSAndroid Build Coastguard Worker {"set_retval", "5.18"},
297*387f9dfdSAndroid Build Coastguard Worker {"xdp_get_buff_len", "5.18"},
298*387f9dfdSAndroid Build Coastguard Worker {"xdp_load_bytes", "5.18"},
299*387f9dfdSAndroid Build Coastguard Worker {"xdp_store_bytes", "5.18"},
300*387f9dfdSAndroid Build Coastguard Worker {"copy_from_user_task", "5.18"},
301*387f9dfdSAndroid Build Coastguard Worker {"skb_set_tstamp", "5.18"},
302*387f9dfdSAndroid Build Coastguard Worker {"ima_file_hash", "5.18"},
303*387f9dfdSAndroid Build Coastguard Worker {"kptr_xchg", "5.19"},
304*387f9dfdSAndroid Build Coastguard Worker {"map_lookup_percpu_elem", "5.19"},
305*387f9dfdSAndroid Build Coastguard Worker {"skc_to_mptcp_sock", "5.19"},
306*387f9dfdSAndroid Build Coastguard Worker {"dynptr_from_mem", "5.19"},
307*387f9dfdSAndroid Build Coastguard Worker {"ringbuf_reserve_dynptr", "5.19"},
308*387f9dfdSAndroid Build Coastguard Worker {"ringbuf_submit_dynptr", "5.19"},
309*387f9dfdSAndroid Build Coastguard Worker {"ringbuf_discard_dynptr", "5.19"},
310*387f9dfdSAndroid Build Coastguard Worker {"dynptr_read", "5.19"},
311*387f9dfdSAndroid Build Coastguard Worker {"dynptr_write", "5.19"},
312*387f9dfdSAndroid Build Coastguard Worker {"dynptr_data", "5.19"},
313*387f9dfdSAndroid Build Coastguard Worker {"tcp_raw_gen_syncookie_ipv4", "6.0"},
314*387f9dfdSAndroid Build Coastguard Worker {"tcp_raw_gen_syncookie_ipv6", "6.0"},
315*387f9dfdSAndroid Build Coastguard Worker {"tcp_raw_check_syncookie_ipv4", "6.0"},
316*387f9dfdSAndroid Build Coastguard Worker {"tcp_raw_check_syncookie_ipv6", "6.0"},
317*387f9dfdSAndroid Build Coastguard Worker {"ktime_get_tai_ns", "6.1"},
318*387f9dfdSAndroid Build Coastguard Worker {"user_ringbuf_drain", "6.1"},
319*387f9dfdSAndroid Build Coastguard Worker {"cgrp_storage_get", "6.2"},
320*387f9dfdSAndroid Build Coastguard Worker {"cgrp_storage_delete", "6.2"},
321*387f9dfdSAndroid Build Coastguard Worker };
322*387f9dfdSAndroid Build Coastguard Worker
ptr_to_u64(void * ptr)323*387f9dfdSAndroid Build Coastguard Worker static uint64_t ptr_to_u64(void *ptr)
324*387f9dfdSAndroid Build Coastguard Worker {
325*387f9dfdSAndroid Build Coastguard Worker return (uint64_t) (unsigned long) ptr;
326*387f9dfdSAndroid Build Coastguard Worker }
327*387f9dfdSAndroid Build Coastguard Worker
libbpf_bpf_map_create(struct bcc_create_map_attr * create_attr)328*387f9dfdSAndroid Build Coastguard Worker static int libbpf_bpf_map_create(struct bcc_create_map_attr *create_attr)
329*387f9dfdSAndroid Build Coastguard Worker {
330*387f9dfdSAndroid Build Coastguard Worker LIBBPF_OPTS(bpf_map_create_opts, p);
331*387f9dfdSAndroid Build Coastguard Worker
332*387f9dfdSAndroid Build Coastguard Worker p.map_flags = create_attr->map_flags;
333*387f9dfdSAndroid Build Coastguard Worker p.numa_node = create_attr->numa_node;
334*387f9dfdSAndroid Build Coastguard Worker p.btf_fd = create_attr->btf_fd;
335*387f9dfdSAndroid Build Coastguard Worker p.btf_key_type_id = create_attr->btf_key_type_id;
336*387f9dfdSAndroid Build Coastguard Worker p.btf_value_type_id = create_attr->btf_value_type_id;
337*387f9dfdSAndroid Build Coastguard Worker p.map_ifindex = create_attr->map_ifindex;
338*387f9dfdSAndroid Build Coastguard Worker if (create_attr->map_type == BPF_MAP_TYPE_STRUCT_OPS)
339*387f9dfdSAndroid Build Coastguard Worker p.btf_vmlinux_value_type_id = create_attr->btf_vmlinux_value_type_id;
340*387f9dfdSAndroid Build Coastguard Worker else
341*387f9dfdSAndroid Build Coastguard Worker p.inner_map_fd = create_attr->inner_map_fd;
342*387f9dfdSAndroid Build Coastguard Worker
343*387f9dfdSAndroid Build Coastguard Worker return bpf_map_create(create_attr->map_type, create_attr->name, create_attr->key_size,
344*387f9dfdSAndroid Build Coastguard Worker create_attr->value_size, create_attr->max_entries, &p);
345*387f9dfdSAndroid Build Coastguard Worker }
346*387f9dfdSAndroid Build Coastguard Worker
bcc_create_map_xattr(struct bcc_create_map_attr * attr,bool allow_rlimit)347*387f9dfdSAndroid Build Coastguard Worker int bcc_create_map_xattr(struct bcc_create_map_attr *attr, bool allow_rlimit)
348*387f9dfdSAndroid Build Coastguard Worker {
349*387f9dfdSAndroid Build Coastguard Worker unsigned name_len = attr->name ? strlen(attr->name) : 0;
350*387f9dfdSAndroid Build Coastguard Worker char map_name[BPF_OBJ_NAME_LEN] = {};
351*387f9dfdSAndroid Build Coastguard Worker
352*387f9dfdSAndroid Build Coastguard Worker memcpy(map_name, attr->name, min(name_len, BPF_OBJ_NAME_LEN - 1));
353*387f9dfdSAndroid Build Coastguard Worker attr->name = map_name;
354*387f9dfdSAndroid Build Coastguard Worker int ret = libbpf_bpf_map_create(attr);
355*387f9dfdSAndroid Build Coastguard Worker
356*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 && errno == EPERM) {
357*387f9dfdSAndroid Build Coastguard Worker if (!allow_rlimit)
358*387f9dfdSAndroid Build Coastguard Worker return ret;
359*387f9dfdSAndroid Build Coastguard Worker
360*387f9dfdSAndroid Build Coastguard Worker // see note below about the rationale for this retry
361*387f9dfdSAndroid Build Coastguard Worker struct rlimit rl = {};
362*387f9dfdSAndroid Build Coastguard Worker if (getrlimit(RLIMIT_MEMLOCK, &rl) == 0) {
363*387f9dfdSAndroid Build Coastguard Worker rl.rlim_max = RLIM_INFINITY;
364*387f9dfdSAndroid Build Coastguard Worker rl.rlim_cur = rl.rlim_max;
365*387f9dfdSAndroid Build Coastguard Worker if (setrlimit(RLIMIT_MEMLOCK, &rl) == 0)
366*387f9dfdSAndroid Build Coastguard Worker ret = libbpf_bpf_map_create(attr);
367*387f9dfdSAndroid Build Coastguard Worker }
368*387f9dfdSAndroid Build Coastguard Worker }
369*387f9dfdSAndroid Build Coastguard Worker
370*387f9dfdSAndroid Build Coastguard Worker // kernel already supports btf if its loading is successful,
371*387f9dfdSAndroid Build Coastguard Worker // but this map type may not support pretty print yet.
372*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 && attr->btf_key_type_id && errno == 524 /* ENOTSUPP */) {
373*387f9dfdSAndroid Build Coastguard Worker attr->btf_fd = 0;
374*387f9dfdSAndroid Build Coastguard Worker attr->btf_key_type_id = 0;
375*387f9dfdSAndroid Build Coastguard Worker attr->btf_value_type_id = 0;
376*387f9dfdSAndroid Build Coastguard Worker ret = libbpf_bpf_map_create(attr);
377*387f9dfdSAndroid Build Coastguard Worker }
378*387f9dfdSAndroid Build Coastguard Worker
379*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 && name_len && (errno == E2BIG || errno == EINVAL)) {
380*387f9dfdSAndroid Build Coastguard Worker map_name[0] = '\0';
381*387f9dfdSAndroid Build Coastguard Worker ret = libbpf_bpf_map_create(attr);
382*387f9dfdSAndroid Build Coastguard Worker }
383*387f9dfdSAndroid Build Coastguard Worker
384*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 && errno == EPERM) {
385*387f9dfdSAndroid Build Coastguard Worker if (!allow_rlimit)
386*387f9dfdSAndroid Build Coastguard Worker return ret;
387*387f9dfdSAndroid Build Coastguard Worker
388*387f9dfdSAndroid Build Coastguard Worker // see note below about the rationale for this retry
389*387f9dfdSAndroid Build Coastguard Worker struct rlimit rl = {};
390*387f9dfdSAndroid Build Coastguard Worker if (getrlimit(RLIMIT_MEMLOCK, &rl) == 0) {
391*387f9dfdSAndroid Build Coastguard Worker rl.rlim_max = RLIM_INFINITY;
392*387f9dfdSAndroid Build Coastguard Worker rl.rlim_cur = rl.rlim_max;
393*387f9dfdSAndroid Build Coastguard Worker if (setrlimit(RLIMIT_MEMLOCK, &rl) == 0)
394*387f9dfdSAndroid Build Coastguard Worker ret = libbpf_bpf_map_create(attr);
395*387f9dfdSAndroid Build Coastguard Worker }
396*387f9dfdSAndroid Build Coastguard Worker }
397*387f9dfdSAndroid Build Coastguard Worker return ret;
398*387f9dfdSAndroid Build Coastguard Worker }
399*387f9dfdSAndroid Build Coastguard Worker
bcc_create_map(enum bpf_map_type map_type,const char * name,int key_size,int value_size,int max_entries,int map_flags)400*387f9dfdSAndroid Build Coastguard Worker int bcc_create_map(enum bpf_map_type map_type, const char *name,
401*387f9dfdSAndroid Build Coastguard Worker int key_size, int value_size,
402*387f9dfdSAndroid Build Coastguard Worker int max_entries, int map_flags)
403*387f9dfdSAndroid Build Coastguard Worker {
404*387f9dfdSAndroid Build Coastguard Worker struct bcc_create_map_attr attr = {};
405*387f9dfdSAndroid Build Coastguard Worker
406*387f9dfdSAndroid Build Coastguard Worker attr.map_type = map_type;
407*387f9dfdSAndroid Build Coastguard Worker attr.name = name;
408*387f9dfdSAndroid Build Coastguard Worker attr.key_size = key_size;
409*387f9dfdSAndroid Build Coastguard Worker attr.value_size = value_size;
410*387f9dfdSAndroid Build Coastguard Worker attr.max_entries = max_entries;
411*387f9dfdSAndroid Build Coastguard Worker attr.map_flags = map_flags;
412*387f9dfdSAndroid Build Coastguard Worker return bcc_create_map_xattr(&attr, true);
413*387f9dfdSAndroid Build Coastguard Worker }
414*387f9dfdSAndroid Build Coastguard Worker
bpf_update_elem(int fd,void * key,void * value,unsigned long long flags)415*387f9dfdSAndroid Build Coastguard Worker int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags)
416*387f9dfdSAndroid Build Coastguard Worker {
417*387f9dfdSAndroid Build Coastguard Worker return bpf_map_update_elem(fd, key, value, flags);
418*387f9dfdSAndroid Build Coastguard Worker }
419*387f9dfdSAndroid Build Coastguard Worker
bpf_lookup_elem(int fd,void * key,void * value)420*387f9dfdSAndroid Build Coastguard Worker int bpf_lookup_elem(int fd, void *key, void *value)
421*387f9dfdSAndroid Build Coastguard Worker {
422*387f9dfdSAndroid Build Coastguard Worker return bpf_map_lookup_elem(fd, key, value);
423*387f9dfdSAndroid Build Coastguard Worker }
424*387f9dfdSAndroid Build Coastguard Worker
bpf_delete_elem(int fd,void * key)425*387f9dfdSAndroid Build Coastguard Worker int bpf_delete_elem(int fd, void *key)
426*387f9dfdSAndroid Build Coastguard Worker {
427*387f9dfdSAndroid Build Coastguard Worker return bpf_map_delete_elem(fd, key);
428*387f9dfdSAndroid Build Coastguard Worker }
429*387f9dfdSAndroid Build Coastguard Worker
bpf_lookup_and_delete(int fd,void * key,void * value)430*387f9dfdSAndroid Build Coastguard Worker int bpf_lookup_and_delete(int fd, void *key, void *value)
431*387f9dfdSAndroid Build Coastguard Worker {
432*387f9dfdSAndroid Build Coastguard Worker return bpf_map_lookup_and_delete_elem(fd, key, value);
433*387f9dfdSAndroid Build Coastguard Worker }
434*387f9dfdSAndroid Build Coastguard Worker
bpf_lookup_batch(int fd,__u32 * in_batch,__u32 * out_batch,void * keys,void * values,__u32 * count)435*387f9dfdSAndroid Build Coastguard Worker int bpf_lookup_batch(int fd, __u32 *in_batch, __u32 *out_batch, void *keys,
436*387f9dfdSAndroid Build Coastguard Worker void *values, __u32 *count)
437*387f9dfdSAndroid Build Coastguard Worker {
438*387f9dfdSAndroid Build Coastguard Worker return bpf_map_lookup_batch(fd, in_batch, out_batch, keys, values, count,
439*387f9dfdSAndroid Build Coastguard Worker NULL);
440*387f9dfdSAndroid Build Coastguard Worker }
441*387f9dfdSAndroid Build Coastguard Worker
bpf_delete_batch(int fd,void * keys,__u32 * count)442*387f9dfdSAndroid Build Coastguard Worker int bpf_delete_batch(int fd, void *keys, __u32 *count)
443*387f9dfdSAndroid Build Coastguard Worker {
444*387f9dfdSAndroid Build Coastguard Worker return bpf_map_delete_batch(fd, keys, count, NULL);
445*387f9dfdSAndroid Build Coastguard Worker }
446*387f9dfdSAndroid Build Coastguard Worker
bpf_update_batch(int fd,void * keys,void * values,__u32 * count)447*387f9dfdSAndroid Build Coastguard Worker int bpf_update_batch(int fd, void *keys, void *values, __u32 *count)
448*387f9dfdSAndroid Build Coastguard Worker {
449*387f9dfdSAndroid Build Coastguard Worker return bpf_map_update_batch(fd, keys, values, count, NULL);
450*387f9dfdSAndroid Build Coastguard Worker }
451*387f9dfdSAndroid Build Coastguard Worker
bpf_lookup_and_delete_batch(int fd,__u32 * in_batch,__u32 * out_batch,void * keys,void * values,__u32 * count)452*387f9dfdSAndroid Build Coastguard Worker int bpf_lookup_and_delete_batch(int fd, __u32 *in_batch, __u32 *out_batch,
453*387f9dfdSAndroid Build Coastguard Worker void *keys, void *values, __u32 *count)
454*387f9dfdSAndroid Build Coastguard Worker {
455*387f9dfdSAndroid Build Coastguard Worker return bpf_map_lookup_and_delete_batch(fd, in_batch, out_batch, keys, values,
456*387f9dfdSAndroid Build Coastguard Worker count, NULL);
457*387f9dfdSAndroid Build Coastguard Worker }
458*387f9dfdSAndroid Build Coastguard Worker
bpf_get_first_key(int fd,void * key,size_t key_size)459*387f9dfdSAndroid Build Coastguard Worker int bpf_get_first_key(int fd, void *key, size_t key_size)
460*387f9dfdSAndroid Build Coastguard Worker {
461*387f9dfdSAndroid Build Coastguard Worker int i, res;
462*387f9dfdSAndroid Build Coastguard Worker
463*387f9dfdSAndroid Build Coastguard Worker // 4.12 and above kernel supports passing NULL to BPF_MAP_GET_NEXT_KEY
464*387f9dfdSAndroid Build Coastguard Worker // to get first key of the map. For older kernels, the call will fail.
465*387f9dfdSAndroid Build Coastguard Worker res = bpf_map_get_next_key(fd, 0, key);
466*387f9dfdSAndroid Build Coastguard Worker if (res < 0 && errno == EFAULT) {
467*387f9dfdSAndroid Build Coastguard Worker // Fall back to try to find a non-existing key.
468*387f9dfdSAndroid Build Coastguard Worker static unsigned char try_values[3] = {0, 0xff, 0x55};
469*387f9dfdSAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
470*387f9dfdSAndroid Build Coastguard Worker memset(key, try_values[i], key_size);
471*387f9dfdSAndroid Build Coastguard Worker // We want to check the existence of the key but we don't know the size
472*387f9dfdSAndroid Build Coastguard Worker // of map's value. So we pass an invalid pointer for value, expect
473*387f9dfdSAndroid Build Coastguard Worker // the call to fail and check if the error is ENOENT indicating the
474*387f9dfdSAndroid Build Coastguard Worker // key doesn't exist. If we use NULL for the invalid pointer, it might
475*387f9dfdSAndroid Build Coastguard Worker // trigger a page fault in kernel and affect performance. Hence we use
476*387f9dfdSAndroid Build Coastguard Worker // ~0 which will fail and return fast.
477*387f9dfdSAndroid Build Coastguard Worker // This should fail since we pass an invalid pointer for value.
478*387f9dfdSAndroid Build Coastguard Worker if (bpf_map_lookup_elem(fd, key, (void *)~0) >= 0)
479*387f9dfdSAndroid Build Coastguard Worker return -1;
480*387f9dfdSAndroid Build Coastguard Worker // This means the key doesn't exist.
481*387f9dfdSAndroid Build Coastguard Worker if (errno == ENOENT)
482*387f9dfdSAndroid Build Coastguard Worker return bpf_map_get_next_key(fd, (void*)&try_values[i], key);
483*387f9dfdSAndroid Build Coastguard Worker }
484*387f9dfdSAndroid Build Coastguard Worker return -1;
485*387f9dfdSAndroid Build Coastguard Worker } else {
486*387f9dfdSAndroid Build Coastguard Worker return res;
487*387f9dfdSAndroid Build Coastguard Worker }
488*387f9dfdSAndroid Build Coastguard Worker }
489*387f9dfdSAndroid Build Coastguard Worker
bpf_get_next_key(int fd,void * key,void * next_key)490*387f9dfdSAndroid Build Coastguard Worker int bpf_get_next_key(int fd, void *key, void *next_key)
491*387f9dfdSAndroid Build Coastguard Worker {
492*387f9dfdSAndroid Build Coastguard Worker return bpf_map_get_next_key(fd, key, next_key);
493*387f9dfdSAndroid Build Coastguard Worker }
494*387f9dfdSAndroid Build Coastguard Worker
bpf_print_hints(int ret,char * log)495*387f9dfdSAndroid Build Coastguard Worker static void bpf_print_hints(int ret, char *log)
496*387f9dfdSAndroid Build Coastguard Worker {
497*387f9dfdSAndroid Build Coastguard Worker if (ret < 0)
498*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf: Failed to load program: %s\n", strerror(errno));
499*387f9dfdSAndroid Build Coastguard Worker if (log == NULL)
500*387f9dfdSAndroid Build Coastguard Worker return;
501*387f9dfdSAndroid Build Coastguard Worker else
502*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "%s\n", log);
503*387f9dfdSAndroid Build Coastguard Worker
504*387f9dfdSAndroid Build Coastguard Worker if (ret >= 0)
505*387f9dfdSAndroid Build Coastguard Worker return;
506*387f9dfdSAndroid Build Coastguard Worker
507*387f9dfdSAndroid Build Coastguard Worker // The following error strings will need maintenance to match LLVM.
508*387f9dfdSAndroid Build Coastguard Worker
509*387f9dfdSAndroid Build Coastguard Worker // stack busting
510*387f9dfdSAndroid Build Coastguard Worker if (strstr(log, "invalid stack off=-") != NULL) {
511*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "HINT: Looks like you exceeded the BPF stack limit. "
512*387f9dfdSAndroid Build Coastguard Worker "This can happen if you allocate too much local variable storage. "
513*387f9dfdSAndroid Build Coastguard Worker "For example, if you allocated a 1 Kbyte struct (maybe for "
514*387f9dfdSAndroid Build Coastguard Worker "BPF_PERF_OUTPUT), busting a max stack of 512 bytes.\n\n");
515*387f9dfdSAndroid Build Coastguard Worker }
516*387f9dfdSAndroid Build Coastguard Worker
517*387f9dfdSAndroid Build Coastguard Worker // didn't check NULL on map lookup
518*387f9dfdSAndroid Build Coastguard Worker if (strstr(log, "invalid mem access 'map_value_or_null'") != NULL) {
519*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "HINT: The 'map_value_or_null' error can happen if "
520*387f9dfdSAndroid Build Coastguard Worker "you dereference a pointer value from a map lookup without first "
521*387f9dfdSAndroid Build Coastguard Worker "checking if that pointer is NULL.\n\n");
522*387f9dfdSAndroid Build Coastguard Worker }
523*387f9dfdSAndroid Build Coastguard Worker
524*387f9dfdSAndroid Build Coastguard Worker // lacking a bpf_probe_read
525*387f9dfdSAndroid Build Coastguard Worker if (strstr(log, "invalid mem access 'inv'") != NULL) {
526*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "HINT: The invalid mem access 'inv' error can happen "
527*387f9dfdSAndroid Build Coastguard Worker "if you try to dereference memory without first using "
528*387f9dfdSAndroid Build Coastguard Worker "bpf_probe_read_kernel() to copy it to the BPF stack. Sometimes the "
529*387f9dfdSAndroid Build Coastguard Worker "bpf_probe_read_kernel() is automatic by the bcc rewriter, other times "
530*387f9dfdSAndroid Build Coastguard Worker "you'll need to be explicit.\n\n");
531*387f9dfdSAndroid Build Coastguard Worker }
532*387f9dfdSAndroid Build Coastguard Worker
533*387f9dfdSAndroid Build Coastguard Worker // referencing global/static variables or read only data
534*387f9dfdSAndroid Build Coastguard Worker if (strstr(log, "unknown opcode") != NULL) {
535*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "HINT: The 'unknown opcode' can happen if you reference "
536*387f9dfdSAndroid Build Coastguard Worker "a global or static variable, or data in read-only section. For example,"
537*387f9dfdSAndroid Build Coastguard Worker " 'char *p = \"hello\"' will result in p referencing a read-only section,"
538*387f9dfdSAndroid Build Coastguard Worker " and 'char p[] = \"hello\"' will have \"hello\" stored on the stack.\n\n");
539*387f9dfdSAndroid Build Coastguard Worker }
540*387f9dfdSAndroid Build Coastguard Worker
541*387f9dfdSAndroid Build Coastguard Worker // helper function not found in kernel
542*387f9dfdSAndroid Build Coastguard Worker char *helper_str = strstr(log, "invalid func ");
543*387f9dfdSAndroid Build Coastguard Worker if (helper_str != NULL) {
544*387f9dfdSAndroid Build Coastguard Worker helper_str += strlen("invalid func ");
545*387f9dfdSAndroid Build Coastguard Worker char *str = strchr(helper_str, '#');
546*387f9dfdSAndroid Build Coastguard Worker if (str != NULL) {
547*387f9dfdSAndroid Build Coastguard Worker helper_str = str + 1;
548*387f9dfdSAndroid Build Coastguard Worker }
549*387f9dfdSAndroid Build Coastguard Worker unsigned int helper_id = atoi(helper_str);
550*387f9dfdSAndroid Build Coastguard Worker if (helper_id && helper_id < sizeof(helpers) / sizeof(struct bpf_helper)) {
551*387f9dfdSAndroid Build Coastguard Worker struct bpf_helper helper = helpers[helper_id - 1];
552*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "HINT: bpf_%s missing (added in Linux %s).\n\n",
553*387f9dfdSAndroid Build Coastguard Worker helper.name, helper.required_version);
554*387f9dfdSAndroid Build Coastguard Worker }
555*387f9dfdSAndroid Build Coastguard Worker }
556*387f9dfdSAndroid Build Coastguard Worker }
557*387f9dfdSAndroid Build Coastguard Worker #define ROUND_UP(x, n) (((x) + (n) - 1u) & ~((n) - 1u))
558*387f9dfdSAndroid Build Coastguard Worker
bpf_obj_get_info(int prog_map_fd,void * info,uint32_t * info_len)559*387f9dfdSAndroid Build Coastguard Worker int bpf_obj_get_info(int prog_map_fd, void *info, uint32_t *info_len)
560*387f9dfdSAndroid Build Coastguard Worker {
561*387f9dfdSAndroid Build Coastguard Worker return bpf_obj_get_info_by_fd(prog_map_fd, info, info_len);
562*387f9dfdSAndroid Build Coastguard Worker }
563*387f9dfdSAndroid Build Coastguard Worker
bpf_prog_compute_tag(const struct bpf_insn * insns,int prog_len,unsigned long long * ptag)564*387f9dfdSAndroid Build Coastguard Worker int bpf_prog_compute_tag(const struct bpf_insn *insns, int prog_len,
565*387f9dfdSAndroid Build Coastguard Worker unsigned long long *ptag)
566*387f9dfdSAndroid Build Coastguard Worker {
567*387f9dfdSAndroid Build Coastguard Worker struct sockaddr_alg alg = {
568*387f9dfdSAndroid Build Coastguard Worker .salg_family = AF_ALG,
569*387f9dfdSAndroid Build Coastguard Worker .salg_type = "hash",
570*387f9dfdSAndroid Build Coastguard Worker .salg_name = "sha1",
571*387f9dfdSAndroid Build Coastguard Worker };
572*387f9dfdSAndroid Build Coastguard Worker int shafd = socket(AF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
573*387f9dfdSAndroid Build Coastguard Worker if (shafd < 0) {
574*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "sha1 socket not available %s\n", strerror(errno));
575*387f9dfdSAndroid Build Coastguard Worker return -1;
576*387f9dfdSAndroid Build Coastguard Worker }
577*387f9dfdSAndroid Build Coastguard Worker int ret = bind(shafd, (struct sockaddr *)&alg, sizeof(alg));
578*387f9dfdSAndroid Build Coastguard Worker if (ret < 0) {
579*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "sha1 bind fail %s\n", strerror(errno));
580*387f9dfdSAndroid Build Coastguard Worker close(shafd);
581*387f9dfdSAndroid Build Coastguard Worker return ret;
582*387f9dfdSAndroid Build Coastguard Worker }
583*387f9dfdSAndroid Build Coastguard Worker int shafd2 = accept4(shafd, NULL, 0, SOCK_CLOEXEC);
584*387f9dfdSAndroid Build Coastguard Worker if (shafd2 < 0) {
585*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "sha1 accept fail %s\n", strerror(errno));
586*387f9dfdSAndroid Build Coastguard Worker close(shafd);
587*387f9dfdSAndroid Build Coastguard Worker return -1;
588*387f9dfdSAndroid Build Coastguard Worker }
589*387f9dfdSAndroid Build Coastguard Worker struct bpf_insn prog[prog_len / 8];
590*387f9dfdSAndroid Build Coastguard Worker bool map_ld_seen = false;
591*387f9dfdSAndroid Build Coastguard Worker int i;
592*387f9dfdSAndroid Build Coastguard Worker for (i = 0; i < prog_len / 8; i++) {
593*387f9dfdSAndroid Build Coastguard Worker prog[i] = insns[i];
594*387f9dfdSAndroid Build Coastguard Worker if (insns[i].code == (BPF_LD | BPF_DW | BPF_IMM) &&
595*387f9dfdSAndroid Build Coastguard Worker insns[i].src_reg == BPF_PSEUDO_MAP_FD &&
596*387f9dfdSAndroid Build Coastguard Worker !map_ld_seen) {
597*387f9dfdSAndroid Build Coastguard Worker prog[i].imm = 0;
598*387f9dfdSAndroid Build Coastguard Worker map_ld_seen = true;
599*387f9dfdSAndroid Build Coastguard Worker } else if (insns[i].code == 0 && map_ld_seen) {
600*387f9dfdSAndroid Build Coastguard Worker prog[i].imm = 0;
601*387f9dfdSAndroid Build Coastguard Worker map_ld_seen = false;
602*387f9dfdSAndroid Build Coastguard Worker } else {
603*387f9dfdSAndroid Build Coastguard Worker map_ld_seen = false;
604*387f9dfdSAndroid Build Coastguard Worker }
605*387f9dfdSAndroid Build Coastguard Worker }
606*387f9dfdSAndroid Build Coastguard Worker ret = write(shafd2, prog, prog_len);
607*387f9dfdSAndroid Build Coastguard Worker if (ret != prog_len) {
608*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "sha1 write fail %s\n", strerror(errno));
609*387f9dfdSAndroid Build Coastguard Worker close(shafd2);
610*387f9dfdSAndroid Build Coastguard Worker close(shafd);
611*387f9dfdSAndroid Build Coastguard Worker return -1;
612*387f9dfdSAndroid Build Coastguard Worker }
613*387f9dfdSAndroid Build Coastguard Worker
614*387f9dfdSAndroid Build Coastguard Worker union {
615*387f9dfdSAndroid Build Coastguard Worker unsigned char sha[20];
616*387f9dfdSAndroid Build Coastguard Worker unsigned long long tag;
617*387f9dfdSAndroid Build Coastguard Worker } u = {};
618*387f9dfdSAndroid Build Coastguard Worker ret = read(shafd2, u.sha, 20);
619*387f9dfdSAndroid Build Coastguard Worker if (ret != 20) {
620*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "sha1 read fail %s\n", strerror(errno));
621*387f9dfdSAndroid Build Coastguard Worker close(shafd2);
622*387f9dfdSAndroid Build Coastguard Worker close(shafd);
623*387f9dfdSAndroid Build Coastguard Worker return -1;
624*387f9dfdSAndroid Build Coastguard Worker }
625*387f9dfdSAndroid Build Coastguard Worker *ptag = __builtin_bswap64(u.tag);
626*387f9dfdSAndroid Build Coastguard Worker close(shafd2);
627*387f9dfdSAndroid Build Coastguard Worker close(shafd);
628*387f9dfdSAndroid Build Coastguard Worker return 0;
629*387f9dfdSAndroid Build Coastguard Worker }
630*387f9dfdSAndroid Build Coastguard Worker
bpf_prog_get_tag(int fd,unsigned long long * ptag)631*387f9dfdSAndroid Build Coastguard Worker int bpf_prog_get_tag(int fd, unsigned long long *ptag)
632*387f9dfdSAndroid Build Coastguard Worker {
633*387f9dfdSAndroid Build Coastguard Worker char fmt[64];
634*387f9dfdSAndroid Build Coastguard Worker snprintf(fmt, sizeof(fmt), "/proc/self/fdinfo/%d", fd);
635*387f9dfdSAndroid Build Coastguard Worker FILE * f = fopen(fmt, "re");
636*387f9dfdSAndroid Build Coastguard Worker if (!f) {
637*387f9dfdSAndroid Build Coastguard Worker /* fprintf(stderr, "failed to open fdinfo %s\n", strerror(errno));*/
638*387f9dfdSAndroid Build Coastguard Worker return -1;
639*387f9dfdSAndroid Build Coastguard Worker }
640*387f9dfdSAndroid Build Coastguard Worker unsigned long long tag = 0;
641*387f9dfdSAndroid Build Coastguard Worker // prog_tag: can appear in different lines
642*387f9dfdSAndroid Build Coastguard Worker while (fgets(fmt, sizeof(fmt), f)) {
643*387f9dfdSAndroid Build Coastguard Worker if (sscanf(fmt, "prog_tag:%llx", &tag) == 1) {
644*387f9dfdSAndroid Build Coastguard Worker *ptag = tag;
645*387f9dfdSAndroid Build Coastguard Worker fclose(f);
646*387f9dfdSAndroid Build Coastguard Worker return 0;
647*387f9dfdSAndroid Build Coastguard Worker }
648*387f9dfdSAndroid Build Coastguard Worker }
649*387f9dfdSAndroid Build Coastguard Worker fclose(f);
650*387f9dfdSAndroid Build Coastguard Worker return -2;
651*387f9dfdSAndroid Build Coastguard Worker }
652*387f9dfdSAndroid Build Coastguard Worker
libbpf_bpf_prog_load(enum bpf_prog_type prog_type,const char * prog_name,const char * license,const struct bpf_insn * insns,size_t insn_cnt,struct bpf_prog_load_opts * opts,char * log_buf,size_t log_buf_sz)653*387f9dfdSAndroid Build Coastguard Worker static int libbpf_bpf_prog_load(enum bpf_prog_type prog_type,
654*387f9dfdSAndroid Build Coastguard Worker const char *prog_name, const char *license,
655*387f9dfdSAndroid Build Coastguard Worker const struct bpf_insn *insns, size_t insn_cnt,
656*387f9dfdSAndroid Build Coastguard Worker struct bpf_prog_load_opts *opts,
657*387f9dfdSAndroid Build Coastguard Worker char *log_buf, size_t log_buf_sz)
658*387f9dfdSAndroid Build Coastguard Worker {
659*387f9dfdSAndroid Build Coastguard Worker
660*387f9dfdSAndroid Build Coastguard Worker LIBBPF_OPTS(bpf_prog_load_opts, p);
661*387f9dfdSAndroid Build Coastguard Worker
662*387f9dfdSAndroid Build Coastguard Worker if (!opts || !log_buf != !log_buf_sz) {
663*387f9dfdSAndroid Build Coastguard Worker errno = EINVAL;
664*387f9dfdSAndroid Build Coastguard Worker return -EINVAL;
665*387f9dfdSAndroid Build Coastguard Worker }
666*387f9dfdSAndroid Build Coastguard Worker
667*387f9dfdSAndroid Build Coastguard Worker p.expected_attach_type = opts->expected_attach_type;
668*387f9dfdSAndroid Build Coastguard Worker switch (prog_type) {
669*387f9dfdSAndroid Build Coastguard Worker case BPF_PROG_TYPE_STRUCT_OPS:
670*387f9dfdSAndroid Build Coastguard Worker case BPF_PROG_TYPE_LSM:
671*387f9dfdSAndroid Build Coastguard Worker p.attach_btf_id = opts->attach_btf_id;
672*387f9dfdSAndroid Build Coastguard Worker break;
673*387f9dfdSAndroid Build Coastguard Worker case BPF_PROG_TYPE_TRACING:
674*387f9dfdSAndroid Build Coastguard Worker case BPF_PROG_TYPE_EXT:
675*387f9dfdSAndroid Build Coastguard Worker p.attach_btf_id = opts->attach_btf_id;
676*387f9dfdSAndroid Build Coastguard Worker p.attach_prog_fd = opts->attach_prog_fd;
677*387f9dfdSAndroid Build Coastguard Worker p.attach_btf_obj_fd = opts->attach_btf_obj_fd;
678*387f9dfdSAndroid Build Coastguard Worker break;
679*387f9dfdSAndroid Build Coastguard Worker default:
680*387f9dfdSAndroid Build Coastguard Worker p.prog_ifindex = opts->prog_ifindex;
681*387f9dfdSAndroid Build Coastguard Worker p.kern_version = opts->kern_version;
682*387f9dfdSAndroid Build Coastguard Worker }
683*387f9dfdSAndroid Build Coastguard Worker p.log_level = opts->log_level;
684*387f9dfdSAndroid Build Coastguard Worker p.log_buf = log_buf;
685*387f9dfdSAndroid Build Coastguard Worker p.log_size = log_buf_sz;
686*387f9dfdSAndroid Build Coastguard Worker p.prog_btf_fd = opts->prog_btf_fd;
687*387f9dfdSAndroid Build Coastguard Worker p.func_info_rec_size = opts->func_info_rec_size;
688*387f9dfdSAndroid Build Coastguard Worker p.func_info_cnt = opts->func_info_cnt;
689*387f9dfdSAndroid Build Coastguard Worker p.func_info = opts->func_info;
690*387f9dfdSAndroid Build Coastguard Worker p.line_info_rec_size = opts->line_info_rec_size;
691*387f9dfdSAndroid Build Coastguard Worker p.line_info_cnt = opts->line_info_cnt;
692*387f9dfdSAndroid Build Coastguard Worker p.line_info = opts->line_info;
693*387f9dfdSAndroid Build Coastguard Worker p.prog_flags = opts->prog_flags;
694*387f9dfdSAndroid Build Coastguard Worker
695*387f9dfdSAndroid Build Coastguard Worker return bpf_prog_load(prog_type, prog_name, license,
696*387f9dfdSAndroid Build Coastguard Worker insns, insn_cnt, &p);
697*387f9dfdSAndroid Build Coastguard Worker }
698*387f9dfdSAndroid Build Coastguard Worker
699*387f9dfdSAndroid Build Coastguard Worker #ifndef MINIMAL_LIBBPF
find_btf_id(const char * module_name,const char * func_name,enum bpf_attach_type expected_attach_type,int * btf_fd)700*387f9dfdSAndroid Build Coastguard Worker static int find_btf_id(const char *module_name, const char *func_name,
701*387f9dfdSAndroid Build Coastguard Worker enum bpf_attach_type expected_attach_type, int *btf_fd)
702*387f9dfdSAndroid Build Coastguard Worker {
703*387f9dfdSAndroid Build Coastguard Worker struct btf *vmlinux_btf = NULL, *module_btf = NULL;
704*387f9dfdSAndroid Build Coastguard Worker struct bpf_btf_info info;
705*387f9dfdSAndroid Build Coastguard Worker int err, fd, btf_id;
706*387f9dfdSAndroid Build Coastguard Worker __u32 id = 0, len;
707*387f9dfdSAndroid Build Coastguard Worker char name[64];
708*387f9dfdSAndroid Build Coastguard Worker
709*387f9dfdSAndroid Build Coastguard Worker if (!module_name[0] || !strcmp(module_name, "vmlinux"))
710*387f9dfdSAndroid Build Coastguard Worker return libbpf_find_vmlinux_btf_id(func_name, expected_attach_type);
711*387f9dfdSAndroid Build Coastguard Worker
712*387f9dfdSAndroid Build Coastguard Worker while (true) {
713*387f9dfdSAndroid Build Coastguard Worker err = bpf_btf_get_next_id(id, &id);
714*387f9dfdSAndroid Build Coastguard Worker if (err) {
715*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf_btf_get_next_id failed: %d\n", err);
716*387f9dfdSAndroid Build Coastguard Worker return err;
717*387f9dfdSAndroid Build Coastguard Worker }
718*387f9dfdSAndroid Build Coastguard Worker
719*387f9dfdSAndroid Build Coastguard Worker fd = bpf_btf_get_fd_by_id(id);
720*387f9dfdSAndroid Build Coastguard Worker if (fd < 0) {
721*387f9dfdSAndroid Build Coastguard Worker err = fd;
722*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf_btf_get_fd_by_id failed: %d\n", err);
723*387f9dfdSAndroid Build Coastguard Worker return err;
724*387f9dfdSAndroid Build Coastguard Worker }
725*387f9dfdSAndroid Build Coastguard Worker
726*387f9dfdSAndroid Build Coastguard Worker len = sizeof(info);
727*387f9dfdSAndroid Build Coastguard Worker memset(&info, 0, sizeof(info));
728*387f9dfdSAndroid Build Coastguard Worker info.name = ptr_to_u64(name);
729*387f9dfdSAndroid Build Coastguard Worker info.name_len = sizeof(name);
730*387f9dfdSAndroid Build Coastguard Worker
731*387f9dfdSAndroid Build Coastguard Worker err = bpf_btf_get_info_by_fd(fd, &info, &len);
732*387f9dfdSAndroid Build Coastguard Worker if (err) {
733*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf_btf_get_info_by_fd failed: %d\n", err);
734*387f9dfdSAndroid Build Coastguard Worker goto err_out;
735*387f9dfdSAndroid Build Coastguard Worker }
736*387f9dfdSAndroid Build Coastguard Worker
737*387f9dfdSAndroid Build Coastguard Worker if (!info.kernel_btf || strcmp(name, module_name)) {
738*387f9dfdSAndroid Build Coastguard Worker close(fd);
739*387f9dfdSAndroid Build Coastguard Worker continue;
740*387f9dfdSAndroid Build Coastguard Worker }
741*387f9dfdSAndroid Build Coastguard Worker
742*387f9dfdSAndroid Build Coastguard Worker vmlinux_btf = btf__load_vmlinux_btf();
743*387f9dfdSAndroid Build Coastguard Worker err = libbpf_get_error(vmlinux_btf);
744*387f9dfdSAndroid Build Coastguard Worker if (err) {
745*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "btf__load_vmlinux_btf failed: %d\n", err);
746*387f9dfdSAndroid Build Coastguard Worker goto err_out;
747*387f9dfdSAndroid Build Coastguard Worker }
748*387f9dfdSAndroid Build Coastguard Worker
749*387f9dfdSAndroid Build Coastguard Worker module_btf = btf__load_module_btf(module_name, vmlinux_btf);
750*387f9dfdSAndroid Build Coastguard Worker err = libbpf_get_error(vmlinux_btf);
751*387f9dfdSAndroid Build Coastguard Worker if (err) {
752*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "btf__load_module_btf failed: %d\n", err);
753*387f9dfdSAndroid Build Coastguard Worker goto err_out;
754*387f9dfdSAndroid Build Coastguard Worker }
755*387f9dfdSAndroid Build Coastguard Worker
756*387f9dfdSAndroid Build Coastguard Worker btf_id = btf__find_by_name_kind(module_btf, func_name, BTF_KIND_FUNC);
757*387f9dfdSAndroid Build Coastguard Worker if (btf_id < 0) {
758*387f9dfdSAndroid Build Coastguard Worker err = btf_id;
759*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "btf__find_by_name_kind failed: %d\n", err);
760*387f9dfdSAndroid Build Coastguard Worker goto err_out;
761*387f9dfdSAndroid Build Coastguard Worker }
762*387f9dfdSAndroid Build Coastguard Worker
763*387f9dfdSAndroid Build Coastguard Worker btf__free(module_btf);
764*387f9dfdSAndroid Build Coastguard Worker btf__free(vmlinux_btf);
765*387f9dfdSAndroid Build Coastguard Worker
766*387f9dfdSAndroid Build Coastguard Worker *btf_fd = fd;
767*387f9dfdSAndroid Build Coastguard Worker return btf_id;
768*387f9dfdSAndroid Build Coastguard Worker
769*387f9dfdSAndroid Build Coastguard Worker err_out:
770*387f9dfdSAndroid Build Coastguard Worker btf__free(module_btf);
771*387f9dfdSAndroid Build Coastguard Worker btf__free(vmlinux_btf);
772*387f9dfdSAndroid Build Coastguard Worker close(fd);
773*387f9dfdSAndroid Build Coastguard Worker *btf_fd = -1;
774*387f9dfdSAndroid Build Coastguard Worker return err;
775*387f9dfdSAndroid Build Coastguard Worker }
776*387f9dfdSAndroid Build Coastguard Worker
777*387f9dfdSAndroid Build Coastguard Worker return -1;
778*387f9dfdSAndroid Build Coastguard Worker }
779*387f9dfdSAndroid Build Coastguard Worker #endif
780*387f9dfdSAndroid Build Coastguard Worker
bcc_prog_load_xattr(enum bpf_prog_type prog_type,const char * prog_name,const char * license,const struct bpf_insn * insns,struct bpf_prog_load_opts * opts,int prog_len,char * log_buf,unsigned log_buf_size,bool allow_rlimit)781*387f9dfdSAndroid Build Coastguard Worker int bcc_prog_load_xattr(enum bpf_prog_type prog_type, const char *prog_name,
782*387f9dfdSAndroid Build Coastguard Worker const char *license, const struct bpf_insn *insns,
783*387f9dfdSAndroid Build Coastguard Worker struct bpf_prog_load_opts *opts, int prog_len,
784*387f9dfdSAndroid Build Coastguard Worker char *log_buf, unsigned log_buf_size, bool allow_rlimit)
785*387f9dfdSAndroid Build Coastguard Worker {
786*387f9dfdSAndroid Build Coastguard Worker unsigned name_len = prog_name ? strlen(prog_name) : 0;
787*387f9dfdSAndroid Build Coastguard Worker char *tmp_log_buf = NULL, *opts_log_buf = NULL;
788*387f9dfdSAndroid Build Coastguard Worker unsigned tmp_log_buf_size = 0, opts_log_buf_size = 0;
789*387f9dfdSAndroid Build Coastguard Worker int ret = 0, name_offset = 0, expected_attach_type = 0;
790*387f9dfdSAndroid Build Coastguard Worker char new_prog_name[BPF_OBJ_NAME_LEN] = {};
791*387f9dfdSAndroid Build Coastguard Worker char mod_name[64] = {};
792*387f9dfdSAndroid Build Coastguard Worker char *mod_end;
793*387f9dfdSAndroid Build Coastguard Worker int mod_len;
794*387f9dfdSAndroid Build Coastguard Worker int fd = -1;
795*387f9dfdSAndroid Build Coastguard Worker
796*387f9dfdSAndroid Build Coastguard Worker unsigned insns_cnt = prog_len / sizeof(struct bpf_insn);
797*387f9dfdSAndroid Build Coastguard Worker
798*387f9dfdSAndroid Build Coastguard Worker if (opts->log_level > 0) {
799*387f9dfdSAndroid Build Coastguard Worker if (log_buf_size > 0) {
800*387f9dfdSAndroid Build Coastguard Worker // Use user-provided log buffer if available.
801*387f9dfdSAndroid Build Coastguard Worker log_buf[0] = 0;
802*387f9dfdSAndroid Build Coastguard Worker opts_log_buf = log_buf;
803*387f9dfdSAndroid Build Coastguard Worker opts_log_buf_size = log_buf_size;
804*387f9dfdSAndroid Build Coastguard Worker } else {
805*387f9dfdSAndroid Build Coastguard Worker // Create and use temporary log buffer if user didn't provide one.
806*387f9dfdSAndroid Build Coastguard Worker tmp_log_buf_size = LOG_BUF_SIZE;
807*387f9dfdSAndroid Build Coastguard Worker tmp_log_buf = malloc(tmp_log_buf_size);
808*387f9dfdSAndroid Build Coastguard Worker if (!tmp_log_buf) {
809*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf: Failed to allocate temporary log buffer: %s\n\n",
810*387f9dfdSAndroid Build Coastguard Worker strerror(errno));
811*387f9dfdSAndroid Build Coastguard Worker opts->log_level = 0;
812*387f9dfdSAndroid Build Coastguard Worker } else {
813*387f9dfdSAndroid Build Coastguard Worker tmp_log_buf[0] = 0;
814*387f9dfdSAndroid Build Coastguard Worker opts_log_buf = tmp_log_buf;
815*387f9dfdSAndroid Build Coastguard Worker opts_log_buf_size = tmp_log_buf_size;
816*387f9dfdSAndroid Build Coastguard Worker }
817*387f9dfdSAndroid Build Coastguard Worker }
818*387f9dfdSAndroid Build Coastguard Worker }
819*387f9dfdSAndroid Build Coastguard Worker
820*387f9dfdSAndroid Build Coastguard Worker if (name_len) {
821*387f9dfdSAndroid Build Coastguard Worker if (strncmp(prog_name, "kprobe__", 8) == 0)
822*387f9dfdSAndroid Build Coastguard Worker name_offset = 8;
823*387f9dfdSAndroid Build Coastguard Worker else if (strncmp(prog_name, "kretprobe__", 11) == 0)
824*387f9dfdSAndroid Build Coastguard Worker name_offset = 11;
825*387f9dfdSAndroid Build Coastguard Worker else if (strncmp(prog_name, "tracepoint__", 12) == 0)
826*387f9dfdSAndroid Build Coastguard Worker name_offset = 12;
827*387f9dfdSAndroid Build Coastguard Worker else if (strncmp(prog_name, "raw_tracepoint__", 16) == 0)
828*387f9dfdSAndroid Build Coastguard Worker name_offset = 16;
829*387f9dfdSAndroid Build Coastguard Worker else if (strncmp(prog_name, "kfunc__", 7) == 0) {
830*387f9dfdSAndroid Build Coastguard Worker // kfunc__vmlinux__vfs_read
831*387f9dfdSAndroid Build Coastguard Worker mod_end = strstr(prog_name + 7, "__");
832*387f9dfdSAndroid Build Coastguard Worker mod_len = mod_end - prog_name - 7;
833*387f9dfdSAndroid Build Coastguard Worker strncpy(mod_name, prog_name + 7, mod_len);
834*387f9dfdSAndroid Build Coastguard Worker name_offset = 7 + mod_len + 2;
835*387f9dfdSAndroid Build Coastguard Worker expected_attach_type = BPF_TRACE_FENTRY;
836*387f9dfdSAndroid Build Coastguard Worker } else if (strncmp(prog_name, "kmod_ret__", 10) == 0) {
837*387f9dfdSAndroid Build Coastguard Worker name_offset = 10;
838*387f9dfdSAndroid Build Coastguard Worker expected_attach_type = BPF_MODIFY_RETURN;
839*387f9dfdSAndroid Build Coastguard Worker } else if (strncmp(prog_name, "kretfunc__", 10) == 0) {
840*387f9dfdSAndroid Build Coastguard Worker // kretfunc__vmlinux__vfs_read
841*387f9dfdSAndroid Build Coastguard Worker mod_end = strstr(prog_name + 10, "__");
842*387f9dfdSAndroid Build Coastguard Worker mod_len = mod_end - prog_name - 10;
843*387f9dfdSAndroid Build Coastguard Worker strncpy(mod_name, prog_name + 10, mod_len);
844*387f9dfdSAndroid Build Coastguard Worker name_offset = 10 + mod_len + 2;
845*387f9dfdSAndroid Build Coastguard Worker expected_attach_type = BPF_TRACE_FEXIT;
846*387f9dfdSAndroid Build Coastguard Worker } else if (strncmp(prog_name, "lsm__", 5) == 0) {
847*387f9dfdSAndroid Build Coastguard Worker name_offset = 5;
848*387f9dfdSAndroid Build Coastguard Worker expected_attach_type = BPF_LSM_MAC;
849*387f9dfdSAndroid Build Coastguard Worker } else if (strncmp(prog_name, "bpf_iter__", 10) == 0) {
850*387f9dfdSAndroid Build Coastguard Worker name_offset = 10;
851*387f9dfdSAndroid Build Coastguard Worker expected_attach_type = BPF_TRACE_ITER;
852*387f9dfdSAndroid Build Coastguard Worker }
853*387f9dfdSAndroid Build Coastguard Worker
854*387f9dfdSAndroid Build Coastguard Worker if (prog_type == BPF_PROG_TYPE_TRACING ||
855*387f9dfdSAndroid Build Coastguard Worker prog_type == BPF_PROG_TYPE_LSM) {
856*387f9dfdSAndroid Build Coastguard Worker #ifdef MINIMAL_LIBBPF
857*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "vmlinux BTF not supported in this build of libbpf\n");
858*387f9dfdSAndroid Build Coastguard Worker return -1;
859*387f9dfdSAndroid Build Coastguard Worker #else
860*387f9dfdSAndroid Build Coastguard Worker ret = find_btf_id(mod_name, prog_name + name_offset,
861*387f9dfdSAndroid Build Coastguard Worker expected_attach_type, &fd);
862*387f9dfdSAndroid Build Coastguard Worker if (ret == -EINVAL) {
863*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf: %s BTF is not found\n", mod_name);
864*387f9dfdSAndroid Build Coastguard Worker return ret;
865*387f9dfdSAndroid Build Coastguard Worker } else if (ret < 0) {
866*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf: %s is not found in %s BTF\n",
867*387f9dfdSAndroid Build Coastguard Worker prog_name + name_offset, mod_name);
868*387f9dfdSAndroid Build Coastguard Worker return ret;
869*387f9dfdSAndroid Build Coastguard Worker }
870*387f9dfdSAndroid Build Coastguard Worker
871*387f9dfdSAndroid Build Coastguard Worker opts->attach_btf_obj_fd = fd == -1 ? 0 : fd;
872*387f9dfdSAndroid Build Coastguard Worker opts->attach_btf_id = ret;
873*387f9dfdSAndroid Build Coastguard Worker opts->expected_attach_type = expected_attach_type;
874*387f9dfdSAndroid Build Coastguard Worker #endif
875*387f9dfdSAndroid Build Coastguard Worker }
876*387f9dfdSAndroid Build Coastguard Worker
877*387f9dfdSAndroid Build Coastguard Worker memcpy(new_prog_name, prog_name + name_offset,
878*387f9dfdSAndroid Build Coastguard Worker min(name_len - name_offset, BPF_OBJ_NAME_LEN - 1));
879*387f9dfdSAndroid Build Coastguard Worker }
880*387f9dfdSAndroid Build Coastguard Worker
881*387f9dfdSAndroid Build Coastguard Worker ret = libbpf_bpf_prog_load(prog_type, new_prog_name, license, insns, insns_cnt, opts, opts_log_buf, opts_log_buf_size);
882*387f9dfdSAndroid Build Coastguard Worker
883*387f9dfdSAndroid Build Coastguard Worker // func_info/line_info may not be supported in old kernels.
884*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 && opts->func_info && errno == EINVAL) {
885*387f9dfdSAndroid Build Coastguard Worker opts->prog_btf_fd = 0;
886*387f9dfdSAndroid Build Coastguard Worker opts->func_info = NULL;
887*387f9dfdSAndroid Build Coastguard Worker opts->func_info_cnt = 0;
888*387f9dfdSAndroid Build Coastguard Worker opts->func_info_rec_size = 0;
889*387f9dfdSAndroid Build Coastguard Worker opts->line_info = NULL;
890*387f9dfdSAndroid Build Coastguard Worker opts->line_info_cnt = 0;
891*387f9dfdSAndroid Build Coastguard Worker opts->line_info_rec_size = 0;
892*387f9dfdSAndroid Build Coastguard Worker ret = libbpf_bpf_prog_load(prog_type, new_prog_name, license, insns, insns_cnt, opts, opts_log_buf, opts_log_buf_size);
893*387f9dfdSAndroid Build Coastguard Worker }
894*387f9dfdSAndroid Build Coastguard Worker
895*387f9dfdSAndroid Build Coastguard Worker // BPF object name is not supported on older Kernels.
896*387f9dfdSAndroid Build Coastguard Worker // If we failed due to this, clear the name and try again.
897*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 && name_len && (errno == E2BIG || errno == EINVAL)) {
898*387f9dfdSAndroid Build Coastguard Worker new_prog_name[0] = '\0';
899*387f9dfdSAndroid Build Coastguard Worker ret = libbpf_bpf_prog_load(prog_type, new_prog_name, license, insns, insns_cnt, opts, opts_log_buf, opts_log_buf_size);
900*387f9dfdSAndroid Build Coastguard Worker }
901*387f9dfdSAndroid Build Coastguard Worker
902*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 && errno == EPERM) {
903*387f9dfdSAndroid Build Coastguard Worker if (!allow_rlimit)
904*387f9dfdSAndroid Build Coastguard Worker return ret;
905*387f9dfdSAndroid Build Coastguard Worker
906*387f9dfdSAndroid Build Coastguard Worker // When EPERM is returned, two reasons are possible:
907*387f9dfdSAndroid Build Coastguard Worker // 1. user has no permissions for bpf()
908*387f9dfdSAndroid Build Coastguard Worker // 2. user has insufficent rlimit for locked memory
909*387f9dfdSAndroid Build Coastguard Worker // Unfortunately, there is no api to inspect the current usage of locked
910*387f9dfdSAndroid Build Coastguard Worker // mem for the user, so an accurate calculation of how much memory to lock
911*387f9dfdSAndroid Build Coastguard Worker // for this new program is difficult to calculate. As a hack, bump the limit
912*387f9dfdSAndroid Build Coastguard Worker // to unlimited. If program load fails again, return the error.
913*387f9dfdSAndroid Build Coastguard Worker struct rlimit rl = {};
914*387f9dfdSAndroid Build Coastguard Worker if (getrlimit(RLIMIT_MEMLOCK, &rl) == 0) {
915*387f9dfdSAndroid Build Coastguard Worker rl.rlim_max = RLIM_INFINITY;
916*387f9dfdSAndroid Build Coastguard Worker rl.rlim_cur = rl.rlim_max;
917*387f9dfdSAndroid Build Coastguard Worker if (setrlimit(RLIMIT_MEMLOCK, &rl) == 0)
918*387f9dfdSAndroid Build Coastguard Worker ret = libbpf_bpf_prog_load(prog_type, new_prog_name, license, insns, insns_cnt, opts, opts_log_buf, opts_log_buf_size);
919*387f9dfdSAndroid Build Coastguard Worker }
920*387f9dfdSAndroid Build Coastguard Worker }
921*387f9dfdSAndroid Build Coastguard Worker
922*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 && errno == E2BIG) {
923*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr,
924*387f9dfdSAndroid Build Coastguard Worker "bpf: %s. Program %s too large (%u insns), at most %d insns\n\n",
925*387f9dfdSAndroid Build Coastguard Worker strerror(errno), new_prog_name, insns_cnt, BPF_MAXINSNS);
926*387f9dfdSAndroid Build Coastguard Worker return -1;
927*387f9dfdSAndroid Build Coastguard Worker }
928*387f9dfdSAndroid Build Coastguard Worker
929*387f9dfdSAndroid Build Coastguard Worker // The load has failed. Handle log message.
930*387f9dfdSAndroid Build Coastguard Worker if (ret < 0) {
931*387f9dfdSAndroid Build Coastguard Worker // User has provided a log buffer.
932*387f9dfdSAndroid Build Coastguard Worker if (log_buf_size) {
933*387f9dfdSAndroid Build Coastguard Worker // If logging is not already enabled, enable it and do the syscall again.
934*387f9dfdSAndroid Build Coastguard Worker if (opts->log_level == 0) {
935*387f9dfdSAndroid Build Coastguard Worker opts->log_level = 1;
936*387f9dfdSAndroid Build Coastguard Worker ret = libbpf_bpf_prog_load(prog_type, new_prog_name, license, insns, insns_cnt, opts, log_buf, log_buf_size);
937*387f9dfdSAndroid Build Coastguard Worker }
938*387f9dfdSAndroid Build Coastguard Worker // Print the log message and return.
939*387f9dfdSAndroid Build Coastguard Worker bpf_print_hints(ret, log_buf);
940*387f9dfdSAndroid Build Coastguard Worker if (errno == ENOSPC)
941*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf: log_buf size may be insufficient\n");
942*387f9dfdSAndroid Build Coastguard Worker goto return_result;
943*387f9dfdSAndroid Build Coastguard Worker }
944*387f9dfdSAndroid Build Coastguard Worker
945*387f9dfdSAndroid Build Coastguard Worker // User did not provide log buffer. We will try to increase size of
946*387f9dfdSAndroid Build Coastguard Worker // our temporary log buffer to get full error message.
947*387f9dfdSAndroid Build Coastguard Worker if (tmp_log_buf)
948*387f9dfdSAndroid Build Coastguard Worker free(tmp_log_buf);
949*387f9dfdSAndroid Build Coastguard Worker tmp_log_buf_size = LOG_BUF_SIZE;
950*387f9dfdSAndroid Build Coastguard Worker if (opts->log_level == 0)
951*387f9dfdSAndroid Build Coastguard Worker opts->log_level = 1;
952*387f9dfdSAndroid Build Coastguard Worker for (;;) {
953*387f9dfdSAndroid Build Coastguard Worker tmp_log_buf = malloc(tmp_log_buf_size);
954*387f9dfdSAndroid Build Coastguard Worker if (!tmp_log_buf) {
955*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf: Failed to allocate temporary log buffer: %s\n\n",
956*387f9dfdSAndroid Build Coastguard Worker strerror(errno));
957*387f9dfdSAndroid Build Coastguard Worker goto return_result;
958*387f9dfdSAndroid Build Coastguard Worker }
959*387f9dfdSAndroid Build Coastguard Worker tmp_log_buf[0] = 0;
960*387f9dfdSAndroid Build Coastguard Worker ret = libbpf_bpf_prog_load(prog_type, new_prog_name, license, insns, insns_cnt, opts, tmp_log_buf, tmp_log_buf_size);
961*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 && errno == ENOSPC) {
962*387f9dfdSAndroid Build Coastguard Worker // Temporary buffer size is not enough. Double it and try again.
963*387f9dfdSAndroid Build Coastguard Worker free(tmp_log_buf);
964*387f9dfdSAndroid Build Coastguard Worker tmp_log_buf = NULL;
965*387f9dfdSAndroid Build Coastguard Worker tmp_log_buf_size <<= 1;
966*387f9dfdSAndroid Build Coastguard Worker } else {
967*387f9dfdSAndroid Build Coastguard Worker break;
968*387f9dfdSAndroid Build Coastguard Worker }
969*387f9dfdSAndroid Build Coastguard Worker }
970*387f9dfdSAndroid Build Coastguard Worker }
971*387f9dfdSAndroid Build Coastguard Worker
972*387f9dfdSAndroid Build Coastguard Worker // Check if we should print the log message if log_level is not 0,
973*387f9dfdSAndroid Build Coastguard Worker // either specified by user or set due to error.
974*387f9dfdSAndroid Build Coastguard Worker if (opts->log_level > 0) {
975*387f9dfdSAndroid Build Coastguard Worker // Don't print if user enabled logging and provided log buffer,
976*387f9dfdSAndroid Build Coastguard Worker // but there is no error.
977*387f9dfdSAndroid Build Coastguard Worker if (log_buf && ret < 0)
978*387f9dfdSAndroid Build Coastguard Worker bpf_print_hints(ret, log_buf);
979*387f9dfdSAndroid Build Coastguard Worker else if (tmp_log_buf)
980*387f9dfdSAndroid Build Coastguard Worker bpf_print_hints(ret, tmp_log_buf);
981*387f9dfdSAndroid Build Coastguard Worker }
982*387f9dfdSAndroid Build Coastguard Worker
983*387f9dfdSAndroid Build Coastguard Worker return_result:
984*387f9dfdSAndroid Build Coastguard Worker if (fd >= 0)
985*387f9dfdSAndroid Build Coastguard Worker close(fd);
986*387f9dfdSAndroid Build Coastguard Worker if (tmp_log_buf)
987*387f9dfdSAndroid Build Coastguard Worker free(tmp_log_buf);
988*387f9dfdSAndroid Build Coastguard Worker return ret;
989*387f9dfdSAndroid Build Coastguard Worker }
990*387f9dfdSAndroid Build Coastguard Worker
bcc_prog_load(enum bpf_prog_type prog_type,const char * name,const struct bpf_insn * insns,int prog_len,const char * license,unsigned kern_version,int log_level,char * log_buf,unsigned log_buf_size)991*387f9dfdSAndroid Build Coastguard Worker int bcc_prog_load(enum bpf_prog_type prog_type, const char *name,
992*387f9dfdSAndroid Build Coastguard Worker const struct bpf_insn *insns, int prog_len,
993*387f9dfdSAndroid Build Coastguard Worker const char *license, unsigned kern_version,
994*387f9dfdSAndroid Build Coastguard Worker int log_level, char *log_buf, unsigned log_buf_size)
995*387f9dfdSAndroid Build Coastguard Worker {
996*387f9dfdSAndroid Build Coastguard Worker struct bpf_prog_load_opts opts = {};
997*387f9dfdSAndroid Build Coastguard Worker
998*387f9dfdSAndroid Build Coastguard Worker
999*387f9dfdSAndroid Build Coastguard Worker if (prog_type != BPF_PROG_TYPE_TRACING && prog_type != BPF_PROG_TYPE_EXT)
1000*387f9dfdSAndroid Build Coastguard Worker opts.kern_version = kern_version;
1001*387f9dfdSAndroid Build Coastguard Worker opts.log_level = log_level;
1002*387f9dfdSAndroid Build Coastguard Worker return bcc_prog_load_xattr(prog_type, name, license, insns, &opts, prog_len, log_buf, log_buf_size, true);
1003*387f9dfdSAndroid Build Coastguard Worker }
1004*387f9dfdSAndroid Build Coastguard Worker
bpf_open_raw_sock(const char * name)1005*387f9dfdSAndroid Build Coastguard Worker int bpf_open_raw_sock(const char *name)
1006*387f9dfdSAndroid Build Coastguard Worker {
1007*387f9dfdSAndroid Build Coastguard Worker struct sockaddr_ll sll;
1008*387f9dfdSAndroid Build Coastguard Worker int sock;
1009*387f9dfdSAndroid Build Coastguard Worker
1010*387f9dfdSAndroid Build Coastguard Worker sock = socket(PF_PACKET, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, htons(ETH_P_ALL));
1011*387f9dfdSAndroid Build Coastguard Worker if (sock < 0) {
1012*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "cannot create raw socket\n");
1013*387f9dfdSAndroid Build Coastguard Worker return -1;
1014*387f9dfdSAndroid Build Coastguard Worker }
1015*387f9dfdSAndroid Build Coastguard Worker
1016*387f9dfdSAndroid Build Coastguard Worker /* Do not bind on empty interface names */
1017*387f9dfdSAndroid Build Coastguard Worker if (!name || *name == '\0')
1018*387f9dfdSAndroid Build Coastguard Worker return sock;
1019*387f9dfdSAndroid Build Coastguard Worker
1020*387f9dfdSAndroid Build Coastguard Worker memset(&sll, 0, sizeof(sll));
1021*387f9dfdSAndroid Build Coastguard Worker sll.sll_family = AF_PACKET;
1022*387f9dfdSAndroid Build Coastguard Worker sll.sll_ifindex = if_nametoindex(name);
1023*387f9dfdSAndroid Build Coastguard Worker if (sll.sll_ifindex == 0) {
1024*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf: Resolving device name to index: %s\n", strerror(errno));
1025*387f9dfdSAndroid Build Coastguard Worker close(sock);
1026*387f9dfdSAndroid Build Coastguard Worker return -1;
1027*387f9dfdSAndroid Build Coastguard Worker }
1028*387f9dfdSAndroid Build Coastguard Worker sll.sll_protocol = htons(ETH_P_ALL);
1029*387f9dfdSAndroid Build Coastguard Worker if (bind(sock, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
1030*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bind to %s: %s\n", name, strerror(errno));
1031*387f9dfdSAndroid Build Coastguard Worker close(sock);
1032*387f9dfdSAndroid Build Coastguard Worker return -1;
1033*387f9dfdSAndroid Build Coastguard Worker }
1034*387f9dfdSAndroid Build Coastguard Worker
1035*387f9dfdSAndroid Build Coastguard Worker return sock;
1036*387f9dfdSAndroid Build Coastguard Worker }
1037*387f9dfdSAndroid Build Coastguard Worker
bpf_attach_socket(int sock,int prog)1038*387f9dfdSAndroid Build Coastguard Worker int bpf_attach_socket(int sock, int prog) {
1039*387f9dfdSAndroid Build Coastguard Worker return setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog, sizeof(prog));
1040*387f9dfdSAndroid Build Coastguard Worker }
1041*387f9dfdSAndroid Build Coastguard Worker
1042*387f9dfdSAndroid Build Coastguard Worker #define PMU_TYPE_FILE "/sys/bus/event_source/devices/%s/type"
bpf_find_probe_type(const char * event_type)1043*387f9dfdSAndroid Build Coastguard Worker static int bpf_find_probe_type(const char *event_type)
1044*387f9dfdSAndroid Build Coastguard Worker {
1045*387f9dfdSAndroid Build Coastguard Worker int fd;
1046*387f9dfdSAndroid Build Coastguard Worker int ret;
1047*387f9dfdSAndroid Build Coastguard Worker char buf[PATH_MAX];
1048*387f9dfdSAndroid Build Coastguard Worker
1049*387f9dfdSAndroid Build Coastguard Worker ret = snprintf(buf, sizeof(buf), PMU_TYPE_FILE, event_type);
1050*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 || ret >= (int)sizeof(buf))
1051*387f9dfdSAndroid Build Coastguard Worker return -1;
1052*387f9dfdSAndroid Build Coastguard Worker
1053*387f9dfdSAndroid Build Coastguard Worker fd = open(buf, O_RDONLY | O_CLOEXEC);
1054*387f9dfdSAndroid Build Coastguard Worker if (fd < 0)
1055*387f9dfdSAndroid Build Coastguard Worker return -1;
1056*387f9dfdSAndroid Build Coastguard Worker ret = read(fd, buf, sizeof(buf));
1057*387f9dfdSAndroid Build Coastguard Worker close(fd);
1058*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 || ret >= (int)sizeof(buf))
1059*387f9dfdSAndroid Build Coastguard Worker return -1;
1060*387f9dfdSAndroid Build Coastguard Worker errno = 0;
1061*387f9dfdSAndroid Build Coastguard Worker ret = (int)strtol(buf, NULL, 10);
1062*387f9dfdSAndroid Build Coastguard Worker return errno ? -1 : ret;
1063*387f9dfdSAndroid Build Coastguard Worker }
1064*387f9dfdSAndroid Build Coastguard Worker
1065*387f9dfdSAndroid Build Coastguard Worker #define PMU_RETPROBE_FILE "/sys/bus/event_source/devices/%s/format/retprobe"
bpf_get_retprobe_bit(const char * event_type)1066*387f9dfdSAndroid Build Coastguard Worker static int bpf_get_retprobe_bit(const char *event_type)
1067*387f9dfdSAndroid Build Coastguard Worker {
1068*387f9dfdSAndroid Build Coastguard Worker int fd;
1069*387f9dfdSAndroid Build Coastguard Worker int ret;
1070*387f9dfdSAndroid Build Coastguard Worker char buf[PATH_MAX];
1071*387f9dfdSAndroid Build Coastguard Worker
1072*387f9dfdSAndroid Build Coastguard Worker ret = snprintf(buf, sizeof(buf), PMU_RETPROBE_FILE, event_type);
1073*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 || ret >= (int)sizeof(buf))
1074*387f9dfdSAndroid Build Coastguard Worker return -1;
1075*387f9dfdSAndroid Build Coastguard Worker
1076*387f9dfdSAndroid Build Coastguard Worker fd = open(buf, O_RDONLY | O_CLOEXEC);
1077*387f9dfdSAndroid Build Coastguard Worker if (fd < 0)
1078*387f9dfdSAndroid Build Coastguard Worker return -1;
1079*387f9dfdSAndroid Build Coastguard Worker ret = read(fd, buf, sizeof(buf));
1080*387f9dfdSAndroid Build Coastguard Worker close(fd);
1081*387f9dfdSAndroid Build Coastguard Worker if (ret < 0 || ret >= (int)sizeof(buf))
1082*387f9dfdSAndroid Build Coastguard Worker return -1;
1083*387f9dfdSAndroid Build Coastguard Worker if (strncmp(buf, "config:", strlen("config:")))
1084*387f9dfdSAndroid Build Coastguard Worker return -1;
1085*387f9dfdSAndroid Build Coastguard Worker errno = 0;
1086*387f9dfdSAndroid Build Coastguard Worker ret = (int)strtol(buf + strlen("config:"), NULL, 10);
1087*387f9dfdSAndroid Build Coastguard Worker return errno ? -1 : ret;
1088*387f9dfdSAndroid Build Coastguard Worker }
1089*387f9dfdSAndroid Build Coastguard Worker
1090*387f9dfdSAndroid Build Coastguard Worker /*
1091*387f9dfdSAndroid Build Coastguard Worker * Kernel API with e12f03d ("perf/core: Implement the 'perf_kprobe' PMU") allows
1092*387f9dfdSAndroid Build Coastguard Worker * creating [k,u]probe with perf_event_open, which makes it easier to clean up
1093*387f9dfdSAndroid Build Coastguard Worker * the [k,u]probe. This function tries to create pfd with the perf_kprobe PMU.
1094*387f9dfdSAndroid Build Coastguard Worker */
bpf_try_perf_event_open_with_probe(const char * name,uint64_t offs,int pid,const char * event_type,int is_return,uint64_t ref_ctr_offset)1095*387f9dfdSAndroid Build Coastguard Worker static int bpf_try_perf_event_open_with_probe(const char *name, uint64_t offs,
1096*387f9dfdSAndroid Build Coastguard Worker int pid, const char *event_type, int is_return,
1097*387f9dfdSAndroid Build Coastguard Worker uint64_t ref_ctr_offset)
1098*387f9dfdSAndroid Build Coastguard Worker {
1099*387f9dfdSAndroid Build Coastguard Worker struct perf_event_attr attr = {};
1100*387f9dfdSAndroid Build Coastguard Worker int type = bpf_find_probe_type(event_type);
1101*387f9dfdSAndroid Build Coastguard Worker int is_return_bit = bpf_get_retprobe_bit(event_type);
1102*387f9dfdSAndroid Build Coastguard Worker int cpu = 0;
1103*387f9dfdSAndroid Build Coastguard Worker
1104*387f9dfdSAndroid Build Coastguard Worker if (type < 0 || is_return_bit < 0)
1105*387f9dfdSAndroid Build Coastguard Worker return -1;
1106*387f9dfdSAndroid Build Coastguard Worker attr.sample_period = 1;
1107*387f9dfdSAndroid Build Coastguard Worker attr.wakeup_events = 1;
1108*387f9dfdSAndroid Build Coastguard Worker if (is_return)
1109*387f9dfdSAndroid Build Coastguard Worker attr.config |= 1 << is_return_bit;
1110*387f9dfdSAndroid Build Coastguard Worker attr.config |= (ref_ctr_offset << PERF_UPROBE_REF_CTR_OFFSET_SHIFT);
1111*387f9dfdSAndroid Build Coastguard Worker
1112*387f9dfdSAndroid Build Coastguard Worker /*
1113*387f9dfdSAndroid Build Coastguard Worker * struct perf_event_attr in latest perf_event.h has the following
1114*387f9dfdSAndroid Build Coastguard Worker * extension to config1 and config2. To keep bcc compatibe with
1115*387f9dfdSAndroid Build Coastguard Worker * older perf_event.h, we use config1 and config2 here instead of
1116*387f9dfdSAndroid Build Coastguard Worker * kprobe_func, uprobe_path, kprobe_addr, and probe_offset.
1117*387f9dfdSAndroid Build Coastguard Worker *
1118*387f9dfdSAndroid Build Coastguard Worker * union {
1119*387f9dfdSAndroid Build Coastguard Worker * __u64 bp_addr;
1120*387f9dfdSAndroid Build Coastguard Worker * __u64 kprobe_func;
1121*387f9dfdSAndroid Build Coastguard Worker * __u64 uprobe_path;
1122*387f9dfdSAndroid Build Coastguard Worker * __u64 config1;
1123*387f9dfdSAndroid Build Coastguard Worker * };
1124*387f9dfdSAndroid Build Coastguard Worker * union {
1125*387f9dfdSAndroid Build Coastguard Worker * __u64 bp_len;
1126*387f9dfdSAndroid Build Coastguard Worker * __u64 kprobe_addr;
1127*387f9dfdSAndroid Build Coastguard Worker * __u64 probe_offset;
1128*387f9dfdSAndroid Build Coastguard Worker * __u64 config2;
1129*387f9dfdSAndroid Build Coastguard Worker * };
1130*387f9dfdSAndroid Build Coastguard Worker */
1131*387f9dfdSAndroid Build Coastguard Worker attr.config2 = offs; /* config2 here is kprobe_addr or probe_offset */
1132*387f9dfdSAndroid Build Coastguard Worker attr.size = sizeof(attr);
1133*387f9dfdSAndroid Build Coastguard Worker attr.type = type;
1134*387f9dfdSAndroid Build Coastguard Worker /* config1 here is kprobe_func or uprobe_path */
1135*387f9dfdSAndroid Build Coastguard Worker attr.config1 = ptr_to_u64((void *)name);
1136*387f9dfdSAndroid Build Coastguard Worker // PID filter is only possible for uprobe events.
1137*387f9dfdSAndroid Build Coastguard Worker if (pid < 0)
1138*387f9dfdSAndroid Build Coastguard Worker pid = -1;
1139*387f9dfdSAndroid Build Coastguard Worker // perf_event_open API doesn't allow both pid and cpu to be -1.
1140*387f9dfdSAndroid Build Coastguard Worker // So only set it to -1 when PID is not -1.
1141*387f9dfdSAndroid Build Coastguard Worker // Tracing events do not do CPU filtering in any cases.
1142*387f9dfdSAndroid Build Coastguard Worker if (pid != -1)
1143*387f9dfdSAndroid Build Coastguard Worker cpu = -1;
1144*387f9dfdSAndroid Build Coastguard Worker return syscall(__NR_perf_event_open, &attr, pid, cpu, -1 /* group_fd */,
1145*387f9dfdSAndroid Build Coastguard Worker PERF_FLAG_FD_CLOEXEC);
1146*387f9dfdSAndroid Build Coastguard Worker }
1147*387f9dfdSAndroid Build Coastguard Worker
1148*387f9dfdSAndroid Build Coastguard Worker #define DEBUGFS_TRACEFS "/sys/kernel/debug/tracing"
1149*387f9dfdSAndroid Build Coastguard Worker #define TRACEFS "/sys/kernel/tracing"
1150*387f9dfdSAndroid Build Coastguard Worker
get_tracefs_path()1151*387f9dfdSAndroid Build Coastguard Worker static const char *get_tracefs_path()
1152*387f9dfdSAndroid Build Coastguard Worker {
1153*387f9dfdSAndroid Build Coastguard Worker if (access(DEBUGFS_TRACEFS, F_OK) == 0) {
1154*387f9dfdSAndroid Build Coastguard Worker return DEBUGFS_TRACEFS;
1155*387f9dfdSAndroid Build Coastguard Worker }
1156*387f9dfdSAndroid Build Coastguard Worker return TRACEFS;
1157*387f9dfdSAndroid Build Coastguard Worker }
1158*387f9dfdSAndroid Build Coastguard Worker
1159*387f9dfdSAndroid Build Coastguard Worker
1160*387f9dfdSAndroid Build Coastguard Worker // When a valid Perf Event FD provided through pfd, it will be used to enable
1161*387f9dfdSAndroid Build Coastguard Worker // and attach BPF program to the event, and event_path will be ignored.
1162*387f9dfdSAndroid Build Coastguard Worker // Otherwise, event_path is expected to contain the path to the event in tracefs
1163*387f9dfdSAndroid Build Coastguard Worker // and it will be used to open the Perf Event FD.
1164*387f9dfdSAndroid Build Coastguard Worker // In either case, if the attach partially failed (such as issue with the
1165*387f9dfdSAndroid Build Coastguard Worker // ioctl operations), the **caller** need to clean up the Perf Event FD, either
1166*387f9dfdSAndroid Build Coastguard Worker // provided by the caller or opened here.
bpf_attach_tracing_event(int progfd,const char * event_path,int pid,int * pfd)1167*387f9dfdSAndroid Build Coastguard Worker static int bpf_attach_tracing_event(int progfd, const char *event_path, int pid,
1168*387f9dfdSAndroid Build Coastguard Worker int *pfd)
1169*387f9dfdSAndroid Build Coastguard Worker {
1170*387f9dfdSAndroid Build Coastguard Worker int efd, cpu = 0;
1171*387f9dfdSAndroid Build Coastguard Worker ssize_t bytes;
1172*387f9dfdSAndroid Build Coastguard Worker char buf[PATH_MAX];
1173*387f9dfdSAndroid Build Coastguard Worker struct perf_event_attr attr = {};
1174*387f9dfdSAndroid Build Coastguard Worker // Caller did not provide a valid Perf Event FD. Create one with the tracefs
1175*387f9dfdSAndroid Build Coastguard Worker // event path provided.
1176*387f9dfdSAndroid Build Coastguard Worker if (*pfd < 0) {
1177*387f9dfdSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "%s/id", event_path);
1178*387f9dfdSAndroid Build Coastguard Worker efd = open(buf, O_RDONLY | O_CLOEXEC, 0);
1179*387f9dfdSAndroid Build Coastguard Worker if (efd < 0) {
1180*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "open(%s): %s\n", buf, strerror(errno));
1181*387f9dfdSAndroid Build Coastguard Worker return -1;
1182*387f9dfdSAndroid Build Coastguard Worker }
1183*387f9dfdSAndroid Build Coastguard Worker
1184*387f9dfdSAndroid Build Coastguard Worker bytes = read(efd, buf, sizeof(buf));
1185*387f9dfdSAndroid Build Coastguard Worker if (bytes <= 0 || bytes >= (int)sizeof(buf)) {
1186*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "read(%s): %s\n", buf, strerror(errno));
1187*387f9dfdSAndroid Build Coastguard Worker close(efd);
1188*387f9dfdSAndroid Build Coastguard Worker return -1;
1189*387f9dfdSAndroid Build Coastguard Worker }
1190*387f9dfdSAndroid Build Coastguard Worker close(efd);
1191*387f9dfdSAndroid Build Coastguard Worker buf[bytes] = '\0';
1192*387f9dfdSAndroid Build Coastguard Worker attr.config = strtol(buf, NULL, 0);
1193*387f9dfdSAndroid Build Coastguard Worker attr.type = PERF_TYPE_TRACEPOINT;
1194*387f9dfdSAndroid Build Coastguard Worker attr.sample_period = 1;
1195*387f9dfdSAndroid Build Coastguard Worker attr.wakeup_events = 1;
1196*387f9dfdSAndroid Build Coastguard Worker // PID filter is only possible for uprobe events.
1197*387f9dfdSAndroid Build Coastguard Worker if (pid < 0)
1198*387f9dfdSAndroid Build Coastguard Worker pid = -1;
1199*387f9dfdSAndroid Build Coastguard Worker // perf_event_open API doesn't allow both pid and cpu to be -1.
1200*387f9dfdSAndroid Build Coastguard Worker // So only set it to -1 when PID is not -1.
1201*387f9dfdSAndroid Build Coastguard Worker // Tracing events do not do CPU filtering in any cases.
1202*387f9dfdSAndroid Build Coastguard Worker if (pid != -1)
1203*387f9dfdSAndroid Build Coastguard Worker cpu = -1;
1204*387f9dfdSAndroid Build Coastguard Worker *pfd = syscall(__NR_perf_event_open, &attr, pid, cpu, -1 /* group_fd */, PERF_FLAG_FD_CLOEXEC);
1205*387f9dfdSAndroid Build Coastguard Worker if (*pfd < 0) {
1206*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "perf_event_open(%s/id): %s\n", event_path, strerror(errno));
1207*387f9dfdSAndroid Build Coastguard Worker return -1;
1208*387f9dfdSAndroid Build Coastguard Worker }
1209*387f9dfdSAndroid Build Coastguard Worker }
1210*387f9dfdSAndroid Build Coastguard Worker
1211*387f9dfdSAndroid Build Coastguard Worker if (ioctl(*pfd, PERF_EVENT_IOC_SET_BPF, progfd) < 0) {
1212*387f9dfdSAndroid Build Coastguard Worker perror("ioctl(PERF_EVENT_IOC_SET_BPF)");
1213*387f9dfdSAndroid Build Coastguard Worker return -1;
1214*387f9dfdSAndroid Build Coastguard Worker }
1215*387f9dfdSAndroid Build Coastguard Worker if (ioctl(*pfd, PERF_EVENT_IOC_ENABLE, 0) < 0) {
1216*387f9dfdSAndroid Build Coastguard Worker perror("ioctl(PERF_EVENT_IOC_ENABLE)");
1217*387f9dfdSAndroid Build Coastguard Worker return -1;
1218*387f9dfdSAndroid Build Coastguard Worker }
1219*387f9dfdSAndroid Build Coastguard Worker
1220*387f9dfdSAndroid Build Coastguard Worker return 0;
1221*387f9dfdSAndroid Build Coastguard Worker }
1222*387f9dfdSAndroid Build Coastguard Worker
1223*387f9dfdSAndroid Build Coastguard Worker /* Creates an [uk]probe using tracefs.
1224*387f9dfdSAndroid Build Coastguard Worker * On success, the path to the probe is placed in buf (which is assumed to be of size PATH_MAX).
1225*387f9dfdSAndroid Build Coastguard Worker */
create_probe_event(char * buf,const char * ev_name,enum bpf_probe_attach_type attach_type,const char * config1,uint64_t offset,const char * event_type,pid_t pid,int maxactive)1226*387f9dfdSAndroid Build Coastguard Worker static int create_probe_event(char *buf, const char *ev_name,
1227*387f9dfdSAndroid Build Coastguard Worker enum bpf_probe_attach_type attach_type,
1228*387f9dfdSAndroid Build Coastguard Worker const char *config1, uint64_t offset,
1229*387f9dfdSAndroid Build Coastguard Worker const char *event_type, pid_t pid, int maxactive)
1230*387f9dfdSAndroid Build Coastguard Worker {
1231*387f9dfdSAndroid Build Coastguard Worker int kfd = -1, res = -1;
1232*387f9dfdSAndroid Build Coastguard Worker char ev_alias[256];
1233*387f9dfdSAndroid Build Coastguard Worker bool is_kprobe = strncmp("kprobe", event_type, 6) == 0;
1234*387f9dfdSAndroid Build Coastguard Worker bool use_debugfs = false;
1235*387f9dfdSAndroid Build Coastguard Worker
1236*387f9dfdSAndroid Build Coastguard Worker snprintf(buf, PATH_MAX, "%s/%s_events", get_tracefs_path(), event_type);
1237*387f9dfdSAndroid Build Coastguard Worker kfd = open(buf, O_WRONLY | O_APPEND | O_CLOEXEC, 0);
1238*387f9dfdSAndroid Build Coastguard Worker if (kfd < 0) {
1239*387f9dfdSAndroid Build Coastguard Worker use_debugfs = true;
1240*387f9dfdSAndroid Build Coastguard Worker snprintf(buf, PATH_MAX, "/sys/kernel/debug/tracing/%s_events", event_type);
1241*387f9dfdSAndroid Build Coastguard Worker kfd = open(buf, O_WRONLY | O_APPEND | O_CLOEXEC, 0);
1242*387f9dfdSAndroid Build Coastguard Worker if (kfd < 0) {
1243*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "%s: open(%s): %s\n", __func__, buf,
1244*387f9dfdSAndroid Build Coastguard Worker strerror(errno));
1245*387f9dfdSAndroid Build Coastguard Worker return -1;
1246*387f9dfdSAndroid Build Coastguard Worker }
1247*387f9dfdSAndroid Build Coastguard Worker }
1248*387f9dfdSAndroid Build Coastguard Worker
1249*387f9dfdSAndroid Build Coastguard Worker res = snprintf(ev_alias, sizeof(ev_alias), "%s_bcc_%d", ev_name, getpid());
1250*387f9dfdSAndroid Build Coastguard Worker if (res < 0 || res >= sizeof(ev_alias)) {
1251*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "Event name (%s) is too long for buffer\n", ev_name);
1252*387f9dfdSAndroid Build Coastguard Worker close(kfd);
1253*387f9dfdSAndroid Build Coastguard Worker goto error;
1254*387f9dfdSAndroid Build Coastguard Worker }
1255*387f9dfdSAndroid Build Coastguard Worker
1256*387f9dfdSAndroid Build Coastguard Worker if (is_kprobe) {
1257*387f9dfdSAndroid Build Coastguard Worker if (offset > 0 && attach_type == BPF_PROBE_ENTRY)
1258*387f9dfdSAndroid Build Coastguard Worker snprintf(buf, PATH_MAX, "p:kprobes/%s %s+%"PRIu64,
1259*387f9dfdSAndroid Build Coastguard Worker ev_alias, config1, offset);
1260*387f9dfdSAndroid Build Coastguard Worker else if (maxactive > 0 && attach_type == BPF_PROBE_RETURN)
1261*387f9dfdSAndroid Build Coastguard Worker snprintf(buf, PATH_MAX, "r%d:kprobes/%s %s",
1262*387f9dfdSAndroid Build Coastguard Worker maxactive, ev_alias, config1);
1263*387f9dfdSAndroid Build Coastguard Worker else
1264*387f9dfdSAndroid Build Coastguard Worker snprintf(buf, PATH_MAX, "%c:kprobes/%s %s",
1265*387f9dfdSAndroid Build Coastguard Worker attach_type == BPF_PROBE_ENTRY ? 'p' : 'r',
1266*387f9dfdSAndroid Build Coastguard Worker ev_alias, config1);
1267*387f9dfdSAndroid Build Coastguard Worker } else {
1268*387f9dfdSAndroid Build Coastguard Worker res = snprintf(buf, PATH_MAX, "%c:%ss/%s %s:0x%lx", attach_type==BPF_PROBE_ENTRY ? 'p' : 'r',
1269*387f9dfdSAndroid Build Coastguard Worker event_type, ev_alias, config1, (unsigned long)offset);
1270*387f9dfdSAndroid Build Coastguard Worker if (res < 0 || res >= PATH_MAX) {
1271*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "Event alias (%s) too long for buffer\n", ev_alias);
1272*387f9dfdSAndroid Build Coastguard Worker close(kfd);
1273*387f9dfdSAndroid Build Coastguard Worker return -1;
1274*387f9dfdSAndroid Build Coastguard Worker }
1275*387f9dfdSAndroid Build Coastguard Worker }
1276*387f9dfdSAndroid Build Coastguard Worker
1277*387f9dfdSAndroid Build Coastguard Worker if (write(kfd, buf, strlen(buf)) < 0) {
1278*387f9dfdSAndroid Build Coastguard Worker if (errno == ENOENT)
1279*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "cannot attach %s, probe entry may not exist\n", event_type);
1280*387f9dfdSAndroid Build Coastguard Worker else
1281*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "cannot attach %s, %s\n", event_type, strerror(errno));
1282*387f9dfdSAndroid Build Coastguard Worker close(kfd);
1283*387f9dfdSAndroid Build Coastguard Worker goto error;
1284*387f9dfdSAndroid Build Coastguard Worker }
1285*387f9dfdSAndroid Build Coastguard Worker close(kfd);
1286*387f9dfdSAndroid Build Coastguard Worker snprintf(buf, PATH_MAX, "%s/events/%ss/%s", get_tracefs_path(),
1287*387f9dfdSAndroid Build Coastguard Worker event_type, ev_alias);
1288*387f9dfdSAndroid Build Coastguard Worker return 0;
1289*387f9dfdSAndroid Build Coastguard Worker error:
1290*387f9dfdSAndroid Build Coastguard Worker return -1;
1291*387f9dfdSAndroid Build Coastguard Worker }
1292*387f9dfdSAndroid Build Coastguard Worker
1293*387f9dfdSAndroid Build Coastguard Worker // config1 could be either kprobe_func or uprobe_path,
1294*387f9dfdSAndroid Build Coastguard Worker // see bpf_try_perf_event_open_with_probe().
bpf_attach_probe(int progfd,enum bpf_probe_attach_type attach_type,const char * ev_name,const char * config1,const char * event_type,uint64_t offset,pid_t pid,int maxactive,uint32_t ref_ctr_offset)1295*387f9dfdSAndroid Build Coastguard Worker static int bpf_attach_probe(int progfd, enum bpf_probe_attach_type attach_type,
1296*387f9dfdSAndroid Build Coastguard Worker const char *ev_name, const char *config1, const char* event_type,
1297*387f9dfdSAndroid Build Coastguard Worker uint64_t offset, pid_t pid, int maxactive,
1298*387f9dfdSAndroid Build Coastguard Worker uint32_t ref_ctr_offset)
1299*387f9dfdSAndroid Build Coastguard Worker {
1300*387f9dfdSAndroid Build Coastguard Worker int kfd, pfd = -1;
1301*387f9dfdSAndroid Build Coastguard Worker char buf[PATH_MAX], fname[256], kprobe_events[PATH_MAX];
1302*387f9dfdSAndroid Build Coastguard Worker bool is_kprobe = strncmp("kprobe", event_type, 6) == 0;
1303*387f9dfdSAndroid Build Coastguard Worker
1304*387f9dfdSAndroid Build Coastguard Worker if (maxactive <= 0)
1305*387f9dfdSAndroid Build Coastguard Worker // Try create the [k,u]probe Perf Event with perf_event_open API.
1306*387f9dfdSAndroid Build Coastguard Worker pfd = bpf_try_perf_event_open_with_probe(config1, offset, pid, event_type,
1307*387f9dfdSAndroid Build Coastguard Worker attach_type != BPF_PROBE_ENTRY,
1308*387f9dfdSAndroid Build Coastguard Worker ref_ctr_offset);
1309*387f9dfdSAndroid Build Coastguard Worker
1310*387f9dfdSAndroid Build Coastguard Worker // If failed, most likely Kernel doesn't support the perf_kprobe PMU
1311*387f9dfdSAndroid Build Coastguard Worker // (e12f03d "perf/core: Implement the 'perf_kprobe' PMU") yet.
1312*387f9dfdSAndroid Build Coastguard Worker // Try create the event using tracefs.
1313*387f9dfdSAndroid Build Coastguard Worker if (pfd < 0) {
1314*387f9dfdSAndroid Build Coastguard Worker if (create_probe_event(buf, ev_name, attach_type, config1, offset,
1315*387f9dfdSAndroid Build Coastguard Worker event_type, pid, maxactive) < 0)
1316*387f9dfdSAndroid Build Coastguard Worker goto error;
1317*387f9dfdSAndroid Build Coastguard Worker
1318*387f9dfdSAndroid Build Coastguard Worker // If we're using maxactive, we need to check that the event was created
1319*387f9dfdSAndroid Build Coastguard Worker // under the expected name. If tracefs doesn't support maxactive yet
1320*387f9dfdSAndroid Build Coastguard Worker // (kernel < 4.12), the event is created under a different name; we need to
1321*387f9dfdSAndroid Build Coastguard Worker // delete that event and start again without maxactive.
1322*387f9dfdSAndroid Build Coastguard Worker if (is_kprobe && maxactive > 0 && attach_type == BPF_PROBE_RETURN) {
1323*387f9dfdSAndroid Build Coastguard Worker if (snprintf(fname, sizeof(fname), "%s/id", buf) >= sizeof(fname)) {
1324*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "filename (%s) is too long for buffer\n", buf);
1325*387f9dfdSAndroid Build Coastguard Worker goto error;
1326*387f9dfdSAndroid Build Coastguard Worker }
1327*387f9dfdSAndroid Build Coastguard Worker if (access(fname, F_OK) == -1) {
1328*387f9dfdSAndroid Build Coastguard Worker snprintf(kprobe_events, PATH_MAX, "%s/kprobe_events", get_tracefs_path());
1329*387f9dfdSAndroid Build Coastguard Worker // Deleting kprobe event with incorrect name.
1330*387f9dfdSAndroid Build Coastguard Worker kfd = open(kprobe_events, O_WRONLY | O_APPEND | O_CLOEXEC, 0);
1331*387f9dfdSAndroid Build Coastguard Worker if (kfd < 0) {
1332*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "open(%s): %s\n", kprobe_events, strerror(errno));
1333*387f9dfdSAndroid Build Coastguard Worker return -1;
1334*387f9dfdSAndroid Build Coastguard Worker }
1335*387f9dfdSAndroid Build Coastguard Worker snprintf(fname, sizeof(fname), "-:kprobes/%s_0", ev_name);
1336*387f9dfdSAndroid Build Coastguard Worker if (write(kfd, fname, strlen(fname)) < 0) {
1337*387f9dfdSAndroid Build Coastguard Worker if (errno == ENOENT)
1338*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "cannot detach kprobe, probe entry may not exist\n");
1339*387f9dfdSAndroid Build Coastguard Worker else
1340*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "cannot detach kprobe, %s\n", strerror(errno));
1341*387f9dfdSAndroid Build Coastguard Worker close(kfd);
1342*387f9dfdSAndroid Build Coastguard Worker goto error;
1343*387f9dfdSAndroid Build Coastguard Worker }
1344*387f9dfdSAndroid Build Coastguard Worker close(kfd);
1345*387f9dfdSAndroid Build Coastguard Worker
1346*387f9dfdSAndroid Build Coastguard Worker // Re-creating kprobe event without maxactive.
1347*387f9dfdSAndroid Build Coastguard Worker if (create_probe_event(buf, ev_name, attach_type, config1,
1348*387f9dfdSAndroid Build Coastguard Worker offset, event_type, pid, 0) < 0)
1349*387f9dfdSAndroid Build Coastguard Worker goto error;
1350*387f9dfdSAndroid Build Coastguard Worker }
1351*387f9dfdSAndroid Build Coastguard Worker }
1352*387f9dfdSAndroid Build Coastguard Worker }
1353*387f9dfdSAndroid Build Coastguard Worker // If perf_event_open succeeded, bpf_attach_tracing_event will use the created
1354*387f9dfdSAndroid Build Coastguard Worker // Perf Event FD directly and buf would be empty and unused.
1355*387f9dfdSAndroid Build Coastguard Worker // Otherwise it will read the event ID from the path in buf, create the
1356*387f9dfdSAndroid Build Coastguard Worker // Perf Event event using that ID, and updated value of pfd.
1357*387f9dfdSAndroid Build Coastguard Worker if (bpf_attach_tracing_event(progfd, buf, pid, &pfd) == 0)
1358*387f9dfdSAndroid Build Coastguard Worker return pfd;
1359*387f9dfdSAndroid Build Coastguard Worker
1360*387f9dfdSAndroid Build Coastguard Worker error:
1361*387f9dfdSAndroid Build Coastguard Worker bpf_close_perf_event_fd(pfd);
1362*387f9dfdSAndroid Build Coastguard Worker return -1;
1363*387f9dfdSAndroid Build Coastguard Worker }
1364*387f9dfdSAndroid Build Coastguard Worker
bpf_attach_kprobe(int progfd,enum bpf_probe_attach_type attach_type,const char * ev_name,const char * fn_name,uint64_t fn_offset,int maxactive)1365*387f9dfdSAndroid Build Coastguard Worker int bpf_attach_kprobe(int progfd, enum bpf_probe_attach_type attach_type,
1366*387f9dfdSAndroid Build Coastguard Worker const char *ev_name, const char *fn_name,
1367*387f9dfdSAndroid Build Coastguard Worker uint64_t fn_offset, int maxactive)
1368*387f9dfdSAndroid Build Coastguard Worker {
1369*387f9dfdSAndroid Build Coastguard Worker return bpf_attach_probe(progfd, attach_type,
1370*387f9dfdSAndroid Build Coastguard Worker ev_name, fn_name, "kprobe",
1371*387f9dfdSAndroid Build Coastguard Worker fn_offset, -1, maxactive, 0);
1372*387f9dfdSAndroid Build Coastguard Worker }
1373*387f9dfdSAndroid Build Coastguard Worker
_find_archive_path_and_offset(const char * entry_path,char out_path[PATH_MAX],uint64_t * offset)1374*387f9dfdSAndroid Build Coastguard Worker static int _find_archive_path_and_offset(const char *entry_path,
1375*387f9dfdSAndroid Build Coastguard Worker char out_path[PATH_MAX],
1376*387f9dfdSAndroid Build Coastguard Worker uint64_t *offset) {
1377*387f9dfdSAndroid Build Coastguard Worker const char *separator = strstr(entry_path, "!/");
1378*387f9dfdSAndroid Build Coastguard Worker if (separator == NULL || (separator - entry_path) >= PATH_MAX) {
1379*387f9dfdSAndroid Build Coastguard Worker return -1;
1380*387f9dfdSAndroid Build Coastguard Worker }
1381*387f9dfdSAndroid Build Coastguard Worker
1382*387f9dfdSAndroid Build Coastguard Worker struct bcc_zip_entry entry;
1383*387f9dfdSAndroid Build Coastguard Worker struct bcc_zip_archive *archive =
1384*387f9dfdSAndroid Build Coastguard Worker bcc_zip_archive_open_and_find(entry_path, &entry);
1385*387f9dfdSAndroid Build Coastguard Worker if (archive == NULL) {
1386*387f9dfdSAndroid Build Coastguard Worker return -1;
1387*387f9dfdSAndroid Build Coastguard Worker }
1388*387f9dfdSAndroid Build Coastguard Worker if (entry.compression) {
1389*387f9dfdSAndroid Build Coastguard Worker bcc_zip_archive_close(archive);
1390*387f9dfdSAndroid Build Coastguard Worker return -1;
1391*387f9dfdSAndroid Build Coastguard Worker }
1392*387f9dfdSAndroid Build Coastguard Worker
1393*387f9dfdSAndroid Build Coastguard Worker strncpy(out_path, entry_path, separator - entry_path);
1394*387f9dfdSAndroid Build Coastguard Worker out_path[separator - entry_path] = 0;
1395*387f9dfdSAndroid Build Coastguard Worker *offset += entry.data_offset;
1396*387f9dfdSAndroid Build Coastguard Worker
1397*387f9dfdSAndroid Build Coastguard Worker bcc_zip_archive_close(archive);
1398*387f9dfdSAndroid Build Coastguard Worker return 0;
1399*387f9dfdSAndroid Build Coastguard Worker }
1400*387f9dfdSAndroid Build Coastguard Worker
bpf_attach_uprobe(int progfd,enum bpf_probe_attach_type attach_type,const char * ev_name,const char * binary_path,uint64_t offset,pid_t pid,uint32_t ref_ctr_offset)1401*387f9dfdSAndroid Build Coastguard Worker int bpf_attach_uprobe(int progfd, enum bpf_probe_attach_type attach_type,
1402*387f9dfdSAndroid Build Coastguard Worker const char *ev_name, const char *binary_path,
1403*387f9dfdSAndroid Build Coastguard Worker uint64_t offset, pid_t pid, uint32_t ref_ctr_offset)
1404*387f9dfdSAndroid Build Coastguard Worker {
1405*387f9dfdSAndroid Build Coastguard Worker char archive_path[PATH_MAX];
1406*387f9dfdSAndroid Build Coastguard Worker if (access(binary_path, F_OK) != 0 &&
1407*387f9dfdSAndroid Build Coastguard Worker _find_archive_path_and_offset(binary_path, archive_path, &offset) == 0) {
1408*387f9dfdSAndroid Build Coastguard Worker binary_path = archive_path;
1409*387f9dfdSAndroid Build Coastguard Worker }
1410*387f9dfdSAndroid Build Coastguard Worker
1411*387f9dfdSAndroid Build Coastguard Worker return bpf_attach_probe(progfd, attach_type,
1412*387f9dfdSAndroid Build Coastguard Worker ev_name, binary_path, "uprobe",
1413*387f9dfdSAndroid Build Coastguard Worker offset, pid, -1, ref_ctr_offset);
1414*387f9dfdSAndroid Build Coastguard Worker }
1415*387f9dfdSAndroid Build Coastguard Worker
bpf_detach_probe(const char * ev_name,const char * event_type)1416*387f9dfdSAndroid Build Coastguard Worker static int bpf_detach_probe(const char *ev_name, const char *event_type)
1417*387f9dfdSAndroid Build Coastguard Worker {
1418*387f9dfdSAndroid Build Coastguard Worker int kfd = -1, res;
1419*387f9dfdSAndroid Build Coastguard Worker char buf[PATH_MAX];
1420*387f9dfdSAndroid Build Coastguard Worker int found_event = 0;
1421*387f9dfdSAndroid Build Coastguard Worker size_t bufsize = 0;
1422*387f9dfdSAndroid Build Coastguard Worker char *cptr = NULL;
1423*387f9dfdSAndroid Build Coastguard Worker FILE *fp;
1424*387f9dfdSAndroid Build Coastguard Worker bool use_debugfs = false;
1425*387f9dfdSAndroid Build Coastguard Worker
1426*387f9dfdSAndroid Build Coastguard Worker /*
1427*387f9dfdSAndroid Build Coastguard Worker * For [k,u]probe created with perf_event_open (on newer kernel), it is
1428*387f9dfdSAndroid Build Coastguard Worker * not necessary to clean it up in [k,u]probe_events. We first look up
1429*387f9dfdSAndroid Build Coastguard Worker * the %s_bcc_%d line in [k,u]probe_events. If the event is not found,
1430*387f9dfdSAndroid Build Coastguard Worker * it is safe to skip the cleaning up process (write -:... to the file).
1431*387f9dfdSAndroid Build Coastguard Worker */
1432*387f9dfdSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "%s/%s_events", get_tracefs_path(), event_type);
1433*387f9dfdSAndroid Build Coastguard Worker fp = fopen(buf, "r");
1434*387f9dfdSAndroid Build Coastguard Worker if (!fp) {
1435*387f9dfdSAndroid Build Coastguard Worker use_debugfs = true;
1436*387f9dfdSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/%s_events", event_type);
1437*387f9dfdSAndroid Build Coastguard Worker fp = fopen(buf, "re");
1438*387f9dfdSAndroid Build Coastguard Worker if (!fp) {
1439*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "open(%s): %s\n", buf, strerror(errno));
1440*387f9dfdSAndroid Build Coastguard Worker goto error;
1441*387f9dfdSAndroid Build Coastguard Worker }
1442*387f9dfdSAndroid Build Coastguard Worker }
1443*387f9dfdSAndroid Build Coastguard Worker
1444*387f9dfdSAndroid Build Coastguard Worker res = snprintf(buf, sizeof(buf), "%ss/%s_bcc_%d", event_type, ev_name, getpid());
1445*387f9dfdSAndroid Build Coastguard Worker if (res < 0 || res >= (int)sizeof(buf)) {
1446*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "snprintf(%s): %d\n", ev_name, res);
1447*387f9dfdSAndroid Build Coastguard Worker goto error;
1448*387f9dfdSAndroid Build Coastguard Worker }
1449*387f9dfdSAndroid Build Coastguard Worker
1450*387f9dfdSAndroid Build Coastguard Worker while (getline(&cptr, &bufsize, fp) != -1)
1451*387f9dfdSAndroid Build Coastguard Worker if (strstr(cptr, buf) != NULL) {
1452*387f9dfdSAndroid Build Coastguard Worker found_event = 1;
1453*387f9dfdSAndroid Build Coastguard Worker break;
1454*387f9dfdSAndroid Build Coastguard Worker }
1455*387f9dfdSAndroid Build Coastguard Worker free(cptr);
1456*387f9dfdSAndroid Build Coastguard Worker fclose(fp);
1457*387f9dfdSAndroid Build Coastguard Worker fp = NULL;
1458*387f9dfdSAndroid Build Coastguard Worker
1459*387f9dfdSAndroid Build Coastguard Worker if (!found_event)
1460*387f9dfdSAndroid Build Coastguard Worker return 0;
1461*387f9dfdSAndroid Build Coastguard Worker
1462*387f9dfdSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "%s/%s_events", get_tracefs_path(), event_type);
1463*387f9dfdSAndroid Build Coastguard Worker kfd = open(buf, O_WRONLY | O_APPEND | O_CLOEXEC, 0);
1464*387f9dfdSAndroid Build Coastguard Worker if (kfd < 0) {
1465*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "open(%s): %s\n", buf, strerror(errno));
1466*387f9dfdSAndroid Build Coastguard Worker goto error;
1467*387f9dfdSAndroid Build Coastguard Worker }
1468*387f9dfdSAndroid Build Coastguard Worker
1469*387f9dfdSAndroid Build Coastguard Worker res = snprintf(buf, sizeof(buf), "-:%ss/%s_bcc_%d", event_type, ev_name, getpid());
1470*387f9dfdSAndroid Build Coastguard Worker if (res < 0 || res >= (int)sizeof(buf)) {
1471*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "snprintf(%s): %d\n", ev_name, res);
1472*387f9dfdSAndroid Build Coastguard Worker goto error;
1473*387f9dfdSAndroid Build Coastguard Worker }
1474*387f9dfdSAndroid Build Coastguard Worker if (write(kfd, buf, strlen(buf)) < 0) {
1475*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "write(%s): %s\n", buf, strerror(errno));
1476*387f9dfdSAndroid Build Coastguard Worker goto error;
1477*387f9dfdSAndroid Build Coastguard Worker }
1478*387f9dfdSAndroid Build Coastguard Worker
1479*387f9dfdSAndroid Build Coastguard Worker close(kfd);
1480*387f9dfdSAndroid Build Coastguard Worker return 0;
1481*387f9dfdSAndroid Build Coastguard Worker
1482*387f9dfdSAndroid Build Coastguard Worker error:
1483*387f9dfdSAndroid Build Coastguard Worker if (kfd >= 0)
1484*387f9dfdSAndroid Build Coastguard Worker close(kfd);
1485*387f9dfdSAndroid Build Coastguard Worker if (fp)
1486*387f9dfdSAndroid Build Coastguard Worker fclose(fp);
1487*387f9dfdSAndroid Build Coastguard Worker return -1;
1488*387f9dfdSAndroid Build Coastguard Worker }
1489*387f9dfdSAndroid Build Coastguard Worker
bpf_detach_kprobe(const char * ev_name)1490*387f9dfdSAndroid Build Coastguard Worker int bpf_detach_kprobe(const char *ev_name)
1491*387f9dfdSAndroid Build Coastguard Worker {
1492*387f9dfdSAndroid Build Coastguard Worker return bpf_detach_probe(ev_name, "kprobe");
1493*387f9dfdSAndroid Build Coastguard Worker }
1494*387f9dfdSAndroid Build Coastguard Worker
bpf_detach_uprobe(const char * ev_name)1495*387f9dfdSAndroid Build Coastguard Worker int bpf_detach_uprobe(const char *ev_name)
1496*387f9dfdSAndroid Build Coastguard Worker {
1497*387f9dfdSAndroid Build Coastguard Worker return bpf_detach_probe(ev_name, "uprobe");
1498*387f9dfdSAndroid Build Coastguard Worker }
1499*387f9dfdSAndroid Build Coastguard Worker
bpf_attach_tracepoint(int progfd,const char * tp_category,const char * tp_name)1500*387f9dfdSAndroid Build Coastguard Worker int bpf_attach_tracepoint(int progfd, const char *tp_category,
1501*387f9dfdSAndroid Build Coastguard Worker const char *tp_name)
1502*387f9dfdSAndroid Build Coastguard Worker {
1503*387f9dfdSAndroid Build Coastguard Worker char buf[256];
1504*387f9dfdSAndroid Build Coastguard Worker int pfd = -1;
1505*387f9dfdSAndroid Build Coastguard Worker
1506*387f9dfdSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "%s/events/%s/%s", get_tracefs_path(), tp_category, tp_name);
1507*387f9dfdSAndroid Build Coastguard Worker if (bpf_attach_tracing_event(progfd, buf, -1 /* PID */, &pfd) == 0)
1508*387f9dfdSAndroid Build Coastguard Worker return pfd;
1509*387f9dfdSAndroid Build Coastguard Worker
1510*387f9dfdSAndroid Build Coastguard Worker bpf_close_perf_event_fd(pfd);
1511*387f9dfdSAndroid Build Coastguard Worker return -1;
1512*387f9dfdSAndroid Build Coastguard Worker }
1513*387f9dfdSAndroid Build Coastguard Worker
bpf_detach_tracepoint(const char * tp_category,const char * tp_name)1514*387f9dfdSAndroid Build Coastguard Worker int bpf_detach_tracepoint(const char *tp_category, const char *tp_name) {
1515*387f9dfdSAndroid Build Coastguard Worker UNUSED(tp_category);
1516*387f9dfdSAndroid Build Coastguard Worker UNUSED(tp_name);
1517*387f9dfdSAndroid Build Coastguard Worker // Right now, there is nothing to do, but it's a good idea to encourage
1518*387f9dfdSAndroid Build Coastguard Worker // callers to detach anything they attach.
1519*387f9dfdSAndroid Build Coastguard Worker return 0;
1520*387f9dfdSAndroid Build Coastguard Worker }
1521*387f9dfdSAndroid Build Coastguard Worker
bpf_attach_raw_tracepoint(int progfd,const char * tp_name)1522*387f9dfdSAndroid Build Coastguard Worker int bpf_attach_raw_tracepoint(int progfd, const char *tp_name)
1523*387f9dfdSAndroid Build Coastguard Worker {
1524*387f9dfdSAndroid Build Coastguard Worker int ret;
1525*387f9dfdSAndroid Build Coastguard Worker
1526*387f9dfdSAndroid Build Coastguard Worker ret = bpf_raw_tracepoint_open(tp_name, progfd);
1527*387f9dfdSAndroid Build Coastguard Worker if (ret < 0)
1528*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf_attach_raw_tracepoint (%s): %s\n", tp_name, strerror(errno));
1529*387f9dfdSAndroid Build Coastguard Worker return ret;
1530*387f9dfdSAndroid Build Coastguard Worker }
1531*387f9dfdSAndroid Build Coastguard Worker
1532*387f9dfdSAndroid Build Coastguard Worker #ifndef MINIMAL_LIBBPF
bpf_has_kernel_btf(void)1533*387f9dfdSAndroid Build Coastguard Worker bool bpf_has_kernel_btf(void)
1534*387f9dfdSAndroid Build Coastguard Worker {
1535*387f9dfdSAndroid Build Coastguard Worker struct btf *btf;
1536*387f9dfdSAndroid Build Coastguard Worker int err;
1537*387f9dfdSAndroid Build Coastguard Worker
1538*387f9dfdSAndroid Build Coastguard Worker btf = btf__parse_raw("/sys/kernel/btf/vmlinux");
1539*387f9dfdSAndroid Build Coastguard Worker err = libbpf_get_error(btf);
1540*387f9dfdSAndroid Build Coastguard Worker if (err)
1541*387f9dfdSAndroid Build Coastguard Worker return false;
1542*387f9dfdSAndroid Build Coastguard Worker
1543*387f9dfdSAndroid Build Coastguard Worker btf__free(btf);
1544*387f9dfdSAndroid Build Coastguard Worker return true;
1545*387f9dfdSAndroid Build Coastguard Worker }
1546*387f9dfdSAndroid Build Coastguard Worker
find_member_by_name(struct btf * btf,const struct btf_type * btf_type,const char * field_name)1547*387f9dfdSAndroid Build Coastguard Worker static int find_member_by_name(struct btf *btf, const struct btf_type *btf_type, const char *field_name) {
1548*387f9dfdSAndroid Build Coastguard Worker const struct btf_member *btf_member = btf_members(btf_type);
1549*387f9dfdSAndroid Build Coastguard Worker int i;
1550*387f9dfdSAndroid Build Coastguard Worker
1551*387f9dfdSAndroid Build Coastguard Worker for (i = 0; i < btf_vlen(btf_type); i++, btf_member++) {
1552*387f9dfdSAndroid Build Coastguard Worker const char *name = btf__name_by_offset(btf, btf_member->name_off);
1553*387f9dfdSAndroid Build Coastguard Worker if (!strcmp(name, field_name)) {
1554*387f9dfdSAndroid Build Coastguard Worker return 1;
1555*387f9dfdSAndroid Build Coastguard Worker } else if (name[0] == '\0') {
1556*387f9dfdSAndroid Build Coastguard Worker if (find_member_by_name(btf, btf__type_by_id(btf, btf_member->type), field_name))
1557*387f9dfdSAndroid Build Coastguard Worker return 1;
1558*387f9dfdSAndroid Build Coastguard Worker }
1559*387f9dfdSAndroid Build Coastguard Worker }
1560*387f9dfdSAndroid Build Coastguard Worker return 0;
1561*387f9dfdSAndroid Build Coastguard Worker }
1562*387f9dfdSAndroid Build Coastguard Worker
kernel_struct_has_field(const char * struct_name,const char * field_name)1563*387f9dfdSAndroid Build Coastguard Worker int kernel_struct_has_field(const char *struct_name, const char *field_name)
1564*387f9dfdSAndroid Build Coastguard Worker {
1565*387f9dfdSAndroid Build Coastguard Worker const struct btf_type *btf_type;
1566*387f9dfdSAndroid Build Coastguard Worker struct btf *btf;
1567*387f9dfdSAndroid Build Coastguard Worker int ret, btf_id;
1568*387f9dfdSAndroid Build Coastguard Worker
1569*387f9dfdSAndroid Build Coastguard Worker btf = btf__load_vmlinux_btf();
1570*387f9dfdSAndroid Build Coastguard Worker ret = libbpf_get_error(btf);
1571*387f9dfdSAndroid Build Coastguard Worker if (ret)
1572*387f9dfdSAndroid Build Coastguard Worker return -1;
1573*387f9dfdSAndroid Build Coastguard Worker
1574*387f9dfdSAndroid Build Coastguard Worker btf_id = btf__find_by_name_kind(btf, struct_name, BTF_KIND_STRUCT);
1575*387f9dfdSAndroid Build Coastguard Worker if (btf_id < 0) {
1576*387f9dfdSAndroid Build Coastguard Worker ret = -1;
1577*387f9dfdSAndroid Build Coastguard Worker goto cleanup;
1578*387f9dfdSAndroid Build Coastguard Worker }
1579*387f9dfdSAndroid Build Coastguard Worker
1580*387f9dfdSAndroid Build Coastguard Worker btf_type = btf__type_by_id(btf, btf_id);
1581*387f9dfdSAndroid Build Coastguard Worker ret = find_member_by_name(btf, btf_type, field_name);
1582*387f9dfdSAndroid Build Coastguard Worker
1583*387f9dfdSAndroid Build Coastguard Worker cleanup:
1584*387f9dfdSAndroid Build Coastguard Worker btf__free(btf);
1585*387f9dfdSAndroid Build Coastguard Worker return ret;
1586*387f9dfdSAndroid Build Coastguard Worker }
1587*387f9dfdSAndroid Build Coastguard Worker #endif
1588*387f9dfdSAndroid Build Coastguard Worker
bpf_attach_kfunc(int prog_fd)1589*387f9dfdSAndroid Build Coastguard Worker int bpf_attach_kfunc(int prog_fd)
1590*387f9dfdSAndroid Build Coastguard Worker {
1591*387f9dfdSAndroid Build Coastguard Worker int ret;
1592*387f9dfdSAndroid Build Coastguard Worker
1593*387f9dfdSAndroid Build Coastguard Worker ret = bpf_raw_tracepoint_open(NULL, prog_fd);
1594*387f9dfdSAndroid Build Coastguard Worker if (ret < 0)
1595*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf_attach_raw_tracepoint (kfunc): %s\n", strerror(errno));
1596*387f9dfdSAndroid Build Coastguard Worker return ret;
1597*387f9dfdSAndroid Build Coastguard Worker }
1598*387f9dfdSAndroid Build Coastguard Worker
bpf_attach_lsm(int prog_fd)1599*387f9dfdSAndroid Build Coastguard Worker int bpf_attach_lsm(int prog_fd)
1600*387f9dfdSAndroid Build Coastguard Worker {
1601*387f9dfdSAndroid Build Coastguard Worker int ret;
1602*387f9dfdSAndroid Build Coastguard Worker
1603*387f9dfdSAndroid Build Coastguard Worker ret = bpf_raw_tracepoint_open(NULL, prog_fd);
1604*387f9dfdSAndroid Build Coastguard Worker if (ret < 0)
1605*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf_attach_raw_tracepoint (lsm): %s\n", strerror(errno));
1606*387f9dfdSAndroid Build Coastguard Worker return ret;
1607*387f9dfdSAndroid Build Coastguard Worker }
1608*387f9dfdSAndroid Build Coastguard Worker
bpf_open_perf_buffer(perf_reader_raw_cb raw_cb,perf_reader_lost_cb lost_cb,void * cb_cookie,int pid,int cpu,int page_cnt)1609*387f9dfdSAndroid Build Coastguard Worker void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb,
1610*387f9dfdSAndroid Build Coastguard Worker perf_reader_lost_cb lost_cb, void *cb_cookie,
1611*387f9dfdSAndroid Build Coastguard Worker int pid, int cpu, int page_cnt)
1612*387f9dfdSAndroid Build Coastguard Worker {
1613*387f9dfdSAndroid Build Coastguard Worker struct bcc_perf_buffer_opts opts = {
1614*387f9dfdSAndroid Build Coastguard Worker .pid = pid,
1615*387f9dfdSAndroid Build Coastguard Worker .cpu = cpu,
1616*387f9dfdSAndroid Build Coastguard Worker .wakeup_events = 1,
1617*387f9dfdSAndroid Build Coastguard Worker };
1618*387f9dfdSAndroid Build Coastguard Worker
1619*387f9dfdSAndroid Build Coastguard Worker return bpf_open_perf_buffer_opts(raw_cb, lost_cb, cb_cookie, page_cnt, &opts);
1620*387f9dfdSAndroid Build Coastguard Worker }
1621*387f9dfdSAndroid Build Coastguard Worker
bpf_open_perf_buffer_opts(perf_reader_raw_cb raw_cb,perf_reader_lost_cb lost_cb,void * cb_cookie,int page_cnt,struct bcc_perf_buffer_opts * opts)1622*387f9dfdSAndroid Build Coastguard Worker void * bpf_open_perf_buffer_opts(perf_reader_raw_cb raw_cb,
1623*387f9dfdSAndroid Build Coastguard Worker perf_reader_lost_cb lost_cb, void *cb_cookie,
1624*387f9dfdSAndroid Build Coastguard Worker int page_cnt, struct bcc_perf_buffer_opts *opts)
1625*387f9dfdSAndroid Build Coastguard Worker {
1626*387f9dfdSAndroid Build Coastguard Worker int pfd, pid = opts->pid, cpu = opts->cpu;
1627*387f9dfdSAndroid Build Coastguard Worker struct perf_event_attr attr = {};
1628*387f9dfdSAndroid Build Coastguard Worker struct perf_reader *reader = NULL;
1629*387f9dfdSAndroid Build Coastguard Worker
1630*387f9dfdSAndroid Build Coastguard Worker reader = perf_reader_new(raw_cb, lost_cb, cb_cookie, page_cnt);
1631*387f9dfdSAndroid Build Coastguard Worker if (!reader)
1632*387f9dfdSAndroid Build Coastguard Worker goto error;
1633*387f9dfdSAndroid Build Coastguard Worker
1634*387f9dfdSAndroid Build Coastguard Worker attr.config = 10;//PERF_COUNT_SW_BPF_OUTPUT;
1635*387f9dfdSAndroid Build Coastguard Worker attr.type = PERF_TYPE_SOFTWARE;
1636*387f9dfdSAndroid Build Coastguard Worker attr.sample_type = PERF_SAMPLE_RAW;
1637*387f9dfdSAndroid Build Coastguard Worker attr.sample_period = 1;
1638*387f9dfdSAndroid Build Coastguard Worker attr.wakeup_events = opts->wakeup_events;
1639*387f9dfdSAndroid Build Coastguard Worker pfd = syscall(__NR_perf_event_open, &attr, pid, cpu, -1, PERF_FLAG_FD_CLOEXEC);
1640*387f9dfdSAndroid Build Coastguard Worker if (pfd < 0) {
1641*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "perf_event_open: %s\n", strerror(errno));
1642*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, " (check your kernel for PERF_COUNT_SW_BPF_OUTPUT support, 4.4 or newer)\n");
1643*387f9dfdSAndroid Build Coastguard Worker goto error;
1644*387f9dfdSAndroid Build Coastguard Worker }
1645*387f9dfdSAndroid Build Coastguard Worker perf_reader_set_fd(reader, pfd);
1646*387f9dfdSAndroid Build Coastguard Worker
1647*387f9dfdSAndroid Build Coastguard Worker if (perf_reader_mmap(reader) < 0)
1648*387f9dfdSAndroid Build Coastguard Worker goto error;
1649*387f9dfdSAndroid Build Coastguard Worker
1650*387f9dfdSAndroid Build Coastguard Worker if (ioctl(pfd, PERF_EVENT_IOC_ENABLE, 0) < 0) {
1651*387f9dfdSAndroid Build Coastguard Worker perror("ioctl(PERF_EVENT_IOC_ENABLE)");
1652*387f9dfdSAndroid Build Coastguard Worker goto error;
1653*387f9dfdSAndroid Build Coastguard Worker }
1654*387f9dfdSAndroid Build Coastguard Worker
1655*387f9dfdSAndroid Build Coastguard Worker return reader;
1656*387f9dfdSAndroid Build Coastguard Worker
1657*387f9dfdSAndroid Build Coastguard Worker error:
1658*387f9dfdSAndroid Build Coastguard Worker if (reader)
1659*387f9dfdSAndroid Build Coastguard Worker perf_reader_free(reader);
1660*387f9dfdSAndroid Build Coastguard Worker
1661*387f9dfdSAndroid Build Coastguard Worker return NULL;
1662*387f9dfdSAndroid Build Coastguard Worker }
1663*387f9dfdSAndroid Build Coastguard Worker
invalid_perf_config(uint32_t type,uint64_t config)1664*387f9dfdSAndroid Build Coastguard Worker static int invalid_perf_config(uint32_t type, uint64_t config) {
1665*387f9dfdSAndroid Build Coastguard Worker switch (type) {
1666*387f9dfdSAndroid Build Coastguard Worker case PERF_TYPE_HARDWARE:
1667*387f9dfdSAndroid Build Coastguard Worker if (config >= PERF_COUNT_HW_MAX) {
1668*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "HARDWARE perf event config out of range\n");
1669*387f9dfdSAndroid Build Coastguard Worker goto is_invalid;
1670*387f9dfdSAndroid Build Coastguard Worker }
1671*387f9dfdSAndroid Build Coastguard Worker return 0;
1672*387f9dfdSAndroid Build Coastguard Worker case PERF_TYPE_SOFTWARE:
1673*387f9dfdSAndroid Build Coastguard Worker if (config >= PERF_COUNT_SW_MAX) {
1674*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "SOFTWARE perf event config out of range\n");
1675*387f9dfdSAndroid Build Coastguard Worker goto is_invalid;
1676*387f9dfdSAndroid Build Coastguard Worker } else if (config == 10 /* PERF_COUNT_SW_BPF_OUTPUT */) {
1677*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "Unable to open or attach perf event for BPF_OUTPUT\n");
1678*387f9dfdSAndroid Build Coastguard Worker goto is_invalid;
1679*387f9dfdSAndroid Build Coastguard Worker }
1680*387f9dfdSAndroid Build Coastguard Worker return 0;
1681*387f9dfdSAndroid Build Coastguard Worker case PERF_TYPE_HW_CACHE:
1682*387f9dfdSAndroid Build Coastguard Worker if (((config >> 16) >= PERF_COUNT_HW_CACHE_RESULT_MAX) ||
1683*387f9dfdSAndroid Build Coastguard Worker (((config >> 8) & 0xff) >= PERF_COUNT_HW_CACHE_OP_MAX) ||
1684*387f9dfdSAndroid Build Coastguard Worker ((config & 0xff) >= PERF_COUNT_HW_CACHE_MAX)) {
1685*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "HW_CACHE perf event config out of range\n");
1686*387f9dfdSAndroid Build Coastguard Worker goto is_invalid;
1687*387f9dfdSAndroid Build Coastguard Worker }
1688*387f9dfdSAndroid Build Coastguard Worker return 0;
1689*387f9dfdSAndroid Build Coastguard Worker case PERF_TYPE_TRACEPOINT:
1690*387f9dfdSAndroid Build Coastguard Worker case PERF_TYPE_BREAKPOINT:
1691*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr,
1692*387f9dfdSAndroid Build Coastguard Worker "Unable to open or attach TRACEPOINT or BREAKPOINT events\n");
1693*387f9dfdSAndroid Build Coastguard Worker goto is_invalid;
1694*387f9dfdSAndroid Build Coastguard Worker default:
1695*387f9dfdSAndroid Build Coastguard Worker return 0;
1696*387f9dfdSAndroid Build Coastguard Worker }
1697*387f9dfdSAndroid Build Coastguard Worker is_invalid:
1698*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "Invalid perf event type %" PRIu32 " config %" PRIu64 "\n",
1699*387f9dfdSAndroid Build Coastguard Worker type, config);
1700*387f9dfdSAndroid Build Coastguard Worker return 1;
1701*387f9dfdSAndroid Build Coastguard Worker }
1702*387f9dfdSAndroid Build Coastguard Worker
bpf_open_perf_event(uint32_t type,uint64_t config,int pid,int cpu)1703*387f9dfdSAndroid Build Coastguard Worker int bpf_open_perf_event(uint32_t type, uint64_t config, int pid, int cpu) {
1704*387f9dfdSAndroid Build Coastguard Worker int fd;
1705*387f9dfdSAndroid Build Coastguard Worker struct perf_event_attr attr = {};
1706*387f9dfdSAndroid Build Coastguard Worker
1707*387f9dfdSAndroid Build Coastguard Worker if (invalid_perf_config(type, config)) {
1708*387f9dfdSAndroid Build Coastguard Worker return -1;
1709*387f9dfdSAndroid Build Coastguard Worker }
1710*387f9dfdSAndroid Build Coastguard Worker
1711*387f9dfdSAndroid Build Coastguard Worker attr.sample_period = LONG_MAX;
1712*387f9dfdSAndroid Build Coastguard Worker attr.type = type;
1713*387f9dfdSAndroid Build Coastguard Worker attr.config = config;
1714*387f9dfdSAndroid Build Coastguard Worker
1715*387f9dfdSAndroid Build Coastguard Worker fd = syscall(__NR_perf_event_open, &attr, pid, cpu, -1, PERF_FLAG_FD_CLOEXEC);
1716*387f9dfdSAndroid Build Coastguard Worker if (fd < 0) {
1717*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "perf_event_open: %s\n", strerror(errno));
1718*387f9dfdSAndroid Build Coastguard Worker return -1;
1719*387f9dfdSAndroid Build Coastguard Worker }
1720*387f9dfdSAndroid Build Coastguard Worker
1721*387f9dfdSAndroid Build Coastguard Worker if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0) < 0) {
1722*387f9dfdSAndroid Build Coastguard Worker perror("ioctl(PERF_EVENT_IOC_ENABLE)");
1723*387f9dfdSAndroid Build Coastguard Worker close(fd);
1724*387f9dfdSAndroid Build Coastguard Worker return -1;
1725*387f9dfdSAndroid Build Coastguard Worker }
1726*387f9dfdSAndroid Build Coastguard Worker
1727*387f9dfdSAndroid Build Coastguard Worker return fd;
1728*387f9dfdSAndroid Build Coastguard Worker }
1729*387f9dfdSAndroid Build Coastguard Worker
bpf_attach_xdp(const char * dev_name,int progfd,uint32_t flags)1730*387f9dfdSAndroid Build Coastguard Worker int bpf_attach_xdp(const char *dev_name, int progfd, uint32_t flags) {
1731*387f9dfdSAndroid Build Coastguard Worker int ifindex = if_nametoindex(dev_name);
1732*387f9dfdSAndroid Build Coastguard Worker char err_buf[256];
1733*387f9dfdSAndroid Build Coastguard Worker int ret = -1;
1734*387f9dfdSAndroid Build Coastguard Worker
1735*387f9dfdSAndroid Build Coastguard Worker if (ifindex == 0) {
1736*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf: Resolving device name to index: %s\n", strerror(errno));
1737*387f9dfdSAndroid Build Coastguard Worker return -1;
1738*387f9dfdSAndroid Build Coastguard Worker }
1739*387f9dfdSAndroid Build Coastguard Worker
1740*387f9dfdSAndroid Build Coastguard Worker ret = bpf_xdp_attach(ifindex, progfd, flags, NULL);
1741*387f9dfdSAndroid Build Coastguard Worker if (ret) {
1742*387f9dfdSAndroid Build Coastguard Worker libbpf_strerror(ret, err_buf, sizeof(err_buf));
1743*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "bpf: Attaching prog to %s: %s\n", dev_name, err_buf);
1744*387f9dfdSAndroid Build Coastguard Worker return -1;
1745*387f9dfdSAndroid Build Coastguard Worker }
1746*387f9dfdSAndroid Build Coastguard Worker
1747*387f9dfdSAndroid Build Coastguard Worker return 0;
1748*387f9dfdSAndroid Build Coastguard Worker }
1749*387f9dfdSAndroid Build Coastguard Worker
bpf_attach_perf_event_raw(int progfd,void * perf_event_attr,pid_t pid,int cpu,int group_fd,unsigned long extra_flags)1750*387f9dfdSAndroid Build Coastguard Worker int bpf_attach_perf_event_raw(int progfd, void *perf_event_attr, pid_t pid,
1751*387f9dfdSAndroid Build Coastguard Worker int cpu, int group_fd, unsigned long extra_flags) {
1752*387f9dfdSAndroid Build Coastguard Worker int fd = syscall(__NR_perf_event_open, perf_event_attr, pid, cpu, group_fd,
1753*387f9dfdSAndroid Build Coastguard Worker PERF_FLAG_FD_CLOEXEC | extra_flags);
1754*387f9dfdSAndroid Build Coastguard Worker if (fd < 0) {
1755*387f9dfdSAndroid Build Coastguard Worker perror("perf_event_open failed");
1756*387f9dfdSAndroid Build Coastguard Worker return -1;
1757*387f9dfdSAndroid Build Coastguard Worker }
1758*387f9dfdSAndroid Build Coastguard Worker if (ioctl(fd, PERF_EVENT_IOC_SET_BPF, progfd) != 0) {
1759*387f9dfdSAndroid Build Coastguard Worker perror("ioctl(PERF_EVENT_IOC_SET_BPF) failed");
1760*387f9dfdSAndroid Build Coastguard Worker close(fd);
1761*387f9dfdSAndroid Build Coastguard Worker return -1;
1762*387f9dfdSAndroid Build Coastguard Worker }
1763*387f9dfdSAndroid Build Coastguard Worker if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0) != 0) {
1764*387f9dfdSAndroid Build Coastguard Worker perror("ioctl(PERF_EVENT_IOC_ENABLE) failed");
1765*387f9dfdSAndroid Build Coastguard Worker close(fd);
1766*387f9dfdSAndroid Build Coastguard Worker return -1;
1767*387f9dfdSAndroid Build Coastguard Worker }
1768*387f9dfdSAndroid Build Coastguard Worker
1769*387f9dfdSAndroid Build Coastguard Worker return fd;
1770*387f9dfdSAndroid Build Coastguard Worker }
1771*387f9dfdSAndroid Build Coastguard Worker
bpf_attach_perf_event(int progfd,uint32_t ev_type,uint32_t ev_config,uint64_t sample_period,uint64_t sample_freq,pid_t pid,int cpu,int group_fd)1772*387f9dfdSAndroid Build Coastguard Worker int bpf_attach_perf_event(int progfd, uint32_t ev_type, uint32_t ev_config,
1773*387f9dfdSAndroid Build Coastguard Worker uint64_t sample_period, uint64_t sample_freq,
1774*387f9dfdSAndroid Build Coastguard Worker pid_t pid, int cpu, int group_fd) {
1775*387f9dfdSAndroid Build Coastguard Worker if (invalid_perf_config(ev_type, ev_config)) {
1776*387f9dfdSAndroid Build Coastguard Worker return -1;
1777*387f9dfdSAndroid Build Coastguard Worker }
1778*387f9dfdSAndroid Build Coastguard Worker if (!((sample_period > 0) ^ (sample_freq > 0))) {
1779*387f9dfdSAndroid Build Coastguard Worker fprintf(
1780*387f9dfdSAndroid Build Coastguard Worker stderr, "Exactly one of sample_period / sample_freq should be set\n"
1781*387f9dfdSAndroid Build Coastguard Worker );
1782*387f9dfdSAndroid Build Coastguard Worker return -1;
1783*387f9dfdSAndroid Build Coastguard Worker }
1784*387f9dfdSAndroid Build Coastguard Worker
1785*387f9dfdSAndroid Build Coastguard Worker struct perf_event_attr attr = {};
1786*387f9dfdSAndroid Build Coastguard Worker attr.type = ev_type;
1787*387f9dfdSAndroid Build Coastguard Worker attr.config = ev_config;
1788*387f9dfdSAndroid Build Coastguard Worker if (pid > 0)
1789*387f9dfdSAndroid Build Coastguard Worker attr.inherit = 1;
1790*387f9dfdSAndroid Build Coastguard Worker if (sample_freq > 0) {
1791*387f9dfdSAndroid Build Coastguard Worker attr.freq = 1;
1792*387f9dfdSAndroid Build Coastguard Worker attr.sample_freq = sample_freq;
1793*387f9dfdSAndroid Build Coastguard Worker } else {
1794*387f9dfdSAndroid Build Coastguard Worker attr.sample_period = sample_period;
1795*387f9dfdSAndroid Build Coastguard Worker }
1796*387f9dfdSAndroid Build Coastguard Worker
1797*387f9dfdSAndroid Build Coastguard Worker return bpf_attach_perf_event_raw(progfd, &attr, pid, cpu, group_fd, 0);
1798*387f9dfdSAndroid Build Coastguard Worker }
1799*387f9dfdSAndroid Build Coastguard Worker
bpf_close_perf_event_fd(int fd)1800*387f9dfdSAndroid Build Coastguard Worker int bpf_close_perf_event_fd(int fd) {
1801*387f9dfdSAndroid Build Coastguard Worker int res, error = 0;
1802*387f9dfdSAndroid Build Coastguard Worker if (fd >= 0) {
1803*387f9dfdSAndroid Build Coastguard Worker res = ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
1804*387f9dfdSAndroid Build Coastguard Worker if (res != 0) {
1805*387f9dfdSAndroid Build Coastguard Worker perror("ioctl(PERF_EVENT_IOC_DISABLE) failed");
1806*387f9dfdSAndroid Build Coastguard Worker error = res;
1807*387f9dfdSAndroid Build Coastguard Worker }
1808*387f9dfdSAndroid Build Coastguard Worker res = close(fd);
1809*387f9dfdSAndroid Build Coastguard Worker if (res != 0) {
1810*387f9dfdSAndroid Build Coastguard Worker perror("close perf event FD failed");
1811*387f9dfdSAndroid Build Coastguard Worker error = (res && !error) ? res : error;
1812*387f9dfdSAndroid Build Coastguard Worker }
1813*387f9dfdSAndroid Build Coastguard Worker }
1814*387f9dfdSAndroid Build Coastguard Worker return error;
1815*387f9dfdSAndroid Build Coastguard Worker }
1816*387f9dfdSAndroid Build Coastguard Worker
1817*387f9dfdSAndroid Build Coastguard Worker /* Create a new ringbuf manager to manage ringbuf associated with
1818*387f9dfdSAndroid Build Coastguard Worker * map_fd, associating it with callback sample_cb. */
bpf_new_ringbuf(int map_fd,ring_buffer_sample_fn sample_cb,void * ctx)1819*387f9dfdSAndroid Build Coastguard Worker void * bpf_new_ringbuf(int map_fd, ring_buffer_sample_fn sample_cb, void *ctx) {
1820*387f9dfdSAndroid Build Coastguard Worker return ring_buffer__new(map_fd, sample_cb, ctx, NULL);
1821*387f9dfdSAndroid Build Coastguard Worker }
1822*387f9dfdSAndroid Build Coastguard Worker
1823*387f9dfdSAndroid Build Coastguard Worker /* Free the ringbuf manager rb and all ring buffers associated with it. */
bpf_free_ringbuf(struct ring_buffer * rb)1824*387f9dfdSAndroid Build Coastguard Worker void bpf_free_ringbuf(struct ring_buffer *rb) {
1825*387f9dfdSAndroid Build Coastguard Worker ring_buffer__free(rb);
1826*387f9dfdSAndroid Build Coastguard Worker }
1827*387f9dfdSAndroid Build Coastguard Worker
1828*387f9dfdSAndroid Build Coastguard Worker /* Add a new ring buffer associated with map_fd to the ring buffer manager rb,
1829*387f9dfdSAndroid Build Coastguard Worker * associating it with callback sample_cb. */
bpf_add_ringbuf(struct ring_buffer * rb,int map_fd,ring_buffer_sample_fn sample_cb,void * ctx)1830*387f9dfdSAndroid Build Coastguard Worker int bpf_add_ringbuf(struct ring_buffer *rb, int map_fd,
1831*387f9dfdSAndroid Build Coastguard Worker ring_buffer_sample_fn sample_cb, void *ctx) {
1832*387f9dfdSAndroid Build Coastguard Worker return ring_buffer__add(rb, map_fd, sample_cb, ctx);
1833*387f9dfdSAndroid Build Coastguard Worker }
1834*387f9dfdSAndroid Build Coastguard Worker
1835*387f9dfdSAndroid Build Coastguard Worker /* Poll for available data and consume, if data is available. Returns number
1836*387f9dfdSAndroid Build Coastguard Worker * of records consumed, or a negative number if any callbacks returned an
1837*387f9dfdSAndroid Build Coastguard Worker * error. */
bpf_poll_ringbuf(struct ring_buffer * rb,int timeout_ms)1838*387f9dfdSAndroid Build Coastguard Worker int bpf_poll_ringbuf(struct ring_buffer *rb, int timeout_ms) {
1839*387f9dfdSAndroid Build Coastguard Worker return ring_buffer__poll(rb, timeout_ms);
1840*387f9dfdSAndroid Build Coastguard Worker }
1841*387f9dfdSAndroid Build Coastguard Worker
1842*387f9dfdSAndroid Build Coastguard Worker /* Consume available data _without_ polling. Good for use cases where low
1843*387f9dfdSAndroid Build Coastguard Worker * latency is desired over performance impact. Returns number of records
1844*387f9dfdSAndroid Build Coastguard Worker * consumed, or a negative number if any callbacks returned an error. */
bpf_consume_ringbuf(struct ring_buffer * rb)1845*387f9dfdSAndroid Build Coastguard Worker int bpf_consume_ringbuf(struct ring_buffer *rb) {
1846*387f9dfdSAndroid Build Coastguard Worker return ring_buffer__consume(rb);
1847*387f9dfdSAndroid Build Coastguard Worker }
1848*387f9dfdSAndroid Build Coastguard Worker
bcc_iter_attach(int prog_fd,union bpf_iter_link_info * link_info,uint32_t link_info_len)1849*387f9dfdSAndroid Build Coastguard Worker int bcc_iter_attach(int prog_fd, union bpf_iter_link_info *link_info,
1850*387f9dfdSAndroid Build Coastguard Worker uint32_t link_info_len)
1851*387f9dfdSAndroid Build Coastguard Worker {
1852*387f9dfdSAndroid Build Coastguard Worker DECLARE_LIBBPF_OPTS(bpf_link_create_opts, link_create_opts);
1853*387f9dfdSAndroid Build Coastguard Worker
1854*387f9dfdSAndroid Build Coastguard Worker link_create_opts.iter_info = link_info;
1855*387f9dfdSAndroid Build Coastguard Worker link_create_opts.iter_info_len = link_info_len;
1856*387f9dfdSAndroid Build Coastguard Worker return bpf_link_create(prog_fd, 0, BPF_TRACE_ITER, &link_create_opts);
1857*387f9dfdSAndroid Build Coastguard Worker }
1858*387f9dfdSAndroid Build Coastguard Worker
bcc_iter_create(int link_fd)1859*387f9dfdSAndroid Build Coastguard Worker int bcc_iter_create(int link_fd)
1860*387f9dfdSAndroid Build Coastguard Worker {
1861*387f9dfdSAndroid Build Coastguard Worker return bpf_iter_create(link_fd);
1862*387f9dfdSAndroid Build Coastguard Worker }
1863*387f9dfdSAndroid Build Coastguard Worker
bcc_make_parent_dir(const char * path)1864*387f9dfdSAndroid Build Coastguard Worker int bcc_make_parent_dir(const char *path) {
1865*387f9dfdSAndroid Build Coastguard Worker int err = 0;
1866*387f9dfdSAndroid Build Coastguard Worker char *dname, *dir;
1867*387f9dfdSAndroid Build Coastguard Worker
1868*387f9dfdSAndroid Build Coastguard Worker dname = strdup(path);
1869*387f9dfdSAndroid Build Coastguard Worker if (dname == NULL)
1870*387f9dfdSAndroid Build Coastguard Worker return -ENOMEM;
1871*387f9dfdSAndroid Build Coastguard Worker
1872*387f9dfdSAndroid Build Coastguard Worker dir = dirname(dname);
1873*387f9dfdSAndroid Build Coastguard Worker if (mkdir(dir, 0700) && errno != EEXIST)
1874*387f9dfdSAndroid Build Coastguard Worker err = -errno;
1875*387f9dfdSAndroid Build Coastguard Worker
1876*387f9dfdSAndroid Build Coastguard Worker free(dname);
1877*387f9dfdSAndroid Build Coastguard Worker if (err)
1878*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "failed to mkdir %s: %s\n", path, strerror(-err));
1879*387f9dfdSAndroid Build Coastguard Worker
1880*387f9dfdSAndroid Build Coastguard Worker return err;
1881*387f9dfdSAndroid Build Coastguard Worker }
1882*387f9dfdSAndroid Build Coastguard Worker
bcc_check_bpffs_path(const char * path)1883*387f9dfdSAndroid Build Coastguard Worker int bcc_check_bpffs_path(const char *path) {
1884*387f9dfdSAndroid Build Coastguard Worker struct statfs st_fs;
1885*387f9dfdSAndroid Build Coastguard Worker char *dname, *dir;
1886*387f9dfdSAndroid Build Coastguard Worker int err = 0;
1887*387f9dfdSAndroid Build Coastguard Worker
1888*387f9dfdSAndroid Build Coastguard Worker if (path == NULL)
1889*387f9dfdSAndroid Build Coastguard Worker return -EINVAL;
1890*387f9dfdSAndroid Build Coastguard Worker
1891*387f9dfdSAndroid Build Coastguard Worker dname = strdup(path);
1892*387f9dfdSAndroid Build Coastguard Worker if (dname == NULL)
1893*387f9dfdSAndroid Build Coastguard Worker return -ENOMEM;
1894*387f9dfdSAndroid Build Coastguard Worker
1895*387f9dfdSAndroid Build Coastguard Worker dir = dirname(dname);
1896*387f9dfdSAndroid Build Coastguard Worker if (statfs(dir, &st_fs)) {
1897*387f9dfdSAndroid Build Coastguard Worker err = -errno;
1898*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "failed to statfs %s: %s\n", path, strerror(-err));
1899*387f9dfdSAndroid Build Coastguard Worker }
1900*387f9dfdSAndroid Build Coastguard Worker
1901*387f9dfdSAndroid Build Coastguard Worker free(dname);
1902*387f9dfdSAndroid Build Coastguard Worker if (!err && st_fs.f_type != BPF_FS_MAGIC) {
1903*387f9dfdSAndroid Build Coastguard Worker err = -EINVAL;
1904*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "specified path %s is not on BPF FS\n", path);
1905*387f9dfdSAndroid Build Coastguard Worker }
1906*387f9dfdSAndroid Build Coastguard Worker
1907*387f9dfdSAndroid Build Coastguard Worker return err;
1908*387f9dfdSAndroid Build Coastguard Worker }
1909