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