1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: backtrace.c,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
38 #include <sys/frame.h>
39 #include "backtrace.h"
45 #define FRAME_PTR_OFFSET 1
46 #define FRAME_OFFSET 0
47 #define STACK_BIAS 0x7ff
51 #define FRAME_PTR_OFFSET 1
52 #define FRAME_OFFSET 0
57 #elif defined( INTEL )
59 #define FRAME_PTR_OFFSET 3
60 #define FRAME_OFFSET 0
65 #error Unknown Solaris target platform.
67 #endif /* defined SPARC or INTEL */
70 int backtrace( void **buffer
, int max_frames
)
77 /* flush register windows */
82 /* get stack- and framepointer */
85 fpval
= ((long*)(ctx
))[FRAME_PTR_OFFSET
];
86 fp
= (struct frame
*)((char*)(fpval
) + STACK_BIAS
);
88 for (i
= 0; (i
< FRAME_OFFSET
) && (fp
!= 0); i
++)
89 fp
= (struct frame
*)((char*)(fp
->fr_savfp
) + STACK_BIAS
);
91 /* iterate through backtrace */
92 for (i
= 0; (fp
!= 0) && (fp
->fr_savpc
!= 0) && (i
< max_frames
); i
++)
94 /* saved (prev) frame */
95 struct frame
* prev
= (struct frame
*)((char*)(fp
->fr_savfp
) + STACK_BIAS
);
98 *(buffer
++) = (void*)(fp
->fr_savpc
);
100 /* prev frame (w/ stack growing top down) */
101 fp
= (prev
> fp
) ? prev
: 0;
104 /* return number of frames stored */
108 void backtrace_symbols_fd( void **buffer
, int size
, int fd
)
110 FILE *fp
= fdopen( fd
, "w" );
116 for ( pFramePtr
= buffer
; size
> 0 && pFramePtr
&& *pFramePtr
; pFramePtr
++, size
-- )
121 if ( 0 != dladdr( *pFramePtr
, &dli
) )
123 if ( dli
.dli_fname
&& dli
.dli_fbase
)
125 offset
= (ptrdiff_t)*pFramePtr
- (ptrdiff_t)dli
.dli_fbase
;
126 fprintf( fp
, "%s+0x%x", dli
.dli_fname
, offset
);
128 if ( dli
.dli_sname
&& dli
.dli_saddr
)
130 offset
= (ptrdiff_t)*pFramePtr
- (ptrdiff_t)dli
.dli_saddr
;
131 fprintf( fp
, "(%s+0x%x)", dli
.dli_sname
, offset
);
134 fprintf( fp
, "[0x%x]\n", *pFramePtr
);
142 #endif /* defined SOLARIS */
145 #if defined FREEBSD || defined NETBSD
151 #include "backtrace.h"
153 #define FRAME_PTR_OFFSET 1
154 #define FRAME_OFFSET 0
156 int backtrace( void **buffer
, int max_frames
)
161 /* get stack- and framepointer */
163 fp
= (struct frame
*)(((size_t*)(ctx
))[FRAME_PTR_OFFSET
]);
164 for ( i
=0; (i
<FRAME_OFFSET
) && (fp
!=0); i
++)
166 /* iterate through backtrace */
167 for (i
=0; fp
&& fp
->fr_savpc
&& i
<max_frames
; i
++)
170 *(buffer
++) = (void *)fp
->fr_savpc
;
177 void backtrace_symbols_fd( void **buffer
, int size
, int fd
)
179 FILE *fp
= fdopen( fd
, "w" );
184 for ( pFramePtr
= buffer
; size
> 0 && pFramePtr
&& *pFramePtr
; pFramePtr
++, size
-- )
189 if ( 0 != dladdr( *pFramePtr
, &dli
) )
191 if ( dli
.dli_fname
&& dli
.dli_fbase
)
193 offset
= (ptrdiff_t)*pFramePtr
- (ptrdiff_t)dli
.dli_fbase
;
194 fprintf( fp
, "%s+0x%x", dli
.dli_fname
, offset
);
196 if ( dli
.dli_sname
&& dli
.dli_saddr
)
198 offset
= (ptrdiff_t)*pFramePtr
- (ptrdiff_t)dli
.dli_saddr
;
199 fprintf( fp
, "(%s+0x%x)", dli
.dli_sname
, offset
);
202 fprintf( fp
, "[0x%x]\n", *pFramePtr
);
208 #endif /* defined FREEBSD */
212 #include <rld_interface.h>
213 #include <exception.h>
214 #include <sys/signal.h>
217 /* Need extra libs -lexc -ldwarf -lelf */
219 int backtrace( void **buffer
, int max_frames
)
221 struct sigcontext context
;
224 memset(&context
, 0, sizeof(struct sigcontext
));
226 exc_setjmp(&context
);
227 while(context
.sc_pc
!= 1 && i
< max_frames
) {
228 exc_unwind(&context
, 0);
229 if(context
.sc_pc
!= 1) {
230 *(buffer
++) = (void *)context
.sc_pc
;
237 void backtrace_symbols_fd( void **buffer
, int size
, int fd
)
239 FILE *fp
= fdopen( fd
, "w" );
240 struct sigcontext context
;
244 while(context
.sc_pc
!=1) {
245 if(context
.sc_pc
!= 1) {
246 exc_unwind_name(&context
, 0, &name
);
247 fprintf(fp
, " 0x%012lx %.100s\n", context
.sc_pc
, name
? name
: "<unknown function>");
256 #endif /* defined IRIX */
268 #include "backtrace.h"
272 #define FRAME_PTR_OFFSET 1
273 #define FRAME_OFFSET 0
277 #error Unknown Linux target platform.
279 #endif /* defined SPARC or INTEL */
281 typedef int ptrdiff_t;
283 int backtrace( void **buffer
, int max_frames
)
289 /* flush register windows */
293 /* get stack- and framepointer */
295 fp
= (struct frame
*)(((size_t*)(ctx
))[FRAME_PTR_OFFSET
]);
296 for ( i
=0; (i
<FRAME_OFFSET
) && (fp
!=0); i
++)
299 /* iterate through backtrace */
300 for (i
=0; fp
&& fp
->fr_savpc
&& i
<max_frames
; i
++)
303 *(buffer
++) = (void *)fp
->fr_savpc
;
310 void backtrace_symbols_fd( void **buffer
, int size
, int fd
)
312 FILE *fp
= fdopen( fd
, "w" );
318 for ( pFramePtr
= buffer
; size
> 0 && pFramePtr
&& *pFramePtr
; pFramePtr
++, size
-- )
323 if ( 0 != dladdr( *pFramePtr
, &dli
) )
325 if ( dli
.dli_fname
&& dli
.dli_fbase
)
327 offset
= (ptrdiff_t)*pFramePtr
- (ptrdiff_t)dli
.dli_fbase
;
328 fprintf( fp
, "%s+0x%x", dli
.dli_fname
, offset
);
330 if ( dli
.dli_sname
&& dli
.dli_saddr
)
332 offset
= (ptrdiff_t)*pFramePtr
- (ptrdiff_t)dli
.dli_saddr
;
333 fprintf( fp
, "(%s+0x%x)", dli
.dli_sname
, offset
);
336 fprintf( fp
, "[0x%x]\n", *pFramePtr
);
344 #endif /* defined LINUX */
346 #if defined( MACOSX )
350 #include "backtrace.h"
352 typedef unsigned ptrdiff_t;
354 /* glib backtrace is only available on MacOsX 10.5 or higher
355 so we do it on our own */
357 int backtrace( void **buffer
, int max_frames
)
359 void **frame
= (void **)__builtin_frame_address(0);
360 void **bp
= ( void **)(*frame
);
364 for ( i
= 0; bp
&& ip
&& i
< max_frames
; i
++ )
369 bp
= (void**)(bp
[0]);
376 void backtrace_symbols_fd( void **buffer
, int size
, int fd
)
378 FILE *fp
= fdopen( fd
, "w" );
384 for ( pFramePtr
= buffer
; size
> 0 && pFramePtr
&& *pFramePtr
; pFramePtr
++, size
-- )
389 if ( 0 != dladdr( *pFramePtr
, &dli
) )
391 if ( dli
.dli_fname
&& dli
.dli_fbase
)
393 offset
= (ptrdiff_t)*pFramePtr
- (ptrdiff_t)dli
.dli_fbase
;
394 fprintf( fp
, "%s+0x%x", dli
.dli_fname
, offset
);
396 if ( dli
.dli_sname
&& dli
.dli_saddr
)
398 offset
= (ptrdiff_t)*pFramePtr
- (ptrdiff_t)dli
.dli_saddr
;
399 fprintf( fp
, "(%s+0x%x)", dli
.dli_sname
, offset
);
402 fprintf( fp
, "[0x%x]\n", (unsigned int)*pFramePtr
);
410 #endif /* defined MACOSX */