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 3 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 #if defined X86_64 188 fprintf( fp, "%s+0x%lx", dli.dli_fname, offset ); 189 #else 190 fprintf( fp, "%s+0x%x", dli.dli_fname, offset ); 191 #endif 192 } 193 if ( dli.dli_sname && dli.dli_saddr ) 194 { 195 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr; 196 #if defined X86_64 197 fprintf( fp, "(%s+0x%lx)", dli.dli_sname, offset ); 198 #else 199 fprintf( fp, "(%s+0x%x)", dli.dli_sname, offset ); 200 #endif 201 } 202 } 203 fprintf( fp, "[0x%p]\n", *pFramePtr ); 204 } 205 fflush( fp ); 206 fclose( fp ); 207 } 208 } 209 #endif /* defined FREEBSD */ 210 211 #ifdef LINUX 212 213 #ifndef _GNU_SOURCE 214 #define _GNU_SOURCE 215 #endif 216 217 #include <dlfcn.h> 218 #include <pthread.h> 219 #include <setjmp.h> 220 #include <stdio.h> 221 #include "backtrace.h" 222 223 #if defined(SPARC) 224 225 #define FRAME_PTR_OFFSET 1 226 #define FRAME_OFFSET 0 227 228 #else 229 230 #error Unknown Linux target platform. 231 232 #endif /* defined SPARC or INTEL */ 233 234 typedef int ptrdiff_t; 235 236 int backtrace( void **buffer, int max_frames ) 237 { 238 struct frame *fp; 239 jmp_buf ctx; 240 int i; 241 242 /* flush register windows */ 243 #ifdef SPARC 244 asm("ta 3"); 245 #endif 246 /* get stack- and framepointer */ 247 setjmp(ctx); 248 fp = (struct frame*)(((size_t*)(ctx))[FRAME_PTR_OFFSET]); 249 for ( i=0; (i<FRAME_OFFSET) && (fp!=0); i++) 250 fp = fp->fr_savfp; 251 252 /* iterate through backtrace */ 253 for (i=0; fp && fp->fr_savpc && i<max_frames; i++) 254 { 255 /* store frame */ 256 *(buffer++) = (void *)fp->fr_savpc; 257 /* next frame */ 258 fp=fp->fr_savfp; 259 } 260 return i; 261 } 262 263 void backtrace_symbols_fd( void **buffer, int size, int fd ) 264 { 265 FILE *fp = fdopen( fd, "w" ); 266 267 if ( fp ) 268 { 269 void **pFramePtr; 270 271 for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- ) 272 { 273 Dl_info dli; 274 ptrdiff_t offset; 275 276 if ( 0 != dladdr( *pFramePtr, &dli ) ) 277 { 278 if ( dli.dli_fname && dli.dli_fbase ) 279 { 280 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase; 281 fprintf( fp, "%s+0x%x", dli.dli_fname, offset ); 282 } 283 if ( dli.dli_sname && dli.dli_saddr ) 284 { 285 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr; 286 fprintf( fp, "(%s+0x%x)", dli.dli_sname, offset ); 287 } 288 } 289 fprintf( fp, "[0x%x]\n", *pFramePtr ); 290 } 291 292 fflush( fp ); 293 fclose( fp ); 294 } 295 } 296 297 #endif /* defined LINUX */ 298 299 #if defined( MACOSX ) 300 301 #include <dlfcn.h> 302 #include <stdio.h> 303 #include "backtrace.h" 304 305 typedef unsigned ptrdiff_t; 306 307 /* glib backtrace is only available on MacOsX 10.5 or higher 308 so we do it on our own */ 309 310 int backtrace( void **buffer, int max_frames ) 311 { 312 void **frame = (void **)__builtin_frame_address(0); 313 void **bp = ( void **)(*frame); 314 void *ip = frame[1]; 315 int i; 316 317 for ( i = 0; bp && ip && i < max_frames; i++ ) 318 { 319 *(buffer++) = ip; 320 321 ip = bp[1]; 322 bp = (void**)(bp[0]); 323 } 324 325 return i; 326 } 327 328 329 void backtrace_symbols_fd( void **buffer, int size, int fd ) 330 { 331 FILE *fp = fdopen( fd, "w" ); 332 333 if ( fp ) 334 { 335 void **pFramePtr; 336 337 for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- ) 338 { 339 Dl_info dli; 340 ptrdiff_t offset; 341 342 if ( 0 != dladdr( *pFramePtr, &dli ) ) 343 { 344 if ( dli.dli_fname && dli.dli_fbase ) 345 { 346 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase; 347 fprintf( fp, "%s+0x%x", dli.dli_fname, offset ); 348 } 349 if ( dli.dli_sname && dli.dli_saddr ) 350 { 351 offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr; 352 fprintf( fp, "(%s+0x%x)", dli.dli_sname, offset ); 353 } 354 } 355 fprintf( fp, "[0x%x]\n", (unsigned int)*pFramePtr ); 356 } 357 358 fflush( fp ); 359 fclose( fp ); 360 } 361 } 362 363 #endif /* defined MACOSX */ 364