projects/linux·blob master · refs

98 lines · 2.2 KiB

1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * tools/testing/selftests/kvm/lib/assert.c
4 *
5 * Copyright (C) 2018, Google LLC.
6 */
7#include "test_util.h"
8
9
10#include <sys/syscall.h>
11
12#include "kselftest.h"
13#include "kvm_syscalls.h"
14
15#ifdef __GLIBC__
16#include <execinfo.h>
17
18/* Dumps the current stack trace to stderr. */
19static void __attribute__((noinline)) test_dump_stack(void);
20static void test_dump_stack(void)
21{
22 /*
23 * Build and run this command:
24 *
25 * addr2line -s -e /proc/$PPID/exe -fpai {backtrace addresses} | \
26 * cat -n 1>&2
27 *
28 * Note that the spacing is different and there's no newline.
29 */
30 size_t i;
31 size_t n = 20;
32 void *stack[n];
33 const char *addr2line = "addr2line -s -e /proc/$PPID/exe -fpai";
34 const char *pipeline = "|cat -n 1>&2";
35 char cmd[strlen(addr2line) + strlen(pipeline) +
36 /* N bytes per addr * 2 digits per byte + 1 space per addr: */
37 n * (((sizeof(void *)) * 2) + 1) +
38 /* Null terminator: */
39 1];
40 char *c = cmd;
41
42 n = backtrace(stack, n);
43 /*
44 * Skip the first 2 frames, which should be test_dump_stack() and
45 * test_assert(); both of which are declared noinline. Bail if the
46 * resulting stack trace would be empty. Otherwise, addr2line will block
47 * waiting for addresses to be passed in via stdin.
48 */
49 if (n <= 2) {
50 fputs(" (stack trace empty)\n", stderr);
51 return;
52 }
53
54 c += sprintf(c, "%s", addr2line);
55 for (i = 2; i < n; i++)
56 c += sprintf(c, " %lx", ((unsigned long) stack[i]) - 1);
57
58 c += sprintf(c, "%s", pipeline);
59#pragma GCC diagnostic push
60#pragma GCC diagnostic ignored "-Wunused-result"
61 system(cmd);
62#pragma GCC diagnostic pop
63}
64#else
65static void test_dump_stack(void) {}
66#endif
67
68void __attribute__((noinline))
69test_assert(bool exp, const char *exp_str,
70 const char *file, unsigned int line, const char *fmt, ...)
71{
72 va_list ap;
73
74 if (!(exp)) {
75 va_start(ap, fmt);
76
77 fprintf(stderr, "\n==== Test Assertion Failure ====\n"
78 " %s:%u: %s\n"
79 " pid=%d tid=%d errno=%d - %s\n",
80 file, line, exp_str, getpid(), kvm_gettid(),
81 errno, strerror(errno));
82 test_dump_stack();
83 if (fmt) {
84 fputs(" ", stderr);
85 vfprintf(stderr, fmt, ap);
86 fputs("\n", stderr);
87 }
88 va_end(ap);
89
90 if (errno == EACCES) {
91 print_skip("Access denied - Exiting");
92 exit(KSFT_SKIP);
93 }
94 exit(254);
95 }
96
97 return;
98}