offwaketime_user.c (3241B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* Copyright (c) 2016 Facebook 3 */ 4#include <stdio.h> 5#include <unistd.h> 6#include <stdlib.h> 7#include <signal.h> 8#include <linux/perf_event.h> 9#include <errno.h> 10#include <stdbool.h> 11#include <bpf/libbpf.h> 12#include <bpf/bpf.h> 13#include "trace_helpers.h" 14 15#define PRINT_RAW_ADDR 0 16 17/* counts, stackmap */ 18static int map_fd[2]; 19 20static void print_ksym(__u64 addr) 21{ 22 struct ksym *sym; 23 24 if (!addr) 25 return; 26 sym = ksym_search(addr); 27 if (!sym) { 28 printf("ksym not found. Is kallsyms loaded?\n"); 29 return; 30 } 31 32 if (PRINT_RAW_ADDR) 33 printf("%s/%llx;", sym->name, addr); 34 else 35 printf("%s;", sym->name); 36} 37 38#define TASK_COMM_LEN 16 39 40struct key_t { 41 char waker[TASK_COMM_LEN]; 42 char target[TASK_COMM_LEN]; 43 __u32 wret; 44 __u32 tret; 45}; 46 47static void print_stack(struct key_t *key, __u64 count) 48{ 49 __u64 ip[PERF_MAX_STACK_DEPTH] = {}; 50 static bool warned; 51 int i; 52 53 printf("%s;", key->target); 54 if (bpf_map_lookup_elem(map_fd[1], &key->tret, ip) != 0) { 55 printf("---;"); 56 } else { 57 for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--) 58 print_ksym(ip[i]); 59 } 60 printf("-;"); 61 if (bpf_map_lookup_elem(map_fd[1], &key->wret, ip) != 0) { 62 printf("---;"); 63 } else { 64 for (i = 0; i < PERF_MAX_STACK_DEPTH; i++) 65 print_ksym(ip[i]); 66 } 67 printf(";%s %lld\n", key->waker, count); 68 69 if ((key->tret == -EEXIST || key->wret == -EEXIST) && !warned) { 70 printf("stackmap collisions seen. Consider increasing size\n"); 71 warned = true; 72 } else if (((int)(key->tret) < 0 || (int)(key->wret) < 0)) { 73 printf("err stackid %d %d\n", key->tret, key->wret); 74 } 75} 76 77static void print_stacks(int fd) 78{ 79 struct key_t key = {}, next_key; 80 __u64 value; 81 82 while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { 83 bpf_map_lookup_elem(fd, &next_key, &value); 84 print_stack(&next_key, value); 85 key = next_key; 86 } 87} 88 89static void int_exit(int sig) 90{ 91 print_stacks(map_fd[0]); 92 exit(0); 93} 94 95int main(int argc, char **argv) 96{ 97 struct bpf_object *obj = NULL; 98 struct bpf_link *links[2]; 99 struct bpf_program *prog; 100 int delay = 1, i = 0; 101 char filename[256]; 102 103 if (load_kallsyms()) { 104 printf("failed to process /proc/kallsyms\n"); 105 return 2; 106 } 107 108 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 109 obj = bpf_object__open_file(filename, NULL); 110 if (libbpf_get_error(obj)) { 111 fprintf(stderr, "ERROR: opening BPF object file failed\n"); 112 obj = NULL; 113 goto cleanup; 114 } 115 116 /* load BPF program */ 117 if (bpf_object__load(obj)) { 118 fprintf(stderr, "ERROR: loading BPF object file failed\n"); 119 goto cleanup; 120 } 121 122 map_fd[0] = bpf_object__find_map_fd_by_name(obj, "counts"); 123 map_fd[1] = bpf_object__find_map_fd_by_name(obj, "stackmap"); 124 if (map_fd[0] < 0 || map_fd[1] < 0) { 125 fprintf(stderr, "ERROR: finding a map in obj file failed\n"); 126 goto cleanup; 127 } 128 129 signal(SIGINT, int_exit); 130 signal(SIGTERM, int_exit); 131 132 bpf_object__for_each_program(prog, obj) { 133 links[i] = bpf_program__attach(prog); 134 if (libbpf_get_error(links[i])) { 135 fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 136 links[i] = NULL; 137 goto cleanup; 138 } 139 i++; 140 } 141 142 if (argc > 1) 143 delay = atoi(argv[1]); 144 sleep(delay); 145 print_stacks(map_fd[0]); 146 147cleanup: 148 for (i--; i >= 0; i--) 149 bpf_link__destroy(links[i]); 150 151 bpf_object__close(obj); 152 return 0; 153}