00001 /* 00002 pstack.c -- asynchronous stack trace of a running process 00003 Copyright (c) 1999 Ross Thompson 00004 Author: Ross Thompson <ross@whatsis.com> 00005 Critical bug fix: Tim Waugh 00006 */ 00007 00008 /* 00009 This file is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 2 of the License, or 00012 (at your option) any later version. 00013 00014 This program is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00022 */ 00023 00024 /* RESTRICTIONS: 00025 00026 pstack currently works only on Linux, only on an x86 machine running 00027 32 bit ELF binaries (64 bit not supported). Also, for symbolic 00028 information, you need to use a GNU compiler to generate your 00029 program, and you can't strip symbols from the binaries. For thread 00030 information to be dumped, you have to use the debug-aware version 00031 of libpthread.so. (To check, run 'nm' on your libpthread.so, and 00032 make sure that the symbol "__pthread_threads_debug" is defined.) 00033 00034 The details of pulling stuff out of ELF files and running through 00035 program images is very platform specific, and I don't want to 00036 try to support modes or machine types I can't test in or on. 00037 If someone wants to generalize this to other architectures, I would 00038 be happy to help and coordinate the activity. Please send me whatever 00039 changes you make to support these machines, so that I can own the 00040 central font of all truth (at least as regards this program). 00041 00042 Thanks 00043 */ 00044 00045 #include <sys/types.h> 00046 #include <sys/stat.h> 00047 #include <sys/wait.h> 00048 #include <sys/ptrace.h> 00049 #include <asm/ptrace.h> 00050 00051 #include <assert.h> 00052 #include <fcntl.h> 00053 #include <link.h> 00054 #include <malloc.h> 00055 #include <string.h> 00056 #include <stdarg.h> 00057 #include <unistd.h> 00058 #include <stdlib.h> 00059 #include <stdio.h> 00060 #include <errno.h> 00061 #include <signal.h> 00062 #include <pthread.h> 00063 #include <limits.h> /* PTHREAD_THREADS_MAX */ 00064 00065 00066 #include <bfd.h> 00067 00068 #include "libiberty.h" 00069 00070 #include "pstack.h" /* just one function */ 00071 #include "budbg.h" /* binutils stuff related to debugging symbols. */ 00072 #include "bucomm.h" /* some common stuff */ 00073 #include "debug.h" /* and more binutils stuff... */ 00074 #include "budbg.h" 00075 #include "linuxthreads.h" /* LinuxThreads specific stuff... */ 00076 00077 00078 /* 00079 * fprintf for file descriptors :) NOTE: we have to use fixed-size buffer :)( 00080 * due to malloc's unavalaibility. 00081 */ 00082 int 00083 fdprintf( int fd, 00084 const char* fmt,...) 00085 { 00086 char xbuf[2048];// FIXME: enough? 00087 va_list ap; 00088 int r; 00089 if (fd<0) 00090 return -1; 00091 va_start(ap, fmt); 00092 r = vsnprintf(xbuf, sizeof(xbuf), fmt, ap); 00093 va_end(ap); 00094 return write(fd, xbuf, r); 00095 } 00096 00097 int 00098 fdputc( char c, 00099 int fd) 00100 { 00101 if (fd<0) 00102 return -1; 00103 return write(fd, &c, sizeof(c)); 00104 } 00105 00106 int 00107 fdputs( const char* s, 00108 int fd) 00109 { 00110 if (fd<0) 00111 return -1; 00112 return write(fd, s, strlen(s)); 00113 } 00114 00115 /* 00116 * Use this function to open log file. 00117 * Flags: truncate on opening. 00118 */ 00119 static const char* path_format = "stack-trace-on-segv-%d.txt"; 00120 static int 00121 open_log_file( const pthread_t tid, 00122 const pid_t pid) 00123 { 00124 char fname[PATH_MAX]; 00125 int r; 00126 snprintf(fname, sizeof(fname), path_format, tid, pid); 00127 r = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 00128 S_IRUSR|S_IWUSR); 00129 if (r<0) 00130 perror("open"); 00131 return r; 00132 } 00133 /* 00134 * Add additional debugging information for functions. 00135 */ 00136 00137 /* 00138 * Lineno 00139 */ 00140 typedef struct { 00141 int lineno; 00142 bfd_vma addr; 00143 } debug_lineno_t; 00144 00145 /* 00146 * Block - a {} pair. 00147 */ 00148 typedef struct debug_block_st { 00149 bfd_vma begin_addr; /* where did it start */ 00150 bfd_vma end_addr; /* where did it end */ 00151 struct debug_block_st* parent; 00152 struct debug_block_st* childs; 00153 int childs_count; 00154 } debug_block_t; 00155 00156 /* 00157 * Function parameter. 00158 */ 00159 typedef struct { 00160 bfd_vma offset; /* Offset in the stack */ 00161 const char* name; /* And name. */ 00162 } debug_parameter_t; 00163 00164 /* 00165 * Extra information about functions. 00166 */ 00167 typedef struct { 00168 asymbol* symbol; /* mangled function name, addr */ 00169 debug_lineno_t* lines; 00170 int lines_count; 00171 int max_lines_count; 00172 const char* name; 00173 const char* filename;/* a file name it occured in... */ 00174 debug_block_t* block; /* each function has a block, or not, you know */ 00175 debug_parameter_t* argv; /* argument types. */ 00176 int argc; 00177 int max_argc; 00178 } debug_function_t; 00179 00180 /* This is the structure we use as a handle for these routines. */ 00181 struct pr_handle 00182 { 00183 /* File to print information to. */ 00184 FILE *f; 00185 /* Current indentation level. */ 00186 unsigned int indent; 00187 /* Type stack. */ 00188 struct pr_stack *stack; 00189 /* Parameter number we are about to output. */ 00190 int parameter; 00191 debug_block_t* block; /* current block */ 00192 debug_function_t* function; /* current function */ 00193 debug_function_t* functions; /* all functions */ 00194 int functions_size; /* current size */ 00195 int functions_maxsize; /* maximum size */ 00196 }; 00197 00198 /* The type stack. */ 00199 00200 struct pr_stack 00201 { 00202 /* Next element on the stack. */ 00203 struct pr_stack *next; 00204 /* This element. */ 00205 char *type; 00206 /* Current visibility of fields if this is a class. */ 00207 enum debug_visibility visibility; 00208 /* Name of the current method we are handling. */ 00209 const char *method; 00210 }; 00211 00212 static void indent PARAMS ((struct pr_handle *)); 00213 static boolean push_type PARAMS ((struct pr_handle *, const char *)); 00214 static boolean prepend_type PARAMS ((struct pr_handle *, const char *)); 00215 static boolean append_type PARAMS ((struct pr_handle *, const char *)); 00216 static boolean substitute_type PARAMS ((struct pr_handle *, const char *)); 00217 static boolean indent_type PARAMS ((struct pr_handle *)); 00218 static char *pop_type PARAMS ((struct pr_handle *)); 00219 static void print_vma PARAMS ((bfd_vma, char *, boolean, boolean)); 00220 static boolean pr_fix_visibility 00221 PARAMS ((struct pr_handle *, enum debug_visibility)); 00222 00223 static boolean pr_start_compilation_unit PARAMS ((PTR, const char *)); 00224 static boolean pr_start_source PARAMS ((PTR, const char *)); 00225 static boolean pr_empty_type PARAMS ((PTR)); 00226 static boolean pr_void_type PARAMS ((PTR)); 00227 static boolean pr_int_type PARAMS ((PTR, unsigned int, boolean)); 00228 static boolean pr_float_type PARAMS ((PTR, unsigned int)); 00229 static boolean pr_complex_type PARAMS ((PTR, unsigned int)); 00230 static boolean pr_bool_type PARAMS ((PTR, unsigned int)); 00231 static boolean pr_enum_type 00232 PARAMS ((PTR, const char *, const char **, bfd_signed_vma *)); 00233 static boolean pr_pointer_type PARAMS ((PTR)); 00234 static boolean pr_function_type PARAMS ((PTR, int, boolean)); 00235 static boolean pr_reference_type PARAMS ((PTR)); 00236 static boolean pr_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma)); 00237 static boolean pr_array_type 00238 PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean)); 00239 static boolean pr_set_type PARAMS ((PTR, boolean)); 00240 static boolean pr_offset_type PARAMS ((PTR)); 00241 static boolean pr_method_type PARAMS ((PTR, boolean, int, boolean)); 00242 static boolean pr_const_type PARAMS ((PTR)); 00243 static boolean pr_volatile_type PARAMS ((PTR)); 00244 static boolean pr_start_struct_type 00245 PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int)); 00246 static boolean pr_struct_field 00247 PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility)); 00248 static boolean pr_end_struct_type PARAMS ((PTR)); 00249 static boolean pr_start_class_type 00250 PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean, 00251 boolean)); 00252 static boolean pr_class_static_member 00253 PARAMS ((PTR, const char *, const char *, enum debug_visibility)); 00254 static boolean pr_class_baseclass 00255 PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility)); 00256 static boolean pr_class_start_method PARAMS ((PTR, const char *)); 00257 static boolean pr_class_method_variant 00258 PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean, 00259 bfd_vma, boolean)); 00260 static boolean pr_class_static_method_variant 00261 PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean)); 00262 static boolean pr_class_end_method PARAMS ((PTR)); 00263 static boolean pr_end_class_type PARAMS ((PTR)); 00264 static boolean pr_typedef_type PARAMS ((PTR, const char *)); 00265 static boolean pr_tag_type 00266 PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind)); 00267 static boolean pr_typdef PARAMS ((PTR, const char *)); 00268 static boolean pr_tag PARAMS ((PTR, const char *)); 00269 static boolean pr_int_constant PARAMS ((PTR, const char *, bfd_vma)); 00270 static boolean pr_float_constant PARAMS ((PTR, const char *, double)); 00271 static boolean pr_typed_constant PARAMS ((PTR, const char *, bfd_vma)); 00272 static boolean pr_variable 00273 PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma)); 00274 static boolean pr_start_function PARAMS ((PTR, const char *, boolean)); 00275 static boolean pr_function_parameter 00276 PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma)); 00277 static boolean pr_start_block PARAMS ((PTR, bfd_vma)); 00278 static boolean pr_end_block PARAMS ((PTR, bfd_vma)); 00279 static boolean pr_end_function PARAMS ((PTR)); 00280 static boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma)); 00281 00282 static const struct debug_write_fns pr_fns = 00283 { 00284 pr_start_compilation_unit, 00285 pr_start_source, 00286 pr_empty_type, 00287 pr_void_type, 00288 pr_int_type, 00289 pr_float_type, 00290 pr_complex_type, 00291 pr_bool_type, 00292 pr_enum_type, 00293 pr_pointer_type, 00294 pr_function_type, 00295 pr_reference_type, 00296 pr_range_type, 00297 pr_array_type, 00298 pr_set_type, 00299 pr_offset_type, 00300 pr_method_type, 00301 pr_const_type, 00302 pr_volatile_type, 00303 pr_start_struct_type, 00304 pr_struct_field, 00305 pr_end_struct_type, 00306 pr_start_class_type, 00307 pr_class_static_member, 00308 pr_class_baseclass, 00309 pr_class_start_method, 00310 pr_class_method_variant, 00311 pr_class_static_method_variant, 00312 pr_class_end_method, 00313 pr_end_class_type, 00314 pr_typedef_type, 00315 pr_tag_type, 00316 pr_typdef, 00317 pr_tag, 00318 pr_int_constant, 00319 pr_float_constant, 00320 pr_typed_constant, 00321 pr_variable, 00322 pr_start_function, 00323 pr_function_parameter, 00324 pr_start_block, 00325 pr_end_block, 00326 pr_end_function, 00327 pr_lineno 00328 }; 00329 00330 00331 /* Indent to the current indentation level. */ 00332 00333 static void 00334 indent (info) 00335 struct pr_handle *info; 00336 { 00337 unsigned int i; 00338 00339 for (i = 0; i < info->indent; i++) 00340 TRACE_PUTC ((' ', info->f)); 00341 } 00342 00343 /* Push a type on the type stack. */ 00344 00345 static boolean 00346 push_type (info, type) 00347 struct pr_handle *info; 00348 const char *type; 00349 { 00350 struct pr_stack *n; 00351 00352 if (type == NULL) 00353 return false; 00354 00355 n = (struct pr_stack *) xmalloc (sizeof *n); 00356 memset (n, 0, sizeof *n); 00357 00358 n->type = xstrdup (type); 00359 n->visibility = DEBUG_VISIBILITY_IGNORE; 00360 n->method = NULL; 00361 n->next = info->stack; 00362 info->stack = n; 00363 00364 return true; 00365 } 00366 00367 /* Prepend a string onto the type on the top of the type stack. */ 00368 00369 static boolean 00370 prepend_type (info, s) 00371 struct pr_handle *info; 00372 const char *s; 00373 { 00374 char *n; 00375 00376 assert (info->stack != NULL); 00377 00378 n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1); 00379 sprintf (n, "%s%s", s, info->stack->type); 00380 free (info->stack->type); 00381 info->stack->type = n; 00382 00383 return true; 00384 } 00385 00386 /* Append a string to the type on the top of the type stack. */ 00387 00388 static boolean 00389 append_type (info, s) 00390 struct pr_handle *info; 00391 const char *s; 00392 { 00393 unsigned int len; 00394 00395 if (s == NULL) 00396 return false; 00397 00398 assert (info->stack != NULL); 00399 00400 len = strlen (info->stack->type); 00401 info->stack->type = (char *) xrealloc (info->stack->type, 00402 len + strlen (s) + 1); 00403 strcpy (info->stack->type + len, s); 00404 00405 return true; 00406 } 00407 00408 /* We use an underscore to indicate where the name should go in a type 00409 string. This function substitutes a string for the underscore. If 00410 there is no underscore, the name follows the type. */ 00411 00412 static boolean 00413 substitute_type (info, s) 00414 struct pr_handle *info; 00415 const char *s; 00416 { 00417 char *u; 00418 00419 assert (info->stack != NULL); 00420 00421 u = strchr (info->stack->type, '|'); 00422 if (u != NULL) 00423 { 00424 char *n; 00425 00426 n = (char *) xmalloc (strlen (info->stack->type) + strlen (s)); 00427 00428 memcpy (n, info->stack->type, u - info->stack->type); 00429 strcpy (n + (u - info->stack->type), s); 00430 strcat (n, u + 1); 00431 00432 free (info->stack->type); 00433 info->stack->type = n; 00434 00435 return true; 00436 } 00437 00438 if (strchr (s, '|') != NULL 00439 && (strchr (info->stack->type, '{') != NULL 00440 || strchr (info->stack->type, '(') != NULL)) 00441 { 00442 if (! prepend_type (info, "(") 00443 || ! append_type (info, ")")) 00444 return false; 00445 } 00446 00447 if (*s == '\0') 00448 return true; 00449 00450 return (append_type (info, " ") 00451 && append_type (info, s)); 00452 } 00453 00454 /* Indent the type at the top of the stack by appending spaces. */ 00455 00456 static boolean 00457 indent_type (info) 00458 struct pr_handle *info; 00459 { 00460 unsigned int i; 00461 00462 for (i = 0; i < info->indent; i++) 00463 { 00464 if (! append_type (info, " ")) 00465 return false; 00466 } 00467 00468 return true; 00469 } 00470 00471 /* Pop a type from the type stack. */ 00472 00473 static char * 00474 pop_type (info) 00475 struct pr_handle *info; 00476 { 00477 struct pr_stack *o; 00478 char *ret; 00479 00480 assert (info->stack != NULL); 00481 00482 o = info->stack; 00483 info->stack = o->next; 00484 ret = o->type; 00485 free (o); 00486 00487 return ret; 00488 } 00489 00490 /* Print a VMA value into a string. */ 00491 00492 static void 00493 print_vma (vma, buf, unsignedp, hexp) 00494 bfd_vma vma; 00495 char *buf; 00496 boolean unsignedp; 00497 boolean hexp; 00498 { 00499 if (sizeof (vma) <= sizeof (unsigned long)) 00500 { 00501 if (hexp) 00502 sprintf (buf, "0x%lx", (unsigned long) vma); 00503 else if (unsignedp) 00504 sprintf (buf, "%lu", (unsigned long) vma); 00505 else 00506 sprintf (buf, "%ld", (long) vma); 00507 } 00508 else 00509 { 00510 buf[0] = '0'; 00511 buf[1] = 'x'; 00512 sprintf_vma (buf + 2, vma); 00513 } 00514 } 00515 00516 /* Start a new compilation unit. */ 00517 00518 static boolean 00519 pr_start_compilation_unit (p, filename) 00520 PTR p; 00521 const char *filename; 00522 { 00523 struct pr_handle *info = (struct pr_handle *) p; 00524 00525 assert (info->indent == 0); 00526 /* 00527 TRACE_FPRINTF( (info->f, "%s:\n", filename)); 00528 */ 00529 return true; 00530 } 00531 00532 /* Start a source file within a compilation unit. */ 00533 00534 static boolean 00535 pr_start_source (p, filename) 00536 PTR p; 00537 const char *filename; 00538 { 00539 struct pr_handle *info = (struct pr_handle *) p; 00540 00541 assert (info->indent == 0); 00542 /* 00543 TRACE_FPRINTF( (info->f, " %s:\n", filename)); 00544 */ 00545 return true; 00546 } 00547 00548 /* Push an empty type onto the type stack. */ 00549 00550 static boolean 00551 pr_empty_type (p) 00552 PTR p; 00553 { 00554 struct pr_handle *info = (struct pr_handle *) p; 00555 00556 return push_type (info, "<undefined>"); 00557 } 00558 00559 /* Push a void type onto the type stack. */ 00560 00561 static boolean 00562 pr_void_type (p) 00563 PTR p; 00564 { 00565 struct pr_handle *info = (struct pr_handle *) p; 00566 00567 return push_type (info, "void"); 00568 } 00569 00570 /* Push an integer type onto the type stack. */ 00571 00572 static boolean 00573 pr_int_type (p, size, unsignedp) 00574 PTR p; 00575 unsigned int size; 00576 boolean unsignedp; 00577 { 00578 struct pr_handle *info = (struct pr_handle *) p; 00579 char ab[10]; 00580 00581 sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8); 00582 return push_type (info, ab); 00583 } 00584 00585 /* Push a floating type onto the type stack. */ 00586 00587 static boolean 00588 pr_float_type (p, size) 00589 PTR p; 00590 unsigned int size; 00591 { 00592 struct pr_handle *info = (struct pr_handle *) p; 00593 char ab[10]; 00594 00595 if (size == 4) 00596 return push_type (info, "float"); 00597 else if (size == 8) 00598 return push_type (info, "double"); 00599 00600 sprintf (ab, "float%d", size * 8); 00601 return push_type (info, ab); 00602 } 00603 00604 /* Push a complex type onto the type stack. */ 00605 00606 static boolean 00607 pr_complex_type (p, size) 00608 PTR p; 00609 unsigned int size; 00610 { 00611 struct pr_handle *info = (struct pr_handle *) p; 00612 00613 if (! pr_float_type (p, size)) 00614 return false; 00615 00616 return prepend_type (info, "complex "); 00617 } 00618 00619 /* Push a boolean type onto the type stack. */ 00620 00621 static boolean 00622 pr_bool_type (p, size) 00623 PTR p; 00624 unsigned int size; 00625 { 00626 struct pr_handle *info = (struct pr_handle *) p; 00627 char ab[10]; 00628 00629 sprintf (ab, "bool%d", size * 8); 00630 00631 return push_type (info, ab); 00632 } 00633 00634 /* Push an enum type onto the type stack. */ 00635 00636 static boolean 00637 pr_enum_type (p, tag, names, values) 00638 PTR p; 00639 const char *tag; 00640 const char **names; 00641 bfd_signed_vma *values; 00642 { 00643 struct pr_handle *info = (struct pr_handle *) p; 00644 unsigned int i; 00645 bfd_signed_vma val; 00646 00647 if (! push_type (info, "enum ")) 00648 return false; 00649 if (tag != NULL) 00650 { 00651 if (! append_type (info, tag) 00652 || ! append_type (info, " ")) 00653 return false; 00654 } 00655 if (! append_type (info, "{ ")) 00656 return false; 00657 00658 if (names == NULL) 00659 { 00660 if (! append_type (info, "/* undefined */")) 00661 return false; 00662 } 00663 else 00664 { 00665 val = 0; 00666 for (i = 0; names[i] != NULL; i++) 00667 { 00668 if (i > 0) 00669 { 00670 if (! append_type (info, ", ")) 00671 return false; 00672 } 00673 00674 if (! append_type (info, names[i])) 00675 return false; 00676 00677 if (values[i] != val) 00678 { 00679 char ab[20]; 00680 00681 print_vma (values[i], ab, false, false); 00682 if (! append_type (info, " = ") 00683 || ! append_type (info, ab)) 00684 return false; 00685 val = values[i]; 00686 } 00687 00688 ++val; 00689 } 00690 } 00691 00692 return append_type (info, " }"); 00693 } 00694 00695 /* Turn the top type on the stack into a pointer. */ 00696 00697 static boolean 00698 pr_pointer_type (p) 00699 PTR p; 00700 { 00701 struct pr_handle *info = (struct pr_handle *) p; 00702 char *s; 00703 00704 assert (info->stack != NULL); 00705 00706 s = strchr (info->stack->type, '|'); 00707 if (s != NULL && s[1] == '[') 00708 return substitute_type (info, "(*|)"); 00709 return substitute_type (info, "*|"); 00710 } 00711 00712 /* Turn the top type on the stack into a function returning that type. */ 00713 00714 static boolean 00715 pr_function_type (p, argcount, varargs) 00716 PTR p; 00717 int argcount; 00718 boolean varargs; 00719 { 00720 struct pr_handle *info = (struct pr_handle *) p; 00721 char **arg_types; 00722 unsigned int len; 00723 char *s; 00724 00725 assert (info->stack != NULL); 00726 00727 len = 10; 00728 00729 if (argcount <= 0) 00730 { 00731 arg_types = NULL; 00732 len += 15; 00733 } 00734 else 00735 { 00736 int i; 00737 00738 arg_types = (char **) xmalloc (argcount * sizeof *arg_types); 00739 for (i = argcount - 1; i >= 0; i--) 00740 { 00741 if (! substitute_type (info, "")) 00742 return false; 00743 arg_types[i] = pop_type (info); 00744 if (arg_types[i] == NULL) 00745 return false; 00746 len += strlen (arg_types[i]) + 2; 00747 } 00748 if (varargs) 00749 len += 5; 00750 } 00751 00752 /* Now the return type is on the top of the stack. */ 00753 00754 s = (char *) xmalloc (len); 00755 strcpy (s, "(|) ("); 00756 00757 if (argcount < 0) 00758 { 00759 #if 0 00760 /* Turn off unknown arguments. */ 00761 strcat (s, "/* unknown */"); 00762 #endif 00763 } 00764 else 00765 { 00766 int i; 00767 00768 for (i = 0; i < argcount; i++) 00769 { 00770 if (i > 0) 00771 strcat (s, ", "); 00772 strcat (s, arg_types[i]); 00773 } 00774 if (varargs) 00775 { 00776 if (i > 0) 00777 strcat (s, ", "); 00778 strcat (s, "..."); 00779 } 00780 if (argcount > 0) 00781 free (arg_types); 00782 } 00783 00784 strcat (s, ")"); 00785 00786 if (! substitute_type (info, s)) 00787 return false; 00788 00789 free (s); 00790 00791 return true; 00792 } 00793 00794 /* Turn the top type on the stack into a reference to that type. */ 00795 00796 static boolean 00797 pr_reference_type (p) 00798 PTR p; 00799 { 00800 struct pr_handle *info = (struct pr_handle *) p; 00801 00802 assert (info->stack != NULL); 00803 00804 return substitute_type (info, "&|"); 00805 } 00806 00807 /* Make a range type. */ 00808 00809 static boolean 00810 pr_range_type (p, lower, upper) 00811 PTR p; 00812 bfd_signed_vma lower; 00813 bfd_signed_vma upper; 00814 { 00815 struct pr_handle *info = (struct pr_handle *) p; 00816 char abl[20], abu[20]; 00817 00818 assert (info->stack != NULL); 00819 00820 if (! substitute_type (info, "")) 00821 return false; 00822 00823 print_vma (lower, abl, false, false); 00824 print_vma (upper, abu, false, false); 00825 00826 return (prepend_type (info, "range (") 00827 && append_type (info, "):") 00828 && append_type (info, abl) 00829 && append_type (info, ":") 00830 && append_type (info, abu)); 00831 } 00832 00833 /* Make an array type. */ 00834 00835 /*ARGSUSED*/ 00836 static boolean 00837 pr_array_type (p, lower, upper, stringp) 00838 PTR p; 00839 bfd_signed_vma lower; 00840 bfd_signed_vma upper; 00841 boolean stringp; 00842 { 00843 struct pr_handle *info = (struct pr_handle *) p; 00844 char *range_type; 00845 char abl[20], abu[20], ab[50]; 00846 00847 range_type = pop_type (info); 00848 if (range_type == NULL) 00849 return false; 00850 00851 if (lower == 0) 00852 { 00853 if (upper == -1) 00854 sprintf (ab, "|[]"); 00855 else 00856 { 00857 print_vma (upper + 1, abu, false, false); 00858 sprintf (ab, "|[%s]", abu); 00859 } 00860 } 00861 else 00862 { 00863 print_vma (lower, abl, false, false); 00864 print_vma (upper, abu, false, false); 00865 sprintf (ab, "|[%s:%s]", abl, abu); 00866 } 00867 00868 if (! substitute_type (info, ab)) 00869 return false; 00870 00871 if (strcmp (range_type, "int") != 0) 00872 { 00873 if (! append_type (info, ":") 00874 || ! append_type (info, range_type)) 00875 return false; 00876 } 00877 00878 if (stringp) 00879 { 00880 if (! append_type (info, " /* string */")) 00881 return false; 00882 } 00883 00884 return true; 00885 } 00886 00887 /* Make a set type. */ 00888 00889 /*ARGSUSED*/ 00890 static boolean 00891 pr_set_type (p, bitstringp) 00892 PTR p; 00893 boolean bitstringp; 00894 { 00895 struct pr_handle *info = (struct pr_handle *) p; 00896 00897 if (! substitute_type (info, "")) 00898 return false; 00899 00900 if (! prepend_type (info, "set { ") 00901 || ! append_type (info, " }")) 00902 return false; 00903 00904 if (bitstringp) 00905 { 00906 if (! append_type (info, "/* bitstring */")) 00907 return false; 00908 } 00909 00910 return true; 00911 } 00912 00913 /* Make an offset type. */ 00914 00915 static boolean 00916 pr_offset_type (p) 00917 PTR p; 00918 { 00919 struct pr_handle *info = (struct pr_handle *) p; 00920 char *t; 00921 00922 if (! substitute_type (info, "")) 00923 return false; 00924 00925 t = pop_type (info); 00926 if (t == NULL) 00927 return false; 00928 00929 return (substitute_type (info, "") 00930 && prepend_type (info, " ") 00931 && prepend_type (info, t) 00932 && append_type (info, "::|")); 00933 } 00934 00935 /* Make a method type. */ 00936 00937 static boolean 00938 pr_method_type (p, domain, argcount, varargs) 00939 PTR p; 00940 boolean domain; 00941 int argcount; 00942 boolean varargs; 00943 { 00944 struct pr_handle *info = (struct pr_handle *) p; 00945 unsigned int len; 00946 char *domain_type; 00947 char **arg_types; 00948 char *s; 00949 00950 len = 10; 00951 00952 if (! domain) 00953 domain_type = NULL; 00954 else 00955 { 00956 if (! substitute_type (info, "")) 00957 return false; 00958 domain_type = pop_type (info); 00959 if (domain_type == NULL) 00960 return false; 00961 if (strncmp (domain_type, "class ", sizeof "class " - 1) == 0 00962 && strchr (domain_type + sizeof "class " - 1, ' ') == NULL) 00963 domain_type += sizeof "class " - 1; 00964 else if (strncmp (domain_type, "union class ", 00965 sizeof "union class ") == 0 00966 && (strchr (domain_type + sizeof "union class " - 1, ' ') 00967 == NULL)) 00968 domain_type += sizeof "union class " - 1; 00969 len += strlen (domain_type); 00970 } 00971 00972 if (argcount <= 0) 00973 { 00974 arg_types = NULL; 00975 len += 15; 00976 } 00977 else 00978 { 00979 int i; 00980 00981 arg_types = (char **) xmalloc (argcount * sizeof *arg_types); 00982 for (i = argcount - 1; i >= 0; i--) 00983 { 00984 if (! substitute_type (info, "")) 00985 return false; 00986 arg_types[i] = pop_type (info); 00987 if (arg_types[i] == NULL) 00988 return false; 00989 len += strlen (arg_types[i]) + 2; 00990 } 00991 if (varargs) 00992 len += 5; 00993 } 00994 00995 /* Now the return type is on the top of the stack. */ 00996 00997 s = (char *) xmalloc (len); 00998 if (! domain) 00999 *s = '\0'; 01000 else 01001 strcpy (s, domain_type); 01002 strcat (s, "::| ("); 01003 01004 if (argcount < 0) 01005 strcat (s, "/* unknown */"); 01006 else 01007 { 01008 int i; 01009 01010 for (i = 0; i < argcount; i++) 01011 { 01012 if (i > 0) 01013 strcat (s, ", "); 01014 strcat (s, arg_types[i]); 01015 } 01016 if (varargs) 01017 { 01018 if (i > 0) 01019 strcat (s, ", "); 01020 strcat (s, "..."); 01021 } 01022 if (argcount > 0) 01023 free (arg_types); 01024 } 01025 01026 strcat (s, ")"); 01027 01028 if (! substitute_type (info, s)) 01029 return false; 01030 01031 free (s); 01032 01033 return true; 01034 } 01035 01036 /* Make a const qualified type. */ 01037 01038 static boolean 01039 pr_const_type (p) 01040 PTR p; 01041 { 01042 struct pr_handle *info = (struct pr_handle *) p; 01043 01044 return substitute_type (info, "const |"); 01045 } 01046 01047 /* Make a volatile qualified type. */ 01048 01049 static boolean 01050 pr_volatile_type (p) 01051 PTR p; 01052 { 01053 struct pr_handle *info = (struct pr_handle *) p; 01054 01055 return substitute_type (info, "volatile |"); 01056 } 01057 01058 /* Start accumulating a struct type. */ 01059 01060 static boolean 01061 pr_start_struct_type (p, tag, id, structp, size) 01062 PTR p; 01063 const char *tag; 01064 unsigned int id; 01065 boolean structp; 01066 unsigned int size; 01067 { 01068 struct pr_handle *info = (struct pr_handle *) p; 01069 01070 info->indent += 2; 01071 01072 if (! push_type (info, structp ? "struct " : "union ")) 01073 return false; 01074 if (tag != NULL) 01075 { 01076 if (! append_type (info, tag)) 01077 return false; 01078 } 01079 else 01080 { 01081 char idbuf[20]; 01082 01083 sprintf (idbuf, "%%anon%u", id); 01084 if (! append_type (info, idbuf)) 01085 return false; 01086 } 01087 01088 if (! append_type (info, " {")) 01089 return false; 01090 if (size != 0 || tag != NULL) 01091 { 01092 char ab[30]; 01093 01094 if (! append_type (info, " /*")) 01095 return false; 01096 01097 if (size != 0) 01098 { 01099 sprintf (ab, " size %u", size); 01100 if (! append_type (info, ab)) 01101 return false; 01102 } 01103 if (tag != NULL) 01104 { 01105 sprintf (ab, " id %u", id); 01106 if (! append_type (info, ab)) 01107 return false; 01108 } 01109 if (! append_type (info, " */")) 01110 return false; 01111 } 01112 if (! append_type (info, "\n")) 01113 return false; 01114 01115 info->stack->visibility = DEBUG_VISIBILITY_PUBLIC; 01116 01117 return indent_type (info); 01118 } 01119 01120 /* Output the visibility of a field in a struct. */ 01121 01122 static boolean 01123 pr_fix_visibility (info, visibility) 01124 struct pr_handle *info; 01125 enum debug_visibility visibility; 01126 { 01127 const char *s; 01128 char *t; 01129 unsigned int len; 01130 01131 assert (info->stack != NULL); 01132 01133 if (info->stack->visibility == visibility) 01134 return true; 01135 01136 assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE); 01137 01138 switch (visibility) 01139 { 01140 case DEBUG_VISIBILITY_PUBLIC: 01141 s = "public"; 01142 break; 01143 case DEBUG_VISIBILITY_PRIVATE: 01144 s = "private"; 01145 break; 01146 case DEBUG_VISIBILITY_PROTECTED: 01147 s = "protected"; 01148 break; 01149 case DEBUG_VISIBILITY_IGNORE: 01150 s = "/* ignore */"; 01151 break; 01152 default: 01153 abort (); 01154 return false; 01155 } 01156 01157 /* Trim off a trailing space in the struct string, to make the 01158 output look a bit better, then stick on the visibility string. */ 01159 01160 t = info->stack->type; 01161 len = strlen (t); 01162 assert (t[len - 1] == ' '); 01163 t[len - 1] = '\0'; 01164 01165 if (! append_type (info, s) 01166 || ! append_type (info, ":\n") 01167 || ! indent_type (info)) 01168 return false; 01169 01170 info->stack->visibility = visibility; 01171 01172 return true; 01173 } 01174 01175 /* Add a field to a struct type. */ 01176 01177 static boolean 01178 pr_struct_field (p, name, bitpos, bitsize, visibility) 01179 PTR p; 01180 const char *name; 01181 bfd_vma bitpos; 01182 bfd_vma bitsize; 01183 enum debug_visibility visibility; 01184 { 01185 struct pr_handle *info = (struct pr_handle *) p; 01186 char ab[20]; 01187 char *t; 01188 01189 if (! substitute_type (info, name)) 01190 return false; 01191 01192 if (! append_type (info, "; /* ")) 01193 return false; 01194 01195 if (bitsize != 0) 01196 { 01197 print_vma (bitsize, ab, true, false); 01198 if (! append_type (info, "bitsize ") 01199 || ! append_type (info, ab) 01200 || ! append_type (info, ", ")) 01201 return false; 01202 } 01203 01204 print_vma (bitpos, ab, true, false); 01205 if (! append_type (info, "bitpos ") 01206 || ! append_type (info, ab) 01207 || ! append_type (info, " */\n") 01208 || ! indent_type (info)) 01209 return false; 01210 01211 t = pop_type (info); 01212 if (t == NULL) 01213 return false; 01214 01215 if (! pr_fix_visibility (info, visibility)) 01216 return false; 01217 01218 return append_type (info, t); 01219 } 01220 01221 /* Finish a struct type. */ 01222 01223 static boolean 01224 pr_end_struct_type (p) 01225 PTR p; 01226 { 01227 struct pr_handle *info = (struct pr_handle *) p; 01228 char *s; 01229 01230 assert (info->stack != NULL); 01231 assert (info->indent >= 2); 01232 01233 info->indent -= 2; 01234 01235 /* Change the trailing indentation to have a close brace. */ 01236 s = info->stack->type + strlen (info->stack->type) - 2; 01237 assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0'); 01238 01239 *s++ = '}'; 01240 *s = '\0'; 01241 01242 return true; 01243 } 01244 01245 /* Start a class type. */ 01246 01247 static boolean 01248 pr_start_class_type (p, tag, id, structp, size, vptr, ownvptr) 01249 PTR p; 01250 const char *tag; 01251 unsigned int id; 01252 boolean structp; 01253 unsigned int size; 01254 boolean vptr; 01255 boolean ownvptr; 01256 { 01257 struct pr_handle *info = (struct pr_handle *) p; 01258 char *tv = NULL; 01259 01260 info->indent += 2; 01261 01262 if (vptr && ! ownvptr) 01263 { 01264 tv = pop_type (info); 01265 if (tv == NULL) 01266 return false; 01267 } 01268 01269 if (! push_type (info, structp ? "class " : "union class ")) 01270 return false; 01271 if (tag != NULL) 01272 { 01273 if (! append_type (info, tag)) 01274 return false; 01275 } 01276 else 01277 { 01278 char idbuf[20]; 01279 01280 sprintf (idbuf, "%%anon%u", id); 01281 if (! append_type (info, idbuf)) 01282 return false; 01283 } 01284 01285 if (! append_type (info, " {")) 01286 return false; 01287 if (size != 0 || vptr || ownvptr || tag != NULL) 01288 { 01289 if (! append_type (info, " /*")) 01290 return false; 01291 01292 if (size != 0) 01293 { 01294 char ab[20]; 01295 01296 sprintf (ab, "%u", size); 01297 if (! append_type (info, " size ") 01298 || ! append_type (info, ab)) 01299 return false; 01300 } 01301 01302 if (vptr) 01303 { 01304 if (! append_type (info, " vtable ")) 01305 return false; 01306 if (ownvptr) 01307 { 01308 if (! append_type (info, "self ")) 01309 return false; 01310 } 01311 else 01312 { 01313 if (! append_type (info, tv) 01314 || ! append_type (info, " ")) 01315 return false; 01316 } 01317 } 01318 01319 if (tag != NULL) 01320 { 01321 char ab[30]; 01322 01323 sprintf (ab, " id %u", id); 01324 if (! append_type (info, ab)) 01325 return false; 01326 } 01327 01328 if (! append_type (info, " */")) 01329 return false; 01330 } 01331 01332 info->stack->visibility = DEBUG_VISIBILITY_PRIVATE; 01333 01334 return (append_type (info, "\n") 01335 && indent_type (info)); 01336 } 01337 01338 /* Add a static member to a class. */ 01339 01340 static boolean 01341 pr_class_static_member (p, name, physname, visibility) 01342 PTR p; 01343 const char *name; 01344 const char *physname; 01345 enum debug_visibility visibility; 01346 { 01347 struct pr_handle *info = (struct pr_handle *) p; 01348 char *t; 01349 01350 if (! substitute_type (info, name)) 01351 return false; 01352 01353 if (! prepend_type (info, "static ") 01354 || ! append_type (info, "; /* ") 01355 || ! append_type (info, physname) 01356 || ! append_type (info, " */\n") 01357 || ! indent_type (info)) 01358 return false; 01359 01360 t = pop_type (info); 01361 if (t == NULL) 01362 return false; 01363 01364 if (! pr_fix_visibility (info, visibility)) 01365 return false; 01366 01367 return append_type (info, t); 01368 } 01369 01370 /* Add a base class to a class. */ 01371 01372 static boolean 01373 pr_class_baseclass (p, bitpos, virtual, visibility) 01374 PTR p; 01375 bfd_vma bitpos; 01376 boolean virtual; 01377 enum debug_visibility visibility; 01378 { 01379 struct pr_handle *info = (struct pr_handle *) p; 01380 char *t; 01381 const char *prefix; 01382 char ab[20]; 01383 char *s, *l, *n; 01384 01385 assert (info->stack != NULL && info->stack->next != NULL); 01386 01387 if (! substitute_type (info, "")) 01388 return false; 01389 01390 t = pop_type (info); 01391 if (t == NULL) 01392 return false; 01393 01394 if (strncmp (t, "class ", sizeof "class " - 1) == 0) 01395 t += sizeof "class " - 1; 01396 01397 /* Push it back on to take advantage of the prepend_type and 01398 append_type routines. */ 01399 if (! push_type (info, t)) 01400 return false; 01401 01402 if (virtual) 01403 { 01404 if (! prepend_type (info, "virtual ")) 01405 return false; 01406 } 01407 01408 switch (visibility) 01409 { 01410 case DEBUG_VISIBILITY_PUBLIC: 01411 prefix = "public "; 01412 break; 01413 case DEBUG_VISIBILITY_PROTECTED: 01414 prefix = "protected "; 01415 break; 01416 case DEBUG_VISIBILITY_PRIVATE: 01417 prefix = "private "; 01418 break; 01419 default: 01420 prefix = "/* unknown visibility */ "; 01421 break; 01422 } 01423 01424 if (! prepend_type (info, prefix)) 01425 return false; 01426 01427 if (bitpos != 0) 01428 { 01429 print_vma (bitpos, ab, true, false); 01430 if (! append_type (info, " /* bitpos ") 01431 || ! append_type (info, ab) 01432 || ! append_type (info, " */")) 01433 return false; 01434 } 01435 01436 /* Now the top of the stack is something like "public A / * bitpos 01437 10 * /". The next element on the stack is something like "class 01438 xx { / * size 8 * /\n...". We want to substitute the top of the 01439 stack in before the {. */ 01440 s = strchr (info->stack->next->type, '{'); 01441 assert (s != NULL); 01442 --s; 01443 01444 /* If there is already a ':', then we already have a baseclass, and 01445 we must append this one after a comma. */ 01446 for (l = info->stack->next->type; l != s; l++) 01447 if (*l == ':') 01448 break; 01449 if (! prepend_type (info, l == s ? " : " : ", ")) 01450 return false; 01451 01452 t = pop_type (info); 01453 if (t == NULL) 01454 return false; 01455 01456 n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1); 01457 memcpy (n, info->stack->type, s - info->stack->type); 01458 strcpy (n + (s - info->stack->type), t); 01459 strcat (n, s); 01460 01461 free (info->stack->type); 01462 info->stack->type = n; 01463 01464 free (t); 01465 01466 return true; 01467 } 01468 01469 /* Start adding a method to a class. */ 01470 01471 static boolean 01472 pr_class_start_method (p, name) 01473 PTR p; 01474 const char *name; 01475 { 01476 struct pr_handle *info = (struct pr_handle *) p; 01477 01478 assert (info->stack != NULL); 01479 info->stack->method = name; 01480 return true; 01481 } 01482 01483 /* Add a variant to a method. */ 01484 01485 static boolean 01486 pr_class_method_variant (p, physname, visibility, constp, volatilep, voffset, 01487 context) 01488 PTR p; 01489 const char *physname; 01490 enum debug_visibility visibility; 01491 boolean constp; 01492 boolean volatilep; 01493 bfd_vma voffset; 01494 boolean context; 01495 { 01496 struct pr_handle *info = (struct pr_handle *) p; 01497 char *method_type; 01498 char *context_type; 01499 01500 assert (info->stack != NULL); 01501 assert (info->stack->next != NULL); 01502 01503 /* Put the const and volatile qualifiers on the type. */ 01504 if (volatilep) 01505 { 01506 if (! append_type (info, " volatile")) 01507 return false; 01508 } 01509 if (constp) 01510 { 01511 if (! append_type (info, " const")) 01512 return false; 01513 } 01514 01515 /* Stick the name of the method into its type. */ 01516 if (! substitute_type (info, 01517 (context 01518 ? info->stack->next->next->method 01519 : info->stack->next->method))) 01520 return false; 01521 01522 /* Get the type. */ 01523 method_type = pop_type (info); 01524 if (method_type == NULL) 01525 return false; 01526 01527 /* Pull off the context type if there is one. */ 01528 if (! context) 01529 context_type = NULL; 01530 else 01531 { 01532 context_type = pop_type (info); 01533 if (context_type == NULL) 01534 return false; 01535 } 01536 01537 /* Now the top of the stack is the class. */ 01538 01539 if (! pr_fix_visibility (info, visibility)) 01540 return false; 01541 01542 if (! append_type (info, method_type) 01543 || ! append_type (info, " /* ") 01544 || ! append_type (info, physname) 01545 || ! append_type (info, " ")) 01546 return false; 01547 if (context || voffset != 0) 01548 { 01549 char ab[20]; 01550 01551 if (context) 01552 { 01553 if (! append_type (info, "context ") 01554 || ! append_type (info, context_type) 01555 || ! append_type (info, " ")) 01556 return false; 01557 } 01558 print_vma (voffset, ab, true, false); 01559 if (! append_type (info, "voffset ") 01560 || ! append_type (info, ab)) 01561 return false; 01562 } 01563 01564 return (append_type (info, " */;\n") 01565 && indent_type (info)); 01566 } 01567 01568 /* Add a static variant to a method. */ 01569 01570 static boolean 01571 pr_class_static_method_variant (p, physname, visibility, constp, volatilep) 01572 PTR p; 01573 const char *physname; 01574 enum debug_visibility visibility; 01575 boolean constp; 01576 boolean volatilep; 01577 { 01578 struct pr_handle *info = (struct pr_handle *) p; 01579 char *method_type; 01580 01581 assert (info->stack != NULL); 01582 assert (info->stack->next != NULL); 01583 assert (info->stack->next->method != NULL); 01584 01585 /* Put the const and volatile qualifiers on the type. */ 01586 if (volatilep) 01587 { 01588 if (! append_type (info, " volatile")) 01589 return false; 01590 } 01591 if (constp) 01592 { 01593 if (! append_type (info, " const")) 01594 return false; 01595 } 01596 01597 /* Mark it as static. */ 01598 if (! prepend_type (info, "static ")) 01599 return false; 01600 01601 /* Stick the name of the method into its type. */ 01602 if (! substitute_type (info, info->stack->next->method)) 01603 return false; 01604 01605 /* Get the type. */ 01606 method_type = pop_type (info); 01607 if (method_type == NULL) 01608 return false; 01609 01610 /* Now the top of the stack is the class. */ 01611 01612 if (! pr_fix_visibility (info, visibility)) 01613 return false; 01614 01615 return (append_type (info, method_type) 01616 && append_type (info, " /* ") 01617 && append_type (info, physname) 01618 && append_type (info, " */;\n") 01619 && indent_type (info)); 01620 } 01621 01622 /* Finish up a method. */ 01623 01624 static boolean 01625 pr_class_end_method (p) 01626 PTR p; 01627 { 01628 struct pr_handle *info = (struct pr_handle *) p; 01629 01630 info->stack->method = NULL; 01631 return true; 01632 } 01633 01634 /* Finish up a class. */ 01635 01636 static boolean 01637 pr_end_class_type (p) 01638 PTR p; 01639 { 01640 return pr_end_struct_type (p); 01641 } 01642 01643 /* Push a type on the stack using a typedef name. */ 01644 01645 static boolean 01646 pr_typedef_type (p, name) 01647 PTR p; 01648 const char *name; 01649 { 01650 struct pr_handle *info = (struct pr_handle *) p; 01651 01652 return push_type (info, name); 01653 } 01654 01655 /* Push a type on the stack using a tag name. */ 01656 01657 static boolean 01658 pr_tag_type (p, name, id, kind) 01659 PTR p; 01660 const char *name; 01661 unsigned int id; 01662 enum debug_type_kind kind; 01663 { 01664 struct pr_handle *info = (struct pr_handle *) p; 01665 const char *t, *tag; 01666 char idbuf[30]; 01667 01668 switch (kind) 01669 { 01670 case DEBUG_KIND_STRUCT: 01671 t = "struct "; 01672 break; 01673 case DEBUG_KIND_UNION: 01674 t = "union "; 01675 break; 01676 case DEBUG_KIND_ENUM: 01677 t = "enum "; 01678 break; 01679 case DEBUG_KIND_CLASS: 01680 t = "class "; 01681 break; 01682 case DEBUG_KIND_UNION_CLASS: 01683 t = "union class "; 01684 break; 01685 default: 01686 abort (); 01687 return false; 01688 } 01689 01690 if (! push_type (info, t)) 01691 return false; 01692 if (name != NULL) 01693 tag = name; 01694 else 01695 { 01696 sprintf (idbuf, "%%anon%u", id); 01697 tag = idbuf; 01698 } 01699 01700 if (! append_type (info, tag)) 01701 return false; 01702 if (name != NULL && kind != DEBUG_KIND_ENUM) 01703 { 01704 sprintf (idbuf, " /* id %u */", id); 01705 if (! append_type (info, idbuf)) 01706 return false; 01707 } 01708 01709 return true; 01710 } 01711 01712 /* Output a typedef. */ 01713 01714 static boolean 01715 pr_typdef (p, name) 01716 PTR p; 01717 const char *name; 01718 { 01719 struct pr_handle *info = (struct pr_handle *) p; 01720 char *s; 01721 01722 if (! substitute_type (info, name)) 01723 return false; 01724 01725 s = pop_type (info); 01726 if (s == NULL) 01727 return false; 01728 /* 01729 indent (info); 01730 TRACE_FPRINTF( (info->f, "typedef %s;\n", s)); 01731 */ 01732 free (s); 01733 01734 return true; 01735 } 01736 01737 /* Output a tag. The tag should already be in the string on the 01738 stack, so all we have to do here is print it out. */ 01739 01740 /*ARGSUSED*/ 01741 static boolean 01742 pr_tag (p, name) 01743 PTR p; 01744 const char *name; 01745 { 01746 struct pr_handle *info = (struct pr_handle *) p; 01747 char *t; 01748 01749 t = pop_type (info); 01750 if (t == NULL) 01751 return false; 01752 /* 01753 indent (info); 01754 TRACE_FPRINTF( (info->f, "%s;\n", t)); 01755 */ 01756 free (t); 01757 01758 return true; 01759 } 01760 01761 /* Output an integer constant. */ 01762 01763 static boolean 01764 pr_int_constant (p, name, val) 01765 PTR p; 01766 const char *name; 01767 bfd_vma val; 01768 { 01769 /* 01770 struct pr_handle *info = (struct pr_handle *) p; 01771 char ab[20]; 01772 indent (info); 01773 print_vma (val, ab, false, false); 01774 TRACE_FPRINTF( (info->f, "const int %s = %s;\n", name, ab)); 01775 */ 01776 return true; 01777 } 01778 01779 /* Output a floating point constant. */ 01780 01781 static boolean 01782 pr_float_constant (p, name, val) 01783 PTR p; 01784 const char *name; 01785 double val; 01786 { 01787 /* 01788 struct pr_handle *info = (struct pr_handle *) p; 01789 indent (info); 01790 TRACE_FPRINTF( (info->f, "const double %s = %g;\n", name, val)); 01791 */ 01792 return true; 01793 } 01794 01795 /* Output a typed constant. */ 01796 01797 static boolean 01798 pr_typed_constant (p, name, val) 01799 PTR p; 01800 const char *name; 01801 bfd_vma val; 01802 { 01803 struct pr_handle *info = (struct pr_handle *) p; 01804 char *t; 01805 01806 t = pop_type (info); 01807 if (t == NULL) 01808 return false; 01809 /* 01810 char ab[20]; 01811 indent (info); 01812 print_vma (val, ab, false, false); 01813 TRACE_FPRINTF( (info->f, "const %s %s = %s;\n", t, name, ab)); 01814 */ 01815 free (t); 01816 01817 return true; 01818 } 01819 01820 /* Output a variable. */ 01821 01822 static boolean 01823 pr_variable (p, name, kind, val) 01824 PTR p; 01825 const char *name; 01826 enum debug_var_kind kind; 01827 bfd_vma val; 01828 { 01829 struct pr_handle *info = (struct pr_handle *) p; 01830 char *t; 01831 char ab[20]; 01832 (void)ab; 01833 01834 if (! substitute_type (info, name)) 01835 return false; 01836 01837 t = pop_type (info); 01838 if (t == NULL) 01839 return false; 01840 01841 #if 0 01842 indent (info); 01843 switch (kind) 01844 { 01845 case DEBUG_STATIC: 01846 case DEBUG_LOCAL_STATIC: 01847 TRACE_FPRINTF( (info->f, "static ")); 01848 break; 01849 case DEBUG_REGISTER: 01850 TRACE_FPRINTF( (info->f, "register ")); 01851 break; 01852 default: 01853 break; 01854 } 01855 print_vma (val, ab, true, true); 01856 TRACE_FPRINTF( (info->f, "%s /* %s */;\n", t, ab)); 01857 #else /* 0 */ 01858 #if 0 01859 if (kind==DEBUG_STATIC || kind==DEBUG_LOCAL_STATIC) { 01860 print_vma (val, ab, true, true); 01861 TRACE_FPRINTF( (info->f, "STATIC_VAR: %s /* %s */;\n", t, ab)); 01862 } 01863 #endif /* 0 */ 01864 #endif /* !0 */ 01865 01866 free (t); 01867 01868 return true; 01869 } 01870 01871 /* Start outputting a function. */ 01872 01873 static boolean 01874 pr_start_function (p, name, global) 01875 PTR p; 01876 const char *name; 01877 boolean global; 01878 { 01879 struct pr_handle *info = (struct pr_handle *) p; 01880 char *t; 01881 01882 if (! substitute_type (info, name)) 01883 return false; 01884 01885 t = pop_type (info); 01886 if (t == NULL) 01887 return false; 01888 01889 #if 0 01890 indent (info); 01891 if (! global) 01892 TRACE_FPRINTF( (info->f, "static ")); 01893 TRACE_FPRINTF( (info->f, "%s (", t)); 01894 info->parameter = 1; 01895 #else /* 0 */ 01896 if (info->functions_size==info->functions_maxsize) { 01897 info->functions_maxsize *= 2; 01898 info->functions = xrealloc(info->functions, 01899 info->functions_maxsize*sizeof(debug_function_t)); 01900 assert(info->functions!=0); 01901 } 01902 /* info->functions[info->functions_size] = xmalloc(sizeof(debug_function_t)); */ 01903 info->function = &info->functions[info->functions_size]; 01904 ++info->functions_size; 01905 info->function->symbol = NULL; 01906 info->function->lines = NULL; 01907 info->function->lines_count = 0; 01908 info->function->max_lines_count = 0; 01909 info->function->name = t; 01910 info->function->filename = NULL; 01911 info->function->block = NULL; 01912 info->function->argv = NULL; 01913 info->function->argc = 0; 01914 info->function->max_argc = 0; 01915 #endif /* !0 */ 01916 return true; 01917 } 01918 01919 /* Output a function parameter. */ 01920 01921 static boolean 01922 pr_function_parameter (p, name, kind, val) 01923 PTR p; 01924 const char *name; 01925 enum debug_parm_kind kind; 01926 bfd_vma val; 01927 { 01928 struct pr_handle *info = (struct pr_handle *) p; 01929 debug_function_t* f = info->function; 01930 char *t; 01931 char ab[20]; 01932 (void)ab; 01933 01934 if (kind == DEBUG_PARM_REFERENCE 01935 || kind == DEBUG_PARM_REF_REG) 01936 { 01937 if (! pr_reference_type (p)) 01938 return false; 01939 } 01940 01941 if (! substitute_type (info, name)) 01942 return false; 01943 01944 t = pop_type (info); 01945 if (t == NULL) 01946 return false; 01947 01948 #if 0 01949 if (info->parameter != 1) 01950 TRACE_FPRINTF( (info->f, ", ")); 01951 01952 if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG) 01953 TRACE_FPRINTF( (info->f, "register ")); 01954 01955 print_vma (val, ab, true, true); 01956 TRACE_FPRINTF( (info->f, "%s /* %s */", t, ab)); 01957 free (t); 01958 ++info->parameter; 01959 #else /* 0 */ 01960 assert(f!=NULL); 01961 if (f->argv==NULL) { 01962 f->max_argc = 7; /* rarely anyone has more than that many args... */ 01963 f->argv = xmalloc(sizeof(debug_parameter_t)*f->max_argc); 01964 } else if (f->argc==f->max_argc) { 01965 f->max_argc *= 2; 01966 f->argv = realloc(f->argv,sizeof(debug_parameter_t)*f->max_argc); 01967 } 01968 f->argv[f->argc].offset = val; 01969 f->argv[f->argc].name = t; 01970 ++f->argc; 01971 #endif /* !0 */ 01972 return true; 01973 } 01974 01975 /* Start writing out a block. */ 01976 01977 static boolean 01978 pr_start_block (p, addr) 01979 PTR p; 01980 bfd_vma addr; 01981 { 01982 struct pr_handle *info = (struct pr_handle *) p; 01983 char ab[20]; 01984 debug_block_t* block = 0; 01985 (void)ab; 01986 #if 0 01987 if (info->parameter > 0) 01988 { 01989 TRACE_FPRINTF( (info->f, ")\n")); 01990 info->parameter = 0; 01991 } 01992 indent (info); 01993 print_vma (addr, ab, true, true); 01994 TRACE_FPRINTF( (info->f, "{ /* %s */\n", ab)); 01995 info->indent += 2; 01996 #else 01997 if (info->block) { 01998 if (info->block->childs_count==0) 01999 info->block->childs = xmalloc(sizeof(debug_block_t)); 02000 else 02001 info->block->childs = xrealloc(info->block->childs, 02002 info->block->childs_count*sizeof(debug_block_t)); 02003 block = &info->block->childs[info->block->childs_count]; 02004 } else { 02005 block = xmalloc(sizeof(debug_block_t)); 02006 info->function->block = block; 02007 } 02008 block->begin_addr = addr; 02009 block->end_addr = 0; 02010 block->parent = info->block; 02011 block->childs = NULL; 02012 block->childs_count = 0; 02013 info->block = block; 02014 #endif 02015 return true; 02016 } 02017 02018 /* Write out line number information. */ 02019 02020 static boolean 02021 pr_lineno (p, filename, lineno, addr) 02022 PTR p; 02023 const char *filename; 02024 unsigned long lineno; 02025 bfd_vma addr; 02026 { 02027 struct pr_handle *info = (struct pr_handle *) p; 02028 char ab[20]; 02029 debug_function_t* f = info->function; 02030 (void)ab; 02031 02032 #if 0 02033 indent (info); 02034 print_vma (addr, ab, true, true); 02035 TRACE_FPRINTF( (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab)); 02036 #else /* 0 */ 02037 if (f==NULL) /* FIXME: skips junk silently. */ 02038 return true; 02039 /* assert(f!=NULL); */ 02040 if (f->filename==NULL) { 02041 f->filename = filename; 02042 assert(f->lines==0); 02043 f->max_lines_count = 4; 02044 f->lines = xmalloc(sizeof(debug_lineno_t)*f->max_lines_count); 02045 } 02046 if (f->lines_count==f->max_lines_count) { 02047 f->max_lines_count *= 2; 02048 f->lines = xrealloc(f->lines, sizeof(debug_lineno_t)*f->max_lines_count); 02049 } 02050 f->lines[f->lines_count].lineno = lineno; 02051 f->lines[f->lines_count].addr = addr; 02052 ++f->lines_count; 02053 #endif /* !0 */ 02054 02055 return true; 02056 } 02057 02058 /* Finish writing out a block. */ 02059 02060 static boolean 02061 pr_end_block (p, addr) 02062 PTR p; 02063 bfd_vma addr; 02064 { 02065 struct pr_handle *info = (struct pr_handle *) p; 02066 02067 #if 0 02068 char ab[20]; 02069 02070 info->indent -= 2; 02071 indent (info); 02072 print_vma (addr, ab, true, true); 02073 TRACE_FPRINTF( (info->f, "} /* %s */\n", ab)); 02074 #else /* 0 */ 02075 assert(info->block!=0); 02076 info->block->end_addr = addr; 02077 info->block = info->block->parent; 02078 #endif /* !0 */ 02079 02080 return true; 02081 } 02082 02083 /* Finish writing out a function. */ 02084 02085 /*ARGSUSED*/ 02086 static boolean 02087 pr_end_function (p) 02088 PTR p; 02089 { 02090 struct pr_handle *info = (struct pr_handle *) p; 02091 assert(info->block==0); 02092 info->function = NULL; 02093 return true; 02094 } 02095 02096 /* third parameter to segv_action. */ 02097 /* Got it after a bit of head scratching and stack dumping. */ 02098 typedef struct { 02099 u_int32_t foo1; /* +0x00 */ 02100 u_int32_t foo2; 02101 u_int32_t foo3; 02102 u_int32_t foo4; /* usually 2 */ 02103 u_int32_t foo5; /* +0x10 */ 02104 u_int32_t xgs; /* always zero */ 02105 u_int32_t xfs; /* always zero */ 02106 u_int32_t xes; /* always es=ds=ss */ 02107 u_int32_t xds; /* +0x20 */ 02108 u_int32_t edi; 02109 u_int32_t esi; 02110 u_int32_t ebp; 02111 u_int32_t esp; /* +0x30 */ 02112 u_int32_t ebx; 02113 u_int32_t edx; 02114 u_int32_t ecx; 02115 u_int32_t eax; /* +0x40 */ 02116 u_int32_t foo11; /* usually 0xe */ 02117 u_int32_t foo12; /* usually 0x6 */ 02118 u_int32_t eip; /* instruction pointer */ 02119 u_int32_t xcs; /* +0x50 */ 02120 u_int32_t foo21; /* usually 0x2 */ 02121 u_int32_t foo22; /* second stack pointer?! Probably. */ 02122 u_int32_t xss; 02123 u_int32_t foo31; /* +0x60 */ /* usually 0x0 */ 02124 u_int32_t foo32; /* usually 0x2 */ 02125 u_int32_t fault_addr; /* Address which caused a fault */ 02126 u_int32_t foo41; /* usually 0x2 */ 02127 } signal_regs_t; 02128 02129 signal_regs_t* ptrace_regs = 0; /* Tells my_ptrace to "ptrace" current process" */ 02130 /* 02131 * my_ptrace: small wrapper around ptrace. 02132 * Act as normal ptrace if ptrace_regs==0. 02133 * Read data from current process if ptrace_regs!=0. 02134 */ 02135 static int 02136 my_ptrace( int request, 02137 int pid, 02138 int addr, 02139 int data) 02140 { 02141 if (ptrace_regs==0) 02142 return ptrace(request, pid, addr, data); 02143 /* we are tracing ourselves! */ 02144 switch (request) { 02145 case PTRACE_ATTACH: return 0; 02146 case PTRACE_CONT: return 0; 02147 case PTRACE_DETACH: return 0; 02148 case PTRACE_PEEKUSER: 02149 switch (addr / 4) { 02150 case EIP: return ptrace_regs->eip; 02151 case EBP: return ptrace_regs->ebp; 02152 default: assert(0); 02153 } 02154 case PTRACE_PEEKTEXT: /* FALLTHROUGH */ 02155 case PTRACE_PEEKDATA: return *(int*)(addr); 02156 default: assert(0); 02157 } 02158 errno = 1; /* what to do here? */ 02159 return 1; /* failed?! */ 02160 } 02161 02162 #define MAXARGS 6 02163 02164 /* 02165 * To minimize the number of parameters. 02166 */ 02167 typedef struct { 02168 asymbol** syms; /* Sorted! */ 02169 int symcount; 02170 debug_function_t** functions; 02171 int functions_size; 02172 } symbol_data_t; 02173 02174 /* 02175 * Perform a search. A binary search for a symbol. 02176 */ 02177 static void 02178 decode_symbol( symbol_data_t* symbol_data, 02179 const unsigned long addr, 02180 char* buf, 02181 const int bufsize) 02182 { 02183 asymbol** syms = symbol_data->syms; 02184 const int symcount = symbol_data->symcount; 02185 int bottom = 0; 02186 int top = symcount - 1; 02187 int i; 02188 if (symcount==0) { 02189 sprintf(buf, "????"); 02190 return; 02191 } 02192 while (top>bottom+1) { 02193 i = (top+bottom) / 2; 02194 if (bfd_asymbol_value(syms[i])==addr) { 02195 sprintf(buf, "%s", syms[i]->name); 02196 return; 02197 } else if (bfd_asymbol_value(syms[i]) > addr) 02198 top = i; 02199 else 02200 bottom = i; 02201 } 02202 i = bottom; 02203 if (addr<bfd_asymbol_value(syms[i]) || addr>(syms[i]->section->vma+syms[i]->section->_cooked_size)) 02204 sprintf(buf, "????"); 02205 else 02206 sprintf(buf, "%s + 0x%lx", syms[i]->name, addr-bfd_asymbol_value(syms[i])); 02207 } 02208 02209 /* 02210 * 1. Perform a binary search for an debug_function_t. 02211 * 2. Fill buf/bufsize with name, parameters and lineno, if found 02212 * Or with '????' otherwise. 02213 */ 02214 static debug_function_t* 02215 find_debug_function_t( symbol_data_t* symbol_data, 02216 const pid_t pid, 02217 const unsigned long fp, /* frame pointer */ 02218 const unsigned long addr, 02219 char* buf, /* string buffer */ 02220 const int bufsize)/* FIXME: not used! */ 02221 { 02222 debug_function_t** syms = symbol_data->functions; 02223 debug_function_t* f = NULL; 02224 debug_block_t* block = NULL; 02225 debug_lineno_t* lineno = NULL; 02226 const int symcount = symbol_data->functions_size; 02227 int bottom = 0; 02228 int top = symcount - 1; 02229 int i; 02230 char* bufptr = buf; 02231 02232 if (symcount==0) { 02233 sprintf(buf, "????"); 02234 return NULL; 02235 } 02236 while (top>bottom+1) { 02237 i = (top+bottom) / 2; 02238 if (syms[i]->block->begin_addr==addr) { 02239 f = syms[i]; 02240 break; 02241 } else if (syms[i]->block->begin_addr > addr) 02242 top = i; 02243 else 02244 if (syms[i]->block->end_addr >= addr) { 02245 f = syms[i]; 02246 break; 02247 } else 02248 bottom = i; 02249 } 02250 i = bottom; 02251 if (f!=0) 02252 block = f->block; 02253 else { 02254 block = syms[i]->block; 02255 if (block->begin_addr>=addr && block->end_addr<=addr) 02256 f = syms[i]; 02257 } 02258 if (f==0) 02259 sprintf(buf, "????"); 02260 else { 02261 /* 02262 * Do the backtrace the GDB way... 02263 */ 02264 unsigned long arg; 02265 /* assert(f->lines_count>0); */ 02266 if (f->lines_count>0) { 02267 lineno = &f->lines[f->lines_count-1]; 02268 for (i=1; i<f->lines_count; ++i) 02269 if (f->lines[i].addr>addr) { 02270 lineno = &f->lines[i-1]; 02271 break; 02272 } 02273 } 02274 bufptr[0] = 0; 02275 bufptr += sprintf(bufptr, "%s+0x%lx (", f->name, addr-block->begin_addr); 02276 for (i=0; i<f->argc; ++i) { 02277 bufptr += sprintf(bufptr, "%s = ", f->argv[i].name); 02278 /* FIXME: better parameter printing */ 02279 errno = 0; 02280 arg = my_ptrace(PTRACE_PEEKDATA, pid, fp+f->argv[i].offset, 0); 02281 assert(errno==0); 02282 bufptr += sprintf(bufptr, "0x%x", arg); 02283 if (i!=f->argc-1) 02284 bufptr += sprintf(bufptr, ", "); 02285 } 02286 if (lineno!=0) 02287 bufptr += sprintf(bufptr, ") at %s:%d", f->filename, lineno->lineno); 02288 } 02289 return f; 02290 } 02291 02292 /* 02293 * Advance through the stacks and display frames as needed. 02294 */ 02295 static int 02296 my_crawl( int pid, 02297 symbol_data_t* symbol_data, 02298 int fout) 02299 { 02300 unsigned long pc = 0; 02301 unsigned long fp = 0; 02302 unsigned long nextfp; 02303 unsigned long nargs; 02304 unsigned long i; 02305 unsigned long arg; 02306 char buf[8096]; // FIXME: enough? 02307 debug_function_t* f = 0; 02308 02309 errno = 0; 02310 02311 pc = my_ptrace(PTRACE_PEEKUSER, pid, EIP * 4, 0); 02312 if (!errno) 02313 fp = my_ptrace(PTRACE_PEEKUSER, pid, EBP * 4, 0); 02314 02315 if (!errno) { 02316 #if 1 02317 f = find_debug_function_t(symbol_data, pid, fp, pc, buf, sizeof(buf)); 02318 fdprintf(fout,"0x%08lx: %s", pc, buf); 02319 for ( ; !errno && fp; ) { 02320 nextfp = my_ptrace(PTRACE_PEEKDATA, pid, fp, 0); 02321 if (errno) 02322 break; 02323 02324 if (f==0) { 02325 nargs = (nextfp - fp - 8) / 4; 02326 if (nargs > MAXARGS) 02327 nargs = MAXARGS; 02328 if (nargs > 0) { 02329 fdputs(" (", fout); 02330 for (i = 1; i <= nargs; i++) { 02331 arg = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4 * (i + 1), 0); 02332 if (errno) 02333 break; 02334 fdprintf(fout,"%lx", arg); 02335 if (i < nargs) 02336 fdputs(", ", fout); 02337 } 02338 fdputc(')', fout); 02339 nargs = nextfp - fp - 8 - (4 * nargs); 02340 if (!errno && nargs > 0) 02341 fdprintf(fout," + %lx\n", nargs); 02342 else 02343 fdputc('\n', fout); 02344 } else 02345 fdputc('\n', fout); 02346 } else 02347 fdputc('\n', fout); 02348 02349 if (errno || !nextfp) 02350 break; 02351 pc = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4, 0); 02352 fp = nextfp; 02353 if (errno) 02354 break; 02355 f = find_debug_function_t(symbol_data, pid, fp, pc, buf, sizeof(buf)); 02356 fdprintf(fout,"0x%08lx: %s", pc, buf); 02357 } 02358 #else /* 1 */ 02359 decode_symbol(symbol_data, pc, buf, sizeof(buf)); 02360 fdprintf(fout,"0x%08lx: %s", pc, buf); 02361 for ( ; !errno && fp; ) { 02362 nextfp = my_ptrace(PTRACE_PEEKDATA, pid, fp, 0); 02363 if (errno) 02364 break; 02365 02366 nargs = (nextfp - fp - 8) / 4; 02367 if (nargs > MAXARGS) 02368 nargs = MAXARGS; 02369 if (nargs > 0) { 02370 fputs(" (", fout); 02371 for (i = 1; i <= nargs; i++) { 02372 arg = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4 * (i + 1), 0); 02373 if (errno) 02374 break; 02375 fdprintf(fout,"%lx", arg); 02376 if (i < nargs) 02377 fputs(", ", fout); 02378 } 02379 fdputc(')', fout); 02380 nargs = nextfp - fp - 8 - (4 * nargs); 02381 if (!errno && nargs > 0) 02382 fdprintf(fout," + %lx\n", nargs); 02383 else 02384 fdputc('\n', fout); 02385 } else 02386 fdputc('\n', fout); 02387 02388 if (errno || !nextfp) 02389 break; 02390 pc = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4, 0); 02391 fp = nextfp; 02392 if (errno) 02393 break; 02394 decode_symbol(symbol_data, pc, buf, sizeof(buf)); 02395 fdprintf(fout,"0x%08lx: %s", pc, buf); 02396 } 02397 #endif /* !1 */ 02398 } 02399 if (errno) 02400 perror("my_crawl"); 02401 return errno; 02402 } 02403 02404 /* layout from /usr/src/linux/arch/i386/kernel/process.c */ 02405 static void 02406 show_regs( signal_regs_t* regs, 02407 int fd) 02408 { 02409 /* long cr0 = 0L, cr2 = 0L, cr3 = 0L; */ 02410 02411 fdprintf(fd,"\n"); 02412 fdprintf(fd,"FAULT ADDR: %08x\n", regs->fault_addr); 02413 fdprintf(fd,"EIP: %04x:[<%08x>]",0xffff & regs->xcs,regs->eip); 02414 if (regs->xcs & 3) 02415 fdprintf(fd," ESP: %04x:%08x",0xffff & regs->xss,regs->esp); 02416 /*fdprintf(fd," EFLAGS: %08lx\n",regs->eflags); */ 02417 fdprintf(fd, "\n"); 02418 fdprintf(fd,"EAX: %08x EBX: %08x ECX: %08x EDX: %08x\n", 02419 regs->eax,regs->ebx,regs->ecx,regs->edx); 02420 fdprintf(fd,"ESI: %08x EDI: %08x EBP: %08x", 02421 regs->esi, regs->edi, regs->ebp); 02422 fdprintf(fd," DS: %04x ES: %04x\n", 02423 0xffff & regs->xds,0xffff & regs->xes); 02424 /* 02425 __asm__("movl %%cr0, %0": "=r" (cr0)); 02426 __asm__("movl %%cr2, %0": "=r" (cr2)); 02427 __asm__("movl %%cr3, %0": "=r" (cr3)); 02428 fprintf(stderr,"CR0: %08lx CR2: %08lx CR3: %08lx\n", cr0, cr2, cr3); */ 02429 } 02430 02431 /* 02432 * Load a BFD for an executable based on PID. Return 0 on failure. 02433 */ 02434 static bfd* 02435 load_bfd( const int pid) 02436 { 02437 char filename[512]; 02438 bfd* abfd = 0; 02439 02440 /* Get the contents from procfs. */ 02441 #if 1 02442 sprintf(filename, "/proc/%d/exe", pid); 02443 #else 02444 sprintf(filename, "crashing"); 02445 #endif 02446 02447 if ((abfd = bfd_openr (filename, 0))== NULL) 02448 bfd_nonfatal (filename); 02449 else { 02450 char** matching; 02451 assert(bfd_check_format(abfd, bfd_archive)!=true); 02452 02453 /* 02454 * There is no indication in BFD documentation that it should be done. 02455 * God knows why... 02456 */ 02457 if (!bfd_check_format_matches (abfd, bfd_object, &matching)) { 02458 bfd_nonfatal (bfd_get_filename (abfd)); 02459 if (bfd_get_error () == bfd_error_file_ambiguously_recognized) { 02460 list_matching_formats (matching); 02461 free (matching); 02462 } 02463 } 02464 } 02465 return abfd; 02466 } 02467 02468 /* 02469 * Those are for qsort. We need only function addresses, so all the others don't count. 02470 */ 02471 /* 02472 * Compare two BFD::asymbol-s. 02473 */ 02474 static int 02475 compare_symbols(const void* ap, 02476 const void* bp) 02477 { 02478 const asymbol *a = *(const asymbol **)ap; 02479 const asymbol *b = *(const asymbol **)bp; 02480 if (bfd_asymbol_value (a) > bfd_asymbol_value (b)) 02481 return 1; 02482 else if (bfd_asymbol_value (a) < bfd_asymbol_value (b)) 02483 return -1; 02484 return 0; 02485 } 02486 02487 /* 02488 * Compare two debug_asymbol_t-s. 02489 */ 02490 static int 02491 compare_debug_function_t(const void* ap, 02492 const void* bp) 02493 { 02494 const debug_function_t *a = *(const debug_function_t **)ap; 02495 const debug_function_t *b = *(const debug_function_t **)bp; 02496 assert(a->block!=0); 02497 assert(b->block!=0); 02498 { 02499 const bfd_vma addr1 = a->block->begin_addr; 02500 const bfd_vma addr2 = b->block->begin_addr; 02501 if (addr1 > addr2) 02502 return 1; 02503 else if (addr2 > addr1) 02504 return -1; 02505 } 02506 return 0; 02507 } 02508 02509 /* 02510 * Filter out (in place) symbols that are useless for stack tracing. 02511 * COUNT is the number of elements in SYMBOLS. 02512 * Return the number of useful symbols. 02513 */ 02514 02515 static long 02516 remove_useless_symbols( asymbol** symbols, 02517 long count) 02518 { 02519 asymbol** in_ptr = symbols; 02520 asymbol** out_ptr = symbols; 02521 02522 while (--count >= 0) { 02523 asymbol *sym = *in_ptr++; 02524 02525 if (sym->name == NULL || sym->name[0] == '\0' || sym->value==0) 02526 continue; 02527 if (sym->flags & (BSF_DEBUGGING)) 02528 continue; 02529 if (bfd_is_und_section (sym->section) || bfd_is_com_section (sym->section)) 02530 continue; 02531 *out_ptr++ = sym; 02532 } 02533 return out_ptr - symbols; 02534 } 02535 02536 /* 02537 * Debugging information. 02538 */ 02539 static bfd* abfd = 0; 02540 static PTR dhandle = 0; 02541 static asymbol** syms = 0; 02542 static long symcount = 0; 02543 static asymbol** sorted_syms = 0; 02544 static long sorted_symcount = 0; 02545 static debug_function_t** functions = 0; 02546 static int functions_size = 0; 02547 static int sigreport = SIGUSR1; 02548 static pthread_t segv_tid; /* What thread did SEGV? */ 02549 static pid_t segv_pid; 02550 02551 /* 02552 * We'll get here after a SIGSEGV. But you can install it on other signals, too :) 02553 * Because we are in the middle of the SIGSEGV, we are on our own. We can't do 02554 * any malloc(), any fopen(), nothing. The last is actually a sin. We event can't 02555 * fprintf(stderr,...)!!! 02556 */ 02557 static void 02558 segv_action(int signo, siginfo_t* siginfo, void* ptr) 02559 { 02560 symbol_data_t symbol_data; 02561 int fd = -1; 02562 02563 segv_pid = getpid(); 02564 segv_tid = pthread_self(); 02565 fd = open_log_file(segv_tid, segv_pid); 02566 /* signal(SIGSEGV, SIG_DFL); */ 02567 ptrace_regs = (signal_regs_t*)ptr; 02568 assert(ptrace_regs!=0); 02569 02570 /* Show user how guilty we are. */ 02571 fdprintf(fd,"--------- SEGV in PROCESS %d, THREAD %d ---------------\n", segv_pid, pthread_self()); 02572 show_regs(ptrace_regs, fd); 02573 02574 /* Some form of stack trace, too. */ 02575 fdprintf(fd, "STACK TRACE:\n"); 02576 02577 symbol_data.syms = sorted_syms; 02578 symbol_data.symcount = sorted_symcount; 02579 symbol_data.functions = functions; 02580 symbol_data.functions_size = functions_size; 02581 my_crawl(segv_pid, &symbol_data, fd); 02582 //fflush(stdout); 02583 close(fd); 02584 linuxthreads_notify_others(sigreport); 02585 } 02586 02587 02588 static void 02589 report_action(int signo, siginfo_t* siginfo, void* ptr) 02590 { 02591 const int pid = getpid(); 02592 pthread_t tid = pthread_self(); 02593 symbol_data_t symbol_data; 02594 int fd; 02595 if (pthread_equal(tid, segv_tid)) { 02596 /* We have already printed our stack trace... */ 02597 return; 02598 } 02599 02600 fd = open_log_file(tid, pid); 02601 fdprintf(fd, "REPORT: CURRENT PROCESS:%d, THREAD:%d\n", getpid(), pthread_self()); 02602 /* signal(SIGSEGV, SIG_DFL); */ 02603 ptrace_regs = (signal_regs_t*)ptr; 02604 assert(ptrace_regs!=0); 02605 02606 /* Show user how guilty we are. */ 02607 fdprintf(fd,"--------- STACK TRACE FOR PROCESS %d, THREAD %d ---------------\n", pid, pthread_self()); 02608 show_regs(ptrace_regs, fd); 02609 02610 /* Some form of stack trace, too. */ 02611 fdprintf(fd, "STACK TRACE:\n"); 02612 02613 symbol_data.syms = sorted_syms; 02614 symbol_data.symcount = sorted_symcount; 02615 symbol_data.functions = functions; 02616 symbol_data.functions_size = functions_size; 02617 my_crawl(pid, &symbol_data, fd); 02618 //fflush(stdout); 02619 close(fd); 02620 /* Tell segv_thread to proceed after pause(). */ 02621 /*pthread_kill(segv_tid, sigreport); 02622 kill(segv_pid, sigreport); 02623 pthread_cancel(tid); */ 02624 } 02625 02626 /* 02627 * Main library routine. Just call it on your program. 02628 */ 02629 int 02630 pstack_install_segv_action( const char* path_format_) 02631 { 02632 const int pid = getpid(); 02633 struct sigaction act; 02634 02635 /* Store what we have to for later usage. */ 02636 path_format = path_format_; 02637 02638 /* We need a signal action for SIGSEGV and sigreport ! */ 02639 sigreport = SIGUSR1; 02640 act.sa_handler = 0; 02641 sigemptyset(&act.sa_mask); 02642 act.sa_flags = SA_SIGINFO|SA_ONESHOT; /* Just one SIGSEGV. */ 02643 act.sa_sigaction = segv_action; 02644 act.sa_restorer = NULL; 02645 if (sigaction(SIGSEGV, &act, NULL)!=0) { 02646 perror("sigaction"); 02647 return 1; 02648 } 02649 act.sa_sigaction = report_action; 02650 act.sa_flags = SA_SIGINFO; /* But many sigreports. */ 02651 if (sigaction(sigreport, &act, NULL)!=0) { 02652 perror("sigaction"); 02653 return 1; 02654 } 02655 02656 /* And a little setup for libiberty. */ 02657 program_name = "crashing"; 02658 xmalloc_set_program_name (program_name); 02659 02660 /* Umm, and initialize BFD, too */ 02661 bfd_init(); 02662 #if 0 02663 list_supported_targets(0, stdout); 02664 set_default_bfd_target(); 02665 #endif /* 0 */ 02666 02667 if ((abfd = load_bfd(pid))==0) 02668 fprintf(stderr, "BFD load failed..\n"); 02669 else { 02670 long storage_needed= (bfd_get_file_flags(abfd) & HAS_SYMS) ? 02671 bfd_get_symtab_upper_bound (abfd) : 0; 02672 long i; 02673 (void)i; 02674 02675 if (storage_needed < 0) 02676 fprintf(stderr, "Symbol table size estimation failure.\n"); 02677 else if (storage_needed > 0) { 02678 syms = (asymbol **) xmalloc (storage_needed); 02679 symcount = bfd_canonicalize_symtab (abfd, syms); 02680 02681 TRACE_FPRINTF((stderr, "TOTAL: %ld SYMBOLS.\n", symcount)); 02682 /* We need debugging info, too! */ 02683 if (symcount==0 || (dhandle = read_debugging_info (abfd, syms, symcount))==0) 02684 fprintf(stderr, "NO DEBUGGING INFORMATION FOUND.\n"); 02685 02686 /* We make a copy of syms to sort. We don't want to sort syms 02687 because that will screw up the relocs. */ 02688 sorted_syms = (asymbol **) xmalloc (symcount * sizeof (asymbol *)); 02689 memcpy (sorted_syms, syms, symcount * sizeof (asymbol *)); 02690 02691 #if 0 02692 for (i=0; i<symcount; ++i) 02693 if (syms[i]->name!=0 && strlen(syms[i]->name)>0 && syms[i]->value!=0) 02694 printf("%08lx T %s\n", syms[i]->section->vma + syms[i]->value, syms[i]->name); 02695 #endif 02696 sorted_symcount = remove_useless_symbols (sorted_syms, symcount); 02697 TRACE_FPRINTF((stderr, "SORTED: %ld SYMBOLS.\n", sorted_symcount)); 02698 02699 /* Sort the symbols into section and symbol order */ 02700 qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols); 02701 #if 0 02702 for (i=0; i<sorted_symcount; ++i) 02703 if (sorted_syms[i]->name!=0 && strlen(sorted_syms[i]->name)>0 && sorted_syms[i]->value!=0) 02704 printf("%08lx T %s\n", sorted_syms[i]->section->vma + sorted_syms[i]->value, sorted_syms[i]->name); 02705 #endif 02706 /* We have symbols, we need debugging info somehow sorted out. */ 02707 if (dhandle==0) { 02708 fprintf(stderr, "STACK TRACE WILL BE UNCOMFORTABLE.\n"); 02709 } else { 02710 /* Start collecting the debugging information.... */ 02711 struct pr_handle info; 02712 02713 info.f = stdout; 02714 info.indent = 0; 02715 info.stack = NULL; 02716 info.parameter = 0; 02717 info.block = NULL; 02718 info.function = NULL; 02719 info.functions_size = 0; 02720 info.functions_maxsize = 1000; 02721 info.functions = (debug_function_t*)xmalloc(sizeof(debug_function_t)*info.functions_maxsize); 02722 debug_write (dhandle, &pr_fns, (PTR) &info); 02723 TRACE_FPRINTF((stdout, "\n%d DEBUG SYMBOLS\n", info.functions_size)); 02724 assert(info.functions_size!=0); 02725 functions = xmalloc(sizeof(debug_function_t*)*info.functions_size); 02726 functions_size = info.functions_size; 02727 for (i=0; i<functions_size; ++i) 02728 functions[i] = &info.functions[i]; 02729 /* Sort the symbols into section and symbol order */ 02730 qsort (functions, functions_size, sizeof(debug_function_t*), 02731 compare_debug_function_t); 02732 #if 0 02733 for (i=0; i<info.functions_size; ++i) 02734 fprintf(stdout, "%08lx T %s\n", info.functions[i].block->begin_addr, info.functions[i].name); 02735 #endif 02736 fflush(stdout); 02737 } 02738 } else /* storage_needed == 0 */ 02739 fprintf(stderr, "NO SYMBOLS FOUND.\n"); 02740 } 02741 return 0; 02742 } 02743 02744 /*********************************************************************/ 02745 /*********************************************************************/ 02746 /*********************************************************************/
1.4.7

