[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r26063 - monkey/trunk/pathologist/src/pathologist
From: |
gnunet |
Subject: |
[GNUnet-SVN] r26063 - monkey/trunk/pathologist/src/pathologist |
Date: |
Mon, 11 Feb 2013 10:49:40 +0100 |
Author: teichm
Date: 2013-02-11 10:49:40 +0100 (Mon, 11 Feb 2013)
New Revision: 26063
Added:
monkey/trunk/pathologist/src/pathologist/action.c
monkey/trunk/pathologist/src/pathologist/action.h
Removed:
monkey/trunk/pathologist/src/pathologist/action_api.c
monkey/trunk/pathologist/src/pathologist/pathologist_action.h
Modified:
monkey/trunk/pathologist/src/pathologist/Makefile.am
monkey/trunk/pathologist/src/pathologist/pathologist.c
Log:
refactored: no more librarys, merged them to one binary to rule them all
Modified: monkey/trunk/pathologist/src/pathologist/Makefile.am
===================================================================
--- monkey/trunk/pathologist/src/pathologist/Makefile.am 2013-02-11
08:49:40 UTC (rev 26062)
+++ monkey/trunk/pathologist/src/pathologist/Makefile.am 2013-02-11
09:49:40 UTC (rev 26063)
@@ -1,12 +1,12 @@
INCLUDES = -I$(top_srcdir)/src/include
if MINGW
- WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+ WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
endif
if USE_COVERAGE
- AM_CFLAGS = --coverage -O0
- XLIB = -lgcov
+ AM_CFLAGS = --coverage -O0
+ XLIB = -lgcov
endif
@@ -14,57 +14,26 @@
if HAVE_ESMTP
if HAVE_OPENSSL
-
-lib_LTLIBRARIES = libpathologistedb.la \
- libpathologistaction.la \
- libpathologistxml.la
-
-libpathologistedb_la_SOURCES = \
- edb_api.c \
- pathologist_edb.h
-
-libpathologistedb_la_LIBADD = \
- $(top_builddir)/src/util/libpathologistutil.la \
- -lsqlite3 \
- $(XLIB)
-
-libpathologistaction_la_SOURCES = \
- action_api.c \
- pathologist_action.h
-
-libpathologistaction_la_LIBADD = \
- $(top_builddir)/src/mi/libmi.la \
- $(top_builddir)/src/pathologist/libpathologistedb.la \
- $(top_builddir)/src/util/libpathologistutil.la \
- $(XLIB)
-
-libpathologistxml_la_SOURCES = \
- xml_writer.c \
- pathologist_xml_writer.h
-
-libpathologistxml_la_LIBADD = \
- $(top_builddir)/src/util/libpathologistutil.la \
- $(XLIB)
-
bin_PROGRAMS = \
- pathologist
+ pathologist
pathologist_SOURCES = \
- pathologist.c \
- getopt.c \
- getopt_helpers.c \
- mail_sender.c
+ pathologist.c \
+ getopt.c \
+ getopt_helpers.c \
+ mail_sender.c \
+ action.c \
+ xml_writer.c \
+ edb_api.c
pathologist_LDADD = \
- $(top_builddir)/src/mi/libmi.la \
- $(top_builddir)/src/util/libpathologistutil.la \
- $(top_builddir)/src/pathologist/libpathologistedb.la \
- $(top_builddir)/src/pathologist/libpathologistaction.la \
- $(top_builddir)/src/pathologist/libpathologistxml.la \
- -lesmtp \
- $(GN_LIBINTL)
+ $(top_builddir)/src/mi/libmi.la \
+ $(top_builddir)/src/util/libpathologistutil.la \
+ -lesmtp \
+ -lsqlite3 \
+ $(XLIB) \
+ $(GN_LIBINTL)
-
if ENABLE_TEST_RUN
if SEASPIDER
TESTS = $(check_PROGRAMS)
@@ -72,15 +41,16 @@
endif
check_PROGRAMS = \
- test_pathologist
+ test_pathologist
test_pathologist_SOURCES = \
- test_pathologist.c
+ test_pathologist.c
+
test_pathologist_LDADD = \
- $(top_builddir)/src/minixml/libminixml.la
+ $(top_builddir)/src/minixml/libminixml.la
EXTRA_DIST = \
- ../../refs
+ ../../refs
endif
Added: monkey/trunk/pathologist/src/pathologist/action.c
===================================================================
--- monkey/trunk/pathologist/src/pathologist/action.c
(rev 0)
+++ monkey/trunk/pathologist/src/pathologist/action.c 2013-02-11 09:49:40 UTC
(rev 26063)
@@ -0,0 +1,1115 @@
+
+#include "monkey_common.h"
+#include "action.h"
+#include "pathologist_edb.h"
+#include "pathologist_xml_writer.h"
+#include <libesmtp.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+extern void sendMail(const char *messageContents, const char *reportFileName,
+ const char *emailAddress);
+
+static int crashExpressionFoundInEDB = MONKEY_YES;
+static int async_c = 0;
+static int stoppedInSharedLib = MONKEY_NO;
+static int failureFunctionStartLine = 0; // start line number of the
function in which the failure occurs
+static struct WatchInfo *watchInfoListHead = NULL;
+static struct WatchInfo *watchInfoListTail = NULL;
+static struct FileName *fileNameListHead = NULL;
+static struct FileName *fileNameListTail = NULL;
+static struct ScopeEnd *scopeEndListHead = NULL;
+static struct ScopeEnd *scopeEndListTail = NULL;
+
+
+struct ScopeEnd {
+ struct ScopeEnd *next;
+ struct ScopeEnd *prev;
+
+ int lineNo;
+};
+
+
+struct FileName {
+ struct FileName *next;
+ struct FileName *prev;
+
+ const char *name;
+};
+
+
+struct Expression {
+ struct Expression *next;
+ struct Expression *prev;
+ const char *expressionSyntax;
+ const char *expressionValue;
+ int isCall;
+};
+
+
+struct Function {
+ struct Function *next;
+ struct Function *prev;
+ const char *name;
+ const char *file;
+ int line;
+ int depth;
+ struct Expression *expressionListHead;
+ struct Expression *expressionListTail;
+};
+
+struct Trace {
+ struct Trace *next;
+ struct Trace *prev;
+ struct Function *functionListHead;
+ struct Function *functionListTail;
+ struct Expression *globalsListHead;
+ struct Expression *globalsListTail;
+};
+
+
+struct Epoch {
+ struct Trace *traceListHead;
+ struct Trace *traceListTail;
+} *epoch;
+
+struct WatchInfo {
+ struct WatchInfo *next;
+ struct WatchInfo *prev;
+ int hitNumber;
+ const char *value;
+};
+
+
+static void cb_console(const char *str, void *data)
+{
+ printf("CONSOLE> %s\n", str);
+}
+
+
+/* Note that unlike what's documented in gdb docs it isn't usable. */
+static void cb_target(const char *str, void *data)
+{
+ printf("TARGET> %s\n", str);
+}
+
+
+static void cb_log(const char *str, void *data)
+{
+ printf("LOG> %s\n", str);
+}
+
+
+static void cb_to(const char *str, void *data)
+{
+ printf(">> %s", str);
+}
+
+
+static void cb_from(const char *str, void *data)
+{
+ printf("<< %s\n", str);
+}
+
+
+static void cb_async(mi_output * o, void *data)
+{
+ printf("ASYNC\n");
+ async_c++;
+}
+
+static int isInCodeBase(const char *name)
+{
+ struct FileName *fileName = fileNameListHead;
+ while (fileName) {
+ if (strcmp(fileName->name, name) == 0)
+ return MONKEY_YES;
+ fileName = fileName->next;
+ }
+ return MONKEY_NO;
+}
+
+
+static int wait_for_stop(struct MONKEY_ACTION_Context *cntxt)
+{
+ static int safetyCount = 0;
+
+ while (!mi_get_response(cntxt->gdb_handle))
+ usleep(GDB_MI_ASYNC_WAIT);
+ /* The end of the async. */
+
+ cntxt->gdb_stop_reason = mi_res_stop(cntxt->gdb_handle);
+
+ if (cntxt->gdb_stop_reason) {
+ safetyCount = 0; // reset the Safety Count whenever you
stop for a meaningful reason
+
+ switch (cntxt->gdb_stop_reason->reason) {
+ case sr_exited_normally:
+ return GDB_STATE_EXIT_NORMALLY;
+ case sr_signal_received:
+ //gmi_set_unwind_on_signal_on(cntxt->gdb_handle);
// Program crashed. From now on preserve stack on any further received signals
+ break;
+ case sr_bkpt_hit:
+ {
+ /* continue execution */
+ gmi_exec_continue(cntxt->gdb_handle);
+ return wait_for_stop(cntxt);
+ }
+ case sr_wp_trigger:
+ {
+ /* Execution stopped because of hitting a watch point */
+ static int watchPointHitNumber = 0;
+ struct WatchInfo *watchInfo =
+ MONKEY_malloc(sizeof(struct WatchInfo));
+ watchInfo->hitNumber = ++watchPointHitNumber;
+ watchInfo->value = cntxt->gdb_stop_reason->wp_val;
+ MONKEY_CONTAINER_DLL_insert(watchInfoListHead,
+ watchInfoListTail,
watchInfo);
+ if (watchPointHitNumber == 1023)
+ printf("HEY! 1023! WE ARE GETTING OUT OF THE
LOOP!\n");
+ gmi_exec_continue(cntxt->gdb_handle);
+ return wait_for_stop(cntxt);
+ }
+ case sr_wp_scope:
+ gmi_exec_continue(cntxt->gdb_handle);
+ return wait_for_stop(cntxt);
+ default:
+ break;
+ }
+
+ /* Reaching this line means that the program has stopped
abnormally OR we are in backtracking mode, and it's a step backward */
+ cntxt->gdb_frames = gmi_stack_list_frames(cntxt->gdb_handle);
+ while ((NULL != cntxt->gdb_frames) && (NULL ==
cntxt->gdb_frames->file)) {
+ cntxt->gdb_frames = cntxt->gdb_frames->next;
+ }
+
+ if ((NULL != cntxt->gdb_frames) && (MONKEY_YES !=
isInCodeBase(cntxt->gdb_frames->file))) {
+ do {
+ cntxt->gdb_frames = cntxt->gdb_frames->next;
+ } while ((NULL != cntxt->gdb_frames) && (MONKEY_YES !=
isInCodeBase(cntxt->gdb_frames->file)));
+
+ if ((NULL != cntxt->gdb_frames) && (MONKEY_YES ==
cntxt->run_reverse)) {
+ /* We are in backtracking mode, we need to move
GDB from the shared library to our source code */
+ stoppedInSharedLib = MONKEY_YES;
+ gmi_break_insert(cntxt->gdb_handle,
cntxt->gdb_frames->file,
+ cntxt->gdb_frames->line);
+ gmi_exec_continue_reverse(cntxt->gdb_handle);
+ while (!mi_get_response(cntxt->gdb_handle))
+ usleep(GDB_MI_ASYNC_WAIT);
+ cntxt->gdb_frames =
gmi_stack_list_frames(cntxt->gdb_handle);
+ }
+ }
+
+ if (NULL == cntxt->gdb_frames) {
+ fprintf(stderr, "Cannot get stack frames from gdb. You
might be debugging the wrong program.\n"); // Something really bad happened.
Abort!
+ return GDB_STATE_ERROR;
+ }
+
+ /* Change current GDB frame to the one containing source code */
+ gmi_stack_select_frame(cntxt->gdb_handle,
+ cntxt->gdb_frames->level);
+
+ return GDB_STATE_STOPPED;
+ }
+ else if ((MONKEY_YES == cntxt->run_reverse) && (safetyCount <
GDB_SAFETY_COUNT)) { // GDB_SAFETY_COUNT prevents infinite analysis
+ /* If the stop reason is NULL, don't bail out immediately, wait for
stop again.
+ * It happens when a breakpoint is placed (for backtracking) that the
program stops for an unknown reason,
+ * resulting in a NULL stop reason which causes Monkey to bail out
before finishing its analysis. This else if
+ * clause prevents premature bail out
+ */
+ safetyCount++;
+ return wait_for_stop(cntxt);
+ }
+
+ return GDB_STATE_ERROR;
+}
+
+
+int
+MONKEY_ACTION_report_file(struct MONKEY_ACTION_Context *cntxt,
+ const char *dumpFileName, int isXML)
+{
+ FILE *f;
+ f = MONKEY_XML_WRITER_create_document(dumpFileName);
+ if (NULL == f) {
+ fprintf(stderr, "Error: pathologist was not able to create
report file.\n");
+ return MONKEY_NO;
+ }
+ MONKEY_XML_WRITER_write_document(f, cntxt->xml_report_node);
+ if (0 != fclose(f)) {
+ fprintf(stderr, "Error: pathologist could not close report
file.\n");
+ return MONKEY_NO;
+ }
+ return MONKEY_OK;
+}
+
+
+int MONKEY_ACTION_report_email(struct MONKEY_ACTION_Context *cntxt, const char
* dumpFileName)
+{
+ FILE *f;
+ MONKEY_ACTION_format_report_xml(cntxt);
+ f = MONKEY_XML_WRITER_create_document(dumpFileName);
+ MONKEY_XML_WRITER_write_document(f, cntxt->xml_report_node);
+ fclose(f);
+ sendMail(NULL, dumpFileName, cntxt->email_address);
+ return MONKEY_OK;
+}
+
+
+static int
+iterateFileNames(void *cls, int numColumns, char **colValues,
+ char **colNames)
+{
+ struct FileName *fileName;
+ char *token;
+
+ if (NULL == colValues[0])
+ return 1; /* Error */
+
+ // This is done to extract the only the file name from the full path
coming from the Database
+ token = strrchr(colValues[0], '/');
+ if (NULL == token) {
+ token = colValues[0];
+ } else {
+ token++;
+ }
+ fileName = MONKEY_malloc(sizeof(struct FileName));
+ fileName->prev = NULL;
+ fileName->next = NULL;
+ fileName->name = MONKEY_strdup(token);
+ MONKEY_CONTAINER_DLL_insert(fileNameListHead, fileNameListTail, fileName);
+ return 0; /* OK */
+}
+
+
+static int
+outerScopesCallback(void *cls, int numColumns, char **colValues,
+ char **colNames)
+{
+ if (NULL == colValues[0])
+ return 1; /* Error */
+
+ struct ScopeEnd *scopeEnd = MONKEY_malloc(sizeof(struct ScopeEnd));
+ scopeEnd->lineNo = atoi(colValues[0]);
+ MONKEY_CONTAINER_DLL_insert(scopeEndListHead, scopeEndListTail,
+ scopeEnd);
+ return 0; /* OK */
+}
+
+
+static int
+iterateExpressions(void *cls, int numColumns, char **colValues,
+ char **colNames)
+{
+ struct Expression *expression;
+ struct Function *function = (struct Function *) cls;
+
+ if (NULL == colValues[0] || NULL == colValues[1])
+ return 1; /* Error */
+
+ expression = MONKEY_malloc(sizeof(struct Expression));
+ expression->expressionSyntax = MONKEY_strdup(colValues[0]);
+ expression->isCall = atoi(colValues[1]);
+ expression->expressionValue = NULL;
+ expression->next = NULL;
+ expression->prev = NULL;
+
+ MONKEY_CONTAINER_DLL_insert(function->expressionListHead,
+ function->expressionListTail, expression);
+
+ return 0; /* OK */
+}
+
+
+static int
+iterateGlobals(void *cls, int numColumns, char **colValues,
+ char **colNames)
+{
+ struct Expression *expression;
+ struct Trace *trace = (struct Trace *) cls;
+
+ if (NULL == colValues[0] || NULL == colValues[1])
+ return 1; /* Error */
+
+ expression = MONKEY_malloc(sizeof(struct Expression));
+ expression->expressionSyntax = MONKEY_strdup(colValues[0]);
+ expression->isCall = atoi(colValues[1]);
+ expression->expressionValue = NULL;
+ expression->next = NULL;
+ expression->prev = NULL;
+
+ MONKEY_CONTAINER_DLL_insert(trace->globalsListHead,
+ trace->globalsListTail, 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 isAssignment(const char *expressionSyntax)
+{
+ return (NULL != strstr(expressionSyntax, "=")) ? MONKEY_YES : MONKEY_NO;
+}
+
+
+static struct Expression*
+analyzeExpressionValue( struct MONKEY_ACTION_Context *cntxt,
+ struct Expression *expr,
+ struct Expression **expressionListHead,
+ struct Expression **expressionListTail)
+{
+ MONKEY_assert(expr);
+ struct Expression *next = expr->next;
+ struct Expression *removedExpression = expr;
+
+ // We will not evaluate function calls (because GDB will evaluate by
calling the function)
+ if( expr->isCall )
+ goto remove;
+
+ // We should NOT evaluate assignments, otherwise subsequent expression
evaluations will be spoiled
+ else if( isAssignment(expr->expressionSyntax) )
+ goto remove;
+
+ // NULL Pointer are also ignored (cause theire NULL)
+ if (strcmp(expr->expressionSyntax, "NULL") == 0 ||
+ strcmp(expr->expressionSyntax, "0x0") == 0 ||
+ strcmp(expr->expressionSyntax, "((void*)0)") == 0)
+ goto remove;
+
+ expr->expressionValue =
+ gmi_data_evaluate_expression( cntxt->gdb_handle,
+
expr->expressionSyntax);
+
+ // ignore trivial report entries (constants for that matter)
+ if (expr->expressionValue && strcmp(expr->expressionSyntax,
expr->expressionValue) == 0)
+ goto remove;
+
+ // ignore functionpointers with their default names
+ size_t value_len; //= strlen(expr->expressionValue);
+ size_t syntax_len; //= strlen(expr->expressionSyntax);
+ if (expr->expressionValue &&
+ (value_len = strlen(expr->expressionValue)) > (syntax_len =
strlen(expr->expressionSyntax)) + 2 &&
+ !strncmp(expr->expressionValue + value_len - 1, ">", 1) &&
+ !strncmp(expr->expressionValue + value_len - syntax_len - 2,
"<", 1) &&
+ !strncmp(expr->expressionValue + value_len - syntax_len - 1,
expr->expressionSyntax, syntax_len))
+ goto remove;
+
+ if (NULL != expr->expressionValue
+ && (strcmp(expr->expressionValue, "0x0") == 0
+ || strcmp(expr->expressionValue, "NULL") == 0))
+ {
+ expr->expressionValue = "NULL";
+ cntxt->gdb_null_variable = expr->expressionSyntax;
+ cntxt->has_null = MONKEY_YES;
+ }
+
+ return next;
+
+remove:
+ MONKEY_CONTAINER_DLL_remove(*expressionListHead,
+
*expressionListTail,
+
removedExpression);
+ return next;
+}
+
+
+static int
+analyzeExpressionValues(struct Function *function,
+ struct MONKEY_ACTION_Context *cntxt)
+{
+ struct Expression *tmp;
+
+ tmp = function->expressionListHead;
+ while (NULL != tmp) {
+ tmp = analyzeExpressionValue(cntxt, tmp,
&(function->expressionListHead), &(function->expressionListTail));
+ }
+
+ return MONKEY_OK;
+}
+
+
+static int
+analyzeGlobalsValues(struct Trace *trace,
+ struct MONKEY_ACTION_Context *cntxt)
+{
+ struct Expression *tmp;
+
+ tmp = trace->globalsListHead;
+ while (NULL != tmp) {
+ tmp = analyzeExpressionValue(cntxt, tmp,
&(trace->globalsListHead), &(trace->globalsListTail));
+ }
+
+ return MONKEY_OK;
+}
+
+
+static int flushTrace(struct Trace *trace)
+{
+ struct Function *functionPtr = NULL;
+ struct Expression *expressionPtr = NULL;
+
+ while (NULL != trace->functionListHead) {
+ functionPtr = trace->functionListHead;
+ trace->functionListHead = trace->functionListHead->next;
+
+ while (NULL != functionPtr->expressionListHead) {
+ expressionPtr = functionPtr->expressionListHead;
+ functionPtr->expressionListHead =
+ functionPtr->expressionListHead->next;
+
+ MONKEY_free((char *) expressionPtr->expressionSyntax);
+ MONKEY_free(expressionPtr);
+ }
+ MONKEY_free(functionPtr);
+ }
+ return MONKEY_OK;
+}
+
+static void printTrace()
+{
+ int i = 0;
+ struct Function *functionPtr;
+ struct Expression *expressionPtr;
+ struct Trace *tracePtr = epoch->traceListHead;
+ while (NULL != tracePtr) {
+ printf("Program Stack Trace: Epoch Step %d\n", i++);
+ functionPtr = tracePtr->functionListHead;
+ while (NULL != functionPtr) {
+ printf("Function: %s, file: %s, line: %d\n", functionPtr->name,
+ functionPtr->file, functionPtr->line);
+ printf
+
("--------------------------------------------------------------------------------------------------\n");
+ printf("Expressions:\n");
+
+ expressionPtr = functionPtr->expressionListHead;
+ while (NULL != expressionPtr) {
+ printf("%s = %s\n",
+ expressionPtr->expressionSyntax,
+ (NULL ==
+ expressionPtr->
+ expressionValue) ? "No Value" : expressionPtr->
+ expressionValue);
+ expressionPtr = expressionPtr->next;
+ }
+
+ functionPtr = functionPtr->next;
+ }
+ printf
+ ("############################## End Stack Trace
######################################################\n\n");
+ tracePtr = tracePtr->next;
+ }
+}
+
+static void flushScopeEndList()
+{
+ struct ScopeEnd* scopeEndPtr;
+ while (NULL != scopeEndListHead) {
+ scopeEndPtr = scopeEndListHead;
+ scopeEndListHead = scopeEndPtr->next;
+ MONKEY_free(scopeEndPtr);
+ }
+
+ scopeEndListHead = NULL;
+ scopeEndListTail = NULL;
+}
+
+int MONKEY_ACTION_inspect_expression_database(struct MONKEY_ACTION_Context
*cntxt)
+{
+ int ret = MONKEY_OK;
+ int stackDepth = 0;
+ char* file_names = NULL;
+ struct Function *function = NULL;
+ struct Trace *trace = NULL;
+
+ /* Variables used across recursive calls */
+ static struct MONKEY_EDB_Context *edbCntxt;
+
+ if (NULL == epoch) {
+ epoch = MONKEY_malloc(sizeof(struct Epoch));
+ epoch->traceListHead = NULL;
+ epoch->traceListTail = NULL;
+ }
+
+ // Initialize the trace structure for this particular epoch step
+ trace = MONKEY_malloc(sizeof(struct Trace));
+ trace->globalsListHead = NULL;
+ trace->globalsListTail = NULL;
+ MONKEY_CONTAINER_DLL_insert_tail(epoch->traceListHead,
+ epoch->traceListTail, trace);
+
+
+ // Create a connection to the Expression Database
+ edbCntxt = MONKEY_EDB_connect(cntxt->expression_database_path);
+ if (NULL == edbCntxt) {
+ fprintf(stderr, "Unable to connect to Expression Database
file!\n");
+ ret = MONKEY_NO;
+ goto cleanup;
+ }
+
+ while( cntxt->gdb_frames && stackDepth <= cntxt->scope_depth) {
+ gmi_stack_select_frame(cntxt->gdb_handle,
cntxt->gdb_frames->level);
+ gmi_stack_info_frame(cntxt->gdb_handle);
+
+ // build the function struct
+ function = MONKEY_malloc(sizeof(struct Function));
+ function->depth = stackDepth++;
+ function->line = cntxt->gdb_frames->line;
+ function->name = cntxt->gdb_frames->func;
+ function->file = cntxt->gdb_frames->file;
+ function->expressionListHead = NULL;
+ function->expressionListTail = NULL;
+ function->next = NULL;
+ function->prev = NULL;
+ MONKEY_CONTAINER_DLL_insert_tail(trace->functionListHead,
+ trace->functionListTail,
function);
+
+ // Retrieve scope expressions from the database
+ MONKEY_EDB_get_expressions(edbCntxt,
+
cntxt->gdb_frames->file,
+
cntxt->gdb_frames->line,
+
&iterateExpressions, function);
+
+ // Do value analysis for relevant expressions
+ analyzeExpressionValues(function, cntxt);
+
+ // add current filename to the list
+ char* tmp = file_names;
+ MONKEY_asprintf(&file_names,
+ "%s OR file_name LIKE \'%%%s\'",
+ file_names,
+ cntxt->gdb_frames->file);
+ MONKEY_free_non_null(tmp);
+
+ /* Now, dive deeper into the stack trace */
+ cntxt->gdb_frames = cntxt->gdb_frames->next;
+ }
+
+
+ // Retrieve globals from the database
+ file_names += 10; // cut the first 10 chars "(null) OR "
+ MONKEY_EDB_get_globals( edbCntxt,
+ file_names,
+ &iterateGlobals, trace);
+ file_names -= 10;
+
+ // Do value analysis for globals
+ analyzeGlobalsValues(trace, cntxt);
+
+cleanup:
+ MONKEY_EDB_disconnect(edbCntxt);
+ MONKEY_free_non_null(file_names);
+ return ret;
+}
+
+
+int MONKEY_ACTION_start_reverse_execution(struct MONKEY_ACTION_Context
+ *cntxt)
+{
+ const char *failureFile = epoch->traceListHead->functionListHead->file;
+ const char *failureFunction =
+ epoch->traceListHead->functionListHead->name;
+ struct Trace *tracePtr = epoch->traceListHead;
+ int oldLine;
+
+ /*
+ * We execute one step back operation before starting analysis. We do that
to go to the expression before the one where the crash occurred.
+ * Because we already have the expression where the crash happened in our
stack structure from the previous epoch step (the initial epoch)
+ */
+ if (MONKEY_NO == stoppedInSharedLib) {
+ if (MONKEY_NO != gmi_exec_next_reverse(cntxt->gdb_handle)) {
+ while (!mi_get_response(cntxt->gdb_handle))
+ usleep(GDB_MI_ASYNC_WAIT);
+ } else {
+ fprintf(stderr, "Error: Reverse Execution has failed!
Backtracking might not be supported for the current architecture.\n");
+ if (MONKEY_YES == cntxt->gdb_connected) {
+ mi_disconnect(cntxt->gdb_handle); // No
need for gdb mi at this point!
+ cntxt->gdb_connected = MONKEY_NO;
+ }
+ return MONKEY_NO;
+ }
+ }
+
+ /* Do reverse execution for all expressions in the function in which the
failure occurred */
+ do {
+ oldLine = tracePtr->functionListHead->line;
+ if (MONKEY_NO != gmi_exec_next_reverse(cntxt->gdb_handle)) {
+ if (GDB_STATE_ERROR == wait_for_stop(cntxt)) {
+ fprintf(stderr, "Error: Analysis during Reverse
Execution has failed!\n");
+ return MONKEY_NO;
+ }
+ if (oldLine == cntxt->gdb_frames->line)
+ break;// We reached the end of record history
TODO: DIRTY SOLUTION! WILL FAIL IF TWO EXPRESSIONS ON THE SAME LINE
+ MONKEY_ACTION_inspect_expression_database(cntxt);
+ } else {
+ fprintf(stderr, "Error: Reverse Execution has
failed!\n");
+ return MONKEY_NO;
+ }
+
+ tracePtr = tracePtr->next; // tracePtr will have the new trace added
after examining the expression database for this reverse execution step
+ } while ((NULL != tracePtr)
+ && (strcmp(failureFile, tracePtr->functionListHead->file) ==
+ 0)
+ && (strcmp(failureFunction, tracePtr->functionListHead->name)
+ == 0));
+
+ // stop recording and return
+ gmi_exec_record_stop(cntxt->gdb_handle);
+ return MONKEY_OK;
+}
+
+int MONKEY_ACTION_rerun_with_valgrind(struct MONKEY_ACTION_Context
+ *cntxt)
+{
+ char *valgrindCommand;
+ FILE *valgrindPipe;
+ const char *valgrindPath = cntxt->valgrind_binary_path;
+ struct stat buf;
+
+ if (NULL == valgrindPath)
+ valgrindPath = "/usr/bin/valgrind"; /* Assumption for valgrind
installation */
+
+ /* Check if Valgrind is installed */
+ if (stat(valgrindPath, &buf) != 0 && errno == ENOENT ) {
+ fprintf(stderr,
+ "Warning: Valgrind is not installed. Memory check aborted!\n");
+ return MONKEY_NO;
+ }
+
+ MONKEY_asprintf(&cntxt->valgrind_output_tmp_file_name, "%d", rand());
+ cntxt->debug_mode = DEBUG_MODE_VALGRIND;
+ MONKEY_asprintf(&valgrindCommand,
+ "%s --leak-check=yes --log-file=%s %s", valgrindPath,
+ cntxt->valgrind_output_tmp_file_name,
+ cntxt->binary_name);
+ valgrindPipe = popen(valgrindCommand, "r");
+ if (NULL == valgrindPipe) {
+ fprintf(stderr, "Error in running Valgrind! Memory check aborted!\n");
+ MONKEY_free(valgrindCommand);
+ return MONKEY_NO;
+ }
+
+ pclose(valgrindPipe);
+ MONKEY_free(valgrindCommand);
+ return MONKEY_OK;
+}
+
+
+int MONKEY_ACTION_rerun_with_gdb(struct MONKEY_ACTION_Context
+ *cntxt)
+{
+ struct MONKEY_EDB_Context *edbCntxt;
+ struct stat buf;
+
+ /* Check if gdb is installed */
+ if (NULL == cntxt->gdb_binary_path) {
+ cntxt->gdb_binary_path = "/usr/bin/gdb"; /* Assumption for gdb default
installation */
+ }
+ if (stat(cntxt->gdb_binary_path, &buf) != 0 && errno == ENOENT ) {
+ fprintf(stderr,
+ "Error: gdb is not installed!\n");
+ return MONKEY_NO;
+ }
+
+ epoch = NULL; /* Initializing epoch Data Structure */
+ cntxt->debug_mode = DEBUG_MODE_GDB;
+ /* This is like a file-handle for fopen.
+ Here we have all the state of gdb "connection". */
+ if (NULL != cntxt->gdb_binary_path)
+ mi_set_gdb_exe(cntxt->gdb_binary_path);
+ int ret;
+
+ /* Connect to gdb child. */
+ cntxt->gdb_handle = mi_connect_local();
+ if (!cntxt->gdb_handle) {
+ fprintf(stderr, "Error: failed to connect to gdb!\n");
+ return MONKEY_NO;
+ }
+ fprintf(stderr, "Info: Connected to gdb!\n");
+ cntxt->gdb_connected = MONKEY_YES;
+
+ /* Set all callbacks. */
+ 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,
cntxt->binaryArgs)) {
+ fprintf(stderr, "Error: could not set gdb exec y args\n");
+ goto fail;
+ }
+
+ /* Tell gdb to attach the child to a terminal. */
+ if (!gmi_target_terminal(cntxt->gdb_handle, ttyname(STDIN_FILENO))) {
+ fprintf(stderr, "Error: could not select gdb target
terminal\n");
+ goto fail;
+ }
+
+
+ if (MONKEY_YES == cntxt->run_reverse) {
+ /* If Backtracking is enabled, we must set a breakpoint at the
main function, starting the program, then starting recording */
+ mi_bkpt *bp = gmi_break_insert_full(cntxt->gdb_handle, 0, 0,
NULL, -1, -1, "main");
+ if (NULL == bp) {
+ fprintf(stderr, "Error: gdb could not set a breakpoint
at function:%s\n",
+ cntxt->inspect_function);
+ goto fail;
+ }
+ mi_free_bkpt(bp);
+ }
+
+
+ if ((NULL != cntxt->inspect_expression) && (NULL !=
cntxt->inspect_function)) {
+ /* Setting a breakpoint at the function containing the
expression to inspect */
+ mi_bkpt *bp = gmi_break_insert_full(cntxt->gdb_handle, 0, 0,
NULL, -1, -1, cntxt->inspect_function);
+ if (NULL == bp) {
+ fprintf(stderr, "Error: gdb could not set a breakpoint
at function:%s\n", cntxt->inspect_function);
+ goto fail;
+ }
+ mi_free_bkpt(bp);
+ }
+
+ /* Prepare a list of the file names for the source files we are analyzing
*/
+ edbCntxt = MONKEY_EDB_connect(cntxt->expression_database_path);
+ if (NULL == edbCntxt) {
+ fprintf(stderr,
+ "Unable to connect to Expression Database file!\n");
+ goto fail;
+ }
+
+ if (MONKEY_OK != MONKEY_EDB_get_file_names(edbCntxt, &iterateFileNames,
NULL)) {
+ fprintf(stderr, "Error: Pathologist could not retrieve source file
names from expression database!\n");
+ goto fail;
+ }
+ MONKEY_EDB_disconnect(edbCntxt);
+
+
+ /* Run the program. */
+ if (!gmi_exec_run(cntxt->gdb_handle)) {
+ fprintf(stderr, "Error: gdb could not run the target
program!\n");
+ goto fail;
+ }
+
+ /* Backtracking is issued after running the program */
+ if (MONKEY_YES == cntxt->run_reverse) {
+ gmi_exec_record_process(cntxt->gdb_handle);
+ }
+
+ /* Here we should be stopped when the program crashes */
+ ret = wait_for_stop(cntxt);
+ if (ret == GDB_STATE_ERROR || ret == GDB_STATE_EXIT_NORMALLY) {
+ if (MONKEY_YES == cntxt->gdb_connected) {
+ mi_disconnect(cntxt->gdb_handle);
+ cntxt->gdb_connected = MONKEY_NO;
+ }
+ }
+
+ return ret;
+
+ // cleanup and abort
+fail:
+ if (MONKEY_YES == cntxt->gdb_connected) {
+ mi_disconnect(cntxt->gdb_handle);
+ cntxt->gdb_connected = MONKEY_NO;
+ }
+ return MONKEY_NO;
+}
+
+
+static const char *expressionListToString(struct Expression *head)
+{
+ char *string = MONKEY_strdup("");
+ char *strTmp;
+ struct Expression *tmp;
+
+ for (tmp = head; NULL != tmp; tmp = tmp->next) {
+ MONKEY_asprintf(&strTmp,
+ "%s%s => %s\n",
+ string,
+ tmp->expressionSyntax,
+ NULL ==
+ tmp->
+ expressionValue ? "Not evaluated" :
+ tmp->expressionValue);
+ MONKEY_free(string);
+ string = strTmp;
+ }
+ return string;
+}
+
+#if 0
+static int getWatchInfoListSize(struct WatchInfo *head)
+{
+ int count = 0;
+ int largestStr = 0;
+ struct WatchInfo *tmp = head;
+
+ while (NULL != tmp) {
+ if (largestStr < strlen(tmp->value))
+ largestStr = strlen(tmp->value);
+ tmp = tmp->next;
+ count++;
+ }
+
+ return count * largestStr;
+}
+
+static const char *watchInfoListToString(struct WatchInfo *head)
+{
+ char *string = MONKEY_malloc(getWatchInfoListSize(head));
+ char *strTmp;
+ struct WatchInfo *tmp = head;
+
+ MONKEY_asprintf(&strTmp, "%s\t \t%s\n", tmp->hitNumber, tmp->value);
+ strcpy(string, strTmp);
+ MONKEY_free(strTmp);
+ tmp = tmp->next;
+
+ while (NULL != tmp) {
+ MONKEY_asprintf(&strTmp, "%s\t \t%s\n", tmp->hitNumber,
+ tmp->value);
+ strcat(string, strTmp);
+ MONKEY_free(strTmp);
+ tmp = tmp->next;
+ }
+
+ return string;
+}
+#endif
+
+static const char *getValgrindOutput(struct MONKEY_ACTION_Context *cntxt)
+{
+ char *valgrindOutput;
+ int size;
+ FILE *valgrindFile = fopen(cntxt->valgrind_output_tmp_file_name, "r");
+ fseek(valgrindFile, 0L, SEEK_END);
+ size = ftell(valgrindFile);
+ fseek(valgrindFile, 0L, SEEK_SET);
+
+ valgrindOutput = MONKEY_malloc(size);
+ fread(valgrindOutput, size - 1, 1, valgrindFile);
+ fclose(valgrindFile);
+ return valgrindOutput;
+}
+
+
+static struct MONKEY_XML_Node *createXmlSimpleNode(const char *nodeName,
+ const char
+ *nodeInnerText)
+{
+ struct MONKEY_XML_Node *node =
+ MONKEY_XML_WRITER_new_node(nodeName, nodeInnerText);
+ return node;
+}
+
+
+static struct MONKEY_XML_Node *createXmlCrashNode(const char *category,
+ const char *function,
+ int line,
+ const char *file)
+{
+ struct MONKEY_XML_Node *node;
+ char *lineStr;
+
+ MONKEY_asprintf(&lineStr, "%d", line);
+ node = MONKEY_XML_WRITER_new_node("crash", NULL);
+ MONKEY_XML_WRITER_add_attribute(node, "category", category);
+ MONKEY_XML_WRITER_add_attribute(node, "function", function);
+ MONKEY_XML_WRITER_add_attribute(node, "line", lineStr);
+ MONKEY_XML_WRITER_add_attribute(node, "file", file);
+ return node;
+}
+
+
+static struct MONKEY_XML_Node *createXmlEpochStep(int step)
+{
+ struct MONKEY_XML_Node *node;
+ char *stepStr;
+ MONKEY_asprintf(&stepStr, "%d", step);
+ node = MONKEY_XML_WRITER_new_node("epoch", NULL);
+ MONKEY_XML_WRITER_add_attribute(node, "step", stepStr);
+ return node;
+}
+
+
+static struct MONKEY_XML_Node *createXmlFunctionNode(const char *name,
+ int line,
+ const char *file,
+ int depth)
+{
+ struct MONKEY_XML_Node *node;
+ char *lineStr;
+ char *depthStr;
+
+ MONKEY_asprintf(&lineStr, "%d", line);
+ MONKEY_asprintf(&depthStr, "%d", depth);
+ node = MONKEY_XML_WRITER_new_node("function", NULL);
+ MONKEY_XML_WRITER_add_attribute(node, "name", name);
+ MONKEY_XML_WRITER_add_attribute(node, "line", lineStr);
+ MONKEY_XML_WRITER_add_attribute(node, "file", file);
+ MONKEY_XML_WRITER_add_attribute(node, "depth", depthStr);
+ return node;
+}
+
+
+static struct MONKEY_XML_Node *createXmlExpressionNode(const char *name,
+ const char *value)
+{
+ struct MONKEY_XML_Node *node;
+
+ node = MONKEY_XML_WRITER_new_node("expression", value);
+ MONKEY_XML_WRITER_add_attribute(node, "name", name);
+ return node;
+}
+
+
+static struct MONKEY_XML_Node *createXmlGlobalExpressionNode(const char *name,
+ const char *value)
+{
+ struct MONKEY_XML_Node *node;
+
+ node = MONKEY_XML_WRITER_new_node("expression", value);
+ MONKEY_XML_WRITER_add_attribute(node, "name", name);
+ return node;
+}
+
+
+int MONKEY_ACTION_is_Nullpointer(struct MONKEY_ACTION_Context* cntxt)
+{
+ mi_asm_insns* disassembled_code =
gmi_data_disassemble_se(cntxt->gdb_handle, "$pc", "$pc+1", 0);
+ char* reg;
+ while(reg = strstr(disassembled_code->ins->inst, "(%")) {
+ //printf("%s\n", reg);
+ reg++;
+ size_t len = strcspn(reg, "),");
+ reg[0]='$';
+ reg[len]='\0';
+ char* val = gmi_data_evaluate_expression(cntxt->gdb_handle,
reg);
+ //printf("%s\n", val);
+ if( !strcmp(val, "0") ) return 1;
+ }
+ return 0;
+}
+
+
+int MONKEY_ACTION_format_report_xml(struct MONKEY_ACTION_Context
+ *cntxt)
+{
+ int i = 0;
+ struct MONKEY_XML_Node *node;
+ struct MONKEY_XML_Node *historyNode;
+ struct MONKEY_XML_Node *traceNode;
+ struct MONKEY_XML_Node *globalsNode;
+ struct Trace *tracePtr = epoch->traceListHead;
+ struct Function *functionPtr = tracePtr->functionListHead;
+ struct Expression *expressionPtr;
+
+
+ switch (cntxt->bug_detected) {
+ case BUG_NULL_POINTER:
+ cntxt->xml_report_node = createXmlCrashNode("npe",
functionPtr->name, functionPtr->line, functionPtr->file);
+ break;
+ case BUG_BAD_MEM_ACCESS:
+ cntxt->xml_report_node = createXmlCrashNode("Bad memory
access", functionPtr->name, functionPtr->line, functionPtr->file);
+ node = MONKEY_XML_WRITER_add_child(cntxt->xml_report_node,
createXmlSimpleNode("valgrind", getValgrindOutput(cntxt)));
+ break;
+ case BUG_ABORT:
+ cntxt->xml_report_node = createXmlCrashNode("Assertion
Failure", functionPtr->name, functionPtr->line, functionPtr->file);
+ break;
+ case BUG_ARITHMETIC:
+ cntxt->xml_report_node = createXmlCrashNode("Division By Zero",
functionPtr->name, functionPtr->line, functionPtr->file);
+ break;
+ case BUG_SIG_BUS:
+ cntxt->xml_report_node = createXmlCrashNode("Bus Error",
functionPtr->name, functionPtr->line, functionPtr->file);
+ break;
+ default:
+ cntxt->xml_report_node = createXmlCrashNode("Unknown",
functionPtr->name, functionPtr->line, functionPtr->file);
+ break;
+ }
+
+ historyNode = MONKEY_XML_WRITER_add_child(cntxt->xml_report_node,
createXmlSimpleNode("history", NULL));
+
+ /* Adding Stack Trace Nodes to XML Report */
+ while (NULL != tracePtr) {
+ node = MONKEY_XML_WRITER_add_child(historyNode,
createXmlEpochStep(i));
+ traceNode = MONKEY_XML_WRITER_add_child(node,
createXmlSimpleNode("trace", NULL));
+ globalsNode = MONKEY_XML_WRITER_add_child(node,
createXmlSimpleNode("globals", NULL));
+
+ functionPtr = tracePtr->functionListHead;
+ while (NULL != functionPtr) {
+ node = MONKEY_XML_WRITER_add_child(traceNode,
createXmlFunctionNode(functionPtr->name,
+
functionPtr->line,
+
functionPtr->file,
+
functionPtr->depth));
+ node = MONKEY_XML_WRITER_add_child(node,
createXmlSimpleNode("expressions", NULL));
+
+ expressionPtr = functionPtr->expressionListHead;
+ while (NULL != expressionPtr) {
+ // ignore non helpful expressions
+ if( expressionPtr->expressionValue )
+ MONKEY_XML_WRITER_add_child(node,
createXmlExpressionNode(expressionPtr->expressionSyntax,
expressionPtr->expressionValue));
+ expressionPtr = expressionPtr->next;
+ }
+
+ functionPtr = functionPtr->next;
+ }
+
+ expressionPtr = tracePtr->globalsListHead;
+ while( expressionPtr ) {
+ if( expressionPtr->expressionValue )
+ MONKEY_XML_WRITER_add_child(globalsNode,
createXmlGlobalExpressionNode(expressionPtr->expressionSyntax,
expressionPtr->expressionValue));
+ expressionPtr = expressionPtr->next;
+ }
+
+
+ tracePtr = tracePtr->next;
+ i++;
+ }
+ return MONKEY_OK;
+}
+
+
+
+
+int MONKEY_ACTION_delete_context(struct MONKEY_ACTION_Context
+ *cntxt)
+{
+ if (MONKEY_YES == cntxt->gdb_connected) {
+ mi_disconnect(cntxt->gdb_handle);
+ cntxt->gdb_connected = MONKEY_NO;
+ }
+ if (NULL != cntxt->debug_report)
+ MONKEY_free(cntxt->debug_report);
+ if (NULL != cntxt->valgrind_output_tmp_file_name) {
+ remove(cntxt->valgrind_output_tmp_file_name);
+ MONKEY_free(cntxt->valgrind_output_tmp_file_name);
+ }
+ if (NULL != cntxt->xml_report_node)
+ MONKEY_XML_WRITER_delete_tree(cntxt->xml_report_node);
+ if (NULL != cntxt->binaryArgs)
+ MONKEY_free(cntxt->binaryArgs);
+
+ MONKEY_free(cntxt);
+ return MONKEY_OK;
+}
+
+
+int MONKEY_ACTION_check_bug_redundancy()
+{
+ return MONKEY_OK;
+}
Added: monkey/trunk/pathologist/src/pathologist/action.h
===================================================================
--- monkey/trunk/pathologist/src/pathologist/action.h
(rev 0)
+++ monkey/trunk/pathologist/src/pathologist/action.h 2013-02-11 09:49:40 UTC
(rev 26063)
@@ -0,0 +1,100 @@
+/**
+ * @file monkey/MONKEY_action.h
+ * @brief Monkey API for actions taken by Monkey while debugging
+ */
+
+#ifndef MONKEY_ACTION_H
+#define MONKEY_ACTION_H
+
+#include "gdbmi.h"
+#include "pathologist_xml_writer.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0 /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+/* Debug constants */
+#define DEBUG_MODE_GDB 0
+#define GDB_STATE_STOPPED 1
+#define GDB_STATE_EXIT_NORMALLY 2
+#define GDB_STATE_ERROR 3
+#define GDB_SAFETY_COUNT 2
+#define DEBUG_MODE_VALGRIND 4
+#define DEBUG_MODE_REPORT_READY 5
+#define NO_BUG_DETECTED -1
+#define BUG_NULL_POINTER 6
+#define BUG_ABORT 7
+#define BUG_ARITHMETIC 8
+#define BUG_BAD_MEM_ACCESS 9
+#define BUG_SIG_BUS 10
+#define GDB_MI_ASYNC_WAIT 5
+
+/**
+ * Context for the Action API
+ */
+struct MONKEY_ACTION_Context
+{
+ const char *binary_name;
+ char *binaryArgs;
+ const char *email_address;
+ const char *expression_database_path;
+ const char *gdb_binary_path;
+ const char *valgrind_binary_path;
+ const char *inspect_expression;
+ const char *inspect_function;
+ int debug_mode;
+ int bug_detected;
+ int has_null;
+ char *debug_report;
+ struct MONKEY_XML_Node *xml_report_node;
+
+ /* gdb debugging attributes */
+ int run_reverse;
+ int scope_depth;
+ mi_h *gdb_handle;
+ int gdb_connected;
+ const char *gdb_in_use;
+ mi_stop *gdb_stop_reason;
+ mi_frames *gdb_frames;
+ const char *gdb_null_variable;
+
+ /* Valgrind memcheck attributes */
+ char* valgrind_output_tmp_file_name;
+};
+
+
+int MONKEY_ACTION_report_file (struct MONKEY_ACTION_Context
+ *cntxt, const char *dumpFileName, int
isXML);
+int MONKEY_ACTION_report_email (struct MONKEY_ACTION_Context
+ *cntxt, const char *dumpFileName);
+int MONKEY_ACTION_inspect_expression_database (struct
+ MONKEY_ACTION_Context
+ *cntxt);
+int MONKEY_ACTION_rerun_with_gdb (struct MONKEY_ACTION_Context
+ *cntxt);
+int MONKEY_ACTION_start_reverse_execution(struct MONKEY_ACTION_Context *
cntxt);
+int MONKEY_ACTION_rerun_with_valgrind (struct
+ MONKEY_ACTION_Context
+ *cntxt);
+int MONKEY_ACTION_format_report (struct MONKEY_ACTION_Context
+ *cntxt);
+int
+MONKEY_ACTION_format_report_xml (struct MONKEY_ACTION_Context
+ *cntxt);
+int MONKEY_ACTION_delete_context(struct MONKEY_ACTION_Context *cntxt);
+
+int MONKEY_ACTION_check_bug_redundancy (void);
+
+
+#if 0 /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
Deleted: monkey/trunk/pathologist/src/pathologist/action_api.c
===================================================================
--- monkey/trunk/pathologist/src/pathologist/action_api.c 2013-02-11
08:49:40 UTC (rev 26062)
+++ monkey/trunk/pathologist/src/pathologist/action_api.c 2013-02-11
09:49:40 UTC (rev 26063)
@@ -1,1119 +0,0 @@
-/**
- * @file monkey/action_api.c
- * @brief Monkey API for actions taken by Monkey while debugging
- */
-
-#include "monkey_common.h"
-#include "pathologist_action.h"
-#include "pathologist_edb.h"
-#include "pathologist_xml_writer.h"
-#include <libesmtp.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-extern void sendMail(const char *messageContents, const char *reportFileName,
- const char *emailAddress);
-
-static int crashExpressionFoundInEDB = MONKEY_YES;
-static int async_c = 0;
-static int stoppedInSharedLib = MONKEY_NO;
-static int failureFunctionStartLine = 0; // start line number of the
function in which the failure occurs
-static struct WatchInfo *watchInfoListHead = NULL;
-static struct WatchInfo *watchInfoListTail = NULL;
-static struct FileName *fileNameListHead = NULL;
-static struct FileName *fileNameListTail = NULL;
-static struct ScopeEnd *scopeEndListHead = NULL;
-static struct ScopeEnd *scopeEndListTail = NULL;
-
-
-struct ScopeEnd {
- struct ScopeEnd *next;
- struct ScopeEnd *prev;
-
- int lineNo;
-};
-
-
-struct FileName {
- struct FileName *next;
- struct FileName *prev;
-
- const char *name;
-};
-
-
-struct Expression {
- struct Expression *next;
- struct Expression *prev;
- const char *expressionSyntax;
- const char *expressionValue;
- int isCall;
-};
-
-
-struct Function {
- struct Function *next;
- struct Function *prev;
- const char *name;
- const char *file;
- int line;
- int depth;
- struct Expression *expressionListHead;
- struct Expression *expressionListTail;
-};
-
-struct Trace {
- struct Trace *next;
- struct Trace *prev;
- struct Function *functionListHead;
- struct Function *functionListTail;
- struct Expression *globalsListHead;
- struct Expression *globalsListTail;
-};
-
-
-struct Epoch {
- struct Trace *traceListHead;
- struct Trace *traceListTail;
-} *epoch;
-
-struct WatchInfo {
- struct WatchInfo *next;
- struct WatchInfo *prev;
- int hitNumber;
- const char *value;
-};
-
-
-static void cb_console(const char *str, void *data)
-{
- printf("CONSOLE> %s\n", str);
-}
-
-
-/* Note that unlike what's documented in gdb docs it isn't usable. */
-static void cb_target(const char *str, void *data)
-{
- printf("TARGET> %s\n", str);
-}
-
-
-static void cb_log(const char *str, void *data)
-{
- printf("LOG> %s\n", str);
-}
-
-
-static void cb_to(const char *str, void *data)
-{
- printf(">> %s", str);
-}
-
-
-static void cb_from(const char *str, void *data)
-{
- printf("<< %s\n", str);
-}
-
-
-static void cb_async(mi_output * o, void *data)
-{
- printf("ASYNC\n");
- async_c++;
-}
-
-static int isInCodeBase(const char *name)
-{
- struct FileName *fileName = fileNameListHead;
- while (NULL != fileName) {
- if (strcmp(fileName->name, name) == 0)
- return MONKEY_YES;
- fileName = fileName->next;
- }
- return MONKEY_NO;
-}
-
-
-static int wait_for_stop(struct MONKEY_ACTION_Context *cntxt)
-{
- static int safetyCount = 0;
-
- while (!mi_get_response(cntxt->gdb_handle))
- usleep(GDB_MI_ASYNC_WAIT);
- /* The end of the async. */
-
- cntxt->gdb_stop_reason = mi_res_stop(cntxt->gdb_handle);
-
- if (cntxt->gdb_stop_reason) {
- safetyCount = 0; // reset the Safety Count whenever you
stop for a meaningful reason
-
- switch (cntxt->gdb_stop_reason->reason) {
- case sr_exited_normally:
- return GDB_STATE_EXIT_NORMALLY;
- case sr_signal_received:
- //gmi_set_unwind_on_signal_on(cntxt->gdb_handle);
// Program crashed. From now on preserve stack on any further received signals
- break;
- case sr_bkpt_hit:
- {
- /* continue execution */
- gmi_exec_continue(cntxt->gdb_handle);
- return wait_for_stop(cntxt);
- }
- case sr_wp_trigger:
- {
- /* Execution stopped because of hitting a watch point */
- static int watchPointHitNumber = 0;
- struct WatchInfo *watchInfo =
- MONKEY_malloc(sizeof(struct WatchInfo));
- watchInfo->hitNumber = ++watchPointHitNumber;
- watchInfo->value = cntxt->gdb_stop_reason->wp_val;
- MONKEY_CONTAINER_DLL_insert(watchInfoListHead,
- watchInfoListTail,
watchInfo);
- if (watchPointHitNumber == 1023)
- printf("HEY! 1023! WE ARE GETTING OUT OF THE
LOOP!\n");
- gmi_exec_continue(cntxt->gdb_handle);
- return wait_for_stop(cntxt);
- }
- case sr_wp_scope:
- gmi_exec_continue(cntxt->gdb_handle);
- return wait_for_stop(cntxt);
- default:
- break;
- }
-
- /* Reaching this line means that the program has stopped
abnormally OR we are in backtracking mode, and it's a step backward */
- cntxt->gdb_frames = gmi_stack_list_frames(cntxt->gdb_handle);
- while ((NULL != cntxt->gdb_frames) && (NULL ==
cntxt->gdb_frames->file)) {
- cntxt->gdb_frames = cntxt->gdb_frames->next;
- }
-
- if ((NULL != cntxt->gdb_frames) && (MONKEY_YES !=
isInCodeBase(cntxt->gdb_frames->file))) {
- do {
- cntxt->gdb_frames = cntxt->gdb_frames->next;
- } while ((NULL != cntxt->gdb_frames) && (MONKEY_YES !=
isInCodeBase(cntxt->gdb_frames->file)));
-
- if ((NULL != cntxt->gdb_frames) && (MONKEY_YES ==
cntxt->run_reverse)) {
- /* We are in backtracking mode, we need to move
GDB from the shared library to our source code */
- stoppedInSharedLib = MONKEY_YES;
- gmi_break_insert(cntxt->gdb_handle,
cntxt->gdb_frames->file,
- cntxt->gdb_frames->line);
- gmi_exec_continue_reverse(cntxt->gdb_handle);
- while (!mi_get_response(cntxt->gdb_handle))
- usleep(GDB_MI_ASYNC_WAIT);
- cntxt->gdb_frames =
gmi_stack_list_frames(cntxt->gdb_handle);
- }
- }
-
- if (NULL == cntxt->gdb_frames) {
- fprintf(stderr, "Cannot get stack frames from gdb. You
might be debugging the wrong program.\n"); // Something really bad happened.
Abort!
- return GDB_STATE_ERROR;
- }
-
- /* Change current GDB frame to the one containing source code */
- gmi_stack_select_frame(cntxt->gdb_handle,
- cntxt->gdb_frames->level);
-
- return GDB_STATE_STOPPED;
- }
- else if ((MONKEY_YES == cntxt->run_reverse) && (safetyCount <
GDB_SAFETY_COUNT)) { // GDB_SAFETY_COUNT prevents infinite analysis
- /* If the stop reason is NULL, don't bail out immediately, wait for
stop again.
- * It happens when a breakpoint is placed (for backtracking) that the
program stops for an unknown reason,
- * resulting in a NULL stop reason which causes Monkey to bail out
before finishing its analysis. This else if
- * clause prevents premature bail out
- */
- safetyCount++;
- return wait_for_stop(cntxt);
- }
-
- return GDB_STATE_ERROR;
-}
-
-
-int
-MONKEY_ACTION_report_file(struct MONKEY_ACTION_Context *cntxt,
- const char *dumpFileName, int isXML)
-{
- FILE *f;
- f = MONKEY_XML_WRITER_create_document(dumpFileName);
- if (NULL == f) {
- fprintf(stderr, "Error: pathologist was not able to create
report file.\n");
- return MONKEY_NO;
- }
- MONKEY_XML_WRITER_write_document(f, cntxt->xml_report_node);
- if (0 != fclose(f)) {
- fprintf(stderr, "Error: pathologist could not close report
file.\n");
- return MONKEY_NO;
- }
- return MONKEY_OK;
-}
-
-
-int MONKEY_ACTION_report_email(struct MONKEY_ACTION_Context *cntxt, const char
* dumpFileName)
-{
- FILE *f;
- MONKEY_ACTION_format_report_xml(cntxt);
- f = MONKEY_XML_WRITER_create_document(dumpFileName);
- MONKEY_XML_WRITER_write_document(f, cntxt->xml_report_node);
- fclose(f);
- sendMail(NULL, dumpFileName, cntxt->email_address);
- return MONKEY_OK;
-}
-
-
-static int
-iterateFileNames(void *cls, int numColumns, char **colValues,
- char **colNames)
-{
- struct FileName *fileName;
- char *token;
-
- if (NULL == colValues[0])
- return 1; /* Error */
-
- // This is done to extract the only the file name from the full path
coming from the Database
- token = strrchr(colValues[0], '/');
- if (NULL == token) {
- token = colValues[0];
- } else {
- token++;
- }
- fileName = MONKEY_malloc(sizeof(struct FileName));
- fileName->prev = NULL;
- fileName->next = NULL;
- fileName->name = MONKEY_strdup(token);
- MONKEY_CONTAINER_DLL_insert(fileNameListHead, fileNameListTail, fileName);
- return 0; /* OK */
-}
-
-
-static int
-outerScopesCallback(void *cls, int numColumns, char **colValues,
- char **colNames)
-{
- if (NULL == colValues[0])
- return 1; /* Error */
-
- struct ScopeEnd *scopeEnd = MONKEY_malloc(sizeof(struct ScopeEnd));
- scopeEnd->lineNo = atoi(colValues[0]);
- MONKEY_CONTAINER_DLL_insert(scopeEndListHead, scopeEndListTail,
- scopeEnd);
- return 0; /* OK */
-}
-
-
-static int
-iterateExpressions(void *cls, int numColumns, char **colValues,
- char **colNames)
-{
- struct Expression *expression;
- struct Function *function = (struct Function *) cls;
-
- if (NULL == colValues[0] || NULL == colValues[1])
- return 1; /* Error */
-
- expression = MONKEY_malloc(sizeof(struct Expression));
- expression->expressionSyntax = MONKEY_strdup(colValues[0]);
- expression->isCall = atoi(colValues[1]);
- expression->expressionValue = NULL;
- expression->next = NULL;
- expression->prev = NULL;
-
- MONKEY_CONTAINER_DLL_insert(function->expressionListHead,
- function->expressionListTail, expression);
-
- return 0; /* OK */
-}
-
-
-static int
-iterateGlobals(void *cls, int numColumns, char **colValues,
- char **colNames)
-{
- struct Expression *expression;
- struct Trace *trace = (struct Trace *) cls;
-
- if (NULL == colValues[0] || NULL == colValues[1])
- return 1; /* Error */
-
- expression = MONKEY_malloc(sizeof(struct Expression));
- expression->expressionSyntax = MONKEY_strdup(colValues[0]);
- expression->isCall = atoi(colValues[1]);
- expression->expressionValue = NULL;
- expression->next = NULL;
- expression->prev = NULL;
-
- MONKEY_CONTAINER_DLL_insert(trace->globalsListHead,
- trace->globalsListTail, 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 isAssignment(const char *expressionSyntax)
-{
- return (NULL != strstr(expressionSyntax, "=")) ? MONKEY_YES : MONKEY_NO;
-}
-
-
-static struct Expression*
-analyzeExpressionValue( struct MONKEY_ACTION_Context *cntxt,
- struct Expression *expr,
- struct Expression **expressionListHead,
- struct Expression **expressionListTail)
-{
- MONKEY_assert(expr);
- struct Expression *next = expr->next;
- struct Expression *removedExpression = expr;
-
- // We will not evaluate function calls (because GDB will evaluate by
calling the function)
- if( expr->isCall )
- goto remove;
-
- // We should NOT evaluate assignments, otherwise subsequent expression
evaluations will be spoiled
- else if( isAssignment(expr->expressionSyntax) )
- goto remove;
-
- // NULL Pointer are also ignored (cause theire NULL)
- if (strcmp(expr->expressionSyntax, "NULL") == 0 ||
- strcmp(expr->expressionSyntax, "0x0") == 0 ||
- strcmp(expr->expressionSyntax, "((void*)0)") == 0)
- goto remove;
-
- expr->expressionValue =
- gmi_data_evaluate_expression( cntxt->gdb_handle,
-
expr->expressionSyntax);
-
- // ignore trivial report entries (constants for that matter)
- if (expr->expressionValue && strcmp(expr->expressionSyntax,
expr->expressionValue) == 0)
- goto remove;
-
- // ignore functionpointers with their default names
- size_t value_len; //= strlen(expr->expressionValue);
- size_t syntax_len; //= strlen(expr->expressionSyntax);
- if (expr->expressionValue &&
- (value_len = strlen(expr->expressionValue)) > (syntax_len =
strlen(expr->expressionSyntax)) + 2 &&
- !strncmp(expr->expressionValue + value_len - 1, ">", 1) &&
- !strncmp(expr->expressionValue + value_len - syntax_len - 2,
"<", 1) &&
- !strncmp(expr->expressionValue + value_len - syntax_len - 1,
expr->expressionSyntax, syntax_len))
- goto remove;
-
- if (NULL != expr->expressionValue
- && (strcmp(expr->expressionValue, "0x0") == 0
- || strcmp(expr->expressionValue, "NULL") == 0))
- {
- expr->expressionValue = "NULL";
- cntxt->gdb_null_variable = expr->expressionSyntax;
- cntxt->has_null = MONKEY_YES;
- }
-
- return next;
-
-remove:
- MONKEY_CONTAINER_DLL_remove(*expressionListHead,
-
*expressionListTail,
-
removedExpression);
- return next;
-}
-
-
-static int
-analyzeExpressionValues(struct Function *function,
- struct MONKEY_ACTION_Context *cntxt)
-{
- struct Expression *tmp;
-
- tmp = function->expressionListHead;
- while (NULL != tmp) {
- tmp = analyzeExpressionValue(cntxt, tmp,
&(function->expressionListHead), &(function->expressionListTail));
- }
-
- return MONKEY_OK;
-}
-
-
-static int
-analyzeGlobalsValues(struct Trace *trace,
- struct MONKEY_ACTION_Context *cntxt)
-{
- struct Expression *tmp;
-
- tmp = trace->globalsListHead;
- while (NULL != tmp) {
- tmp = analyzeExpressionValue(cntxt, tmp,
&(trace->globalsListHead), &(trace->globalsListTail));
- }
-
- return MONKEY_OK;
-}
-
-
-static int flushTrace(struct Trace *trace)
-{
- struct Function *functionPtr = NULL;
- struct Expression *expressionPtr = NULL;
-
- while (NULL != trace->functionListHead) {
- functionPtr = trace->functionListHead;
- trace->functionListHead = trace->functionListHead->next;
-
- while (NULL != functionPtr->expressionListHead) {
- expressionPtr = functionPtr->expressionListHead;
- functionPtr->expressionListHead =
- functionPtr->expressionListHead->next;
-
- MONKEY_free((char *) expressionPtr->expressionSyntax);
- MONKEY_free(expressionPtr);
- }
- MONKEY_free(functionPtr);
- }
- return MONKEY_OK;
-}
-
-static void printTrace()
-{
- int i = 0;
- struct Function *functionPtr;
- struct Expression *expressionPtr;
- struct Trace *tracePtr = epoch->traceListHead;
- while (NULL != tracePtr) {
- printf("Program Stack Trace: Epoch Step %d\n", i++);
- functionPtr = tracePtr->functionListHead;
- while (NULL != functionPtr) {
- printf("Function: %s, file: %s, line: %d\n", functionPtr->name,
- functionPtr->file, functionPtr->line);
- printf
-
("--------------------------------------------------------------------------------------------------\n");
- printf("Expressions:\n");
-
- expressionPtr = functionPtr->expressionListHead;
- while (NULL != expressionPtr) {
- printf("%s = %s\n",
- expressionPtr->expressionSyntax,
- (NULL ==
- expressionPtr->
- expressionValue) ? "No Value" : expressionPtr->
- expressionValue);
- expressionPtr = expressionPtr->next;
- }
-
- functionPtr = functionPtr->next;
- }
- printf
- ("############################## End Stack Trace
######################################################\n\n");
- tracePtr = tracePtr->next;
- }
-}
-
-static void flushScopeEndList()
-{
- struct ScopeEnd* scopeEndPtr;
- while (NULL != scopeEndListHead) {
- scopeEndPtr = scopeEndListHead;
- scopeEndListHead = scopeEndPtr->next;
- MONKEY_free(scopeEndPtr);
- }
-
- scopeEndListHead = NULL;
- scopeEndListTail = NULL;
-}
-
-int MONKEY_ACTION_inspect_expression_database(struct MONKEY_ACTION_Context
*cntxt)
-{
- int ret = MONKEY_OK;
- int stackDepth = 0;
- char* file_names = NULL;
- struct Function *function = NULL;
- struct Trace *trace = NULL;
-
- /* Variables used across recursive calls */
- static struct MONKEY_EDB_Context *edbCntxt;
-
- if (NULL == epoch) {
- epoch = MONKEY_malloc(sizeof(struct Epoch));
- epoch->traceListHead = NULL;
- epoch->traceListTail = NULL;
- }
-
- // Initialize the trace structure for this particular epoch step
- trace = MONKEY_malloc(sizeof(struct Trace));
- trace->globalsListHead = NULL;
- trace->globalsListTail = NULL;
- MONKEY_CONTAINER_DLL_insert_tail(epoch->traceListHead,
- epoch->traceListTail, trace);
-
-
- // Create a connection to the Expression Database
- edbCntxt = MONKEY_EDB_connect(cntxt->expression_database_path);
- if (NULL == edbCntxt) {
- fprintf(stderr, "Unable to connect to Expression Database
file!\n");
- ret = MONKEY_NO;
- goto cleanup;
- }
-
- while( cntxt->gdb_frames && stackDepth <= cntxt->scope_depth) {
- gmi_stack_select_frame(cntxt->gdb_handle,
cntxt->gdb_frames->level);
- gmi_stack_info_frame(cntxt->gdb_handle);
-
- // build the function struct
- function = MONKEY_malloc(sizeof(struct Function));
- function->depth = stackDepth++;
- function->line = cntxt->gdb_frames->line;
- function->name = cntxt->gdb_frames->func;
- function->file = cntxt->gdb_frames->file;
- function->expressionListHead = NULL;
- function->expressionListTail = NULL;
- function->next = NULL;
- function->prev = NULL;
- MONKEY_CONTAINER_DLL_insert_tail(trace->functionListHead,
- trace->functionListTail,
function);
-
- // Retrieve scope expressions from the database
- MONKEY_EDB_get_expressions(edbCntxt,
-
cntxt->gdb_frames->file,
-
cntxt->gdb_frames->line,
-
&iterateExpressions, function);
-
- // Do value analysis for relevant expressions
- analyzeExpressionValues(function, cntxt);
-
- // add current filename to the list
- char* tmp = file_names;
- MONKEY_asprintf(&file_names,
- "%s OR file_name LIKE \'%%%s\'",
- file_names,
- cntxt->gdb_frames->file);
- MONKEY_free_non_null(tmp);
-
- /* Now, dive deeper into the stack trace */
- cntxt->gdb_frames = cntxt->gdb_frames->next;
- }
-
-
- // Retrieve globals from the database
- file_names += 10; // cut the first 10 chars "(null) OR "
- MONKEY_EDB_get_globals( edbCntxt,
- file_names,
- &iterateGlobals, trace);
- file_names -= 10;
-
- // Do value analysis for globals
- analyzeGlobalsValues(trace, cntxt);
-
-cleanup:
- MONKEY_EDB_disconnect(edbCntxt);
- MONKEY_free_non_null(file_names);
- return ret;
-}
-
-
-int MONKEY_ACTION_start_reverse_execution(struct MONKEY_ACTION_Context
- *cntxt)
-{
- const char *failureFile = epoch->traceListHead->functionListHead->file;
- const char *failureFunction =
- epoch->traceListHead->functionListHead->name;
- struct Trace *tracePtr = epoch->traceListHead;
- int oldLine;
-
- /*
- * We execute one step back operation before starting analysis. We do that
to go to the expression before the one where the crash occurred.
- * Because we already have the expression where the crash happened in our
stack structure from the previous epoch step (the initial epoch)
- */
- if (MONKEY_NO == stoppedInSharedLib) {
- if (MONKEY_NO != gmi_exec_next_reverse(cntxt->gdb_handle)) {
- while (!mi_get_response(cntxt->gdb_handle))
- usleep(GDB_MI_ASYNC_WAIT);
- } else {
- fprintf(stderr, "Error: Reverse Execution has failed!
Backtracking might not be supported for the current architecture.\n");
- if (MONKEY_YES == cntxt->gdb_connected) {
- mi_disconnect(cntxt->gdb_handle); // No
need for gdb mi at this point!
- cntxt->gdb_connected = MONKEY_NO;
- }
- return MONKEY_NO;
- }
- }
-
- /* Do reverse execution for all expressions in the function in which the
failure occurred */
- do {
- oldLine = tracePtr->functionListHead->line;
- if (MONKEY_NO != gmi_exec_next_reverse(cntxt->gdb_handle)) {
- if (GDB_STATE_ERROR == wait_for_stop(cntxt)) {
- fprintf(stderr, "Error: Analysis during Reverse
Execution has failed!\n");
- return MONKEY_NO;
- }
- if (oldLine == cntxt->gdb_frames->line)
- break;// We reached the end of record history
TODO: DIRTY SOLUTION! WILL FAIL IF TWO EXPRESSIONS ON THE SAME LINE
- MONKEY_ACTION_inspect_expression_database(cntxt);
- } else {
- fprintf(stderr, "Error: Reverse Execution has
failed!\n");
- return MONKEY_NO;
- }
-
- tracePtr = tracePtr->next; // tracePtr will have the new trace added
after examining the expression database for this reverse execution step
- } while ((NULL != tracePtr)
- && (strcmp(failureFile, tracePtr->functionListHead->file) ==
- 0)
- && (strcmp(failureFunction, tracePtr->functionListHead->name)
- == 0));
-
- // stop recording and return
- gmi_exec_record_stop(cntxt->gdb_handle);
- return MONKEY_OK;
-}
-
-int MONKEY_ACTION_rerun_with_valgrind(struct MONKEY_ACTION_Context
- *cntxt)
-{
- char *valgrindCommand;
- FILE *valgrindPipe;
- const char *valgrindPath = cntxt->valgrind_binary_path;
- struct stat buf;
-
- if (NULL == valgrindPath)
- valgrindPath = "/usr/bin/valgrind"; /* Assumption for valgrind
installation */
-
- /* Check if Valgrind is installed */
- if (stat(valgrindPath, &buf) != 0 && errno == ENOENT ) {
- fprintf(stderr,
- "Warning: Valgrind is not installed. Memory check aborted!\n");
- return MONKEY_NO;
- }
-
- MONKEY_asprintf(&cntxt->valgrind_output_tmp_file_name, "%d", rand());
- cntxt->debug_mode = DEBUG_MODE_VALGRIND;
- MONKEY_asprintf(&valgrindCommand,
- "%s --leak-check=yes --log-file=%s %s", valgrindPath,
- cntxt->valgrind_output_tmp_file_name,
- cntxt->binary_name);
- valgrindPipe = popen(valgrindCommand, "r");
- if (NULL == valgrindPipe) {
- fprintf(stderr, "Error in running Valgrind! Memory check aborted!\n");
- MONKEY_free(valgrindCommand);
- return MONKEY_NO;
- }
-
- pclose(valgrindPipe);
- MONKEY_free(valgrindCommand);
- return MONKEY_OK;
-}
-
-
-int MONKEY_ACTION_rerun_with_gdb(struct MONKEY_ACTION_Context
- *cntxt)
-{
- struct MONKEY_EDB_Context *edbCntxt;
- struct stat buf;
-
- /* Check if gdb is installed */
- if (NULL == cntxt->gdb_binary_path) {
- cntxt->gdb_binary_path = "/usr/bin/gdb"; /* Assumption for gdb default
installation */
- }
- if (stat(cntxt->gdb_binary_path, &buf) != 0 && errno == ENOENT ) {
- fprintf(stderr,
- "Error: gdb is not installed!\n");
- return MONKEY_NO;
- }
-
- epoch = NULL; /* Initializing epoch Data Structure */
- cntxt->debug_mode = DEBUG_MODE_GDB;
- /* This is like a file-handle for fopen.
- Here we have all the state of gdb "connection". */
- if (NULL != cntxt->gdb_binary_path)
- mi_set_gdb_exe(cntxt->gdb_binary_path);
- int ret;
-
- /* Connect to gdb child. */
- cntxt->gdb_handle = mi_connect_local();
- if (!cntxt->gdb_handle) {
- fprintf(stderr, "Error: failed to connect to gdb!\n");
- return MONKEY_NO;
- }
- fprintf(stderr, "Info: Connected to gdb!\n");
- cntxt->gdb_connected = MONKEY_YES;
-
- /* Set all callbacks. */
- 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,
cntxt->binaryArgs)) {
- fprintf(stderr, "Error: could not set gdb exec y args\n");
- goto fail;
- }
-
- /* Tell gdb to attach the child to a terminal. */
- if (!gmi_target_terminal(cntxt->gdb_handle, ttyname(STDIN_FILENO))) {
- fprintf(stderr, "Error: could not select gdb target
terminal\n");
- goto fail;
- }
-
-
- if (MONKEY_YES == cntxt->run_reverse) {
- /* If Backtracking is enabled, we must set a breakpoint at the
main function, starting the program, then starting recording */
- mi_bkpt *bp = gmi_break_insert_full(cntxt->gdb_handle, 0, 0,
NULL, -1, -1, "main");
- if (NULL == bp) {
- fprintf(stderr, "Error: gdb could not set a breakpoint
at function:%s\n",
- cntxt->inspect_function);
- goto fail;
- }
- mi_free_bkpt(bp);
- }
-
-
- if ((NULL != cntxt->inspect_expression) && (NULL !=
cntxt->inspect_function)) {
- /* Setting a breakpoint at the function containing the
expression to inspect */
- mi_bkpt *bp = gmi_break_insert_full(cntxt->gdb_handle, 0, 0,
NULL, -1, -1, cntxt->inspect_function);
- if (NULL == bp) {
- fprintf(stderr, "Error: gdb could not set a breakpoint
at function:%s\n", cntxt->inspect_function);
- goto fail;
- }
- mi_free_bkpt(bp);
- }
-
- /* Prepare a list of the file names for the source files we are analyzing
*/
- edbCntxt = MONKEY_EDB_connect(cntxt->expression_database_path);
- if (NULL == edbCntxt) {
- fprintf(stderr,
- "Unable to connect to Expression Database file!\n");
- goto fail;
- }
-
- if (MONKEY_OK != MONKEY_EDB_get_file_names(edbCntxt, &iterateFileNames,
NULL)) {
- fprintf(stderr, "Error: Pathologist could not retrieve source file
names from expression database!\n");
- goto fail;
- }
- MONKEY_EDB_disconnect(edbCntxt);
-
-
- /* Run the program. */
- if (!gmi_exec_run(cntxt->gdb_handle)) {
- fprintf(stderr, "Error: gdb could not run the target
program!\n");
- goto fail;
- }
-
- /* Backtracking is issued after running the program */
- if (MONKEY_YES == cntxt->run_reverse) {
- gmi_exec_record_process(cntxt->gdb_handle);
- }
-
- /* Here we should be stopped when the program crashes */
- ret = wait_for_stop(cntxt);
- if (ret == GDB_STATE_ERROR || ret == GDB_STATE_EXIT_NORMALLY) {
- if (MONKEY_YES == cntxt->gdb_connected) {
- mi_disconnect(cntxt->gdb_handle);
- cntxt->gdb_connected = MONKEY_NO;
- }
- }
-
- return ret;
-
- // cleanup and abort
-fail:
- if (MONKEY_YES == cntxt->gdb_connected) {
- mi_disconnect(cntxt->gdb_handle);
- cntxt->gdb_connected = MONKEY_NO;
- }
- return MONKEY_NO;
-}
-
-
-static const char *expressionListToString(struct Expression *head)
-{
- char *string = MONKEY_strdup("");
- char *strTmp;
- struct Expression *tmp;
-
- for (tmp = head; NULL != tmp; tmp = tmp->next) {
- MONKEY_asprintf(&strTmp,
- "%s%s => %s\n",
- string,
- tmp->expressionSyntax,
- NULL ==
- tmp->
- expressionValue ? "Not evaluated" :
- tmp->expressionValue);
- MONKEY_free(string);
- string = strTmp;
- }
- return string;
-}
-
-#if 0
-static int getWatchInfoListSize(struct WatchInfo *head)
-{
- int count = 0;
- int largestStr = 0;
- struct WatchInfo *tmp = head;
-
- while (NULL != tmp) {
- if (largestStr < strlen(tmp->value))
- largestStr = strlen(tmp->value);
- tmp = tmp->next;
- count++;
- }
-
- return count * largestStr;
-}
-
-static const char *watchInfoListToString(struct WatchInfo *head)
-{
- char *string = MONKEY_malloc(getWatchInfoListSize(head));
- char *strTmp;
- struct WatchInfo *tmp = head;
-
- MONKEY_asprintf(&strTmp, "%s\t \t%s\n", tmp->hitNumber, tmp->value);
- strcpy(string, strTmp);
- MONKEY_free(strTmp);
- tmp = tmp->next;
-
- while (NULL != tmp) {
- MONKEY_asprintf(&strTmp, "%s\t \t%s\n", tmp->hitNumber,
- tmp->value);
- strcat(string, strTmp);
- MONKEY_free(strTmp);
- tmp = tmp->next;
- }
-
- return string;
-}
-#endif
-
-static const char *getValgrindOutput(struct MONKEY_ACTION_Context *cntxt)
-{
- char *valgrindOutput;
- int size;
- FILE *valgrindFile = fopen(cntxt->valgrind_output_tmp_file_name, "r");
- fseek(valgrindFile, 0L, SEEK_END);
- size = ftell(valgrindFile);
- fseek(valgrindFile, 0L, SEEK_SET);
-
- valgrindOutput = MONKEY_malloc(size);
- fread(valgrindOutput, size - 1, 1, valgrindFile);
- fclose(valgrindFile);
- return valgrindOutput;
-}
-
-
-static struct MONKEY_XML_Node *createXmlSimpleNode(const char *nodeName,
- const char
- *nodeInnerText)
-{
- struct MONKEY_XML_Node *node =
- MONKEY_XML_WRITER_new_node(nodeName, nodeInnerText);
- return node;
-}
-
-
-static struct MONKEY_XML_Node *createXmlCrashNode(const char *category,
- const char *function,
- int line,
- const char *file)
-{
- struct MONKEY_XML_Node *node;
- char *lineStr;
-
- MONKEY_asprintf(&lineStr, "%d", line);
- node = MONKEY_XML_WRITER_new_node("crash", NULL);
- MONKEY_XML_WRITER_add_attribute(node, "category", category);
- MONKEY_XML_WRITER_add_attribute(node, "function", function);
- MONKEY_XML_WRITER_add_attribute(node, "line", lineStr);
- MONKEY_XML_WRITER_add_attribute(node, "file", file);
- return node;
-}
-
-
-static struct MONKEY_XML_Node *createXmlEpochStep(int step)
-{
- struct MONKEY_XML_Node *node;
- char *stepStr;
- MONKEY_asprintf(&stepStr, "%d", step);
- node = MONKEY_XML_WRITER_new_node("epoch", NULL);
- MONKEY_XML_WRITER_add_attribute(node, "step", stepStr);
- return node;
-}
-
-
-static struct MONKEY_XML_Node *createXmlFunctionNode(const char *name,
- int line,
- const char *file,
- int depth)
-{
- struct MONKEY_XML_Node *node;
- char *lineStr;
- char *depthStr;
-
- MONKEY_asprintf(&lineStr, "%d", line);
- MONKEY_asprintf(&depthStr, "%d", depth);
- node = MONKEY_XML_WRITER_new_node("function", NULL);
- MONKEY_XML_WRITER_add_attribute(node, "name", name);
- MONKEY_XML_WRITER_add_attribute(node, "line", lineStr);
- MONKEY_XML_WRITER_add_attribute(node, "file", file);
- MONKEY_XML_WRITER_add_attribute(node, "depth", depthStr);
- return node;
-}
-
-
-static struct MONKEY_XML_Node *createXmlExpressionNode(const char *name,
- const char *value)
-{
- struct MONKEY_XML_Node *node;
-
- node = MONKEY_XML_WRITER_new_node("expression", value);
- MONKEY_XML_WRITER_add_attribute(node, "name", name);
- return node;
-}
-
-
-static struct MONKEY_XML_Node *createXmlGlobalExpressionNode(const char *name,
- const char *value)
-{
- struct MONKEY_XML_Node *node;
-
- node = MONKEY_XML_WRITER_new_node("expression", value);
- MONKEY_XML_WRITER_add_attribute(node, "name", name);
- return node;
-}
-
-
-int MONKEY_ACTION_is_Nullpointer(struct MONKEY_ACTION_Context* cntxt)
-{
- mi_asm_insns* disassembled_code =
gmi_data_disassemble_se(cntxt->gdb_handle, "$pc", "$pc+1", 0);
- char* reg;
- while(reg = strstr(disassembled_code->ins->inst, "(%")) {
- //printf("%s\n", reg);
- reg++;
- size_t len = strcspn(reg, "),");
- reg[0]='$';
- reg[len]='\0';
- char* val = gmi_data_evaluate_expression(cntxt->gdb_handle,
reg);
- //printf("%s\n", val);
- if( !strcmp(val, "0") ) return 1;
- }
- return 0;
-}
-
-
-int MONKEY_ACTION_format_report_xml(struct MONKEY_ACTION_Context
- *cntxt)
-{
- int i = 0;
- struct MONKEY_XML_Node *node;
- struct MONKEY_XML_Node *historyNode;
- struct MONKEY_XML_Node *traceNode;
- struct MONKEY_XML_Node *globalsNode;
- struct Trace *tracePtr = epoch->traceListHead;
- struct Function *functionPtr = tracePtr->functionListHead;
- struct Expression *expressionPtr;
-
-
- switch (cntxt->bug_detected) {
- case BUG_NULL_POINTER:
- cntxt->xml_report_node = createXmlCrashNode("npe",
functionPtr->name, functionPtr->line, functionPtr->file);
- break;
- case BUG_BAD_MEM_ACCESS:
- cntxt->xml_report_node = createXmlCrashNode("Bad memory
access", functionPtr->name, functionPtr->line, functionPtr->file);
- node = MONKEY_XML_WRITER_add_child(cntxt->xml_report_node,
createXmlSimpleNode("valgrind", getValgrindOutput(cntxt)));
- break;
- case BUG_ABORT:
- cntxt->xml_report_node = createXmlCrashNode("Assertion
Failure", functionPtr->name, functionPtr->line, functionPtr->file);
- break;
- case BUG_ARITHMETIC:
- cntxt->xml_report_node = createXmlCrashNode("Division By Zero",
functionPtr->name, functionPtr->line, functionPtr->file);
- break;
- case BUG_SIG_BUS:
- cntxt->xml_report_node = createXmlCrashNode("Bus Error",
functionPtr->name, functionPtr->line, functionPtr->file);
- break;
- default:
- cntxt->xml_report_node = createXmlCrashNode("Unknown",
functionPtr->name, functionPtr->line, functionPtr->file);
- break;
- }
-
- historyNode = MONKEY_XML_WRITER_add_child(cntxt->xml_report_node,
createXmlSimpleNode("history", NULL));
-
- /* Adding Stack Trace Nodes to XML Report */
- while (NULL != tracePtr) {
- node = MONKEY_XML_WRITER_add_child(historyNode,
createXmlEpochStep(i));
- traceNode = MONKEY_XML_WRITER_add_child(node,
createXmlSimpleNode("trace", NULL));
- globalsNode = MONKEY_XML_WRITER_add_child(node,
createXmlSimpleNode("globals", NULL));
-
- functionPtr = tracePtr->functionListHead;
- while (NULL != functionPtr) {
- node = MONKEY_XML_WRITER_add_child(traceNode,
createXmlFunctionNode(functionPtr->name,
-
functionPtr->line,
-
functionPtr->file,
-
functionPtr->depth));
- node = MONKEY_XML_WRITER_add_child(node,
createXmlSimpleNode("expressions", NULL));
-
- expressionPtr = functionPtr->expressionListHead;
- while (NULL != expressionPtr) {
- // ignore non helpful expressions
- if( expressionPtr->expressionValue )
- MONKEY_XML_WRITER_add_child(node,
createXmlExpressionNode(expressionPtr->expressionSyntax,
expressionPtr->expressionValue));
- expressionPtr = expressionPtr->next;
- }
-
- functionPtr = functionPtr->next;
- }
-
- expressionPtr = tracePtr->globalsListHead;
- while( expressionPtr ) {
- if( expressionPtr->expressionValue )
- MONKEY_XML_WRITER_add_child(globalsNode,
createXmlGlobalExpressionNode(expressionPtr->expressionSyntax,
expressionPtr->expressionValue));
- expressionPtr = expressionPtr->next;
- }
-
-
- tracePtr = tracePtr->next;
- i++;
- }
- return MONKEY_OK;
-}
-
-
-
-
-int MONKEY_ACTION_delete_context(struct MONKEY_ACTION_Context
- *cntxt)
-{
- if (MONKEY_YES == cntxt->gdb_connected) {
- mi_disconnect(cntxt->gdb_handle);
- cntxt->gdb_connected = MONKEY_NO;
- }
- if (NULL != cntxt->debug_report)
- MONKEY_free(cntxt->debug_report);
- if (NULL != cntxt->valgrind_output_tmp_file_name) {
- remove(cntxt->valgrind_output_tmp_file_name);
- MONKEY_free(cntxt->valgrind_output_tmp_file_name);
- }
- if (NULL != cntxt->xml_report_node)
- MONKEY_XML_WRITER_delete_tree(cntxt->xml_report_node);
- if (NULL != cntxt->binaryArgs)
- MONKEY_free(cntxt->binaryArgs);
-
- MONKEY_free(cntxt);
- return MONKEY_OK;
-}
-
-
-int MONKEY_ACTION_check_bug_redundancy()
-{
- return MONKEY_OK;
-}
Modified: monkey/trunk/pathologist/src/pathologist/pathologist.c
===================================================================
--- monkey/trunk/pathologist/src/pathologist/pathologist.c 2013-02-11
08:49:40 UTC (rev 26062)
+++ monkey/trunk/pathologist/src/pathologist/pathologist.c 2013-02-11
09:49:40 UTC (rev 26063)
@@ -28,11 +28,9 @@
#include <unistd.h>
#include <sys/stat.h>
#include "monkey_common.h"
-#include "pathologist_action.h"
+#include "action.h"
#include "monkey_getopt_lib.h"
-#define MIN_ARG_REQUIRED 2
-
static char *dumpFileName;
static char *binaryName;
static char *command;
Deleted: monkey/trunk/pathologist/src/pathologist/pathologist_action.h
===================================================================
--- monkey/trunk/pathologist/src/pathologist/pathologist_action.h
2013-02-11 08:49:40 UTC (rev 26062)
+++ monkey/trunk/pathologist/src/pathologist/pathologist_action.h
2013-02-11 09:49:40 UTC (rev 26063)
@@ -1,100 +0,0 @@
-/**
- * @file monkey/MONKEY_action.h
- * @brief Monkey API for actions taken by Monkey while debugging
- */
-
-#ifndef MONKEY_ACTION_H
-#define MONKEY_ACTION_H
-
-#include "gdbmi.h"
-#include "pathologist_xml_writer.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0 /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-
-/* Debug constants */
-#define DEBUG_MODE_GDB 0
-#define GDB_STATE_STOPPED 1
-#define GDB_STATE_EXIT_NORMALLY 2
-#define GDB_STATE_ERROR 3
-#define GDB_SAFETY_COUNT 2
-#define DEBUG_MODE_VALGRIND 4
-#define DEBUG_MODE_REPORT_READY 5
-#define NO_BUG_DETECTED -1
-#define BUG_NULL_POINTER 6
-#define BUG_ABORT 7
-#define BUG_ARITHMETIC 8
-#define BUG_BAD_MEM_ACCESS 9
-#define BUG_SIG_BUS 10
-#define GDB_MI_ASYNC_WAIT 5
-
-/**
- * Context for the Action API
- */
-struct MONKEY_ACTION_Context
-{
- const char *binary_name;
- char *binaryArgs;
- const char *email_address;
- const char *expression_database_path;
- const char *gdb_binary_path;
- const char *valgrind_binary_path;
- const char *inspect_expression;
- const char *inspect_function;
- int debug_mode;
- int bug_detected;
- int has_null;
- char *debug_report;
- struct MONKEY_XML_Node *xml_report_node;
-
- /* gdb debugging attributes */
- int run_reverse;
- int scope_depth;
- mi_h *gdb_handle;
- int gdb_connected;
- const char *gdb_in_use;
- mi_stop *gdb_stop_reason;
- mi_frames *gdb_frames;
- const char *gdb_null_variable;
-
- /* Valgrind memcheck attributes */
- char* valgrind_output_tmp_file_name;
-};
-
-
-int MONKEY_ACTION_report_file (struct MONKEY_ACTION_Context
- *cntxt, const char *dumpFileName, int
isXML);
-int MONKEY_ACTION_report_email (struct MONKEY_ACTION_Context
- *cntxt, const char *dumpFileName);
-int MONKEY_ACTION_inspect_expression_database (struct
- MONKEY_ACTION_Context
- *cntxt);
-int MONKEY_ACTION_rerun_with_gdb (struct MONKEY_ACTION_Context
- *cntxt);
-int MONKEY_ACTION_start_reverse_execution(struct MONKEY_ACTION_Context *
cntxt);
-int MONKEY_ACTION_rerun_with_valgrind (struct
- MONKEY_ACTION_Context
- *cntxt);
-int MONKEY_ACTION_format_report (struct MONKEY_ACTION_Context
- *cntxt);
-int
-MONKEY_ACTION_format_report_xml (struct MONKEY_ACTION_Context
- *cntxt);
-int MONKEY_ACTION_delete_context(struct MONKEY_ACTION_Context *cntxt);
-
-int MONKEY_ACTION_check_bug_redundancy (void);
-
-
-#if 0 /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r26063 - monkey/trunk/pathologist/src/pathologist,
gnunet <=