/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