]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/trad-frame.c
*** empty log message ***
[thirdparty/binutils-gdb.git] / gdb / trad-frame.c
CommitLineData
a0f267c7
AC
1/* Traditional frame unwind support, for GDB the GNU Debugger.
2
6aba47ca 3 Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
a0f267c7
AC
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
a0f267c7
AC
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
a0f267c7
AC
19
20#include "defs.h"
21#include "frame.h"
22#include "trad-frame.h"
23#include "regcache.h"
24
0db9b4b7
AC
25struct trad_frame_cache
26{
27 struct frame_info *next_frame;
28 CORE_ADDR this_base;
29 struct trad_frame_saved_reg *prev_regs;
30 struct frame_id this_id;
31};
32
33struct trad_frame_cache *
34trad_frame_cache_zalloc (struct frame_info *next_frame)
35{
36 struct trad_frame_cache *this_trad_cache;
37
38 this_trad_cache = FRAME_OBSTACK_ZALLOC (struct trad_frame_cache);
39 this_trad_cache->prev_regs = trad_frame_alloc_saved_regs (next_frame);
40 this_trad_cache->next_frame = next_frame;
41 return this_trad_cache;
42}
43
a0f267c7
AC
44/* A traditional frame is unwound by analysing the function prologue
45 and using the information gathered to track registers. For
46 non-optimized frames, the technique is reliable (just need to check
47 for all potential instruction sequences). */
48
8983bd83 49struct trad_frame_saved_reg *
a0f267c7
AC
50trad_frame_alloc_saved_regs (struct frame_info *next_frame)
51{
8983bd83 52 int regnum;
a0f267c7 53 struct gdbarch *gdbarch = get_frame_arch (next_frame);
f57d151a
UW
54 int numregs = gdbarch_num_regs (current_gdbarch)
55 + gdbarch_num_pseudo_regs (current_gdbarch);
8983bd83
AC
56 struct trad_frame_saved_reg *this_saved_regs
57 = FRAME_OBSTACK_CALLOC (numregs, struct trad_frame_saved_reg);
58 for (regnum = 0; regnum < numregs; regnum++)
3b3850e8
AC
59 {
60 this_saved_regs[regnum].realreg = regnum;
61 this_saved_regs[regnum].addr = -1;
62 }
a0f267c7
AC
63 return this_saved_regs;
64}
65
3b3850e8
AC
66enum { REG_VALUE = -1, REG_UNKNOWN = -2 };
67
68int
69trad_frame_value_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
70{
71 return (this_saved_regs[regnum].realreg == REG_VALUE);
72}
73
74int
75trad_frame_addr_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
76{
77 return (this_saved_regs[regnum].realreg >= 0
78 && this_saved_regs[regnum].addr != -1);
79}
80
81int
82trad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs[],
83 int regnum)
84{
85 return (this_saved_regs[regnum].realreg >= 0
86 && this_saved_regs[regnum].addr == -1);
87}
88
a0f267c7 89void
3b3850e8
AC
90trad_frame_set_value (struct trad_frame_saved_reg this_saved_regs[],
91 int regnum, LONGEST val)
a0f267c7 92{
3b3850e8 93 /* Make the REALREG invalid, indicating that the ADDR contains the
a0f267c7 94 register's value. */
3b3850e8 95 this_saved_regs[regnum].realreg = REG_VALUE;
a0f267c7
AC
96 this_saved_regs[regnum].addr = val;
97}
98
61e784e7
MS
99void
100trad_frame_set_reg_value (struct trad_frame_cache *this_trad_cache,
101 int regnum, LONGEST val)
102{
103 /* External interface for users of trad_frame_cache
104 (who cannot access the prev_regs object directly). */
105 trad_frame_set_value (this_trad_cache->prev_regs, regnum, val);
106}
107
e66299b3
AC
108void
109trad_frame_set_reg_realreg (struct trad_frame_cache *this_trad_cache,
110 int regnum, int realreg)
111{
112 this_trad_cache->prev_regs[regnum].realreg = realreg;
113 this_trad_cache->prev_regs[regnum].addr = -1;
114}
115
0db9b4b7
AC
116void
117trad_frame_set_reg_addr (struct trad_frame_cache *this_trad_cache,
118 int regnum, CORE_ADDR addr)
119{
120 this_trad_cache->prev_regs[regnum].addr = addr;
121}
122
3b3850e8
AC
123void
124trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[],
125 int regnum)
126{
127 /* Make the REALREG invalid, indicating that the value is not known. */
128 this_saved_regs[regnum].realreg = REG_UNKNOWN;
129 this_saved_regs[regnum].addr = -1;
130}
131
a0f267c7 132void
1f67027d
AC
133trad_frame_get_prev_register (struct frame_info *next_frame,
134 struct trad_frame_saved_reg this_saved_regs[],
135 int regnum, int *optimizedp,
136 enum lval_type *lvalp, CORE_ADDR *addrp,
10c42a71 137 int *realregp, gdb_byte *bufferp)
a0f267c7
AC
138{
139 struct gdbarch *gdbarch = get_frame_arch (next_frame);
3b3850e8 140 if (trad_frame_addr_p (this_saved_regs, regnum))
a0f267c7 141 {
8983bd83 142 /* The register was saved in memory. */
a0f267c7
AC
143 *optimizedp = 0;
144 *lvalp = lval_memory;
145 *addrp = this_saved_regs[regnum].addr;
3b3850e8 146 *realregp = -1;
a0f267c7
AC
147 if (bufferp != NULL)
148 {
149 /* Read the value in from memory. */
150 get_frame_memory (next_frame, this_saved_regs[regnum].addr, bufferp,
151 register_size (gdbarch, regnum));
152 }
153 }
3b3850e8 154 else if (trad_frame_realreg_p (this_saved_regs, regnum))
a0f267c7 155 {
00b25ff3
AC
156 *optimizedp = 0;
157 *lvalp = lval_register;
158 *addrp = 0;
159 *realregp = this_saved_regs[regnum].realreg;
260a4188 160 /* Ask the next frame to return the value of the register. */
00b25ff3
AC
161 if (bufferp)
162 frame_unwind_register (next_frame, (*realregp), bufferp);
a0f267c7 163 }
3b3850e8 164 else if (trad_frame_value_p (this_saved_regs, regnum))
a0f267c7
AC
165 {
166 /* The register's value is available. */
167 *optimizedp = 0;
168 *lvalp = not_lval;
169 *addrp = 0;
3b3850e8 170 *realregp = -1;
a0f267c7
AC
171 if (bufferp != NULL)
172 store_unsigned_integer (bufferp, register_size (gdbarch, regnum),
173 this_saved_regs[regnum].addr);
174 }
3b3850e8
AC
175 else
176 {
8a3fe4f8 177 error (_("Register %s not available"),
3b3850e8
AC
178 gdbarch_register_name (gdbarch, regnum));
179 }
a0f267c7 180}
0db9b4b7
AC
181
182void
183trad_frame_get_register (struct trad_frame_cache *this_trad_cache,
184 struct frame_info *next_frame,
185 int regnum, int *optimizedp,
186 enum lval_type *lvalp, CORE_ADDR *addrp,
10c42a71 187 int *realregp, gdb_byte *bufferp)
0db9b4b7 188{
1f67027d
AC
189 trad_frame_get_prev_register (next_frame, this_trad_cache->prev_regs,
190 regnum, optimizedp, lvalp, addrp, realregp,
191 bufferp);
0db9b4b7
AC
192}
193
194void
195trad_frame_set_id (struct trad_frame_cache *this_trad_cache,
196 struct frame_id this_id)
197{
198 this_trad_cache->this_id = this_id;
199}
200
201void
202trad_frame_get_id (struct trad_frame_cache *this_trad_cache,
203 struct frame_id *this_id)
204{
205 (*this_id) = this_trad_cache->this_id;
206}
e66299b3
AC
207
208void
209trad_frame_set_this_base (struct trad_frame_cache *this_trad_cache,
210 CORE_ADDR this_base)
211{
212 this_trad_cache->this_base = this_base;
213}
214
215CORE_ADDR
216trad_frame_get_this_base (struct trad_frame_cache *this_trad_cache)
217{
218 return this_trad_cache->this_base;
219}