7b4ac7e1 |
1 | /* Print and select stack frames for GDB, the GNU debugger. |
e91b87a3 |
2 | Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. |
7b4ac7e1 |
3 | |
4187119d |
4 | This file is part of GDB. |
5 | |
6 | GDB is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 1, or (at your option) |
9 | any later version. |
10 | |
11 | GDB is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | GNU General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with GDB; see the file COPYING. If not, write to |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ |
7b4ac7e1 |
19 | |
20 | #include <stdio.h> |
21 | |
22 | #include "defs.h" |
7b4ac7e1 |
23 | #include "param.h" |
24 | #include "symtab.h" |
25 | #include "frame.h" |
26 | |
7b4ac7e1 |
27 | |
28 | /* Thie "selected" stack frame is used by default for local and arg access. |
29 | May be zero, for no selected frame. */ |
30 | |
31 | FRAME selected_frame; |
32 | |
33 | /* Level of the selected frame: |
34 | 0 for innermost, 1 for its caller, ... |
35 | or -1 for frame specified by address with no defined level. */ |
36 | |
37 | int selected_frame_level; |
38 | |
632ea0cc |
39 | /* Nonzero means print the full filename and linenumber |
40 | when a frame is printed, and do so in a format programs can parse. */ |
41 | |
42 | int frame_file_full_name = 0; |
43 | |
7b4ac7e1 |
44 | static void select_calling_frame (); |
45 | |
46 | void print_frame_info (); |
47 | \f |
4187119d |
48 | /* Print a stack frame briefly. FRAME should be the frame id |
7b4ac7e1 |
49 | and LEVEL should be its level in the stack (or -1 for level not defined). |
50 | This prints the level, the function executing, the arguments, |
51 | and the file name and line number. |
52 | If the pc is not at the beginning of the source line, |
53 | the actual pc is printed at the beginning. |
54 | |
55 | If SOURCE is 1, print the source line as well. |
56 | If SOURCE is -1, print ONLY the source line. */ |
57 | |
58 | static void |
59 | print_stack_frame (frame, level, source) |
60 | FRAME frame; |
61 | int level; |
62 | int source; |
63 | { |
e91b87a3 |
64 | struct frame_info *fi; |
7b4ac7e1 |
65 | |
66 | fi = get_frame_info (frame); |
67 | |
e91b87a3 |
68 | print_frame_info (fi, level, source, 1); |
7b4ac7e1 |
69 | } |
70 | |
4187119d |
71 | /* Flag which will indicate when the frame has been changed |
72 | by and "up" or "down" command. */ |
73 | static int frame_changed; |
74 | |
7b4ac7e1 |
75 | void |
76 | print_frame_info (fi, level, source, args) |
77 | struct frame_info *fi; |
78 | register int level; |
79 | int source; |
80 | int args; |
81 | { |
7b4ac7e1 |
82 | struct symtab_and_line sal; |
83 | struct symbol *func; |
84 | register char *funname = 0; |
85 | int numargs; |
4187119d |
86 | struct partial_symtab *pst; |
87 | |
88 | /* Don't give very much information if we haven't readin the |
89 | symbol table yet. */ |
90 | pst = find_pc_psymtab (fi->pc); |
91 | if (pst && !pst->readin) |
92 | { |
93 | /* Abbreviated information. */ |
94 | char *fname; |
95 | |
96 | if (!find_pc_partial_function (fi->pc, &fname, 0)) |
97 | fname = "??"; |
98 | |
99 | printf_filtered ("#%-2d ", level); |
100 | printf_filtered ("0x%x in ", fi->pc); |
101 | |
102 | printf_filtered ("%s (...) (...)\n", fname); |
103 | |
104 | return; |
105 | } |
7b4ac7e1 |
106 | |
107 | sal = find_pc_line (fi->pc, fi->next_frame); |
e91b87a3 |
108 | func = find_pc_function (fi->pc); |
7b4ac7e1 |
109 | if (func) |
4187119d |
110 | { |
111 | /* In certain pathological cases, the symtabs give the wrong |
112 | function (when we are in the first function in a file which |
113 | is compiled without debugging symbols, the previous function |
114 | is compiled with debugging symbols, and the "foo.o" symbol |
115 | that is supposed to tell us where the file with debugging symbols |
116 | ends has been truncated by ar because it is longer than 15 |
117 | characters). |
118 | |
119 | So look in the misc_function_vector as well, and if it comes |
120 | up with a larger address for the function use that instead. |
121 | I don't think this can ever cause any problems; |
122 | there shouldn't be any |
123 | misc_function_vector symbols in the middle of a function. */ |
124 | int misc_index = find_pc_misc_function (fi->pc); |
125 | if (misc_index >= 0 |
126 | && (misc_function_vector[misc_index].address |
127 | > BLOCK_START (SYMBOL_BLOCK_VALUE (func)))) |
128 | { |
129 | /* In this case we have no way of knowing the source file |
130 | and line number, so don't print them. */ |
131 | sal.symtab = 0; |
132 | /* We also don't know anything about the function besides |
133 | its address and name. */ |
134 | func = 0; |
135 | funname = misc_function_vector[misc_index].name; |
136 | } |
137 | else |
138 | funname = SYMBOL_NAME (func); |
139 | } |
7b4ac7e1 |
140 | else |
141 | { |
142 | register int misc_index = find_pc_misc_function (fi->pc); |
143 | if (misc_index >= 0) |
144 | funname = misc_function_vector[misc_index].name; |
145 | } |
146 | |
4187119d |
147 | if (frame_changed || source >= 0 || !sal.symtab) |
7b4ac7e1 |
148 | { |
7b4ac7e1 |
149 | if (level >= 0) |
4187119d |
150 | printf_filtered ("#%-2d ", level); |
151 | else if (frame_changed) |
152 | printf ("#%-2d ", 0); |
7b4ac7e1 |
153 | if (fi->pc != sal.pc || !sal.symtab) |
4187119d |
154 | printf_filtered ("0x%x in ", fi->pc); |
155 | printf_filtered ("%s (", funname ? funname : "??"); |
7b4ac7e1 |
156 | if (args) |
157 | { |
e91b87a3 |
158 | FRAME_NUM_ARGS (numargs, fi); |
159 | print_frame_args (func, fi, numargs, stdout); |
7b4ac7e1 |
160 | } |
4187119d |
161 | printf_filtered (")"); |
7b4ac7e1 |
162 | if (sal.symtab) |
4187119d |
163 | printf_filtered (" (%s line %d)", sal.symtab->filename, sal.line); |
164 | printf_filtered ("\n"); |
7b4ac7e1 |
165 | } |
166 | |
4187119d |
167 | if ((frame_changed || source != 0) && sal.symtab) |
7b4ac7e1 |
168 | { |
632ea0cc |
169 | int done = 0; |
3bf57d21 |
170 | int mid_statement = source < 0 && fi->pc != sal.pc; |
632ea0cc |
171 | if (frame_file_full_name) |
3bf57d21 |
172 | done = identify_source_line (sal.symtab, sal.line, mid_statement); |
632ea0cc |
173 | if (!done) |
3bf57d21 |
174 | { |
175 | if (mid_statement) |
4187119d |
176 | printf_filtered ("0x%x\t", fi->pc); |
3bf57d21 |
177 | print_source_lines (sal.symtab, sal.line, sal.line + 1, 1); |
178 | } |
7b4ac7e1 |
179 | current_source_line = max (sal.line - 5, 1); |
180 | } |
4187119d |
181 | frame_changed = 0; |
7b4ac7e1 |
182 | if (source != 0) |
183 | set_default_breakpoint (1, fi->pc, sal.symtab, sal.line); |
184 | |
185 | fflush (stdout); |
186 | } |
187 | |
188 | /* Call here to print info on selected frame, after a trap. */ |
189 | |
190 | void |
191 | print_sel_frame (just_source) |
192 | int just_source; |
193 | { |
194 | print_stack_frame (selected_frame, -1, just_source ? -1 : 1); |
195 | } |
196 | |
197 | /* Print info on the selected frame, including level number |
198 | but not source. */ |
199 | |
e91b87a3 |
200 | void |
7b4ac7e1 |
201 | print_selected_frame () |
202 | { |
203 | print_stack_frame (selected_frame, selected_frame_level, 0); |
204 | } |
205 | |
4187119d |
206 | void flush_cached_frames (); |
e91b87a3 |
207 | |
208 | #ifdef FRAME_SPECIFICATION_DYADIC |
209 | extern FRAME setup_arbitrary_frame (); |
210 | #endif |
211 | |
212 | /* |
213 | * Read a frame specification in whatever the appropriate format is. |
214 | */ |
215 | static FRAME |
216 | parse_frame_specification (frame_exp) |
217 | char *frame_exp; |
218 | { |
219 | int numargs = 0; |
220 | int arg1, arg2; |
221 | |
222 | if (frame_exp) |
223 | { |
224 | char *addr_string, *p; |
225 | struct cleanup *tmp_cleanup; |
226 | struct frame_info *fci; |
227 | |
228 | while (*frame_exp == ' ') frame_exp++; |
229 | for (p = frame_exp; *p && *p != ' '; p++) |
230 | ; |
231 | |
232 | if (*frame_exp) |
233 | { |
234 | numargs = 1; |
235 | addr_string = savestring(frame_exp, p - frame_exp); |
236 | |
237 | { |
238 | tmp_cleanup = make_cleanup (free, addr_string); |
239 | arg1 = parse_and_eval_address (addr_string); |
240 | do_cleanups (tmp_cleanup); |
241 | } |
242 | |
243 | while (*p == ' ') p++; |
244 | |
245 | if (*p) |
246 | { |
247 | numargs = 2; |
248 | arg2 = parse_and_eval_address (p); |
249 | } |
250 | } |
251 | } |
252 | |
253 | switch (numargs) |
254 | { |
255 | case 0: |
e91b87a3 |
256 | return selected_frame; |
257 | /* NOTREACHED */ |
258 | case 1: |
259 | { |
260 | int level = arg1; |
261 | FRAME fid = find_relative_frame (get_current_frame (), &level); |
262 | FRAME tfid; |
263 | |
264 | if (level == 0) |
265 | /* find_relative_frame was successful */ |
266 | return fid; |
267 | |
268 | /* If (s)he specifies the frame with an address, he deserves what |
269 | (s)he gets. Still, give the highest one that matches. */ |
270 | |
271 | for (fid = get_current_frame (); |
272 | fid && FRAME_FP (fid) != arg1; |
273 | fid = get_prev_frame (fid)) |
274 | ; |
275 | |
276 | if (fid) |
277 | while ((tfid = get_prev_frame (fid)) && |
278 | (FRAME_FP (tfid) == arg1)) |
279 | fid = tfid; |
280 | |
281 | #ifdef FRAME_SPECIFICATION_DYADIC |
282 | if (!fid) |
283 | error ("Incorrect number of args in frame specification"); |
284 | |
285 | return fid; |
286 | #else |
287 | return create_new_frame (arg1, 0); |
288 | #endif |
289 | } |
290 | /* NOTREACHED */ |
291 | case 2: |
292 | /* Must be addresses */ |
293 | #ifndef FRAME_SPECIFICATION_DYADIC |
294 | error ("Incorrect number of args in frame specification"); |
295 | #else |
296 | return setup_arbitrary_frame (arg1, arg2); |
297 | #endif |
298 | /* NOTREACHED */ |
299 | } |
300 | fatal ("Internal: Error in parsing in parse_frame_specification"); |
301 | /* NOTREACHED */ |
302 | } |
303 | |
1c997a4a |
304 | /* FRAME_ARGS_ADDRESS_CORRECT is just like FRAME_ARGS_ADDRESS except |
305 | that if it is unsure about the answer, it returns Frame_unknown |
306 | instead of guessing (this happens on the VAX, for example). |
307 | |
308 | On most machines, we never have to guess about the args address, |
309 | so FRAME_ARGS_ADDRESS{,_CORRECT} are the same. */ |
310 | #if !defined (FRAME_ARGS_ADDRESS_CORRECT) |
311 | #define FRAME_ARGS_ADDRESS_CORRECT FRAME_ARGS_ADDRESS |
312 | #endif |
313 | |
7b4ac7e1 |
314 | /* Print verbosely the selected frame or the frame at address ADDR. |
315 | This means absolutely all information in the frame is printed. */ |
316 | |
317 | static void |
318 | frame_info (addr_exp) |
319 | char *addr_exp; |
320 | { |
e91b87a3 |
321 | FRAME frame; |
322 | struct frame_info *fi; |
7b4ac7e1 |
323 | struct frame_saved_regs fsr; |
324 | struct symtab_and_line sal; |
325 | struct symbol *func; |
326 | FRAME calling_frame; |
327 | int i, count; |
328 | char *funname = 0; |
7b4ac7e1 |
329 | |
4187119d |
330 | if (!(have_inferior_p () || have_core_file_p ())) |
331 | error ("No inferior or core file."); |
332 | |
e91b87a3 |
333 | frame = parse_frame_specification (addr_exp); |
4187119d |
334 | if (!frame) |
335 | error ("Invalid frame specified."); |
e91b87a3 |
336 | |
7b4ac7e1 |
337 | fi = get_frame_info (frame); |
e91b87a3 |
338 | get_frame_saved_regs (fi, &fsr); |
339 | sal = find_pc_line (fi->pc, fi->next_frame); |
7b4ac7e1 |
340 | func = get_frame_function (frame); |
341 | if (func) |
342 | funname = SYMBOL_NAME (func); |
343 | else |
344 | { |
e91b87a3 |
345 | register int misc_index = find_pc_misc_function (fi->pc); |
7b4ac7e1 |
346 | if (misc_index >= 0) |
347 | funname = misc_function_vector[misc_index].name; |
348 | } |
349 | calling_frame = get_prev_frame (frame); |
350 | |
351 | if (!addr_exp && selected_frame_level >= 0) |
352 | printf ("Stack level %d, frame at 0x%x:\n pc = 0x%x", |
e91b87a3 |
353 | selected_frame_level, FRAME_FP(frame), fi->pc); |
7b4ac7e1 |
354 | else |
355 | printf ("Stack frame at 0x%x:\n pc = 0x%x", |
e91b87a3 |
356 | FRAME_FP(frame), fi->pc); |
7b4ac7e1 |
357 | |
358 | if (funname) |
359 | printf (" in %s", funname); |
360 | if (sal.symtab) |
361 | printf (" (%s line %d)", sal.symtab->filename, sal.line); |
e91b87a3 |
362 | printf ("; saved pc 0x%x\n", FRAME_SAVED_PC (frame)); |
7b4ac7e1 |
363 | if (calling_frame) |
e91b87a3 |
364 | printf (" called by frame at 0x%x", FRAME_FP (calling_frame)); |
365 | if (fi->next_frame && calling_frame) |
7b4ac7e1 |
366 | printf (","); |
e91b87a3 |
367 | if (fi->next_frame) |
368 | printf (" caller of frame at 0x%x", fi->next_frame); |
369 | if (fi->next_frame || calling_frame) |
7b4ac7e1 |
370 | printf ("\n"); |
7b4ac7e1 |
371 | |
1c997a4a |
372 | { |
373 | /* Address of the argument list for this frame, or Frame_unknown. */ |
374 | CORE_ADDR arg_list = FRAME_ARGS_ADDRESS_CORRECT (fi); |
375 | /* Number of args for this frame, or -1 if unknown. */ |
376 | int numargs; |
377 | |
378 | if (arg_list != Frame_unknown) |
379 | { |
380 | printf (" Arglist at 0x%x,", arg_list); |
381 | |
382 | FRAME_NUM_ARGS (numargs, fi); |
383 | if (numargs < 0) |
384 | printf (" args: "); |
385 | else if (numargs == 0) |
386 | printf (" no args."); |
387 | else if (numargs == 1) |
388 | printf (" 1 arg: "); |
389 | else |
390 | printf (" %d args: ", numargs); |
391 | print_frame_args (func, fi, numargs, stdout); |
392 | printf ("\n"); |
393 | } |
394 | } |
395 | |
4187119d |
396 | /* The sp is special; what's returned isn't the save address, but |
397 | actually the value of the previous frame's sp. */ |
398 | printf (" Previous frame's sp is 0x%x\n", fsr.regs[SP_REGNUM]); |
7b4ac7e1 |
399 | count = 0; |
400 | for (i = 0; i < NUM_REGS; i++) |
4187119d |
401 | if (fsr.regs[i] && i != SP_REGNUM) |
7b4ac7e1 |
402 | { |
403 | if (count % 4 != 0) |
404 | printf (", "); |
405 | else |
406 | { |
407 | if (count == 0) |
408 | printf (" Saved registers:"); |
409 | printf ("\n "); |
410 | } |
411 | printf ("%s at 0x%x", reg_names[i], fsr.regs[i]); |
412 | count++; |
413 | } |
414 | if (count) |
415 | printf ("\n"); |
416 | } |
417 | |
e91b87a3 |
418 | #if 0 |
419 | /* Set a limit on the number of frames printed by default in a |
420 | backtrace. */ |
421 | |
422 | static int backtrace_limit; |
423 | |
424 | static void |
425 | set_backtrace_limit_command (count_exp, from_tty) |
426 | char *count_exp; |
427 | int from_tty; |
428 | { |
429 | int count = parse_and_eval_address (count_exp); |
430 | |
431 | if (count < 0) |
432 | error ("Negative argument not meaningful as backtrace limit."); |
433 | |
434 | backtrace_limit = count; |
435 | } |
436 | |
437 | static void |
438 | backtrace_limit_info (arg, from_tty) |
439 | char *arg; |
440 | int from_tty; |
441 | { |
442 | if (arg) |
443 | error ("\"Info backtrace-limit\" takes no arguments."); |
444 | |
445 | printf ("Backtrace limit: %d.\n", backtrace_limit); |
446 | } |
447 | #endif |
448 | |
7b4ac7e1 |
449 | /* Print briefly all stack frames or just the innermost COUNT frames. */ |
450 | |
451 | static void |
452 | backtrace_command (count_exp) |
453 | char *count_exp; |
454 | { |
e91b87a3 |
455 | struct frame_info *fi; |
7b4ac7e1 |
456 | register int count; |
457 | register FRAME frame; |
458 | register int i; |
e91b87a3 |
459 | register FRAME trailing; |
460 | register int trailing_level; |
461 | |
e91b87a3 |
462 | /* The following code must do two things. First, it must |
463 | set the variable TRAILING to the frame from which we should start |
464 | printing. Second, it must set the variable count to the number |
465 | of frames which we should print, or -1 if all of them. */ |
466 | trailing = get_current_frame (); |
467 | trailing_level = 0; |
7b4ac7e1 |
468 | if (count_exp) |
e91b87a3 |
469 | { |
470 | count = parse_and_eval_address (count_exp); |
471 | if (count < 0) |
472 | { |
473 | FRAME current; |
474 | |
475 | count = -count; |
476 | |
477 | current = trailing; |
478 | while (current && count--) |
479 | current = get_prev_frame (current); |
480 | |
481 | /* Will stop when CURRENT reaches the top of the stack. TRAILING |
482 | will be COUNT below it. */ |
483 | while (current) |
484 | { |
485 | trailing = get_prev_frame (trailing); |
486 | current = get_prev_frame (current); |
487 | trailing_level++; |
488 | } |
489 | |
490 | count = -1; |
491 | } |
492 | } |
7b4ac7e1 |
493 | else |
494 | count = -1; |
495 | |
e91b87a3 |
496 | for (i = 0, frame = trailing; |
7b4ac7e1 |
497 | frame && count--; |
e91b87a3 |
498 | i++, frame = get_prev_frame (frame)) |
7b4ac7e1 |
499 | { |
500 | QUIT; |
e91b87a3 |
501 | fi = get_frame_info (frame); |
502 | print_frame_info (fi, trailing_level + i, 0, 1); |
7b4ac7e1 |
503 | } |
e91b87a3 |
504 | |
505 | /* If we've stopped before the end, mention that. */ |
506 | if (frame) |
4187119d |
507 | printf_filtered ("(More stack frames follow...)\n"); |
7b4ac7e1 |
508 | } |
509 | \f |
4187119d |
510 | /* Print the local variables of a block B active in FRAME. |
511 | Return 1 if any variables were printed; 0 otherwise. */ |
7b4ac7e1 |
512 | |
4187119d |
513 | static int |
7b4ac7e1 |
514 | print_block_frame_locals (b, frame, stream) |
515 | struct block *b; |
516 | register FRAME frame; |
517 | register FILE *stream; |
518 | { |
519 | int nsyms; |
520 | register int i; |
521 | register struct symbol *sym; |
4187119d |
522 | register int values_printed = 0; |
7b4ac7e1 |
523 | |
524 | nsyms = BLOCK_NSYMS (b); |
525 | |
526 | for (i = 0; i < nsyms; i++) |
527 | { |
528 | sym = BLOCK_SYM (b, i); |
529 | if (SYMBOL_CLASS (sym) == LOC_LOCAL |
3bf57d21 |
530 | || SYMBOL_CLASS (sym) == LOC_REGISTER |
531 | || SYMBOL_CLASS (sym) == LOC_STATIC) |
7b4ac7e1 |
532 | { |
4187119d |
533 | values_printed = 1; |
534 | fputs_filtered (SYMBOL_NAME (sym), stream); |
535 | fputs_filtered (" = ", stream); |
7b4ac7e1 |
536 | print_variable_value (sym, frame, stream); |
4187119d |
537 | fprintf_filtered (stream, "\n"); |
7b4ac7e1 |
538 | fflush (stream); |
539 | } |
540 | } |
4187119d |
541 | return values_printed; |
7b4ac7e1 |
542 | } |
543 | |
544 | /* Print on STREAM all the local variables in frame FRAME, |
545 | including all the blocks active in that frame |
546 | at its current pc. |
547 | |
548 | Returns 1 if the job was done, |
549 | or 0 if nothing was printed because we have no info |
550 | on the function running in FRAME. */ |
551 | |
552 | static int |
553 | print_frame_local_vars (frame, stream) |
554 | register FRAME frame; |
555 | register FILE *stream; |
556 | { |
4187119d |
557 | register struct block *block = get_frame_block (frame); |
558 | register int values_printed = 0; |
e91b87a3 |
559 | |
7b4ac7e1 |
560 | if (block == 0) |
4187119d |
561 | { |
562 | fprintf_filtered (stream, "No symbol table info available.\n"); |
563 | fflush (stream); |
564 | return 0; |
565 | } |
566 | |
7b4ac7e1 |
567 | while (block != 0) |
568 | { |
4187119d |
569 | if (print_block_frame_locals (block, frame, stream)) |
570 | values_printed = 1; |
7b4ac7e1 |
571 | /* After handling the function's top-level block, stop. |
572 | Don't continue to its superblock, the block of |
573 | per-file symbols. */ |
574 | if (BLOCK_FUNCTION (block)) |
575 | break; |
576 | block = BLOCK_SUPERBLOCK (block); |
577 | } |
4187119d |
578 | |
579 | if (!values_printed) |
580 | { |
581 | fprintf_filtered (stream, "No locals.\n"); |
582 | fflush (stream); |
583 | } |
584 | |
7b4ac7e1 |
585 | return 1; |
586 | } |
587 | |
588 | static void |
589 | locals_info () |
590 | { |
4187119d |
591 | if (!have_inferior_p () && !have_core_file_p ()) |
592 | error ("No inferior or core file."); |
593 | |
7b4ac7e1 |
594 | print_frame_local_vars (selected_frame, stdout); |
595 | } |
596 | |
597 | static int |
598 | print_frame_arg_vars (frame, stream) |
599 | register FRAME frame; |
600 | register FILE *stream; |
601 | { |
4187119d |
602 | struct symbol *func = get_frame_function (frame); |
7b4ac7e1 |
603 | register struct block *b; |
604 | int nsyms; |
605 | register int i; |
606 | register struct symbol *sym; |
4187119d |
607 | register int values_printed = 0; |
7b4ac7e1 |
608 | |
609 | if (func == 0) |
4187119d |
610 | { |
611 | fprintf_filtered (stream, "No symbol table info available.\n"); |
612 | fflush (stream); |
613 | return 0; |
614 | } |
7b4ac7e1 |
615 | |
616 | b = SYMBOL_BLOCK_VALUE (func); |
617 | nsyms = BLOCK_NSYMS (b); |
618 | |
619 | for (i = 0; i < nsyms; i++) |
620 | { |
621 | sym = BLOCK_SYM (b, i); |
4187119d |
622 | if (SYMBOL_CLASS (sym) == LOC_ARG |
623 | || SYMBOL_CLASS (sym) == LOC_REF_ARG |
624 | || SYMBOL_CLASS (sym) == LOC_REGPARM) |
7b4ac7e1 |
625 | { |
4187119d |
626 | values_printed = 1; |
627 | fputs_filtered (SYMBOL_NAME (sym), stream); |
628 | fputs_filtered (" = ", stream); |
7b4ac7e1 |
629 | print_variable_value (sym, frame, stream); |
4187119d |
630 | fprintf_filtered (stream, "\n"); |
7b4ac7e1 |
631 | fflush (stream); |
632 | } |
633 | } |
634 | |
4187119d |
635 | if (!values_printed) |
636 | { |
637 | fprintf_filtered (stream, "No arguments.\n"); |
638 | fflush (stream); |
639 | } |
640 | |
7b4ac7e1 |
641 | return 1; |
642 | } |
643 | |
644 | static void |
645 | args_info () |
646 | { |
4187119d |
647 | if (!have_inferior_p () && !have_core_file_p ()) |
648 | error ("No inferior or core file."); |
7b4ac7e1 |
649 | print_frame_arg_vars (selected_frame, stdout); |
650 | } |
651 | \f |
652 | /* Select frame FRAME, and note that its stack level is LEVEL. |
653 | LEVEL may be -1 if an actual level number is not known. */ |
654 | |
655 | void |
656 | select_frame (frame, level) |
657 | FRAME frame; |
658 | int level; |
659 | { |
660 | selected_frame = frame; |
661 | selected_frame_level = level; |
4187119d |
662 | /* Ensure that symbols for this frame are readin. */ |
663 | if (frame) |
664 | find_pc_symtab (get_frame_info (frame)->pc); |
7b4ac7e1 |
665 | } |
666 | |
667 | /* Store the selected frame and its level into *FRAMEP and *LEVELP. */ |
668 | |
669 | void |
e91b87a3 |
670 | record_selected_frame (frameaddrp, levelp) |
671 | FRAME_ADDR *frameaddrp; |
7b4ac7e1 |
672 | int *levelp; |
673 | { |
e91b87a3 |
674 | *frameaddrp = FRAME_FP (selected_frame); |
7b4ac7e1 |
675 | *levelp = selected_frame_level; |
676 | } |
677 | |
678 | /* Return the symbol-block in which the selected frame is executing. |
679 | Can return zero under various legitimate circumstances. */ |
680 | |
681 | struct block * |
682 | get_selected_block () |
683 | { |
684 | if (!have_inferior_p () && !have_core_file_p ()) |
685 | return 0; |
686 | |
687 | if (!selected_frame) |
688 | return get_current_block (); |
689 | return get_frame_block (selected_frame); |
690 | } |
691 | |
692 | /* Find a frame a certain number of levels away from FRAME. |
693 | LEVEL_OFFSET_PTR points to an int containing the number of levels. |
694 | Positive means go to earlier frames (up); negative, the reverse. |
695 | The int that contains the number of levels is counted toward |
696 | zero as the frames for those levels are found. |
697 | If the top or bottom frame is reached, that frame is returned, |
698 | but the final value of *LEVEL_OFFSET_PTR is nonzero and indicates |
699 | how much farther the original request asked to go. */ |
700 | |
701 | FRAME |
702 | find_relative_frame (frame, level_offset_ptr) |
703 | register FRAME frame; |
704 | register int* level_offset_ptr; |
705 | { |
706 | register FRAME prev; |
7b4ac7e1 |
707 | register FRAME frame1, frame2; |
708 | |
709 | /* Going up is simple: just do get_prev_frame enough times |
710 | or until initial frame is reached. */ |
711 | while (*level_offset_ptr > 0) |
712 | { |
713 | prev = get_prev_frame (frame); |
714 | if (prev == 0) |
715 | break; |
716 | (*level_offset_ptr)--; |
717 | frame = prev; |
718 | } |
719 | /* Going down could be done by iterating get_frame_info to |
720 | find the next frame, but that would be quadratic |
721 | since get_frame_info must scan all the way from the current frame. |
bb7592f0 |
722 | The following algorithm is linear. */ |
7b4ac7e1 |
723 | if (*level_offset_ptr < 0) |
724 | { |
725 | /* First put frame1 at innermost frame |
726 | and frame2 N levels up from there. */ |
727 | frame1 = get_current_frame (); |
728 | frame2 = frame1; |
729 | while (*level_offset_ptr < 0 && frame2 != frame) |
730 | { |
731 | frame2 = get_prev_frame (frame2); |
732 | (*level_offset_ptr) ++; |
733 | } |
734 | /* Then slide frame1 and frame2 up in synchrony |
735 | and when frame2 reaches our starting point |
736 | frame1 must be N levels down from there. */ |
737 | while (frame2 != frame) |
738 | { |
739 | frame1 = get_prev_frame (frame1); |
740 | frame2 = get_prev_frame (frame2); |
741 | } |
742 | return frame1; |
743 | } |
744 | return frame; |
745 | } |
746 | |
747 | /* The "frame" command. With no arg, print selected frame briefly. |
e91b87a3 |
748 | With arg LEVEL_EXP, select the frame at level LEVEL if it is a |
749 | valid level. Otherwise, treat level_exp as an address expression |
750 | and print it. See parse_frame_specification for more info on proper |
751 | frame expressions. */ |
7b4ac7e1 |
752 | |
753 | static void |
754 | frame_command (level_exp, from_tty) |
755 | char *level_exp; |
756 | int from_tty; |
757 | { |
e91b87a3 |
758 | register FRAME frame, frame1; |
759 | unsigned int level = 0; |
7b4ac7e1 |
760 | |
4187119d |
761 | if (!have_inferior_p () && ! have_core_file_p ()) |
762 | error ("No inferior or core file."); |
763 | |
e91b87a3 |
764 | frame = parse_frame_specification (level_exp); |
7b4ac7e1 |
765 | |
e91b87a3 |
766 | for (frame1 = get_prev_frame (0); |
767 | frame1 && frame1 != frame; |
768 | frame1 = get_prev_frame (frame1)) |
769 | level++; |
770 | |
771 | if (!frame1) |
772 | level = 0; |
773 | |
4187119d |
774 | frame_changed = level; |
e91b87a3 |
775 | select_frame (frame, level); |
776 | |
777 | if (!from_tty) |
778 | return; |
7b4ac7e1 |
779 | |
780 | print_stack_frame (selected_frame, selected_frame_level, 1); |
781 | } |
782 | |
783 | /* Select the frame up one or COUNT stack levels |
784 | from the previously selected frame, and print it briefly. */ |
785 | |
786 | static void |
787 | up_command (count_exp) |
788 | char *count_exp; |
789 | { |
790 | register FRAME frame; |
791 | int count = 1, count1; |
792 | if (count_exp) |
793 | count = parse_and_eval_address (count_exp); |
794 | count1 = count; |
795 | |
4187119d |
796 | if (!have_inferior_p () && !have_core_file_p ()) |
797 | error ("No inferior or core file."); |
798 | |
7b4ac7e1 |
799 | frame = find_relative_frame (selected_frame, &count1); |
800 | if (count1 != 0 && count_exp == 0) |
801 | error ("Initial frame selected; you cannot go up."); |
802 | select_frame (frame, selected_frame_level + count - count1); |
803 | |
804 | print_stack_frame (selected_frame, selected_frame_level, 1); |
4187119d |
805 | frame_changed++; |
7b4ac7e1 |
806 | } |
807 | |
808 | /* Select the frame down one or COUNT stack levels |
809 | from the previously selected frame, and print it briefly. */ |
810 | |
811 | static void |
812 | down_command (count_exp) |
813 | char *count_exp; |
814 | { |
815 | register FRAME frame; |
816 | int count = -1, count1; |
817 | if (count_exp) |
818 | count = - parse_and_eval_address (count_exp); |
819 | count1 = count; |
820 | |
821 | frame = find_relative_frame (selected_frame, &count1); |
822 | if (count1 != 0 && count_exp == 0) |
823 | error ("Bottom (i.e., innermost) frame selected; you cannot go down."); |
824 | select_frame (frame, selected_frame_level + count - count1); |
825 | |
826 | print_stack_frame (selected_frame, selected_frame_level, 1); |
4187119d |
827 | frame_changed--; |
7b4ac7e1 |
828 | } |
829 | \f |
830 | static void |
831 | return_command (retval_exp, from_tty) |
832 | char *retval_exp; |
833 | int from_tty; |
834 | { |
835 | struct symbol *thisfun = get_frame_function (selected_frame); |
4187119d |
836 | FRAME_ADDR selected_frame_addr = FRAME_FP (selected_frame); |
7b4ac7e1 |
837 | |
838 | /* If interactive, require confirmation. */ |
839 | |
840 | if (from_tty) |
841 | { |
842 | if (thisfun != 0) |
843 | { |
844 | if (!query ("Make %s return now? ", SYMBOL_NAME (thisfun))) |
845 | error ("Not confirmed."); |
846 | } |
847 | else |
848 | if (!query ("Make selected stack frame return now? ")) |
849 | error ("Not confirmed."); |
850 | } |
851 | |
4187119d |
852 | /* Do the real work. Pop until the specified frame is current. We |
853 | use this method because the selected_frame is not valid after |
854 | a POP_FRAME. Note that this will not work if the selected frame |
855 | shares it's fp with another frame. */ |
7b4ac7e1 |
856 | |
4187119d |
857 | while (selected_frame_addr != FRAME_FP (get_current_frame())) |
7b4ac7e1 |
858 | POP_FRAME; |
859 | |
860 | /* Then pop that frame. */ |
861 | |
862 | POP_FRAME; |
863 | |
864 | /* Compute the return value (if any) and store in the place |
865 | for return values. */ |
866 | |
867 | if (retval_exp) |
868 | set_return_value (parse_and_eval (retval_exp)); |
869 | |
870 | /* If interactive, print the frame that is now current. */ |
871 | |
872 | if (from_tty) |
873 | frame_command ("0", 1); |
874 | } |
875 | \f |
e91b87a3 |
876 | extern struct cmd_list_element *setlist; |
877 | |
878 | void |
879 | _initialize_stack () |
7b4ac7e1 |
880 | { |
e91b87a3 |
881 | #if 0 |
882 | backtrace_limit = 30; |
883 | #endif |
884 | |
7b4ac7e1 |
885 | add_com ("return", class_stack, return_command, |
886 | "Make selected stack frame return to its caller.\n\ |
887 | Control remains in the debugger, but when you continue\n\ |
888 | execution will resume in the frame above the one now selected.\n\ |
889 | If an argument is given, it is an expression for the value to return."); |
890 | |
891 | add_com ("up", class_stack, up_command, |
892 | "Select and print stack frame that called this one.\n\ |
893 | An argument says how many frames up to go."); |
894 | |
895 | add_com ("down", class_stack, down_command, |
896 | "Select and print stack frame called by this one.\n\ |
897 | An argument says how many frames down to go."); |
898 | add_com_alias ("do", "down", class_stack, 1); |
899 | |
900 | add_com ("frame", class_stack, frame_command, |
901 | "Select and print a stack frame.\n\ |
902 | With no argument, print the selected stack frame. (See also \"info frame\").\n\ |
903 | An argument specifies the frame to select.\n\ |
904 | It can be a stack frame number or the address of the frame.\n\ |
905 | With argument, nothing is printed if input is coming from\n\ |
906 | a command file or a user-defined command."); |
907 | |
908 | add_com_alias ("f", "frame", class_stack, 1); |
909 | |
910 | add_com ("backtrace", class_stack, backtrace_command, |
e91b87a3 |
911 | "Print backtrace of all stack frames, or innermost COUNT frames.\n\ |
912 | With a negative argument, print outermost -COUNT frames."); |
7b4ac7e1 |
913 | add_com_alias ("bt", "backtrace", class_stack, 0); |
914 | add_com_alias ("where", "backtrace", class_alias, 0); |
915 | add_info ("stack", backtrace_command, |
916 | "Backtrace of the stack, or innermost COUNT frames."); |
917 | add_info_alias ("s", "stack", 1); |
918 | add_info ("frame", frame_info, |
919 | "All about selected stack frame, or frame at ADDR."); |
920 | add_info_alias ("f", "frame", 1); |
921 | add_info ("locals", locals_info, |
922 | "Local variables of current stack frame."); |
923 | add_info ("args", args_info, |
924 | "Argument variables of current stack frame."); |
e91b87a3 |
925 | |
926 | #if 0 |
927 | add_cmd ("backtrace-limit", class_stack, set_backtrace_limit_command, |
928 | "Specify maximum number of frames for \"backtrace\" to print by default.", |
929 | &setlist); |
930 | add_info ("backtrace-limit", backtrace_limit_info, |
931 | "The maximum number of frames for \"backtrace\" to print by default."); |
932 | #endif |
7b4ac7e1 |
933 | } |
934 | |