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