linux/tools/perf/tests/dwarf-unwind.c
<<
>>
Prefs
   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