]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/guile/scm-frame.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / guile / scm-frame.c
CommitLineData
ed3ef339
DE
1/* Scheme interface to stack frames.
2
213516ef 3 Copyright (C) 2008-2023 Free Software Foundation, Inc.
ed3ef339
DE
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/* See README file in this directory for implementation notes, coding
21 conventions, et.al. */
22
23#include "defs.h"
24#include "block.h"
25#include "frame.h"
ed3ef339
DE
26#include "inferior.h"
27#include "objfiles.h"
28#include "symfile.h"
29#include "symtab.h"
30#include "stack.h"
f2983cc3 31#include "user-regs.h"
ed3ef339
DE
32#include "value.h"
33#include "guile-internal.h"
34
f99b5177 35/* The <gdb:frame> smob. */
ed3ef339 36
f99b5177 37struct frame_smob
ed3ef339
DE
38{
39 /* This always appears first. */
40 eqable_gdb_smob base;
41
42 struct frame_id frame_id;
43 struct gdbarch *gdbarch;
44
45 /* Frames are tracked by inferior.
46 We need some place to put the eq?-able hash table, and this feels as
47 good a place as any. Frames in one inferior shouldn't be considered
48 equal to frames in a different inferior. The frame becomes invalid if
49 this becomes NULL (the inferior has been deleted from gdb).
50 It's easier to relax restrictions than impose them after the fact.
51 N.B. It is an outstanding question whether a frame survives reruns of
52 the inferior. Intuitively the answer is "No", but currently a frame
53 also survives, e.g., multiple invocations of the same function from
54 the same point. Even different threads can have the same frame, e.g.,
55 if a thread dies and a new thread gets the same stack. */
56 struct inferior *inferior;
57
58 /* Marks that the FRAME_ID member actually holds the ID of the frame next
59 to this, and not this frame's ID itself. This is a hack to permit Scheme
60 frame objects which represent invalid frames (i.e., the last frame_info
61 in a corrupt stack). The problem arises from the fact that this code
62 relies on FRAME_ID to uniquely identify a frame, which is not always true
63 for the last "frame" in a corrupt stack (it can have a null ID, or the
64 same ID as the previous frame). Whenever get_prev_frame returns NULL, we
65 record the frame_id of the next frame and set FRAME_ID_IS_NEXT to 1. */
66 int frame_id_is_next;
67};
68
69static const char frame_smob_name[] = "gdb:frame";
70
71/* The tag Guile knows the frame smob by. */
72static scm_t_bits frame_smob_tag;
73
74/* Keywords used in argument passing. */
75static SCM block_keyword;
76
08b8a139
TT
77/* This is called when an inferior is about to be freed.
78 Invalidate the frame as further actions on the frame could result
79 in bad data. All access to the frame should be gated by
80 frscm_get_frame_smob_arg_unsafe which will raise an exception on
81 invalid frames. */
82struct frscm_deleter
83{
84 /* Helper function for frscm_del_inferior_frames to mark the frame
85 as invalid. */
86
87 static int
88 frscm_mark_frame_invalid (void **slot, void *info)
89 {
90 frame_smob *f_smob = (frame_smob *) *slot;
91
92 f_smob->inferior = NULL;
93 return 1;
94 }
95
96 void operator() (htab_t htab)
97 {
43cffa64
TT
98 gdb_assert (htab != nullptr);
99 htab_traverse_noresize (htab, frscm_mark_frame_invalid, NULL);
100 htab_delete (htab);
08b8a139
TT
101 }
102};
103
104static const registry<inferior>::key<htab, frscm_deleter>
105 frscm_inferior_data_key;
ed3ef339
DE
106\f
107/* Administrivia for frame smobs. */
108
109/* Helper function to hash a frame_smob. */
110
111static hashval_t
112frscm_hash_frame_smob (const void *p)
113{
9a3c8263 114 const frame_smob *f_smob = (const frame_smob *) p;
ed3ef339
DE
115 const struct frame_id *fid = &f_smob->frame_id;
116 hashval_t hash = htab_hash_pointer (f_smob->inferior);
117
118 if (fid->stack_status == FID_STACK_VALID)
119 hash = iterative_hash (&fid->stack_addr, sizeof (fid->stack_addr), hash);
120 if (fid->code_addr_p)
121 hash = iterative_hash (&fid->code_addr, sizeof (fid->code_addr), hash);
122 if (fid->special_addr_p)
123 hash = iterative_hash (&fid->special_addr, sizeof (fid->special_addr),
124 hash);
125
126 return hash;
127}
128
129/* Helper function to compute equality of frame_smobs. */
130
131static int
132frscm_eq_frame_smob (const void *ap, const void *bp)
133{
9a3c8263
SM
134 const frame_smob *a = (const frame_smob *) ap;
135 const frame_smob *b = (const frame_smob *) bp;
ed3ef339 136
79aafec9 137 return (a->frame_id == b->frame_id
ed3ef339
DE
138 && a->inferior == b->inferior
139 && a->inferior != NULL);
140}
141
142/* Return the frame -> SCM mapping table.
143 It is created if necessary. */
144
145static htab_t
146frscm_inferior_frame_map (struct inferior *inferior)
147{
08b8a139 148 htab_t htab = frscm_inferior_data_key.get (inferior);
ed3ef339
DE
149
150 if (htab == NULL)
151 {
152 htab = gdbscm_create_eqable_gsmob_ptr_map (frscm_hash_frame_smob,
153 frscm_eq_frame_smob);
08b8a139 154 frscm_inferior_data_key.set (inferior, htab);
ed3ef339
DE
155 }
156
157 return htab;
158}
159
ed3ef339
DE
160/* The smob "free" function for <gdb:frame>. */
161
162static size_t
163frscm_free_frame_smob (SCM self)
164{
165 frame_smob *f_smob = (frame_smob *) SCM_SMOB_DATA (self);
166
167 if (f_smob->inferior != NULL)
168 {
169 htab_t htab = frscm_inferior_frame_map (f_smob->inferior);
170
171 gdbscm_clear_eqable_gsmob_ptr_slot (htab, &f_smob->base);
172 }
173
174 /* Not necessary, done to catch bugs. */
175 f_smob->inferior = NULL;
176
177 return 0;
178}
179
180/* The smob "print" function for <gdb:frame>. */
181
182static int
183frscm_print_frame_smob (SCM self, SCM port, scm_print_state *pstate)
184{
185 frame_smob *f_smob = (frame_smob *) SCM_SMOB_DATA (self);
ed3ef339 186
927c4e35
AB
187 gdbscm_printf (port, "#<%s %s>",
188 frame_smob_name,
189 f_smob->frame_id.to_string ().c_str ());
ed3ef339
DE
190 scm_remember_upto_here_1 (self);
191
192 /* Non-zero means success. */
193 return 1;
194}
195
196/* Low level routine to create a <gdb:frame> object. */
197
198static SCM
199frscm_make_frame_smob (void)
200{
201 frame_smob *f_smob = (frame_smob *)
202 scm_gc_malloc (sizeof (frame_smob), frame_smob_name);
203 SCM f_scm;
204
205 f_smob->frame_id = null_frame_id;
206 f_smob->gdbarch = NULL;
207 f_smob->inferior = NULL;
208 f_smob->frame_id_is_next = 0;
209 f_scm = scm_new_smob (frame_smob_tag, (scm_t_bits) f_smob);
1254eefc 210 gdbscm_init_eqable_gsmob (&f_smob->base, f_scm);
ed3ef339
DE
211
212 return f_scm;
213}
214
215/* Return non-zero if SCM is a <gdb:frame> object. */
216
217int
218frscm_is_frame (SCM scm)
219{
220 return SCM_SMOB_PREDICATE (frame_smob_tag, scm);
221}
222
223/* (frame? object) -> boolean */
224
225static SCM
226gdbscm_frame_p (SCM scm)
227{
228 return scm_from_bool (frscm_is_frame (scm));
229}
230
231/* Create a new <gdb:frame> object that encapsulates FRAME.
232 Returns a <gdb:exception> object if there is an error. */
233
234static SCM
235frscm_scm_from_frame (struct frame_info *frame, struct inferior *inferior)
236{
237 frame_smob *f_smob, f_smob_for_lookup;
238 SCM f_scm;
239 htab_t htab;
240 eqable_gdb_smob **slot;
ed3ef339
DE
241 struct frame_id frame_id = null_frame_id;
242 struct gdbarch *gdbarch = NULL;
243 int frame_id_is_next = 0;
244
245 /* If we've already created a gsmob for this frame, return it.
246 This makes frames eq?-able. */
247 htab = frscm_inferior_frame_map (inferior);
79aafec9 248 f_smob_for_lookup.frame_id = get_frame_id (frame_info_ptr (frame));
ed3ef339
DE
249 f_smob_for_lookup.inferior = inferior;
250 slot = gdbscm_find_eqable_gsmob_ptr_slot (htab, &f_smob_for_lookup.base);
251 if (*slot != NULL)
252 return (*slot)->containing_scm;
253
a70b8144 254 try
ed3ef339 255 {
79aafec9
TT
256 frame_info_ptr frame_ptr (frame);
257
ed3ef339
DE
258 /* Try to get the previous frame, to determine if this is the last frame
259 in a corrupt stack. If so, we need to store the frame_id of the next
260 frame and not of this one (which is possibly invalid). */
79aafec9
TT
261 if (get_prev_frame (frame_ptr) == NULL
262 && get_frame_unwind_stop_reason (frame_ptr) != UNWIND_NO_REASON
263 && get_next_frame (frame_ptr) != NULL)
ed3ef339 264 {
79aafec9 265 frame_id = get_frame_id (get_next_frame (frame_ptr));
ed3ef339
DE
266 frame_id_is_next = 1;
267 }
268 else
269 {
79aafec9 270 frame_id = get_frame_id (frame_ptr);
ed3ef339
DE
271 frame_id_is_next = 0;
272 }
79aafec9 273 gdbarch = get_frame_arch (frame_ptr);
ed3ef339 274 }
230d2906 275 catch (const gdb_exception &except)
492d29ea 276 {
680d7fd5 277 return gdbscm_scm_from_gdb_exception (unpack (except));
492d29ea 278 }
ed3ef339
DE
279
280 f_scm = frscm_make_frame_smob ();
281 f_smob = (frame_smob *) SCM_SMOB_DATA (f_scm);
282 f_smob->frame_id = frame_id;
283 f_smob->gdbarch = gdbarch;
284 f_smob->inferior = inferior;
285 f_smob->frame_id_is_next = frame_id_is_next;
286
1254eefc 287 gdbscm_fill_eqable_gsmob_ptr_slot (slot, &f_smob->base);
ed3ef339
DE
288
289 return f_scm;
290}
291
292/* Create a new <gdb:frame> object that encapsulates FRAME.
293 A Scheme exception is thrown if there is an error. */
294
295static SCM
296frscm_scm_from_frame_unsafe (struct frame_info *frame,
297 struct inferior *inferior)
298{
299 SCM f_scm = frscm_scm_from_frame (frame, inferior);
300
301 if (gdbscm_is_exception (f_scm))
302 gdbscm_throw (f_scm);
303
304 return f_scm;
305}
306
307/* Returns the <gdb:frame> object in SELF.
308 Throws an exception if SELF is not a <gdb:frame> object. */
309
310static SCM
311frscm_get_frame_arg_unsafe (SCM self, int arg_pos, const char *func_name)
312{
313 SCM_ASSERT_TYPE (frscm_is_frame (self), self, arg_pos, func_name,
314 frame_smob_name);
315
316 return self;
317}
318
319/* There is no gdbscm_scm_to_frame function because translating
320 a frame SCM object to a struct frame_info * can throw a GDB error.
321 Thus code working with frames has to handle both Scheme errors (e.g., the
322 object is not a frame) and GDB errors (e.g., the frame lookup failed).
323
e9fbd043
DE
324 To help keep things clear we split what would be gdbscm_scm_to_frame
325 into two:
ed3ef339 326
e9fbd043 327 frscm_get_frame_smob_arg_unsafe
ed3ef339
DE
328 - throws a Scheme error if object is not a frame,
329 or if the inferior is gone or is no longer current
330
e9fbd043 331 frscm_frame_smob_to_frame
ed3ef339
DE
332 - may throw a gdb error if the conversion fails
333 - it's not clear when it will and won't throw a GDB error,
334 but for robustness' sake we assume that whenever we call out to GDB
335 a GDB error may get thrown (and thus the call must be wrapped in a
336 TRY_CATCH) */
337
338/* Returns the frame_smob for the object wrapped by FRAME_SCM.
339 A Scheme error is thrown if FRAME_SCM is not a frame. */
340
341frame_smob *
342frscm_get_frame_smob_arg_unsafe (SCM self, int arg_pos, const char *func_name)
343{
344 SCM f_scm = frscm_get_frame_arg_unsafe (self, arg_pos, func_name);
345 frame_smob *f_smob = (frame_smob *) SCM_SMOB_DATA (f_scm);
346
347 if (f_smob->inferior == NULL)
348 {
349 gdbscm_invalid_object_error (func_name, arg_pos, self,
350 _("inferior"));
351 }
352 if (f_smob->inferior != current_inferior ())
353 scm_misc_error (func_name, _("inferior has changed"), SCM_EOL);
354
355 return f_smob;
356}
357
358/* Returns the frame_info object wrapped by F_SMOB.
359 If the frame doesn't exist anymore (the frame id doesn't
360 correspond to any frame in the inferior), returns NULL.
361 This function calls GDB routines, so don't assume a GDB error will
362 not be thrown. */
363
79aafec9 364struct frame_info_ptr
ed3ef339
DE
365frscm_frame_smob_to_frame (frame_smob *f_smob)
366{
79aafec9 367 frame_info_ptr frame = frame_find_by_id (f_smob->frame_id);
ed3ef339
DE
368 if (frame == NULL)
369 return NULL;
370
371 if (f_smob->frame_id_is_next)
372 frame = get_prev_frame (frame);
373
374 return frame;
375}
376
ed3ef339
DE
377\f
378/* Frame methods. */
379
380/* (frame-valid? <gdb:frame>) -> bool
381 Returns #t if the frame corresponding to the frame_id of this
382 object still exists in the inferior. */
383
384static SCM
385gdbscm_frame_valid_p (SCM self)
386{
387 frame_smob *f_smob;
79aafec9 388 bool result = false;
ed3ef339
DE
389
390 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
391
680d7fd5 392 gdbscm_gdb_exception exc {};
a70b8144 393 try
ed3ef339 394 {
79aafec9
TT
395 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
396 result = frame != nullptr;
ed3ef339 397 }
230d2906 398 catch (const gdb_exception &except)
492d29ea 399 {
680d7fd5 400 exc = unpack (except);
492d29ea 401 }
ed3ef339 402
680d7fd5 403 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
79aafec9 404 return scm_from_bool (result);
ed3ef339
DE
405}
406
407/* (frame-name <gdb:frame>) -> string
408 Returns the name of the function corresponding to this frame,
409 or #f if there is no function. */
410
411static SCM
412gdbscm_frame_name (SCM self)
413{
414 frame_smob *f_smob;
c6dc63a1 415 gdb::unique_xmalloc_ptr<char> name;
ed3ef339 416 enum language lang = language_minimal;
79aafec9 417 bool found = false;
ed3ef339 418 SCM result;
ed3ef339
DE
419
420 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
421
680d7fd5 422 gdbscm_gdb_exception exc {};
a70b8144 423 try
ed3ef339 424 {
79aafec9 425 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
ed3ef339 426 if (frame != NULL)
79aafec9
TT
427 {
428 found = true;
429 name = find_frame_funname (frame, &lang, NULL);
430 }
ed3ef339 431 }
230d2906 432 catch (const gdb_exception &except)
492d29ea 433 {
680d7fd5 434 exc = unpack (except);
492d29ea 435 }
492d29ea 436
680d7fd5 437 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
79aafec9 438 if (!found)
ed3ef339
DE
439 {
440 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
441 _("<gdb:frame>"));
442 }
443
444 if (name != NULL)
c6dc63a1 445 result = gdbscm_scm_from_c_string (name.get ());
ed3ef339
DE
446 else
447 result = SCM_BOOL_F;
448
449 return result;
450}
451
452/* (frame-type <gdb:frame>) -> integer
453 Returns the frame type, namely one of the gdb:*_FRAME constants. */
454
455static SCM
456gdbscm_frame_type (SCM self)
457{
458 frame_smob *f_smob;
459 enum frame_type type = NORMAL_FRAME;
79aafec9 460 bool found = false;
ed3ef339
DE
461
462 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
463
680d7fd5 464 gdbscm_gdb_exception exc {};
a70b8144 465 try
ed3ef339 466 {
79aafec9 467 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
ed3ef339 468 if (frame != NULL)
79aafec9
TT
469 {
470 found = true;
471 type = get_frame_type (frame);
472 }
ed3ef339 473 }
230d2906 474 catch (const gdb_exception &except)
492d29ea 475 {
680d7fd5 476 exc = unpack (except);
492d29ea 477 }
ed3ef339 478
680d7fd5 479 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
79aafec9 480 if (!found)
ed3ef339
DE
481 {
482 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
483 _("<gdb:frame>"));
484 }
485
486 return scm_from_int (type);
487}
488
489/* (frame-arch <gdb:frame>) -> <gdb:architecture>
490 Returns the frame's architecture as a gdb:architecture object. */
491
492static SCM
493gdbscm_frame_arch (SCM self)
494{
495 frame_smob *f_smob;
79aafec9 496 bool found = false;
ed3ef339
DE
497
498 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
499
680d7fd5 500 gdbscm_gdb_exception exc {};
a70b8144 501 try
ed3ef339 502 {
79aafec9
TT
503 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
504 found = frame != nullptr;
ed3ef339 505 }
230d2906 506 catch (const gdb_exception &except)
492d29ea 507 {
680d7fd5 508 exc = unpack (except);
492d29ea 509 }
ed3ef339 510
680d7fd5 511 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
79aafec9 512 if (!found)
ed3ef339
DE
513 {
514 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
515 _("<gdb:frame>"));
516 }
517
518 return arscm_scm_from_arch (f_smob->gdbarch);
519}
520
521/* (frame-unwind-stop-reason <gdb:frame>) -> integer
522 Returns one of the gdb:FRAME_UNWIND_* constants. */
523
524static SCM
525gdbscm_frame_unwind_stop_reason (SCM self)
526{
527 frame_smob *f_smob;
79aafec9
TT
528 bool found = false;
529 enum unwind_stop_reason stop_reason = UNWIND_NO_REASON;
ed3ef339
DE
530
531 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
532
680d7fd5 533 gdbscm_gdb_exception exc {};
a70b8144 534 try
ed3ef339 535 {
79aafec9
TT
536 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
537 if (frame != nullptr)
538 {
539 found = true;
540 stop_reason = get_frame_unwind_stop_reason (frame);
541 }
ed3ef339 542 }
230d2906 543 catch (const gdb_exception &except)
492d29ea 544 {
680d7fd5 545 exc = unpack (except);
492d29ea 546 }
ed3ef339 547
680d7fd5 548 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
79aafec9 549 if (!found)
ed3ef339
DE
550 {
551 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
552 _("<gdb:frame>"));
553 }
554
ed3ef339
DE
555 return scm_from_int (stop_reason);
556}
557
558/* (frame-pc <gdb:frame>) -> integer
559 Returns the frame's resume address. */
560
561static SCM
562gdbscm_frame_pc (SCM self)
563{
564 frame_smob *f_smob;
565 CORE_ADDR pc = 0;
79aafec9 566 bool found = false;
ed3ef339
DE
567
568 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
569
680d7fd5 570 gdbscm_gdb_exception exc {};
a70b8144 571 try
ed3ef339 572 {
79aafec9 573 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
ed3ef339 574 if (frame != NULL)
79aafec9
TT
575 {
576 pc = get_frame_pc (frame);
577 found = true;
578 }
ed3ef339 579 }
230d2906 580 catch (const gdb_exception &except)
492d29ea 581 {
680d7fd5 582 exc = unpack (except);
492d29ea 583 }
ed3ef339 584
680d7fd5 585 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
79aafec9 586 if (!found)
ed3ef339
DE
587 {
588 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
589 _("<gdb:frame>"));
590 }
591
592 return gdbscm_scm_from_ulongest (pc);
593}
594
595/* (frame-block <gdb:frame>) -> <gdb:block>
596 Returns the frame's code block, or #f if one cannot be found. */
597
598static SCM
599gdbscm_frame_block (SCM self)
600{
601 frame_smob *f_smob;
3977b71f 602 const struct block *block = NULL, *fn_block;
79aafec9 603 bool found = false;
ed3ef339
DE
604
605 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
606
680d7fd5 607 gdbscm_gdb_exception exc {};
a70b8144 608 try
ed3ef339 609 {
79aafec9 610 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
ed3ef339 611 if (frame != NULL)
79aafec9
TT
612 {
613 found = true;
614 block = get_frame_block (frame, NULL);
615 }
ed3ef339 616 }
230d2906 617 catch (const gdb_exception &except)
492d29ea 618 {
680d7fd5 619 exc = unpack (except);
492d29ea 620 }
ed3ef339 621
680d7fd5 622 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
79aafec9 623 if (!found)
ed3ef339
DE
624 {
625 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
626 _("<gdb:frame>"));
627 }
628
629 for (fn_block = block;
6c00f721 630 fn_block != NULL && fn_block->function () == NULL;
f135fe72 631 fn_block = fn_block->superblock ())
ed3ef339
DE
632 continue;
633
6c00f721 634 if (block == NULL || fn_block == NULL || fn_block->function () == NULL)
ed3ef339
DE
635 {
636 scm_misc_error (FUNC_NAME, _("cannot find block for frame"),
637 scm_list_1 (self));
638 }
639
640 if (block != NULL)
641 {
08be3fe3 642 return bkscm_scm_from_block
6c00f721 643 (block, fn_block->function ()->objfile ());
ed3ef339
DE
644 }
645
646 return SCM_BOOL_F;
647}
648
649/* (frame-function <gdb:frame>) -> <gdb:symbol>
650 Returns the symbol for the function corresponding to this frame,
651 or #f if there isn't one. */
652
653static SCM
654gdbscm_frame_function (SCM self)
655{
656 frame_smob *f_smob;
657 struct symbol *sym = NULL;
79aafec9 658 bool found = false;
ed3ef339
DE
659
660 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
661
680d7fd5 662 gdbscm_gdb_exception exc {};
a70b8144 663 try
ed3ef339 664 {
79aafec9 665 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
ed3ef339 666 if (frame != NULL)
79aafec9
TT
667 {
668 found = true;
669 sym = find_pc_function (get_frame_address_in_block (frame));
670 }
ed3ef339 671 }
230d2906 672 catch (const gdb_exception &except)
492d29ea 673 {
680d7fd5 674 exc = unpack (except);
492d29ea 675 }
ed3ef339 676
680d7fd5 677 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
79aafec9 678 if (!found)
ed3ef339
DE
679 {
680 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
681 _("<gdb:frame>"));
682 }
683
684 if (sym != NULL)
685 return syscm_scm_from_symbol (sym);
686
687 return SCM_BOOL_F;
688}
689
690/* (frame-older <gdb:frame>) -> <gdb:frame>
691 Returns the frame immediately older (outer) to this frame,
692 or #f if there isn't one. */
693
694static SCM
695gdbscm_frame_older (SCM self)
696{
697 frame_smob *f_smob;
698 struct frame_info *prev = NULL;
79aafec9 699 bool found = false;
ed3ef339
DE
700
701 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
702
680d7fd5 703 gdbscm_gdb_exception exc {};
a70b8144 704 try
ed3ef339 705 {
79aafec9 706 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
ed3ef339 707 if (frame != NULL)
79aafec9
TT
708 {
709 found = true;
710 prev = get_prev_frame (frame).get ();
711 }
ed3ef339 712 }
230d2906 713 catch (const gdb_exception &except)
492d29ea 714 {
680d7fd5 715 exc = unpack (except);
492d29ea 716 }
ed3ef339 717
680d7fd5 718 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
79aafec9 719 if (!found)
ed3ef339
DE
720 {
721 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
722 _("<gdb:frame>"));
723 }
724
725 if (prev != NULL)
726 return frscm_scm_from_frame_unsafe (prev, f_smob->inferior);
727
728 return SCM_BOOL_F;
729}
730
731/* (frame-newer <gdb:frame>) -> <gdb:frame>
732 Returns the frame immediately newer (inner) to this frame,
733 or #f if there isn't one. */
734
735static SCM
736gdbscm_frame_newer (SCM self)
737{
738 frame_smob *f_smob;
739 struct frame_info *next = NULL;
79aafec9 740 bool found = false;
ed3ef339
DE
741
742 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
743
680d7fd5 744 gdbscm_gdb_exception exc {};
a70b8144 745 try
ed3ef339 746 {
79aafec9 747 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
ed3ef339 748 if (frame != NULL)
79aafec9
TT
749 {
750 found = true;
751 next = get_next_frame (frame).get ();
752 }
ed3ef339 753 }
230d2906 754 catch (const gdb_exception &except)
492d29ea 755 {
680d7fd5 756 exc = unpack (except);
492d29ea 757 }
ed3ef339 758
680d7fd5 759 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
79aafec9 760 if (!found)
ed3ef339
DE
761 {
762 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
763 _("<gdb:frame>"));
764 }
765
766 if (next != NULL)
767 return frscm_scm_from_frame_unsafe (next, f_smob->inferior);
768
769 return SCM_BOOL_F;
770}
771
772/* (frame-sal <gdb:frame>) -> <gdb:sal>
773 Returns the frame's symtab and line. */
774
775static SCM
776gdbscm_frame_sal (SCM self)
777{
778 frame_smob *f_smob;
779 struct symtab_and_line sal;
79aafec9 780 bool found = false;
ed3ef339
DE
781
782 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
783
680d7fd5 784 gdbscm_gdb_exception exc {};
a70b8144 785 try
ed3ef339 786 {
79aafec9 787 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
ed3ef339 788 if (frame != NULL)
79aafec9
TT
789 {
790 found = true;
791 sal = find_frame_sal (frame);
792 }
ed3ef339 793 }
230d2906 794 catch (const gdb_exception &except)
492d29ea 795 {
680d7fd5 796 exc = unpack (except);
492d29ea 797 }
ed3ef339 798
680d7fd5 799 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
79aafec9 800 if (!found)
ed3ef339
DE
801 {
802 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
803 _("<gdb:frame>"));
804 }
805
806 return stscm_scm_from_sal (sal);
807}
808
f2983cc3
AW
809/* (frame-read-register <gdb:frame> string) -> <gdb:value>
810 The register argument must be a string. */
811
812static SCM
813gdbscm_frame_read_register (SCM self, SCM register_scm)
814{
815 char *register_str;
816 struct value *value = NULL;
79aafec9 817 bool found = false;
f2983cc3
AW
818 frame_smob *f_smob;
819
820 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
821 gdbscm_parse_function_args (FUNC_NAME, SCM_ARG2, NULL, "s",
822 register_scm, &register_str);
557e56be 823
680d7fd5 824 gdbscm_gdb_exception except {};
f2983cc3 825
a70b8144 826 try
f2983cc3
AW
827 {
828 int regnum;
829
79aafec9 830 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
f2983cc3
AW
831 if (frame)
832 {
79aafec9 833 found = true;
f2983cc3
AW
834 regnum = user_reg_map_name_to_regnum (get_frame_arch (frame),
835 register_str,
836 strlen (register_str));
837 if (regnum >= 0)
838 value = value_of_register (regnum, frame);
839 }
840 }
230d2906 841 catch (const gdb_exception &ex)
f2983cc3 842 {
680d7fd5 843 except = unpack (ex);
f2983cc3 844 }
f2983cc3 845
557e56be
PA
846 xfree (register_str);
847 GDBSCM_HANDLE_GDB_EXCEPTION (except);
f2983cc3 848
79aafec9 849 if (!found)
f2983cc3
AW
850 {
851 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
852 _("<gdb:frame>"));
853 }
854
855 if (value == NULL)
856 {
857 gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG2, register_scm,
858 _("unknown register"));
859 }
860
861 return vlscm_scm_from_value (value);
862}
863
ed3ef339
DE
864/* (frame-read-var <gdb:frame> <gdb:symbol>) -> <gdb:value>
865 (frame-read-var <gdb:frame> string [#:block <gdb:block>]) -> <gdb:value>
866 If the optional block argument is provided start the search from that block,
867 otherwise search from the frame's current block (determined by examining
868 the resume address of the frame). The variable argument must be a string
869 or an instance of a <gdb:symbol>. The block argument must be an instance of
870 <gdb:block>. */
871
872static SCM
873gdbscm_frame_read_var (SCM self, SCM symbol_scm, SCM rest)
874{
875 SCM keywords[] = { block_keyword, SCM_BOOL_F };
ed3ef339
DE
876 frame_smob *f_smob;
877 int block_arg_pos = -1;
878 SCM block_scm = SCM_UNDEFINED;
879 struct frame_info *frame = NULL;
880 struct symbol *var = NULL;
63e43d3a 881 const struct block *block = NULL;
ed3ef339 882 struct value *value = NULL;
ed3ef339
DE
883
884 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
885
680d7fd5 886 gdbscm_gdb_exception exc {};
a70b8144 887 try
ed3ef339 888 {
79aafec9 889 frame = frscm_frame_smob_to_frame (f_smob).get ();
ed3ef339 890 }
230d2906 891 catch (const gdb_exception &except)
492d29ea 892 {
680d7fd5 893 exc = unpack (except);
492d29ea 894 }
ed3ef339 895
680d7fd5 896 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
ed3ef339
DE
897 if (frame == NULL)
898 {
899 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
900 _("<gdb:frame>"));
901 }
902
903 gdbscm_parse_function_args (FUNC_NAME, SCM_ARG3, keywords, "#O",
904 rest, &block_arg_pos, &block_scm);
905
906 if (syscm_is_symbol (symbol_scm))
907 {
908 var = syscm_get_valid_symbol_arg_unsafe (symbol_scm, SCM_ARG2,
909 FUNC_NAME);
910 SCM_ASSERT (SCM_UNBNDP (block_scm), block_scm, SCM_ARG3, FUNC_NAME);
911 }
912 else if (scm_is_string (symbol_scm))
913 {
680d7fd5 914 gdbscm_gdb_exception except {};
ed3ef339
DE
915
916 if (! SCM_UNBNDP (block_scm))
917 {
918 SCM except_scm;
919
920 gdb_assert (block_arg_pos > 0);
921 block = bkscm_scm_to_block (block_scm, block_arg_pos, FUNC_NAME,
922 &except_scm);
923 if (block == NULL)
924 gdbscm_throw (except_scm);
925 }
926
a95c7dab
TT
927 {
928 gdb::unique_xmalloc_ptr<char> var_name
929 (gdbscm_scm_to_c_string (symbol_scm));
930 /* N.B. Between here and the end of the scope, don't do anything
931 to cause a Scheme exception. */
932
a70b8144 933 try
a95c7dab
TT
934 {
935 struct block_symbol lookup_sym;
936
937 if (block == NULL)
79aafec9 938 block = get_frame_block (frame_info_ptr (frame), NULL);
a95c7dab
TT
939 lookup_sym = lookup_symbol (var_name.get (), block, VAR_DOMAIN,
940 NULL);
941 var = lookup_sym.symbol;
942 block = lookup_sym.block;
943 }
230d2906 944 catch (const gdb_exception &ex)
a95c7dab 945 {
680d7fd5 946 except = unpack (ex);
a95c7dab 947 }
a95c7dab 948 }
ed3ef339 949
ed3ef339
DE
950 GDBSCM_HANDLE_GDB_EXCEPTION (except);
951
952 if (var == NULL)
a95c7dab
TT
953 gdbscm_out_of_range_error (FUNC_NAME, 0, symbol_scm,
954 _("variable not found"));
ed3ef339
DE
955 }
956 else
957 {
958 /* Use SCM_ASSERT_TYPE for more consistent error messages. */
959 SCM_ASSERT_TYPE (0, symbol_scm, SCM_ARG1, FUNC_NAME,
960 _("gdb:symbol or string"));
961 }
962
a70b8144 963 try
ed3ef339 964 {
79aafec9 965 value = read_var_value (var, block, frame_info_ptr (frame));
ed3ef339 966 }
230d2906 967 catch (const gdb_exception &except)
492d29ea 968 {
680d7fd5 969 exc = unpack (except);
492d29ea 970 }
ed3ef339 971
680d7fd5 972 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
ed3ef339
DE
973 return vlscm_scm_from_value (value);
974}
975
976/* (frame-select <gdb:frame>) -> unspecified
977 Select this frame. */
978
979static SCM
980gdbscm_frame_select (SCM self)
981{
982 frame_smob *f_smob;
79aafec9 983 bool found = false;
ed3ef339
DE
984
985 f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
986
680d7fd5 987 gdbscm_gdb_exception exc {};
a70b8144 988 try
ed3ef339 989 {
79aafec9 990 frame_info_ptr frame = frscm_frame_smob_to_frame (f_smob);
ed3ef339 991 if (frame != NULL)
79aafec9
TT
992 {
993 found = true;
994 select_frame (frame);
995 }
ed3ef339 996 }
230d2906 997 catch (const gdb_exception &except)
492d29ea 998 {
680d7fd5 999 exc = unpack (except);
492d29ea 1000 }
ed3ef339 1001
680d7fd5 1002 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
79aafec9 1003 if (!found)
ed3ef339
DE
1004 {
1005 gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
1006 _("<gdb:frame>"));
1007 }
1008
1009 return SCM_UNSPECIFIED;
1010}
1011
1012/* (newest-frame) -> <gdb:frame>
1013 Returns the newest frame. */
1014
1015static SCM
1016gdbscm_newest_frame (void)
1017{
1018 struct frame_info *frame = NULL;
ed3ef339 1019
680d7fd5 1020 gdbscm_gdb_exception exc {};
a70b8144 1021 try
ed3ef339 1022 {
79aafec9 1023 frame = get_current_frame ().get ();
ed3ef339 1024 }
230d2906 1025 catch (const gdb_exception &except)
492d29ea 1026 {
680d7fd5 1027 exc = unpack (except);
492d29ea 1028 }
ed3ef339 1029
680d7fd5 1030 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
ed3ef339
DE
1031 return frscm_scm_from_frame_unsafe (frame, current_inferior ());
1032}
1033
1034/* (selected-frame) -> <gdb:frame>
1035 Returns the selected frame. */
1036
1037static SCM
1038gdbscm_selected_frame (void)
1039{
1040 struct frame_info *frame = NULL;
ed3ef339 1041
680d7fd5 1042 gdbscm_gdb_exception exc {};
a70b8144 1043 try
ed3ef339 1044 {
79aafec9 1045 frame = get_selected_frame (_("No frame is currently selected")).get ();
ed3ef339 1046 }
230d2906 1047 catch (const gdb_exception &except)
492d29ea 1048 {
680d7fd5 1049 exc = unpack (except);
492d29ea 1050 }
ed3ef339 1051
680d7fd5 1052 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
ed3ef339
DE
1053 return frscm_scm_from_frame_unsafe (frame, current_inferior ());
1054}
1055
1056/* (unwind-stop-reason-string integer) -> string
1057 Return a string explaining the unwind stop reason. */
1058
1059static SCM
1060gdbscm_unwind_stop_reason_string (SCM reason_scm)
1061{
1062 int reason;
1063 const char *str;
1064
1065 gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, NULL, "i",
1066 reason_scm, &reason);
1067
1068 if (reason < UNWIND_FIRST || reason > UNWIND_LAST)
1069 scm_out_of_range (FUNC_NAME, reason_scm);
1070
fa4c39cb 1071 str = unwind_stop_reason_to_string ((enum unwind_stop_reason) reason);
ed3ef339
DE
1072 return gdbscm_scm_from_c_string (str);
1073}
1074\f
1075/* Initialize the Scheme frame support. */
1076
1077static const scheme_integer_constant frame_integer_constants[] =
1078{
1079#define ENTRY(X) { #X, X }
1080
1081 ENTRY (NORMAL_FRAME),
1082 ENTRY (DUMMY_FRAME),
1083 ENTRY (INLINE_FRAME),
1084 ENTRY (TAILCALL_FRAME),
1085 ENTRY (SIGTRAMP_FRAME),
1086 ENTRY (ARCH_FRAME),
1087 ENTRY (SENTINEL_FRAME),
1088
1089#undef ENTRY
1090
1091#define SET(name, description) \
1092 { "FRAME_" #name, name },
1093#include "unwind_stop_reasons.def"
1094#undef SET
1095
1096 END_INTEGER_CONSTANTS
1097};
1098
1099static const scheme_function frame_functions[] =
1100{
72e02483 1101 { "frame?", 1, 0, 0, as_a_scm_t_subr (gdbscm_frame_p),
ed3ef339
DE
1102 "\
1103Return #t if the object is a <gdb:frame> object." },
1104
72e02483 1105 { "frame-valid?", 1, 0, 0, as_a_scm_t_subr (gdbscm_frame_valid_p),
ed3ef339
DE
1106 "\
1107Return #t if the object is a valid <gdb:frame> object.\n\
1108Frames become invalid when the inferior returns to its caller." },
1109
72e02483 1110 { "frame-name", 1, 0, 0, as_a_scm_t_subr (gdbscm_frame_name),
ed3ef339
DE
1111 "\
1112Return the name of the function corresponding to this frame,\n\
1113or #f if there is no function." },
1114
72e02483 1115 { "frame-arch", 1, 0, 0, as_a_scm_t_subr (gdbscm_frame_arch),
ed3ef339
DE
1116 "\
1117Return the frame's architecture as a <gdb:arch> object." },
1118
72e02483 1119 { "frame-type", 1, 0, 0, as_a_scm_t_subr (gdbscm_frame_type),
ed3ef339
DE
1120 "\
1121Return the frame type, namely one of the gdb:*_FRAME constants." },
1122
72e02483
PA
1123 { "frame-unwind-stop-reason", 1, 0, 0,
1124 as_a_scm_t_subr (gdbscm_frame_unwind_stop_reason),
ed3ef339
DE
1125 "\
1126Return one of the gdb:FRAME_UNWIND_* constants explaining why\n\
1127it's not possible to find frames older than this." },
1128
72e02483 1129 { "frame-pc", 1, 0, 0, as_a_scm_t_subr (gdbscm_frame_pc),
ed3ef339
DE
1130 "\
1131Return the frame's resume address." },
1132
72e02483 1133 { "frame-block", 1, 0, 0, as_a_scm_t_subr (gdbscm_frame_block),
ed3ef339
DE
1134 "\
1135Return the frame's code block, or #f if one cannot be found." },
1136
72e02483 1137 { "frame-function", 1, 0, 0, as_a_scm_t_subr (gdbscm_frame_function),
ed3ef339
DE
1138 "\
1139Return the <gdb:symbol> for the function corresponding to this frame,\n\
1140or #f if there isn't one." },
1141
72e02483 1142 { "frame-older", 1, 0, 0, as_a_scm_t_subr (gdbscm_frame_older),
ed3ef339
DE
1143 "\
1144Return the frame immediately older (outer) to this frame,\n\
1145or #f if there isn't one." },
1146
72e02483 1147 { "frame-newer", 1, 0, 0, as_a_scm_t_subr (gdbscm_frame_newer),
ed3ef339
DE
1148 "\
1149Return the frame immediately newer (inner) to this frame,\n\
1150or #f if there isn't one." },
1151
72e02483 1152 { "frame-sal", 1, 0, 0, as_a_scm_t_subr (gdbscm_frame_sal),
ed3ef339
DE
1153 "\
1154Return the frame's symtab-and-line <gdb:sal> object." },
1155
72e02483 1156 { "frame-read-var", 2, 0, 1, as_a_scm_t_subr (gdbscm_frame_read_var),
ed3ef339
DE
1157 "\
1158Return the value of the symbol in the frame.\n\
1159\n\
1160 Arguments: <gdb:frame> <gdb:symbol>\n\
dda83cd7 1161 Or: <gdb:frame> string [#:block <gdb:block>]" },
ed3ef339 1162
72e02483
PA
1163 { "frame-read-register", 2, 0, 0,
1164 as_a_scm_t_subr (gdbscm_frame_read_register),
f2983cc3
AW
1165 "\
1166Return the value of the register in the frame.\n\
1167\n\
1168 Arguments: <gdb:frame> string" },
1169
72e02483 1170 { "frame-select", 1, 0, 0, as_a_scm_t_subr (gdbscm_frame_select),
ed3ef339
DE
1171 "\
1172Select this frame." },
1173
72e02483 1174 { "newest-frame", 0, 0, 0, as_a_scm_t_subr (gdbscm_newest_frame),
ed3ef339
DE
1175 "\
1176Return the newest frame." },
1177
72e02483 1178 { "selected-frame", 0, 0, 0, as_a_scm_t_subr (gdbscm_selected_frame),
ed3ef339
DE
1179 "\
1180Return the selected frame." },
1181
72e02483
PA
1182 { "unwind-stop-reason-string", 1, 0, 0,
1183 as_a_scm_t_subr (gdbscm_unwind_stop_reason_string),
ed3ef339
DE
1184 "\
1185Return a string explaining the unwind stop reason.\n\
1186\n\
1187 Arguments: integer (the result of frame-unwind-stop-reason)" },
1188
1189 END_FUNCTIONS
1190};
1191
1192void
1193gdbscm_initialize_frames (void)
1194{
1195 frame_smob_tag
1196 = gdbscm_make_smob_type (frame_smob_name, sizeof (frame_smob));
ed3ef339
DE
1197 scm_set_smob_free (frame_smob_tag, frscm_free_frame_smob);
1198 scm_set_smob_print (frame_smob_tag, frscm_print_frame_smob);
1199
1200 gdbscm_define_integer_constants (frame_integer_constants, 1);
1201 gdbscm_define_functions (frame_functions, 1);
1202
1203 block_keyword = scm_from_latin1_keyword ("block");
880ae75a 1204}