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 13static 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_mmap2_event(machine, event, NULL); 19} 20 21static 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 32static 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)) 61static 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)) 91static int krava_3(struct thread *thread, struct machine *machine) 92{ 93 return unwind_thread(thread, machine); 94} 95 96__attribute__ ((noinline)) 97static int krava_2(struct thread *thread, struct machine *machine) 98{ 99 return krava_3(thread, machine); 100} 101 102__attribute__ ((noinline)) 103static int krava_1(struct thread *thread, struct machine *machine) 104{ 105 return krava_2(thread, machine); 106} 107 108int 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