From: Arran Cudbard-Bell Date: Wed, 23 Jun 2021 19:41:22 +0000 (-0500) Subject: Add custom stack dump functions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a9c0c24053f1adf2580b30bb602d38916994f660;p=thirdparty%2Ffreeradius-server.git Add custom stack dump functions These can print out more information about the frame state --- diff --git a/src/lib/unlang/function.c b/src/lib/unlang/function.c index d4558c3c6d5..b7527f4d871 100644 --- a/src/lib/unlang/function.c +++ b/src/lib/unlang/function.c @@ -33,8 +33,11 @@ RCSID("$Id$") */ typedef struct { unlang_function_t func; //!< To call when going down the stack. + char const *func_name; //!< Debug name for the function. unlang_function_t repeat; //!< To call when going back up the stack. + char const *repeat_name; //!< Debug name for the repeat function. unlang_function_signal_t signal; //!< Signal function to call. + char const *signal_name; //!< Debug name for the signal function. void *uctx; //!< Uctx to pass to function. } unlang_frame_state_func_t; @@ -86,7 +89,7 @@ static unlang_action_t unlang_function_call_repeat(rlm_rcode_t *p_result, reques */ caller = request->module; request->module = NULL; - RDEBUG4("Calling repeat function %p", state->repeat); + RDEBUG4("Calling repeat function %p (%s)", state->repeat, state->repeat_name); ua = state->repeat(p_result, &frame->priority, request, state->uctx); request->module = caller; @@ -112,7 +115,7 @@ static unlang_action_t unlang_function_call(rlm_rcode_t *p_result, request_t *re caller = request->module; request->module = NULL; - RDEBUG4("Calling function %p", state->func); + RDEBUG4("Calling function %p (%s)", state->func, state->func_name); ua = state->func(p_result, &frame->priority, request, state->uctx); switch (ua) { case UNLANG_ACTION_STOP_PROCESSING: @@ -174,13 +177,14 @@ int unlang_function_clear(request_t *request) * * The function frame being modified must be at the top of the stack. * - * @param[in] request The current request. - * @param[in] repeat the repeat function to set. + * @param[in] request The current request. + * @param[in] repeat the repeat function to set. + * @param[in] repeat_name Name of the repeat function call (for debugging). * @return * - 0 on success. * - -1 on failure. */ -int unlang_function_repeat(request_t *request, unlang_function_t repeat) +int _unlang_function_repeat(request_t *request, unlang_function_t repeat, char const *repeat_name) { unlang_stack_t *stack = request->stack; unlang_stack_frame_t *frame = &stack->frame[stack->depth]; @@ -199,6 +203,8 @@ int unlang_function_repeat(request_t *request, unlang_function_t repeat) * once the current function returns. */ state->repeat = repeat; + state->repeat_name = repeat_name; + repeatable_set(frame); return 0; } @@ -208,18 +214,24 @@ int unlang_function_repeat(request_t *request, unlang_function_t repeat) * These can be pushed by any other type of unlang op to allow a submodule or function * deeper in the C call stack to establish a new resumption point. * - * @param[in] request The current request. - * @param[in] func to call going up the stack. - * @param[in] repeat function to call going back down the stack (may be NULL). - * This may be the same as func. - * @param[in] signal function to call if the request is signalled. - * @param[in] uctx to pass to func. + * @param[in] request The current request. + * @param[in] func to call going up the stack. + * @param[in] func_name Name of the function call (for debugging). + * @param[in] repeat function to call going back down the stack (may be NULL). + * This may be the same as func. + * @param[in] repeat_name Name of the repeat function call (for debugging). + * @param[in] signal function to call if the request is signalled. + * @param[in] signal_name Name of the signal function call (for debugging). + * @param[in] uctx to pass to func(s). * @return * - 0 on success. * - -1 on failure. */ -unlang_action_t unlang_function_push(request_t *request, unlang_function_t func, unlang_function_t repeat, - unlang_function_signal_t signal, bool top_frame, void *uctx) +unlang_action_t _unlang_function_push(request_t *request, + unlang_function_t func, char const *func_name, + unlang_function_t repeat, char const *repeat_name, + unlang_function_signal_t signal, char const *signal_name, + bool top_frame, void *uctx) { unlang_stack_t *stack = request->stack; unlang_stack_frame_t *frame; @@ -244,8 +256,11 @@ unlang_action_t unlang_function_push(request_t *request, unlang_function_t func, */ state = frame->state; state->func = func; + state->func_name = func_name; state->repeat = repeat; + state->repeat_name = repeat_name; state->signal = signal; + state->signal_name = signal_name; state->uctx = uctx; /* @@ -256,6 +271,19 @@ unlang_action_t unlang_function_push(request_t *request, unlang_function_t func, return UNLANG_ACTION_PUSHED_CHILD; } +/** Custom frame state dumper + * + */ +static void unlang_function_dump(request_t *request, unlang_stack_frame_t *frame) +{ + unlang_frame_state_func_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_func_t); + + RDEBUG2("frame state"); + if (state->func) RDEBUG2("function %p (%s)", state->func, state->func_name); + if (state->repeat) RDEBUG2("repeat %p (%s)", state->repeat, state->repeat_name); + if (state->signal) RDEBUG2("signal %p (%s)", state->signal, state->signal_name); +} + void unlang_function_init(void) { unlang_register(UNLANG_TYPE_FUNCTION, @@ -263,6 +291,7 @@ void unlang_function_init(void) .name = "function", .interpret = unlang_function_call, .signal = unlang_function_signal, + .dump = unlang_function_dump, .debug_braces = false, .frame_state_size = sizeof(unlang_frame_state_func_t), .frame_state_name = "unlang_frame_state_func_t", diff --git a/src/lib/unlang/function.h b/src/lib/unlang/function.h index 1bc0b327735..8a9113385fa 100644 --- a/src/lib/unlang/function.h +++ b/src/lib/unlang/function.h @@ -58,12 +58,49 @@ typedef void (*unlang_function_signal_t)(request_t *request, fr_state_signal_t a int unlang_function_clear(request_t *request) CC_HINT(warn_unused_result); -int unlang_function_repeat(request_t *request, unlang_function_t repeat) CC_HINT(warn_unused_result); +int _unlang_function_repeat(request_t *request, unlang_function_t repeat, char const *name) CC_HINT(warn_unused_result); -unlang_action_t unlang_function_push(request_t *request, - unlang_function_t func, unlang_function_t repeat, - unlang_function_signal_t signal, bool top_frame, void *uctx) - CC_HINT(warn_unused_result); +/** Set a new repeat function for an existing function frame + * + * The function frame being modified must be at the top of the stack. + * + * @param[in] _request The current request. + * @param[in] _repeat the repeat function to set. + * @return + * - 0 on success. + * - -1 on failure. + */ +#define unlang_function_repeat(_request, _repeat) \ + _unlang_function_repeat(_request, _repeat, STRINGIFY(_repeat)) + +unlang_action_t _unlang_function_push(request_t *request, + unlang_function_t func, char const *func_name, + unlang_function_t repeat, char const *repeat_name, + unlang_function_signal_t signal, char const *signal_name, + bool top_frame, void *uctx) + CC_HINT(warn_unused_result); + +/** Push a generic function onto the unlang stack + * + * These can be pushed by any other type of unlang op to allow a submodule or function + * deeper in the C call stack to establish a new resumption point. + * + * @param[in] _request The current request. + * @param[in] _func to call going up the stack. + * @param[in] _repeat function to call going back down the stack (may be NULL). + * This may be the same as func. + * @param[in] _signal function to call if the request is signalled. + * @param[in] _uctx to pass to func(s). + * @return + * - 0 on success. + * - -1 on failure. + */ +#define unlang_function_push(_request, _func, _repeat, _signal, _top_frame, _uctx) \ + _unlang_function_push(_request, \ + _func, STRINGIFY(_func), \ + _repeat, STRINGIFY(_repeat), \ + _signal, STRINGIFY(_signal), \ + _top_frame, _uctx) #ifdef __cplusplus } diff --git a/src/lib/unlang/interpret.c b/src/lib/unlang/interpret.c index bccac437296..e09bdc69aa9 100644 --- a/src/lib/unlang/interpret.c +++ b/src/lib/unlang/interpret.c @@ -39,19 +39,19 @@ RCSID("$Id$") static _Thread_local unlang_interpret_t *intp_thread_default; static fr_table_num_ordered_t const unlang_action_table[] = { - { L("unwind"), UNLANG_ACTION_UNWIND }, + { L("unwind"), UNLANG_ACTION_UNWIND }, { L("calculate-result"), UNLANG_ACTION_CALCULATE_RESULT }, - { L("next"), UNLANG_ACTION_EXECUTE_NEXT }, - { L("pushed-child"), UNLANG_ACTION_PUSHED_CHILD }, - { L("stop"), UNLANG_ACTION_STOP_PROCESSING }, - { L("yield"), UNLANG_ACTION_YIELD } + { L("next"), UNLANG_ACTION_EXECUTE_NEXT }, + { L("pushed-child"), UNLANG_ACTION_PUSHED_CHILD }, + { L("stop"), UNLANG_ACTION_STOP_PROCESSING }, + { L("yield"), UNLANG_ACTION_YIELD } }; static size_t unlang_action_table_len = NUM_ELEMENTS(unlang_action_table); static fr_table_num_ordered_t const unlang_frame_action_table[] = { - { L("pop"), UNLANG_FRAME_ACTION_POP }, - { L("next"), UNLANG_FRAME_ACTION_NEXT }, - { L("yield"), UNLANG_FRAME_ACTION_YIELD } + { L("pop"), UNLANG_FRAME_ACTION_POP }, + { L("next"), UNLANG_FRAME_ACTION_NEXT }, + { L("yield"), UNLANG_FRAME_ACTION_YIELD } }; static size_t unlang_frame_action_table_len = NUM_ELEMENTS(unlang_frame_action_table); @@ -73,6 +73,10 @@ static void instruction_dump(request_t *request, unlang_t const *instruction) static void frame_dump(request_t *request, unlang_stack_frame_t *frame) { + unlang_op_t *op = NULL; + + if (frame->instruction) op = &unlang_ops[frame->instruction->type]; + instruction_dump(request, frame->instruction); RINDENT(); @@ -89,6 +93,12 @@ static void frame_dump(request_t *request, unlang_stack_frame_t *frame) RDEBUG2("break_point %s", is_break_point(frame) ? "yes" : "no"); RDEBUG2("return_point %s", is_return_point(frame) ? "yes" : "no"); RDEBUG2("resumable %s", is_yielded(frame) ? "yes" : "no"); + + /* + * Call the custom frame dump function + */ + if (op && op->dump) op->dump(request, frame); + REXDENT(); } diff --git a/src/lib/unlang/unlang_priv.h b/src/lib/unlang/unlang_priv.h index 8bd27163d26..eb447b6bc9a 100644 --- a/src/lib/unlang/unlang_priv.h +++ b/src/lib/unlang/unlang_priv.h @@ -183,6 +183,13 @@ typedef unlang_action_t (*unlang_process_t)(rlm_rcode_t *p_result, request_t *re typedef void (*unlang_signal_t)(request_t *request, unlang_stack_frame_t *frame, fr_state_signal_t action); +/** Custom callback for dumping information about frame state + * + * @param[in] request The current request. + * @param[in] frame to provide additional information for. + */ +typedef void (*unlang_dump_t)(request_t *request, unlang_stack_frame_t *frame); + /** An unlang operation * * These are like the opcodes in other interpreters. Each operation, when executed @@ -195,6 +202,8 @@ typedef struct { unlang_signal_t signal; //!< Function to signal stop / dup / whatever + unlang_dump_t dump; //!< Dump additional information about the frame state. + bool debug_braces; //!< Whether the operation needs to print braces ///< in debug mode.