root/tools/testing/selftests/kvm/lib/assert.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. test_dump_stack
  2. _gettid
  3. test_assert

   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 
   8 #define _GNU_SOURCE /* for getline(3) and strchrnul(3)*/
   9 
  10 #include "test_util.h"
  11 
  12 #include <execinfo.h>
  13 #include <sys/syscall.h>
  14 
  15 #include "kselftest.h"
  16 
  17 /* Dumps the current stack trace to stderr. */
  18 static void __attribute__((noinline)) test_dump_stack(void);
  19 static void test_dump_stack(void)
  20 {
  21         /*
  22          * Build and run this command:
  23          *
  24          *      addr2line -s -e /proc/$PPID/exe -fpai {backtrace addresses} | \
  25          *              grep -v test_dump_stack | cat -n 1>&2
  26          *
  27          * Note that the spacing is different and there's no newline.
  28          */
  29         size_t i;
  30         size_t n = 20;
  31         void *stack[n];
  32         const char *addr2line = "addr2line -s -e /proc/$PPID/exe -fpai";
  33         const char *pipeline = "|cat -n 1>&2";
  34         char cmd[strlen(addr2line) + strlen(pipeline) +
  35                  /* N bytes per addr * 2 digits per byte + 1 space per addr: */
  36                  n * (((sizeof(void *)) * 2) + 1) +
  37                  /* Null terminator: */
  38                  1];
  39         char *c;
  40 
  41         n = backtrace(stack, n);
  42         c = &cmd[0];
  43         c += sprintf(c, "%s", addr2line);
  44         /*
  45          * Skip the first 3 frames: backtrace, test_dump_stack, and
  46          * test_assert. We hope that backtrace isn't inlined and the other two
  47          * we've declared noinline.
  48          */
  49         for (i = 2; i < n; i++)
  50                 c += sprintf(c, " %lx", ((unsigned long) stack[i]) - 1);
  51         c += sprintf(c, "%s", pipeline);
  52 #pragma GCC diagnostic push
  53 #pragma GCC diagnostic ignored "-Wunused-result"
  54         system(cmd);
  55 #pragma GCC diagnostic pop
  56 }
  57 
  58 static pid_t _gettid(void)
  59 {
  60         return syscall(SYS_gettid);
  61 }
  62 
  63 void __attribute__((noinline))
  64 test_assert(bool exp, const char *exp_str,
  65         const char *file, unsigned int line, const char *fmt, ...)
  66 {
  67         va_list ap;
  68 
  69         if (!(exp)) {
  70                 va_start(ap, fmt);
  71 
  72                 fprintf(stderr, "==== Test Assertion Failure ====\n"
  73                         "  %s:%u: %s\n"
  74                         "  pid=%d tid=%d - %s\n",
  75                         file, line, exp_str, getpid(), _gettid(),
  76                         strerror(errno));
  77                 test_dump_stack();
  78                 if (fmt) {
  79                         fputs("  ", stderr);
  80                         vfprintf(stderr, fmt, ap);
  81                         fputs("\n", stderr);
  82                 }
  83                 va_end(ap);
  84 
  85                 if (errno == EACCES)
  86                         ksft_exit_skip("Access denied - Exiting.\n");
  87                 exit(254);
  88         }
  89 
  90         return;
  91 }

/* [<][>][^][v][top][bottom][index][help] */