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