1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "sal/types.h"
25
26
27 #ifdef SOLARIS
28
29 #include <dlfcn.h>
30 #include <pthread.h>
31 #include <setjmp.h>
32 #include <stdio.h>
33 #include <sys/frame.h>
34 #include "backtrace.h"
35
36 #if defined(SPARC)
37
38 #if defined IS_LP64
39
40 #define FRAME_PTR_OFFSET 1
41 #define FRAME_OFFSET 0
42 #define STACK_BIAS 0x7ff
43
44 #else
45
46 #define FRAME_PTR_OFFSET 1
47 #define FRAME_OFFSET 0
48 #define STACK_BIAS 0
49
50 #endif
51
52 #elif defined( INTEL )
53
54 #define FRAME_PTR_OFFSET 3
55 #define FRAME_OFFSET 0
56 #define STACK_BIAS 0
57
58 #else
59
60 #error Unknown Solaris target platform.
61
62 #endif /* defined SPARC or INTEL */
63
64
backtrace(void ** buffer,int max_frames)65 int backtrace( void **buffer, int max_frames )
66 {
67 jmp_buf ctx;
68 long fpval;
69 struct frame *fp;
70 int i;
71
72 /* flush register windows */
73 #ifdef SPARC
74 asm("ta 3");
75 #endif
76
77 /* get stack- and framepointer */
78 setjmp(ctx);
79
80 fpval = ((long*)(ctx))[FRAME_PTR_OFFSET];
81 fp = (struct frame*)((char*)(fpval) + STACK_BIAS);
82
83 for (i = 0; (i < FRAME_OFFSET) && (fp != NULL); i++)
84 fp = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
85
86 /* iterate through backtrace */
87 for (i = 0; (fp != NULL) && (fp->fr_savpc != 0) && (i < max_frames); i++)
88 {
89 /* saved (prev) frame */
90 struct frame * prev = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
91
92 /* store frame */
93 *(buffer++) = (void*)(fp->fr_savpc);
94
95 /* prev frame (w/ stack growing top down) */
96 fp = (prev > fp) ? prev : 0;
97 }
98
99 /* return number of frames stored */
100 return i;
101 }
102
backtrace_symbols_fd(void ** buffer,int size,int fd)103 void backtrace_symbols_fd( void **buffer, int size, int fd )
104 {
105 FILE *fp = fdopen( fd, "w" );
106
107 if ( fp )
108 {
109 void **pFramePtr;
110
111 for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
112 {
113 Dl_info dli;
114 ptrdiff_t offset;
115
116 if ( 0 != dladdr( *pFramePtr, &dli ) )
117 {
118 if ( dli.dli_fname && dli.dli_fbase )
119 {
120 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
121 fprintf( fp, "%s+0x%" SAL_PRI_PTRDIFFT "x", dli.dli_fname, offset );
122 }
123 if ( dli.dli_sname && dli.dli_saddr )
124 {
125 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
126 fprintf( fp, "(%s+0x%" SAL_PRI_PTRDIFFT "x)", dli.dli_sname, offset );
127 }
128 }
129 fprintf( fp, "[%p]\n", *pFramePtr );
130 }
131
132 fflush( fp );
133 fclose( fp );
134 }
135 }
136
137 #endif /* defined SOLARIS */
138
139
140 #if defined FREEBSD || defined NETBSD
141 #include <dlfcn.h>
142 #include <pthread.h>
143 #include <setjmp.h>
144 #include <stddef.h>
145 #include <stdio.h>
146 #include "backtrace.h"
147
148 #define FRAME_PTR_OFFSET 3
149 #define FRAME_OFFSET 0
150
backtrace(void ** buffer,int max_frames)151 int backtrace( void **buffer, int max_frames )
152 {
153 struct frame *fp;
154 jmp_buf ctx;
155 int i;
156 /* get stack- and framepointer */
157 setjmp(ctx);
158 fp = (struct frame*)(((size_t*)(ctx))[FRAME_PTR_OFFSET]);
159 for ( i=0; (i<FRAME_OFFSET) && (fp!=NULL); i++)
160 fp = fp->fr_savfp;
161 /* iterate through backtrace */
162 for (i=0; fp && fp->fr_savpc && i<max_frames; i++)
163 {
164 /* store frame */
165 *(buffer++) = (void *)fp->fr_savpc;
166 /* next frame */
167 fp=fp->fr_savfp;
168 }
169 return i;
170 }
171
backtrace_symbols_fd(void ** buffer,int size,int fd)172 void backtrace_symbols_fd( void **buffer, int size, int fd )
173 {
174 FILE *fp = fdopen( fd, "w" );
175
176 if ( fp )
177 {
178 void **pFramePtr;
179 for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
180 {
181 Dl_info dli;
182 ptrdiff_t offset;
183
184 if ( 0 != dladdr( *pFramePtr, &dli ) )
185 {
186 if ( dli.dli_fname && dli.dli_fbase )
187 {
188 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
189 fprintf( fp, "%s+0x%" SAL_PRI_PTRDIFFT "x", dli.dli_fname, offset );
190 }
191 if ( dli.dli_sname && dli.dli_saddr )
192 {
193 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
194 fprintf( fp, "(%s+0x%" SAL_PRI_PTRDIFFT "x)", dli.dli_sname, offset );
195 }
196 }
197 fprintf( fp, "[%p]\n", *pFramePtr );
198 }
199 fflush( fp );
200 fclose( fp );
201 }
202 }
203 #endif /* defined FREEBSD */
204
205 #ifdef LINUX
206
207 #ifndef _GNU_SOURCE
208 #define _GNU_SOURCE
209 #endif
210
211 #include <dlfcn.h>
212 #include <pthread.h>
213 #include <setjmp.h>
214 #include <stdio.h>
215 #include "backtrace.h"
216
217 #if defined(SPARC)
218
219 #define FRAME_PTR_OFFSET 1
220 #define FRAME_OFFSET 0
221
222 #else
223
224 #error Unknown Linux target platform.
225
226 #endif /* defined SPARC or INTEL */
227
228 typedef int ptrdiff_t;
229
backtrace(void ** buffer,int max_frames)230 int backtrace( void **buffer, int max_frames )
231 {
232 struct frame *fp;
233 jmp_buf ctx;
234 int i;
235
236 /* flush register windows */
237 #ifdef SPARC
238 asm("ta 3");
239 #endif
240 /* get stack- and framepointer */
241 setjmp(ctx);
242 fp = (struct frame*)(((size_t*)(ctx))[FRAME_PTR_OFFSET]);
243 for ( i=0; (i<FRAME_OFFSET) && (fp!=NULL); i++)
244 fp = fp->fr_savfp;
245
246 /* iterate through backtrace */
247 for (i=0; fp && fp->fr_savpc && i<max_frames; i++)
248 {
249 /* store frame */
250 *(buffer++) = (void *)fp->fr_savpc;
251 /* next frame */
252 fp=fp->fr_savfp;
253 }
254 return i;
255 }
256
backtrace_symbols_fd(void ** buffer,int size,int fd)257 void backtrace_symbols_fd( void **buffer, int size, int fd )
258 {
259 FILE *fp = fdopen( fd, "w" );
260
261 if ( fp )
262 {
263 void **pFramePtr;
264
265 for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
266 {
267 Dl_info dli;
268 ptrdiff_t offset;
269
270 if ( 0 != dladdr( *pFramePtr, &dli ) )
271 {
272 if ( dli.dli_fname && dli.dli_fbase )
273 {
274 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
275 fprintf( fp, "%s+0x%" SAL_PRI_PTRDIFFT "x", dli.dli_fname, offset );
276 }
277 if ( dli.dli_sname && dli.dli_saddr )
278 {
279 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
280 fprintf( fp, "(%s+0x%" SAL_PRI_PTRDIFFT "x)", dli.dli_sname, offset );
281 }
282 }
283 fprintf( fp, "[%p]\n", *pFramePtr );
284 }
285
286 fflush( fp );
287 fclose( fp );
288 }
289 }
290
291 #endif /* defined LINUX */
292
293 #if defined( MACOSX )
294
295 #include <dlfcn.h>
296 #include <stdio.h>
297 #include "backtrace.h"
298
299 typedef unsigned ptrdiff_t;
300
301 /* glib backtrace is only available on MacOsX 10.5 or higher
302 so we do it on our own */
303
backtrace(void ** buffer,int max_frames)304 int backtrace( void **buffer, int max_frames )
305 {
306 void **frame = (void **)__builtin_frame_address(0);
307 void **bp = ( void **)(*frame);
308 void *ip = frame[1];
309 int i;
310
311 for ( i = 0; bp && ip && i < max_frames; i++ )
312 {
313 *(buffer++) = ip;
314
315 ip = bp[1];
316 bp = (void**)(bp[0]);
317 }
318
319 return i;
320 }
321
322
backtrace_symbols_fd(void ** buffer,int size,int fd)323 void backtrace_symbols_fd( void **buffer, int size, int fd )
324 {
325 FILE *fp = fdopen( fd, "w" );
326
327 if ( fp )
328 {
329 void **pFramePtr;
330
331 for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
332 {
333 Dl_info dli;
334 ptrdiff_t offset;
335
336 if ( 0 != dladdr( *pFramePtr, &dli ) )
337 {
338 if ( dli.dli_fname && dli.dli_fbase )
339 {
340 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
341 fprintf( fp, "%s+0x%" SAL_PRI_PTRDIFFT "x", dli.dli_fname, offset );
342 }
343 if ( dli.dli_sname && dli.dli_saddr )
344 {
345 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
346 fprintf( fp, "(%s+0x%" SAL_PRI_PTRDIFFT "x)", dli.dli_sname, offset );
347 }
348 }
349 fprintf( fp, "[%p]\n", *pFramePtr );
350 }
351
352 fflush( fp );
353 fclose( fp );
354 }
355 }
356
357 #endif /* defined MACOSX */
358