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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
/* See LICENSE file for copyright and license details. */
#include "common.h"
#ifndef TEST
#if defined(__linux__)
# define HAVE_LINE_INFO
#endif
void
libtest_print_backtrace(FILE *fp, const char *indent, size_t first, const struct backtrace *backtrace)
{
static _Thread_local int recursion_guard = 0;
int saved_errno;
unw_word_t rip;
unw_cursor_t cursor;
unw_context_t context;
Dwarf_Addr ip;
size_t i;
#if defined(HAVE_LINE_INFO)
Dwfl_Callbacks callbacks;
char *debuginfo_path = NULL;
Dwfl *dwfl = NULL;
Dwfl_Line *line = NULL;
Dwfl_Module *module = NULL;
int lineno = 0; /* initialised for compiler happiness */
const char *filename = NULL;
const char *funcname = NULL;
#endif
if (recursion_guard)
return;
saved_errno = errno;
recursion_guard = 1;
libtest_malloc_internal_usage++;
if (!backtrace) {
if (unw_getcontext(&context))
goto out;
if (unw_init_local(&cursor, &context))
goto out;
}
#if defined(__linux__)
memset(&callbacks, 0, sizeof(callbacks));
callbacks.find_elf = &dwfl_linux_proc_find_elf;
callbacks.find_debuginfo = &dwfl_standard_find_debuginfo;
callbacks.section_address = NULL;
callbacks.debuginfo_path = &debuginfo_path;
dwfl = dwfl_begin(&callbacks);
if (dwfl) {
if (dwfl_linux_proc_report(dwfl, getpid()) ||
dwfl_report_end(dwfl, NULL, NULL)) {
dwfl_end(dwfl);
dwfl = NULL;
}
}
#endif
for (i = 0u; backtrace ? i < backtrace->n : unw_step(&cursor) > 0; i++) {
if (backtrace) {
ip = backtrace->trace[i];
} else {
if (unw_get_reg(&cursor, UNW_REG_IP, &rip))
break;
ip = (Dwarf_Addr)rip;
}
if (i < first)
continue;
#if defined(HAVE_LINE_INFO)
if (dwfl) {
module = dwfl_addrmodule(dwfl, ip);
funcname = module ? dwfl_module_addrname(module, ip) : NULL;
line = dwfl_getsrc(dwfl, ip);
if (line) {
filename = dwfl_lineinfo(line, &(Dwarf_Addr){0}, &lineno, NULL, NULL, NULL);
# ifdef USE_BASENAMES_IN_BACKTRACES
if (strrchr(filename, '/'))
filename = &strrchr(filename, '/')[1];
# endif
}
}
#endif
#if defined(HAVE_LINE_INFO)
fprintf(fp, "%s0x%016"PRIxPTR": %s", indent, (uintptr_t)ip, funcname ? funcname : "???");
if (line)
fprintf(fp, " (%s:%i)\n", filename, lineno);
else
fprintf(fp, "\n");
#else
fprintf(fp, "%s0x%016"PRIxPTR"\n", indent, (uintptr_t)ip);
#endif
}
#if defined(HAVE_LINE_INFO)
if (dwfl)
dwfl_end(dwfl);
#endif
out:
libtest_malloc_internal_usage--;
recursion_guard = 0;
errno = saved_errno;
}
#else
CONST int
main(void)
{
/* How would one even test this, and what would be the point? */
return 0;
}
#endif
|