| /* ----------------------------------------------------------------------------- |
| * vars.c |
| * |
| * This file examines the stack trace and tries to make some sense out of |
| * collected debugging information. This includes locating the data on |
| * the stack and/or registers. |
| * |
| * This feature is detached from the debugging info collector to make |
| * it independent of debugging formats. |
| * |
| * 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[] = "$Id$"; |
| |
| /* ----------------------------------------------------------------------------- |
| * wad_build_vars() |
| * |
| * Build variable information for a single stack frame |
| * ----------------------------------------------------------------------------- */ |
| |
| void wad_build_vars(WadFrame *f) { |
| char *stack = 0; |
| char *nstack = 0; |
| char *pstack = 0; |
| WadLocal *loc; |
| int n; |
| |
| stack = (char *) f->stack; |
| if (f->next) { |
| nstack = (char *) f->next->stack; |
| } |
| if (f->prev) { |
| pstack = (char *) f->prev->stack; |
| } |
| |
| for (n = 0; n < 2; n++) { |
| if (n == 0) loc = f->debug_args; |
| else loc = f->debug_locals; |
| |
| while (loc) { |
| loc->ptr = 0; |
| if (loc->loc == PARM_STACK) { |
| if ((loc->stack >= 0) && (nstack)) { |
| loc->ptr = (void *) (nstack + loc->stack); |
| } else if (loc->stack < 0) { |
| loc->ptr = (void *) (stack + f->stack_size + loc->stack); |
| } |
| loc->size = sizeof(long); |
| } |
| if (loc->loc == PARM_REGISTER) { |
| /* Parameter is located in a register */ |
| #ifdef WAD_SOLARIS |
| if ((loc->reg >= 24) && (loc->reg < 32)) { |
| /* Value is located in the %in registers. */ |
| loc->ptr = (void *) (stack + (loc->reg - 16)*sizeof(int)); |
| loc->size = sizeof(int); |
| } else if ((loc->reg >= 8) && (loc->reg < 16)) { |
| |
| /* Value is located in the %on registers */ |
| if (nstack) { |
| loc->ptr = (void *) (stack + (loc->reg)*sizeof(int)); |
| loc->size = sizeof(int); |
| } |
| } else if ((loc->reg >= 16) && (loc->reg < 24)) { |
| /* Value has been placed in the %ln registers */ |
| loc->ptr = (void *) (stack + (loc->reg - 16)*sizeof(int)); |
| loc->size = sizeof(int); |
| } |
| #endif |
| } |
| loc = loc->next; |
| } |
| } |
| } |
| |
| /* This function creates a formatted integer given a pointer, size, and sign flag */ |
| static |
| char *wad_format_int(char *ptr, int nbytes, int sgn) { |
| static char fmt[128]; |
| unsigned char *s; |
| int incr; |
| unsigned long value = 0; |
| int i; |
| |
| #ifdef WAD_LITTLE_ENDIAN |
| s = (unsigned char *) (ptr + nbytes - 1); |
| incr = -1; |
| #else |
| s = (unsigned char *) (ptr); |
| incr = +1; |
| #endif |
| for (i = 0; i < nbytes; i++, s += incr) { |
| value = (value << 8) + *s; |
| } |
| if (sgn) { |
| return wad_format_signed((long) value,-1); |
| } else { |
| return wad_format_unsigned((unsigned long) value, -1); |
| } |
| return fmt; |
| } |
| |
| /* Try to make a formatted version of a local */ |
| char *wad_format_var(WadLocal *l) { |
| static char hexdigits[] = "0123456789abcdef"; |
| static char buffer[1024]; |
| double dval; |
| float fval; |
| |
| buffer[0] = 0; |
| |
| switch(l->type) { |
| case WAD_TYPE_INT32: |
| wad_strcpy(buffer,wad_format_int(l->ptr,4,1)); |
| break; |
| case WAD_TYPE_UINT32: |
| wad_strcpy(buffer,wad_format_int(l->ptr,4,0)); |
| break; |
| case WAD_TYPE_INT16: |
| wad_strcpy(buffer,wad_format_int(l->ptr,2,1)); |
| break; |
| case WAD_TYPE_UINT16: |
| wad_strcpy(buffer,wad_format_int(l->ptr,2,0)); |
| break; |
| case WAD_TYPE_INT8: |
| wad_strcpy(buffer,wad_format_int(l->ptr,1,1)); |
| break; |
| case WAD_TYPE_UINT8: |
| wad_strcpy(buffer,wad_format_int(l->ptr,1,0)); |
| break; |
| case WAD_TYPE_CHAR: |
| buffer[0] = '\''; |
| buffer[1] = *((char *) l->ptr); |
| buffer[2] = '\''; |
| buffer[3] = 0; |
| break; |
| case WAD_TYPE_FLOAT: |
| wad_memcpy(&fval,l->ptr,sizeof(float)); |
| sprintf(buffer,"%g",fval); |
| break; |
| case WAD_TYPE_DOUBLE: |
| wad_memcpy(&dval,l->ptr,sizeof(double)); |
| sprintf(buffer,"%g",dval); |
| break; |
| case WAD_TYPE_UNKNOWN: |
| case WAD_TYPE_POINTER: |
| default: |
| /* Hmmm. Unknown data type. We'll just treat it as a word */ |
| if (l->ptr) { |
| int incr,i; |
| int b; |
| int leading = 1; |
| char *c; |
| char *ptr; |
| |
| #ifdef WAD_LITTLE_ENDIAN |
| ptr = ((char *) l->ptr) + 3; |
| incr = -1; |
| #else |
| ptr = (char *) l->ptr; |
| incr =1 ; |
| #endif |
| wad_strcat(buffer,"0x"); |
| c = buffer+2; |
| for (i = 0; i < sizeof(void *); i++) { |
| b = (int) *ptr; |
| if (!leading || (b)) { |
| if (!leading || (b & 0xf0)) |
| *(c++) = hexdigits[(b & 0xf0) >> 4]; |
| *(c++) = hexdigits[(b & 0xf)]; |
| leading = 0; |
| } |
| ptr += incr; |
| } |
| if (leading) |
| *(c++) = '0'; |
| |
| *c = 0; |
| } |
| } |
| return buffer; |
| } |
| |
| /* Convert a wad local variable to a long */ |
| long wad_local_as_long(WadLocal *loc) { |
| long value = 0; |
| int32 i32; |
| int16 i16; |
| int8 i8; |
| uint32 u32; |
| uint16 u16; |
| uint8 u8; |
| |
| switch(loc->type) { |
| case WAD_TYPE_INT32: |
| wad_memcpy(&i32,loc->ptr,4); |
| value = (long) i32; |
| break; |
| case WAD_TYPE_UINT32: |
| wad_memcpy(&u32,loc->ptr,4); |
| value = (long) u32; |
| break; |
| case WAD_TYPE_INT16: |
| wad_memcpy(&i16,loc->ptr,2); |
| value = (long) i16; |
| break; |
| case WAD_TYPE_UINT16: |
| wad_memcpy(&u16,loc->ptr,2); |
| value = (long) u16; |
| break; |
| case WAD_TYPE_INT8: |
| case WAD_TYPE_CHAR: |
| wad_memcpy(&i8, loc->ptr,1); |
| value = (long) i8; |
| break; |
| case WAD_TYPE_UINT8: |
| wad_memcpy(&u8, loc->ptr,1); |
| value = (long) u8; |
| break; |
| default: |
| wad_memcpy(&u32,loc->ptr,4); |
| value = (long) u32; |
| } |
| return value; |
| } |
| |
| /* Convert a wad local variable to a long */ |
| double wad_local_as_double(WadLocal *loc) { |
| double value = 0; |
| float fval; |
| |
| switch(loc->type) { |
| case WAD_TYPE_DOUBLE: |
| wad_memcpy(&value,loc->ptr,8); |
| break; |
| case WAD_TYPE_FLOAT: |
| wad_memcpy(&fval,loc->ptr,4); |
| value = (double) fval; |
| break; |
| default: |
| value = 0; |
| } |
| return value; |
| } |
| |
| |
| |
| |
| |
| |