1 /* Representation of stack frame debug information
2 * Copyright (C) 1996,1997,2000,2001, 2006 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"
35 #include "libguile/private-options.h"
39 /* {Frames and stacks}
41 * The debugging evaluator creates debug frames on the stack. These
42 * are linked from the innermost frame and outwards. The last frame
43 * created can always be accessed as SCM_LAST_DEBUG_FRAME.
44 * Continuations contain a pointer to the innermost debug frame on the
47 * Each debug frame contains a set of flags and information about one
48 * or more stack frames. The case of multiple frames occurs due to
49 * tail recursion. The maximal number of stack frames which can be
50 * recorded in one debug frame can be set dynamically with the debug
53 * Stack frame information is of two types: eval information (the
54 * expression being evaluated and its environment) and apply
55 * information (the procedure being applied and its arguments). A
56 * stack frame normally corresponds to an eval/apply pair, but macros
57 * and special forms (which are implemented as macros in Guile) only
58 * have eval information and apply calls leads to apply only frames.
60 * Since we want to record the total stack information and later
61 * manipulate this data at the scheme level in the debugger, we need
62 * to transform it into a new representation. In the following code
63 * section you'll find the functions implementing this data type.
67 * The stack is represented as a struct with an id slot and a tail
68 * array of scm_t_info_frame structs.
70 * A frame is represented as a pair where the car contains a stack and
71 * the cdr an inum. The inum is an index to the first SCM value of
72 * the scm_t_info_frame struct.
96 * frame-evaluating-args?
101 /* Some auxiliary functions for reading debug frames off the stack.
104 /* Stacks often contain pointers to other items on the stack; for
105 example, each scm_t_debug_frame structure contains a pointer to the
106 next frame out. When we capture a continuation, we copy the stack
107 into the heap, and just leave all the pointers unchanged. This
108 makes it simple to restore the continuation --- just copy the stack
109 back! However, if we retrieve a pointer from the heap copy to
110 another item that was originally on the stack, we have to add an
111 offset to the pointer to discover the new referent.
113 If PTR is a pointer retrieved from a continuation, whose original
114 target was on the stack, and OFFSET is the appropriate offset from
115 the original stack to the continuation, then RELOC_MUMBLE (PTR,
116 OFFSET) is a pointer to the copy in the continuation of the
117 original referent, cast to an scm_debug_MUMBLE *. */
118 #define RELOC_INFO(ptr, offset) \
119 ((scm_t_debug_info *) ((SCM_STACKITEM *) (ptr) + (offset)))
120 #define RELOC_FRAME(ptr, offset) \
121 ((scm_t_debug_frame *) ((SCM_STACKITEM *) (ptr) + (offset)))
124 /* Count number of debug info frames on a stack, beginning with
125 * DFRAME. OFFSET is used for relocation of pointers when the stack
126 * is read from a continuation.
129 stack_depth (scm_t_debug_frame
*dframe
, scm_t_ptrdiff offset
,
133 long max_depth
= SCM_BACKTRACE_MAXDEPTH
;
135 dframe
&& !SCM_VOIDFRAMEP (*dframe
) && n
< max_depth
;
136 dframe
= RELOC_FRAME (dframe
->prev
, offset
))
138 if (SCM_EVALFRAMEP (*dframe
))
140 scm_t_debug_info
*info
= RELOC_INFO (dframe
->info
, offset
);
141 scm_t_debug_info
*vect
= RELOC_INFO (dframe
->vect
, offset
);
142 n
+= (info
- vect
) / 2 + 1;
143 /* Data in the apply part of an eval info frame comes from previous
144 stack frame if the scm_t_debug_info vector is overflowed. */
145 if ((((info
- vect
) & 1) == 0)
146 && SCM_OVERFLOWP (*dframe
)
147 && !SCM_UNBNDP (info
[1].a
.proc
))
153 if (dframe
&& SCM_VOIDFRAMEP (*dframe
))
154 *id
= RELOC_INFO(dframe
->vect
, offset
)[0].id
;
160 /* Read debug info from DFRAME into IFRAME.
163 read_frame (scm_t_debug_frame
*dframe
, scm_t_ptrdiff offset
,
164 scm_t_info_frame
*iframe
)
166 scm_t_bits flags
= SCM_UNPACK (SCM_INUM0
); /* UGh. */
167 if (SCM_EVALFRAMEP (*dframe
))
169 scm_t_debug_info
*info
= RELOC_INFO (dframe
->info
, offset
);
170 scm_t_debug_info
*vect
= RELOC_INFO (dframe
->vect
, offset
);
171 if ((info
- vect
) & 1)
173 /* Debug.vect ends with apply info. */
175 if (!SCM_UNBNDP (info
[1].a
.proc
))
177 flags
|= SCM_FRAMEF_PROC
;
178 iframe
->proc
= info
[1].a
.proc
;
179 iframe
->args
= info
[1].a
.args
;
180 if (!SCM_ARGS_READY_P (*dframe
))
181 flags
|= SCM_FRAMEF_EVAL_ARGS
;
184 iframe
->source
= scm_make_memoized (info
[0].e
.exp
, info
[0].e
.env
);
188 scm_t_debug_info
*vect
= RELOC_INFO (dframe
->vect
, offset
);
189 flags
|= SCM_FRAMEF_PROC
;
190 iframe
->proc
= vect
[0].a
.proc
;
191 iframe
->args
= vect
[0].a
.args
;
193 iframe
->flags
= flags
;
196 /* Look up the first body form of the apply closure. We'll use this
197 below to prevent it from being displayed.
202 SCM var
= scm_sym2var (scm_sym_apply
, SCM_BOOL_F
, SCM_BOOL_F
);
203 if (SCM_VARIABLEP (var
) && SCM_CLOSUREP (SCM_VARIABLE_REF (var
)))
204 return SCM_CAR (SCM_CLOSURE_BODY (SCM_VARIABLE_REF (var
)));
206 return SCM_UNDEFINED
;
209 #define NEXT_FRAME(iframe, n, quit) \
211 if (SCM_MEMOIZEDP (iframe->source) \
212 && scm_is_eq (SCM_MEMOIZED_EXP (iframe->source), applybody)) \
214 iframe->source = SCM_BOOL_F; \
215 if (scm_is_false (iframe->proc)) \
227 /* Fill the scm_t_info_frame vector IFRAME with data from N stack frames
228 * starting with the first stack frame represented by debug frame
233 read_frames (scm_t_debug_frame
*dframe
, scm_t_ptrdiff offset
,
234 long n
, scm_t_info_frame
*iframes
)
236 scm_t_info_frame
*iframe
= iframes
;
237 scm_t_debug_info
*info
, *vect
;
238 static SCM applybody
= SCM_UNDEFINED
;
240 /* The value of applybody has to be setup after r4rs.scm has executed. */
241 if (SCM_UNBNDP (applybody
))
242 applybody
= get_applybody ();
244 dframe
&& !SCM_VOIDFRAMEP (*dframe
) && n
> 0;
245 dframe
= RELOC_FRAME (dframe
->prev
, offset
))
247 read_frame (dframe
, offset
, iframe
);
248 if (SCM_EVALFRAMEP (*dframe
))
250 /* If current frame is a macro during expansion, we should
251 skip the previously recorded macro transformer
252 application frame. */
253 if (SCM_MACROEXPP (*dframe
) && iframe
> iframes
)
255 *(iframe
- 1) = *iframe
;
258 info
= RELOC_INFO (dframe
->info
, offset
);
259 vect
= RELOC_INFO (dframe
->vect
, offset
);
260 if ((info
- vect
) & 1)
262 /* Data in the apply part of an eval info frame comes from
263 previous stack frame if the scm_t_debug_info vector is
265 else if (SCM_OVERFLOWP (*dframe
)
266 && !SCM_UNBNDP (info
[1].a
.proc
))
268 NEXT_FRAME (iframe
, n
, quit
);
269 iframe
->flags
= SCM_UNPACK(SCM_INUM0
) | SCM_FRAMEF_PROC
;
270 iframe
->proc
= info
[1].a
.proc
;
271 iframe
->args
= info
[1].a
.args
;
273 if (SCM_OVERFLOWP (*dframe
))
274 iframe
->flags
|= SCM_FRAMEF_OVERFLOW
;
276 NEXT_FRAME (iframe
, n
, quit
);
279 if (!SCM_UNBNDP (info
[1].a
.proc
))
281 iframe
->flags
= SCM_UNPACK(SCM_INUM0
) | SCM_FRAMEF_PROC
;
282 iframe
->proc
= info
[1].a
.proc
;
283 iframe
->args
= info
[1].a
.args
;
286 iframe
->flags
= SCM_UNPACK (SCM_INUM0
);
287 iframe
->source
= scm_make_memoized (info
[0].e
.exp
,
290 NEXT_FRAME (iframe
, n
, quit
);
293 else if (scm_is_eq (iframe
->proc
, scm_f_gsubr_apply
))
294 /* Skip gsubr apply frames. */
298 NEXT_FRAME (iframe
, n
, quit
);
301 if (iframe
> iframes
)
302 (iframe
- 1) -> flags
|= SCM_FRAMEF_REAL
;
304 return iframe
- iframes
; /* Number of frames actually read */
307 /* Narrow STACK by cutting away stackframes (mutatingly).
309 * Inner frames (most recent) are cut by advancing the frames pointer.
310 * Outer frames are cut by decreasing the recorded length.
312 * Cut maximally INNER inner frames and OUTER outer frames using
313 * the keys INNER_KEY and OUTER_KEY.
315 * Frames are cut away starting at the end points and moving towards
316 * the center of the stack. The key is normally compared to the
317 * operator in application frames. Frames up to and including the key
320 * If INNER_KEY is #t a different scheme is used for inner frames:
322 * Frames up to but excluding the first source frame originating from
323 * a user module are cut, except for possible application frames
324 * between the user frame and the last system frame previously
329 narrow_stack (SCM stack
, long inner
, SCM inner_key
, long outer
, SCM outer_key
)
331 scm_t_stack
*s
= SCM_STACK (stack
);
335 /* Cut inner part. */
336 if (scm_is_eq (inner_key
, SCM_BOOL_T
))
338 /* Cut all frames up to user module code */
339 for (i
= 0; inner
; ++i
, --inner
)
341 SCM m
= s
->frames
[i
].source
;
342 if (SCM_MEMOIZEDP (m
)
343 && !SCM_IMP (SCM_MEMOIZED_ENV (m
))
344 && scm_is_false (scm_system_module_env_p (SCM_MEMOIZED_ENV (m
))))
346 /* Back up in order to include any non-source frames */
349 m
= s
->frames
[i
- 1].source
;
350 if (SCM_MEMOIZEDP (m
))
353 m
= s
->frames
[i
- 1].proc
;
354 if (scm_is_true (scm_procedure_p (m
))
355 && scm_is_true (scm_procedure_property
356 (m
, scm_sym_system_procedure
)))
367 /* Use standard cutting procedure. */
369 for (i
= 0; inner
; --inner
)
370 if (scm_is_eq (s
->frames
[i
++].proc
, inner_key
))
373 s
->frames
= &s
->frames
[i
];
376 /* Cut outer part. */
377 for (; n
&& outer
; --outer
)
378 if (scm_is_eq (s
->frames
[--n
].proc
, outer_key
))
391 SCM_DEFINE (scm_stack_p
, "stack?", 1, 0, 0,
393 "Return @code{#t} if @var{obj} is a calling stack.")
394 #define FUNC_NAME s_scm_stack_p
396 return scm_from_bool(SCM_STACKP (obj
));
400 SCM_DEFINE (scm_make_stack
, "make-stack", 1, 0, 1,
402 "Create a new stack. If @var{obj} is @code{#t}, the current\n"
403 "evaluation stack is used for creating the stack frames,\n"
404 "otherwise the frames are taken from @var{obj} (which must be\n"
405 "either a debug object or a continuation).\n\n"
406 "@var{args} should be a list containing any combination of\n"
407 "integer, procedure and @code{#t} values.\n\n"
408 "These values specify various ways of cutting away uninteresting\n"
409 "stack frames from the top and bottom of the stack that\n"
410 "@code{make-stack} returns. They come in pairs like this:\n"
411 "@code{(@var{inner_cut_1} @var{outer_cut_1} @var{inner_cut_2}\n"
412 "@var{outer_cut_2} @dots{})}.\n\n"
413 "Each @var{inner_cut_N} can be @code{#t}, an integer, or a\n"
414 "procedure. @code{#t} means to cut away all frames up to but\n"
415 "excluding the first user module frame. An integer means to cut\n"
416 "away exactly that number of frames. A procedure means to cut\n"
417 "away all frames up to but excluding the application frame whose\n"
418 "procedure matches the specified one.\n\n"
419 "Each @var{outer_cut_N} can be an integer or a procedure. An\n"
420 "integer means to cut away that number of frames. A procedure\n"
421 "means to cut away frames down to but excluding the application\n"
422 "frame whose procedure matches the specified one.\n\n"
423 "If the @var{outer_cut_N} of the last pair is missing, it is\n"
425 #define FUNC_NAME s_scm_make_stack
429 scm_t_debug_frame
*dframe
;
430 scm_t_info_frame
*iframe
;
433 SCM inner_cut
, outer_cut
;
435 /* Extract a pointer to the innermost frame of whatever object
436 scm_make_stack was given. */
437 if (scm_is_eq (obj
, SCM_BOOL_T
))
439 dframe
= scm_i_last_debug_frame ();
441 else if (SCM_DEBUGOBJP (obj
))
443 dframe
= SCM_DEBUGOBJ_FRAME (obj
);
445 else if (SCM_CONTINUATIONP (obj
))
447 scm_t_contregs
*cont
= SCM_CONTREGS (obj
);
448 offset
= cont
->offset
;
449 dframe
= RELOC_FRAME (cont
->dframe
, offset
);
453 SCM_WRONG_TYPE_ARG (SCM_ARG1
, obj
);
457 /* Count number of frames. Also get stack id tag and check whether
458 there are more stackframes than we want to record
459 (SCM_BACKTRACE_MAXDEPTH). */
462 n
= stack_depth (dframe
, offset
, &id
, &maxp
);
463 size
= n
* SCM_FRAME_N_SLOTS
;
465 /* Make the stack object. */
466 stack
= scm_make_struct (scm_stack_type
, scm_from_long (size
), SCM_EOL
);
467 SCM_STACK (stack
) -> id
= id
;
468 iframe
= &SCM_STACK (stack
) -> tail
[0];
469 SCM_STACK (stack
) -> frames
= iframe
;
471 /* Translate the current chain of stack frames into debugging information. */
472 n
= read_frames (dframe
, offset
, n
, iframe
);
473 SCM_STACK (stack
) -> length
= n
;
475 /* Narrow the stack according to the arguments given to scm_make_stack. */
476 SCM_VALIDATE_REST_ARGUMENT (args
);
477 while (n
> 0 && !scm_is_null (args
))
479 inner_cut
= SCM_CAR (args
);
480 args
= SCM_CDR (args
);
481 if (scm_is_null (args
))
483 outer_cut
= SCM_INUM0
;
487 outer_cut
= SCM_CAR (args
);
488 args
= SCM_CDR (args
);
492 scm_is_integer (inner_cut
) ? scm_to_int (inner_cut
) : n
,
493 scm_is_integer (inner_cut
) ? 0 : inner_cut
,
494 scm_is_integer (outer_cut
) ? scm_to_int (outer_cut
) : n
,
495 scm_is_integer (outer_cut
) ? 0 : outer_cut
);
497 n
= SCM_STACK (stack
) -> length
;
503 iframe
[n
- 1].flags
|= SCM_FRAMEF_OVERFLOW
;
511 SCM_DEFINE (scm_stack_id
, "stack-id", 1, 0, 0,
513 "Return the identifier given to @var{stack} by @code{start-stack}.")
514 #define FUNC_NAME s_scm_stack_id
516 scm_t_debug_frame
*dframe
;
518 if (scm_is_eq (stack
, SCM_BOOL_T
))
520 dframe
= scm_i_last_debug_frame ();
522 else if (SCM_DEBUGOBJP (stack
))
524 dframe
= SCM_DEBUGOBJ_FRAME (stack
);
526 else if (SCM_CONTINUATIONP (stack
))
528 scm_t_contregs
*cont
= SCM_CONTREGS (stack
);
529 offset
= cont
->offset
;
530 dframe
= RELOC_FRAME (cont
->dframe
, offset
);
532 else if (SCM_STACKP (stack
))
534 return SCM_STACK (stack
) -> id
;
538 SCM_WRONG_TYPE_ARG (1, stack
);
541 while (dframe
&& !SCM_VOIDFRAMEP (*dframe
))
542 dframe
= RELOC_FRAME (dframe
->prev
, offset
);
543 if (dframe
&& SCM_VOIDFRAMEP (*dframe
))
544 return RELOC_INFO (dframe
->vect
, offset
)[0].id
;
549 SCM_DEFINE (scm_stack_ref
, "stack-ref", 2, 0, 0,
550 (SCM stack
, SCM index
),
551 "Return the @var{index}'th frame from @var{stack}.")
552 #define FUNC_NAME s_scm_stack_ref
554 unsigned long int c_index
;
556 SCM_VALIDATE_STACK (1, stack
);
557 c_index
= scm_to_unsigned_integer (index
, 0, SCM_STACK_LENGTH(stack
)-1);
558 return scm_cons (stack
, index
);
562 SCM_DEFINE (scm_stack_length
, "stack-length", 1, 0, 0,
564 "Return the length of @var{stack}.")
565 #define FUNC_NAME s_scm_stack_length
567 SCM_VALIDATE_STACK (1, stack
);
568 return scm_from_int (SCM_STACK_LENGTH (stack
));
575 SCM_DEFINE (scm_frame_p
, "frame?", 1, 0, 0,
577 "Return @code{#t} if @var{obj} is a stack frame.")
578 #define FUNC_NAME s_scm_frame_p
580 return scm_from_bool(SCM_FRAMEP (obj
));
584 SCM_DEFINE (scm_last_stack_frame
, "last-stack-frame", 1, 0, 0,
586 "Return the last (innermost) frame of @var{obj}, which must be\n"
587 "either a debug object or a continuation.")
588 #define FUNC_NAME s_scm_last_stack_frame
590 scm_t_debug_frame
*dframe
;
594 if (SCM_DEBUGOBJP (obj
))
596 dframe
= SCM_DEBUGOBJ_FRAME (obj
);
598 else if (SCM_CONTINUATIONP (obj
))
600 scm_t_contregs
*cont
= SCM_CONTREGS (obj
);
601 offset
= cont
->offset
;
602 dframe
= RELOC_FRAME (cont
->dframe
, offset
);
606 SCM_WRONG_TYPE_ARG (1, obj
);
610 if (!dframe
|| SCM_VOIDFRAMEP (*dframe
))
613 stack
= scm_make_struct (scm_stack_type
, scm_from_int (SCM_FRAME_N_SLOTS
),
615 SCM_STACK (stack
) -> length
= 1;
616 SCM_STACK (stack
) -> frames
= &SCM_STACK (stack
) -> tail
[0];
617 read_frame (dframe
, offset
,
618 (scm_t_info_frame
*) &SCM_STACK (stack
) -> frames
[0]);
620 return scm_cons (stack
, SCM_INUM0
);
624 SCM_DEFINE (scm_frame_number
, "frame-number", 1, 0, 0,
626 "Return the frame number of @var{frame}.")
627 #define FUNC_NAME s_scm_frame_number
629 SCM_VALIDATE_FRAME (1, frame
);
630 return scm_from_int (SCM_FRAME_NUMBER (frame
));
634 SCM_DEFINE (scm_frame_source
, "frame-source", 1, 0, 0,
636 "Return the source of @var{frame}.")
637 #define FUNC_NAME s_scm_frame_source
639 SCM_VALIDATE_FRAME (1, frame
);
640 return SCM_FRAME_SOURCE (frame
);
644 SCM_DEFINE (scm_frame_procedure
, "frame-procedure", 1, 0, 0,
646 "Return the procedure for @var{frame}, or @code{#f} if no\n"
647 "procedure is associated with @var{frame}.")
648 #define FUNC_NAME s_scm_frame_procedure
650 SCM_VALIDATE_FRAME (1, frame
);
651 return (SCM_FRAME_PROC_P (frame
)
652 ? SCM_FRAME_PROC (frame
)
657 SCM_DEFINE (scm_frame_arguments
, "frame-arguments", 1, 0, 0,
659 "Return the arguments of @var{frame}.")
660 #define FUNC_NAME s_scm_frame_arguments
662 SCM_VALIDATE_FRAME (1, frame
);
663 return SCM_FRAME_ARGS (frame
);
667 SCM_DEFINE (scm_frame_previous
, "frame-previous", 1, 0, 0,
669 "Return the previous frame of @var{frame}, or @code{#f} if\n"
670 "@var{frame} is the first frame in its stack.")
671 #define FUNC_NAME s_scm_frame_previous
674 SCM_VALIDATE_FRAME (1, frame
);
675 n
= scm_to_ulong (SCM_CDR (frame
)) + 1;
676 if (n
>= SCM_STACK_LENGTH (SCM_CAR (frame
)))
679 return scm_cons (SCM_CAR (frame
), scm_from_ulong (n
));
683 SCM_DEFINE (scm_frame_next
, "frame-next", 1, 0, 0,
685 "Return the next frame of @var{frame}, or @code{#f} if\n"
686 "@var{frame} is the last frame in its stack.")
687 #define FUNC_NAME s_scm_frame_next
690 SCM_VALIDATE_FRAME (1, frame
);
691 n
= scm_to_ulong (SCM_CDR (frame
));
695 return scm_cons (SCM_CAR (frame
), scm_from_ulong (n
- 1));
699 SCM_DEFINE (scm_frame_real_p
, "frame-real?", 1, 0, 0,
701 "Return @code{#t} if @var{frame} is a real frame.")
702 #define FUNC_NAME s_scm_frame_real_p
704 SCM_VALIDATE_FRAME (1, frame
);
705 return scm_from_bool(SCM_FRAME_REAL_P (frame
));
709 SCM_DEFINE (scm_frame_procedure_p
, "frame-procedure?", 1, 0, 0,
711 "Return @code{#t} if a procedure is associated with @var{frame}.")
712 #define FUNC_NAME s_scm_frame_procedure_p
714 SCM_VALIDATE_FRAME (1, frame
);
715 return scm_from_bool(SCM_FRAME_PROC_P (frame
));
719 SCM_DEFINE (scm_frame_evaluating_args_p
, "frame-evaluating-args?", 1, 0, 0,
721 "Return @code{#t} if @var{frame} contains evaluated arguments.")
722 #define FUNC_NAME s_scm_frame_evaluating_args_p
724 SCM_VALIDATE_FRAME (1, frame
);
725 return scm_from_bool(SCM_FRAME_EVAL_ARGS_P (frame
));
729 SCM_DEFINE (scm_frame_overflow_p
, "frame-overflow?", 1, 0, 0,
731 "Return @code{#t} if @var{frame} is an overflow frame.")
732 #define FUNC_NAME s_scm_frame_overflow_p
734 SCM_VALIDATE_FRAME (1, frame
);
735 return scm_from_bool(SCM_FRAME_OVERFLOW_P (frame
));
746 = scm_make_struct_layout (scm_from_locale_string (SCM_STACK_LAYOUT
));
747 vtable
= scm_make_vtable_vtable (scm_nullstr
, SCM_INUM0
, SCM_EOL
);
749 = scm_permanent_object (scm_make_struct (vtable
, SCM_INUM0
,
750 scm_cons (stack_layout
,
752 scm_set_struct_vtable_name_x (scm_stack_type
,
753 scm_from_locale_symbol ("stack"));
754 #include "libguile/stacks.x"