~ubuntu-branches/ubuntu/hoary/swig1.3/hoary

« back to all changes in this revision

Viewing changes to Tools/WAD/Wad/stack.c

  • Committer: Bazaar Package Importer
  • Author(s): Thom May
  • Date: 2004-08-02 15:57:10 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040802155710-bm292q1d6x6tw7gc
Tags: 1.3.21-5ubuntu1
Fix linking for ruby, python, perl and tcl bindings

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
29
static char cvs[] = "$Header: /cvsroot/SWIG/Tools/WAD/Wad/stack.c,v 1.24 2001/06/20 15:12:53 beazley Exp $";
 
30
 
 
31
/* -----------------------------------------------------------------------------
 
32
 * new_frame()
 
33
 *
 
34
 * Create a new stack frame object and initialize all of the fields.
 
35
 * ----------------------------------------------------------------------------- */
 
36
 
 
37
static WadFrame *
 
38
new_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
 
 
88
static WadFrame *
 
89
stack_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
 
 
170
WadFrame *
 
171
wad_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
 
 
208
void 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
 
 
276
long 
 
277
wad_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