/* ----------------------------------------------------------------------------- * 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: vars.c 10001 2007-10-17 21:33:57Z wsfulton $"; /* ----------------------------------------------------------------------------- * 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; }