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. */ 19 static void __attribute__((noinline)) test_dump_stack(void); 20 static 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 65 static void test_dump_stack(void) {} 66 #endif 67 68 void __attribute__((noinline)) 69 test_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 } 99