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;
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
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;