GDB (xrefs)
Loading...
Searching...
No Matches
dummy-frame.c
Go to the documentation of this file.
1/* Code dealing with dummy stack frames, for GDB, the GNU debugger.
2
3 Copyright (C) 1986-2023 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
21#include "defs.h"
22#include "dummy-frame.h"
23#include "regcache.h"
24#include "frame.h"
25#include "inferior.h"
26#include "frame-unwind.h"
27#include "command.h"
28#include "gdbcmd.h"
29#include "observable.h"
30#include "gdbthread.h"
31#include "infcall.h"
32#include "gdbarch.h"
33
35{
36 /* This frame's ID. Must match the value returned by
37 gdbarch_dummy_id. */
38 struct frame_id id;
39
40 /* The thread this dummy_frame relates to. */
42};
43
44/* Return whether dummy_frame_id *ID1 and *ID2 are equal. */
45
46static int
48 struct dummy_frame_id *id2)
49{
50 return id1->id == id2->id && id1->thread == id2->thread;
51}
52
53/* List of dummy_frame destructors. */
54
56{
57 /* Next element in the list or NULL if this is the last element. */
59
60 /* If non-NULL, a destructor that is run when this dummy frame is freed. */
62
63 /* Arbitrary data that is passed to DTOR. */
64 void *dtor_data;
65};
66
67/* Dummy frame. This saves the processor state just prior to setting
68 up the inferior function call. Older targets save the registers
69 on the target stack (but that really slows down function calls). */
70
72{
74
75 /* An id represents a dummy frame. */
77
78 /* The caller's state prior to the call. */
80
81 /* First element of destructors list or NULL if there are no
82 destructors registered for this dummy_frame. */
84};
85
86static struct dummy_frame *dummy_frame_stack = NULL;
87
88/* Push the caller's state, along with the dummy frame info, onto the
89 dummy-frame stack. */
90
91void
93 const frame_id *dummy_id, thread_info *thread)
94{
96
97 dummy_frame = XCNEW (struct dummy_frame);
99 dummy_frame->id.id = (*dummy_id);
100 dummy_frame->id.thread = thread;
103}
104
105/* Remove *DUMMY_PTR from the dummy frame stack. */
106
107static void
108remove_dummy_frame (struct dummy_frame **dummy_ptr)
109{
110 struct dummy_frame *dummy = *dummy_ptr;
111
112 while (dummy->dtor_list != NULL)
113 {
114 struct dummy_frame_dtor_list *list = dummy->dtor_list;
115
116 dummy->dtor_list = list->next;
117 list->dtor (list->dtor_data, 0);
118 xfree (list);
119 }
120
121 *dummy_ptr = dummy->next;
122 discard_infcall_suspend_state (dummy->caller_state);
123 xfree (dummy);
124}
125
126/* Delete any breakpoint B which is a momentary breakpoint for return from
127 inferior call matching DUMMY_VOIDP. */
128
129static bool
131{
132 if (b->thread == dummy->id.thread->global_num
133 && b->disposition == disp_del && b->frame_id == dummy->id.id)
134 {
135 while (b->related_breakpoint != b)
137
139
140 /* Stop the traversal. */
141 return true;
142 }
143
144 /* Continue the traversal. */
145 return false;
146}
147
148/* Pop *DUMMY_PTR, restoring program state to that before the
149 frame was created. */
150
151static void
152pop_dummy_frame (struct dummy_frame **dummy_ptr)
153{
154 struct dummy_frame *dummy = *dummy_ptr;
155
156 gdb_assert (dummy->id.thread == inferior_thread ());
157
158 while (dummy->dtor_list != NULL)
159 {
160 struct dummy_frame_dtor_list *list = dummy->dtor_list;
161
162 dummy->dtor_list = list->next;
163 list->dtor (list->dtor_data, 1);
164 xfree (list);
165 }
166
167 restore_infcall_suspend_state (dummy->caller_state);
168
171 break;
172
173 /* restore_infcall_control_state frees inf_state,
174 all that remains is to pop *dummy_ptr. */
175 *dummy_ptr = dummy->next;
176 xfree (dummy);
177
178 /* We've made right mess of GDB's local state, just discard
179 everything. */
181}
182
183/* Look up DUMMY_ID.
184 Return NULL if not found. */
185
186static struct dummy_frame **
188{
189 struct dummy_frame **dp;
190
191 for (dp = &dummy_frame_stack; *dp != NULL; dp = &(*dp)->next)
192 {
193 if (dummy_frame_id_eq (&(*dp)->id, dummy_id))
194 return dp;
195 }
196
197 return NULL;
198}
199
200/* Find the dummy frame by DUMMY_ID and THREAD, and pop it, restoring
201 program state to that before the frame was created.
202 On return reinit_frame_cache has been called.
203 If the frame isn't found, flag an internal error. */
204
205void
207{
208 struct dummy_frame **dp;
209 struct dummy_frame_id id = { dummy_id, thread };
210
211 dp = lookup_dummy_frame (&id);
212 gdb_assert (dp != NULL);
213
214 pop_dummy_frame (dp);
215}
216
217/* Find the dummy frame by DUMMY_ID and PTID and drop it. Do nothing
218 if it is not found. Do not restore its state into inferior, just
219 free its memory. */
220
221void
223{
224 struct dummy_frame **dp;
225 struct dummy_frame_id id = { dummy_id, thread };
226
227 dp = lookup_dummy_frame (&id);
228 if (dp)
230}
231
232/* See dummy-frame.h. */
233
234void
236 dummy_frame_dtor_ftype *dtor, void *dtor_data)
237{
238 struct dummy_frame_id id = { dummy_id, thread };
239 struct dummy_frame **dp, *d;
240 struct dummy_frame_dtor_list *list;
241
242 dp = lookup_dummy_frame (&id);
243 gdb_assert (dp != NULL);
244 d = *dp;
245 list = XNEW (struct dummy_frame_dtor_list);
246 list->next = d->dtor_list;
247 d->dtor_list = list;
248 list->dtor = dtor;
249 list->dtor_data = dtor_data;
250}
251
252/* See dummy-frame.h. */
253
254int
256{
257 struct dummy_frame *d;
258
259 for (d = dummy_frame_stack; d != NULL; d = d->next)
260 {
261 struct dummy_frame_dtor_list *list;
262
263 for (list = d->dtor_list; list != NULL; list = list->next)
264 if (list->dtor == dtor && list->dtor_data == dtor_data)
265 return 1;
266 }
267 return 0;
268}
269
270/* There may be stale dummy frames, perhaps left over from when an uncaught
271 longjmp took us out of a function that was called by the debugger. Clean
272 them up at least once whenever we start a new inferior. */
273
274static void
280
281/* Return the dummy frame cache, it contains both the ID, and a
282 pointer to the regcache. */
288
289static int
291 frame_info_ptr this_frame,
292 void **this_prologue_cache)
293{
294 /* When unwinding a normal frame, the stack structure is determined
295 by analyzing the frame's function's code (be it using brute force
296 prologue analysis, or the dwarf2 CFI). In the case of a dummy
297 frame, that simply isn't possible. The PC is either the program
298 entry point, or some random address on the stack. Trying to use
299 that PC to apply standard frame ID unwind techniques is just
300 asking for trouble. */
301
302 /* Don't bother unless there is at least one dummy frame. */
303 if (dummy_frame_stack != NULL)
304 {
305 struct dummy_frame *dummyframe;
306 /* Use an architecture specific method to extract this frame's
307 dummy ID, assuming it is a dummy frame. */
308 struct frame_id this_id
309 = gdbarch_dummy_id (get_frame_arch (this_frame), this_frame);
310 struct dummy_frame_id dummy_id = { this_id, inferior_thread () };
311
312 /* Use that ID to find the corresponding cache entry. */
313 for (dummyframe = dummy_frame_stack;
314 dummyframe != NULL;
315 dummyframe = dummyframe->next)
316 {
317 if (dummy_frame_id_eq (&dummyframe->id, &dummy_id))
318 {
319 struct dummy_frame_cache *cache;
320
323 (dummyframe->caller_state);
324 cache->this_id = this_id;
325 (*this_prologue_cache) = cache;
326 return 1;
327 }
328 }
329 }
330 return 0;
331}
332
333/* Given a call-dummy dummy-frame, return the registers. Here the
334 register value is taken from the local copy of the register buffer. */
335
336static struct value *
338 void **this_prologue_cache,
339 int regnum)
340{
341 struct dummy_frame_cache *cache
342 = (struct dummy_frame_cache *) *this_prologue_cache;
343 struct gdbarch *gdbarch = get_frame_arch (this_frame);
344 struct value *reg_val;
345
346 /* The dummy-frame sniffer always fills in the cache. */
347 gdb_assert (cache != NULL);
348
349 /* Describe the register's location. Generic dummy frames always
350 have the register value in an ``expression''. */
352
353 /* Use the regcache_cooked_read() method so that it, on the fly,
354 constructs either a raw or pseudo register from the raw
355 register cache. */
357 (regnum, reg_val->contents_writeable ().data ());
358 return reg_val;
359}
360
361/* Assuming that THIS_FRAME is a dummy, return its ID. That ID is
362 determined by examining the NEXT frame's unwound registers using
363 the method dummy_id(). As a side effect, THIS dummy frame's
364 dummy cache is located and saved in THIS_PROLOGUE_CACHE. */
365
366static void
368 void **this_prologue_cache,
369 struct frame_id *this_id)
370{
371 /* The dummy-frame sniffer always fills in the cache. */
372 struct dummy_frame_cache *cache
373 = (struct dummy_frame_cache *) *this_prologue_cache;
374
375 gdb_assert (cache != NULL);
376 (*this_id) = cache->this_id;
377}
378
389
390/* See dummy-frame.h. */
391
392struct frame_id
394{
395 CORE_ADDR sp, pc;
396
397 sp = get_frame_sp (this_frame);
398 pc = get_frame_pc (this_frame);
399 return frame_id_build (sp, pc);
400}
401
402static void
404{
405 struct dummy_frame *s;
406
407 for (s = dummy_frame_stack; s != NULL; s = s->next)
408 gdb_printf (file, "%s: id=%s, ptid=%s\n",
409 host_address_to_string (s),
410 s->id.id.to_string ().c_str (),
411 s->id.thread->ptid.to_string ().c_str ());
412}
413
414static void
415maintenance_print_dummy_frames (const char *args, int from_tty)
416{
417 if (args == NULL)
419 else
420 {
421 stdio_file file;
422
423 if (!file.open (args, "w"))
424 perror_with_name (_("maintenance print dummy-frames"));
425 fprint_dummy_frames (&file);
426 }
427}
428
430void
432{
434 _("Print the contents of the internal dummy-frame stack."),
436
438}
int regnum
void xfree(void *)
void delete_breakpoint(struct breakpoint *bpt)
breakpoint_safe_range all_breakpoints_safe()
Definition breakpoint.c:712
@ disp_del
Definition breakpoint.h:237
enum register_status cooked_read(int regnum, gdb_byte *buf)
Definition regcache.c:698
ptid_t ptid
Definition gdbthread.h:259
struct cmd_list_element * maintenanceprintlist
Definition cli-cmds.c:151
struct cmd_list_element * add_cmd(const char *name, enum command_class theclass, const char *doc, struct cmd_list_element **list)
Definition cli-decode.c:233
@ class_maintenance
Definition command.h:65
@ not_lval
Definition defs.h:361
void register_dummy_frame_dtor(frame_id dummy_id, thread_info *thread, dummy_frame_dtor_ftype *dtor, void *dtor_data)
static struct dummy_frame * dummy_frame_stack
Definition dummy-frame.c:86
int find_dummy_frame_dtor(dummy_frame_dtor_ftype *dtor, void *dtor_data)
static void fprint_dummy_frames(struct ui_file *file)
static bool pop_dummy_frame_bpt(struct breakpoint *b, struct dummy_frame *dummy)
static void maintenance_print_dummy_frames(const char *args, int from_tty)
static struct value * dummy_frame_prev_register(frame_info_ptr this_frame, void **this_prologue_cache, int regnum)
void dummy_frame_pop(frame_id dummy_id, thread_info *thread)
static int dummy_frame_sniffer(const struct frame_unwind *self, frame_info_ptr this_frame, void **this_prologue_cache)
void _initialize_dummy_frame()
static struct dummy_frame ** lookup_dummy_frame(struct dummy_frame_id *dummy_id)
static void remove_dummy_frame(struct dummy_frame **dummy_ptr)
void dummy_frame_push(struct infcall_suspend_state *caller_state, const frame_id *dummy_id, thread_info *thread)
Definition dummy-frame.c:92
static int dummy_frame_id_eq(struct dummy_frame_id *id1, struct dummy_frame_id *id2)
Definition dummy-frame.c:47
static void cleanup_dummy_frames(inferior *inf)
void dummy_frame_discard(struct frame_id dummy_id, thread_info *thread)
static void dummy_frame_this_id(frame_info_ptr this_frame, void **this_prologue_cache, struct frame_id *this_id)
const struct frame_unwind dummy_frame_unwind
struct frame_id default_dummy_id(struct gdbarch *gdbarch, frame_info_ptr this_frame)
static void pop_dummy_frame(struct dummy_frame **dummy_ptr)
void dummy_frame_dtor_ftype(void *data, int registers_valid)
Definition dummy-frame.h:61
enum unwind_stop_reason default_frame_unwind_stop_reason(frame_info_ptr this_frame, void **this_cache)
CORE_ADDR get_frame_pc(frame_info_ptr frame)
Definition frame.c:2712
CORE_ADDR get_frame_sp(frame_info_ptr this_frame)
Definition frame.c:3115
void reinit_frame_cache(void)
Definition frame.c:2107
struct frame_id frame_id_build(CORE_ADDR stack_addr, CORE_ADDR code_addr)
Definition frame.c:736
struct gdbarch * get_frame_arch(frame_info_ptr this_frame)
Definition frame.c:3027
@ DUMMY_FRAME
Definition frame.h:190
#define FRAME_OBSTACK_ZALLOC(TYPE)
Definition frame.h:825
struct frame_id gdbarch_dummy_id(struct gdbarch *gdbarch, frame_info_ptr this_frame)
Definition gdbarch.c:2211
struct thread_info * inferior_thread(void)
Definition thread.c:85
unsigned dummy
Definition go32-nat.c:8
void discard_infcall_suspend_state(struct infcall_suspend_state *)
Definition infrun.c:9641
void restore_infcall_suspend_state(struct infcall_suspend_state *)
Definition infrun.c:9630
readonly_detached_regcache * get_infcall_suspend_state_regcache(struct infcall_suspend_state *)
Definition infrun.c:9647
observable< inferior * > inferior_created
struct type * register_type(struct gdbarch *gdbarch, int regnum)
Definition regcache.c:158
breakpoint * related_breakpoint
Definition breakpoint.h:860
bpdisp disposition
Definition breakpoint.h:802
struct frame_id frame_id
Definition breakpoint.h:824
readonly_detached_regcache * prev_regcache
struct frame_id this_id
dummy_frame_dtor_ftype * dtor
Definition dummy-frame.c:61
struct dummy_frame_dtor_list * next
Definition dummy-frame.c:58
struct frame_id id
Definition dummy-frame.c:38
thread_info * thread
Definition dummy-frame.c:41
struct infcall_suspend_state * caller_state
Definition dummy-frame.c:79
struct dummy_frame_dtor_list * dtor_list
Definition dummy-frame.c:83
struct dummy_frame * next
Definition dummy-frame.c:73
struct dummy_frame_id id
Definition dummy-frame.c:76
std::string to_string() const
Definition frame.c:407
Definition gnu-nat.c:153
Definition value.h:130
static struct value * zero(struct type *type, enum lval_type lv)
Definition value.c:3426
gdb::array_view< gdb_byte > contents_writeable()
Definition value.c:1271
void gdb_printf(struct ui_file *stream, const char *format,...)
Definition utils.c:1886
#define gdb_stdout
Definition utils.h:182