1 #include <linux/compiler.h> 2 #include <linux/types.h> 3 #include <unistd.h> 4 #include "tests.h" 5 #include "debug.h" 6 #include "machine.h" 7 #include "event.h" 8 #include "unwind.h" 9 #include "perf_regs.h" 10 #include "map.h" 11 #include "thread.h" 12 #include "callchain.h" 13 14 static int mmap_handler(struct perf_tool *tool __maybe_unused, 15 union perf_event *event, 16 struct perf_sample *sample __maybe_unused, 17 struct machine *machine) 18 { 19 return machine__process_mmap2_event(machine, event, NULL); 20 } 21 22 static int init_live_machine(struct machine *machine) 23 { 24 union perf_event event; 25 pid_t pid = getpid(); 26 27 return perf_event__synthesize_mmap_events(NULL, &event, pid, pid, 28 mmap_handler, machine, true); 29 } 30 31 #define MAX_STACK 6 32 33 static int unwind_entry(struct unwind_entry *entry, void *arg) 34 { 35 unsigned long *cnt = (unsigned long *) arg; 36 char *symbol = entry->sym ? entry->sym->name : NULL; 37 static const char *funcs[MAX_STACK] = { 38 "test__arch_unwind_sample", 39 "unwind_thread", 40 "krava_3", 41 "krava_2", 42 "krava_1", 43 "test__dwarf_unwind" 44 }; 45 46 if (*cnt >= MAX_STACK) { 47 pr_debug("failed: crossed the max stack value %d\n", MAX_STACK); 48 return -1; 49 } 50 51 if (!symbol) { 52 pr_debug("failed: got unresolved address 0x%" PRIx64 "\n", 53 entry->ip); 54 return -1; 55 } 56 57 pr_debug("got: %s 0x%" PRIx64 "\n", symbol, entry->ip); 58 return strcmp((const char *) symbol, funcs[(*cnt)++]); 59 } 60 61 __attribute__ ((noinline)) 62 static int unwind_thread(struct thread *thread) 63 { 64 struct perf_sample sample; 65 unsigned long cnt = 0; 66 int err = -1; 67 68 memset(&sample, 0, sizeof(sample)); 69 70 if (test__arch_unwind_sample(&sample, thread)) { 71 pr_debug("failed to get unwind sample\n"); 72 goto out; 73 } 74 75 err = unwind__get_entries(unwind_entry, &cnt, thread, 76 &sample, MAX_STACK); 77 if (err) 78 pr_debug("unwind failed\n"); 79 else if (cnt != MAX_STACK) { 80 pr_debug("got wrong number of stack entries %lu != %d\n", 81 cnt, MAX_STACK); 82 err = -1; 83 } 84 85 out: 86 free(sample.user_stack.data); 87 free(sample.user_regs.regs); 88 return err; 89 } 90 91 __attribute__ ((noinline)) 92 static int krava_3(struct thread *thread) 93 { 94 return unwind_thread(thread); 95 } 96 97 __attribute__ ((noinline)) 98 static int krava_2(struct thread *thread) 99 { 100 return krava_3(thread); 101 } 102 103 __attribute__ ((noinline)) 104 static int krava_1(struct thread *thread) 105 { 106 return krava_2(thread); 107 } 108 109 int test__dwarf_unwind(void) 110 { 111 struct machines machines; 112 struct machine *machine; 113 struct thread *thread; 114 int err = -1; 115 116 machines__init(&machines); 117 118 machine = machines__find(&machines, HOST_KERNEL_ID); 119 if (!machine) { 120 pr_err("Could not get machine\n"); 121 return -1; 122 } 123 124 callchain_param.record_mode = CALLCHAIN_DWARF; 125 126 if (init_live_machine(machine)) { 127 pr_err("Could not init machine\n"); 128 goto out; 129 } 130 131 if (verbose > 1) 132 machine__fprintf(machine, stderr); 133 134 thread = machine__find_thread(machine, getpid(), getpid()); 135 if (!thread) { 136 pr_err("Could not get thread\n"); 137 goto out; 138 } 139 140 err = krava_1(thread); 141 142 out: 143 machine__delete_threads(machine); 144 machine__exit(machine); 145 machines__exit(&machines); 146 return err; 147 } 148