gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / trad-frame.c
CommitLineData
a0f267c7
AC
1/* Traditional frame unwind support, for GDB the GNU Debugger.
2
b811d2c2 3 Copyright (C) 2003-2020 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"
25492ce3 24#include "frame-unwind.h"
498f7407 25#include "target.h"
25492ce3 26#include "value.h"
0d12e84c 27#include "gdbarch.h"
a0f267c7 28
0db9b4b7
AC
29struct trad_frame_cache
30{
25492ce3 31 struct frame_info *this_frame;
0db9b4b7
AC
32 CORE_ADDR this_base;
33 struct trad_frame_saved_reg *prev_regs;
34 struct frame_id this_id;
35};
36
37struct trad_frame_cache *
25492ce3 38trad_frame_cache_zalloc (struct frame_info *this_frame)
0db9b4b7
AC
39{
40 struct trad_frame_cache *this_trad_cache;
41
42 this_trad_cache = FRAME_OBSTACK_ZALLOC (struct trad_frame_cache);
25492ce3
DJ
43 this_trad_cache->prev_regs = trad_frame_alloc_saved_regs (this_frame);
44 this_trad_cache->this_frame = this_frame;
0db9b4b7
AC
45 return this_trad_cache;
46}
47
68811f8f
AH
48/* See trad-frame.h. */
49
50void
51trad_frame_reset_saved_regs (struct gdbarch *gdbarch,
52 struct trad_frame_saved_reg *regs)
53{
54 int numregs = gdbarch_num_cooked_regs (gdbarch);
55 for (int regnum = 0; regnum < numregs; regnum++)
56 {
57 regs[regnum].realreg = regnum;
58 regs[regnum].addr = -1;
59 }
60}
61
8983bd83 62struct trad_frame_saved_reg *
4d9a9006 63trad_frame_alloc_saved_regs (struct gdbarch *gdbarch)
a0f267c7 64{
f6efe3f8 65 int numregs = gdbarch_num_cooked_regs (gdbarch);
8983bd83
AC
66 struct trad_frame_saved_reg *this_saved_regs
67 = FRAME_OBSTACK_CALLOC (numregs, struct trad_frame_saved_reg);
5d502164 68
68811f8f 69 trad_frame_reset_saved_regs (gdbarch, this_saved_regs);
a0f267c7
AC
70 return this_saved_regs;
71}
72
4d9a9006
YQ
73/* A traditional frame is unwound by analysing the function prologue
74 and using the information gathered to track registers. For
75 non-optimized frames, the technique is reliable (just need to check
76 for all potential instruction sequences). */
77
78struct trad_frame_saved_reg *
79trad_frame_alloc_saved_regs (struct frame_info *this_frame)
80{
81 struct gdbarch *gdbarch = get_frame_arch (this_frame);
82
83 return trad_frame_alloc_saved_regs (gdbarch);
84}
85
ee99023e 86enum { TF_REG_VALUE = -1, TF_REG_UNKNOWN = -2 };
3b3850e8
AC
87
88int
89trad_frame_value_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
90{
ee99023e 91 return (this_saved_regs[regnum].realreg == TF_REG_VALUE);
3b3850e8
AC
92}
93
94int
95trad_frame_addr_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
96{
97 return (this_saved_regs[regnum].realreg >= 0
98 && this_saved_regs[regnum].addr != -1);
99}
100
101int
102trad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs[],
103 int regnum)
104{
105 return (this_saved_regs[regnum].realreg >= 0
106 && this_saved_regs[regnum].addr == -1);
107}
108
a0f267c7 109void
3b3850e8
AC
110trad_frame_set_value (struct trad_frame_saved_reg this_saved_regs[],
111 int regnum, LONGEST val)
a0f267c7 112{
3b3850e8 113 /* Make the REALREG invalid, indicating that the ADDR contains the
a0f267c7 114 register's value. */
ee99023e 115 this_saved_regs[regnum].realreg = TF_REG_VALUE;
a0f267c7
AC
116 this_saved_regs[regnum].addr = val;
117}
118
23e60e7a
AB
119/* See trad-frame.h. */
120
121void
122trad_frame_set_realreg (struct trad_frame_saved_reg this_saved_regs[],
123 int regnum, int realreg)
124{
125 this_saved_regs[regnum].realreg = realreg;
126 this_saved_regs[regnum].addr = -1;
127}
128
129/* See trad-frame.h. */
130
131void
132trad_frame_set_addr (struct trad_frame_saved_reg this_saved_regs[],
133 int regnum, CORE_ADDR addr)
134{
135 this_saved_regs[regnum].realreg = regnum;
136 this_saved_regs[regnum].addr = addr;
137}
138
61e784e7
MS
139void
140trad_frame_set_reg_value (struct trad_frame_cache *this_trad_cache,
141 int regnum, LONGEST val)
142{
143 /* External interface for users of trad_frame_cache
144 (who cannot access the prev_regs object directly). */
145 trad_frame_set_value (this_trad_cache->prev_regs, regnum, val);
146}
147
e66299b3
AC
148void
149trad_frame_set_reg_realreg (struct trad_frame_cache *this_trad_cache,
150 int regnum, int realreg)
151{
23e60e7a 152 trad_frame_set_realreg (this_trad_cache->prev_regs, regnum, realreg);
e66299b3
AC
153}
154
0db9b4b7
AC
155void
156trad_frame_set_reg_addr (struct trad_frame_cache *this_trad_cache,
157 int regnum, CORE_ADDR addr)
158{
23e60e7a 159 trad_frame_set_addr (this_trad_cache->prev_regs, regnum, addr);
0db9b4b7
AC
160}
161
498f7407
JB
162void
163trad_frame_set_reg_regmap (struct trad_frame_cache *this_trad_cache,
164 const struct regcache_map_entry *regmap,
165 CORE_ADDR addr, size_t size)
166{
167 struct gdbarch *gdbarch = get_frame_arch (this_trad_cache->this_frame);
168 int offs = 0, count;
169
170 for (; (count = regmap->count) != 0; regmap++)
171 {
172 int regno = regmap->regno;
173 int slot_size = regmap->size;
174
175 if (slot_size == 0 && regno != REGCACHE_MAP_SKIP)
176 slot_size = register_size (gdbarch, regno);
177
178 if (offs + slot_size > size)
179 break;
180
181 if (regno == REGCACHE_MAP_SKIP)
182 offs += count * slot_size;
183 else
184 for (; count--; regno++, offs += slot_size)
185 {
186 /* Mimic the semantics of regcache::transfer_regset if a
187 register slot's size does not match the size of a
188 register.
189
190 If a register slot is larger than a register, assume
191 the register's value is stored in the first N bytes of
192 the slot and ignore the remaining bytes.
193
194 If the register slot is smaller than the register,
195 assume that the slot contains the low N bytes of the
196 register's value. Since trad_frame assumes that
197 registers stored by address are sized according to the
198 register, read the low N bytes and zero-extend them to
199 generate a register value. */
200 if (slot_size >= register_size (gdbarch, regno))
201 trad_frame_set_reg_addr (this_trad_cache, regno, addr + offs);
202 else
203 {
204 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
205 gdb_byte buf[slot_size];
206
207 if (target_read_memory (addr + offs, buf, sizeof buf) == 0)
208 {
209 LONGEST val
210 = extract_unsigned_integer (buf, sizeof buf, byte_order);
211 trad_frame_set_reg_value (this_trad_cache, regno, val);
212 }
213 }
214 }
215 }
216}
217
3b3850e8
AC
218void
219trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[],
220 int regnum)
221{
222 /* Make the REALREG invalid, indicating that the value is not known. */
ee99023e 223 this_saved_regs[regnum].realreg = TF_REG_UNKNOWN;
3b3850e8
AC
224 this_saved_regs[regnum].addr = -1;
225}
226
25492ce3
DJ
227struct value *
228trad_frame_get_prev_register (struct frame_info *this_frame,
1f67027d 229 struct trad_frame_saved_reg this_saved_regs[],
25492ce3 230 int regnum)
a0f267c7 231{
3b3850e8 232 if (trad_frame_addr_p (this_saved_regs, regnum))
25492ce3
DJ
233 /* The register was saved in memory. */
234 return frame_unwind_got_memory (this_frame, regnum,
235 this_saved_regs[regnum].addr);
3b3850e8 236 else if (trad_frame_realreg_p (this_saved_regs, regnum))
25492ce3
DJ
237 return frame_unwind_got_register (this_frame, regnum,
238 this_saved_regs[regnum].realreg);
3b3850e8 239 else if (trad_frame_value_p (this_saved_regs, regnum))
25492ce3
DJ
240 /* The register's value is available. */
241 return frame_unwind_got_constant (this_frame, regnum,
242 this_saved_regs[regnum].addr);
3b3850e8 243 else
25492ce3 244 return frame_unwind_got_optimized (this_frame, regnum);
a0f267c7 245}
0db9b4b7 246
25492ce3 247struct value *
0db9b4b7 248trad_frame_get_register (struct trad_frame_cache *this_trad_cache,
25492ce3
DJ
249 struct frame_info *this_frame,
250 int regnum)
251{
252 return trad_frame_get_prev_register (this_frame, this_trad_cache->prev_regs,
253 regnum);
0db9b4b7
AC
254}
255
256void
257trad_frame_set_id (struct trad_frame_cache *this_trad_cache,
258 struct frame_id this_id)
259{
260 this_trad_cache->this_id = this_id;
261}
262
263void
264trad_frame_get_id (struct trad_frame_cache *this_trad_cache,
265 struct frame_id *this_id)
266{
267 (*this_id) = this_trad_cache->this_id;
268}
e66299b3
AC
269
270void
271trad_frame_set_this_base (struct trad_frame_cache *this_trad_cache,
272 CORE_ADDR this_base)
273{
274 this_trad_cache->this_base = this_base;
275}
276
277CORE_ADDR
278trad_frame_get_this_base (struct trad_frame_cache *this_trad_cache)
279{
280 return this_trad_cache->this_base;
281}
This page took 1.893015 seconds and 4 git commands to generate.