1ac643f1dSJens Alfke#include "debug.h"
2ceb27a9fSSundar Sridharan#include <stdio.h>
3818cce61SJung-Sang Ahn#include <stdlib.h>
4818cce61SJung-Sang Ahn#include <stdint.h>
5eda2b6e5SSundar Sridharan#include "time_utils.h"
64178fbe1SSundar Sridharan#if !defined(WIN32) && !defined(_WIN32)
7bda6f426SSundar Sridharan#include <sys/wait.h>
8bda6f426SSundar Sridharan#include <unistd.h>
94178fbe1SSundar Sridharan#include <execinfo.h>
104178fbe1SSundar Sridharan#endif // !defined(WIN32) && !defined(_WIN32)
11818cce61SJung-Sang Ahn
12818cce61SJung-Sang Ahn#define N_DBG_SWITCH (256)
13818cce61SJung-Sang Ahn
14818cce61SJung-Sang Ahnstatic uint8_t _global_dbg_switch[N_DBG_SWITCH];
15818cce61SJung-Sang Ahnstatic void* _global_dbg_addr[N_DBG_SWITCH];
16818cce61SJung-Sang Ahnstatic uint64_t _global_dbg_uint64_t[N_DBG_SWITCH];
17818cce61SJung-Sang Ahn
18bc5884e7SChiyoung Seo// LCOV_EXCL_START
19818cce61SJung-Sang Ahnvoid _dbg_sw_set(int n)
20818cce61SJung-Sang Ahn{
21818cce61SJung-Sang Ahn    _global_dbg_switch[n] = 1;
22818cce61SJung-Sang Ahn}
23818cce61SJung-Sang Ahn
24818cce61SJung-Sang Ahnvoid _dbg_sw_clear(int n)
25818cce61SJung-Sang Ahn{
26818cce61SJung-Sang Ahn    _global_dbg_switch[n] = 0;
27818cce61SJung-Sang Ahn}
28818cce61SJung-Sang Ahn
29818cce61SJung-Sang Ahnvoid _dbg_set_addr(int n, void *addr)
30818cce61SJung-Sang Ahn{
31818cce61SJung-Sang Ahn    _global_dbg_addr[n] = addr;
32818cce61SJung-Sang Ahn}
33818cce61SJung-Sang Ahn
34818cce61SJung-Sang Ahnvoid * _dbg_get_addr(int n)
35818cce61SJung-Sang Ahn{
36818cce61SJung-Sang Ahn    return _global_dbg_addr[n];
37818cce61SJung-Sang Ahn}
38818cce61SJung-Sang Ahn
39818cce61SJung-Sang Ahnvoid _dbg_set_uint64_t(int n, uint64_t val)
40818cce61SJung-Sang Ahn{
41818cce61SJung-Sang Ahn    _global_dbg_uint64_t[n] = val;
42818cce61SJung-Sang Ahn}
43818cce61SJung-Sang Ahn
44818cce61SJung-Sang Ahnuint64_t _dbg_get_uint64_t(int n)
45818cce61SJung-Sang Ahn{
46818cce61SJung-Sang Ahn    return _global_dbg_uint64_t[n];
47818cce61SJung-Sang Ahn}
48818cce61SJung-Sang Ahn
49818cce61SJung-Sang Ahnint _dbg_is_sw_set(int n)
50818cce61SJung-Sang Ahn{
519ceccb2cSJung-Sang Ahn    return _global_dbg_switch[n];
52818cce61SJung-Sang Ahn}
53a53fc9e9SSundar Sridharan
54bda6f426SSundar Sridharanvoid dump_backtraces() {
55bda6f426SSundar Sridharan#ifdef __linux__
56bda6f426SSundar Sridharan    char my_pid[16];
57bda6f426SSundar Sridharan    char proc_name[512];
58bda6f426SSundar Sridharan    sprintf(my_pid, "--pid=%d", getpid());
59bda6f426SSundar Sridharan    proc_name[readlink("/proc/self/exe", proc_name, 511)] = '\0';
60bda6f426SSundar Sridharan    printf("Dumping backtrace for %s pid=%s..\n", proc_name, my_pid);
61bda6f426SSundar Sridharan    int gdb_pid = fork();
62bda6f426SSundar Sridharan    if (!gdb_pid) { // child process...
63bda6f426SSundar Sridharan        printf("Running gdb backtrace for %s pid=%s\n", proc_name, my_pid);
64bda6f426SSundar Sridharan        execlp("gdb", "gdb", "--batch", "-n",
65bda6f426SSundar Sridharan               "-ex", "thread apply all bt 8",
66bda6f426SSundar Sridharan               proc_name, my_pid, NULL);
67bda6f426SSundar Sridharan        abort(); /* If gdb failed to start */
68bda6f426SSundar Sridharan    } else {
69bda6f426SSundar Sridharan        int ret_stat;
70bda6f426SSundar Sridharan        waitpid(gdb_pid, &ret_stat, 0);
71bda6f426SSundar Sridharan        if (!ret_stat) {
72bda6f426SSundar Sridharan            fprintf(stderr, "\ngdb dumping successful\n");
73bda6f426SSundar Sridharan        } else {
74bda6f426SSundar Sridharan            fprintf(stderr, "\ngdb backtracing incomplete\n");
75bda6f426SSundar Sridharan        }
76bda6f426SSundar Sridharan    }
77bda6f426SSundar Sridharan#elif !defined(WIN32) && !defined(_WIN32)
78bda6f426SSundar Sridharan    void *callstack[10];
79bda6f426SSundar Sridharan    char **backtrace_buf;
80bda6f426SSundar Sridharan    int frames = backtrace(callstack, 10);
81bda6f426SSundar Sridharan    backtrace_buf = backtrace_symbols(callstack, frames);
82bda6f426SSundar Sridharan    if (backtrace_buf) {
83bda6f426SSundar Sridharan        for (int i = 0; i < frames; ++i) {
84bda6f426SSundar Sridharan            fprintf(stderr, "%d : %s\n", i, backtrace_buf[i]);
85bda6f426SSundar Sridharan        } // (no need to free memory as process is crashing)
86bda6f426SSundar Sridharan    }
87bda6f426SSundar Sridharan#endif // __linux__ or WIN32 || _WIN32
88bda6f426SSundar Sridharan}
89bda6f426SSundar Sridharan
90a53fc9e9SSundar Sridharanvoid _dbg_assert(int line, const char *file, uint64_t val, uint64_t expected) {
91eda2b6e5SSundar Sridharan    char *hang_process;
92a53fc9e9SSundar Sridharan     fprintf(stderr, "Assertion in %p != %p in %s:%d\n",
93a53fc9e9SSundar Sridharan            (void *)val, (void *)expected, file, line);
944178fbe1SSundar Sridharan
95bda6f426SSundar Sridharan     dump_backtraces(); // try to dump backtraces, for linux use gdb
96bda6f426SSundar Sridharan
97eda2b6e5SSundar Sridharan     hang_process = getenv("HANG_ON_ASSERTION");
98eda2b6e5SSundar Sridharan     if (hang_process) {
99eda2b6e5SSundar Sridharan         fprintf(stderr, "Hanging process...");
100eda2b6e5SSundar Sridharan         fprintf(stderr, "\n");
101eda2b6e5SSundar Sridharan         while (1) {
102eda2b6e5SSundar Sridharan             usleep(1000);
103eda2b6e5SSundar Sridharan         }
104eda2b6e5SSundar Sridharan     }
105a53fc9e9SSundar Sridharan}
106bc5884e7SChiyoung Seo// LCOV_EXCL_STOP
107818cce61SJung-Sang Ahn
108