Make "thread apply" use the gdb::option framework
[deliverable/binutils-gdb.git] / gdb / trad-frame.c
CommitLineData
a0f267c7
AC
1/* Traditional frame unwind support, for GDB the GNU Debugger.
2
42a4f53d 3 Copyright (C) 2003-2019 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"
a0f267c7 27
0db9b4b7
AC
28struct trad_frame_cache
29{
25492ce3 30 struct frame_info *this_frame;
0db9b4b7
AC
31 CORE_ADDR this_base;
32 struct trad_frame_saved_reg *prev_regs;
33 struct frame_id this_id;
34};
35
36struct trad_frame_cache *
25492ce3 37trad_frame_cache_zalloc (struct frame_info *this_frame)
0db9b4b7
AC
38{
39 struct trad_frame_cache *this_trad_cache;
40
41 this_trad_cache = FRAME_OBSTACK_ZALLOC (struct trad_frame_cache);
25492ce3
DJ
42 this_trad_cache->prev_regs = trad_frame_alloc_saved_regs (this_frame);
43 this_trad_cache->this_frame = this_frame;
0db9b4b7
AC
44 return this_trad_cache;
45}
46
68811f8f
AH
47/* See trad-frame.h. */
48
49void
50trad_frame_reset_saved_regs (struct gdbarch *gdbarch,
51 struct trad_frame_saved_reg *regs)
52{
53 int numregs = gdbarch_num_cooked_regs (gdbarch);
54 for (int regnum = 0; regnum < numregs; regnum++)
55 {
56 regs[regnum].realreg = regnum;
57 regs[regnum].addr = -1;
58 }
59}
60
8983bd83 61struct trad_frame_saved_reg *
4d9a9006 62trad_frame_alloc_saved_regs (struct gdbarch *gdbarch)
a0f267c7 63{
f6efe3f8 64 int numregs = gdbarch_num_cooked_regs (gdbarch);
8983bd83
AC
65 struct trad_frame_saved_reg *this_saved_regs
66 = FRAME_OBSTACK_CALLOC (numregs, struct trad_frame_saved_reg);
5d502164 67
68811f8f 68 trad_frame_reset_saved_regs (gdbarch, this_saved_regs);
a0f267c7
AC
69 return this_saved_regs;
70}
71
4d9a9006
YQ
72/* A traditional frame is unwound by analysing the function prologue
73 and using the information gathered to track registers. For
74 non-optimized frames, the technique is reliable (just need to check
75 for all potential instruction sequences). */
76
77struct trad_frame_saved_reg *
78trad_frame_alloc_saved_regs (struct frame_info *this_frame)
79{
80 struct gdbarch *gdbarch = get_frame_arch (this_frame);
81
82 return trad_frame_alloc_saved_regs (gdbarch);
83}
84
ee99023e 85enum { TF_REG_VALUE = -1, TF_REG_UNKNOWN = -2 };
3b3850e8
AC
86
87int
88trad_frame_value_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
89{
ee99023e 90 return (this_saved_regs[regnum].realreg == TF_REG_VALUE);
3b3850e8
AC
91}
92
93int
94trad_frame_addr_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
95{
96 return (this_saved_regs[regnum].realreg >= 0
97 && this_saved_regs[regnum].addr != -1);
98}
99
100int
101trad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs[],
102 int regnum)
103{
104 return (this_saved_regs[regnum].realreg >= 0
105 && this_saved_regs[regnum].addr == -1);
106}
107
a0f267c7 108void
3b3850e8
AC
109trad_frame_set_value (struct trad_frame_saved_reg this_saved_regs[],
110 int regnum, LONGEST val)
a0f267c7 111{
3b3850e8 112 /* Make the REALREG invalid, indicating that the ADDR contains the
a0f267c7 113 register's value. */
ee99023e 114 this_saved_regs[regnum].realreg = TF_REG_VALUE;
a0f267c7
AC
115 this_saved_regs[regnum].addr = val;
116}
117
23e60e7a
AB
118/* See trad-frame.h. */
119
120void
121trad_frame_set_realreg (struct trad_frame_saved_reg this_saved_regs[],
122 int regnum, int realreg)
123{
124 this_saved_regs[regnum].realreg = realreg;
125 this_saved_regs[regnum].addr = -1;
126}
127
128/* See trad-frame.h. */
129
130void
131trad_frame_set_addr (struct trad_frame_saved_reg this_saved_regs[],
132 int regnum, CORE_ADDR addr)
133{
134 this_saved_regs[regnum].realreg = regnum;
135 this_saved_regs[regnum].addr = addr;
136}
137
61e784e7
MS
138void
139trad_frame_set_reg_value (struct trad_frame_cache *this_trad_cache,
140 int regnum, LONGEST val)
141{
142 /* External interface for users of trad_frame_cache
143 (who cannot access the prev_regs object directly). */
144 trad_frame_set_value (this_trad_cache->prev_regs, regnum, val);
145}
146
e66299b3
AC
147void
148trad_frame_set_reg_realreg (struct trad_frame_cache *this_trad_cache,
149 int regnum, int realreg)
150{
23e60e7a 151 trad_frame_set_realreg (this_trad_cache->prev_regs, regnum, realreg);
e66299b3
AC
152}
153
0db9b4b7
AC
154void
155trad_frame_set_reg_addr (struct trad_frame_cache *this_trad_cache,
156 int regnum, CORE_ADDR addr)
157{
23e60e7a 158 trad_frame_set_addr (this_trad_cache->prev_regs, regnum, addr);
0db9b4b7
AC
159}
160
498f7407
JB
161void
162trad_frame_set_reg_regmap (struct trad_frame_cache *this_trad_cache,
163 const struct regcache_map_entry *regmap,
164 CORE_ADDR addr, size_t size)
165{
166 struct gdbarch *gdbarch = get_frame_arch (this_trad_cache->this_frame);
167 int offs = 0, count;
168
169 for (; (count = regmap->count) != 0; regmap++)
170 {
171 int regno = regmap->regno;
172 int slot_size = regmap->size;
173
174 if (slot_size == 0 && regno != REGCACHE_MAP_SKIP)
175 slot_size = register_size (gdbarch, regno);
176
177 if (offs + slot_size > size)
178 break;
179
180 if (regno == REGCACHE_MAP_SKIP)
181 offs += count * slot_size;
182 else
183 for (; count--; regno++, offs += slot_size)
184 {
185 /* Mimic the semantics of regcache::transfer_regset if a
186 register slot's size does not match the size of a
187 register.
188
189 If a register slot is larger than a register, assume
190 the register's value is stored in the first N bytes of
191 the slot and ignore the remaining bytes.
192
193 If the register slot is smaller than the register,
194 assume that the slot contains the low N bytes of the
195 register's value. Since trad_frame assumes that
196 registers stored by address are sized according to the
197 register, read the low N bytes and zero-extend them to
198 generate a register value. */
199 if (slot_size >= register_size (gdbarch, regno))
200 trad_frame_set_reg_addr (this_trad_cache, regno, addr + offs);
201 else
202 {
203 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
204 gdb_byte buf[slot_size];
205
206 if (target_read_memory (addr + offs, buf, sizeof buf) == 0)
207 {
208 LONGEST val
209 = extract_unsigned_integer (buf, sizeof buf, byte_order);
210 trad_frame_set_reg_value (this_trad_cache, regno, val);
211 }
212 }
213 }
214 }
215}
216
3b3850e8
AC
217void
218trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[],
219 int regnum)
220{
221 /* Make the REALREG invalid, indicating that the value is not known. */
ee99023e 222 this_saved_regs[regnum].realreg = TF_REG_UNKNOWN;
3b3850e8
AC
223 this_saved_regs[regnum].addr = -1;
224}
225
25492ce3
DJ
226struct value *
227trad_frame_get_prev_register (struct frame_info *this_frame,
1f67027d 228 struct trad_frame_saved_reg this_saved_regs[],
25492ce3 229 int regnum)
a0f267c7 230{
3b3850e8 231 if (trad_frame_addr_p (this_saved_regs, regnum))
25492ce3
DJ
232 /* The register was saved in memory. */
233 return frame_unwind_got_memory (this_frame, regnum,
234 this_saved_regs[regnum].addr);
3b3850e8 235 else if (trad_frame_realreg_p (this_saved_regs, regnum))
25492ce3
DJ
236 return frame_unwind_got_register (this_frame, regnum,
237 this_saved_regs[regnum].realreg);
3b3850e8 238 else if (trad_frame_value_p (this_saved_regs, regnum))
25492ce3
DJ
239 /* The register's value is available. */
240 return frame_unwind_got_constant (this_frame, regnum,
241 this_saved_regs[regnum].addr);
3b3850e8 242 else
25492ce3 243 return frame_unwind_got_optimized (this_frame, regnum);
a0f267c7 244}
0db9b4b7 245
25492ce3 246struct value *
0db9b4b7 247trad_frame_get_register (struct trad_frame_cache *this_trad_cache,
25492ce3
DJ
248 struct frame_info *this_frame,
249 int regnum)
250{
251 return trad_frame_get_prev_register (this_frame, this_trad_cache->prev_regs,
252 regnum);
0db9b4b7
AC
253}
254
255void
256trad_frame_set_id (struct trad_frame_cache *this_trad_cache,
257 struct frame_id this_id)
258{
259 this_trad_cache->this_id = this_id;
260}
261
262void
263trad_frame_get_id (struct trad_frame_cache *this_trad_cache,
264 struct frame_id *this_id)
265{
266 (*this_id) = this_trad_cache->this_id;
267}
e66299b3
AC
268
269void
270trad_frame_set_this_base (struct trad_frame_cache *this_trad_cache,
271 CORE_ADDR this_base)
272{
273 this_trad_cache->this_base = this_base;
274}
275
276CORE_ADDR
277trad_frame_get_this_base (struct trad_frame_cache *this_trad_cache)
278{
279 return this_trad_cache->this_base;
280}
This page took 1.716685 seconds and 4 git commands to generate.