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