fixing leak
[oweals/gnunet.git] / src / monkey / action_api.c
index ff5c59bf9678c67286de9c474d6c8906be4baab0..0412c7630a3c1ca9ee473cef06c3e86fcbe087d5 100644 (file)
 #include "platform.h"
 #include "gnunet_common.h"
 #include "gnunet_monkey_action.h"
+#include "gnunet_monkey_edb.h"
+#include "gnunet_container_lib.h"
 #include <libesmtp.h>
 
 extern void sendMail (const char *messageContents, const char *emailAddress);
 
 
 static int async_c=0;
+static struct Expression *expressionListHead = NULL;
+static struct Expression *expressionListTail = NULL;
 
+struct Expression {
+       struct Expression *next;
+       struct Expression *prev;
+       const char* expressionSyntax;
+       int lineNo;
+};
 
 static void cb_console(const char *str, void *data)
 {
@@ -118,6 +128,103 @@ int GNUNET_MONKEY_ACTION_rerun_with_valgrind()
        return GNUNET_OK;
 }
 
+static int iterateExpressions(void *cls, int numColumns, char **colValues, char **colNames)
+{
+       struct Expression *expression;
+
+       if (NULL == colValues[0] || NULL == colValues[1])
+               return 1; /* Error */
+
+       expression = GNUNET_malloc(sizeof(struct Expression));
+       expression->expressionSyntax = strdup(colValues[0]);
+       expression->lineNo = atoi(colValues[1]);
+
+
+       GNUNET_CONTAINER_DLL_insert(expressionListHead, expressionListTail, expression);
+
+       return 0; /* OK */
+}
+
+
+static int scopeEndCallback(void *cls, int numColumns, char **colValues, char ** colNames)
+{
+       int *scopeEnd = (int*) cls;
+
+       *scopeEnd = atoi(colValues[0]);
+       if (*scopeEnd < 0)
+               return 1; /* Error */
+       return 0;
+}
+
+
+static int analyzeSegmentationFault(struct GNUNET_MONKEY_ACTION_Context *cntxt)
+{
+       struct Expression *faultyExpression;
+       struct Expression *tmp;
+       int expressionLength = 0;
+       mi_wp *watchPoint;
+
+       tmp = expressionListHead;
+       while (NULL != tmp) {
+               if ((tmp->lineNo == cntxt->gdb_frames->line)
+                               && (strlen(tmp->expressionSyntax) > expressionLength)) {
+                       expressionLength = strlen(tmp->expressionSyntax);
+                       faultyExpression = tmp;
+               }
+               tmp = tmp->next;
+       }
+
+       /* Set watch points on the faulty-expression's subexpressions */
+       tmp = expressionListHead;
+       while (NULL != tmp) {
+               if (tmp != faultyExpression) {
+                       /* Only subexpressions are interesting */
+                        watchPoint = gmi_break_watch(cntxt->gdb_handle, wm_write, tmp->expressionSyntax);
+                        if (!watchPoint)
+                          {
+                           printf("Error in setting watchpoint\n");
+                           return 1;
+                          }
+                        printf("Watchpoint %d for expression: %s\n", watchPoint->number, watchPoint->exp);
+                        mi_free_wp(watchPoint);
+               }
+               tmp = tmp->next;
+       }
+       return GNUNET_OK;
+}
+
+
+int GNUNET_MONKEY_ACTION_inspect_expression_database(struct GNUNET_MONKEY_ACTION_Context *cntxt)
+{
+       struct GNUNET_MONKEY_EDB_Context *edbCntxt;
+       int ret = GNUNET_OK;
+       int endScope;
+
+       edbCntxt = GNUNET_MONKEY_EDB_connect(cntxt->expression_database_path);
+       if (NULL == edbCntxt) {
+               GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Unable to connect to Expression Database file!\n");
+               return GNUNET_NO;
+       }
+
+       ret = GNUNET_MONKEY_EDB_get_expression_scope_end(edbCntxt,
+                                          cntxt->gdb_frames->file, cntxt->gdb_frames->line,
+                                          &scopeEndCallback, &endScope);
+       if (endScope < 0)
+               return GNUNET_NO;
+
+       ret = GNUNET_MONKEY_EDB_get_expressions (edbCntxt,
+                                          cntxt->gdb_frames->file, cntxt->gdb_frames->line,
+                                          endScope,
+                                          &iterateExpressions,
+                                          NULL);
+
+       if (strcasecmp(cntxt->gdb_stop_reason->signal_meaning, "Segmentation fault") == 0)
+               analyzeSegmentationFault(cntxt);
+
+       GNUNET_MONKEY_EDB_disconnect(edbCntxt);
+       return ret;
+}
+
 
 int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cntxt)
 {
@@ -125,13 +232,13 @@ int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cnt
 
        /* This is like a file-handle for fopen.
            Here we have all the state of gdb "connection". */
-       mi_set_gdb_exe("/tmp/gdb/bin/gdb");
-       mi_h *h;
+       if (NULL != cntxt->gdb_binary_path)
+               mi_set_gdb_exe(cntxt->gdb_binary_path);
        int ret;
 
         /* Connect to gdb child. */
-        h = mi_connect_local();
-        if (!h)
+       cntxt->gdb_handle = mi_connect_local();
+        if (!cntxt->gdb_handle)
           {
            printf("Connect failed\n");
            return GNUNET_NO;
@@ -139,40 +246,40 @@ int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cnt
         printf("Connected to gdb!\n");
 
         /* Set all callbacks. */
-        mi_set_console_cb(h,cb_console,NULL);
-        mi_set_target_cb(h,cb_target,NULL);
-        mi_set_log_cb(h,cb_log,NULL);
-        mi_set_async_cb(h,cb_async,NULL);
-        mi_set_to_gdb_cb(h,cb_to,NULL);
-        mi_set_from_gdb_cb(h,cb_from,NULL);
-
-        /* Set the name of the child and the command line aguments. */
-        if (!gmi_set_exec(h, cntxt->binary_name, NULL))
+        mi_set_console_cb(cntxt->gdb_handle,cb_console,NULL);
+        mi_set_target_cb(cntxt->gdb_handle,cb_target,NULL);
+        mi_set_log_cb(cntxt->gdb_handle,cb_log,NULL);
+        mi_set_async_cb(cntxt->gdb_handle,cb_async,NULL);
+        mi_set_to_gdb_cb(cntxt->gdb_handle,cb_to,NULL);
+        mi_set_from_gdb_cb(cntxt->gdb_handle,cb_from,NULL);
+
+        /* Set the name of the child and the command line arguments. */
+        if (!gmi_set_exec(cntxt->gdb_handle, cntxt->binary_name, NULL))
           {
            printf("Error setting exec y args\n");
-           mi_disconnect(h);
+           mi_disconnect(cntxt->gdb_handle);
            return GNUNET_NO;
           }
 
         /* Tell gdb to attach the child to a terminal. */
-        if (!gmi_target_terminal(h, ttyname(STDIN_FILENO)))
+        if (!gmi_target_terminal(cntxt->gdb_handle, ttyname(STDIN_FILENO)))
           {
            printf("Error selecting target terminal\n");
-           mi_disconnect(h);
+           mi_disconnect(cntxt->gdb_handle);
            return GNUNET_NO;
           }
 
         /* Run the program. */
-        if (!gmi_exec_run(h))
+        if (!gmi_exec_run(cntxt->gdb_handle))
           {
            printf("Error in run!\n");
-           mi_disconnect(h);
+           mi_disconnect(cntxt->gdb_handle);
            return GNUNET_NO;
           }
         /* Here we should be stopped when the program crashes */
-        ret = wait_for_stop(h, cntxt);
+        ret = wait_for_stop(cntxt->gdb_handle, cntxt);
         if (ret != GDB_STATE_ERROR)
-           mi_disconnect(h);
+           mi_disconnect(cntxt->gdb_handle);
 
        return ret;
 }