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