^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "tests.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "machine.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "event.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "../util/unwind.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "perf_regs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "map.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "symbol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "thread.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "callchain.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "util/synthetic-events.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #if defined (__x86_64__) || defined (__i386__) || defined (__powerpc__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "arch-tests.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* For bsearch. We try to unwind functions in shared object. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static int mmap_handler(struct perf_tool *tool __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return machine__process_mmap2_event(machine, event, sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int init_live_machine(struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) union perf_event event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) pid_t pid = getpid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) memset(&event, 0, sizeof(event));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return perf_event__synthesize_mmap_events(NULL, &event, pid, pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) mmap_handler, machine, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * We need to keep these functions global, despite the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * fact that they are used only locally in this object,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * in order to keep them around even if the binary is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * stripped. If they are gone, the unwind check for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * symbol fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int test_dwarf_unwind__thread(struct thread *thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int test_dwarf_unwind__compare(void *p1, void *p2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int test_dwarf_unwind__krava_3(struct thread *thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int test_dwarf_unwind__krava_2(struct thread *thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int test_dwarf_unwind__krava_1(struct thread *thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define MAX_STACK 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static int unwind_entry(struct unwind_entry *entry, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned long *cnt = (unsigned long *) arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) char *symbol = entry->ms.sym ? entry->ms.sym->name : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static const char *funcs[MAX_STACK] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) "test__arch_unwind_sample",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) "test_dwarf_unwind__thread",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) "test_dwarf_unwind__compare",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) "bsearch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) "test_dwarf_unwind__krava_3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) "test_dwarf_unwind__krava_2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) "test_dwarf_unwind__krava_1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) "test__dwarf_unwind"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * The funcs[MAX_STACK] array index, based on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * callchain order setup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int idx = callchain_param.order == ORDER_CALLER ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) MAX_STACK - *cnt - 1 : *cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (*cnt >= MAX_STACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) pr_debug("failed: crossed the max stack value %d\n", MAX_STACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (!symbol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) pr_debug("failed: got unresolved address 0x%" PRIx64 "\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) entry->ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) (*cnt)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) pr_debug("got: %s 0x%" PRIx64 ", expecting %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) symbol, entry->ip, funcs[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return strcmp((const char *) symbol, funcs[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) noinline int test_dwarf_unwind__thread(struct thread *thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct perf_sample sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned long cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) memset(&sample, 0, sizeof(sample));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (test__arch_unwind_sample(&sample, thread)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) pr_debug("failed to get unwind sample\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) err = unwind__get_entries(unwind_entry, &cnt, thread,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) &sample, MAX_STACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) pr_debug("unwind failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) else if (cnt != MAX_STACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) pr_debug("got wrong number of stack entries %lu != %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) cnt, MAX_STACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) zfree(&sample.user_stack.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) zfree(&sample.user_regs.regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static int global_unwind_retval = -INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) noinline int test_dwarf_unwind__compare(void *p1, void *p2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* Any possible value should be 'thread' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct thread *thread = *(struct thread **)p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (global_unwind_retval == -INT_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* Call unwinder twice for both callchain orders. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) callchain_param.order = ORDER_CALLER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) global_unwind_retval = test_dwarf_unwind__thread(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!global_unwind_retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) callchain_param.order = ORDER_CALLEE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) global_unwind_retval = test_dwarf_unwind__thread(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return p1 - p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) noinline int test_dwarf_unwind__krava_3(struct thread *thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct thread *array[2] = {thread, thread};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) void *fp = &bsearch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * make _bsearch a volatile function pointer to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * prevent potential optimization, which may expand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * bsearch and call compare directly from this function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * instead of libc shared object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) void *(*volatile _bsearch)(void *, void *, size_t,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) size_t, int (*)(void *, void *));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) _bsearch = fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) _bsearch(array, &thread, 2, sizeof(struct thread **),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) test_dwarf_unwind__compare);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return global_unwind_retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) noinline int test_dwarf_unwind__krava_2(struct thread *thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return test_dwarf_unwind__krava_3(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) noinline int test_dwarf_unwind__krava_1(struct thread *thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return test_dwarf_unwind__krava_2(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct machine *machine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct thread *thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) int err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) machine = machine__new_host();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (!machine) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) pr_err("Could not get machine\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (machine__create_kernel_maps(machine)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) pr_err("Failed to create kernel maps\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) callchain_param.record_mode = CALLCHAIN_DWARF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) dwarf_callchain_users = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (init_live_machine(machine)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) pr_err("Could not init machine\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (verbose > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) machine__fprintf(machine, stderr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) thread = machine__find_thread(machine, getpid(), getpid());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (!thread) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) pr_err("Could not get thread\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) err = test_dwarf_unwind__krava_1(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) thread__put(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) machine__delete_threads(machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) machine__delete(machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }