1 /* 2 * tools/testing/selftests/kvm/lib/assert.c 3 * 4 * Copyright (C) 2018, Google LLC. 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2. 7 */ 8 9 #define _GNU_SOURCE /* for getline(3) and strchrnul(3)*/ 10 11 #include "test_util.h" 12 13 #include <execinfo.h> 14 #include <sys/syscall.h> 15 16 #include "../../kselftest.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 * grep -v test_dump_stack | 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; 41 42 n = backtrace(stack, n); 43 c = &cmd[0]; 44 c += sprintf(c, "%s", addr2line); 45 /* 46 * Skip the first 3 frames: backtrace, test_dump_stack, and 47 * test_assert. We hope that backtrace isn't inlined and the other two 48 * we've declared noinline. 49 */ 50 for (i = 2; i < n; i++) 51 c += sprintf(c, " %lx", ((unsigned long) stack[i]) - 1); 52 c += sprintf(c, "%s", pipeline); 53 #pragma GCC diagnostic push 54 #pragma GCC diagnostic ignored "-Wunused-result" 55 system(cmd); 56 #pragma GCC diagnostic pop 57 } 58 59 static pid_t gettid(void) 60 { 61 return syscall(SYS_gettid); 62 } 63 64 void __attribute__((noinline)) 65 test_assert(bool exp, const char *exp_str, 66 const char *file, unsigned int line, const char *fmt, ...) 67 { 68 va_list ap; 69 70 if (!(exp)) { 71 va_start(ap, fmt); 72 73 fprintf(stderr, "==== Test Assertion Failure ====\n" 74 " %s:%u: %s\n" 75 " pid=%d tid=%d - %s\n", 76 file, line, exp_str, getpid(), gettid(), 77 strerror(errno)); 78 test_dump_stack(); 79 if (fmt) { 80 fputs(" ", stderr); 81 vfprintf(stderr, fmt, ap); 82 fputs("\n", stderr); 83 } 84 va_end(ap); 85 86 if (errno == EACCES) 87 ksft_exit_skip("Access denied - Exiting.\n"); 88 exit(254); 89 } 90 91 return; 92 } 93