| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* Copyright (c) 2016 Facebook |
|---|
| 2 | | - * |
|---|
| 3 | | - * This program is free software; you can redistribute it and/or |
|---|
| 4 | | - * modify it under the terms of version 2 of the GNU General Public |
|---|
| 5 | | - * License as published by the Free Software Foundation. |
|---|
| 6 | 3 | */ |
|---|
| 7 | 4 | #include <stdio.h> |
|---|
| 8 | 5 | #include <unistd.h> |
|---|
| 9 | 6 | #include <stdlib.h> |
|---|
| 10 | 7 | #include <signal.h> |
|---|
| 11 | | -#include <linux/bpf.h> |
|---|
| 12 | | -#include <string.h> |
|---|
| 13 | 8 | #include <linux/perf_event.h> |
|---|
| 14 | 9 | #include <errno.h> |
|---|
| 15 | | -#include <assert.h> |
|---|
| 16 | 10 | #include <stdbool.h> |
|---|
| 17 | 11 | #include <sys/resource.h> |
|---|
| 18 | | -#include "libbpf.h" |
|---|
| 19 | | -#include "bpf_load.h" |
|---|
| 12 | +#include <bpf/libbpf.h> |
|---|
| 13 | +#include <bpf/bpf.h> |
|---|
| 20 | 14 | #include "trace_helpers.h" |
|---|
| 21 | 15 | |
|---|
| 22 | 16 | #define PRINT_RAW_ADDR 0 |
|---|
| 17 | + |
|---|
| 18 | +/* counts, stackmap */ |
|---|
| 19 | +static int map_fd[2]; |
|---|
| 23 | 20 | |
|---|
| 24 | 21 | static void print_ksym(__u64 addr) |
|---|
| 25 | 22 | { |
|---|
| .. | .. |
|---|
| 28 | 25 | if (!addr) |
|---|
| 29 | 26 | return; |
|---|
| 30 | 27 | sym = ksym_search(addr); |
|---|
| 28 | + if (!sym) { |
|---|
| 29 | + printf("ksym not found. Is kallsyms loaded?\n"); |
|---|
| 30 | + return; |
|---|
| 31 | + } |
|---|
| 32 | + |
|---|
| 31 | 33 | if (PRINT_RAW_ADDR) |
|---|
| 32 | 34 | printf("%s/%llx;", sym->name, addr); |
|---|
| 33 | 35 | else |
|---|
| .. | .. |
|---|
| 50 | 52 | int i; |
|---|
| 51 | 53 | |
|---|
| 52 | 54 | printf("%s;", key->target); |
|---|
| 53 | | - if (bpf_map_lookup_elem(map_fd[3], &key->tret, ip) != 0) { |
|---|
| 55 | + if (bpf_map_lookup_elem(map_fd[1], &key->tret, ip) != 0) { |
|---|
| 54 | 56 | printf("---;"); |
|---|
| 55 | 57 | } else { |
|---|
| 56 | 58 | for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--) |
|---|
| 57 | 59 | print_ksym(ip[i]); |
|---|
| 58 | 60 | } |
|---|
| 59 | 61 | printf("-;"); |
|---|
| 60 | | - if (bpf_map_lookup_elem(map_fd[3], &key->wret, ip) != 0) { |
|---|
| 62 | + if (bpf_map_lookup_elem(map_fd[1], &key->wret, ip) != 0) { |
|---|
| 61 | 63 | printf("---;"); |
|---|
| 62 | 64 | } else { |
|---|
| 63 | 65 | for (i = 0; i < PERF_MAX_STACK_DEPTH; i++) |
|---|
| .. | .. |
|---|
| 94 | 96 | int main(int argc, char **argv) |
|---|
| 95 | 97 | { |
|---|
| 96 | 98 | struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; |
|---|
| 99 | + struct bpf_object *obj = NULL; |
|---|
| 100 | + struct bpf_link *links[2]; |
|---|
| 101 | + struct bpf_program *prog; |
|---|
| 102 | + int delay = 1, i = 0; |
|---|
| 97 | 103 | char filename[256]; |
|---|
| 98 | | - int delay = 1; |
|---|
| 99 | 104 | |
|---|
| 100 | | - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); |
|---|
| 101 | | - setrlimit(RLIMIT_MEMLOCK, &r); |
|---|
| 102 | | - |
|---|
| 103 | | - signal(SIGINT, int_exit); |
|---|
| 104 | | - signal(SIGTERM, int_exit); |
|---|
| 105 | + if (setrlimit(RLIMIT_MEMLOCK, &r)) { |
|---|
| 106 | + perror("setrlimit(RLIMIT_MEMLOCK)"); |
|---|
| 107 | + return 1; |
|---|
| 108 | + } |
|---|
| 105 | 109 | |
|---|
| 106 | 110 | if (load_kallsyms()) { |
|---|
| 107 | 111 | printf("failed to process /proc/kallsyms\n"); |
|---|
| 108 | 112 | return 2; |
|---|
| 109 | 113 | } |
|---|
| 110 | 114 | |
|---|
| 111 | | - if (load_bpf_file(filename)) { |
|---|
| 112 | | - printf("%s", bpf_log_buf); |
|---|
| 113 | | - return 1; |
|---|
| 115 | + snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); |
|---|
| 116 | + obj = bpf_object__open_file(filename, NULL); |
|---|
| 117 | + if (libbpf_get_error(obj)) { |
|---|
| 118 | + fprintf(stderr, "ERROR: opening BPF object file failed\n"); |
|---|
| 119 | + obj = NULL; |
|---|
| 120 | + goto cleanup; |
|---|
| 121 | + } |
|---|
| 122 | + |
|---|
| 123 | + /* load BPF program */ |
|---|
| 124 | + if (bpf_object__load(obj)) { |
|---|
| 125 | + fprintf(stderr, "ERROR: loading BPF object file failed\n"); |
|---|
| 126 | + goto cleanup; |
|---|
| 127 | + } |
|---|
| 128 | + |
|---|
| 129 | + map_fd[0] = bpf_object__find_map_fd_by_name(obj, "counts"); |
|---|
| 130 | + map_fd[1] = bpf_object__find_map_fd_by_name(obj, "stackmap"); |
|---|
| 131 | + if (map_fd[0] < 0 || map_fd[1] < 0) { |
|---|
| 132 | + fprintf(stderr, "ERROR: finding a map in obj file failed\n"); |
|---|
| 133 | + goto cleanup; |
|---|
| 134 | + } |
|---|
| 135 | + |
|---|
| 136 | + signal(SIGINT, int_exit); |
|---|
| 137 | + signal(SIGTERM, int_exit); |
|---|
| 138 | + |
|---|
| 139 | + bpf_object__for_each_program(prog, obj) { |
|---|
| 140 | + links[i] = bpf_program__attach(prog); |
|---|
| 141 | + if (libbpf_get_error(links[i])) { |
|---|
| 142 | + fprintf(stderr, "ERROR: bpf_program__attach failed\n"); |
|---|
| 143 | + links[i] = NULL; |
|---|
| 144 | + goto cleanup; |
|---|
| 145 | + } |
|---|
| 146 | + i++; |
|---|
| 114 | 147 | } |
|---|
| 115 | 148 | |
|---|
| 116 | 149 | if (argc > 1) |
|---|
| .. | .. |
|---|
| 118 | 151 | sleep(delay); |
|---|
| 119 | 152 | print_stacks(map_fd[0]); |
|---|
| 120 | 153 | |
|---|
| 154 | +cleanup: |
|---|
| 155 | + for (i--; i >= 0; i--) |
|---|
| 156 | + bpf_link__destroy(links[i]); |
|---|
| 157 | + |
|---|
| 158 | + bpf_object__close(obj); |
|---|
| 121 | 159 | return 0; |
|---|
| 122 | 160 | } |
|---|