diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/monkey/Makefile.am | 6 | ||||
-rw-r--r-- | src/monkey/action_api.c | 96 | ||||
-rwxr-xr-x | src/monkey/bug_bad_memory_access | bin | 0 -> 9226 bytes | |||
-rw-r--r-- | src/monkey/bug_bad_memory_access.c | 16 | ||||
-rw-r--r-- | src/monkey/gnunet-monkey.c | 12 | ||||
-rw-r--r-- | src/monkey/gnunet_monkey_action.h | 6 |
6 files changed, 106 insertions, 30 deletions
diff --git a/src/monkey/Makefile.am b/src/monkey/Makefile.am index 44042dfdd..effa37bd4 100644 --- a/src/monkey/Makefile.am +++ b/src/monkey/Makefile.am | |||
@@ -40,7 +40,8 @@ bin_PROGRAMS = \ | |||
40 | gnunet-service-monkey | 40 | gnunet-service-monkey |
41 | 41 | ||
42 | noinst_PROGRAMS = \ | 42 | noinst_PROGRAMS = \ |
43 | bug_null_pointer_exception | 43 | bug_null_pointer_exception \ |
44 | bug_bad_memory_access | ||
44 | 45 | ||
45 | gnunet_monkey_SOURCES = \ | 46 | gnunet_monkey_SOURCES = \ |
46 | gdbmi.h \ | 47 | gdbmi.h \ |
@@ -80,6 +81,9 @@ gnunet_service_monkey_LDADD = \ | |||
80 | bug_null_pointer_exception: | 81 | bug_null_pointer_exception: |
81 | gcc -g -O0 -o bug_null_pointer_exception bug_null_pointer_exception.c | 82 | gcc -g -O0 -o bug_null_pointer_exception bug_null_pointer_exception.c |
82 | 83 | ||
84 | bug_bad_memory_access: | ||
85 | gcc -g -O0 -o bug_bad_memory_access bug_bad_memory_access.c | ||
86 | |||
83 | check_PROGRAMS = \ | 87 | check_PROGRAMS = \ |
84 | test_monkey_edb | 88 | test_monkey_edb |
85 | #test_gnunet_monkey | 89 | #test_gnunet_monkey |
diff --git a/src/monkey/action_api.c b/src/monkey/action_api.c index 0412c7630..99809f82f 100644 --- a/src/monkey/action_api.c +++ b/src/monkey/action_api.c | |||
@@ -122,12 +122,6 @@ int GNUNET_MONKEY_ACTION_report_email(struct GNUNET_MONKEY_ACTION_Context* cntxt | |||
122 | } | 122 | } |
123 | 123 | ||
124 | 124 | ||
125 | |||
126 | int GNUNET_MONKEY_ACTION_rerun_with_valgrind() | ||
127 | { | ||
128 | return GNUNET_OK; | ||
129 | } | ||
130 | |||
131 | static int iterateExpressions(void *cls, int numColumns, char **colValues, char **colNames) | 125 | static int iterateExpressions(void *cls, int numColumns, char **colValues, char **colNames) |
132 | { | 126 | { |
133 | struct Expression *expression; | 127 | struct Expression *expression; |
@@ -159,10 +153,10 @@ static int scopeEndCallback(void *cls, int numColumns, char **colValues, char ** | |||
159 | 153 | ||
160 | static int analyzeSegmentationFault(struct GNUNET_MONKEY_ACTION_Context *cntxt) | 154 | static int analyzeSegmentationFault(struct GNUNET_MONKEY_ACTION_Context *cntxt) |
161 | { | 155 | { |
162 | struct Expression *faultyExpression; | 156 | struct Expression *faultyExpression = NULL; |
163 | struct Expression *tmp; | 157 | struct Expression *tmp; |
164 | int expressionLength = 0; | 158 | int expressionLength = 0; |
165 | mi_wp *watchPoint; | 159 | //mi_wp *watchPoint; |
166 | 160 | ||
167 | tmp = expressionListHead; | 161 | tmp = expressionListHead; |
168 | while (NULL != tmp) { | 162 | while (NULL != tmp) { |
@@ -174,23 +168,40 @@ static int analyzeSegmentationFault(struct GNUNET_MONKEY_ACTION_Context *cntxt) | |||
174 | tmp = tmp->next; | 168 | tmp = tmp->next; |
175 | } | 169 | } |
176 | 170 | ||
177 | /* Set watch points on the faulty-expression's subexpressions */ | 171 | if (NULL != faultyExpression) { |
178 | tmp = expressionListHead; | 172 | tmp = expressionListHead; |
179 | while (NULL != tmp) { | 173 | while (NULL != tmp) { |
180 | if (tmp != faultyExpression) { | 174 | const char* eval; |
181 | /* Only subexpressions are interesting */ | 175 | if (tmp != faultyExpression) { |
182 | watchPoint = gmi_break_watch(cntxt->gdb_handle, wm_write, tmp->expressionSyntax); | 176 | eval = gmi_data_evaluate_expression(cntxt->gdb_handle, tmp->expressionSyntax); |
183 | if (!watchPoint) | 177 | if (NULL != eval && strcmp(eval, "0x0") == 0) { |
184 | { | 178 | cntxt->gdb_null_variable = tmp->expressionSyntax; |
185 | printf("Error in setting watchpoint\n"); | 179 | return GNUNET_OK; |
186 | return 1; | 180 | } |
187 | } | 181 | } |
188 | printf("Watchpoint %d for expression: %s\n", watchPoint->number, watchPoint->exp); | 182 | tmp = tmp->next; |
189 | mi_free_wp(watchPoint); | ||
190 | } | 183 | } |
191 | tmp = tmp->next; | ||
192 | } | 184 | } |
193 | return GNUNET_OK; | 185 | /* Set watch points on the faulty-expression's subexpressions */ |
186 | // if (NULL != faultyExpression) { | ||
187 | // tmp = expressionListHead; | ||
188 | // while (NULL != tmp) { | ||
189 | // if (tmp != faultyExpression) { | ||
190 | // /* Only subexpressions are interesting */ | ||
191 | // watchPoint = gmi_break_watch(cntxt->gdb_handle, wm_write, tmp->expressionSyntax); | ||
192 | // if (!watchPoint) | ||
193 | // { | ||
194 | // printf("Error in setting watchpoint\n"); | ||
195 | // return 1; | ||
196 | // } | ||
197 | // printf("Watchpoint %d for expression: %s\n", watchPoint->number, watchPoint->exp); | ||
198 | // mi_free_wp(watchPoint); | ||
199 | // } | ||
200 | // tmp = tmp->next; | ||
201 | // } | ||
202 | // return GNUNET_OK; | ||
203 | // } | ||
204 | return GDB_STATE_ERROR; | ||
194 | } | 205 | } |
195 | 206 | ||
196 | 207 | ||
@@ -219,13 +230,39 @@ int GNUNET_MONKEY_ACTION_inspect_expression_database(struct GNUNET_MONKEY_ACTION | |||
219 | NULL); | 230 | NULL); |
220 | 231 | ||
221 | if (strcasecmp(cntxt->gdb_stop_reason->signal_meaning, "Segmentation fault") == 0) | 232 | if (strcasecmp(cntxt->gdb_stop_reason->signal_meaning, "Segmentation fault") == 0) |
222 | analyzeSegmentationFault(cntxt); | 233 | ret = analyzeSegmentationFault(cntxt); |
223 | 234 | ||
224 | GNUNET_MONKEY_EDB_disconnect(edbCntxt); | 235 | GNUNET_MONKEY_EDB_disconnect(edbCntxt); |
236 | mi_disconnect(cntxt->gdb_handle); | ||
225 | return ret; | 237 | return ret; |
226 | } | 238 | } |
227 | 239 | ||
228 | 240 | ||
241 | int GNUNET_MONKEY_ACTION_rerun_with_valgrind(struct GNUNET_MONKEY_ACTION_Context* cntxt) { | ||
242 | FILE* valgrindPipe; | ||
243 | int size; | ||
244 | const char* valgrindCommand; | ||
245 | cntxt->debug_mode = DEBUG_MODE_VALGRIND; | ||
246 | asprintf(&valgrindCommand, "valgrind --leak-check=yes %s", cntxt->binary_name); | ||
247 | valgrindPipe = popen(valgrindCommand, "r"); | ||
248 | if (NULL == valgrindPipe) { | ||
249 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error in running Valgrind!\n"); | ||
250 | return GNUNET_NO; | ||
251 | } | ||
252 | |||
253 | fscanf(valgrindPipe, "%d", &size); | ||
254 | |||
255 | /* Read Valgrind stream */ | ||
256 | cntxt->valgrind_output = GNUNET_malloc(size); | ||
257 | fscanf(valgrindPipe, "%s", cntxt->valgrind_output); | ||
258 | if (0 != pclose(valgrindPipe)) { | ||
259 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error while closing Valgrind pipe!\n"); | ||
260 | return GNUNET_NO; | ||
261 | } | ||
262 | return GNUNET_OK; | ||
263 | } | ||
264 | |||
265 | |||
229 | int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cntxt) | 266 | int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cntxt) |
230 | { | 267 | { |
231 | cntxt->debug_mode = DEBUG_MODE_GDB; | 268 | cntxt->debug_mode = DEBUG_MODE_GDB; |
@@ -278,7 +315,7 @@ int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cnt | |||
278 | } | 315 | } |
279 | /* Here we should be stopped when the program crashes */ | 316 | /* Here we should be stopped when the program crashes */ |
280 | ret = wait_for_stop(cntxt->gdb_handle, cntxt); | 317 | ret = wait_for_stop(cntxt->gdb_handle, cntxt); |
281 | if (ret != GDB_STATE_ERROR) | 318 | if (ret == GDB_STATE_ERROR) |
282 | mi_disconnect(cntxt->gdb_handle); | 319 | mi_disconnect(cntxt->gdb_handle); |
283 | 320 | ||
284 | return ret; | 321 | return ret; |
@@ -290,10 +327,15 @@ int GNUNET_MONKEY_ACTION_format_report(struct GNUNET_MONKEY_ACTION_Context* cntx | |||
290 | switch (cntxt->debug_mode) { | 327 | switch (cntxt->debug_mode) { |
291 | case DEBUG_MODE_GDB: | 328 | case DEBUG_MODE_GDB: |
292 | GNUNET_asprintf(&(cntxt->debug_report), | 329 | GNUNET_asprintf(&(cntxt->debug_report), |
293 | "Bug detected in file:%s\nfunction:%s\nline:%d\nreason:%s\nreceived signal:%s\n%s\n", | 330 | "Bug detected in file:%s\nfunction:%s\nline:%d\nreason:%s\nreceived signal:%s\n%s\n Details:\n Expression:%s is NULL\n", |
294 | cntxt->gdb_frames->file, cntxt->gdb_frames->func, cntxt->gdb_frames->line, mi_reason_enum_to_str(cntxt->gdb_stop_reason->reason), cntxt->gdb_stop_reason->signal_name, cntxt->gdb_stop_reason->signal_meaning); | 331 | cntxt->gdb_frames->file, cntxt->gdb_frames->func, cntxt->gdb_frames->line, mi_reason_enum_to_str(cntxt->gdb_stop_reason->reason), |
332 | cntxt->gdb_stop_reason->signal_name, cntxt->gdb_stop_reason->signal_meaning, cntxt->gdb_null_variable); | ||
295 | break; | 333 | break; |
296 | case DEBUG_MODE_VALGRIND: | 334 | case DEBUG_MODE_VALGRIND: |
335 | GNUNET_asprintf(&(cntxt->debug_report), | ||
336 | "Bug detected in file:%s\nfunction:%s\nline:%d\nreason:%s\nreceived signal:%s\n%s\n Details:\n Memory Check from Valgrind:%s\n", | ||
337 | cntxt->gdb_frames->file, cntxt->gdb_frames->func, cntxt->gdb_frames->line, mi_reason_enum_to_str(cntxt->gdb_stop_reason->reason), | ||
338 | cntxt->gdb_stop_reason->signal_name, cntxt->gdb_stop_reason->signal_meaning, cntxt->valgrind_output); | ||
297 | break; | 339 | break; |
298 | default: | 340 | default: |
299 | break; | 341 | break; |
diff --git a/src/monkey/bug_bad_memory_access b/src/monkey/bug_bad_memory_access new file mode 100755 index 000000000..ddd87c243 --- /dev/null +++ b/src/monkey/bug_bad_memory_access | |||
Binary files differ | |||
diff --git a/src/monkey/bug_bad_memory_access.c b/src/monkey/bug_bad_memory_access.c new file mode 100644 index 000000000..54e50ade0 --- /dev/null +++ b/src/monkey/bug_bad_memory_access.c | |||
@@ -0,0 +1,16 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | |||
4 | |||
5 | void badMemoryAccess() | ||
6 | { | ||
7 | int *p = (int*) 0x4252352; | ||
8 | printf("Bad memory access now!\n"); | ||
9 | *p = 5; | ||
10 | } | ||
11 | |||
12 | int main(int argc, char *argv[]) | ||
13 | { | ||
14 | badMemoryAccess(); | ||
15 | return 0; | ||
16 | } | ||
diff --git a/src/monkey/gnunet-monkey.c b/src/monkey/gnunet-monkey.c index 7821936bf..030eb0774 100644 --- a/src/monkey/gnunet-monkey.c +++ b/src/monkey/gnunet-monkey.c | |||
@@ -77,6 +77,7 @@ run (void *cls, | |||
77 | 77 | ||
78 | result = GNUNET_MONKEY_ACTION_rerun_with_gdb(cntxt); | 78 | result = GNUNET_MONKEY_ACTION_rerun_with_gdb(cntxt); |
79 | switch (result) { | 79 | switch (result) { |
80 | int retVal; | ||
80 | case GDB_STATE_ERROR: | 81 | case GDB_STATE_ERROR: |
81 | break; | 82 | break; |
82 | case GDB_STATE_EXIT_NORMALLY: | 83 | case GDB_STATE_EXIT_NORMALLY: |
@@ -85,10 +86,19 @@ run (void *cls, | |||
85 | break; | 86 | break; |
86 | case GDB_STATE_STOPPED: | 87 | case GDB_STATE_STOPPED: |
87 | /*FIXME: Expression Database should be inspected here (before writing the report) */ | 88 | /*FIXME: Expression Database should be inspected here (before writing the report) */ |
88 | if (GNUNET_OK != GNUNET_MONKEY_ACTION_inspect_expression_database(cntxt)) { | 89 | retVal = GNUNET_MONKEY_ACTION_inspect_expression_database(cntxt); |
90 | if (GNUNET_NO == retVal) { | ||
89 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error using Expression Database!\n"); | 91 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error using Expression Database!\n"); |
90 | ret = 1; | 92 | ret = 1; |
91 | break; | 93 | break; |
94 | } else if (GDB_STATE_ERROR == retVal) { | ||
95 | /* GDB could not locate a NULL value expression, launch Valgrind */ | ||
96 | retVal = GNUNET_MONKEY_ACTION_rerun_with_valgrind(cntxt); | ||
97 | if (GNUNET_NO == retVal) { | ||
98 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error using Valgrind!\n"); | ||
99 | ret = 1; | ||
100 | break; | ||
101 | } | ||
92 | } | 102 | } |
93 | if(GNUNET_OK != GNUNET_MONKEY_ACTION_format_report(cntxt)){ | 103 | if(GNUNET_OK != GNUNET_MONKEY_ACTION_format_report(cntxt)){ |
94 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error in generating debug report!\n"); | 104 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error in generating debug report!\n"); |
diff --git a/src/monkey/gnunet_monkey_action.h b/src/monkey/gnunet_monkey_action.h index dd96a03a5..d8af8d712 100644 --- a/src/monkey/gnunet_monkey_action.h +++ b/src/monkey/gnunet_monkey_action.h | |||
@@ -63,14 +63,18 @@ struct GNUNET_MONKEY_ACTION_Context | |||
63 | const char* gdb_in_use; | 63 | const char* gdb_in_use; |
64 | mi_stop* gdb_stop_reason; | 64 | mi_stop* gdb_stop_reason; |
65 | mi_frames* gdb_frames; | 65 | mi_frames* gdb_frames; |
66 | const char* gdb_null_variable; | ||
67 | |||
68 | /* Valgrind memcheck attributes */ | ||
69 | char* valgrind_output; | ||
66 | }; | 70 | }; |
67 | 71 | ||
68 | 72 | ||
69 | int GNUNET_MONKEY_ACTION_report_file(struct GNUNET_MONKEY_ACTION_Context* cntxt, const char* dumpFileName); | 73 | int GNUNET_MONKEY_ACTION_report_file(struct GNUNET_MONKEY_ACTION_Context* cntxt, const char* dumpFileName); |
70 | int GNUNET_MONKEY_ACTION_report_email(struct GNUNET_MONKEY_ACTION_Context* cntxt); | 74 | int GNUNET_MONKEY_ACTION_report_email(struct GNUNET_MONKEY_ACTION_Context* cntxt); |
71 | int GNUNET_MONKEY_ACTION_rerun_with_valgrind(void); | ||
72 | int GNUNET_MONKEY_ACTION_inspect_expression_database(struct GNUNET_MONKEY_ACTION_Context* cntxt); | 75 | int GNUNET_MONKEY_ACTION_inspect_expression_database(struct GNUNET_MONKEY_ACTION_Context* cntxt); |
73 | int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cntxt); | 76 | int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cntxt); |
77 | int GNUNET_MONKEY_ACTION_rerun_with_valgrind(struct GNUNET_MONKEY_ACTION_Context* cntxt); | ||
74 | int GNUNET_MONKEY_ACTION_format_report(struct GNUNET_MONKEY_ACTION_Context* cntxt); | 78 | int GNUNET_MONKEY_ACTION_format_report(struct GNUNET_MONKEY_ACTION_Context* cntxt); |
75 | int GNUNET_MONKEY_ACTION_check_bug_redundancy(void); | 79 | int GNUNET_MONKEY_ACTION_check_bug_redundancy(void); |
76 | 80 | ||