xref: /trunk/main/sal/osl/unx/backtrace.c (revision 9664d1e0736bd476d60a744c560a8594e973e313)
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
10cdf0e10cSrcweir  *
11647f063dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
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.
19cdf0e10cSrcweir  *
20647f063dSAndrew Rist  *************************************************************/
21647f063dSAndrew Rist 
22*9664d1e0Smseidel 
23*9664d1e0Smseidel 
2454356271SDamjan Jovanovic #include "sal/types.h"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #ifdef SOLARIS
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <dlfcn.h>
30cdf0e10cSrcweir #include <pthread.h>
31cdf0e10cSrcweir #include <setjmp.h>
32cdf0e10cSrcweir #include <stdio.h>
33cdf0e10cSrcweir #include <sys/frame.h>
34cdf0e10cSrcweir #include "backtrace.h"
35cdf0e10cSrcweir 
36cdf0e10cSrcweir #if defined(SPARC)
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #if defined IS_LP64
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #define FRAME_PTR_OFFSET 1
41cdf0e10cSrcweir #define FRAME_OFFSET     0
42cdf0e10cSrcweir #define STACK_BIAS       0x7ff
43cdf0e10cSrcweir 
44cdf0e10cSrcweir #else
45cdf0e10cSrcweir 
46cdf0e10cSrcweir #define FRAME_PTR_OFFSET 1
47cdf0e10cSrcweir #define FRAME_OFFSET     0
48cdf0e10cSrcweir #define STACK_BIAS       0
49cdf0e10cSrcweir 
50cdf0e10cSrcweir #endif
51cdf0e10cSrcweir 
52cdf0e10cSrcweir #elif defined( INTEL )
53cdf0e10cSrcweir 
54cdf0e10cSrcweir #define FRAME_PTR_OFFSET 3
55cdf0e10cSrcweir #define FRAME_OFFSET     0
56cdf0e10cSrcweir #define STACK_BIAS       0
57cdf0e10cSrcweir 
58cdf0e10cSrcweir #else
59cdf0e10cSrcweir 
60cdf0e10cSrcweir #error Unknown Solaris target platform.
61cdf0e10cSrcweir 
62cdf0e10cSrcweir #endif /* defined SPARC or INTEL */
63cdf0e10cSrcweir 
64cdf0e10cSrcweir 
backtrace(void ** buffer,int max_frames)65cdf0e10cSrcweir int backtrace( void **buffer, int max_frames )
66cdf0e10cSrcweir {
67cdf0e10cSrcweir     jmp_buf       ctx;
68cdf0e10cSrcweir     long          fpval;
69cdf0e10cSrcweir     struct frame *fp;
70cdf0e10cSrcweir     int i;
71cdf0e10cSrcweir 
72cdf0e10cSrcweir     /* flush register windows */
73cdf0e10cSrcweir #ifdef SPARC
74cdf0e10cSrcweir     asm("ta 3");
75cdf0e10cSrcweir #endif
76cdf0e10cSrcweir 
77cdf0e10cSrcweir     /* get stack- and framepointer */
78cdf0e10cSrcweir     setjmp(ctx);
79cdf0e10cSrcweir 
80cdf0e10cSrcweir     fpval = ((long*)(ctx))[FRAME_PTR_OFFSET];
81cdf0e10cSrcweir     fp = (struct frame*)((char*)(fpval) + STACK_BIAS);
82cdf0e10cSrcweir 
83509a48ffSpfg     for (i = 0; (i < FRAME_OFFSET) && (fp != NULL); i++)
84cdf0e10cSrcweir         fp = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
85cdf0e10cSrcweir 
86cdf0e10cSrcweir     /* iterate through backtrace */
87509a48ffSpfg     for (i = 0; (fp != NULL) && (fp->fr_savpc != 0) && (i < max_frames); i++)
88cdf0e10cSrcweir     {
89cdf0e10cSrcweir         /* saved (prev) frame */
90cdf0e10cSrcweir         struct frame * prev = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
91cdf0e10cSrcweir 
92cdf0e10cSrcweir         /* store frame */
93cdf0e10cSrcweir         *(buffer++) = (void*)(fp->fr_savpc);
94cdf0e10cSrcweir 
95cdf0e10cSrcweir         /* prev frame (w/ stack growing top down) */
96cdf0e10cSrcweir         fp = (prev > fp) ? prev : 0;
97cdf0e10cSrcweir     }
98cdf0e10cSrcweir 
99cdf0e10cSrcweir     /* return number of frames stored */
100cdf0e10cSrcweir     return i;
101cdf0e10cSrcweir }
102cdf0e10cSrcweir 
backtrace_symbols_fd(void ** buffer,int size,int fd)103cdf0e10cSrcweir void backtrace_symbols_fd( void **buffer, int size, int fd )
104cdf0e10cSrcweir {
105cdf0e10cSrcweir     FILE    *fp = fdopen( fd, "w" );
106cdf0e10cSrcweir 
107cdf0e10cSrcweir     if ( fp )
108cdf0e10cSrcweir     {
109cdf0e10cSrcweir         void **pFramePtr;
110cdf0e10cSrcweir 
111cdf0e10cSrcweir         for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
112cdf0e10cSrcweir         {
113cdf0e10cSrcweir             Dl_info     dli;
114cdf0e10cSrcweir             ptrdiff_t   offset;
115cdf0e10cSrcweir 
116cdf0e10cSrcweir             if ( 0 != dladdr( *pFramePtr, &dli ) )
117cdf0e10cSrcweir             {
118cdf0e10cSrcweir                 if ( dli.dli_fname && dli.dli_fbase )
119cdf0e10cSrcweir                 {
120cdf0e10cSrcweir                     offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
12140ae658cSDamjan Jovanovic                     fprintf( fp, "%s+0x%" SAL_PRI_PTRDIFFT "x", dli.dli_fname, offset );
122cdf0e10cSrcweir                 }
123cdf0e10cSrcweir                 if ( dli.dli_sname && dli.dli_saddr )
124cdf0e10cSrcweir                 {
125cdf0e10cSrcweir                     offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
12640ae658cSDamjan Jovanovic                     fprintf( fp, "(%s+0x%" SAL_PRI_PTRDIFFT "x)", dli.dli_sname, offset );
127cdf0e10cSrcweir                 }
128cdf0e10cSrcweir             }
1296a5321abSDamjan Jovanovic             fprintf( fp, "[%p]\n", *pFramePtr );
130cdf0e10cSrcweir         }
131cdf0e10cSrcweir 
132cdf0e10cSrcweir         fflush( fp );
133cdf0e10cSrcweir         fclose( fp );
134cdf0e10cSrcweir     }
135cdf0e10cSrcweir }
136cdf0e10cSrcweir 
137cdf0e10cSrcweir #endif /* defined SOLARIS */
138cdf0e10cSrcweir 
139cdf0e10cSrcweir 
140cdf0e10cSrcweir #if defined FREEBSD || defined NETBSD
141cdf0e10cSrcweir #include <dlfcn.h>
142cdf0e10cSrcweir #include <pthread.h>
143cdf0e10cSrcweir #include <setjmp.h>
144cdf0e10cSrcweir #include <stddef.h>
145cdf0e10cSrcweir #include <stdio.h>
146cdf0e10cSrcweir #include "backtrace.h"
147cdf0e10cSrcweir 
1485258b990SDamjan Jovanovic #define FRAME_PTR_OFFSET 3
149cdf0e10cSrcweir #define FRAME_OFFSET 0
150cdf0e10cSrcweir 
backtrace(void ** buffer,int max_frames)151cdf0e10cSrcweir int backtrace( void **buffer, int max_frames )
152cdf0e10cSrcweir {
153cdf0e10cSrcweir     struct frame *fp;
154cdf0e10cSrcweir     jmp_buf ctx;
155cdf0e10cSrcweir     int i;
156cdf0e10cSrcweir     /* get stack- and framepointer */
157cdf0e10cSrcweir     setjmp(ctx);
158cdf0e10cSrcweir     fp = (struct frame*)(((size_t*)(ctx))[FRAME_PTR_OFFSET]);
159509a48ffSpfg     for ( i=0; (i<FRAME_OFFSET) && (fp!=NULL); i++)
160cdf0e10cSrcweir         fp = fp->fr_savfp;
161cdf0e10cSrcweir     /* iterate through backtrace */
162cdf0e10cSrcweir     for (i=0; fp && fp->fr_savpc && i<max_frames; i++)
163cdf0e10cSrcweir     {
164cdf0e10cSrcweir         /* store frame */
165cdf0e10cSrcweir         *(buffer++) = (void *)fp->fr_savpc;
166cdf0e10cSrcweir         /* next frame */
167cdf0e10cSrcweir         fp=fp->fr_savfp;
168cdf0e10cSrcweir     }
169cdf0e10cSrcweir     return i;
170cdf0e10cSrcweir }
171cdf0e10cSrcweir 
backtrace_symbols_fd(void ** buffer,int size,int fd)172cdf0e10cSrcweir void backtrace_symbols_fd( void **buffer, int size, int fd )
173cdf0e10cSrcweir {
174cdf0e10cSrcweir     FILE    *fp = fdopen( fd, "w" );
175cdf0e10cSrcweir 
176cdf0e10cSrcweir     if ( fp )
177cdf0e10cSrcweir     {
178cdf0e10cSrcweir         void **pFramePtr;
179cdf0e10cSrcweir         for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
180cdf0e10cSrcweir         {
181cdf0e10cSrcweir             Dl_info     dli;
182cdf0e10cSrcweir             ptrdiff_t   offset;
183cdf0e10cSrcweir 
184cdf0e10cSrcweir             if ( 0 != dladdr( *pFramePtr, &dli ) )
185cdf0e10cSrcweir             {
186cdf0e10cSrcweir                 if ( dli.dli_fname && dli.dli_fbase )
187cdf0e10cSrcweir                 {
188cdf0e10cSrcweir                     offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
18954356271SDamjan Jovanovic                     fprintf( fp, "%s+0x%" SAL_PRI_PTRDIFFT "x", dli.dli_fname, offset );
190cdf0e10cSrcweir                 }
191cdf0e10cSrcweir                 if ( dli.dli_sname && dli.dli_saddr )
192cdf0e10cSrcweir                 {
193cdf0e10cSrcweir                     offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
19454356271SDamjan Jovanovic                     fprintf( fp, "(%s+0x%" SAL_PRI_PTRDIFFT "x)", dli.dli_sname, offset );
195cdf0e10cSrcweir                 }
196cdf0e10cSrcweir             }
1976a5321abSDamjan Jovanovic             fprintf( fp, "[%p]\n", *pFramePtr );
198cdf0e10cSrcweir         }
199cdf0e10cSrcweir         fflush( fp );
200cdf0e10cSrcweir         fclose( fp );
201cdf0e10cSrcweir     }
202cdf0e10cSrcweir }
203cdf0e10cSrcweir #endif /* defined FREEBSD */
204cdf0e10cSrcweir 
205cdf0e10cSrcweir #ifdef LINUX
206cdf0e10cSrcweir 
207cdf0e10cSrcweir #ifndef _GNU_SOURCE
208cdf0e10cSrcweir #define _GNU_SOURCE
209cdf0e10cSrcweir #endif
210cdf0e10cSrcweir 
211cdf0e10cSrcweir #include <dlfcn.h>
212cdf0e10cSrcweir #include <pthread.h>
213cdf0e10cSrcweir #include <setjmp.h>
214cdf0e10cSrcweir #include <stdio.h>
215cdf0e10cSrcweir #include "backtrace.h"
216cdf0e10cSrcweir 
217cdf0e10cSrcweir #if defined(SPARC)
218cdf0e10cSrcweir 
219cdf0e10cSrcweir #define FRAME_PTR_OFFSET 1
220cdf0e10cSrcweir #define FRAME_OFFSET 0
221cdf0e10cSrcweir 
222cdf0e10cSrcweir #else
223cdf0e10cSrcweir 
224cdf0e10cSrcweir #error Unknown Linux target platform.
225cdf0e10cSrcweir 
226cdf0e10cSrcweir #endif /* defined SPARC or INTEL */
227cdf0e10cSrcweir 
228cdf0e10cSrcweir typedef int ptrdiff_t;
229cdf0e10cSrcweir 
backtrace(void ** buffer,int max_frames)230cdf0e10cSrcweir int backtrace( void **buffer, int max_frames )
231cdf0e10cSrcweir {
232cdf0e10cSrcweir     struct frame *fp;
233cdf0e10cSrcweir     jmp_buf ctx;
234cdf0e10cSrcweir     int i;
235cdf0e10cSrcweir 
236cdf0e10cSrcweir     /* flush register windows */
237cdf0e10cSrcweir #ifdef SPARC
238cdf0e10cSrcweir     asm("ta 3");
239cdf0e10cSrcweir #endif
240cdf0e10cSrcweir     /* get stack- and framepointer */
241cdf0e10cSrcweir     setjmp(ctx);
242cdf0e10cSrcweir     fp = (struct frame*)(((size_t*)(ctx))[FRAME_PTR_OFFSET]);
243509a48ffSpfg     for ( i=0; (i<FRAME_OFFSET) && (fp!=NULL); i++)
244cdf0e10cSrcweir         fp = fp->fr_savfp;
245cdf0e10cSrcweir 
246cdf0e10cSrcweir     /* iterate through backtrace */
247cdf0e10cSrcweir     for (i=0; fp && fp->fr_savpc && i<max_frames; i++)
248cdf0e10cSrcweir     {
249cdf0e10cSrcweir         /* store frame */
250cdf0e10cSrcweir         *(buffer++) = (void *)fp->fr_savpc;
251cdf0e10cSrcweir         /* next frame */
252cdf0e10cSrcweir         fp=fp->fr_savfp;
253cdf0e10cSrcweir     }
254cdf0e10cSrcweir     return i;
255cdf0e10cSrcweir }
256cdf0e10cSrcweir 
backtrace_symbols_fd(void ** buffer,int size,int fd)257cdf0e10cSrcweir void backtrace_symbols_fd( void **buffer, int size, int fd )
258cdf0e10cSrcweir {
259cdf0e10cSrcweir     FILE    *fp = fdopen( fd, "w" );
260cdf0e10cSrcweir 
261cdf0e10cSrcweir     if ( fp )
262cdf0e10cSrcweir     {
263cdf0e10cSrcweir         void **pFramePtr;
264cdf0e10cSrcweir 
265cdf0e10cSrcweir         for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
266cdf0e10cSrcweir         {
267cdf0e10cSrcweir             Dl_info     dli;
268cdf0e10cSrcweir             ptrdiff_t   offset;
269cdf0e10cSrcweir 
270cdf0e10cSrcweir             if ( 0 != dladdr( *pFramePtr, &dli ) )
271cdf0e10cSrcweir             {
272cdf0e10cSrcweir                 if ( dli.dli_fname && dli.dli_fbase )
273cdf0e10cSrcweir                 {
274cdf0e10cSrcweir                     offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
27540ae658cSDamjan Jovanovic                     fprintf( fp, "%s+0x%" SAL_PRI_PTRDIFFT "x", dli.dli_fname, offset );
276cdf0e10cSrcweir                 }
277cdf0e10cSrcweir                 if ( dli.dli_sname && dli.dli_saddr )
278cdf0e10cSrcweir                 {
279cdf0e10cSrcweir                     offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
28040ae658cSDamjan Jovanovic                     fprintf( fp, "(%s+0x%" SAL_PRI_PTRDIFFT "x)", dli.dli_sname, offset );
281cdf0e10cSrcweir                 }
282cdf0e10cSrcweir             }
2836a5321abSDamjan Jovanovic             fprintf( fp, "[%p]\n", *pFramePtr );
284cdf0e10cSrcweir         }
285cdf0e10cSrcweir 
286cdf0e10cSrcweir         fflush( fp );
287cdf0e10cSrcweir         fclose( fp );
288cdf0e10cSrcweir     }
289cdf0e10cSrcweir }
290cdf0e10cSrcweir 
291cdf0e10cSrcweir #endif /* defined LINUX */
292cdf0e10cSrcweir 
293cdf0e10cSrcweir #if defined( MACOSX )
294cdf0e10cSrcweir 
295cdf0e10cSrcweir #include <dlfcn.h>
296cdf0e10cSrcweir #include <stdio.h>
297cdf0e10cSrcweir #include "backtrace.h"
298cdf0e10cSrcweir 
299cdf0e10cSrcweir typedef unsigned     ptrdiff_t;
300cdf0e10cSrcweir 
301cdf0e10cSrcweir /* glib backtrace is only available on MacOsX 10.5 or higher
302cdf0e10cSrcweir    so we do it on our own */
303cdf0e10cSrcweir 
backtrace(void ** buffer,int max_frames)304cdf0e10cSrcweir int backtrace( void **buffer, int max_frames )
305cdf0e10cSrcweir {
306cdf0e10cSrcweir     void **frame = (void **)__builtin_frame_address(0);
307cdf0e10cSrcweir     void **bp = ( void **)(*frame);
308cdf0e10cSrcweir     void *ip = frame[1];
309cdf0e10cSrcweir     int i;
310cdf0e10cSrcweir 
311cdf0e10cSrcweir     for ( i = 0; bp && ip && i < max_frames; i++ )
312cdf0e10cSrcweir     {
313cdf0e10cSrcweir         *(buffer++) = ip;
314cdf0e10cSrcweir 
315cdf0e10cSrcweir         ip = bp[1];
316cdf0e10cSrcweir         bp = (void**)(bp[0]);
317cdf0e10cSrcweir     }
318cdf0e10cSrcweir 
319cdf0e10cSrcweir     return i;
320cdf0e10cSrcweir }
321cdf0e10cSrcweir 
322cdf0e10cSrcweir 
backtrace_symbols_fd(void ** buffer,int size,int fd)323cdf0e10cSrcweir void backtrace_symbols_fd( void **buffer, int size, int fd )
324cdf0e10cSrcweir {
325cdf0e10cSrcweir     FILE    *fp = fdopen( fd, "w" );
326cdf0e10cSrcweir 
327cdf0e10cSrcweir     if ( fp )
328cdf0e10cSrcweir     {
329cdf0e10cSrcweir         void **pFramePtr;
330cdf0e10cSrcweir 
331cdf0e10cSrcweir         for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
332cdf0e10cSrcweir         {
333cdf0e10cSrcweir             Dl_info     dli;
334cdf0e10cSrcweir             ptrdiff_t   offset;
335cdf0e10cSrcweir 
336cdf0e10cSrcweir             if ( 0 != dladdr( *pFramePtr, &dli ) )
337cdf0e10cSrcweir             {
338cdf0e10cSrcweir                 if ( dli.dli_fname && dli.dli_fbase )
339cdf0e10cSrcweir                 {
340cdf0e10cSrcweir                     offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
34140ae658cSDamjan Jovanovic                     fprintf( fp, "%s+0x%" SAL_PRI_PTRDIFFT "x", dli.dli_fname, offset );
342cdf0e10cSrcweir                 }
343cdf0e10cSrcweir                 if ( dli.dli_sname && dli.dli_saddr )
344cdf0e10cSrcweir                 {
345cdf0e10cSrcweir                     offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
34640ae658cSDamjan Jovanovic                     fprintf( fp, "(%s+0x%" SAL_PRI_PTRDIFFT "x)", dli.dli_sname, offset );
347cdf0e10cSrcweir                 }
348cdf0e10cSrcweir             }
3496a5321abSDamjan Jovanovic             fprintf( fp, "[%p]\n", *pFramePtr );
350cdf0e10cSrcweir         }
351cdf0e10cSrcweir 
352cdf0e10cSrcweir         fflush( fp );
353cdf0e10cSrcweir         fclose( fp );
354cdf0e10cSrcweir     }
355cdf0e10cSrcweir }
356cdf0e10cSrcweir 
357cdf0e10cSrcweir #endif /* defined MACOSX */
358