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