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