/* * updates variables from vars list */ void get_variables (GList *vars) { while (vars) { gchar command[1000]; variable *var = (variable*)vars->data; gchar *varname = var->internal->str; gchar *record = NULL; gchar *pos; /* path expression */ sprintf(command, "-var-info-path-expression \"%s\"", varname); exec_sync_command(command, TRUE, &record); pos = strstr(record, "path_expr=\"") + strlen("path_expr=\""); *(strrchr(pos, '\"')) = '\0'; gchar *expression = unescape(pos); g_string_assign(var->expression, expression); g_free(expression); g_free(record); /* children number */ sprintf(command, "-var-info-num-children \"%s\"", varname); exec_sync_command(command, TRUE, &record); pos = strstr(record, "numchild=\"") + strlen("numchild=\""); *(strchr(pos, '\"')) = '\0'; int numchild = atoi(pos); var->has_children = numchild > 0; g_free(record); /* value */ sprintf(command, "-data-evaluate-expression \"%s\"", var->expression->str); exec_sync_command(command, TRUE, &record); pos = strstr(record, "value=\""); if (!pos) { g_free(record); sprintf(command, "-var-evaluate-expression \"%s\"", varname); exec_sync_command(command, TRUE, &record); pos = strstr(record, "value=\""); } pos += + strlen("value=\""); *(strrchr(pos, '\"')) = '\0'; gchar *value = unescape(pos); g_string_assign(var->value, value); g_free(value); g_free(record); /* type */ sprintf(command, "-var-info-type \"%s\"", varname); exec_sync_command(command, TRUE, &record); pos = strstr(record, "type=\"") + strlen("type=\""); *(strchr(pos, '\"')) = '\0'; g_string_assign(var->type, pos); g_free(record); vars = vars->next; } }
/* * get list of children */ GList* get_children (gchar* path) { GList *children = NULL; gchar command[1000]; result_class rc; gchar *record = NULL; gchar *pos = NULL; /* children number */ sprintf(command, "-var-info-num-children \"%s\"", path); rc = exec_sync_command(command, TRUE, &record); if (RC_DONE != rc) return NULL; pos = strstr(record, "numchild=\"") + strlen("numchild=\""); *(strchr(pos, '\"')) = '\0'; int numchild = atoi(pos); g_free(record); if (!numchild) return NULL; /* recursive get children and put into list */ sprintf(command, "-var-list-children \"%s\"", path); rc = exec_sync_command(command, TRUE, &record); if (RC_DONE == rc) { pos = record; while ( (pos = strstr(pos, "child={")) ) { gchar *name, *internal; /* name */ pos = strstr(pos, "name=\"") + strlen("name=\""); *(strstr(pos, "\",exp=\"")) = '\0'; internal = pos; pos += strlen(pos) + 1; /* exp */ pos = strstr(pos, "exp=\"") + strlen("exp=\""); *(strstr(pos, "\",numchild=\"")) = '\0'; name = g_strcompress(pos); variable *var = variable_new2(name, internal, VT_CHILD); var->evaluated = TRUE; pos += strlen(pos) + 1; children = g_list_prepend(children, var); g_free(name); } } g_free(record); get_variables(children); return children; }
/* * gets breakpoint number by file and line */ int get_break_number(char* file, int line) { gchar* record; exec_sync_command("-break-list", TRUE, &record); gchar* bstart = record; while ( (bstart = strstr(bstart, "bkpt=")) ) { bstart += strlen("bkpt={number=\""); *strchr(bstart, '\"') = '\0'; int num = atoi(bstart); bstart += strlen(bstart) + 1; bstart = strstr(bstart, "original-location=\"") + strlen("original-location=\""); *strchr(bstart, ':') = '\0'; gchar *fname = bstart; bstart += strlen(bstart) + 1; *strchr(bstart, '\"') = '\0'; int bline = atoi(bstart); if (!strcmp(fname, file) && bline == line) return num; bstart += strlen(bstart) + 1; } free(record); return -1; }
/* * add new watch */ variable* add_watch(gchar* expression) { gchar command[1000]; variable *var = variable_new(expression, VT_WATCH); watches = g_list_append(watches, var); /* try to create a variable */ gchar *record = NULL; gchar *escaped = g_strescape(expression, NULL); sprintf(command, "-var-create - * \"%s\"", escaped); g_free(escaped); if (RC_DONE != exec_sync_command(command, TRUE, &record)) { g_free(record); return var; } gchar *pos = strstr(record, "name=\"") + strlen("name=\""); *strchr(pos, '\"') = '\0'; g_string_assign(var->internal, pos); var->evaluated = TRUE; GList *vars = g_list_append(NULL, var); get_variables(vars); g_free(record); g_list_free(vars); return var; }
/* * updates files list */ void update_files() { if (files) { /* free previous list */ g_list_foreach(files, (GFunc)g_free, NULL); g_list_free(files); files = NULL; } GHashTable *ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); gchar *record = NULL; exec_sync_command("-file-list-exec-source-files", TRUE, &record); gchar *pos = record; while ( (pos = strstr(pos, "fullname=\"")) ) { pos += strlen("fullname=\""); *(strchr(pos, '\"')) = '\0'; if (!g_hash_table_lookup(ht, pos)) { g_hash_table_insert(ht, (gpointer)pos, (gpointer)1); files = g_list_append(files, g_strdup(pos)); } pos += strlen(pos) + 1; } g_hash_table_destroy(ht); g_free(record); }
/* * select frame */ static void set_active_frame(int frame_number) { gchar *command = g_strdup_printf("-stack-select-frame %i", frame_number); if (RC_DONE == exec_sync_command(command, TRUE, NULL)) { active_frame = frame_number; update_autos(); update_watches(); } g_free(command); }
/* * removes breakpoint */ gboolean remove_break(breakpoint* bp) { /* find break number */ int number = get_break_number(bp->file, bp->line); if (-1 != number) { gchar command[100]; sprintf(command, "-break-delete %i", number); result_class rc = exec_sync_command(command, TRUE, NULL); return RC_DONE == rc; } return FALSE; }
/* * remove watch */ void remove_watch(gchar* internal) { GList *iter = watches; while (iter) { variable *var = (variable*)iter->data; if (!strcmp(var->internal->str, internal)) { gchar command[1000]; sprintf(command, "-var-delete %s", internal); exec_sync_command(command, TRUE, NULL); variable_free(var); watches = g_list_delete_link(watches, iter); } iter = iter->next; } }
/* * gets breakpoint number by file and line */ static int get_break_number(char* file, int line) { gchar *record, *bstart; exec_sync_command("-break-list", TRUE, &record); bstart = record; while ( (bstart = strstr(bstart, "bkpt=")) ) { gchar *fname, *file_quoted; int num, bline; gboolean break_found; bstart += strlen("bkpt={number=\""); *strchr(bstart, '\"') = '\0'; num = atoi(bstart); bstart += strlen(bstart) + 1; bstart = strstr(bstart, "original-location=\"") + strlen("original-location=\""); *strchr(bstart, ':') = '\0'; fname = bstart; bstart += strlen(bstart) + 1; *strchr(bstart, '\"') = '\0'; bline = atoi(bstart); file_quoted = g_strdup_printf("\\\"%s\\\"", file); break_found = !strcmp(fname, file_quoted) && bline == line; g_free(file_quoted); if (break_found) { return num; } bstart += strlen(bstart) + 1; } free(record); return -1; }
/* * evaluates given expression and returns the result */ gchar *evaluate_expression(gchar *expression) { gchar *record = NULL; char command[1000]; sprintf (command, "-data-evaluate-expression \"%s\"", expression); result_class rc = exec_sync_command(command, TRUE, &record); if (RC_DONE != rc) { g_free(record); return NULL; } gchar *pos = strstr(record, "value=\"") + strlen("value=\""); *(strrchr(pos, '\"')) = '\0'; gchar *retval = unescape(pos); return retval; }
/* * set breakpoint */ gboolean set_break(breakpoint* bp, break_set_activity bsa) { char command[1000]; if (BSA_NEW_BREAK == bsa) { /* new breakpoint */ gchar *record = NULL; /* 1. insert breakpoint */ sprintf (command, "-break-insert %s:%i", bp->file, bp->line); if (RC_DONE != exec_sync_command(command, TRUE, &record)) { g_free(record); sprintf (command, "-break-insert -f %s:%i", bp->file, bp->line); if (RC_DONE != exec_sync_command(command, TRUE, &record)) { g_free(record); return FALSE; } } /* lookup break-number */ char *pos = strstr(record, "number=\"") + strlen("number=\""); *strchr(pos, '\"') = '\0'; int number = atoi(pos); g_free(record); /* 2. set hits count if differs from 0 */ if (bp->hitscount) { sprintf (command, "-break-after %i %i", number, bp->hitscount); exec_sync_command(command, TRUE, NULL); } /* 3. set condition if exists */ if (strlen(bp->condition)) { sprintf (command, "-break-condition %i %s", number, bp->condition); if (RC_DONE != exec_sync_command(command, TRUE, NULL)) return FALSE; } /* 4. disable if disabled */ if (!bp->enabled) { sprintf (command, "-break-disable %i", number); exec_sync_command(command, TRUE, NULL); } return TRUE; } else { /* modify existing breakpoint */ int bnumber = get_break_number(bp->file, bp->line); if (-1 == bnumber) return FALSE; if (BSA_UPDATE_ENABLE == bsa) sprintf (command, bp->enabled ? "-break-enable %i" : "-break-disable %i", bnumber); else if (BSA_UPDATE_HITS_COUNT == bsa) sprintf (command, "-break-after %i %i", bnumber, bp->hitscount); else if (BSA_UPDATE_CONDITION == bsa) sprintf (command, "-break-condition %i %s", bnumber, bp->condition); return RC_DONE == exec_sync_command(command, TRUE, NULL); } return FALSE; }
/* * stops GDB */ void stop() { exec_sync_command("-gdb-exit", FALSE, NULL); }
/* * updates autos list */ void update_autos() { gchar command[1000]; /* remove all previous GDB variables for autos */ GList *iter = autos; while (iter) { variable *var = (variable*)iter->data; sprintf(command, "-var-delete %s", var->internal->str); exec_sync_command(command, TRUE, NULL); iter = iter->next; } g_list_foreach(autos, (GFunc)variable_free, NULL); g_list_free(autos); autos = NULL; /* add current autos to the list */ GList *unevaluated = NULL; const char *gdb_commands[] = { "-stack-list-arguments 0 0 0", "-stack-list-locals 0" }; int i, size = sizeof (gdb_commands) / sizeof(char*); for (i = 0; i < size; i++) { gchar *record = NULL; result_class rc = exec_sync_command(gdb_commands[i], TRUE, &record); if (RC_DONE != rc) break; gchar *pos = record; while ((pos = strstr(pos, "name=\""))) { pos += strlen("name=\""); *(strchr(pos, '\"')) = '\0'; variable *var = variable_new(pos, i ? VT_LOCAL : VT_ARGUMENT); /* create new gdb variable */ gchar *create_record = NULL; gchar *escaped = g_strescape(pos, NULL); sprintf(command, "-var-create - * \"%s\"", escaped); g_free(escaped); /* form new variable */ if (RC_DONE == exec_sync_command(command, TRUE, &create_record)) { gchar *intname = strstr(create_record, "name=\"") + strlen ("name=\""); *strchr(intname, '\"') = '\0'; var->evaluated = TRUE; g_string_assign(var->internal, intname); autos = g_list_append(autos, var); g_free(create_record); } else { var->evaluated = FALSE; g_string_assign(var->internal, ""); unevaluated = g_list_append(unevaluated, var); } pos += strlen(pos) + 1; } g_free(record); } /* get values for the autos (without incorrect variables) */ get_variables(autos); /* add incorrect variables */ autos = g_list_concat(autos, unevaluated); }
/* * updates watches list */ void update_watches() { gchar command[1000]; /* delete all GDB variables */ GList *iter = watches; while (iter) { variable *var = (variable*)iter->data; if (var->internal->len) { sprintf(command, "-var-delete %s", var->internal->str); exec_sync_command(command, TRUE, NULL); } /* reset all variables fields */ variable_reset(var); iter = iter->next; } /* create GDB variables, adding successfully created variables to the list then passed for updatind */ GList *updating = NULL; iter = watches; while (iter) { variable *var = (variable*)iter->data; /* try to create variable */ gchar *record = NULL; gchar *escaped = g_strescape(var->name->str, NULL); sprintf(command, "-var-create - * \"%s\"", escaped); g_free(escaped); if (RC_DONE != exec_sync_command(command, TRUE, &record)) { /* do not include to updating list, move to next watch */ var->evaluated = FALSE; g_string_assign(var->internal, ""); g_free(record); iter = iter->next; continue; } /* find and assign internal name */ gchar *pos = strstr(record, "name=\"") + strlen("name=\""); *strchr(pos, '\"') = '\0'; g_string_assign(var->internal, pos); g_free(record); var->evaluated = TRUE; /* add to updating list */ updating = g_list_append(updating, var); iter = iter->next; } /* update watches */ get_variables(updating); /* free updating list */ g_list_free(updating); }
/* * gets stack */ GList* get_stack() { gchar* record = NULL; result_class rc = exec_sync_command("-stack-list-frames", TRUE, &record); if (RC_DONE != rc) return NULL; GList *stack = NULL; gchar **frames = g_strsplit(record, "frame=", 0); gchar **next = frames + 1; while (*next) { frame *f = frame_new(); /* adresss */ gchar* pos = strstr(*next, "addr=\"") + strlen("addr=\""); *strchr(pos, '\"') = '\0'; f->address = g_strdup(pos); pos += strlen(pos) + 1; /* function */ pos = strstr(pos, "func=\"") + strlen("func=\""); *strchr(pos, '\"') = '\0'; f->function = g_strdup(pos); pos += strlen(pos) + 1; /* file: fullname | file | from */ char* fullname = strstr(pos, "fullname=\""); char* file = strstr(pos, "file=\""); char* from = strstr(pos, "from=\""); if (fullname) { fullname += strlen("fullname=\""); pos = fullname; *strchr(pos, '\"') = '\0'; f->file = g_strdup(pos); pos += strlen(pos) + 1; } else if (file) { file += strlen("file=\""); pos = file; *strchr(pos, '\"') = '\0'; f->file = g_strdup(pos); pos += strlen(pos) + 1; } else if (from) { from += strlen("from=\""); pos = from; *strchr(pos, '\"') = '\0'; f->file = g_strdup(pos); pos += strlen(pos) + 1; } else { f->file = g_strdup(""); } /* whether source is available */ f->have_source = fullname ? TRUE : FALSE; /* line */ int line = 0; pos = strstr(pos, "line=\""); if (pos) { pos += strlen("line=\""); *strchr(pos, '\"') = '\0'; line = atoi(pos); pos += strlen(pos) + 1; } f->line = line; stack = g_list_append(stack, f); next++; } g_strfreev(frames); free(record); return stack; }
static ssize_t sync_store(struct device_driver *driver, const char *buf, size_t count) { /* DBG(SYNC, "%s\n", buf); */ return exec_sync_command(buf, count); }