1 /* 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 */ 7 #include <stdio.h> 8 #include <unistd.h> 9 #include <stdlib.h> 10 #include <signal.h> 11 #include <linux/bpf.h> 12 #include <string.h> 13 #include <linux/perf_event.h> 14 #include <errno.h> 15 #include <assert.h> 16 #include <stdbool.h> 17 #include <sys/resource.h> 18 #include "libbpf.h" 19 #include "bpf_load.h" 20 #include "trace_helpers.h" 21 22 #define PRINT_RAW_ADDR 0 23 24 static void print_ksym(__u64 addr) 25 { 26 struct ksym *sym; 27 28 if (!addr) 29 return; 30 sym = ksym_search(addr); 31 if (!sym) { 32 printf("ksym not found. Is kallsyms loaded?\n"); 33 return; 34 } 35 36 if (PRINT_RAW_ADDR) 37 printf("%s/%llx;", sym->name, addr); 38 else 39 printf("%s;", sym->name); 40 } 41 42 #define TASK_COMM_LEN 16 43 44 struct key_t { 45 char waker[TASK_COMM_LEN]; 46 char target[TASK_COMM_LEN]; 47 __u32 wret; 48 __u32 tret; 49 }; 50 51 static void print_stack(struct key_t *key, __u64 count) 52 { 53 __u64 ip[PERF_MAX_STACK_DEPTH] = {}; 54 static bool warned; 55 int i; 56 57 printf("%s;", key->target); 58 if (bpf_map_lookup_elem(map_fd[3], &key->tret, ip) != 0) { 59 printf("---;"); 60 } else { 61 for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--) 62 print_ksym(ip[i]); 63 } 64 printf("-;"); 65 if (bpf_map_lookup_elem(map_fd[3], &key->wret, ip) != 0) { 66 printf("---;"); 67 } else { 68 for (i = 0; i < PERF_MAX_STACK_DEPTH; i++) 69 print_ksym(ip[i]); 70 } 71 printf(";%s %lld\n", key->waker, count); 72 73 if ((key->tret == -EEXIST || key->wret == -EEXIST) && !warned) { 74 printf("stackmap collisions seen. Consider increasing size\n"); 75 warned = true; 76 } else if (((int)(key->tret) < 0 || (int)(key->wret) < 0)) { 77 printf("err stackid %d %d\n", key->tret, key->wret); 78 } 79 } 80 81 static void print_stacks(int fd) 82 { 83 struct key_t key = {}, next_key; 84 __u64 value; 85 86 while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { 87 bpf_map_lookup_elem(fd, &next_key, &value); 88 print_stack(&next_key, value); 89 key = next_key; 90 } 91 } 92 93 static void int_exit(int sig) 94 { 95 print_stacks(map_fd[0]); 96 exit(0); 97 } 98 99 int main(int argc, char **argv) 100 { 101 struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 102 char filename[256]; 103 int delay = 1; 104 105 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 106 setrlimit(RLIMIT_MEMLOCK, &r); 107 108 signal(SIGINT, int_exit); 109 signal(SIGTERM, int_exit); 110 111 if (load_kallsyms()) { 112 printf("failed to process /proc/kallsyms\n"); 113 return 2; 114 } 115 116 if (load_bpf_file(filename)) { 117 printf("%s", bpf_log_buf); 118 return 1; 119 } 120 121 if (argc > 1) 122 delay = atoi(argv[1]); 123 sleep(delay); 124 print_stacks(map_fd[0]); 125 126 return 0; 127 } 128