aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib/bpf/libbpf.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lib/bpf/libbpf.c')
-rw-r--r--tools/lib/bpf/libbpf.c67
1 files changed, 41 insertions, 26 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 794dd5064ae8..2b57d7ea7836 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -20,6 +20,7 @@
20#include <inttypes.h> 20#include <inttypes.h>
21#include <string.h> 21#include <string.h>
22#include <unistd.h> 22#include <unistd.h>
23#include <endian.h>
23#include <fcntl.h> 24#include <fcntl.h>
24#include <errno.h> 25#include <errno.h>
25#include <asm/unistd.h> 26#include <asm/unistd.h>
@@ -181,7 +182,6 @@ struct bpf_program {
181 bpf_program_clear_priv_t clear_priv; 182 bpf_program_clear_priv_t clear_priv;
182 183
183 enum bpf_attach_type expected_attach_type; 184 enum bpf_attach_type expected_attach_type;
184 int btf_fd;
185 void *func_info; 185 void *func_info;
186 __u32 func_info_rec_size; 186 __u32 func_info_rec_size;
187 __u32 func_info_cnt; 187 __u32 func_info_cnt;
@@ -312,7 +312,6 @@ void bpf_program__unload(struct bpf_program *prog)
312 prog->instances.nr = -1; 312 prog->instances.nr = -1;
313 zfree(&prog->instances.fds); 313 zfree(&prog->instances.fds);
314 314
315 zclose(prog->btf_fd);
316 zfree(&prog->func_info); 315 zfree(&prog->func_info);
317 zfree(&prog->line_info); 316 zfree(&prog->line_info);
318} 317}
@@ -391,7 +390,6 @@ bpf_program__init(void *data, size_t size, char *section_name, int idx,
391 prog->instances.fds = NULL; 390 prog->instances.fds = NULL;
392 prog->instances.nr = -1; 391 prog->instances.nr = -1;
393 prog->type = BPF_PROG_TYPE_UNSPEC; 392 prog->type = BPF_PROG_TYPE_UNSPEC;
394 prog->btf_fd = -1;
395 393
396 return 0; 394 return 0;
397errout: 395errout:
@@ -612,10 +610,10 @@ errout:
612 610
613static int bpf_object__check_endianness(struct bpf_object *obj) 611static int bpf_object__check_endianness(struct bpf_object *obj)
614{ 612{
615#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 613#if __BYTE_ORDER == __LITTLE_ENDIAN
616 if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2LSB) 614 if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
617 return 0; 615 return 0;
618#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 616#elif __BYTE_ORDER == __BIG_ENDIAN
619 if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2MSB) 617 if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
620 return 0; 618 return 0;
621#else 619#else
@@ -1377,8 +1375,13 @@ static void bpf_object__sanitize_btf(struct bpf_object *obj)
1377 if (!has_datasec && kind == BTF_KIND_VAR) { 1375 if (!has_datasec && kind == BTF_KIND_VAR) {
1378 /* replace VAR with INT */ 1376 /* replace VAR with INT */
1379 t->info = BTF_INFO_ENC(BTF_KIND_INT, 0, 0); 1377 t->info = BTF_INFO_ENC(BTF_KIND_INT, 0, 0);
1380 t->size = sizeof(int); 1378 /*
1381 *(int *)(t+1) = BTF_INT_ENC(0, 0, 32); 1379 * using size = 1 is the safest choice, 4 will be too
1380 * big and cause kernel BTF validation failure if
1381 * original variable took less than 4 bytes
1382 */
1383 t->size = 1;
1384 *(int *)(t+1) = BTF_INT_ENC(0, 0, 8);
1382 } else if (!has_datasec && kind == BTF_KIND_DATASEC) { 1385 } else if (!has_datasec && kind == BTF_KIND_DATASEC) {
1383 /* replace DATASEC with STRUCT */ 1386 /* replace DATASEC with STRUCT */
1384 struct btf_var_secinfo *v = (void *)(t + 1); 1387 struct btf_var_secinfo *v = (void *)(t + 1);
@@ -1500,6 +1503,12 @@ static int bpf_object__sanitize_and_load_btf(struct bpf_object *obj)
1500 BTF_ELF_SEC, err); 1503 BTF_ELF_SEC, err);
1501 btf__free(obj->btf); 1504 btf__free(obj->btf);
1502 obj->btf = NULL; 1505 obj->btf = NULL;
1506 /* btf_ext can't exist without btf, so free it as well */
1507 if (obj->btf_ext) {
1508 btf_ext__free(obj->btf_ext);
1509 obj->btf_ext = NULL;
1510 }
1511
1503 if (bpf_object__is_btf_mandatory(obj)) 1512 if (bpf_object__is_btf_mandatory(obj))
1504 return err; 1513 return err;
1505 } 1514 }
@@ -2276,9 +2285,6 @@ bpf_program_reloc_btf_ext(struct bpf_program *prog, struct bpf_object *obj,
2276 prog->line_info_rec_size = btf_ext__line_info_rec_size(obj->btf_ext); 2285 prog->line_info_rec_size = btf_ext__line_info_rec_size(obj->btf_ext);
2277 } 2286 }
2278 2287
2279 if (!insn_offset)
2280 prog->btf_fd = btf__fd(obj->btf);
2281
2282 return 0; 2288 return 0;
2283} 2289}
2284 2290
@@ -2451,7 +2457,7 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
2451 char *cp, errmsg[STRERR_BUFSIZE]; 2457 char *cp, errmsg[STRERR_BUFSIZE];
2452 int log_buf_size = BPF_LOG_BUF_SIZE; 2458 int log_buf_size = BPF_LOG_BUF_SIZE;
2453 char *log_buf; 2459 char *log_buf;
2454 int ret; 2460 int btf_fd, ret;
2455 2461
2456 if (!insns || !insns_cnt) 2462 if (!insns || !insns_cnt)
2457 return -EINVAL; 2463 return -EINVAL;
@@ -2466,7 +2472,12 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
2466 load_attr.license = license; 2472 load_attr.license = license;
2467 load_attr.kern_version = kern_version; 2473 load_attr.kern_version = kern_version;
2468 load_attr.prog_ifindex = prog->prog_ifindex; 2474 load_attr.prog_ifindex = prog->prog_ifindex;
2469 load_attr.prog_btf_fd = prog->btf_fd >= 0 ? prog->btf_fd : 0; 2475 /* if .BTF.ext was loaded, kernel supports associated BTF for prog */
2476 if (prog->obj->btf_ext)
2477 btf_fd = bpf_object__btf_fd(prog->obj);
2478 else
2479 btf_fd = -1;
2480 load_attr.prog_btf_fd = btf_fd >= 0 ? btf_fd : 0;
2470 load_attr.func_info = prog->func_info; 2481 load_attr.func_info = prog->func_info;
2471 load_attr.func_info_rec_size = prog->func_info_rec_size; 2482 load_attr.func_info_rec_size = prog->func_info_rec_size;
2472 load_attr.func_info_cnt = prog->func_info_cnt; 2483 load_attr.func_info_cnt = prog->func_info_cnt;
@@ -4507,13 +4518,13 @@ struct perf_buffer *perf_buffer__new(int map_fd, size_t page_cnt,
4507 const struct perf_buffer_opts *opts) 4518 const struct perf_buffer_opts *opts)
4508{ 4519{
4509 struct perf_buffer_params p = {}; 4520 struct perf_buffer_params p = {};
4510 struct perf_event_attr attr = { 4521 struct perf_event_attr attr = { 0, };
4511 .config = PERF_COUNT_SW_BPF_OUTPUT, 4522
4512 .type = PERF_TYPE_SOFTWARE, 4523 attr.config = PERF_COUNT_SW_BPF_OUTPUT,
4513 .sample_type = PERF_SAMPLE_RAW, 4524 attr.type = PERF_TYPE_SOFTWARE;
4514 .sample_period = 1, 4525 attr.sample_type = PERF_SAMPLE_RAW;
4515 .wakeup_events = 1, 4526 attr.sample_period = 1;
4516 }; 4527 attr.wakeup_events = 1;
4517 4528
4518 p.attr = &attr; 4529 p.attr = &attr;
4519 p.sample_cb = opts ? opts->sample_cb : NULL; 4530 p.sample_cb = opts ? opts->sample_cb : NULL;
@@ -4988,13 +4999,15 @@ int libbpf_num_possible_cpus(void)
4988 static const char *fcpu = "/sys/devices/system/cpu/possible"; 4999 static const char *fcpu = "/sys/devices/system/cpu/possible";
4989 int len = 0, n = 0, il = 0, ir = 0; 5000 int len = 0, n = 0, il = 0, ir = 0;
4990 unsigned int start = 0, end = 0; 5001 unsigned int start = 0, end = 0;
5002 int tmp_cpus = 0;
4991 static int cpus; 5003 static int cpus;
4992 char buf[128]; 5004 char buf[128];
4993 int error = 0; 5005 int error = 0;
4994 int fd = -1; 5006 int fd = -1;
4995 5007
4996 if (cpus > 0) 5008 tmp_cpus = READ_ONCE(cpus);
4997 return cpus; 5009 if (tmp_cpus > 0)
5010 return tmp_cpus;
4998 5011
4999 fd = open(fcpu, O_RDONLY); 5012 fd = open(fcpu, O_RDONLY);
5000 if (fd < 0) { 5013 if (fd < 0) {
@@ -5017,7 +5030,7 @@ int libbpf_num_possible_cpus(void)
5017 } 5030 }
5018 buf[len] = '\0'; 5031 buf[len] = '\0';
5019 5032
5020 for (ir = 0, cpus = 0; ir <= len; ir++) { 5033 for (ir = 0, tmp_cpus = 0; ir <= len; ir++) {
5021 /* Each sub string separated by ',' has format \d+-\d+ or \d+ */ 5034 /* Each sub string separated by ',' has format \d+-\d+ or \d+ */
5022 if (buf[ir] == ',' || buf[ir] == '\0') { 5035 if (buf[ir] == ',' || buf[ir] == '\0') {
5023 buf[ir] = '\0'; 5036 buf[ir] = '\0';
@@ -5029,13 +5042,15 @@ int libbpf_num_possible_cpus(void)
5029 } else if (n == 1) { 5042 } else if (n == 1) {
5030 end = start; 5043 end = start;
5031 } 5044 }
5032 cpus += end - start + 1; 5045 tmp_cpus += end - start + 1;
5033 il = ir + 1; 5046 il = ir + 1;
5034 } 5047 }
5035 } 5048 }
5036 if (cpus <= 0) { 5049 if (tmp_cpus <= 0) {
5037 pr_warning("Invalid #CPUs %d from %s\n", cpus, fcpu); 5050 pr_warning("Invalid #CPUs %d from %s\n", tmp_cpus, fcpu);
5038 return -EINVAL; 5051 return -EINVAL;
5039 } 5052 }
5040 return cpus; 5053
5054 WRITE_ONCE(cpus, tmp_cpus);
5055 return tmp_cpus;
5041} 5056}