]> Git Repo - linux.git/blob - tools/bpf/bpftool/pids.c
fs/binfmt_elf: use PT_LOAD p_align values for static PIE
[linux.git] / tools / bpf / bpftool / pids.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2020 Facebook */
3 #include <errno.h>
4 #include <stdbool.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9
10 #include <bpf/bpf.h>
11 #include <bpf/hashmap.h>
12
13 #include "main.h"
14 #include "skeleton/pid_iter.h"
15
16 #ifdef BPFTOOL_WITHOUT_SKELETONS
17
18 int build_obj_refs_table(struct hashmap **map, enum bpf_obj_type type)
19 {
20         return -ENOTSUP;
21 }
22 void delete_obj_refs_table(struct hashmap *map) {}
23 void emit_obj_refs_plain(struct hashmap *map, __u32 id, const char *prefix) {}
24 void emit_obj_refs_json(struct hashmap *map, __u32 id, json_writer_t *json_writer) {}
25
26 #else /* BPFTOOL_WITHOUT_SKELETONS */
27
28 #include "pid_iter.skel.h"
29
30 static void add_ref(struct hashmap *map, struct pid_iter_entry *e)
31 {
32         struct hashmap_entry *entry;
33         struct obj_refs *refs;
34         struct obj_ref *ref;
35         int err, i;
36         void *tmp;
37
38         hashmap__for_each_key_entry(map, entry, u32_as_hash_field(e->id)) {
39                 refs = entry->value;
40
41                 for (i = 0; i < refs->ref_cnt; i++) {
42                         if (refs->refs[i].pid == e->pid)
43                                 return;
44                 }
45
46                 tmp = realloc(refs->refs, (refs->ref_cnt + 1) * sizeof(*ref));
47                 if (!tmp) {
48                         p_err("failed to re-alloc memory for ID %u, PID %d, COMM %s...",
49                               e->id, e->pid, e->comm);
50                         return;
51                 }
52                 refs->refs = tmp;
53                 ref = &refs->refs[refs->ref_cnt];
54                 ref->pid = e->pid;
55                 memcpy(ref->comm, e->comm, sizeof(ref->comm));
56                 refs->ref_cnt++;
57
58                 return;
59         }
60
61         /* new ref */
62         refs = calloc(1, sizeof(*refs));
63         if (!refs) {
64                 p_err("failed to alloc memory for ID %u, PID %d, COMM %s...",
65                       e->id, e->pid, e->comm);
66                 return;
67         }
68
69         refs->refs = malloc(sizeof(*refs->refs));
70         if (!refs->refs) {
71                 free(refs);
72                 p_err("failed to alloc memory for ID %u, PID %d, COMM %s...",
73                       e->id, e->pid, e->comm);
74                 return;
75         }
76         ref = &refs->refs[0];
77         ref->pid = e->pid;
78         memcpy(ref->comm, e->comm, sizeof(ref->comm));
79         refs->ref_cnt = 1;
80
81         err = hashmap__append(map, u32_as_hash_field(e->id), refs);
82         if (err)
83                 p_err("failed to append entry to hashmap for ID %u: %s",
84                       e->id, strerror(errno));
85 }
86
87 static int __printf(2, 0)
88 libbpf_print_none(__maybe_unused enum libbpf_print_level level,
89                   __maybe_unused const char *format,
90                   __maybe_unused va_list args)
91 {
92         return 0;
93 }
94
95 int build_obj_refs_table(struct hashmap **map, enum bpf_obj_type type)
96 {
97         struct pid_iter_entry *e;
98         char buf[4096 / sizeof(*e) * sizeof(*e)];
99         struct pid_iter_bpf *skel;
100         int err, ret, fd = -1, i;
101         libbpf_print_fn_t default_print;
102
103         *map = hashmap__new(hash_fn_for_key_as_id, equal_fn_for_key_as_id, NULL);
104         if (!*map) {
105                 p_err("failed to create hashmap for PID references");
106                 return -1;
107         }
108         set_max_rlimit();
109
110         skel = pid_iter_bpf__open();
111         if (!skel) {
112                 p_err("failed to open PID iterator skeleton");
113                 return -1;
114         }
115
116         skel->rodata->obj_type = type;
117
118         /* we don't want output polluted with libbpf errors if bpf_iter is not
119          * supported
120          */
121         default_print = libbpf_set_print(libbpf_print_none);
122         err = pid_iter_bpf__load(skel);
123         libbpf_set_print(default_print);
124         if (err) {
125                 /* too bad, kernel doesn't support BPF iterators yet */
126                 err = 0;
127                 goto out;
128         }
129         err = pid_iter_bpf__attach(skel);
130         if (err) {
131                 /* if we loaded above successfully, attach has to succeed */
132                 p_err("failed to attach PID iterator: %d", err);
133                 goto out;
134         }
135
136         fd = bpf_iter_create(bpf_link__fd(skel->links.iter));
137         if (fd < 0) {
138                 err = -errno;
139                 p_err("failed to create PID iterator session: %d", err);
140                 goto out;
141         }
142
143         while (true) {
144                 ret = read(fd, buf, sizeof(buf));
145                 if (ret < 0) {
146                         if (errno == EAGAIN)
147                                 continue;
148                         err = -errno;
149                         p_err("failed to read PID iterator output: %d", err);
150                         goto out;
151                 }
152                 if (ret == 0)
153                         break;
154                 if (ret % sizeof(*e)) {
155                         err = -EINVAL;
156                         p_err("invalid PID iterator output format");
157                         goto out;
158                 }
159                 ret /= sizeof(*e);
160
161                 e = (void *)buf;
162                 for (i = 0; i < ret; i++, e++) {
163                         add_ref(*map, e);
164                 }
165         }
166         err = 0;
167 out:
168         if (fd >= 0)
169                 close(fd);
170         pid_iter_bpf__destroy(skel);
171         return err;
172 }
173
174 void delete_obj_refs_table(struct hashmap *map)
175 {
176         struct hashmap_entry *entry;
177         size_t bkt;
178
179         if (!map)
180                 return;
181
182         hashmap__for_each_entry(map, entry, bkt) {
183                 struct obj_refs *refs = entry->value;
184
185                 free(refs->refs);
186                 free(refs);
187         }
188
189         hashmap__free(map);
190 }
191
192 void emit_obj_refs_json(struct hashmap *map, __u32 id,
193                         json_writer_t *json_writer)
194 {
195         struct hashmap_entry *entry;
196
197         if (hashmap__empty(map))
198                 return;
199
200         hashmap__for_each_key_entry(map, entry, u32_as_hash_field(id)) {
201                 struct obj_refs *refs = entry->value;
202                 int i;
203
204                 if (refs->ref_cnt == 0)
205                         break;
206
207                 jsonw_name(json_writer, "pids");
208                 jsonw_start_array(json_writer);
209                 for (i = 0; i < refs->ref_cnt; i++) {
210                         struct obj_ref *ref = &refs->refs[i];
211
212                         jsonw_start_object(json_writer);
213                         jsonw_int_field(json_writer, "pid", ref->pid);
214                         jsonw_string_field(json_writer, "comm", ref->comm);
215                         jsonw_end_object(json_writer);
216                 }
217                 jsonw_end_array(json_writer);
218                 break;
219         }
220 }
221
222 void emit_obj_refs_plain(struct hashmap *map, __u32 id, const char *prefix)
223 {
224         struct hashmap_entry *entry;
225
226         if (hashmap__empty(map))
227                 return;
228
229         hashmap__for_each_key_entry(map, entry, u32_as_hash_field(id)) {
230                 struct obj_refs *refs = entry->value;
231                 int i;
232
233                 if (refs->ref_cnt == 0)
234                         break;
235
236                 printf("%s", prefix);
237                 for (i = 0; i < refs->ref_cnt; i++) {
238                         struct obj_ref *ref = &refs->refs[i];
239
240                         printf("%s%s(%d)", i == 0 ? "" : ", ", ref->comm, ref->pid);
241                 }
242                 break;
243         }
244 }
245
246
247 #endif
This page took 0.046602 seconds and 4 git commands to generate.