/**
* \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;
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;
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 <i>parameterized</i> to
+ * specify which runtime object it applies to. Use of of tracecut's
+ * <i>bind</i> 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;
}
/**
* 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,
{
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));
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;
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 <code>call_param</code>.
+ * Binding to a <code>call_param</code> 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 <code>call_param</code> 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().
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. */
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);
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);
}
}