]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/tramp-frame.c
libsframe: bump version to 2.0
[thirdparty/binutils-gdb.git] / gdb / tramp-frame.c
CommitLineData
d2259dd3
AC
1/* Signal trampoline unwinder, for GDB the GNU Debugger.
2
d01e8234 3 Copyright (C) 2004-2025 Free Software Foundation, Inc.
d2259dd3
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
d2259dd3
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/>. */
d2259dd3 19
d2259dd3 20#include "tramp-frame.h"
ec452525 21#include "extract-store-integer.h"
d2259dd3
AC
22#include "frame-unwind.h"
23#include "gdbcore.h"
24#include "symtab.h"
25#include "objfiles.h"
26#include "target.h"
27#include "trad-frame.h"
28#include "frame-base.h"
29
30struct frame_data
31{
32 const struct tramp_frame *tramp_frame;
33};
34
35struct tramp_frame_cache
36{
37 CORE_ADDR func;
38 const struct tramp_frame *tramp_frame;
39 struct trad_frame_cache *trad_cache;
40};
41
42static struct trad_frame_cache *
8480a37e 43tramp_frame_cache (const frame_info_ptr &this_frame,
d2259dd3
AC
44 void **this_cache)
45{
19ba03f4
SM
46 struct tramp_frame_cache *tramp_cache
47 = (struct tramp_frame_cache *) *this_cache;
5d502164 48
d2259dd3
AC
49 if (tramp_cache->trad_cache == NULL)
50 {
25492ce3 51 tramp_cache->trad_cache = trad_frame_cache_zalloc (this_frame);
d2259dd3 52 tramp_cache->tramp_frame->init (tramp_cache->tramp_frame,
25492ce3 53 this_frame,
d2259dd3
AC
54 tramp_cache->trad_cache,
55 tramp_cache->func);
56 }
57 return tramp_cache->trad_cache;
58}
59
1239e7cf
GL
60class frame_unwind_trampoline : public frame_unwind
61{
62public:
63 frame_unwind_trampoline (enum frame_type type, const struct frame_data *data,
64 frame_prev_arch_ftype *prev_arch_func)
65 : frame_unwind ("trampoline", type, FRAME_UNWIND_GDB, data),
66 m_prev_arch (prev_arch_func)
67 { }
68
69 int sniff (const frame_info_ptr &this_frame,
70 void **this_prologue_cache) const override;
71
72 void this_id (const frame_info_ptr &this_frame, void **this_prologue_cache,
73 struct frame_id *id) const override;
74
75 value *prev_register (const frame_info_ptr &this_frame,
76 void **this_prologue_cache,
77 int regnum) const override;
78
79 struct gdbarch *prev_arch (const frame_info_ptr &this_frame,
80 void **this_prologue_cache) const override
81 {
82 if (m_prev_arch == nullptr)
83 return frame_unwind::prev_arch (this_frame, this_prologue_cache);
84 return m_prev_arch (this_frame, this_prologue_cache);
85 }
86
87private:
88 frame_prev_arch_ftype *m_prev_arch;
89};
90
91void
92frame_unwind_trampoline::this_id (const frame_info_ptr &this_frame,
93 void **this_cache,
94 struct frame_id *this_id) const
d2259dd3
AC
95{
96 struct trad_frame_cache *trad_cache
25492ce3 97 = tramp_frame_cache (this_frame, this_cache);
5d502164 98
d2259dd3
AC
99 trad_frame_get_id (trad_cache, this_id);
100}
101
1239e7cf
GL
102struct value *
103frame_unwind_trampoline::prev_register (const frame_info_ptr &this_frame,
104 void **this_cache,
105 int prev_regnum) const
d2259dd3
AC
106{
107 struct trad_frame_cache *trad_cache
25492ce3 108 = tramp_frame_cache (this_frame, this_cache);
5d502164 109
25492ce3 110 return trad_frame_get_register (trad_cache, this_frame, prev_regnum);
d2259dd3
AC
111}
112
113static CORE_ADDR
304396fb 114tramp_frame_start (const struct tramp_frame *tramp,
8480a37e 115 const frame_info_ptr &this_frame, CORE_ADDR pc)
d2259dd3 116{
e17a4113
UW
117 struct gdbarch *gdbarch = get_frame_arch (this_frame);
118 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
d2259dd3 119 int ti;
5d502164 120
858339f2
MR
121 /* Check if we can use this trampoline. */
122 if (tramp->validate && !tramp->validate (tramp, this_frame, &pc))
123 return 0;
124
d2259dd3
AC
125 /* Search through the trampoline for one that matches the
126 instruction sequence around PC. */
2cd8546d 127 for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)
d2259dd3
AC
128 {
129 CORE_ADDR func = pc - tramp->insn_size * ti;
130 int i;
5d502164 131
d2259dd3
AC
132 for (i = 0; 1; i++)
133 {
fc1a4b47 134 gdb_byte buf[sizeof (tramp->insn[0])];
1196bfda 135 ULONGEST insn;
bdec2917 136 size_t insn_size = tramp->insn_size;
5d502164 137
2cd8546d 138 if (tramp->insn[i].bytes == TRAMP_SENTINEL_INSN)
d2259dd3 139 return func;
25492ce3 140 if (!safe_frame_unwind_memory (this_frame,
bdec2917
LM
141 func + i * insn_size,
142 {buf, insn_size}))
d2259dd3 143 break;
bdec2917 144 insn = extract_unsigned_integer (buf, insn_size, byte_order);
2cd8546d 145 if (tramp->insn[i].bytes != (insn & tramp->insn[i].mask))
d2259dd3
AC
146 break;
147 }
148 }
149 /* Trampoline doesn't match. */
150 return 0;
151}
152
1239e7cf
GL
153int
154frame_unwind_trampoline::sniff (const frame_info_ptr &this_frame,
155 void **this_cache) const
d2259dd3 156{
1239e7cf 157 const struct tramp_frame *tramp = unwind_data ()->tramp_frame;
25492ce3 158 CORE_ADDR pc = get_frame_pc (this_frame);
d2259dd3 159 CORE_ADDR func;
d2259dd3
AC
160 struct tramp_frame_cache *tramp_cache;
161
0efcf9dc
RC
162 /* tausq/2004-12-12: We used to assume if pc has a name or is in a valid
163 section, then this is not a trampoline. However, this assumption is
164 false on HPUX which has a signal trampoline that has a name; it can
165 also be false when using an alternative signal stack. */
25492ce3 166 func = tramp_frame_start (tramp, this_frame, pc);
d2259dd3
AC
167 if (func == 0)
168 return 0;
169 tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache);
170 tramp_cache->func = func;
171 tramp_cache->tramp_frame = tramp;
172 (*this_cache) = tramp_cache;
173 return 1;
174}
175
176void
fb2be677
AC
177tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
178 const struct tramp_frame *tramp_frame)
d2259dd3
AC
179{
180 struct frame_data *data;
181 struct frame_unwind *unwinder;
1196bfda
AC
182 int i;
183
184 /* Check that the instruction sequence contains a sentinel. */
185 for (i = 0; i < ARRAY_SIZE (tramp_frame->insn); i++)
186 {
2cd8546d 187 if (tramp_frame->insn[i].bytes == TRAMP_SENTINEL_INSN)
1196bfda
AC
188 break;
189 }
190 gdb_assert (i < ARRAY_SIZE (tramp_frame->insn));
2cd8546d 191 gdb_assert (tramp_frame->insn_size <= sizeof (tramp_frame->insn[0].bytes));
d2259dd3
AC
192
193 data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data);
d2259dd3 194 data->tramp_frame = tramp_frame;
1239e7cf
GL
195
196 unwinder = obstack_new <frame_unwind_trampoline> (gdbarch_obstack (gdbarch),
197 tramp_frame->frame_type,
198 data,
199 tramp_frame->prev_arch);
fb2be677 200 frame_unwind_prepend_unwinder (gdbarch, unwinder);
d2259dd3 201}