merged tag ooo/DEV300_m102
[LibreOffice.git] / sal / osl / unx / backtrace.c
blob00156b80f1d68ac36fd0e2e3883e89cff05bcd05
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
29 #ifdef SOLARIS
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"
38 #if defined(SPARC)
40 #if defined IS_LP64
42 #define FRAME_PTR_OFFSET 1
43 #define FRAME_OFFSET 0
44 #define STACK_BIAS 0x7ff
46 #else
48 #define FRAME_PTR_OFFSET 1
49 #define FRAME_OFFSET 0
50 #define STACK_BIAS 0
52 #endif
54 #elif defined( INTEL )
56 #define FRAME_PTR_OFFSET 3
57 #define FRAME_OFFSET 0
58 #define STACK_BIAS 0
60 #else
62 #error Unknown Solaris target platform.
64 #endif /* defined SPARC or INTEL */
67 int backtrace( void **buffer, int max_frames )
69 jmp_buf ctx;
70 long fpval;
71 struct frame *fp;
72 int i;
74 /* flush register windows */
75 #ifdef SPARC
76 asm("ta 3");
77 #endif
79 /* get stack- and framepointer */
80 setjmp(ctx);
82 fpval = ((long*)(ctx))[FRAME_PTR_OFFSET];
83 fp = (struct frame*)((char*)(fpval) + STACK_BIAS);
85 for (i = 0; (i < FRAME_OFFSET) && (fp != 0); i++)
86 fp = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
88 /* iterate through backtrace */
89 for (i = 0; (fp != 0) && (fp->fr_savpc != 0) && (i < max_frames); i++)
91 /* saved (prev) frame */
92 struct frame * prev = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
94 /* store frame */
95 *(buffer++) = (void*)(fp->fr_savpc);
97 /* prev frame (w/ stack growing top down) */
98 fp = (prev > fp) ? prev : 0;
101 /* return number of frames stored */
102 return i;
105 void backtrace_symbols_fd( void **buffer, int size, int fd )
107 FILE *fp = fdopen( fd, "w" );
109 if ( fp )
111 void **pFramePtr;
113 for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
115 Dl_info dli;
116 ptrdiff_t offset;
118 if ( 0 != dladdr( *pFramePtr, &dli ) )
120 if ( dli.dli_fname && dli.dli_fbase )
122 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
123 fprintf( fp, "%s+0x%x", dli.dli_fname, offset );
125 if ( dli.dli_sname && dli.dli_saddr )
127 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
128 fprintf( fp, "(%s+0x%x)", dli.dli_sname, offset );
131 fprintf( fp, "[0x%x]\n", *pFramePtr );
134 fflush( fp );
135 fclose( fp );
139 #endif /* defined SOLARIS */
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"
150 #define FRAME_PTR_OFFSET 1
151 #define FRAME_OFFSET 0
153 int backtrace( void **buffer, int max_frames )
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++)
166 /* store frame */
167 *(buffer++) = (void *)fp->fr_savpc;
168 /* next frame */
169 fp=fp->fr_savfp;
171 return i;
174 void backtrace_symbols_fd( void **buffer, int size, int fd )
176 FILE *fp = fdopen( fd, "w" );
178 if ( fp )
180 void **pFramePtr;
181 for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
183 Dl_info dli;
184 ptrdiff_t offset;
186 if ( 0 != dladdr( *pFramePtr, &dli ) )
188 if ( dli.dli_fname && dli.dli_fbase )
190 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
191 fprintf( fp, "%s+0x%x", dli.dli_fname, offset );
193 if ( dli.dli_sname && dli.dli_saddr )
195 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
196 fprintf( fp, "(%s+0x%x)", dli.dli_sname, offset );
199 fprintf( fp, "[0x%x]\n", *pFramePtr );
201 fflush( fp );
202 fclose( fp );
205 #endif /* defined FREEBSD */
207 #ifdef LINUX
209 #ifndef _GNU_SOURCE
210 #define _GNU_SOURCE
211 #endif
213 #include <dlfcn.h>
214 #include <pthread.h>
215 #include <setjmp.h>
216 #include <stdio.h>
217 #include "backtrace.h"
219 #if defined(SPARC)
221 #define FRAME_PTR_OFFSET 1
222 #define FRAME_OFFSET 0
224 #else
226 #error Unknown Linux target platform.
228 #endif /* defined SPARC or INTEL */
230 typedef int ptrdiff_t;
232 int backtrace( void **buffer, int max_frames )
234 struct frame *fp;
235 jmp_buf ctx;
236 int i;
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;
248 /* iterate through backtrace */
249 for (i=0; fp && fp->fr_savpc && i<max_frames; i++)
251 /* store frame */
252 *(buffer++) = (void *)fp->fr_savpc;
253 /* next frame */
254 fp=fp->fr_savfp;
256 return i;
259 void backtrace_symbols_fd( void **buffer, int size, int fd )
261 FILE *fp = fdopen( fd, "w" );
263 if ( fp )
265 void **pFramePtr;
267 for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
269 Dl_info dli;
270 ptrdiff_t offset;
272 if ( 0 != dladdr( *pFramePtr, &dli ) )
274 if ( dli.dli_fname && dli.dli_fbase )
276 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
277 fprintf( fp, "%s+0x%x", dli.dli_fname, offset );
279 if ( dli.dli_sname && dli.dli_saddr )
281 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
282 fprintf( fp, "(%s+0x%x)", dli.dli_sname, offset );
285 fprintf( fp, "[0x%x]\n", *pFramePtr );
288 fflush( fp );
289 fclose( fp );
293 #endif /* defined LINUX */
295 #if defined( MACOSX )
297 #include <dlfcn.h>
298 #include <stdio.h>
299 #include "backtrace.h"
301 typedef unsigned ptrdiff_t;
303 /* glib backtrace is only available on MacOsX 10.5 or higher
304 so we do it on our own */
306 int backtrace( void **buffer, int max_frames )
308 void **frame = (void **)__builtin_frame_address(0);
309 void **bp = ( void **)(*frame);
310 void *ip = frame[1];
311 int i;
313 for ( i = 0; bp && ip && i < max_frames; i++ )
315 *(buffer++) = ip;
317 ip = bp[1];
318 bp = (void**)(bp[0]);
321 return i;
325 void backtrace_symbols_fd( void **buffer, int size, int fd )
327 FILE *fp = fdopen( fd, "w" );
329 if ( fp )
331 void **pFramePtr;
333 for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
335 Dl_info dli;
336 ptrdiff_t offset;
338 if ( 0 != dladdr( *pFramePtr, &dli ) )
340 if ( dli.dli_fname && dli.dli_fbase )
342 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
343 fprintf( fp, "%s+0x%x", dli.dli_fname, offset );
345 if ( dli.dli_sname && dli.dli_saddr )
347 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
348 fprintf( fp, "(%s+0x%x)", dli.dli_sname, offset );
351 fprintf( fp, "[0x%x]\n", (unsigned int)*pFramePtr );
354 fflush( fp );
355 fclose( fp );
359 #endif /* defined MACOSX */