xref: /AOO41X/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