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