1 /* Traditional frame unwind support, for GDB the GNU Debugger.
3 Copyright (C) 2003-2023 Free Software Foundation, Inc.
5 This file is part of GDB.
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
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 #include "trad-frame.h"
24 #include "frame-unwind.h"
28 #include "gdbsupport/traits.h"
30 struct trad_frame_cache
32 frame_info_ptr this_frame
;
34 trad_frame_saved_reg
*prev_regs
;
35 struct frame_id this_id
;
38 struct trad_frame_cache
*
39 trad_frame_cache_zalloc (frame_info_ptr this_frame
)
41 struct trad_frame_cache
*this_trad_cache
;
43 this_trad_cache
= FRAME_OBSTACK_ZALLOC (struct trad_frame_cache
);
44 this_trad_cache
->prev_regs
= trad_frame_alloc_saved_regs (this_frame
);
45 this_trad_cache
->this_frame
= this_frame
;
46 return this_trad_cache
;
49 /* See trad-frame.h. */
52 trad_frame_reset_saved_regs (struct gdbarch
*gdbarch
,
53 trad_frame_saved_reg
*regs
)
55 int numregs
= gdbarch_num_cooked_regs (gdbarch
);
57 for (int regnum
= 0; regnum
< numregs
; regnum
++)
58 regs
[regnum
].set_realreg (regnum
);
61 trad_frame_saved_reg
*
62 trad_frame_alloc_saved_regs (struct gdbarch
*gdbarch
)
64 #ifdef HAVE_IS_TRIVIALLY_CONSTRUCTIBLE
65 gdb_static_assert (std::is_trivially_constructible
<trad_frame_saved_reg
>::value
);
68 int numregs
= gdbarch_num_cooked_regs (gdbarch
);
69 trad_frame_saved_reg
*this_saved_regs
70 = FRAME_OBSTACK_CALLOC (numregs
, trad_frame_saved_reg
);
72 /* For backwards compatibility, initialize all the register values to
73 REALREG, with register 0 stored in 0, register 1 stored in 1 and so
75 trad_frame_reset_saved_regs (gdbarch
, this_saved_regs
);
77 return this_saved_regs
;
80 /* A traditional frame is unwound by analysing the function prologue
81 and using the information gathered to track registers. For
82 non-optimized frames, the technique is reliable (just need to check
83 for all potential instruction sequences). */
85 trad_frame_saved_reg
*
86 trad_frame_alloc_saved_regs (frame_info_ptr this_frame
)
88 struct gdbarch
*gdbarch
= get_frame_arch (this_frame
);
90 return trad_frame_alloc_saved_regs (gdbarch
);
94 trad_frame_set_reg_value (struct trad_frame_cache
*this_trad_cache
,
95 int regnum
, LONGEST val
)
97 /* External interface for users of trad_frame_cache
98 (who cannot access the prev_regs object directly). */
99 this_trad_cache
->prev_regs
[regnum
].set_value (val
);
103 trad_frame_set_reg_realreg (struct trad_frame_cache
*this_trad_cache
,
104 int regnum
, int realreg
)
106 this_trad_cache
->prev_regs
[regnum
].set_realreg (realreg
);
110 trad_frame_set_reg_addr (struct trad_frame_cache
*this_trad_cache
,
111 int regnum
, CORE_ADDR addr
)
113 this_trad_cache
->prev_regs
[regnum
].set_addr (addr
);
117 trad_frame_set_reg_regmap (struct trad_frame_cache
*this_trad_cache
,
118 const struct regcache_map_entry
*regmap
,
119 CORE_ADDR addr
, size_t size
)
121 struct gdbarch
*gdbarch
= get_frame_arch (this_trad_cache
->this_frame
);
124 for (; (count
= regmap
->count
) != 0; regmap
++)
126 int regno
= regmap
->regno
;
127 int slot_size
= regmap
->size
;
129 if (slot_size
== 0 && regno
!= REGCACHE_MAP_SKIP
)
130 slot_size
= register_size (gdbarch
, regno
);
132 if (offs
+ slot_size
> size
)
135 if (regno
== REGCACHE_MAP_SKIP
)
136 offs
+= count
* slot_size
;
138 for (; count
--; regno
++, offs
+= slot_size
)
140 /* Mimic the semantics of regcache::transfer_regset if a
141 register slot's size does not match the size of a
144 If a register slot is larger than a register, assume
145 the register's value is stored in the first N bytes of
146 the slot and ignore the remaining bytes.
148 If the register slot is smaller than the register,
149 assume that the slot contains the low N bytes of the
150 register's value. Since trad_frame assumes that
151 registers stored by address are sized according to the
152 register, read the low N bytes and zero-extend them to
153 generate a register value. */
154 if (slot_size
>= register_size (gdbarch
, regno
))
155 trad_frame_set_reg_addr (this_trad_cache
, regno
, addr
+ offs
);
158 enum bfd_endian byte_order
= gdbarch_byte_order (gdbarch
);
159 gdb_byte buf
[slot_size
];
161 if (target_read_memory (addr
+ offs
, buf
, sizeof buf
) == 0)
164 = extract_unsigned_integer (buf
, sizeof buf
, byte_order
);
165 trad_frame_set_reg_value (this_trad_cache
, regno
, val
);
172 /* See trad-frame.h. */
175 trad_frame_set_reg_value_bytes (struct trad_frame_cache
*this_trad_cache
,
177 gdb::array_view
<const gdb_byte
> bytes
)
179 /* External interface for users of trad_frame_cache
180 (who cannot access the prev_regs object directly). */
181 this_trad_cache
->prev_regs
[regnum
].set_value_bytes (bytes
);
187 trad_frame_get_prev_register (frame_info_ptr this_frame
,
188 trad_frame_saved_reg this_saved_regs
[],
191 if (this_saved_regs
[regnum
].is_addr ())
192 /* The register was saved in memory. */
193 return frame_unwind_got_memory (this_frame
, regnum
,
194 this_saved_regs
[regnum
].addr ());
195 else if (this_saved_regs
[regnum
].is_realreg ())
196 return frame_unwind_got_register (this_frame
, regnum
,
197 this_saved_regs
[regnum
].realreg ());
198 else if (this_saved_regs
[regnum
].is_value ())
199 /* The register's value is available. */
200 return frame_unwind_got_constant (this_frame
, regnum
,
201 this_saved_regs
[regnum
].value ());
202 else if (this_saved_regs
[regnum
].is_value_bytes ())
203 /* The register's value is available as a sequence of bytes. */
204 return frame_unwind_got_bytes (this_frame
, regnum
,
205 this_saved_regs
[regnum
].value_bytes ());
207 return frame_unwind_got_optimized (this_frame
, regnum
);
211 trad_frame_get_register (struct trad_frame_cache
*this_trad_cache
,
212 frame_info_ptr this_frame
,
215 return trad_frame_get_prev_register (this_frame
, this_trad_cache
->prev_regs
,
220 trad_frame_set_id (struct trad_frame_cache
*this_trad_cache
,
221 struct frame_id this_id
)
223 this_trad_cache
->this_id
= this_id
;
227 trad_frame_get_id (struct trad_frame_cache
*this_trad_cache
,
228 struct frame_id
*this_id
)
230 (*this_id
) = this_trad_cache
->this_id
;
234 trad_frame_set_this_base (struct trad_frame_cache
*this_trad_cache
,
237 this_trad_cache
->this_base
= this_base
;
241 trad_frame_get_this_base (struct trad_frame_cache
*this_trad_cache
)
243 return this_trad_cache
->this_base
;