linux/tools/testing/selftests/kvm/lib/assert.c
<<
>>
Prefs
   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. */
  18static void __attribute__((noinline)) test_dump_stack(void);
  19static 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
  58static pid_t _gettid(void)
  59{
  60        return syscall(SYS_gettid);
  61}
  62
  63void __attribute__((noinline))
  64test_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 errno=%d - %s\n",
  75                        file, line, exp_str, getpid(), _gettid(),
  76                        errno, 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                        print_skip("Access denied - Exiting");
  87                        exit(KSFT_SKIP);
  88                }
  89                exit(254);
  90        }
  91
  92        return;
  93}
  94