Pass a tracecut index with each advice call.
authorJustin Seyster <jseyster@cs.sunysb.edu>
Tue, 8 Feb 2011 02:48:26 +0000 (21:48 -0500)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Tue, 8 Feb 2011 02:48:26 +0000 (21:48 -0500)
Fail with TC_BAD_CONTEXT when tracecut calls occur after compilation
starts.

src/tracecut.c

index f3ccbf1d1333eb35068980843f990bba1fecfd21..1c44509a318fb2cb071a4c412def5f253b2f3761 100644 (file)
@@ -74,6 +74,8 @@ struct tc_call_symbol {
 };
 
 struct tc_tracecut {
+  int index;
+
   struct tc_param *param_list;
   struct tc_call_symbol *symbol_list;
 
@@ -98,6 +100,10 @@ struct tc_tracecut {
    main tracecut pass has access to them. */
 static struct tc_tracecut *tracecut_list = NULL;
 
+/* This is true once actual compilation passes start, making it
+   illegal to modify any existing tracecut objects. */
+static int tc_in_compilation = 0;
+
 static struct tc_param *
 lookup_param (struct tc_tracecut *tc, const char *name)
 {
@@ -141,6 +147,9 @@ tc_add_param (struct tc_tracecut *tc, const char *name,
 {
   struct tc_param *param = NULL;
 
+  if (tc_in_compilation)
+    return TC_BAD_CONTEXT;
+
   if (!aop_is_pointer_type (type))
     return TC_INVAL;
 
@@ -212,6 +221,9 @@ tc_add_call_symbol (struct tc_tracecut *tc, const char *name,
 {
   struct tc_call_symbol *symbol = NULL;
 
+  if (tc_in_compilation)
+    return TC_BAD_CONTEXT;
+
   if (lookup_call_symbol (tc, name) != NULL)
     return TC_DUPLICATE;;
 
@@ -291,6 +303,9 @@ 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 (tc_in_compilation)
+    return TC_BAD_CONTEXT;
+
   if (call_param_index < 0)
     return TC_INVAL;
 
@@ -314,25 +329,34 @@ enum tc_error
 tc_bind_to_return_value (struct tc_tracecut *tc, const char *param_name,
                         const char *symbol_name)
 {
+  if (tc_in_compilation)
+    return TC_BAD_CONTEXT;
+
   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().
+ * freeing the object using tc_free_tracecut().  (Do not use the
+ * standard free function.)
  * \return A new tc_tracecut that must be freed with
- * tc_free_tracecut().  The return value can be NULL if allocation
- * fails.
+ * tc_free_tracecut().  The return value will be NULL if allocation
+ * fails or if compilation has already started..
  */
 struct tc_tracecut *
 tc_create_tracecut (void)
 {
   struct tc_tracecut *tc;
 
+  /* Illegal to create a tracecut once compilation has begun. */
+  if (tc_in_compilation)
+    return NULL;
+
   tc = (struct tc_tracecut *)malloc (sizeof (struct tc_tracecut));
   if (tc == NULL)
     return NULL;
 
+  tc->index = -1;
   tc->next_param_index = 0;
   tc->next_symbol_index = 0;
   tc->param_list = NULL;
@@ -377,19 +401,33 @@ tc_free_tracecut (struct tc_tracecut *tc)
   free(tc);
 }
 
+/* Go through the master list of tracecuts and give each a consecutive
+   index. */
+static void
+assign_tracecut_indices ()
+{
+  int next_tracecut_index = 0;
+  struct tc_tracecut *tc;
+
+  for (tc = tracecut_list; tc != NULL; tc = tc->next)
+    tc->index = next_tracecut_index++;
+}
+
 /* 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,
+insert_begin_event_advice (struct aop_joinpoint *jp, int tc_index,
                           struct tc_call_symbol *symbol)
 {
-  aop_insert_advice (jp, "_tc_event_begin", symbol->location, AOP_TERM_ARG);
+  aop_insert_advice (jp, "_tc_event_begin", symbol->location,
+                    AOP_INT_CST (tc_index), 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)
+capture_call_bindings (struct aop_joinpoint *jp, int tc_index,
+                      struct tc_call_symbol *symbol)
 {
   struct tc_call_binding *binding;
 
@@ -409,6 +447,7 @@ capture_call_bindings (struct aop_joinpoint *jp, struct tc_call_symbol *symbol)
        {
          aop_cast_to_all_pointer (param_val);
          aop_insert_advice (jp, "_tc_capture_pointer_param", symbol->location,
+                            AOP_INT_CST (tc_index),
                             AOP_INT_CST (symbol->index),
                             AOP_INT_CST (binding->param->index),
                             AOP_DYNVAL (param_val), AOP_TERM_ARG);
@@ -424,11 +463,12 @@ capture_call_bindings (struct aop_joinpoint *jp, struct tc_call_symbol *symbol)
 /* 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,
+insert_transition_event_advice (struct aop_joinpoint *jp, int tc_index,
                                struct tc_call_symbol *symbol)
 {
   aop_insert_advice (jp, "_tc_event_transition", symbol->location,
-                    AOP_INT_CST (symbol->index), AOP_TERM_ARG);
+                    AOP_INT_CST (tc_index), AOP_INT_CST (symbol->index),
+                    AOP_TERM_ARG);
 }
 
 struct join_on_call_arg {
@@ -440,24 +480,27 @@ static void
 join_on_call (struct aop_joinpoint *jp, void *callback_arg)
 {
   struct join_on_call_arg *arg = callback_arg;
+  struct tc_tracecut *tc = arg->tc;
   struct tc_call_symbol *symbol = arg->symbol;
 
+  int tc_index = tc->index;
+
   /* 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);
+      insert_begin_event_advice (jp, tc_index, symbol);
+      capture_call_bindings (jp, tc_index, symbol);
+      insert_transition_event_advice (jp, tc_index, 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);
+      insert_transition_event_advice (jp, tc_index, symbol);
+      capture_call_bindings (jp, tc_index, symbol);
+      insert_begin_event_advice (jp, tc_index, symbol);
     }
 }
 
@@ -502,6 +545,15 @@ tracecut_pass (void)
 {
   struct tc_tracecut *tc;
 
+  if (!tc_in_compilation)
+    {
+      /* Choose an index for every tracecut object.  After that,
+        tracecut objects are frozen because setting tc_in_compilation
+        to true makes it illegal to modify them. */
+      assign_tracecut_indices ();
+      tc_in_compilation = 1;
+    }
+
   for (tc = tracecut_list; tc != NULL; tc = tc->next)
     add_instrumentation_for_tracecut (tc);