1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2020 Facebook */
12 #include <bpf/hashmap.h>
15 #include "skeleton/pid_iter.h"
17 #ifdef BPFTOOL_WITHOUT_SKELETONS
19 int build_obj_refs_table(struct hashmap
**map
, enum bpf_obj_type type
)
23 void delete_obj_refs_table(struct hashmap
*map
) {}
24 void emit_obj_refs_plain(struct hashmap
*map
, __u32 id
, const char *prefix
) {}
25 void emit_obj_refs_json(struct hashmap
*map
, __u32 id
, json_writer_t
*json_writer
) {}
27 #else /* BPFTOOL_WITHOUT_SKELETONS */
29 #include "pid_iter.skel.h"
31 static void add_ref(struct hashmap
*map
, struct pid_iter_entry
*e
)
33 struct hashmap_entry
*entry
;
34 struct obj_refs
*refs
;
39 hashmap__for_each_key_entry(map
, entry
, e
->id
) {
42 for (i
= 0; i
< refs
->ref_cnt
; i
++) {
43 if (refs
->refs
[i
].pid
== e
->pid
)
47 tmp
= realloc(refs
->refs
, (refs
->ref_cnt
+ 1) * sizeof(*ref
));
49 p_err("failed to re-alloc memory for ID %u, PID %d, COMM %s...",
50 e
->id
, e
->pid
, e
->comm
);
54 ref
= &refs
->refs
[refs
->ref_cnt
];
56 memcpy(ref
->comm
, e
->comm
, sizeof(ref
->comm
));
57 ref
->comm
[sizeof(ref
->comm
) - 1] = '\0';
64 refs
= calloc(1, sizeof(*refs
));
66 p_err("failed to alloc memory for ID %u, PID %d, COMM %s...",
67 e
->id
, e
->pid
, e
->comm
);
71 refs
->refs
= malloc(sizeof(*refs
->refs
));
74 p_err("failed to alloc memory for ID %u, PID %d, COMM %s...",
75 e
->id
, e
->pid
, e
->comm
);
80 memcpy(ref
->comm
, e
->comm
, sizeof(ref
->comm
));
81 ref
->comm
[sizeof(ref
->comm
) - 1] = '\0';
83 refs
->has_bpf_cookie
= e
->has_bpf_cookie
;
84 refs
->bpf_cookie
= e
->bpf_cookie
;
86 err
= hashmap__append(map
, e
->id
, refs
);
88 p_err("failed to append entry to hashmap for ID %u: %s",
89 e
->id
, strerror(errno
));
92 static int __printf(2, 0)
93 libbpf_print_none(__maybe_unused
enum libbpf_print_level level
,
94 __maybe_unused
const char *format
,
95 __maybe_unused
va_list args
)
100 int build_obj_refs_table(struct hashmap
**map
, enum bpf_obj_type type
)
102 struct pid_iter_entry
*e
;
103 char buf
[4096 / sizeof(*e
) * sizeof(*e
)];
104 struct pid_iter_bpf
*skel
;
105 int err
, ret
, fd
= -1, i
;
107 *map
= hashmap__new(hash_fn_for_key_as_id
, equal_fn_for_key_as_id
, NULL
);
109 p_err("failed to create hashmap for PID references");
114 skel
= pid_iter_bpf__open();
116 p_err("failed to open PID iterator skeleton");
120 skel
->rodata
->obj_type
= type
;
122 if (!verifier_logs
) {
123 libbpf_print_fn_t default_print
;
125 /* Unless debug information is on, we don't want the output to
126 * be polluted with libbpf errors if bpf_iter is not supported.
128 default_print
= libbpf_set_print(libbpf_print_none
);
129 err
= pid_iter_bpf__load(skel
);
130 libbpf_set_print(default_print
);
132 err
= pid_iter_bpf__load(skel
);
135 /* too bad, kernel doesn't support BPF iterators yet */
139 err
= pid_iter_bpf__attach(skel
);
141 /* if we loaded above successfully, attach has to succeed */
142 p_err("failed to attach PID iterator: %d", err
);
146 fd
= bpf_iter_create(bpf_link__fd(skel
->links
.iter
));
149 p_err("failed to create PID iterator session: %d", err
);
154 ret
= read(fd
, buf
, sizeof(buf
));
159 p_err("failed to read PID iterator output: %d", err
);
164 if (ret
% sizeof(*e
)) {
166 p_err("invalid PID iterator output format");
172 for (i
= 0; i
< ret
; i
++, e
++) {
180 pid_iter_bpf__destroy(skel
);
184 void delete_obj_refs_table(struct hashmap
*map
)
186 struct hashmap_entry
*entry
;
192 hashmap__for_each_entry(map
, entry
, bkt
) {
193 struct obj_refs
*refs
= entry
->pvalue
;
202 void emit_obj_refs_json(struct hashmap
*map
, __u32 id
,
203 json_writer_t
*json_writer
)
205 struct hashmap_entry
*entry
;
207 if (hashmap__empty(map
))
210 hashmap__for_each_key_entry(map
, entry
, id
) {
211 struct obj_refs
*refs
= entry
->pvalue
;
214 if (refs
->ref_cnt
== 0)
217 if (refs
->has_bpf_cookie
)
218 jsonw_lluint_field(json_writer
, "bpf_cookie", refs
->bpf_cookie
);
220 jsonw_name(json_writer
, "pids");
221 jsonw_start_array(json_writer
);
222 for (i
= 0; i
< refs
->ref_cnt
; i
++) {
223 struct obj_ref
*ref
= &refs
->refs
[i
];
225 jsonw_start_object(json_writer
);
226 jsonw_int_field(json_writer
, "pid", ref
->pid
);
227 jsonw_string_field(json_writer
, "comm", ref
->comm
);
228 jsonw_end_object(json_writer
);
230 jsonw_end_array(json_writer
);
235 void emit_obj_refs_plain(struct hashmap
*map
, __u32 id
, const char *prefix
)
237 struct hashmap_entry
*entry
;
239 if (hashmap__empty(map
))
242 hashmap__for_each_key_entry(map
, entry
, id
) {
243 struct obj_refs
*refs
= entry
->pvalue
;
246 if (refs
->ref_cnt
== 0)
249 if (refs
->has_bpf_cookie
)
250 printf("\n\tbpf_cookie %llu", (unsigned long long) refs
->bpf_cookie
);
252 printf("%s", prefix
);
253 for (i
= 0; i
< refs
->ref_cnt
; i
++) {
254 struct obj_ref
*ref
= &refs
->refs
[i
];
256 printf("%s%s(%d)", i
== 0 ? "" : ", ", ref
->comm
, ref
->pid
);