Add tracecut params and ability to bind them to call params.
authorJustin Seyster <jseyster@cs.sunysb.edu>
Sat, 5 Feb 2011 00:14:59 +0000 (19:14 -0500)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Sat, 5 Feb 2011 00:14:59 +0000 (19:14 -0500)
src/tracecut.c
src/tracecut.h

index 51c73d0b76ef342cf48c7d39a45cdd2b1b7712c8..b4985dc84bcc168deb9e8f874b108cd7dd449e0e 100644 (file)
 /**
  * \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 <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;
 }
 
 /**
@@ -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 <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().
@@ -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, &param);
+      arg.tc = tc;
+      arg.symbol = symbol;
+      aop_join_on (pc, join_on_call, &arg);
     }
 }
 
index 02996575c592e2b74c5c92f0f97493d2bd2d5820..b9557663741887494e17c25683073e9b0aaa3918 100644 (file)
@@ -40,6 +40,7 @@
  * All tracecut functions have a <code>tc_</code> 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);