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