linux/tools/testing/selftests/kvm/lib/assert.c
<<
>>
Prefs
   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. */
  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         *              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
  59static pid_t gettid(void)
  60{
  61        return syscall(SYS_gettid);
  62}
  63
  64void __attribute__((noinline))
  65test_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