From: Justin Seyster Date: Sat, 5 Feb 2011 00:14:59 +0000 (-0500) Subject: Add tracecut params and ability to bind them to call params. X-Git-Tag: release-v1.1~9^2~32 X-Git-Url: https://git.fsl.cs.stonybrook.edu/?a=commitdiff_plain;h=dc1af846d4ad78b40af1da2bad17b503e09b215b;p=interaspect.git Add tracecut params and ability to bind them to call params. --- diff --git a/src/tracecut.c b/src/tracecut.c index 51c73d0..b4985dc 100644 --- a/src/tracecut.c +++ b/src/tracecut.c @@ -42,6 +42,25 @@ /** * \cond HIDDEN_SYMBOLS */ +struct tc_param { + const char *name; + int index; + + const struct aop_type *type; + + struct tc_param *next; +}; + +struct tc_call_binding { + /* The index of the call_param we should bind to. A value of -1 + means bind to the return value instead of a call_param. */ + int call_param_index; + + struct tc_param *param; + + struct tc_call_binding *next; +}; + struct tc_call_symbol { const char *name; int index; @@ -49,12 +68,18 @@ struct tc_call_symbol { const char *func_name; enum aop_insert_location location; + struct tc_call_binding *binding_list; + struct tc_call_symbol *next; }; struct tc_tracecut { + struct tc_param *param_list; struct tc_call_symbol *symbol_list; + /* Each param gets a unique index. */ + int next_param_index; + /* Each symbol gets a unique index. */ int next_symbol_index; @@ -73,19 +98,81 @@ struct tc_tracecut { main tracecut pass has access to them. */ static struct tc_tracecut *tracecut_list = NULL; -static int -symbol_exists (struct tc_tracecut *tc, const char *name) +static struct tc_param * +lookup_param (struct tc_tracecut *tc, const char *name) +{ + struct tc_param *param; + + for (param = tc->param_list; param != NULL; param = param->next) + { + if (strcmp (name, param->name) == 0) + return param; /* Found it. */ + } + + /* We did not find a param with the given name. */ + return NULL; +} + +/** + * Add a new tracecut parameter. Each tracecut tracks several + * objects, so a tracecut event must be parameterized to + * specify which runtime object it applies to. Use of of tracecut's + * bind functions to bind a tracecut param to an actual runtime + * value captured by InterAspect. + * \param tc The tracecut to add a param to. + * \param name The name used to reference this param. + * \param type They type of this param. + * \return #TC_SUCCESS or + * - #TC_BAD_CONTEXT, when called after compilation has already + * started; + * - #TC_DUPLICATE, if there already exists a param with the + * specified name; + * - #TC_NOMEM, if memory runs out. + */ +enum tc_error +tc_add_param (struct tc_tracecut *tc, const char *name, + const struct aop_type *type) +{ + struct tc_param *param = NULL; + + if (lookup_param (tc, name) != NULL) + return TC_DUPLICATE;; + + param = (struct tc_param *)malloc (sizeof (struct tc_param)); + if (param == NULL) + goto nomem; + + param->name = strdup (name); + if (param->name == NULL) + goto nomem; + + param->index = tc->next_param_index++; + param->type = type; + + /* Insert this new param into the list of params. */ + param->next = tc->param_list; + tc->param_list = param; + + return TC_SUCCESS; + + nomem: + free (param); + return TC_NOMEM; +} + +static struct tc_call_symbol * +lookup_call_symbol (struct tc_tracecut *tc, const char *name) { struct tc_call_symbol *symbol; for (symbol = tc->symbol_list; symbol != NULL; symbol = symbol->next) { if (strcmp (name, symbol->name) == 0) - return 1; /* Found it. */ + return symbol; /* Found it. */ } /* We did not find a symbol with the given name. */ - return 0; + return NULL; } /** @@ -103,6 +190,12 @@ symbol_exists (struct tc_tracecut *tc, const char *name) * new symbol's event. * \param location Specifies whether the the symbol event should * trigger before or after the specified function is called. + * \return #TC_SUCCESS or + * - #TC_BAD_CONTEXT, when called after compilation has already + * started; + * - #TC_DUPLICATE, if there already exists a symbol with the + * specified name; + * - #TC_NOMEM, if memory runs out. */ enum tc_error tc_add_call_symbol (struct tc_tracecut *tc, const char *name, @@ -110,7 +203,7 @@ tc_add_call_symbol (struct tc_tracecut *tc, const char *name, { struct tc_call_symbol *symbol = NULL; - if (symbol_exists (tc, name)) + if (lookup_call_symbol (tc, name) != NULL) return TC_DUPLICATE;; symbol = (struct tc_call_symbol *)malloc (sizeof (struct tc_call_symbol)); @@ -124,6 +217,7 @@ tc_add_call_symbol (struct tc_tracecut *tc, const char *name, symbol->index = tc->next_symbol_index++; symbol->location = location; + symbol->binding_list = NULL; /* Insert this new symbol into the list of call symbols. */ symbol->next = tc->symbol_list; @@ -141,6 +235,79 @@ tc_add_call_symbol (struct tc_tracecut *tc, const char *name, return TC_NOMEM; } +static enum tc_error +add_call_symbol_binding (struct tc_tracecut *tc, const char *param_name, + const char *symbol_name, int index) +{ + struct tc_param *param; + struct tc_call_symbol *symbol; + struct tc_call_binding *binding; + + param = lookup_param (tc, param_name); + symbol = lookup_call_symbol (tc, symbol_name); + if (param == NULL || symbol == NULL) + return TC_NOENT; + + binding = (struct tc_call_binding *)malloc (sizeof (struct tc_call_binding)); + if (binding == NULL) + return TC_NOMEM; + + binding->call_param_index = index; + binding->param = param; + + /* Add this binding to the list of bindings for this symbol. */ + binding->next = symbol->binding_list; + symbol->binding_list = binding; + + return TC_SUCCESS; +} + +/** + * Bind a tracecut param to a call symbol's call_param. + * Binding to a call_param will capture that parameter at + * runtime. + * \param tc The tracecut to add a binding to. + * \param param_name Name of the tracecut param to bind. + * \param symbol_name Name of the call symbol to bind to. + * \param call_param_index Index of the call_param to + * bind to (starting from 0). + * \return #TC_SUCCESS or + * - #TC_BAD_CONTEXT, when called after compilation has already + * started; + * - #TC_INVAL, if call_param_index is negative; + * - #TC_NOENT, if either the symbol or the binding does not exist; + * - #TC_NOMEM, if memory runs out. + */ +enum tc_error +tc_bind_to_call_param (struct tc_tracecut *tc, const char *param_name, + const char *symbol_name, int call_param_index) +{ + if (call_param_index < 0) + return TC_INVAL; + + return add_call_symbol_binding (tc, param_name, symbol_name, + call_param_index); +} + +/** + * Bind a tracecut param to a call symbol's return value. Binding to + * return value will capture that return value at runtime. + * \param tc The tracecut to add a binding to. + * \param param_name Name of the tracecut param to bind. + * \param symbol_name Name of the call symbol to bind to. + * \return #TC_SUCCESS or + * - #TC_BAD_CONTEXT, when called after compilation has already + * started; + * - #TC_NOENT, if either the symbol or the binding does not exist; + * - #TC_NOMEM, if memory runs out. + */ +enum tc_error +tc_bind_to_return_value (struct tc_tracecut *tc, const char *param_name, + const char *symbol_name) +{ + return add_call_symbol_binding (tc, param_name, symbol_name, -1); +} + /** * Create an empty tc_tracecut object. The caller is responsible for * freeing the object using tc_free_tracecut(). @@ -157,7 +324,9 @@ tc_create_tracecut (void) if (tc == NULL) return NULL; + tc->next_param_index = 0; tc->next_symbol_index = 0; + tc->param_list = NULL; tc->symbol_list = NULL; /* Insert this tracecut into the master list. */ @@ -199,16 +368,16 @@ tc_free_tracecut (struct tc_tracecut *tc) free(tc); } -struct join_on_call_param { +struct join_on_call_arg { struct tc_tracecut *tc; struct tc_call_symbol *symbol; }; static void -join_on_call (struct aop_joinpoint *jp, void *callback_param) +join_on_call (struct aop_joinpoint *jp, void *callback_arg) { - struct join_on_call_param *param = callback_param; - struct tc_call_symbol *symbol = param->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); @@ -221,15 +390,15 @@ add_instrumentation_for_tracecut (struct tc_tracecut *tc) for (symbol = tc->symbol_list; symbol != NULL; symbol = symbol->next) { - struct join_on_call_param param; + struct join_on_call_arg arg; struct aop_pointcut *pc; pc = aop_match_function_call (); aop_filter_call_pc_by_name (pc, symbol->func_name); - param.tc = tc; - param.symbol = symbol; - aop_join_on (pc, join_on_call, ¶m); + arg.tc = tc; + arg.symbol = symbol; + aop_join_on (pc, join_on_call, &arg); } } diff --git a/src/tracecut.h b/src/tracecut.h index 0299657..b955766 100644 --- a/src/tracecut.h +++ b/src/tracecut.h @@ -40,6 +40,7 @@ * All tracecut functions have a tc_ prefix. */ +struct aop_type; struct tc_tracecut; /** @@ -57,6 +58,11 @@ enum tc_error { */ TC_BAD_CONTEXT, + /** + * An input to the function was invalid. + */ + TC_INVAL, + /** * Attempt to create a duplicate name. */ @@ -73,11 +79,22 @@ enum tc_error { TC_NOMEM, }; +extern enum tc_error tc_add_param (struct tc_tracecut *tc, const char *name, + const struct aop_type *type); + extern enum tc_error tc_add_call_symbol (struct tc_tracecut *tc, const char *name, const char *func_name, enum aop_insert_location location); +enum tc_error tc_bind_to_call_param (struct tc_tracecut *tc, + const char *param_name, + const char *symbol_name, + int call_param_index); +enum tc_error tc_bind_to_return_value (struct tc_tracecut *tc, + const char *param_name, + const char *symbol_name); + extern struct tc_tracecut *tc_create_tracecut (void); extern void tc_free_tracecut (struct tc_tracecut *tc);