]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/trad-frame.c
[AArch64] SVE/FPSIMD fixup for big endian
[thirdparty/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;
6afcd2d4 59 regs[regnum].data = nullptr;
68811f8f
AH
60 }
61}
62
8983bd83 63struct trad_frame_saved_reg *
4d9a9006 64trad_frame_alloc_saved_regs (struct gdbarch *gdbarch)
a0f267c7 65{
f6efe3f8 66 int numregs = gdbarch_num_cooked_regs (gdbarch);
8983bd83
AC
67 struct trad_frame_saved_reg *this_saved_regs
68 = FRAME_OBSTACK_CALLOC (numregs, struct trad_frame_saved_reg);
5d502164 69
68811f8f 70 trad_frame_reset_saved_regs (gdbarch, this_saved_regs);
a0f267c7
AC
71 return this_saved_regs;
72}
73
4d9a9006
YQ
74/* A traditional frame is unwound by analysing the function prologue
75 and using the information gathered to track registers. For
76 non-optimized frames, the technique is reliable (just need to check
77 for all potential instruction sequences). */
78
79struct trad_frame_saved_reg *
80trad_frame_alloc_saved_regs (struct frame_info *this_frame)
81{
82 struct gdbarch *gdbarch = get_frame_arch (this_frame);
83
84 return trad_frame_alloc_saved_regs (gdbarch);
85}
86
6afcd2d4 87enum { TF_REG_VALUE = -1, TF_REG_UNKNOWN = -2, TF_REG_VALUE_BYTES = -3 };
3b3850e8
AC
88
89int
90trad_frame_value_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
91{
ee99023e 92 return (this_saved_regs[regnum].realreg == TF_REG_VALUE);
3b3850e8
AC
93}
94
95int
96trad_frame_addr_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
97{
98 return (this_saved_regs[regnum].realreg >= 0
99 && this_saved_regs[regnum].addr != -1);
100}
101
102int
103trad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs[],
104 int regnum)
105{
106 return (this_saved_regs[regnum].realreg >= 0
107 && this_saved_regs[regnum].addr == -1);
108}
109
6afcd2d4
LM
110/* See trad-frame.h. */
111
112bool
113trad_frame_value_bytes_p (struct trad_frame_saved_reg this_saved_regs[],
114 int regnum)
115{
116 return (this_saved_regs[regnum].realreg == TF_REG_VALUE_BYTES
117 && this_saved_regs[regnum].data != nullptr);
118}
119
a0f267c7 120void
3b3850e8
AC
121trad_frame_set_value (struct trad_frame_saved_reg this_saved_regs[],
122 int regnum, LONGEST val)
a0f267c7 123{
3b3850e8 124 /* Make the REALREG invalid, indicating that the ADDR contains the
a0f267c7 125 register's value. */
ee99023e 126 this_saved_regs[regnum].realreg = TF_REG_VALUE;
a0f267c7
AC
127 this_saved_regs[regnum].addr = val;
128}
129
23e60e7a
AB
130/* See trad-frame.h. */
131
132void
133trad_frame_set_realreg (struct trad_frame_saved_reg this_saved_regs[],
134 int regnum, int realreg)
135{
136 this_saved_regs[regnum].realreg = realreg;
137 this_saved_regs[regnum].addr = -1;
138}
139
140/* See trad-frame.h. */
141
142void
143trad_frame_set_addr (struct trad_frame_saved_reg this_saved_regs[],
144 int regnum, CORE_ADDR addr)
145{
146 this_saved_regs[regnum].realreg = regnum;
147 this_saved_regs[regnum].addr = addr;
148}
149
61e784e7
MS
150void
151trad_frame_set_reg_value (struct trad_frame_cache *this_trad_cache,
152 int regnum, LONGEST val)
153{
154 /* External interface for users of trad_frame_cache
155 (who cannot access the prev_regs object directly). */
156 trad_frame_set_value (this_trad_cache->prev_regs, regnum, val);
157}
158
e66299b3
AC
159void
160trad_frame_set_reg_realreg (struct trad_frame_cache *this_trad_cache,
161 int regnum, int realreg)
162{
23e60e7a 163 trad_frame_set_realreg (this_trad_cache->prev_regs, regnum, realreg);
e66299b3
AC
164}
165
0db9b4b7
AC
166void
167trad_frame_set_reg_addr (struct trad_frame_cache *this_trad_cache,
168 int regnum, CORE_ADDR addr)
169{
23e60e7a 170 trad_frame_set_addr (this_trad_cache->prev_regs, regnum, addr);
0db9b4b7
AC
171}
172
498f7407
JB
173void
174trad_frame_set_reg_regmap (struct trad_frame_cache *this_trad_cache,
175 const struct regcache_map_entry *regmap,
176 CORE_ADDR addr, size_t size)
177{
178 struct gdbarch *gdbarch = get_frame_arch (this_trad_cache->this_frame);
179 int offs = 0, count;
180
181 for (; (count = regmap->count) != 0; regmap++)
182 {
183 int regno = regmap->regno;
184 int slot_size = regmap->size;
185
186 if (slot_size == 0 && regno != REGCACHE_MAP_SKIP)
187 slot_size = register_size (gdbarch, regno);
188
189 if (offs + slot_size > size)
190 break;
191
192 if (regno == REGCACHE_MAP_SKIP)
193 offs += count * slot_size;
194 else
195 for (; count--; regno++, offs += slot_size)
196 {
197 /* Mimic the semantics of regcache::transfer_regset if a
198 register slot's size does not match the size of a
199 register.
200
201 If a register slot is larger than a register, assume
202 the register's value is stored in the first N bytes of
203 the slot and ignore the remaining bytes.
204
205 If the register slot is smaller than the register,
206 assume that the slot contains the low N bytes of the
207 register's value. Since trad_frame assumes that
208 registers stored by address are sized according to the
209 register, read the low N bytes and zero-extend them to
210 generate a register value. */
211 if (slot_size >= register_size (gdbarch, regno))
212 trad_frame_set_reg_addr (this_trad_cache, regno, addr + offs);
213 else
214 {
215 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
216 gdb_byte buf[slot_size];
217
218 if (target_read_memory (addr + offs, buf, sizeof buf) == 0)
219 {
220 LONGEST val
221 = extract_unsigned_integer (buf, sizeof buf, byte_order);
222 trad_frame_set_reg_value (this_trad_cache, regno, val);
223 }
224 }
225 }
226 }
227}
228
3b3850e8
AC
229void
230trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[],
231 int regnum)
232{
233 /* Make the REALREG invalid, indicating that the value is not known. */
ee99023e 234 this_saved_regs[regnum].realreg = TF_REG_UNKNOWN;
3b3850e8
AC
235 this_saved_regs[regnum].addr = -1;
236}
237
6afcd2d4
LM
238/* See trad-frame.h. */
239
240void
241trad_frame_set_value_bytes (struct trad_frame_saved_reg this_saved_regs[],
242 int regnum, const gdb_byte *bytes,
243 size_t size)
244{
245 this_saved_regs[regnum].realreg = TF_REG_VALUE_BYTES;
246
247 /* Allocate the space and copy the data bytes. */
248 this_saved_regs[regnum].data = FRAME_OBSTACK_CALLOC (size, gdb_byte);
249 memcpy (this_saved_regs[regnum].data, bytes, size);
250}
251
252/* See trad-frame.h. */
253
254void
255trad_frame_set_reg_value_bytes (struct trad_frame_cache *this_trad_cache,
256 int regnum, const gdb_byte *bytes,
257 size_t size)
258{
259 /* External interface for users of trad_frame_cache
260 (who cannot access the prev_regs object directly). */
261 trad_frame_set_value_bytes (this_trad_cache->prev_regs, regnum, bytes,
262 size);
263}
264
265
266
25492ce3
DJ
267struct value *
268trad_frame_get_prev_register (struct frame_info *this_frame,
1f67027d 269 struct trad_frame_saved_reg this_saved_regs[],
25492ce3 270 int regnum)
a0f267c7 271{
3b3850e8 272 if (trad_frame_addr_p (this_saved_regs, regnum))
25492ce3
DJ
273 /* The register was saved in memory. */
274 return frame_unwind_got_memory (this_frame, regnum,
275 this_saved_regs[regnum].addr);
3b3850e8 276 else if (trad_frame_realreg_p (this_saved_regs, regnum))
25492ce3
DJ
277 return frame_unwind_got_register (this_frame, regnum,
278 this_saved_regs[regnum].realreg);
3b3850e8 279 else if (trad_frame_value_p (this_saved_regs, regnum))
25492ce3
DJ
280 /* The register's value is available. */
281 return frame_unwind_got_constant (this_frame, regnum,
282 this_saved_regs[regnum].addr);
6afcd2d4
LM
283 else if (trad_frame_value_bytes_p (this_saved_regs, regnum))
284 /* The register's value is available as a sequence of bytes. */
285 return frame_unwind_got_bytes (this_frame, regnum,
286 this_saved_regs[regnum].data);
3b3850e8 287 else
25492ce3 288 return frame_unwind_got_optimized (this_frame, regnum);
a0f267c7 289}
0db9b4b7 290
25492ce3 291struct value *
0db9b4b7 292trad_frame_get_register (struct trad_frame_cache *this_trad_cache,
25492ce3
DJ
293 struct frame_info *this_frame,
294 int regnum)
295{
296 return trad_frame_get_prev_register (this_frame, this_trad_cache->prev_regs,
297 regnum);
0db9b4b7
AC
298}
299
300void
301trad_frame_set_id (struct trad_frame_cache *this_trad_cache,
302 struct frame_id this_id)
303{
304 this_trad_cache->this_id = this_id;
305}
306
307void
308trad_frame_get_id (struct trad_frame_cache *this_trad_cache,
309 struct frame_id *this_id)
310{
311 (*this_id) = this_trad_cache->this_id;
312}
e66299b3
AC
313
314void
315trad_frame_set_this_base (struct trad_frame_cache *this_trad_cache,
316 CORE_ADDR this_base)
317{
318 this_trad_cache->this_base = this_base;
319}
320
321CORE_ADDR
322trad_frame_get_this_base (struct trad_frame_cache *this_trad_cache)
323{
324 return this_trad_cache->this_base;
325}