-
Notifications
You must be signed in to change notification settings - Fork 0
/
cxa_throw_filter.cpp
109 lines (89 loc) · 2.3 KB
/
cxa_throw_filter.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <dlfcn.h>
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cxxabi.h>
#include <execinfo.h>
#include <algorithm>
#include "backtrace_print.h"
namespace {
struct OrigCxaThrowRoutine
{
OrigCxaThrowRoutine()
{
m_fptr = (cxa_throw_type) dlsym(RTLD_NEXT, "__cxa_throw");
}
typedef void (*cxa_throw_type)(void *, void *, void (*) (void *));
cxa_throw_type m_fptr;
};
OrigCxaThrowRoutine g_orig_cxa_throw;
struct OutputFileHolder
{
OutputFileHolder()
{
out = stderr;
char *out_filename_env = getenv("DBGTHROW_OUTPUT_FILENAME");
if (out_filename_env)
{
out = fopen(out_filename_env, "a");
if (!out)
out = stderr;
}
}
~OutputFileHolder()
{
if (out && out != stderr)
fclose(out);
}
FILE *out;
};
OutputFileHolder g_output;
struct ExceptFilter
{
ExceptFilter()
{
pattern = getenv("DBGTHROW_EXCEPT_PATTERN");
}
bool match(const char* s) const
{
return !pattern || strcmp(pattern, s) == 0;
}
char* pattern;
};
ExceptFilter g_filter;
}
extern "C" void __cxa_throw (
void *thrown_exception,
std::type_info *tinfo,
void (*dest)(void *))
{
int dm_status;
char* exp_name_demangled = abi::__cxa_demangle(tinfo->name(), 0, 0, &dm_status);
const char* exp_name = exp_name_demangled;
if (dm_status != 0) {
exp_name = tinfo->name();
}
if (g_filter.match(exp_name)) {
libdbgthrow::pretty_print_sym(g_output.out, tinfo->name());
fputs(" thrown at:\n", g_output.out);
size_t depth = 10;
char *depth_env = getenv("DBGTHROW_BACKTRACE_DEPTH");
if (depth_env)
depth = std::max(1, atoi(depth_env));
// make space for one more function (this one), which we ommit afterwards
++depth;
if (depth > 64) {
depth = 64;
}
void* bt_stack[64] = {};
int size = backtrace(bt_stack, depth);
libdbgthrow::pretty_print_bt(
g_output.out,
bt_stack+1,
std::min((size_t)size-1, depth-1));
fflush(g_output.out);
}
free(exp_name_demangled);
g_orig_cxa_throw.m_fptr(thrown_exception, tinfo, dest);
}