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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001, 2015 Oracle and/or its affiliates. All rights reserved.
*
* $Id$
*/
#include "db_config.h"
#include "db_int.h"
#if defined(HAVE_SYSTEM_INCLUDE_FILES) && defined(HAVE_BACKTRACE) && \
defined(HAVE_BACKTRACE_SYMBOLS) && defined(HAVE_EXECINFO_H)
#include <execinfo.h>
#endif
#undef __DB_STACK_MAXFRAMES
#define __DB_STACK_MAXFRAMES 25
/*
* __os_stack --
* Output a stack trace in a single write to the error file handle.
*
* PUBLIC: void __os_stack __P((const ENV *));
*/
void
__os_stack(env)
const ENV *env;
{
/* Adjust by 2 to exclude __os_stack() and __os_stack_top(). */
__os_stack_top(env, __DB_STACK_MAXFRAMES - 2, 2);
}
/*
* __os_stack_top --
* Output just a certain range of stack frames to the error file handle.
*
* PUBLIC: void __os_stack_top __P((const ENV *, unsigned, unsigned));
*/
void
__os_stack_top(env, nframes, skipframes)
const ENV *env;
unsigned nframes;
unsigned skipframes;
{
#if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
char buf[__DB_STACK_MAXFRAMES * 80]; /* Allow for 80 chars/line. */
__os_stack_text(env, buf, sizeof(buf), nframes, skipframes + 1);
__db_errx(env, "Top of stack:\n%s", buf);
#else
COMPQUIET(env, NULL);
COMPQUIET(nframes, 0);
COMPQUIET(skipframes, 0);
#endif
}
/*
* __os_stack_text --
* 'Print' the current stack into a char text buffer.
*
* PUBLIC: void __os_stack_text
* PUBLIC: __P((const ENV *, char *, size_t, unsigned, unsigned));
*/
void
__os_stack_text(env, result, bufsize, nframes, skip)
const ENV *env;
char *result;
size_t bufsize;
unsigned nframes;
unsigned skip;
{
DB_MSGBUF mb;
DB_MSGBUF_INIT(&mb);
mb.buf = mb.cur = result;
mb.len = bufsize;
F_SET(&mb, DB_MSGBUF_PREALLOCATED);
__os_stack_msgadd(env, &mb, nframes, skip, NULL);
}
/*
* __os_stack_save --
* Save a certain range of stack frames into the frames argument.
*
* PUBLIC: int __os_stack_save __P((const ENV *, unsigned, void **));
*/
int
__os_stack_save(env, nframes, frames)
const ENV *env;
unsigned nframes;
void **frames;
{
COMPQUIET(env, NULL);
#if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
/*
* Solaris and the GNU C library support this interface. Solaris
* has additional interfaces (printstack and walkcontext), I don't
* know if they offer any additional value or not.
*/
return ((int) backtrace(frames, nframes));
#else
COMPQUIET(nframes, 0);
COMPQUIET(frames, NULL);
return (0);
#endif
}
/*
* __os_stack_msgadd --
* Decode a stack and add it to a DB_MSGBUF. The stack was either
* previously obtained stack, e.g., from __os_stack_save(), or if it is
* null, the current stack is fetched here.
*
* PUBLIC: void __os_stack_msgadd
* PUBLIC: __P((const ENV *, DB_MSGBUF *, unsigned, unsigned, void **));
*/
void
__os_stack_msgadd(env, mb, totalframes, skipframes, stack)
const ENV *env;
DB_MSGBUF *mb;
unsigned totalframes;
unsigned skipframes;
void **stack;
{
#if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
char **strings;
void *local_frames[__DB_STACK_MAXFRAMES];
unsigned i;
if (stack == NULL) {
stack = local_frames;
if (totalframes > __DB_STACK_MAXFRAMES)
totalframes = __DB_STACK_MAXFRAMES;
totalframes = backtrace(local_frames, totalframes);
skipframes++;
}
/*
* Solaris and the GNU C library support this interface. Solaris
* has additional interfaces (printstack and walkcontext) which have
* know if they offer any additional value or not.
*/
strings = backtrace_symbols(stack, totalframes);
for (i = skipframes; i < totalframes; ++i)
__db_msgadd((ENV *)env, mb, "\t%s\n", strings[i]);
free(strings);
#else
COMPQUIET(env, NULL);
COMPQUIET(mb, NULL);
COMPQUIET(totalframes, 0);
COMPQUIET(skipframes, 0);
COMPQUIET(stack, NULL);
#endif
}
|