static int gdb_regformat (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { int fm, regno, numregs; struct type *type; if (objc != 3) { Tcl_WrongNumArgs (interp, 0, objv, "gdb_reginfo regno type format"); return TCL_ERROR; } if (Tcl_GetIntFromObj (interp, objv[0], ®no) != TCL_OK) return TCL_ERROR; type = (struct type *)strtol (Tcl_GetStringFromObj (objv[1], NULL), NULL, 16); fm = (int)*(Tcl_GetStringFromObj (objv[2], NULL)); numregs = (gdbarch_num_regs (get_current_arch ()) + gdbarch_num_pseudo_regs (get_current_arch ())); if (regno >= numregs) { gdbtk_set_result (interp, "Register number %d too large", regno); return TCL_ERROR; } regformat[regno] = fm; regtype[regno] = type; return TCL_OK; }
static int map_arg_registers (Tcl_Interp *interp, int objc, Tcl_Obj **objv, map_func func, map_arg arg) { int regnum, numregs; /* Note that the test for a valid register must include checking the gdbarch_register_name because gdbarch_num_regs may be allocated for the union of the register sets within a family of related processors. In this case, some entries of gdbarch_register_name will change depending upon the particular processor being debugged. */ numregs = (gdbarch_num_regs (get_current_arch ()) + gdbarch_num_pseudo_regs (get_current_arch ())); if (objc == 0) /* No args, just do all the regs */ { result_ptr->flags |= GDBTK_MAKES_LIST; for (regnum = 0; regnum < numregs; regnum++) { if (gdbarch_register_name (get_current_arch (), regnum) == NULL || *(gdbarch_register_name (get_current_arch (), regnum)) == '\0') continue; func (regnum, arg); } return TCL_OK; } if (objc == 1) if (Tcl_ListObjGetElements (interp, *objv, &objc, &objv ) != TCL_OK) return TCL_ERROR; if (objc > 1) result_ptr->flags |= GDBTK_MAKES_LIST; /* Else, list of register #s, just do listed regs */ for (; objc > 0; objc--, objv++) { if (Tcl_GetIntFromObj (NULL, *objv, ®num) != TCL_OK) { result_ptr->flags |= GDBTK_IN_TCL_RESULT; return TCL_ERROR; } if (regnum >= 0 && regnum < numregs) func (regnum, arg); else { Tcl_SetStringObj (result_ptr->obj_ptr, "bad register number", -1); return TCL_ERROR; } } return TCL_OK; }
enum mi_cmd_result mi_cmd_data_list_register_names (char *command, char **argv, int argc) { int regnum, numregs; int i; struct cleanup *cleanup; /* Note that the test for a valid register must include checking the gdbarch_register_name because gdbarch_num_regs may be allocated for the union of the register sets within a family of related processors. In this case, some entries of gdbarch_register_name will change depending upon the particular processor being debugged. */ numregs = gdbarch_num_regs (current_gdbarch) + gdbarch_num_pseudo_regs (current_gdbarch); cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-names"); if (argc == 0) /* No args, just do all the regs. */ { for (regnum = 0; regnum < numregs; regnum++) { if (gdbarch_register_name (current_gdbarch, regnum) == NULL || *(gdbarch_register_name (current_gdbarch, regnum)) == '\0') ui_out_field_string (uiout, NULL, ""); else ui_out_field_string (uiout, NULL, gdbarch_register_name (current_gdbarch, regnum)); } } /* Else, list of register #s, just do listed regs. */ for (i = 0; i < argc; i++) { regnum = atoi (argv[i]); if (regnum < 0 || regnum >= numregs) { do_cleanups (cleanup); mi_error_message = xstrprintf ("bad register number"); return MI_CMD_ERROR; } if (gdbarch_register_name (current_gdbarch, regnum) == NULL || *(gdbarch_register_name (current_gdbarch, regnum)) == '\0') ui_out_field_string (uiout, NULL, ""); else ui_out_field_string (uiout, NULL, gdbarch_register_name (current_gdbarch, regnum)); } do_cleanups (cleanup); return MI_CMD_DONE; }
static void setup_architecture_data () { int numregs; xfree (old_regs); xfree (regformat); xfree (regtype); numregs = (gdbarch_num_regs (get_current_arch ()) + gdbarch_num_pseudo_regs (get_current_arch ())); old_regs = xcalloc (1, numregs * MAX_REGISTER_SIZE + 1); regformat = (int *)xcalloc (numregs, sizeof(int)); regtype = (struct type **)xcalloc (numregs, sizeof(struct type **)); }
static int m68k_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int num) { if (num < 8) /* d0..7 */ return (num - 0) + M68K_D0_REGNUM; else if (num < 16) /* a0..7 */ return (num - 8) + M68K_A0_REGNUM; else if (num < 24 && gdbarch_tdep (gdbarch)->fpregs_present) /* fp0..7 */ return (num - 16) + M68K_FP0_REGNUM; else if (num == 25) /* pc */ return M68K_PC_REGNUM; else return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); }
static int gdb_reggroup (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { struct reggroup *group; char *groupname; int regnum, num; if (objc != 1) { Tcl_WrongNumArgs (interp, 0, objv, "gdb_reginfo group groupname"); return TCL_ERROR; } groupname = Tcl_GetStringFromObj (objv[0], NULL); if (groupname == NULL) { gdbtk_set_result (interp, "could not read groupname"); return TCL_ERROR; } for (group = reggroup_next (get_current_arch (), NULL); group != NULL; group = reggroup_next (get_current_arch (), group)) { if (strcmp (groupname, reggroup_name (group)) == 0) break; } if (group == NULL) return TCL_ERROR; num = (gdbarch_num_regs (get_current_arch ()) + gdbarch_num_pseudo_regs (get_current_arch ())); for (regnum = 0; regnum < num; regnum++) { if (gdbarch_register_reggroup_p (get_current_arch (), regnum, group)) Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj (regnum)); } return TCL_OK; }
static enum tui_status tui_show_register_group (struct reggroup *group, struct frame_info *frame, int refresh_values_only) { struct gdbarch *gdbarch = get_frame_arch (frame); enum tui_status ret = TUI_FAILURE; int nr_regs; int allocated_here = FALSE; int regnum, pos; char title[80]; struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info; /* Make a new title showing which group we display. */ snprintf (title, sizeof (title) - 1, "Register group: %s", reggroup_name (group)); xfree (TUI_DATA_WIN->generic.title); TUI_DATA_WIN->generic.title = xstrdup (title); /* See how many registers must be displayed. */ nr_regs = 0; for (regnum = 0; regnum < gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); regnum++) { const char *name; /* Must be in the group. */ if (!gdbarch_register_reggroup_p (gdbarch, regnum, group)) continue; /* If the register name is empty, it is undefined for this processor, so don't display anything. */ name = gdbarch_register_name (gdbarch, regnum); if (name == 0 || *name == '\0') continue; nr_regs++; } if (display_info->regs_content_count > 0 && !refresh_values_only) { tui_free_data_content (display_info->regs_content, display_info->regs_content_count); display_info->regs_content_count = 0; } if (display_info->regs_content_count <= 0) { display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN); allocated_here = TRUE; refresh_values_only = FALSE; } if (display_info->regs_content != (tui_win_content) NULL) { if (!refresh_values_only || allocated_here) { TUI_DATA_WIN->generic.content = (void*) NULL; TUI_DATA_WIN->generic.content_size = 0; tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs); display_info->regs_content = (tui_win_content) TUI_DATA_WIN->generic.content; display_info->regs_content_count = nr_regs; } /* Now set the register names and values. */ pos = 0; for (regnum = 0; regnum < gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); regnum++) { struct tui_gen_win_info *data_item_win; struct tui_data_element *data; const char *name; /* Must be in the group. */ if (!gdbarch_register_reggroup_p (gdbarch, regnum, group)) continue; /* If the register name is empty, it is undefined for this processor, so don't display anything. */ name = gdbarch_register_name (gdbarch, regnum); if (name == 0 || *name == '\0') continue; data_item_win = &display_info->regs_content[pos]->which_element.data_window; data = &((struct tui_win_element *) data_item_win->content[0])->which_element.data; if (data) { if (!refresh_values_only) { data->item_no = regnum; data->name = name; data->highlight = FALSE; } tui_get_register (frame, data, regnum, 0); } pos++; } TUI_DATA_WIN->generic.content_size = display_info->regs_content_count + display_info->data_content_count; ret = TUI_SUCCESS; } return ret; }
/* Write given values into registers. The registers and values are given as pairs. The corresponding MI command is -data-write-register-values <format> [<regnum1> <value1>...<regnumN> <valueN>]*/ enum mi_cmd_result mi_cmd_data_write_register_values (char *command, char **argv, int argc) { int numregs, i; char format; /* Note that the test for a valid register must include checking the gdbarch_register_name because gdbarch_num_regs may be allocated for the union of the register sets within a family of related processors. In this case, some entries of gdbarch_register_name will change depending upon the particular processor being debugged. */ numregs = gdbarch_num_regs (current_gdbarch) + gdbarch_num_pseudo_regs (current_gdbarch); if (argc == 0) { mi_error_message = xstrprintf ("mi_cmd_data_write_register_values: Usage: -data-write-register-values <format> [<regnum1> <value1>...<regnumN> <valueN>]"); return MI_CMD_ERROR; } format = (int) argv[0][0]; if (!target_has_registers) { mi_error_message = xstrprintf ("mi_cmd_data_write_register_values: No registers."); return MI_CMD_ERROR; } if (!(argc - 1)) { mi_error_message = xstrprintf ("mi_cmd_data_write_register_values: No regs and values specified."); return MI_CMD_ERROR; } if ((argc - 1) % 2) { mi_error_message = xstrprintf ("mi_cmd_data_write_register_values: Regs and vals are not in pairs."); return MI_CMD_ERROR; } for (i = 1; i < argc; i = i + 2) { int regnum = atoi (argv[i]); if (regnum >= 0 && regnum < numregs && gdbarch_register_name (current_gdbarch, regnum) && *gdbarch_register_name (current_gdbarch, regnum)) { LONGEST value; /* Get the value as a number. */ value = parse_and_eval_address (argv[i + 1]); /* Write it down. */ regcache_cooked_write_signed (get_current_regcache (), regnum, value); } else { mi_error_message = xstrprintf ("bad register number"); return MI_CMD_ERROR; } } return MI_CMD_DONE; }
/* Return a list of register number and value pairs. The valid arguments expected are: a letter indicating the format in which to display the registers contents. This can be one of: x (hexadecimal), d (decimal), N (natural), t (binary), o (octal), r (raw). After the format argumetn there can be a sequence of numbers, indicating which registers to fetch the content of. If the format is the only argument, a list of all the registers with their values is returned. */ enum mi_cmd_result mi_cmd_data_list_register_values (char *command, char **argv, int argc) { int regnum, numregs, format, result; int i; struct cleanup *list_cleanup, *tuple_cleanup; /* Note that the test for a valid register must include checking the gdbarch_register_name because gdbarch_num_regs may be allocated for the union of the register sets within a family of related processors. In this case, some entries of gdbarch_register_name will change depending upon the particular processor being debugged. */ numregs = gdbarch_num_regs (current_gdbarch) + gdbarch_num_pseudo_regs (current_gdbarch); if (argc == 0) { mi_error_message = xstrprintf ("mi_cmd_data_list_register_values: Usage: -data-list-register-values <format> [<regnum1>...<regnumN>]"); return MI_CMD_ERROR; } format = (int) argv[0][0]; list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-values"); if (argc == 1) /* No args, beside the format: do all the regs. */ { for (regnum = 0; regnum < numregs; regnum++) { if (gdbarch_register_name (current_gdbarch, regnum) == NULL || *(gdbarch_register_name (current_gdbarch, regnum)) == '\0') continue; tuple_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); ui_out_field_int (uiout, "number", regnum); result = get_register (regnum, format); if (result == -1) { do_cleanups (list_cleanup); return MI_CMD_ERROR; } do_cleanups (tuple_cleanup); } } /* Else, list of register #s, just do listed regs. */ for (i = 1; i < argc; i++) { regnum = atoi (argv[i]); if (regnum >= 0 && regnum < numregs && gdbarch_register_name (current_gdbarch, regnum) != NULL && *gdbarch_register_name (current_gdbarch, regnum) != '\000') { tuple_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); ui_out_field_int (uiout, "number", regnum); result = get_register (regnum, format); if (result == -1) { do_cleanups (list_cleanup); return MI_CMD_ERROR; } do_cleanups (tuple_cleanup); } else { do_cleanups (list_cleanup); mi_error_message = xstrprintf ("bad register number"); return MI_CMD_ERROR; } } do_cleanups (list_cleanup); return MI_CMD_DONE; }
enum mi_cmd_result mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) { static struct regcache *this_regs = NULL; struct regcache *prev_regs; int regnum, numregs, changed; int i; struct cleanup *cleanup; /* The last time we visited this function, the current frame's register contents were saved in THIS_REGS. Move THIS_REGS over to PREV_REGS, and refresh THIS_REGS with the now-current register contents. */ prev_regs = this_regs; this_regs = frame_save_as_regcache (get_selected_frame (NULL)); cleanup = make_cleanup_regcache_xfree (prev_regs); /* Note that the test for a valid register must include checking the gdbarch_register_name because gdbarch_num_regs may be allocated for the union of the register sets within a family of related processors. In this case, some entries of gdbarch_register_name will change depending upon the particular processor being debugged. */ numregs = gdbarch_num_regs (current_gdbarch) + gdbarch_num_pseudo_regs (current_gdbarch); make_cleanup_ui_out_list_begin_end (uiout, "changed-registers"); if (argc == 0) /* No args, just do all the regs. */ { for (regnum = 0; regnum < numregs; regnum++) { if (gdbarch_register_name (current_gdbarch, regnum) == NULL || *(gdbarch_register_name (current_gdbarch, regnum)) == '\0') continue; changed = register_changed_p (regnum, prev_regs, this_regs); if (changed < 0) { do_cleanups (cleanup); mi_error_message = xstrprintf ("mi_cmd_data_list_changed_registers: Unable to read register contents."); return MI_CMD_ERROR; } else if (changed) ui_out_field_int (uiout, NULL, regnum); } } /* Else, list of register #s, just do listed regs. */ for (i = 0; i < argc; i++) { regnum = atoi (argv[i]); if (regnum >= 0 && regnum < numregs && gdbarch_register_name (current_gdbarch, regnum) != NULL && *gdbarch_register_name (current_gdbarch, regnum) != '\000') { changed = register_changed_p (regnum, prev_regs, this_regs); if (changed < 0) { do_cleanups (cleanup); mi_error_message = xstrprintf ("mi_cmd_data_list_register_change: Unable to read register contents."); return MI_CMD_ERROR; } else if (changed) ui_out_field_int (uiout, NULL, regnum); } else { do_cleanups (cleanup); mi_error_message = xstrprintf ("bad register number"); return MI_CMD_ERROR; } } do_cleanups (cleanup); return MI_CMD_DONE; }