gdb-2.8
[deliverable/binutils-gdb.git] / gdb / blockframe.c
1 /* Get info from stack frames;
2 convert between frames, blocks, functions and pc values.
3 Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
4
5 GDB is distributed in the hope that it will be useful, but WITHOUT ANY
6 WARRANTY. No author or distributor accepts responsibility to anyone
7 for the consequences of using it or for whether it serves any
8 particular purpose or works at all, unless he says so in writing.
9 Refer to the GDB General Public License for full details.
10
11 Everyone is granted permission to copy, modify and redistribute GDB,
12 but only under the conditions described in the GDB General Public
13 License. A copy of this license is supposed to have been given to you
14 along with GDB so you can know your rights and responsibilities. It
15 should be in a file named COPYING. Among other things, the copyright
16 notice and this notice must be preserved on all copies.
17
18 In other words, go ahead and share GDB, but don't try to stop
19 anyone else from sharing it farther. Help stamp out software hoarding!
20 */
21
22 #include "defs.h"
23 #include "initialize.h"
24 #include "param.h"
25 #include "symtab.h"
26 #include "frame.h"
27
28 /* Address of end of first object file.
29 This file is assumed to be a startup file
30 and frames with pc's inside it
31 are treated as nonexistent. */
32
33 CORE_ADDR first_object_file_end;
34
35 /* Address of innermost stack frame (contents of FP register) */
36
37 static FRAME current_frame;
38
39 struct block *block_for_pc ();
40 CORE_ADDR get_pc_function_start ();
41
42 START_FILE
43
44 /* Return the innermost (currently executing) stack frame. */
45
46 FRAME
47 get_current_frame ()
48 {
49 /* We assume its address is kept in a general register;
50 param.h says which register. */
51
52 return current_frame;
53 }
54
55 void
56 set_current_frame (frame)
57 FRAME frame;
58 {
59 current_frame = frame;
60 }
61
62 /* Return the frame that called FRAME.
63 If FRAME is the original frame (it has no caller), return 0. */
64
65 FRAME
66 get_prev_frame (frame)
67 FRAME frame;
68 {
69 CORE_ADDR pointer;
70 /* The caller of "no frame" is the innermost frame. */
71 if (frame == 0)
72 return get_current_frame ();
73
74 /* Two macros defined in param.h specify the machine-dependent
75 actions to be performed here. */
76 /* First, get the frame's chain-pointer.
77 If that is zero, the frame is the outermost frame. */
78 pointer = FRAME_CHAIN (frame);
79 if (!FRAME_CHAIN_VALID (pointer, frame))
80 return 0;
81 /* If frame has a caller, combine the chain pointer and the frame's own
82 address to get the address of the caller. */
83 return FRAME_CHAIN_COMBINE (pointer, frame);
84 }
85
86 /* Return a structure containing various interesting information
87 about a specified stack frame. */
88
89 struct frame_info
90 get_frame_info (frame)
91 FRAME frame;
92 {
93 struct frame_info val;
94 FRAME current = get_current_frame ();
95 register FRAME frame1;
96
97 val.frame = frame;
98
99 if (frame == current)
100 {
101 val.pc = read_pc ();
102 val.next_frame = 0;
103 }
104 else
105 {
106 for (frame1 = current; frame1; frame1 = get_prev_frame (frame1))
107 {
108 QUIT;
109 if (frame1 == frame)
110 break;
111
112 val.pc = FRAME_SAVED_PC (frame1);
113 val.next_frame = frame1;
114 }
115 }
116
117 return val;
118 }
119
120 /* Return a structure containing various interesting information
121 about the frame that called FRAME.
122
123 This is much faster than get_frame_info (get_prev_frame (FRAME))
124 because it does not need to search the entire stack
125 to find the frame called by the one being described -- that is FRAME. */
126
127 struct frame_info
128 get_prev_frame_info (next_frame)
129 FRAME next_frame;
130 {
131 struct frame_info val;
132 register FRAME frame = get_prev_frame (next_frame);
133
134 val.frame = frame;
135 val.next_frame = next_frame;
136
137 if (next_frame == 0)
138 {
139 val.pc = read_pc ();
140 }
141 else
142 {
143 val.pc = FRAME_SAVED_PC (next_frame);
144 }
145
146 return val;
147 }
148
149 CORE_ADDR
150 get_frame_pc (frame)
151 FRAME frame;
152 {
153 struct frame_info fi;
154 fi = get_frame_info (frame);
155 return fi.pc;
156 }
157
158 /* Find the addresses in which registers are saved in FRAME. */
159
160 void
161 get_frame_saved_regs (frame_info_addr, saved_regs_addr)
162 struct frame_info *frame_info_addr;
163 struct frame_saved_regs *saved_regs_addr;
164 {
165 FRAME_FIND_SAVED_REGS (*frame_info_addr, *saved_regs_addr);
166 }
167
168 /* Return the innermost lexical block in execution
169 in a specified stack frame. The frame address is assumed valid. */
170
171 struct block *
172 get_frame_block (frame)
173 FRAME frame;
174 {
175 struct frame_info fi;
176
177 fi = get_frame_info (frame);
178 return block_for_pc (fi.pc);
179 }
180
181 struct block *
182 get_current_block ()
183 {
184 return block_for_pc (read_pc ());
185 }
186
187 CORE_ADDR
188 get_pc_function_start (pc)
189 CORE_ADDR pc;
190 {
191 register struct block *bl = block_for_pc (pc);
192 register struct symbol *symbol;
193 if (bl == 0)
194 {
195 register int misc_index = find_pc_misc_function (pc);
196 if (misc_index >= 0)
197 return misc_function_vector[misc_index].address;
198 return 0;
199 }
200 symbol = block_function (bl);
201 bl = SYMBOL_BLOCK_VALUE (symbol);
202 return BLOCK_START (bl);
203 }
204
205 /* Return the symbol for the function executing in frame FRAME. */
206
207 struct symbol *
208 get_frame_function (frame)
209 FRAME frame;
210 {
211 register struct block *bl = get_frame_block (frame);
212 if (bl == 0)
213 return 0;
214 return block_function (bl);
215 }
216 \f
217 /* Return the innermost lexical block containing the specified pc value,
218 or 0 if there is none. */
219
220 struct block *
221 block_for_pc (pc)
222 register CORE_ADDR pc;
223 {
224 register struct block *b;
225 register int bot, top, half;
226 register struct symtab *s;
227 struct blockvector *bl;
228
229 /* First search all symtabs for one whose file contains our pc */
230
231 for (s = symtab_list; s; s = s->next)
232 {
233 bl = BLOCKVECTOR (s);
234 b = BLOCKVECTOR_BLOCK (bl, 0);
235 if (BLOCK_START (b) <= pc
236 && BLOCK_END (b) > pc)
237 break;
238 }
239
240 if (s == 0)
241 return 0;
242
243 /* Then search that symtab for the smallest block that wins. */
244 /* Use binary search to find the last block that starts before PC. */
245
246 bot = 0;
247 top = BLOCKVECTOR_NBLOCKS (bl);
248
249 while (top - bot > 1)
250 {
251 half = (top - bot + 1) >> 1;
252 b = BLOCKVECTOR_BLOCK (bl, bot + half);
253 if (BLOCK_START (b) <= pc)
254 bot += half;
255 else
256 top = bot + half;
257 }
258
259 /* Now search backward for a block that ends after PC. */
260
261 while (bot >= 0)
262 {
263 b = BLOCKVECTOR_BLOCK (bl, bot);
264 if (BLOCK_END (b) > pc)
265 return b;
266 bot--;
267 }
268
269 return 0;
270 }
271
272 /* Return the function containing pc value PC.
273 Returns 0 if function is not known. */
274
275 struct symbol *
276 find_pc_function (pc)
277 CORE_ADDR pc;
278 {
279 register struct block *b = block_for_pc (pc);
280 if (b == 0)
281 return 0;
282 return block_function (b);
283 }
284
285 /* Find the misc function whose address is the largest
286 while being less than PC. Return its index in misc_function_vector.
287 Returns -1 if PC is not in suitable range. */
288
289 int
290 find_pc_misc_function (pc)
291 register CORE_ADDR pc;
292 {
293 register int lo = 0;
294 register int hi = misc_function_count-1;
295 register int new;
296 register int distance;
297
298 /* Note that the last thing in the vector is always _etext. */
299
300 /* Above statement is not *always* true - fix for case where there are */
301 /* no misc functions at all (ie no symbol table has been read). */
302 if (hi < 0) return -1; /* no misc functions recorded */
303
304 /* trivial reject range test */
305 if (pc < misc_function_vector[0].address ||
306 pc > misc_function_vector[hi].address)
307 return -1;
308
309 do {
310 new = (lo + hi) >> 1;
311 distance = misc_function_vector[new].address - pc;
312 if (distance == 0)
313 return new; /* an exact match */
314 else if (distance > 0)
315 hi = new;
316 else
317 lo = new;
318 } while (hi-lo != 1);
319
320 /* if here, we had no exact match, so return the lower choice */
321 return lo;
322 }
323
324 /* Return the innermost stack frame executing inside of the specified block,
325 or zero if there is no such frame. */
326
327 FRAME
328 block_innermost_frame (block)
329 struct block *block;
330 {
331 struct frame_info fi;
332 register FRAME frame;
333 register CORE_ADDR start = BLOCK_START (block);
334 register CORE_ADDR end = BLOCK_END (block);
335
336 frame = 0;
337 while (1)
338 {
339 fi = get_prev_frame_info (frame);
340 frame = fi.frame;
341 if (frame == 0)
342 return 0;
343 if (fi.pc >= start && fi.pc < end)
344 return frame;
345 }
346 }
347
348 static
349 initialize ()
350 {
351 }
352
353 END_FILE
This page took 0.041618 seconds and 4 git commands to generate.