1 /* Traditional frame unwind support, for GDB the GNU Debugger.
3 Copyright (C) 2003-2021 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"
29 struct trad_frame_cache
31 struct frame_info
*this_frame
;
33 struct trad_frame_saved_reg
*prev_regs
;
34 struct frame_id this_id
;
37 struct trad_frame_cache
*
38 trad_frame_cache_zalloc (struct frame_info
*this_frame
)
40 struct trad_frame_cache
*this_trad_cache
;
42 this_trad_cache
= FRAME_OBSTACK_ZALLOC (struct trad_frame_cache
);
43 this_trad_cache
->prev_regs
= trad_frame_alloc_saved_regs (this_frame
);
44 this_trad_cache
->this_frame
= this_frame
;
45 return this_trad_cache
;
48 /* See trad-frame.h. */
51 trad_frame_reset_saved_regs (struct gdbarch
*gdbarch
,
52 struct trad_frame_saved_reg
*regs
)
54 int numregs
= gdbarch_num_cooked_regs (gdbarch
);
55 for (int regnum
= 0; regnum
< numregs
; regnum
++)
57 regs
[regnum
].realreg
= regnum
;
58 regs
[regnum
].addr
= -1;
59 regs
[regnum
].data
= nullptr;
63 struct trad_frame_saved_reg
*
64 trad_frame_alloc_saved_regs (struct gdbarch
*gdbarch
)
66 int numregs
= gdbarch_num_cooked_regs (gdbarch
);
67 struct trad_frame_saved_reg
*this_saved_regs
68 = FRAME_OBSTACK_CALLOC (numregs
, struct trad_frame_saved_reg
);
70 trad_frame_reset_saved_regs (gdbarch
, this_saved_regs
);
71 return this_saved_regs
;
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). */
79 struct trad_frame_saved_reg
*
80 trad_frame_alloc_saved_regs (struct frame_info
*this_frame
)
82 struct gdbarch
*gdbarch
= get_frame_arch (this_frame
);
84 return trad_frame_alloc_saved_regs (gdbarch
);
87 enum { TF_REG_VALUE
= -1, TF_REG_UNKNOWN
= -2, TF_REG_VALUE_BYTES
= -3 };
90 trad_frame_value_p (struct trad_frame_saved_reg this_saved_regs
[], int regnum
)
92 return (this_saved_regs
[regnum
].realreg
== TF_REG_VALUE
);
96 trad_frame_addr_p (struct trad_frame_saved_reg this_saved_regs
[], int regnum
)
98 return (this_saved_regs
[regnum
].realreg
>= 0
99 && this_saved_regs
[regnum
].addr
!= -1);
103 trad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs
[],
106 return (this_saved_regs
[regnum
].realreg
>= 0
107 && this_saved_regs
[regnum
].addr
== -1);
110 /* See trad-frame.h. */
113 trad_frame_value_bytes_p (struct trad_frame_saved_reg this_saved_regs
[],
116 return (this_saved_regs
[regnum
].realreg
== TF_REG_VALUE_BYTES
117 && this_saved_regs
[regnum
].data
!= nullptr);
121 trad_frame_set_value (struct trad_frame_saved_reg this_saved_regs
[],
122 int regnum
, LONGEST val
)
124 /* Make the REALREG invalid, indicating that the ADDR contains the
126 this_saved_regs
[regnum
].realreg
= TF_REG_VALUE
;
127 this_saved_regs
[regnum
].addr
= val
;
130 /* See trad-frame.h. */
133 trad_frame_set_realreg (struct trad_frame_saved_reg this_saved_regs
[],
134 int regnum
, int realreg
)
136 this_saved_regs
[regnum
].realreg
= realreg
;
137 this_saved_regs
[regnum
].addr
= -1;
140 /* See trad-frame.h. */
143 trad_frame_set_addr (struct trad_frame_saved_reg this_saved_regs
[],
144 int regnum
, CORE_ADDR addr
)
146 this_saved_regs
[regnum
].realreg
= regnum
;
147 this_saved_regs
[regnum
].addr
= addr
;
151 trad_frame_set_reg_value (struct trad_frame_cache
*this_trad_cache
,
152 int regnum
, LONGEST val
)
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
);
160 trad_frame_set_reg_realreg (struct trad_frame_cache
*this_trad_cache
,
161 int regnum
, int realreg
)
163 trad_frame_set_realreg (this_trad_cache
->prev_regs
, regnum
, realreg
);
167 trad_frame_set_reg_addr (struct trad_frame_cache
*this_trad_cache
,
168 int regnum
, CORE_ADDR addr
)
170 trad_frame_set_addr (this_trad_cache
->prev_regs
, regnum
, addr
);
174 trad_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
)
178 struct gdbarch
*gdbarch
= get_frame_arch (this_trad_cache
->this_frame
);
181 for (; (count
= regmap
->count
) != 0; regmap
++)
183 int regno
= regmap
->regno
;
184 int slot_size
= regmap
->size
;
186 if (slot_size
== 0 && regno
!= REGCACHE_MAP_SKIP
)
187 slot_size
= register_size (gdbarch
, regno
);
189 if (offs
+ slot_size
> size
)
192 if (regno
== REGCACHE_MAP_SKIP
)
193 offs
+= count
* slot_size
;
195 for (; count
--; regno
++, offs
+= slot_size
)
197 /* Mimic the semantics of regcache::transfer_regset if a
198 register slot's size does not match the size of a
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.
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
);
215 enum bfd_endian byte_order
= gdbarch_byte_order (gdbarch
);
216 gdb_byte buf
[slot_size
];
218 if (target_read_memory (addr
+ offs
, buf
, sizeof buf
) == 0)
221 = extract_unsigned_integer (buf
, sizeof buf
, byte_order
);
222 trad_frame_set_reg_value (this_trad_cache
, regno
, val
);
230 trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs
[],
233 /* Make the REALREG invalid, indicating that the value is not known. */
234 this_saved_regs
[regnum
].realreg
= TF_REG_UNKNOWN
;
235 this_saved_regs
[regnum
].addr
= -1;
238 /* See trad-frame.h. */
241 trad_frame_set_value_bytes (struct trad_frame_saved_reg this_saved_regs
[],
242 int regnum
, const gdb_byte
*bytes
,
245 this_saved_regs
[regnum
].realreg
= TF_REG_VALUE_BYTES
;
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
);
252 /* See trad-frame.h. */
255 trad_frame_set_reg_value_bytes (struct trad_frame_cache
*this_trad_cache
,
256 int regnum
, const gdb_byte
*bytes
,
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
,
268 trad_frame_get_prev_register (struct frame_info
*this_frame
,
269 struct trad_frame_saved_reg this_saved_regs
[],
272 if (trad_frame_addr_p (this_saved_regs
, regnum
))
273 /* The register was saved in memory. */
274 return frame_unwind_got_memory (this_frame
, regnum
,
275 this_saved_regs
[regnum
].addr
);
276 else if (trad_frame_realreg_p (this_saved_regs
, regnum
))
277 return frame_unwind_got_register (this_frame
, regnum
,
278 this_saved_regs
[regnum
].realreg
);
279 else if (trad_frame_value_p (this_saved_regs
, regnum
))
280 /* The register's value is available. */
281 return frame_unwind_got_constant (this_frame
, regnum
,
282 this_saved_regs
[regnum
].addr
);
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
);
288 return frame_unwind_got_optimized (this_frame
, regnum
);
292 trad_frame_get_register (struct trad_frame_cache
*this_trad_cache
,
293 struct frame_info
*this_frame
,
296 return trad_frame_get_prev_register (this_frame
, this_trad_cache
->prev_regs
,
301 trad_frame_set_id (struct trad_frame_cache
*this_trad_cache
,
302 struct frame_id this_id
)
304 this_trad_cache
->this_id
= this_id
;
308 trad_frame_get_id (struct trad_frame_cache
*this_trad_cache
,
309 struct frame_id
*this_id
)
311 (*this_id
) = this_trad_cache
->this_id
;
315 trad_frame_set_this_base (struct trad_frame_cache
*this_trad_cache
,
318 this_trad_cache
->this_base
= this_base
;
322 trad_frame_get_this_base (struct trad_frame_cache
*this_trad_cache
)
324 return this_trad_cache
->this_base
;