PageRenderTime 36ms CodeModel.GetById 18ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/ttn-post-libtool-1-4-3-upgrade/SWIG/Tools/WAD/Wad/stack.c

#
C | 309 lines | 197 code | 44 blank | 68 comment | 31 complexity | 4e36e060514f630331bda078b92c87d1 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  1/* ----------------------------------------------------------------------------- 
  2 * stack.c
  3 *
  4 *     This file unwinds the C call stack and creates a list of stack frames.
  5 *
  6 * Author(s) : David Beazley (beazley@cs.uchicago.edu)
  7 *
  8 * Copyright (C) 2000.  The University of Chicago. 
  9 *
 10 * This library is free software; you can redistribute it and/or
 11 * modify it under the terms of the GNU Lesser General Public
 12 * License as published by the Free Software Foundation; either
 13 * version 2.1 of the License, or (at your option) any later version.
 14 *
 15 * This library is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18 * Lesser General Public License for more details.
 19 *
 20 * You should have received a copy of the GNU Lesser General Public
 21 * License along with this library; if not, write to the Free Software
 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23 * 
 24 * See the file COPYING for a complete copy of the LGPL.
 25 * ----------------------------------------------------------------------------- */
 26
 27#include "wad.h"
 28
 29static char cvs[] = "$Header$";
 30
 31/* -----------------------------------------------------------------------------
 32 * new_frame()
 33 *
 34 * Create a new stack frame object and initialize all of the fields.
 35 * ----------------------------------------------------------------------------- */
 36
 37static WadFrame *
 38new_frame() {
 39  WadFrame *f;
 40  f = (WadFrame *) wad_malloc(sizeof(WadFrame));
 41  f->frameno = 0;
 42  f->segment = 0;
 43  f->object = 0;
 44  f->pc = 0;
 45  f->sp = 0;
 46  f->sp = 0;
 47  f->stack = 0;
 48  f->stack_size = 0;
 49
 50  f->sym_name = 0;
 51  f->sym_nlen = 0;
 52  f->sym_file = 0;
 53  f->sym_base = 0;
 54  f->sym_size = 0;
 55  f->sym_type = 0;
 56  f->sym_bind = 0;
 57
 58  f->loc_objfile = 0;
 59  f->loc_srcfile = 0;
 60  f->loc_line = 0;
 61
 62  f->debug_check = 0;
 63  f->debug_nargs = -1;
 64  f->debug_args = 0;
 65  f->debug_lastarg = 0;
 66  f->debug_nlocals = 0;
 67  f->debug_locals = 0;
 68  f->debug_lastlocal = 0;
 69  f->debug_str = 0;
 70  f->debug_srcstr = 0;
 71
 72  f->last = 0;
 73  f->next = 0;
 74  f->prev = 0;
 75  return f;
 76}
 77
 78/* -----------------------------------------------------------------------------
 79 * stack_unwind()
 80 *
 81 * This function performs a single level of stack unwinding given the stack pointer
 82 * frame pointer and program counter.   Validations are made to make sure the stack
 83 * and frame pointers are in valid memory.  Updates the values of the sp, pc, and fp
 84 * in-place.  Returns a stack frame object on success, 0 if memory is invalid
 85 * or the end of the stack has been reached.
 86 * ----------------------------------------------------------------------------- */
 87
 88static WadFrame *
 89stack_unwind(unsigned long *pc, unsigned long *sp, unsigned long *fp) {
 90  WadSegment *sp_seg, *fp_seg;
 91  WadFrame   *f;
 92  unsigned   long fake_fp;
 93
 94  if (wad_debug_mode & DEBUG_UNWIND) {
 95    wad_printf("::: stack unwind :  pc = %x, sp = %x, fp = %x\n", *pc, *sp, *fp);
 96  }
 97
 98  /* Verify that the sp and fp are in mapped memory */
 99  sp_seg = wad_segment_find((void *) *sp);
100  fp_seg = wad_segment_find((void *) *fp);
101
102  /* Make sure the stack pointer is in memory */
103  if (!sp_seg) {
104    return 0;
105  }
106
107  if (!fp_seg) {
108    /* Hmmm. If no frame pointer, we must be off the top of the call stack */
109    fake_fp = (unsigned long) (sp_seg->vaddr + sp_seg->size);
110    fp_seg = sp_seg;
111  } else {
112    fake_fp = *fp;
113  }
114  if (sp_seg != fp_seg) {
115    /* Whoa. Stack pointer and frame pointer are in different memory segments. */
116    wad_printf("WAD: Warning. Stack pointer and frame pointer are in different regions.\n");
117    return 0;
118  }
119
120  /* Check to see if the PC is valid */
121  if (!wad_segment_valid((void *) *pc)) {
122    return 0;
123  }
124
125  f = new_frame();
126  f->pc = *pc;
127  f->sp = *sp;
128  f->fp = fake_fp;
129  f->segment = wad_segment_find((void *) *pc);
130  f->stack_size = fake_fp - *sp;
131  /* Make a copy of the call stack */
132  f->stack = (char *) wad_malloc(f->stack_size);
133  wad_memcpy(f->stack,(void *) *sp, f->stack_size);
134
135  /* Update the sp, fp, and pc */
136
137#ifdef WAD_SOLARIS
138  *pc = *((unsigned long *) *sp+15);         /* %i7 - Return address  */
139  *sp = *((unsigned long *) *sp+14);         /* %i6 - frame pointer   */
140  if (wad_segment_valid((void *) *sp)) {
141    *fp = *((unsigned long *) *sp+14);
142  } else {
143    *fp = 0;
144  }
145#endif
146
147#ifdef WAD_LINUX
148  if (wad_segment_valid((void *) ((unsigned long *) *fp+1))) {
149    *pc = *((unsigned long *) *fp+1); 
150    *sp = *fp;
151  } else {
152    *sp = 0;
153  }
154  if (wad_segment_valid((void *) ((unsigned long *) *fp))) {
155    *fp = *((unsigned long *) *fp);
156  } else {
157    *fp = 0;
158  }
159#endif
160  return f;
161}
162
163/* -----------------------------------------------------------------------------
164 * wad_stack_trace()
165 *
166 * Create a stack trace of the process. Returns a linked list of stack frames
167 * with a limited about debugging information and other details.
168 * ----------------------------------------------------------------------------- */
169
170WadFrame *
171wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
172  WadFrame        *firstframe=0, *lastframe=0, *frame=0;
173  unsigned long   p_pc;
174  unsigned long   p_sp;
175  unsigned long   p_fp;
176  int             n = 0;
177
178  /* Try to do a stack traceback */
179
180  p_pc = pc;
181  p_sp = sp;
182  p_fp = fp;
183
184  while ((frame = stack_unwind(&p_pc, &p_sp, &p_fp))) {
185    /* Got a frame successfully */
186    frame->frameno = n;
187    if (lastframe) {
188      lastframe->next = frame;
189      frame->prev = lastframe;
190      lastframe = frame;
191    } else {
192      firstframe = frame;
193      lastframe = frame;
194    }
195    n++;
196  }
197  if (lastframe)
198    lastframe->last = 1;
199  return firstframe;
200}
201
202/* -----------------------------------------------------------------------------
203 * wad_stack_debug() 
204 *
205 * Make a dump of a stack trace
206 * ----------------------------------------------------------------------------- */
207
208void wad_stack_debug(WadFrame *frame) {
209  if (wad_debug_mode & DEBUG_STACK) {
210    /* Walk the exception frames and try to find a return point */
211    while (frame) {
212      /* Print out detailed stack trace information */
213      wad_printf("::: Stack frame - 0x%08x :::\n", frame);
214      wad_printf("    pc           = %x\n", frame->pc);
215      wad_printf("    sp           = %x\n", frame->sp);
216      wad_printf("    fp           = %x\n", frame->fp);
217      wad_printf("    stack        = %x\n", frame->stack);
218      wad_printf("    size         = %x\n", frame->stack_size);
219      wad_printf("    segment      = %x (%s)\n", frame->segment, frame->segment ? frame->segment->mappath : "?");
220      wad_printf("    object       = %x (%s)\n", frame->object, frame->object ? frame->object->path : "?");
221
222      if (frame->sym_name) {
223	wad_printf("    sym_name     = %s\n", frame->sym_name);
224	wad_printf("    sym_base     = %x\n", frame->sym_base);
225	wad_printf("    sym_size     = %x\n", frame->sym_size);
226	wad_printf("    sym_bind     = %x\n", frame->sym_bind);
227	wad_printf("    sym_file     = %s\n", frame->sym_file ? frame->sym_file : "");
228      }
229
230      if (frame->loc_srcfile) {
231	wad_printf("    loc_srcfile  = %s\n", frame->loc_srcfile);
232      }
233
234      if (frame->loc_objfile) {
235	wad_printf("    loc_objfile  = %s\n", frame->loc_objfile);
236      }
237      wad_printf("    loc_line     = %d\n", frame->loc_line);
238
239
240      wad_printf("    debug_nargs  = %d\n", frame->debug_nargs);
241      if (frame->debug_args) {
242	int i = 0;
243	WadLocal *p = frame->debug_args;
244	wad_printf("    debug_args = [ \n");
245	while (p) {
246	  wad_printf("        arg[%d] : name = '%s', loc = %d, type = %d, stack = %d, reg = %d, line=%d, ptr=%x(%d)\n", i, p->name, p->loc, p->type, p->stack,p->reg,p->line,p->ptr,p->size);
247	  p = p->next;
248	}
249      }
250      wad_printf("    ]\n");
251
252      wad_printf("    debug_nlocal  = %d\n", frame->debug_nlocals);
253      if (frame->debug_locals) {
254	int i = 0;
255	WadLocal *p = frame->debug_locals;
256	wad_printf("    debug_locals = [ \n");
257	while (p) {
258	  wad_printf("        loc[%d] : name = '%s', loc = %d, type = %d, stack = %d, reg = %d, line=%d, ptr=%x(%d)\n", i, p->name, p->loc, p->type, p->stack,p->reg,p->line,p->ptr,p->size);
259	  p = p->next;
260	}
261      }
262      wad_printf("    ]\n");
263
264      frame = frame->next;
265    }
266  }
267}
268
269
270/* -----------------------------------------------------------------------------
271 * wad_steal_outarg()
272 *
273 * Steal an output argument
274 * ----------------------------------------------------------------------------- */
275
276long 
277wad_steal_outarg(WadFrame *f, char *symbol, int argno, int *error) {
278  long *regs;
279  WadFrame *lastf = 0;
280
281  *error = 0;
282  /* Start searching */
283  while (f) {
284    if (f->sym_name && (strcmp(f->sym_name,symbol) == 0)) {
285      /* Got a match */
286      if (lastf) {
287#ifdef WAD_SOLARIS
288	regs = (long *) lastf->stack;
289	return regs[8+argno];
290#endif
291#ifdef WAD_LINUX
292	regs = (long *) f->stack;
293	return regs[argno+2];
294#endif
295      }
296    }
297    lastf = f;
298    f = f->next;
299  }
300  *error = -1;
301  return 0;
302}
303
304
305
306
307
308
309