]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/trad-frame.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / gdb / trad-frame.c
CommitLineData
a0f267c7
AC
1/* Traditional frame unwind support, for GDB the GNU Debugger.
2
d01e8234 3 Copyright (C) 2003-2025 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 19
ec452525 20#include "extract-store-integer.h"
a0f267c7
AC
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"
58eadc4b 28#include "gdbsupport/traits.h"
a0f267c7 29
0db9b4b7
AC
30struct trad_frame_cache
31{
bd2b40ac 32 frame_info_ptr this_frame;
0db9b4b7 33 CORE_ADDR this_base;
098caef4 34 trad_frame_saved_reg *prev_regs;
0db9b4b7
AC
35 struct frame_id this_id;
36};
37
38struct trad_frame_cache *
8480a37e 39trad_frame_cache_zalloc (const frame_info_ptr &this_frame)
0db9b4b7
AC
40{
41 struct trad_frame_cache *this_trad_cache;
42
43 this_trad_cache = FRAME_OBSTACK_ZALLOC (struct trad_frame_cache);
25492ce3
DJ
44 this_trad_cache->prev_regs = trad_frame_alloc_saved_regs (this_frame);
45 this_trad_cache->this_frame = this_frame;
0db9b4b7
AC
46 return this_trad_cache;
47}
48
68811f8f
AH
49/* See trad-frame.h. */
50
51void
52trad_frame_reset_saved_regs (struct gdbarch *gdbarch,
098caef4 53 trad_frame_saved_reg *regs)
68811f8f
AH
54{
55 int numregs = gdbarch_num_cooked_regs (gdbarch);
098caef4 56
68811f8f 57 for (int regnum = 0; regnum < numregs; regnum++)
098caef4 58 regs[regnum].set_realreg (regnum);
68811f8f
AH
59}
60
098caef4 61trad_frame_saved_reg *
4d9a9006 62trad_frame_alloc_saved_regs (struct gdbarch *gdbarch)
a0f267c7 63{
69f6730d 64 static_assert (std::is_trivially_constructible<trad_frame_saved_reg>::value);
098caef4 65
f6efe3f8 66 int numregs = gdbarch_num_cooked_regs (gdbarch);
098caef4
LM
67 trad_frame_saved_reg *this_saved_regs
68 = FRAME_OBSTACK_CALLOC (numregs, trad_frame_saved_reg);
5d502164 69
a9a87d35
LM
70 /* For backwards compatibility, initialize all the register values to
71 REALREG, with register 0 stored in 0, register 1 stored in 1 and so
72 on. */
68811f8f 73 trad_frame_reset_saved_regs (gdbarch, this_saved_regs);
a9a87d35 74
a0f267c7
AC
75 return this_saved_regs;
76}
77
4d9a9006
YQ
78/* A traditional frame is unwound by analysing the function prologue
79 and using the information gathered to track registers. For
80 non-optimized frames, the technique is reliable (just need to check
81 for all potential instruction sequences). */
82
098caef4 83trad_frame_saved_reg *
8480a37e 84trad_frame_alloc_saved_regs (const frame_info_ptr &this_frame)
4d9a9006
YQ
85{
86 struct gdbarch *gdbarch = get_frame_arch (this_frame);
87
88 return trad_frame_alloc_saved_regs (gdbarch);
89}
90
61e784e7
MS
91void
92trad_frame_set_reg_value (struct trad_frame_cache *this_trad_cache,
93 int regnum, LONGEST val)
94{
95 /* External interface for users of trad_frame_cache
96 (who cannot access the prev_regs object directly). */
a9a87d35 97 this_trad_cache->prev_regs[regnum].set_value (val);
61e784e7
MS
98}
99
e66299b3
AC
100void
101trad_frame_set_reg_realreg (struct trad_frame_cache *this_trad_cache,
102 int regnum, int realreg)
103{
a9a87d35 104 this_trad_cache->prev_regs[regnum].set_realreg (realreg);
e66299b3
AC
105}
106
0db9b4b7
AC
107void
108trad_frame_set_reg_addr (struct trad_frame_cache *this_trad_cache,
109 int regnum, CORE_ADDR addr)
110{
a9a87d35 111 this_trad_cache->prev_regs[regnum].set_addr (addr);
0db9b4b7
AC
112}
113
498f7407
JB
114void
115trad_frame_set_reg_regmap (struct trad_frame_cache *this_trad_cache,
116 const struct regcache_map_entry *regmap,
117 CORE_ADDR addr, size_t size)
118{
119 struct gdbarch *gdbarch = get_frame_arch (this_trad_cache->this_frame);
120 int offs = 0, count;
121
122 for (; (count = regmap->count) != 0; regmap++)
123 {
124 int regno = regmap->regno;
125 int slot_size = regmap->size;
126
127 if (slot_size == 0 && regno != REGCACHE_MAP_SKIP)
128 slot_size = register_size (gdbarch, regno);
129
130 if (offs + slot_size > size)
131 break;
132
133 if (regno == REGCACHE_MAP_SKIP)
134 offs += count * slot_size;
135 else
136 for (; count--; regno++, offs += slot_size)
137 {
138 /* Mimic the semantics of regcache::transfer_regset if a
139 register slot's size does not match the size of a
140 register.
141
142 If a register slot is larger than a register, assume
143 the register's value is stored in the first N bytes of
144 the slot and ignore the remaining bytes.
145
146 If the register slot is smaller than the register,
147 assume that the slot contains the low N bytes of the
148 register's value. Since trad_frame assumes that
149 registers stored by address are sized according to the
150 register, read the low N bytes and zero-extend them to
151 generate a register value. */
152 if (slot_size >= register_size (gdbarch, regno))
153 trad_frame_set_reg_addr (this_trad_cache, regno, addr + offs);
154 else
155 {
156 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
d724d71a 157 gdb::byte_vector buf (slot_size);
498f7407 158
d724d71a
SM
159 if (target_read_memory (addr + offs, buf.data (), buf.size ())
160 == 0)
498f7407
JB
161 {
162 LONGEST val
d724d71a
SM
163 = extract_unsigned_integer (buf.data (), buf.size (),
164 byte_order);
498f7407
JB
165 trad_frame_set_reg_value (this_trad_cache, regno, val);
166 }
167 }
168 }
169 }
170}
171
6afcd2d4
LM
172/* See trad-frame.h. */
173
174void
175trad_frame_set_reg_value_bytes (struct trad_frame_cache *this_trad_cache,
ccbe4c82
LM
176 int regnum,
177 gdb::array_view<const gdb_byte> bytes)
6afcd2d4
LM
178{
179 /* External interface for users of trad_frame_cache
180 (who cannot access the prev_regs object directly). */
a9a87d35 181 this_trad_cache->prev_regs[regnum].set_value_bytes (bytes);
6afcd2d4
LM
182}
183
184
185
25492ce3 186struct value *
8480a37e 187trad_frame_get_prev_register (const frame_info_ptr &this_frame,
098caef4 188 trad_frame_saved_reg this_saved_regs[],
25492ce3 189 int regnum)
a0f267c7 190{
a9a87d35 191 if (this_saved_regs[regnum].is_addr ())
25492ce3
DJ
192 /* The register was saved in memory. */
193 return frame_unwind_got_memory (this_frame, regnum,
098caef4 194 this_saved_regs[regnum].addr ());
a9a87d35 195 else if (this_saved_regs[regnum].is_realreg ())
25492ce3 196 return frame_unwind_got_register (this_frame, regnum,
098caef4 197 this_saved_regs[regnum].realreg ());
a9a87d35 198 else if (this_saved_regs[regnum].is_value ())
25492ce3
DJ
199 /* The register's value is available. */
200 return frame_unwind_got_constant (this_frame, regnum,
098caef4 201 this_saved_regs[regnum].value ());
a9a87d35 202 else if (this_saved_regs[regnum].is_value_bytes ())
6afcd2d4
LM
203 /* The register's value is available as a sequence of bytes. */
204 return frame_unwind_got_bytes (this_frame, regnum,
098caef4 205 this_saved_regs[regnum].value_bytes ());
3b3850e8 206 else
25492ce3 207 return frame_unwind_got_optimized (this_frame, regnum);
a0f267c7 208}
0db9b4b7 209
25492ce3 210struct value *
0db9b4b7 211trad_frame_get_register (struct trad_frame_cache *this_trad_cache,
8480a37e 212 const frame_info_ptr &this_frame,
25492ce3
DJ
213 int regnum)
214{
215 return trad_frame_get_prev_register (this_frame, this_trad_cache->prev_regs,
216 regnum);
0db9b4b7
AC
217}
218
219void
220trad_frame_set_id (struct trad_frame_cache *this_trad_cache,
221 struct frame_id this_id)
222{
223 this_trad_cache->this_id = this_id;
224}
225
226void
227trad_frame_get_id (struct trad_frame_cache *this_trad_cache,
228 struct frame_id *this_id)
229{
230 (*this_id) = this_trad_cache->this_id;
231}
e66299b3
AC
232
233void
234trad_frame_set_this_base (struct trad_frame_cache *this_trad_cache,
235 CORE_ADDR this_base)
236{
237 this_trad_cache->this_base = this_base;
238}
239
240CORE_ADDR
241trad_frame_get_this_base (struct trad_frame_cache *this_trad_cache)
242{
243 return this_trad_cache->this_base;
244}