From 4eb7e0f80c8bcd3932f54eb5f8c4d15d2b7b2b7c Mon Sep 17 00:00:00 2001 From: Justin Seyster Date: Mon, 7 Feb 2011 18:03:56 -0500 Subject: [PATCH] Events insert advice to capture bound params. --- src/tracecut.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/src/tracecut.c b/src/tracecut.c index 3ee84b1..f3ccbf1 100644 --- a/src/tracecut.c +++ b/src/tracecut.c @@ -377,6 +377,60 @@ tc_free_tracecut (struct tc_tracecut *tc) free(tc); } +/* Add an advice call to the tracecut runtime notifying it that an + event occurred and that _tc_capture_*_param() calls will follow + to specify the event's params. */ +static void +insert_begin_event_advice (struct aop_joinpoint *jp, + struct tc_call_symbol *symbol) +{ + aop_insert_advice (jp, "_tc_event_begin", symbol->location, AOP_TERM_ARG); +} + +/* Add an advice call to _tc_capture_param for each call binding. */ +static void +capture_call_bindings (struct aop_joinpoint *jp, struct tc_call_symbol *symbol) +{ + struct tc_call_binding *binding; + + for (binding = symbol->binding_list; binding != NULL; binding = binding->next) + { + struct aop_dynval *param_val; + const struct aop_type *param_type; + + if (binding->call_param_index >= 0) + param_val = aop_capture_call_param (jp, binding->call_param_index); + else + param_val = aop_capture_call_return_value (jp); + + param_type = aop_get_dynval_type (param_val); + + if (aop_is_pointer_type (param_type)) + { + aop_cast_to_all_pointer (param_val); + aop_insert_advice (jp, "_tc_capture_pointer_param", symbol->location, + AOP_INT_CST (symbol->index), + AOP_INT_CST (binding->param->index), + AOP_DYNVAL (param_val), AOP_TERM_ARG); + } + else + { + /* TODO: Provide support for more kinds of data. */ + aop_assert (0); + } + } +} + +/* Add an advice call to the tracecut runtime, notifying it that it + has all params and should simulate the event transition. */ +static void +insert_transition_event_advice (struct aop_joinpoint *jp, + struct tc_call_symbol *symbol) +{ + aop_insert_advice (jp, "_tc_event_transition", symbol->location, + AOP_INT_CST (symbol->index), AOP_TERM_ARG); +} + struct join_on_call_arg { struct tc_tracecut *tc; struct tc_call_symbol *symbol; @@ -388,8 +442,39 @@ join_on_call (struct aop_joinpoint *jp, void *callback_arg) struct join_on_call_arg *arg = callback_arg; struct tc_call_symbol *symbol = arg->symbol; - aop_insert_advice (jp, "_tc_event_transition", symbol->location, - AOP_INT_CST (symbol->index), AOP_TERM_ARG); + /* Unfortunately, the choice of AOP_INSERT_BEFORE or + AOP_INSERT_AFTER affects the order that inserted advice functions + will execute. */ + if (symbol->location == AOP_INSERT_BEFORE) + { + /* For AOP_INSERT_BEFORE, we insert in the normal order. */ + insert_begin_event_advice (jp, symbol); + capture_call_bindings (jp, symbol); + insert_transition_event_advice (jp, symbol); + } + else + { + /* For AOP_INSERT_AFTER, we insert in the reverse order. */ + insert_transition_event_advice (jp, symbol); + capture_call_bindings (jp, symbol); + insert_begin_event_advice (jp, symbol); + } +} + +static void +filter_call_pointcut_by_bindings (struct aop_pointcut *pc, + struct tc_call_symbol *symbol) +{ + struct tc_call_binding *binding; + + for (binding = symbol->binding_list; binding != NULL; binding = binding->next) + { + if (binding->call_param_index >= 0) + aop_filter_call_pc_by_param (pc, binding->call_param_index, + binding->param->type); + else + aop_filter_call_pc_by_return_type (pc, binding->param->type); + } } static void @@ -404,6 +489,7 @@ add_instrumentation_for_tracecut (struct tc_tracecut *tc) pc = aop_match_function_call (); aop_filter_call_pc_by_name (pc, symbol->func_name); + filter_call_pointcut_by_bindings (pc, symbol); arg.tc = tc; arg.symbol = symbol; -- 2.34.1