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