Functions | |
void | croc_debug_setHookFunc (CrocThread *t, uword_t mask, uword_t hookDelay) |
word_t | croc_debug_pushHookFunc (CrocThread *t) |
uword_t | croc_debug_getHookMask (CrocThread *t) |
uword_t | croc_debug_getHookDelay (CrocThread *t) |
void | croc_debug_printStack (CrocThread *t) |
void | croc_debug_printWholeStack (CrocThread *t) |
void | croc_debug_printCallStack (CrocThread *t) |
Debugging.
void croc_debug_setHookFunc | ( | CrocThread * | t, |
uword_t | mask, | ||
uword_t | hookDelay | ||
) |
Sets the thread's hook function, which is a special function called at certain points during program execution which allows you to trace execution and inspect the internals of the program as it runs.
This can be used to make a debugger.
This expects the hook function to be on top of the stack. It can be either a function closure or null
to remove the hook function instead. The hook function is popped.
There are four places the hook function can be called:
There is only one hook function, and it will be called for any combination of these events that you specify; it's up to the hook function to see what kind of event it is and respond appropriately.
This hook function (as well as the mask and delay) is inherited by any new threads which the given thread creates after the hook was set.
While the hook function is being run, no hooks will be called (obviously, or else it would result in infinite recursion). When the hook function returns, execution will resume as normal until the hook function is called again.
You cannot yield from within the hook function.
this
(since you could possibly set the same hook function to multiple threads) and the type of the hook event will be a string, its only parameter. This string can be one of the following values:"call"
for normal function calls."tailcall"
which is the same as "call"
except there will not be a corresponding "return"
when this function returns (or more precisely, the previously called function will not have a "return"
event)."return"
for when a function is about to return."line"
for when execution reaches a new line of source code."delay"
for when a certain number of bytecode instructions have been executed.mask | controls which of the following events the hook function will be called for. It should be an or-ing together of the CrocThreadHook enum values. Note that if you use either one of CrocThreadHook_Call or CrocThreadHook_TailCall, you will get both kinds of call events. Also, the CrocThreadHook_Delay flag isn't controlled by this mask, but by the hookDelay parameter. If this parameter is 0, the hook function is removed from the thread. |
hookDelay | controls whether or not the hook function will be called for "delay" events. If this parameter is 0, it won't be. Otherwise, it indicates how often the "delay" hook event will occur. A value of 1 means it will occur after every bytecode instruction; a value of 2 means every other instruction, and so on. |
word_t croc_debug_pushHookFunc | ( | CrocThread * | t | ) |
Pushes the given thread's hook function onto its stack, or null
if none is set on that thread.
uword_t croc_debug_getHookMask | ( | CrocThread * | t | ) |
Gets the hook mask of the given thread (like was set with croc_debug_setHookFunc), or 0 if there is no hook set on that thread.
uword_t croc_debug_getHookDelay | ( | CrocThread * | t | ) |
Gets the hook delay of the given thread (like was set with croc_debug_setHookFunc), or 0 if there is no delay hook on that thread.
void croc_debug_printStack | ( | CrocThread * | t | ) |
Prints out the contents of the current function's stack frame to standard output in the following format:
[xxx:yyyy] val: type
Where xxx
is the absolute stack index (within the thread's entire stack), yyyy is the stack index relative to the current function's stack frame, val is a raw string representation of the value, and type is its type.
void croc_debug_printWholeStack | ( | CrocThread * | t | ) |
Same as croc_debug_printStack, but prints the thread's whole stack, for all stack frames.
In this case the relative stack indexes can be negative, which means that the slot is in a previous stack frame.
void croc_debug_printCallStack | ( | CrocThread * | t | ) |
Prints out the thread's call stack to standard output in reverse, starting with the currently-executing function, in the following format:
Record <name>: Base: <base> Saved top: <top> Vararg base: <vargBase> Return slot: <retSlot> Expected results: <numResults>
Where name
is the name of the function at that level (or ??? if there is no function at that level); base
is the absolute stack index where this activation record's stack frame begins; top
is the absolute stack index of the end of its stack frame (which may and often does overlap the next frame); vargBase
is the absolute stack index of where its variadic arguments, if any, begin; retSlot
is the absolute stack index where its return values will be copied upon returning to the calling function; and numResults
is the number of results the calling function is expecting it to return (or -1 for "all of them").
This only prints the current thread's call stack; it does not cross thread resume boundaries.