Commit | Line | Data |
---|---|---|
04497f0b NW |
1 | /*- |
2 | * This code is derived from software copyrighted by the Free Software | |
3 | * Foundation. | |
4 | * | |
5 | * Modified 1991 by Donn Seeley at UUNET Technologies, Inc. | |
6 | * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory. | |
7 | */ | |
8 | ||
9 | #ifndef lint | |
10 | static char sccsid[] = "@(#)blockframe.c 6.4 (Berkeley) 5/11/91"; | |
11 | #endif /* not lint */ | |
12 | ||
13 | /* Get info from stack frames; | |
14 | convert between frames, blocks, functions and pc values. | |
15 | Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc. | |
16 | ||
17 | This file is part of GDB. | |
18 | ||
19 | GDB is free software; you can redistribute it and/or modify | |
20 | it under the terms of the GNU General Public License as published by | |
21 | the Free Software Foundation; either version 1, or (at your option) | |
22 | any later version. | |
23 | ||
24 | GDB is distributed in the hope that it will be useful, | |
25 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
27 | GNU General Public License for more details. | |
28 | ||
29 | You should have received a copy of the GNU General Public License | |
30 | along with GDB; see the file COPYING. If not, write to | |
31 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
32 | ||
33 | #include "defs.h" | |
34 | #include "param.h" | |
35 | #include "symtab.h" | |
36 | #include "frame.h" | |
37 | ||
38 | #include <obstack.h> | |
39 | ||
40 | #if defined(NEWVM) && defined(KERNELDEBUG) | |
41 | #include <sys/param.h> /* XXX for FRAME_CHAIN_VALID */ | |
42 | #endif | |
43 | ||
44 | /* Start and end of object file containing the entry point. | |
45 | STARTUP_FILE_END is the first address of the next file. | |
46 | This file is assumed to be a startup file | |
47 | and frames with pc's inside it | |
48 | are treated as nonexistent. | |
49 | ||
50 | Setting these variables is necessary so that backtraces do not fly off | |
51 | the bottom of the stack. */ | |
52 | CORE_ADDR startup_file_start; | |
53 | CORE_ADDR startup_file_end; | |
54 | ||
55 | /* Is ADDR outside the startup file? */ | |
56 | int | |
57 | outside_startup_file (addr) | |
58 | CORE_ADDR addr; | |
59 | { | |
60 | return !(addr >= startup_file_start && addr < startup_file_end); | |
61 | } | |
62 | ||
63 | /* Address of innermost stack frame (contents of FP register) */ | |
64 | ||
65 | static FRAME current_frame; | |
66 | ||
67 | struct block *block_for_pc (); | |
68 | CORE_ADDR get_pc_function_start (); | |
69 | ||
70 | /* | |
71 | * Cache for frame addresses already read by gdb. Valid only while | |
72 | * inferior is stopped. Control variables for the frame cache should | |
73 | * be local to this module. | |
74 | */ | |
75 | struct obstack frame_cache_obstack; | |
76 | ||
77 | /* Return the innermost (currently executing) stack frame. */ | |
78 | ||
79 | FRAME | |
80 | get_current_frame () | |
81 | { | |
82 | /* We assume its address is kept in a general register; | |
83 | param.h says which register. */ | |
84 | ||
85 | return current_frame; | |
86 | } | |
87 | ||
88 | void | |
89 | set_current_frame (frame) | |
90 | FRAME frame; | |
91 | { | |
92 | current_frame = frame; | |
93 | } | |
94 | ||
95 | FRAME | |
96 | create_new_frame (addr, pc) | |
97 | FRAME_ADDR addr; | |
98 | CORE_ADDR pc; | |
99 | { | |
100 | struct frame_info *fci; /* Same type as FRAME */ | |
101 | ||
102 | fci = (struct frame_info *) | |
103 | obstack_alloc (&frame_cache_obstack, | |
104 | sizeof (struct frame_info)); | |
105 | ||
106 | /* Arbitrary frame */ | |
107 | fci->next = (struct frame_info *) 0; | |
108 | fci->prev = (struct frame_info *) 0; | |
109 | fci->frame = addr; | |
110 | fci->next_frame = 0; /* Since arbitrary */ | |
111 | fci->pc = pc; | |
112 | ||
113 | #ifdef INIT_EXTRA_FRAME_INFO | |
114 | INIT_EXTRA_FRAME_INFO (fci); | |
115 | #endif | |
116 | ||
117 | return fci; | |
118 | } | |
119 | ||
120 | /* Return the frame that called FRAME. | |
121 | If FRAME is the original frame (it has no caller), return 0. */ | |
122 | ||
123 | FRAME | |
124 | get_prev_frame (frame) | |
125 | FRAME frame; | |
126 | { | |
127 | /* We're allowed to know that FRAME and "struct frame_info *" are | |
128 | the same */ | |
129 | return get_prev_frame_info (frame); | |
130 | } | |
131 | ||
132 | /* Return the frame that FRAME calls (0 if FRAME is the innermost | |
133 | frame). */ | |
134 | ||
135 | FRAME | |
136 | get_next_frame (frame) | |
137 | FRAME frame; | |
138 | { | |
139 | /* We're allowed to know that FRAME and "struct frame_info *" are | |
140 | the same */ | |
141 | return frame->next; | |
142 | } | |
143 | ||
144 | /* | |
145 | * Flush the entire frame cache. | |
146 | */ | |
147 | void | |
148 | flush_cached_frames () | |
149 | { | |
150 | /* Since we can't really be sure what the first object allocated was */ | |
151 | obstack_free (&frame_cache_obstack, 0); | |
152 | obstack_init (&frame_cache_obstack); | |
153 | ||
154 | current_frame = (struct frame_info *) 0; /* Invalidate cache */ | |
155 | } | |
156 | ||
157 | /* Return a structure containing various interesting information | |
158 | about a specified stack frame. */ | |
159 | /* How do I justify including this function? Well, the FRAME | |
160 | identifier format has gone through several changes recently, and | |
161 | it's not completely inconceivable that it could happen again. If | |
162 | it does, have this routine around will help */ | |
163 | ||
164 | struct frame_info * | |
165 | get_frame_info (frame) | |
166 | FRAME frame; | |
167 | { | |
168 | return frame; | |
169 | } | |
170 | ||
171 | /* If a machine allows frameless functions, it should define a macro | |
172 | FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) in param.h. FI is the struct | |
173 | frame_info for the frame, and FRAMELESS should be set to nonzero | |
174 | if it represents a frameless function invocation. */ | |
175 | ||
176 | /* Many machines which allow frameless functions can detect them using | |
177 | this macro. Such machines should define FRAMELESS_FUNCTION_INVOCATION | |
178 | to just call this macro. */ | |
179 | #define FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS) \ | |
180 | { \ | |
181 | CORE_ADDR func_start, after_prologue; \ | |
182 | func_start = (get_pc_function_start ((FI)->pc) + \ | |
183 | FUNCTION_START_OFFSET); \ | |
184 | if (func_start) \ | |
185 | { \ | |
186 | after_prologue = func_start; \ | |
187 | SKIP_PROLOGUE (after_prologue); \ | |
188 | (FRAMELESS) = (after_prologue == func_start); \ | |
189 | } \ | |
190 | else \ | |
191 | /* If we can't find the start of the function, we don't really */ \ | |
192 | /* know whether the function is frameless, but we should be */ \ | |
193 | /* able to get a reasonable (i.e. best we can do under the */ \ | |
194 | /* circumstances) backtrace by saying that it isn't. */ \ | |
195 | (FRAMELESS) = 0; \ | |
196 | } | |
197 | ||
198 | /* Return a structure containing various interesting information | |
199 | about the frame that called NEXT_FRAME. Returns NULL | |
200 | if there is no such frame. */ | |
201 | ||
202 | struct frame_info * | |
203 | get_prev_frame_info (next_frame) | |
204 | FRAME next_frame; | |
205 | { | |
206 | FRAME_ADDR address; | |
207 | struct frame_info *prev; | |
208 | int fromleaf = 0; | |
209 | ||
210 | /* If the requested entry is in the cache, return it. | |
211 | Otherwise, figure out what the address should be for the entry | |
212 | we're about to add to the cache. */ | |
213 | ||
214 | if (!next_frame) | |
215 | { | |
216 | if (!current_frame) | |
217 | { | |
218 | if (!have_inferior_p () && !have_core_file_p ()) | |
219 | fatal ("get_prev_frame_info: Called before cache primed. \"Shouldn't happen.\""); | |
220 | else | |
221 | error ("No inferior or core file."); | |
222 | } | |
223 | ||
224 | return current_frame; | |
225 | } | |
226 | ||
227 | /* If we have the prev one, return it */ | |
228 | if (next_frame->prev) | |
229 | return next_frame->prev; | |
230 | ||
231 | /* On some machines it is possible to call a function without | |
232 | setting up a stack frame for it. On these machines, we | |
233 | define this macro to take two args; a frameinfo pointer | |
234 | identifying a frame and a variable to set or clear if it is | |
235 | or isn't leafless. */ | |
236 | #ifdef FRAMELESS_FUNCTION_INVOCATION | |
237 | /* Still don't want to worry about this except on the innermost | |
238 | frame. This macro will set FROMLEAF if NEXT_FRAME is a | |
239 | frameless function invocation. */ | |
240 | if (!(next_frame->next)) | |
241 | { | |
242 | FRAMELESS_FUNCTION_INVOCATION (next_frame, fromleaf); | |
243 | if (fromleaf) | |
244 | address = next_frame->frame; | |
245 | } | |
246 | #endif | |
247 | ||
248 | if (!fromleaf) | |
249 | { | |
250 | /* Two macros defined in param.h specify the machine-dependent | |
251 | actions to be performed here. | |
252 | First, get the frame's chain-pointer. | |
253 | If that is zero, the frame is the outermost frame or a leaf | |
254 | called by the outermost frame. This means that if start | |
255 | calls main without a frame, we'll return 0 (which is fine | |
256 | anyway). | |
257 | ||
258 | Nope; there's a problem. This also returns when the current | |
259 | routine is a leaf of main. This is unacceptable. We move | |
260 | this to after the ffi test; I'd rather have backtraces from | |
261 | start go curfluy than have an abort called from main not show | |
262 | main. */ | |
263 | address = FRAME_CHAIN (next_frame); | |
264 | if (!FRAME_CHAIN_VALID (address, next_frame)) | |
265 | return 0; | |
266 | /* If this frame is a leaf, this will be superceeded by the | |
267 | code below. */ | |
268 | address = FRAME_CHAIN_COMBINE (address, next_frame); | |
269 | } | |
270 | if (address == 0) | |
271 | return 0; | |
272 | ||
273 | prev = (struct frame_info *) | |
274 | obstack_alloc (&frame_cache_obstack, | |
275 | sizeof (struct frame_info)); | |
276 | ||
277 | if (next_frame) | |
278 | next_frame->prev = prev; | |
279 | prev->next = next_frame; | |
280 | prev->prev = (struct frame_info *) 0; | |
281 | prev->frame = address; | |
282 | prev->next_frame = prev->next ? prev->next->frame : 0; | |
283 | ||
284 | #ifdef INIT_EXTRA_FRAME_INFO | |
285 | INIT_EXTRA_FRAME_INFO(prev); | |
286 | #endif | |
287 | ||
288 | /* This entry is in the frame queue now, which is good since | |
289 | FRAME_SAVED_PC may use that queue to figure out it's value | |
290 | (see m-sparc.h). We want the pc saved in the inferior frame. */ | |
291 | prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (next_frame) : | |
292 | next_frame ? FRAME_SAVED_PC (next_frame) : read_pc ()); | |
293 | ||
294 | return prev; | |
295 | } | |
296 | ||
297 | CORE_ADDR | |
298 | get_frame_pc (frame) | |
299 | FRAME frame; | |
300 | { | |
301 | struct frame_info *fi; | |
302 | fi = get_frame_info (frame); | |
303 | return fi->pc; | |
304 | } | |
305 | ||
306 | /* Find the addresses in which registers are saved in FRAME. */ | |
307 | ||
308 | void | |
309 | get_frame_saved_regs (frame_info_addr, saved_regs_addr) | |
310 | struct frame_info *frame_info_addr; | |
311 | struct frame_saved_regs *saved_regs_addr; | |
312 | { | |
313 | FRAME_FIND_SAVED_REGS (frame_info_addr, *saved_regs_addr); | |
314 | } | |
315 | ||
316 | /* Return the innermost lexical block in execution | |
317 | in a specified stack frame. The frame address is assumed valid. */ | |
318 | ||
319 | struct block * | |
320 | get_frame_block (frame) | |
321 | FRAME frame; | |
322 | { | |
323 | struct frame_info *fi; | |
324 | CORE_ADDR pc; | |
325 | ||
326 | fi = get_frame_info (frame); | |
327 | ||
328 | pc = fi->pc; | |
329 | if (fi->next_frame != 0) | |
330 | /* We are not in the innermost frame. We need to subtract one to | |
331 | get the correct block, in case the call instruction was the | |
332 | last instruction of the block. If there are any machines on | |
333 | which the saved pc does not point to after the call insn, we | |
334 | probably want to make fi->pc point after the call insn anyway. */ | |
335 | --pc; | |
336 | return block_for_pc (pc); | |
337 | } | |
338 | ||
339 | struct block * | |
340 | get_current_block () | |
341 | { | |
342 | return block_for_pc (read_pc ()); | |
343 | } | |
344 | ||
345 | CORE_ADDR | |
346 | get_pc_function_start (pc) | |
347 | CORE_ADDR pc; | |
348 | { | |
349 | register struct block *bl = block_for_pc (pc); | |
350 | register struct symbol *symbol; | |
351 | if (bl == 0 || (symbol = block_function (bl)) == 0) | |
352 | { | |
353 | register int misc_index = find_pc_misc_function (pc); | |
354 | if (misc_index >= 0) | |
355 | return misc_function_vector[misc_index].address; | |
356 | return 0; | |
357 | } | |
358 | bl = SYMBOL_BLOCK_VALUE (symbol); | |
359 | return BLOCK_START (bl); | |
360 | } | |
361 | ||
362 | /* Return the symbol for the function executing in frame FRAME. */ | |
363 | ||
364 | struct symbol * | |
365 | get_frame_function (frame) | |
366 | FRAME frame; | |
367 | { | |
368 | register struct block *bl = get_frame_block (frame); | |
369 | if (bl == 0) | |
370 | return 0; | |
371 | return block_function (bl); | |
372 | } | |
373 | \f | |
374 | /* Return the innermost lexical block containing the specified pc value, | |
375 | or 0 if there is none. */ | |
376 | ||
377 | extern struct symtab *psymtab_to_symtab (); | |
378 | ||
379 | struct block * | |
380 | block_for_pc (pc) | |
381 | register CORE_ADDR pc; | |
382 | { | |
383 | register struct block *b; | |
384 | register int bot, top, half; | |
385 | register struct symtab *s; | |
386 | register struct partial_symtab *ps; | |
387 | struct blockvector *bl; | |
388 | ||
389 | /* First search all symtabs for one whose file contains our pc */ | |
390 | ||
391 | for (s = symtab_list; s; s = s->next) | |
392 | { | |
393 | bl = BLOCKVECTOR (s); | |
394 | b = BLOCKVECTOR_BLOCK (bl, 0); | |
395 | if (BLOCK_START (b) <= pc | |
396 | && BLOCK_END (b) > pc) | |
397 | break; | |
398 | } | |
399 | ||
400 | if (s == 0) | |
401 | for (ps = partial_symtab_list; ps; ps = ps->next) | |
402 | { | |
403 | if (ps->textlow <= pc | |
404 | && ps->texthigh > pc) | |
405 | { | |
406 | if (ps->readin) | |
407 | fatal ("Internal error: pc found in readin psymtab and not in any symtab."); | |
408 | s = psymtab_to_symtab (ps); | |
409 | bl = BLOCKVECTOR (s); | |
410 | b = BLOCKVECTOR_BLOCK (bl, 0); | |
411 | break; | |
412 | } | |
413 | } | |
414 | ||
415 | if (s == 0) | |
416 | return 0; | |
417 | ||
418 | /* Then search that symtab for the smallest block that wins. */ | |
419 | /* Use binary search to find the last block that starts before PC. */ | |
420 | ||
421 | bot = 0; | |
422 | top = BLOCKVECTOR_NBLOCKS (bl); | |
423 | ||
424 | while (top - bot > 1) | |
425 | { | |
426 | half = (top - bot + 1) >> 1; | |
427 | b = BLOCKVECTOR_BLOCK (bl, bot + half); | |
428 | if (BLOCK_START (b) <= pc) | |
429 | bot += half; | |
430 | else | |
431 | top = bot + half; | |
432 | } | |
433 | ||
434 | /* Now search backward for a block that ends after PC. */ | |
435 | ||
436 | while (bot >= 0) | |
437 | { | |
438 | b = BLOCKVECTOR_BLOCK (bl, bot); | |
439 | if (BLOCK_END (b) > pc) | |
440 | return b; | |
441 | bot--; | |
442 | } | |
443 | ||
444 | return 0; | |
445 | } | |
446 | ||
447 | /* Return the function containing pc value PC. | |
448 | Returns 0 if function is not known. */ | |
449 | ||
450 | struct symbol * | |
451 | find_pc_function (pc) | |
452 | CORE_ADDR pc; | |
453 | { | |
454 | register struct block *b = block_for_pc (pc); | |
455 | if (b == 0) | |
456 | return 0; | |
457 | return block_function (b); | |
458 | } | |
459 | ||
460 | /* Finds the "function" (text symbol) that is smaller than PC | |
461 | but greatest of all of the potential text symbols. Sets | |
462 | *NAME and/or *ADDRESS conditionally if that pointer is non-zero. | |
463 | Returns 0 if it couldn't find anything, 1 if it did. On a zero | |
464 | return, *NAME and *ADDRESS are always set to zero. On a 1 return, | |
465 | *NAME and *ADDRESS contain real information. */ | |
466 | ||
467 | int | |
468 | find_pc_partial_function (pc, name, address) | |
469 | CORE_ADDR pc; | |
470 | char **name; | |
471 | CORE_ADDR *address; | |
472 | { | |
473 | struct partial_symtab *pst = find_pc_psymtab (pc); | |
474 | struct symbol *f; | |
475 | int miscfunc; | |
476 | struct partial_symbol *psb; | |
477 | ||
478 | if (pst) | |
479 | { | |
480 | if (pst->readin) | |
481 | { | |
482 | /* The information we want has already been read in. | |
483 | We can go to the already readin symbols and we'll get | |
484 | the best possible answer. */ | |
485 | f = find_pc_function (pc); | |
486 | if (!f) | |
487 | { | |
488 | return_error: | |
489 | /* No availible symbol. */ | |
490 | if (name != 0) | |
491 | *name = 0; | |
492 | if (address != 0) | |
493 | *address = 0; | |
494 | return 0; | |
495 | } | |
496 | ||
497 | if (name) | |
498 | *name = SYMBOL_NAME (f); | |
499 | if (address) | |
500 | *address = BLOCK_START (SYMBOL_BLOCK_VALUE (f)); | |
501 | return 1; | |
502 | } | |
503 | ||
504 | /* Get the information from a combination of the pst | |
505 | (static symbols), and the misc function vector (extern | |
506 | symbols). */ | |
507 | miscfunc = find_pc_misc_function (pc); | |
508 | psb = find_pc_psymbol (pst, pc); | |
509 | ||
510 | if (!psb && miscfunc == -1) | |
511 | { | |
512 | goto return_error; | |
513 | } | |
514 | if (!psb | |
515 | || (miscfunc != -1 | |
516 | && (SYMBOL_VALUE(psb) | |
517 | < misc_function_vector[miscfunc].address))) | |
518 | { | |
519 | if (address) | |
520 | *address = misc_function_vector[miscfunc].address; | |
521 | if (name) | |
522 | *name = misc_function_vector[miscfunc].name; | |
523 | return 1; | |
524 | } | |
525 | else | |
526 | { | |
527 | if (address) | |
528 | *address = SYMBOL_VALUE (psb); | |
529 | if (name) | |
530 | *name = SYMBOL_NAME (psb); | |
531 | return 1; | |
532 | } | |
533 | } | |
534 | else | |
535 | /* Must be in the misc function stuff. */ | |
536 | { | |
537 | miscfunc = find_pc_misc_function (pc); | |
538 | if (miscfunc == -1) | |
539 | goto return_error; | |
540 | if (address) | |
541 | *address = misc_function_vector[miscfunc].address; | |
542 | if (name) | |
543 | *name = misc_function_vector[miscfunc].name; | |
544 | return 1; | |
545 | } | |
546 | } | |
547 | ||
548 | /* Find the misc function whose address is the largest | |
549 | while being less than PC. Return its index in misc_function_vector. | |
550 | Returns -1 if PC is not in suitable range. */ | |
551 | ||
552 | int | |
553 | find_pc_misc_function (pc) | |
554 | register CORE_ADDR pc; | |
555 | { | |
556 | register int lo = 0; | |
557 | register int hi = misc_function_count-1; | |
558 | register int new; | |
559 | register int distance; | |
560 | ||
561 | /* Note that the last thing in the vector is always _etext. */ | |
562 | /* Actually, "end", now that non-functions | |
563 | go on the misc_function_vector. */ | |
564 | ||
565 | /* Above statement is not *always* true - fix for case where there are */ | |
566 | /* no misc functions at all (ie no symbol table has been read). */ | |
567 | if (hi < 0) return -1; /* no misc functions recorded */ | |
568 | ||
569 | /* trivial reject range test */ | |
570 | if (pc < misc_function_vector[0].address || | |
571 | pc > misc_function_vector[hi].address) | |
572 | return -1; | |
573 | ||
574 | /* Note that the following search will not return hi if | |
575 | pc == misc_function_vector[hi].address. If "end" points to the | |
576 | first unused location, this is correct and the above test | |
577 | simply needs to be changed to | |
578 | "pc >= misc_function_vector[hi].address". */ | |
579 | do { | |
580 | new = (lo + hi) >> 1; | |
581 | distance = misc_function_vector[new].address - pc; | |
582 | if (distance == 0) | |
583 | return new; /* an exact match */ | |
584 | else if (distance > 0) | |
585 | hi = new; | |
586 | else | |
587 | lo = new; | |
588 | } while (hi-lo != 1); | |
589 | ||
590 | /* if here, we had no exact match, so return the lower choice */ | |
591 | return lo; | |
592 | } | |
593 | ||
594 | /* Return the innermost stack frame executing inside of the specified block, | |
595 | or zero if there is no such frame. */ | |
596 | ||
597 | FRAME | |
598 | block_innermost_frame (block) | |
599 | struct block *block; | |
600 | { | |
601 | struct frame_info *fi; | |
602 | register FRAME frame; | |
603 | register CORE_ADDR start = BLOCK_START (block); | |
604 | register CORE_ADDR end = BLOCK_END (block); | |
605 | ||
606 | frame = 0; | |
607 | while (1) | |
608 | { | |
609 | frame = get_prev_frame (frame); | |
610 | if (frame == 0) | |
611 | return 0; | |
612 | fi = get_frame_info (frame); | |
613 | if (fi->pc >= start && fi->pc < end) | |
614 | return frame; | |
615 | } | |
616 | } | |
617 | ||
618 | void | |
619 | _initialize_blockframe () | |
620 | { | |
621 | obstack_init (&frame_cache_obstack); | |
622 | } |