1 /* Representation of stack frame debug information
2 * Copyright (C) 1996,1997,2000,2001 Free Software Foundation
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libguile/_scm.h"
23 #include "libguile/eval.h"
24 #include "libguile/debug.h"
25 #include "libguile/continuations.h"
26 #include "libguile/struct.h"
27 #include "libguile/macros.h"
28 #include "libguile/procprop.h"
29 #include "libguile/modules.h"
30 #include "libguile/root.h"
31 #include "libguile/strings.h"
33 #include "libguile/validate.h"
34 #include "libguile/stacks.h"
37 /* {Frames and stacks}
39 * The debugging evaluator creates debug frames on the stack. These
40 * are linked from the innermost frame and outwards. The last frame
41 * created can always be accessed as SCM_LAST_DEBUG_FRAME.
42 * Continuations contain a pointer to the innermost debug frame on the
45 * Each debug frame contains a set of flags and information about one
46 * or more stack frames. The case of multiple frames occurs due to
47 * tail recursion. The maximal number of stack frames which can be
48 * recorded in one debug frame can be set dynamically with the debug
51 * Stack frame information is of two types: eval information (the
52 * expression being evaluated and its environment) and apply
53 * information (the procedure being applied and its arguments). A
54 * stack frame normally corresponds to an eval/apply pair, but macros
55 * and special forms (which are implemented as macros in Guile) only
56 * have eval information and apply calls leads to apply only frames.
58 * Since we want to record the total stack information and later
59 * manipulate this data at the scheme level in the debugger, we need
60 * to transform it into a new representation. In the following code
61 * section you'll find the functions implementing this data type.
65 * The stack is represented as a struct with an id slot and a tail
66 * array of scm_t_info_frame structs.
68 * A frame is represented as a pair where the car contains a stack and
69 * the cdr an inum. The inum is an index to the first SCM value of
70 * the scm_t_info_frame struct.
94 * frame-evaluating-args?
99 /* Some auxiliary functions for reading debug frames off the stack.
102 /* Stacks often contain pointers to other items on the stack; for
103 example, each scm_t_debug_frame structure contains a pointer to the
104 next frame out. When we capture a continuation, we copy the stack
105 into the heap, and just leave all the pointers unchanged. This
106 makes it simple to restore the continuation --- just copy the stack
107 back! However, if we retrieve a pointer from the heap copy to
108 another item that was originally on the stack, we have to add an
109 offset to the pointer to discover the new referent.
111 If PTR is a pointer retrieved from a continuation, whose original
112 target was on the stack, and OFFSET is the appropriate offset from
113 the original stack to the continuation, then RELOC_MUMBLE (PTR,
114 OFFSET) is a pointer to the copy in the continuation of the
115 original referent, cast to an scm_debug_MUMBLE *. */
116 #define RELOC_INFO(ptr, offset) \
117 ((scm_t_debug_info *) ((SCM_STACKITEM *) (ptr) + (offset)))
118 #define RELOC_FRAME(ptr, offset) \
119 ((scm_t_debug_frame *) ((SCM_STACKITEM *) (ptr) + (offset)))
122 /* Count number of debug info frames on a stack, beginning with
123 * DFRAME. OFFSET is used for relocation of pointers when the stack
124 * is read from a continuation.
127 stack_depth (scm_t_debug_frame
*dframe
, scm_t_ptrdiff offset
,
131 long max_depth
= SCM_BACKTRACE_MAXDEPTH
;
133 dframe
&& !SCM_VOIDFRAMEP (*dframe
) && n
< max_depth
;
134 dframe
= RELOC_FRAME (dframe
->prev
, offset
))
136 if (SCM_EVALFRAMEP (*dframe
))
138 scm_t_debug_info
*info
= RELOC_INFO (dframe
->info
, offset
);
139 scm_t_debug_info
*vect
= RELOC_INFO (dframe
->vect
, offset
);
140 n
+= (info
- vect
) / 2 + 1;
141 /* Data in the apply part of an eval info frame comes from previous
142 stack frame if the scm_t_debug_info vector is overflowed. */
143 if ((((info
- vect
) & 1) == 0)
144 && SCM_OVERFLOWP (*dframe
)
145 && !SCM_UNBNDP (info
[1].a
.proc
))
151 if (dframe
&& SCM_VOIDFRAMEP (*dframe
))
152 *id
= RELOC_INFO(dframe
->vect
, offset
)[0].id
;
158 /* Read debug info from DFRAME into IFRAME.
161 read_frame (scm_t_debug_frame
*dframe
, scm_t_ptrdiff offset
,
162 scm_t_info_frame
*iframe
)
164 scm_t_bits flags
= SCM_UNPACK (SCM_INUM0
); /* UGh. */
165 if (SCM_EVALFRAMEP (*dframe
))
167 scm_t_debug_info
*info
= RELOC_INFO (dframe
->info
, offset
);
168 scm_t_debug_info
*vect
= RELOC_INFO (dframe
->vect
, offset
);
169 if ((info
- vect
) & 1)
171 /* Debug.vect ends with apply info. */
173 if (!SCM_UNBNDP (info
[1].a
.proc
))
175 flags
|= SCM_FRAMEF_PROC
;
176 iframe
->proc
= info
[1].a
.proc
;
177 iframe
->args
= info
[1].a
.args
;
178 if (!SCM_ARGS_READY_P (*dframe
))
179 flags
|= SCM_FRAMEF_EVAL_ARGS
;
182 iframe
->source
= scm_make_memoized (info
[0].e
.exp
, info
[0].e
.env
);
186 scm_t_debug_info
*vect
= RELOC_INFO (dframe
->vect
, offset
);
187 flags
|= SCM_FRAMEF_PROC
;
188 iframe
->proc
= vect
[0].a
.proc
;
189 iframe
->args
= vect
[0].a
.args
;
191 iframe
->flags
= flags
;
194 /* Look up the first body form of the apply closure. We'll use this
195 below to prevent it from being displayed.
200 SCM var
= scm_sym2var (scm_sym_apply
, SCM_BOOL_F
, SCM_BOOL_F
);
201 if (SCM_VARIABLEP (var
) && SCM_CLOSUREP (SCM_VARIABLE_REF (var
)))
202 return SCM_CAR (SCM_CLOSURE_BODY (SCM_VARIABLE_REF (var
)));
204 return SCM_UNDEFINED
;
207 #define NEXT_FRAME(iframe, n, quit) \
209 if (SCM_MEMOIZEDP (iframe->source) \
210 && scm_is_eq (SCM_MEMOIZED_EXP (iframe->source), applybody)) \
212 iframe->source = SCM_BOOL_F; \
213 if (scm_is_false (iframe->proc)) \
225 /* Fill the scm_t_info_frame vector IFRAME with data from N stack frames
226 * starting with the first stack frame represented by debug frame
231 read_frames (scm_t_debug_frame
*dframe
, scm_t_ptrdiff offset
,
232 long n
, scm_t_info_frame
*iframes
)
234 scm_t_info_frame
*iframe
= iframes
;
235 scm_t_debug_info
*info
, *vect
;
236 static SCM applybody
= SCM_UNDEFINED
;
238 /* The value of applybody has to be setup after r4rs.scm has executed. */
239 if (SCM_UNBNDP (applybody
))
240 applybody
= get_applybody ();
242 dframe
&& !SCM_VOIDFRAMEP (*dframe
) && n
> 0;
243 dframe
= RELOC_FRAME (dframe
->prev
, offset
))
245 read_frame (dframe
, offset
, iframe
);
246 if (SCM_EVALFRAMEP (*dframe
))
248 /* If current frame is a macro during expansion, we should
249 skip the previously recorded macro transformer
250 application frame. */
251 if (SCM_MACROEXPP (*dframe
) && iframe
> iframes
)
253 *(iframe
- 1) = *iframe
;
256 info
= RELOC_INFO (dframe
->info
, offset
);
257 vect
= RELOC_INFO (dframe
->vect
, offset
);
258 if ((info
- vect
) & 1)
260 /* Data in the apply part of an eval info frame comes from
261 previous stack frame if the scm_t_debug_info vector is
263 else if (SCM_OVERFLOWP (*dframe
)
264 && !SCM_UNBNDP (info
[1].a
.proc
))
266 NEXT_FRAME (iframe
, n
, quit
);
267 iframe
->flags
= SCM_UNPACK(SCM_INUM0
) | SCM_FRAMEF_PROC
;
268 iframe
->proc
= info
[1].a
.proc
;
269 iframe
->args
= info
[1].a
.args
;
271 if (SCM_OVERFLOWP (*dframe
))
272 iframe
->flags
|= SCM_FRAMEF_OVERFLOW
;
274 NEXT_FRAME (iframe
, n
, quit
);
277 if (!SCM_UNBNDP (info
[1].a
.proc
))
279 iframe
->flags
= SCM_UNPACK(SCM_INUM0
) | SCM_FRAMEF_PROC
;
280 iframe
->proc
= info
[1].a
.proc
;
281 iframe
->args
= info
[1].a
.args
;
284 iframe
->flags
= SCM_UNPACK (SCM_INUM0
);
285 iframe
->source
= scm_make_memoized (info
[0].e
.exp
,
288 NEXT_FRAME (iframe
, n
, quit
);
291 else if (scm_is_eq (iframe
->proc
, scm_f_gsubr_apply
))
292 /* Skip gsubr apply frames. */
296 NEXT_FRAME (iframe
, n
, quit
);
299 if (iframe
> iframes
)
300 (iframe
- 1) -> flags
|= SCM_FRAMEF_REAL
;
302 return iframe
- iframes
; /* Number of frames actually read */
305 /* Narrow STACK by cutting away stackframes (mutatingly).
307 * Inner frames (most recent) are cut by advancing the frames pointer.
308 * Outer frames are cut by decreasing the recorded length.
310 * Cut maximally INNER inner frames and OUTER outer frames using
311 * the keys INNER_KEY and OUTER_KEY.
313 * Frames are cut away starting at the end points and moving towards
314 * the center of the stack. The key is normally compared to the
315 * operator in application frames. Frames up to and including the key
318 * If INNER_KEY is #t a different scheme is used for inner frames:
320 * Frames up to but excluding the first source frame originating from
321 * a user module are cut, except for possible application frames
322 * between the user frame and the last system frame previously
327 narrow_stack (SCM stack
, long inner
, SCM inner_key
, long outer
, SCM outer_key
)
329 scm_t_stack
*s
= SCM_STACK (stack
);
333 /* Cut inner part. */
334 if (scm_is_eq (inner_key
, SCM_BOOL_T
))
336 /* Cut all frames up to user module code */
337 for (i
= 0; inner
; ++i
, --inner
)
339 SCM m
= s
->frames
[i
].source
;
340 if (SCM_MEMOIZEDP (m
)
341 && !SCM_IMP (SCM_MEMOIZED_ENV (m
))
342 && scm_is_false (scm_system_module_env_p (SCM_MEMOIZED_ENV (m
))))
344 /* Back up in order to include any non-source frames */
347 m
= s
->frames
[i
- 1].source
;
348 if (SCM_MEMOIZEDP (m
))
351 m
= s
->frames
[i
- 1].proc
;
352 if (scm_is_true (scm_procedure_p (m
))
353 && scm_is_true (scm_procedure_property
354 (m
, scm_sym_system_procedure
)))
365 /* Use standard cutting procedure. */
367 for (i
= 0; inner
; --inner
)
368 if (scm_is_eq (s
->frames
[i
++].proc
, inner_key
))
371 s
->frames
= &s
->frames
[i
];
374 /* Cut outer part. */
375 for (; n
&& outer
; --outer
)
376 if (scm_is_eq (s
->frames
[--n
].proc
, outer_key
))
389 SCM_DEFINE (scm_stack_p
, "stack?", 1, 0, 0,
391 "Return @code{#t} if @var{obj} is a calling stack.")
392 #define FUNC_NAME s_scm_stack_p
394 return scm_from_bool(SCM_STACKP (obj
));
398 SCM_DEFINE (scm_make_stack
, "make-stack", 1, 0, 1,
400 "Create a new stack. If @var{obj} is @code{#t}, the current\n"
401 "evaluation stack is used for creating the stack frames,\n"
402 "otherwise the frames are taken from @var{obj} (which must be\n"
403 "either a debug object or a continuation).\n\n"
404 "@var{args} should be a list containing any combination of\n"
405 "integer, procedure and @code{#t} values.\n\n"
406 "These values specify various ways of cutting away uninteresting\n"
407 "stack frames from the top and bottom of the stack that\n"
408 "@code{make-stack} returns. They come in pairs like this:\n"
409 "@code{(@var{inner_cut_1} @var{outer_cut_1} @var{inner_cut_2}\n"
410 "@var{outer_cut_2} @dots{})}.\n\n"
411 "Each @var{inner_cut_N} can be @code{#t}, an integer, or a\n"
412 "procedure. @code{#t} means to cut away all frames up to but\n"
413 "excluding the first user module frame. An integer means to cut\n"
414 "away exactly that number of frames. A procedure means to cut\n"
415 "away all frames up to but excluding the application frame whose\n"
416 "procedure matches the specified one.\n\n"
417 "Each @var{outer_cut_N} can be an integer or a procedure. An\n"
418 "integer means to cut away that number of frames. A procedure\n"
419 "means to cut away frames down to but excluding the application\n"
420 "frame whose procedure matches the specified one.\n\n"
421 "If the @var{outer_cut_N} of the last pair is missing, it is\n"
423 #define FUNC_NAME s_scm_make_stack
427 scm_t_debug_frame
*dframe
;
428 scm_t_info_frame
*iframe
;
431 SCM inner_cut
, outer_cut
;
433 /* Extract a pointer to the innermost frame of whatever object
434 scm_make_stack was given. */
435 if (scm_is_eq (obj
, SCM_BOOL_T
))
437 dframe
= scm_i_last_debug_frame ();
439 else if (SCM_DEBUGOBJP (obj
))
441 dframe
= SCM_DEBUGOBJ_FRAME (obj
);
443 else if (SCM_CONTINUATIONP (obj
))
445 scm_t_contregs
*cont
= SCM_CONTREGS (obj
);
446 offset
= cont
->offset
;
447 dframe
= RELOC_FRAME (cont
->dframe
, offset
);
451 SCM_WRONG_TYPE_ARG (SCM_ARG1
, obj
);
455 /* Count number of frames. Also get stack id tag and check whether
456 there are more stackframes than we want to record
457 (SCM_BACKTRACE_MAXDEPTH). */
460 n
= stack_depth (dframe
, offset
, &id
, &maxp
);
461 size
= n
* SCM_FRAME_N_SLOTS
;
463 /* Make the stack object. */
464 stack
= scm_make_struct (scm_stack_type
, scm_from_long (size
), SCM_EOL
);
465 SCM_STACK (stack
) -> id
= id
;
466 iframe
= &SCM_STACK (stack
) -> tail
[0];
467 SCM_STACK (stack
) -> frames
= iframe
;
469 /* Translate the current chain of stack frames into debugging information. */
470 n
= read_frames (dframe
, offset
, n
, iframe
);
471 SCM_STACK (stack
) -> length
= n
;
473 /* Narrow the stack according to the arguments given to scm_make_stack. */
474 SCM_VALIDATE_REST_ARGUMENT (args
);
475 while (n
> 0 && !scm_is_null (args
))
477 inner_cut
= SCM_CAR (args
);
478 args
= SCM_CDR (args
);
479 if (scm_is_null (args
))
481 outer_cut
= SCM_INUM0
;
485 outer_cut
= SCM_CAR (args
);
486 args
= SCM_CDR (args
);
490 scm_is_integer (inner_cut
) ? scm_to_int (inner_cut
) : n
,
491 scm_is_integer (inner_cut
) ? 0 : inner_cut
,
492 scm_is_integer (outer_cut
) ? scm_to_int (outer_cut
) : n
,
493 scm_is_integer (outer_cut
) ? 0 : outer_cut
);
495 n
= SCM_STACK (stack
) -> length
;
501 iframe
[n
- 1].flags
|= SCM_FRAMEF_OVERFLOW
;
509 SCM_DEFINE (scm_stack_id
, "stack-id", 1, 0, 0,
511 "Return the identifier given to @var{stack} by @code{start-stack}.")
512 #define FUNC_NAME s_scm_stack_id
514 scm_t_debug_frame
*dframe
;
516 if (scm_is_eq (stack
, SCM_BOOL_T
))
518 dframe
= scm_i_last_debug_frame ();
520 else if (SCM_DEBUGOBJP (stack
))
522 dframe
= SCM_DEBUGOBJ_FRAME (stack
);
524 else if (SCM_CONTINUATIONP (stack
))
526 scm_t_contregs
*cont
= SCM_CONTREGS (stack
);
527 offset
= cont
->offset
;
528 dframe
= RELOC_FRAME (cont
->dframe
, offset
);
530 else if (SCM_STACKP (stack
))
532 return SCM_STACK (stack
) -> id
;
536 SCM_WRONG_TYPE_ARG (1, stack
);
539 while (dframe
&& !SCM_VOIDFRAMEP (*dframe
))
540 dframe
= RELOC_FRAME (dframe
->prev
, offset
);
541 if (dframe
&& SCM_VOIDFRAMEP (*dframe
))
542 return RELOC_INFO (dframe
->vect
, offset
)[0].id
;
547 SCM_DEFINE (scm_stack_ref
, "stack-ref", 2, 0, 0,
548 (SCM stack
, SCM index
),
549 "Return the @var{index}'th frame from @var{stack}.")
550 #define FUNC_NAME s_scm_stack_ref
552 unsigned long int c_index
;
554 SCM_VALIDATE_STACK (1, stack
);
555 c_index
= scm_to_unsigned_integer (index
, 0, SCM_STACK_LENGTH(stack
)-1);
556 return scm_cons (stack
, index
);
560 SCM_DEFINE (scm_stack_length
, "stack-length", 1, 0, 0,
562 "Return the length of @var{stack}.")
563 #define FUNC_NAME s_scm_stack_length
565 SCM_VALIDATE_STACK (1, stack
);
566 return scm_from_int (SCM_STACK_LENGTH (stack
));
573 SCM_DEFINE (scm_frame_p
, "frame?", 1, 0, 0,
575 "Return @code{#t} if @var{obj} is a stack frame.")
576 #define FUNC_NAME s_scm_frame_p
578 return scm_from_bool(SCM_FRAMEP (obj
));
582 SCM_DEFINE (scm_last_stack_frame
, "last-stack-frame", 1, 0, 0,
584 "Return a stack which consists of a single frame, which is the\n"
585 "last stack frame for @var{obj}. @var{obj} must be either a\n"
586 "debug object or a continuation.")
587 #define FUNC_NAME s_scm_last_stack_frame
589 scm_t_debug_frame
*dframe
;
593 if (SCM_DEBUGOBJP (obj
))
595 dframe
= SCM_DEBUGOBJ_FRAME (obj
);
597 else if (SCM_CONTINUATIONP (obj
))
599 scm_t_contregs
*cont
= SCM_CONTREGS (obj
);
600 offset
= cont
->offset
;
601 dframe
= RELOC_FRAME (cont
->dframe
, offset
);
605 SCM_WRONG_TYPE_ARG (1, obj
);
609 if (!dframe
|| SCM_VOIDFRAMEP (*dframe
))
612 stack
= scm_make_struct (scm_stack_type
, scm_from_int (SCM_FRAME_N_SLOTS
),
614 SCM_STACK (stack
) -> length
= 1;
615 SCM_STACK (stack
) -> frames
= &SCM_STACK (stack
) -> tail
[0];
616 read_frame (dframe
, offset
,
617 (scm_t_info_frame
*) &SCM_STACK (stack
) -> frames
[0]);
619 return scm_cons (stack
, SCM_INUM0
);
623 SCM_DEFINE (scm_frame_number
, "frame-number", 1, 0, 0,
625 "Return the frame number of @var{frame}.")
626 #define FUNC_NAME s_scm_frame_number
628 SCM_VALIDATE_FRAME (1, frame
);
629 return scm_from_int (SCM_FRAME_NUMBER (frame
));
633 SCM_DEFINE (scm_frame_source
, "frame-source", 1, 0, 0,
635 "Return the source of @var{frame}.")
636 #define FUNC_NAME s_scm_frame_source
638 SCM_VALIDATE_FRAME (1, frame
);
639 return SCM_FRAME_SOURCE (frame
);
643 SCM_DEFINE (scm_frame_procedure
, "frame-procedure", 1, 0, 0,
645 "Return the procedure for @var{frame}, or @code{#f} if no\n"
646 "procedure is associated with @var{frame}.")
647 #define FUNC_NAME s_scm_frame_procedure
649 SCM_VALIDATE_FRAME (1, frame
);
650 return (SCM_FRAME_PROC_P (frame
)
651 ? SCM_FRAME_PROC (frame
)
656 SCM_DEFINE (scm_frame_arguments
, "frame-arguments", 1, 0, 0,
658 "Return the arguments of @var{frame}.")
659 #define FUNC_NAME s_scm_frame_arguments
661 SCM_VALIDATE_FRAME (1, frame
);
662 return SCM_FRAME_ARGS (frame
);
666 SCM_DEFINE (scm_frame_previous
, "frame-previous", 1, 0, 0,
668 "Return the previous frame of @var{frame}, or @code{#f} if\n"
669 "@var{frame} is the first frame in its stack.")
670 #define FUNC_NAME s_scm_frame_previous
673 SCM_VALIDATE_FRAME (1, frame
);
674 n
= scm_to_ulong (SCM_CDR (frame
)) + 1;
675 if (n
>= SCM_STACK_LENGTH (SCM_CAR (frame
)))
678 return scm_cons (SCM_CAR (frame
), scm_from_ulong (n
));
682 SCM_DEFINE (scm_frame_next
, "frame-next", 1, 0, 0,
684 "Return the next frame of @var{frame}, or @code{#f} if\n"
685 "@var{frame} is the last frame in its stack.")
686 #define FUNC_NAME s_scm_frame_next
689 SCM_VALIDATE_FRAME (1, frame
);
690 n
= scm_to_ulong (SCM_CDR (frame
));
694 return scm_cons (SCM_CAR (frame
), scm_from_ulong (n
- 1));
698 SCM_DEFINE (scm_frame_real_p
, "frame-real?", 1, 0, 0,
700 "Return @code{#t} if @var{frame} is a real frame.")
701 #define FUNC_NAME s_scm_frame_real_p
703 SCM_VALIDATE_FRAME (1, frame
);
704 return scm_from_bool(SCM_FRAME_REAL_P (frame
));
708 SCM_DEFINE (scm_frame_procedure_p
, "frame-procedure?", 1, 0, 0,
710 "Return @code{#t} if a procedure is associated with @var{frame}.")
711 #define FUNC_NAME s_scm_frame_procedure_p
713 SCM_VALIDATE_FRAME (1, frame
);
714 return scm_from_bool(SCM_FRAME_PROC_P (frame
));
718 SCM_DEFINE (scm_frame_evaluating_args_p
, "frame-evaluating-args?", 1, 0, 0,
720 "Return @code{#t} if @var{frame} contains evaluated arguments.")
721 #define FUNC_NAME s_scm_frame_evaluating_args_p
723 SCM_VALIDATE_FRAME (1, frame
);
724 return scm_from_bool(SCM_FRAME_EVAL_ARGS_P (frame
));
728 SCM_DEFINE (scm_frame_overflow_p
, "frame-overflow?", 1, 0, 0,
730 "Return @code{#t} if @var{frame} is an overflow frame.")
731 #define FUNC_NAME s_scm_frame_overflow_p
733 SCM_VALIDATE_FRAME (1, frame
);
734 return scm_from_bool(SCM_FRAME_OVERFLOW_P (frame
));
745 = scm_make_struct_layout (scm_from_locale_string (SCM_STACK_LAYOUT
));
746 vtable
= scm_make_vtable_vtable (scm_nullstr
, SCM_INUM0
, SCM_EOL
);
748 = scm_permanent_object (scm_make_struct (vtable
, SCM_INUM0
,
749 scm_cons (stack_layout
,
751 scm_set_struct_vtable_name_x (scm_stack_type
,
752 scm_from_locale_symbol ("stack"));
753 #include "libguile/stacks.x"