From: Justin Seyster Date: Fri, 4 Feb 2011 21:17:11 +0000 (-0500) Subject: Add tracecut pass that can instrument events reference in tracecuts. X-Git-Tag: release-v1.1~9^2~33 X-Git-Url: https://git.fsl.cs.stonybrook.edu/?a=commitdiff_plain;h=857e462536d0b7a1302df1967d26bcd7527ce195;p=interaspect.git Add tracecut pass that can instrument events reference in tracecuts. Add error return codes. --- diff --git a/src/tracecut.c b/src/tracecut.c index f7cb7d1..51c73d0 100644 --- a/src/tracecut.c +++ b/src/tracecut.c @@ -44,7 +44,10 @@ */ struct tc_call_symbol { const char *name; + int index; + const char *func_name; + enum aop_insert_location location; struct tc_call_symbol *next; }; @@ -52,6 +55,9 @@ struct tc_call_symbol { struct tc_tracecut { struct tc_call_symbol *symbol_list; + /* Each symbol gets a unique index. */ + int next_symbol_index; + struct tc_tracecut *next; }; /** @@ -98,35 +104,49 @@ symbol_exists (struct tc_tracecut *tc, const char *name) * \param location Specifies whether the the symbol event should * trigger before or after the specified function is called. */ -void +enum tc_error tc_add_call_symbol (struct tc_tracecut *tc, const char *name, const char *func_name, enum aop_insert_location location) { - struct tc_call_symbol *symbol; + struct tc_call_symbol *symbol = NULL; if (symbol_exists (tc, name)) - { - fprintf (stderr, "(Tracecut) Ignoring duplicate symbol: %s\n", name); - return; - } + return TC_DUPLICATE;; symbol = (struct tc_call_symbol *)malloc (sizeof (struct tc_call_symbol)); - aop_assert (symbol != NULL); + if (symbol == NULL) + goto nomem; symbol->name = strdup (name); symbol->func_name = strdup (func_name); - aop_assert (symbol->name != NULL && symbol->func_name != NULL); + if (symbol->name == NULL || symbol->func_name == NULL) + goto nomem; + + symbol->index = tc->next_symbol_index++; + symbol->location = location; /* Insert this new symbol into the list of call symbols. */ symbol->next = tc->symbol_list; tc->symbol_list = symbol; + + return TC_SUCCESS; + + nomem: + if (symbol != NULL) + { + free ((char *)symbol->name); + free ((char *)symbol->func_name); + free (symbol); + } + return TC_NOMEM; } /** * Create an empty tc_tracecut object. The caller is responsible for * freeing the object using tc_free_tracecut(). * \return A new tc_tracecut that must be freed with - * tc_free_tracecut(). + * tc_free_tracecut(). The return value can be NULL if allocation + * fails. */ struct tc_tracecut * tc_create_tracecut (void) @@ -134,10 +154,16 @@ tc_create_tracecut (void) struct tc_tracecut *tc; tc = (struct tc_tracecut *)malloc (sizeof (struct tc_tracecut)); - aop_assert (tc != NULL); + if (tc == NULL) + return NULL; + tc->next_symbol_index = 0; tc->symbol_list = NULL; + /* Insert this tracecut into the master list. */ + tc->next = tracecut_list; + tracecut_list = tc; + return tc; } @@ -160,7 +186,7 @@ remove_tracecut_from_list (struct tc_tracecut *tc) } /** - * Free all the memory used by a tc_object. Every call to + * Free all the memory used by a tc_tracecut object. Every call to * tc_create_tracecut() should have a matching call to * tc_free_tracecut(). * \param tc The tracecut object to free. @@ -173,6 +199,57 @@ tc_free_tracecut (struct tc_tracecut *tc) free(tc); } +struct join_on_call_param { + struct tc_tracecut *tc; + struct tc_call_symbol *symbol; +}; + +static void +join_on_call (struct aop_joinpoint *jp, void *callback_param) +{ + struct join_on_call_param *param = callback_param; + struct tc_call_symbol *symbol = param->symbol; + + aop_insert_advice (jp, "_tc_event_transition", symbol->location, + AOP_INT_CST (symbol->index), AOP_TERM_ARG); +} + +static void +add_instrumentation_for_tracecut (struct tc_tracecut *tc) +{ + struct tc_call_symbol *symbol; + + for (symbol = tc->symbol_list; symbol != NULL; symbol = symbol->next) + { + struct join_on_call_param param; + 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); + } +} + +static unsigned int +tracecut_pass (void) +{ + struct tc_tracecut *tc; + + for (tc = tracecut_list; tc != NULL; tc = tc->next) + add_instrumentation_for_tracecut (tc); + + return 0; +} + +void +tc_register_tracecut_pass (void) +{ + aop_register_pass ("tracecut", tracecut_pass); +} + /* Close Doxygen defgroup block. */ /** * \} diff --git a/src/tracecut.h b/src/tracecut.h index c492e39..0299657 100644 --- a/src/tracecut.h +++ b/src/tracecut.h @@ -42,11 +42,45 @@ struct tc_tracecut; -extern void tc_add_call_symbol (struct tc_tracecut *tc, const char *name, - const char *func_name, - enum aop_insert_location location); +/** + * Possible error return values for tracecut functions. + */ +enum tc_error { + /** + * No error: the function succeeded. + */ + TC_SUCCESS, + + /** + * Function was called from an inappropriate context. Most tracecut + * functions should be called from your aop_main() function. + */ + TC_BAD_CONTEXT, + + /** + * Attempt to create a duplicate name. + */ + TC_DUPLICATE, + + /** + * Attempt to reference a name that does not exist. + */ + TC_NOENT, + + /** + * Function could not allocate enough memory. + */ + TC_NOMEM, +}; + +extern enum tc_error tc_add_call_symbol (struct tc_tracecut *tc, + const char *name, + const char *func_name, + enum aop_insert_location location); extern struct tc_tracecut *tc_create_tracecut (void); extern void tc_free_tracecut (struct tc_tracecut *tc); +extern void tc_register_tracecut_pass (void); + #endif