1
/* -----------------------------------------------------------------------------
4
* This file unwinds the C call stack and creates a list of stack frames.
6
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
8
* Copyright (C) 2000. The University of Chicago.
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.
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.
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
24
* See the file COPYING for a complete copy of the LGPL.
25
* ----------------------------------------------------------------------------- */
29
static char cvs[] = "$Header: /cvsroot/SWIG/Tools/WAD/Wad/stack.c,v 1.24 2001/06/20 15:12:53 beazley Exp $";
31
/* -----------------------------------------------------------------------------
34
* Create a new stack frame object and initialize all of the fields.
35
* ----------------------------------------------------------------------------- */
40
f = (WadFrame *) wad_malloc(sizeof(WadFrame));
68
f->debug_lastlocal = 0;
78
/* -----------------------------------------------------------------------------
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
* ----------------------------------------------------------------------------- */
89
stack_unwind(unsigned long *pc, unsigned long *sp, unsigned long *fp) {
90
WadSegment *sp_seg, *fp_seg;
92
unsigned long fake_fp;
94
if (wad_debug_mode & DEBUG_UNWIND) {
95
wad_printf("::: stack unwind : pc = %x, sp = %x, fp = %x\n", *pc, *sp, *fp);
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);
102
/* Make sure the stack pointer is in memory */
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);
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");
120
/* Check to see if the PC is valid */
121
if (!wad_segment_valid((void *) *pc)) {
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);
135
/* Update the sp, fp, and pc */
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);
148
if (wad_segment_valid((void *) ((unsigned long *) *fp+1))) {
149
*pc = *((unsigned long *) *fp+1);
154
if (wad_segment_valid((void *) ((unsigned long *) *fp))) {
155
*fp = *((unsigned long *) *fp);
163
/* -----------------------------------------------------------------------------
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
* ----------------------------------------------------------------------------- */
171
wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
172
WadFrame *firstframe=0, *lastframe=0, *frame=0;
178
/* Try to do a stack traceback */
184
while ((frame = stack_unwind(&p_pc, &p_sp, &p_fp))) {
185
/* Got a frame successfully */
188
lastframe->next = frame;
189
frame->prev = lastframe;
202
/* -----------------------------------------------------------------------------
205
* Make a dump of a stack trace
206
* ----------------------------------------------------------------------------- */
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 */
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 : "?");
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 : "");
230
if (frame->loc_srcfile) {
231
wad_printf(" loc_srcfile = %s\n", frame->loc_srcfile);
234
if (frame->loc_objfile) {
235
wad_printf(" loc_objfile = %s\n", frame->loc_objfile);
237
wad_printf(" loc_line = %d\n", frame->loc_line);
240
wad_printf(" debug_nargs = %d\n", frame->debug_nargs);
241
if (frame->debug_args) {
243
WadLocal *p = frame->debug_args;
244
wad_printf(" debug_args = [ \n");
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);
252
wad_printf(" debug_nlocal = %d\n", frame->debug_nlocals);
253
if (frame->debug_locals) {
255
WadLocal *p = frame->debug_locals;
256
wad_printf(" debug_locals = [ \n");
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);
270
/* -----------------------------------------------------------------------------
273
* Steal an output argument
274
* ----------------------------------------------------------------------------- */
277
wad_steal_outarg(WadFrame *f, char *symbol, int argno, int *error) {
282
/* Start searching */
284
if (f->sym_name && (strcmp(f->sym_name,symbol) == 0)) {
288
regs = (long *) lastf->stack;
289
return regs[8+argno];
292
regs = (long *) f->stack;
293
return regs[argno+2];