Reviewed and approved by Kevin Buettner <kevinb@redhat.com>
[deliverable/binutils-gdb.git] / gdb / frame.c
CommitLineData
4f460812 1/* Cache and manage frames for GDB, the GNU debugger.
96cb11df
AC
2
3 Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000,
4 2001, 2002 Free Software Foundation, Inc.
d65fe839
AC
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23#include "defs.h"
24#include "frame.h"
25#include "target.h"
26#include "value.h"
39f77062 27#include "inferior.h" /* for inferior_ptid */
4e052eda 28#include "regcache.h"
4f460812 29#include "gdb_assert.h"
d65fe839 30
101dcfbe
AC
31/* Return a frame uniq ID that can be used to, later re-find the
32 frame. */
33
34void
35get_frame_id (struct frame_info *fi, struct frame_id *id)
36{
37 if (fi == NULL)
38 {
39 id->base = 0;
40 id->pc = 0;
41 }
42 else
43 {
44 id->base = FRAME_FP (fi);
45 id->pc = fi->pc;
46 }
47}
48
49struct frame_info *
50frame_find_by_id (struct frame_id id)
51{
52 struct frame_info *frame;
53
54 /* ZERO denotes the null frame, let the caller decide what to do
55 about it. Should it instead return get_current_frame()? */
56 if (id.base == 0 && id.pc == 0)
57 return NULL;
58
59 for (frame = get_current_frame ();
60 frame != NULL;
61 frame = get_prev_frame (frame))
62 {
63 if (INNER_THAN (FRAME_FP (frame), id.base))
64 /* ``inner/current < frame < id.base''. Keep looking along
65 the frame chain. */
66 continue;
67 if (INNER_THAN (id.base, FRAME_FP (frame)))
68 /* ``inner/current < id.base < frame''. Oops, gone past it.
69 Just give up. */
70 return NULL;
71 /* FIXME: cagney/2002-04-21: This isn't sufficient. It should
72 use id.pc to check that the two frames belong to the same
73 function. Otherwise we'll do things like match dummy frames
74 or mis-match frameless functions. However, until someone
75 notices, stick with the existing behavour. */
76 return frame;
77 }
78 return NULL;
79}
80
d65fe839
AC
81/* FIND_SAVED_REGISTER ()
82
83 Return the address in which frame FRAME's value of register REGNUM
84 has been saved in memory. Or return zero if it has not been saved.
85 If REGNUM specifies the SP, the value we return is actually
86 the SP value, not an address where it was saved. */
87
88CORE_ADDR
89find_saved_register (struct frame_info *frame, int regnum)
90{
91 register struct frame_info *frame1 = NULL;
92 register CORE_ADDR addr = 0;
93
94 if (frame == NULL) /* No regs saved if want current frame */
95 return 0;
96
b2f01c35
KB
97 /* Note that the following loop assumes that registers used in
98 frame x will be saved only in the frame that x calls and frames
99 interior to it. */
d65fe839
AC
100 while (1)
101 {
102 QUIT;
aa40ec90
JT
103 frame1 = get_next_frame (frame);
104 if (frame1 == 0)
d65fe839 105 break;
aa40ec90 106 frame = frame1;
d65fe839
AC
107 FRAME_INIT_SAVED_REGS (frame1);
108 if (frame1->saved_regs[regnum])
b2f01c35
KB
109 {
110 addr = frame1->saved_regs[regnum];
111 break;
112 }
d65fe839
AC
113 }
114
115 return addr;
116}
117
4f460812
AC
118void
119frame_register_unwind (struct frame_info *frame, int regnum,
120 int *optimizedp, enum lval_type *lvalp,
121 CORE_ADDR *addrp, int *realnump, void *bufferp)
122{
123 struct frame_unwind_cache *cache;
124
125 /* Require all but BUFFERP to be valid. A NULL BUFFERP indicates
126 that the value proper does not need to be fetched. */
127 gdb_assert (optimizedp != NULL);
128 gdb_assert (lvalp != NULL);
129 gdb_assert (addrp != NULL);
130 gdb_assert (realnump != NULL);
131 /* gdb_assert (bufferp != NULL); */
132
133 /* NOTE: cagney/2002-04-14: It would be nice if, instead of a
134 special case, there was always an inner frame dedicated to the
135 hardware registers. Unfortunatly, there is too much unwind code
136 around that looks up/down the frame chain while making the
137 assumption that each frame level is using the same unwind code. */
138
139 if (frame == NULL)
140 {
141 /* We're in the inner-most frame, get the value direct from the
142 register cache. */
143 *optimizedp = 0;
144 *lvalp = lval_register;
fa5f27c7
AC
145 /* ULGH! Code uses the offset into the raw register byte array
146 as a way of identifying a register. */
147 *addrp = REGISTER_BYTE (regnum);
4f460812
AC
148 /* Should this code test ``register_cached (regnum) < 0'' and do
149 something like set realnum to -1 when the register isn't
150 available? */
151 *realnump = regnum;
152 if (bufferp)
153 read_register_gen (regnum, bufferp);
154 return;
155 }
156
157 /* Ask this frame to unwind its register. */
158 frame->register_unwind (frame, &frame->register_unwind_cache, regnum,
159 optimizedp, lvalp, addrp, realnump, bufferp);
160}
161
162
163void
164generic_unwind_get_saved_register (char *raw_buffer,
165 int *optimizedp,
166 CORE_ADDR *addrp,
167 struct frame_info *frame,
168 int regnum,
169 enum lval_type *lvalp)
170{
171 int optimizedx;
172 CORE_ADDR addrx;
173 int realnumx;
174 enum lval_type lvalx;
175
176 if (!target_has_registers)
177 error ("No registers.");
178
179 /* Keep things simple, ensure that all the pointers (except valuep)
180 are non NULL. */
181 if (optimizedp == NULL)
182 optimizedp = &optimizedx;
183 if (lvalp == NULL)
184 lvalp = &lvalx;
185 if (addrp == NULL)
186 addrp = &addrx;
187
188 /* Reached the the bottom (youngest, inner most) of the frame chain
189 (youngest, inner most) frame, go direct to the hardware register
190 cache (do not pass go, do not try to cache the value, ...). The
191 unwound value would have been cached in frame->next but that
192 doesn't exist. This doesn't matter as the hardware register
193 cache is stopping any unnecessary accesses to the target. */
194
195 /* NOTE: cagney/2002-04-14: It would be nice if, instead of a
196 special case, there was always an inner frame dedicated to the
197 hardware registers. Unfortunatly, there is too much unwind code
198 around that looks up/down the frame chain while making the
199 assumption that each frame level is using the same unwind code. */
200
201 if (frame == NULL)
202 frame_register_unwind (NULL, regnum, optimizedp, lvalp, addrp, &realnumx,
203 raw_buffer);
204 else
205 frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp,
206 &realnumx, raw_buffer);
207}
208
d65fe839
AC
209void
210get_saved_register (char *raw_buffer,
211 int *optimized,
212 CORE_ADDR *addrp,
213 struct frame_info *frame,
214 int regnum,
215 enum lval_type *lval)
216{
217 GET_SAVED_REGISTER (raw_buffer, optimized, addrp, frame, regnum, lval);
218}
219
cda5a58a 220/* frame_register_read ()
d65fe839 221
cda5a58a 222 Find and return the value of REGNUM for the specified stack frame.
d65fe839
AC
223 The number of bytes copied is REGISTER_RAW_SIZE (REGNUM).
224
cda5a58a 225 Returns 0 if the register value could not be found. */
d65fe839 226
cda5a58a
AC
227int
228frame_register_read (struct frame_info *frame, int regnum, void *myaddr)
d65fe839
AC
229{
230 int optim;
d65fe839
AC
231 get_saved_register (myaddr, &optim, (CORE_ADDR *) NULL, frame,
232 regnum, (enum lval_type *) NULL);
233
c97dcfc7
AC
234 /* FIXME: cagney/2002-05-15: This test, is just bogus.
235
236 It indicates that the target failed to supply a value for a
237 register because it was "not available" at this time. Problem
238 is, the target still has the register and so get saved_register()
239 may be returning a value saved on the stack. */
240
d65fe839 241 if (register_cached (regnum) < 0)
cda5a58a 242 return 0; /* register value not available */
d65fe839 243
cda5a58a 244 return !optim;
d65fe839 245}
This page took 0.145399 seconds and 4 git commands to generate.