| /* ----------------------------------------------------------------------------- |
| * default.c |
| * |
| * Default signal handler. Just prints a stack trace and returns. |
| * |
| * Author(s) : David Beazley (beazley@cs.uchicago.edu) |
| * |
| * Copyright (C) 2000. The University of Chicago. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| * |
| * See the file COPYING for a complete copy of the LGPL. |
| * ----------------------------------------------------------------------------- */ |
| |
| #include "wad.h" |
| |
| static char cvs[] = "$Header$"; |
| |
| #include <sys/mman.h> |
| |
| |
| /* This function tries to produce some kind of sensible argument |
| string for a stack frame. If no debugging information is available, |
| we'll just dump the %i0-%i5 registers in hex. If debugging information |
| is available, we'll try to do something a little more sensible */ |
| |
| char *wad_arg_string(WadFrame *frame) { |
| static char str[1024]; |
| WadLocal *wp; |
| long *stack; |
| long *nextstack; |
| long *prevstack; |
| int i; |
| WadFrame *nf; |
| WadFrame *pf; |
| |
| nf = frame->next; |
| if (nf) |
| nextstack = (long *) nf->stack; |
| else |
| nextstack = 0; |
| |
| pf = frame->prev; |
| if (pf) |
| prevstack = (long *) pf->stack; |
| else |
| prevstack = 0; |
| |
| str[0] = 0; |
| stack = (long *) frame->stack; |
| |
| |
| #ifdef WAD_LINUX |
| if (!nf) { |
| return ""; |
| } |
| #endif |
| |
| if ((frame->debug_nargs < 0) || (0)){ |
| /* No argument information is available. If we are on SPARC, we'll dump |
| the %in registers since these usually hold input parameters. On |
| Linux, we do nothing */ |
| |
| #ifdef WAD_SOLARIS |
| for (i = 0; i < 6; i++) { |
| wad_strcat(str,"0x"); |
| wad_strcat(str,wad_format_hex((unsigned long) stack[8+i],0)); |
| if (i < 5) |
| wad_strcat(str,","); |
| } |
| #endif |
| } else { |
| /* We were able to get some argument information out the debugging table */ |
| wp = frame->debug_args; |
| for (i = 0; i < frame->debug_nargs; i++, wp = wp->next) { |
| wad_strcat(str,wp->name); |
| wad_strcat(str,"="); |
| wad_strcat(str,wad_format_var(wp)); |
| if (i < (frame->debug_nargs-1)) wad_strcat(str,","); |
| } |
| } |
| return str; |
| |
| } |
| |
| char *wad_strip_dir(char *name) { |
| char *c; |
| /* printf("strip: '%s'\n", name); */ |
| c = name + strlen(name); |
| while (c != name) { |
| if (*c == '/') { |
| c++; |
| return c; |
| } |
| c--; |
| } |
| return name; |
| } |
| |
| |
| |
| static char *src_file = 0; |
| static int src_len = 0; |
| static char src_path[1024] = ""; |
| |
| /* Opens up a source file and tries to locate a specific line number */ |
| |
| char *wad_load_source(char *path, int line) { |
| int fd; |
| char *c; |
| char *start; |
| int n; |
| |
| if (strcmp(src_path,path)) { |
| if (src_file) { |
| munmap(src_file, src_len); |
| src_file = 0; |
| src_len = 0; |
| } |
| fd = open(path, O_RDONLY); |
| if (fd < 0) return 0; |
| src_len = lseek(fd, 0, SEEK_END); |
| lseek(fd,0,SEEK_SET); |
| src_file = (char *)mmap(NULL,src_len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); |
| if (src_file == MAP_FAILED) { |
| close(fd); |
| return 0; |
| } |
| close(fd); |
| wad_strcpy(src_path,path); |
| } |
| n = 0; |
| start = src_file; |
| c = src_file; |
| while (n < src_len) { |
| if (*c == '\n') { |
| line--; |
| if (line == 0) { |
| return start; |
| } |
| start = c+1; |
| } |
| c++; |
| n++; |
| } |
| return 0; |
| } |
| |
| void wad_release_source() { |
| if (src_file) { |
| munmap(src_file,src_len); |
| src_file = 0; |
| src_len = 0; |
| src_path[0] = 0; |
| } |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * wad_debug_src_code(WadFrame *f) |
| * |
| * Get source code for a frame |
| * ----------------------------------------------------------------------------- */ |
| |
| char *wad_debug_src_string(WadFrame *f, int window) { |
| static char temp[16384]; |
| |
| if (f->loc_srcfile && strlen(f->loc_srcfile) && (f->loc_line > 0)) { |
| char *line, *c; |
| int i; |
| int first, last; |
| first = f->loc_line - window; |
| last = f->loc_line + window; |
| if (first < 1) first = 1; |
| line = wad_load_source(f->loc_srcfile,first); |
| if (line) { |
| wad_strcpy(temp,f->loc_srcfile); |
| wad_strcat(temp,", line "); |
| wad_strcat(temp,wad_format_signed(f->loc_line,-1)); |
| wad_strcat(temp,"\n\n"); |
| for (i = first; i <= last; i++) { |
| if (i == f->loc_line) wad_strcat(temp," => "); |
| else wad_strcat(temp," "); |
| c = strchr(line,'\n'); |
| if (c) { |
| *c = 0; |
| wad_strcat(temp,line); |
| wad_strcat(temp,"\n"); |
| *c = '\n'; |
| } else { |
| wad_strcat(temp,line); |
| wad_strcat(temp,"\n"); |
| break; |
| } |
| line = c+1; |
| } |
| f->debug_srcstr = wad_strdup(temp); |
| return f->debug_srcstr; |
| } |
| } |
| f->debug_srcstr = 0; |
| return 0; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * wad_debug_make_strings(WadFrame *f) |
| * |
| * This function walks the stack trace and tries to generate a debugging string |
| * ----------------------------------------------------------------------------- */ |
| |
| void |
| wad_debug_make_strings(WadFrame *f) { |
| static char msg[16384]; |
| while (f) { |
| wad_strcpy(msg,"#"); |
| wad_strcat(msg,wad_format_signed(f->frameno,3)); |
| wad_strcat(msg," 0x"); |
| wad_strcat(msg,wad_format_hex(f->pc,1)); |
| wad_strcat(msg," in "); |
| wad_strcat(msg, f->sym_name ? f->sym_name : "?"); |
| wad_strcat(msg,"("); |
| wad_strcat(msg,wad_arg_string(f)); |
| wad_strcat(msg,")"); |
| if (f->loc_srcfile && strlen(f->loc_srcfile)) { |
| wad_strcat(msg," in '"); |
| wad_strcat(msg, wad_strip_dir(f->loc_srcfile)); |
| wad_strcat(msg,"'"); |
| if (f->loc_line > 0) { |
| wad_strcat(msg,", line "); |
| wad_strcat(msg,wad_format_signed(f->loc_line,-1)); |
| /* Try to locate the source file */ |
| wad_debug_src_string(f, WAD_SRC_WINDOW); |
| } |
| } else { |
| if (f->loc_objfile && strlen(f->loc_objfile)) { |
| wad_strcat(msg," from '"); |
| wad_strcat(msg, wad_strip_dir(f->loc_objfile)); |
| wad_strcat(msg,"'"); |
| } |
| } |
| wad_strcat(msg,"\n"); |
| f->debug_str = wad_strdup(msg); |
| f = f->next; |
| } |
| } |
| |
| /* Dump trace to a file */ |
| void wad_dump_trace(int fd, int signo, WadFrame *f, char *ret) { |
| static char buffer[128]; |
| char *srcstr = 0; |
| |
| switch(signo) { |
| case SIGSEGV: |
| write(fd,"WAD: Segmentation fault.\n", 25); |
| break; |
| case SIGBUS: |
| write(fd,"WAD: Bus error.\n",17); |
| break; |
| case SIGABRT: |
| write(fd,"WAD: Abort.\n",12); |
| break; |
| case SIGFPE: |
| write(fd,"WAD: Floating point exception.\n", 31); |
| break; |
| case SIGILL: |
| write(fd,"WAD: Illegal instruction.\n", 26); |
| break; |
| default: |
| sprintf(buffer,"WAD: Signal %d\n", signo); |
| write(fd,buffer,strlen(buffer)); |
| break; |
| } |
| /* Find the last exception frame */ |
| |
| while (f && !(f->last)) { |
| f = f->next; |
| } |
| |
| while (f) { |
| write(fd,f->debug_str,strlen(f->debug_str)); |
| if (f->debug_srcstr) { |
| srcstr = f->debug_srcstr; |
| } |
| f = f->prev; |
| } |
| if (srcstr) { |
| write(fd,"\n",1); |
| write(fd,srcstr,strlen(srcstr)); |
| write(fd,"\n",1); |
| } |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Default callback |
| * ----------------------------------------------------------------------------- */ |
| |
| void wad_default_callback(int signo, WadFrame *f, char *ret) { |
| wad_dump_trace(2,signo,f,ret); |
| } |
| |