diff options
Diffstat (limited to 'gdb/gdbtk/generic/gdbtk-register.c')
-rw-r--r-- | gdb/gdbtk/generic/gdbtk-register.c | 577 |
1 files changed, 0 insertions, 577 deletions
diff --git a/gdb/gdbtk/generic/gdbtk-register.c b/gdb/gdbtk/generic/gdbtk-register.c deleted file mode 100644 index 49ba9a69c06..00000000000 --- a/gdb/gdbtk/generic/gdbtk-register.c +++ /dev/null @@ -1,577 +0,0 @@ -/* Tcl/Tk command definitions for Insight - Registers - Copyright 2001, 2002 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include "defs.h" -#include "frame.h" -#include "regcache.h" -#include "reggroups.h" -#include "value.h" -#include "target.h" -#include "gdb_string.h" - -#include <tcl.h> -#include "gdbtk.h" -#include "gdbtk-cmds.h" - -/* This contains the previous values of the registers, since the last call to - gdb_changed_register_list. - - It is an array of (NUM_REGS+NUM_PSEUDO_REGS)*MAX_REGISTER_RAW_SIZE bytes. */ - -static int gdb_register_info (ClientData, Tcl_Interp *, int, Tcl_Obj **); -static void get_register (int, void *); -static void get_register_name (int, void *); -static void get_register_size (int regnum, void *arg); -static int map_arg_registers (Tcl_Interp *, int, Tcl_Obj **, - void (*)(int, void *), void *); -static void register_changed_p (int, void *); -static void setup_architecture_data (void); -static int gdb_regformat (ClientData, Tcl_Interp *, int, Tcl_Obj **); -static int gdb_reggroup (ClientData, Tcl_Interp *, int, Tcl_Obj **); -static int gdb_reggrouplist (ClientData, Tcl_Interp *, int, Tcl_Obj **); - -static void get_register_types (int regnum, void *arg); - -static char *old_regs = NULL; -static int *regformat = (int *)NULL; -static struct type **regtype = (struct type **)NULL; - -int -Gdbtk_Register_Init (Tcl_Interp *interp) -{ - Tcl_CreateObjCommand (interp, "gdb_reginfo", gdbtk_call_wrapper, - gdb_register_info, NULL); - - /* Register/initialize any architecture specific data */ - setup_architecture_data (); - - register_gdbarch_swap (&old_regs, sizeof (old_regs), NULL); - register_gdbarch_swap (®format, sizeof (regformat), NULL); - register_gdbarch_swap (®type, sizeof (regtype), NULL); - register_gdbarch_swap (NULL, 0, setup_architecture_data); - - return TCL_OK; -} - -/* This implements the tcl command "gdb_reginfo". - * It returns the requested information about registers. - * - * Tcl Arguments: - * OPTION - "changed", "name", "size", "value" (see below) - * REGNUM(S) - the register(s) for which info is requested - * - * Tcl Result: - * The requested information - * - * Options: - * changed - * Returns a list of registers whose values have changed since the - * last time the proc was called. - * - * usage: gdb_reginfo changed [regnum0, ..., regnumN] - * - * name - * Return a list containing the names of the registers whose numbers - * are given by REGNUM ... . If no register numbers are given, return - * all the registers' names. - * - * usage: gdb_reginfo name [-numbers] [regnum0, ..., regnumN] - * - * Note that some processors have gaps in the register numberings: - * even if there is no register numbered N, there may still be a - * register numbered N+1. So if you call gdb_regnames with no - * arguments, you can't assume that the N'th element of the result is - * register number N. - * - * Given the -numbers option, gdb_regnames returns, not a list of names, - * but a list of pairs {NAME NUMBER}, where NAME is the register name, - * and NUMBER is its number. - * - * size - * Returns the raw size of the register(s) in bytes. - * - * usage: gdb_reginfo size [regnum0, ..., regnumN] - * - * value - * Returns a list of register values. - * - * usage: gdb_reginfo value [regnum0, ..., regnumN] - */ -static int -gdb_register_info (ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj **objv) -{ - int index; - void *argp; - void (*func)(int, void *); - static const char *commands[] = {"changed", "name", "size", "value", "type", - "format", "group", "grouplist", NULL}; - enum commands_enum { REGINFO_CHANGED, REGINFO_NAME, REGINFO_SIZE, REGINFO_VALUE, - REGINFO_TYPE, REGINFO_FORMAT, REGINFO_GROUP, REGINFO_GROUPLIST }; - - if (objc < 2) - { - Tcl_WrongNumArgs (interp, 1, objv, "name|size|value|type|format|groups [regnum1 ... regnumN]"); - return TCL_ERROR; - } - - if (Tcl_GetIndexFromObj (interp, objv[1], commands, "options", 0, - &index) != TCL_OK) - { - result_ptr->flags |= GDBTK_IN_TCL_RESULT; - return TCL_ERROR; - } - - /* Skip the option */ - objc -= 2; - objv += 2; - - switch ((enum commands_enum) index) - { - case REGINFO_CHANGED: - func = register_changed_p; - argp = NULL; - break; - - case REGINFO_NAME: - { - int len; - char *s = Tcl_GetStringFromObj (objv[0], &len); - if (objc != 0 && strncmp (s, "-numbers", len) == 0) - { - argp = (void *) 1; - objc--; - objv++; - } - else - argp = NULL; - - func = get_register_name; - } - break; - - case REGINFO_SIZE: - func = get_register_size; - argp = NULL; - break; - - case REGINFO_VALUE: - func = get_register; - argp = NULL; - break; - - case REGINFO_TYPE: - func = get_register_types; - argp = NULL; - break; - - case REGINFO_FORMAT: - return gdb_regformat (clientData, interp, objc, objv); - - case REGINFO_GROUP: - return gdb_reggroup (clientData, interp, objc, objv); - - case REGINFO_GROUPLIST: - return gdb_reggrouplist (clientData, interp, objc, objv); - - default: - return TCL_ERROR; - } - - return map_arg_registers (interp, objc, objv, func, argp); -} - -static void -get_register_size (int regnum, void *arg) -{ - Tcl_ListObjAppendElement (gdbtk_interp, result_ptr->obj_ptr, - Tcl_NewIntObj (REGISTER_RAW_SIZE (regnum))); -} - -/* returns a list of valid types for a register */ -/* Normally this will be only one type, except for SIMD and other */ -/* special registers. */ - -static void -get_register_types (int regnum, void *arg) -{ - struct type *reg_vtype; - int i,n; - - reg_vtype = register_type (current_gdbarch, regnum); - - if (TYPE_CODE (reg_vtype) == TYPE_CODE_UNION) - { - n = TYPE_NFIELDS (reg_vtype); - /* limit to 16 types */ - if (n > 16) - n = 16; - - for (i = 0; i < n; i++) - { - Tcl_Obj *ar[3], *list; - char *buff; - xasprintf (&buff, "%lx", (long)TYPE_FIELD_TYPE (reg_vtype, i)); - ar[0] = Tcl_NewStringObj (TYPE_FIELD_NAME (reg_vtype, i), -1); - ar[1] = Tcl_NewStringObj (buff, -1); - if (TYPE_CODE (TYPE_FIELD_TYPE (reg_vtype, i)) == TYPE_CODE_FLT) - ar[2] = Tcl_NewStringObj ("float", -1); - else - ar[2] = Tcl_NewStringObj ("int", -1); - list = Tcl_NewListObj (3, ar); - Tcl_ListObjAppendElement (gdbtk_interp, result_ptr->obj_ptr, list); - xfree (buff); - } - } - else - { - Tcl_Obj *ar[3], *list; - char *buff; - xasprintf (&buff, "%lx", (long)reg_vtype); - ar[0] = Tcl_NewStringObj (TYPE_NAME(reg_vtype), -1); - ar[1] = Tcl_NewStringObj (buff, -1); - if (TYPE_CODE (reg_vtype) == TYPE_CODE_FLT) - ar[2] = Tcl_NewStringObj ("float", -1); - else - ar[2] = Tcl_NewStringObj ("int", -1); - list = Tcl_NewListObj (3, ar); - xfree (buff); - Tcl_ListObjAppendElement (gdbtk_interp, result_ptr->obj_ptr, list); - } -} - - -static void -get_register (int regnum, void *arg) -{ - int realnum; - CORE_ADDR addr; - enum lval_type lval; - struct type *reg_vtype; - char raw_buffer[MAX_REGISTER_SIZE]; - char virtual_buffer[MAX_REGISTER_SIZE]; - int optim, format; - struct cleanup *old_chain = NULL; - struct ui_file *stb; - long dummy; - char *res; - - format = regformat[regnum]; - if (format == 0) - format = 'x'; - - reg_vtype = regtype[regnum]; - if (reg_vtype == NULL) - reg_vtype = register_type (current_gdbarch, regnum); - - if (!target_has_registers) - { - if (result_ptr->flags & GDBTK_MAKES_LIST) - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewStringObj ("", -1)); - else - Tcl_SetStringObj (result_ptr->obj_ptr, "", -1); - return; - } - - frame_register (get_selected_frame (), regnum, &optim, &lval, - &addr, &realnum, raw_buffer); - - if (optim) - { - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewStringObj ("Optimized out", -1)); - return; - } - - /* Convert raw data to virtual format if necessary. */ - if (REGISTER_CONVERTIBLE (regnum)) - { - REGISTER_CONVERT_TO_VIRTUAL (regnum, reg_vtype, - raw_buffer, virtual_buffer); - } - else - memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum)); - - stb = mem_fileopen (); - old_chain = make_cleanup_ui_file_delete (stb); - - if (format == 'r') - { - /* shouldn't happen. raw format is deprecated */ - int j; - char *ptr, buf[1024]; - - strcpy (buf, "0x"); - ptr = buf + 2; - for (j = 0; j < REGISTER_RAW_SIZE (regnum); j++) - { - int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j - : REGISTER_RAW_SIZE (regnum) - 1 - j; - sprintf (ptr, "%02x", (unsigned char) raw_buffer[idx]); - ptr += 2; - } - fputs_unfiltered (buf, stb); - } - else - { - if ((TYPE_CODE (reg_vtype) == TYPE_CODE_UNION) - && (strcmp (FIELD_NAME (TYPE_FIELD (reg_vtype, 0)), - REGISTER_NAME (regnum)) == 0)) - { - val_print (FIELD_TYPE (TYPE_FIELD (reg_vtype, 0)), virtual_buffer, 0, 0, - stb, format, 1, 0, Val_pretty_default); - } - else - val_print (reg_vtype, virtual_buffer, 0, 0, - stb, format, 1, 0, Val_pretty_default); - } - - res = ui_file_xstrdup (stb, &dummy); - - if (result_ptr->flags & GDBTK_MAKES_LIST) - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewStringObj (res, -1)); - else - Tcl_SetStringObj (result_ptr->obj_ptr, res, -1); - - xfree (res); - do_cleanups (old_chain); -} - -static void -get_register_name (int regnum, void *argp) -{ - /* Non-zero if the caller wants the register numbers, too. */ - int numbers = (int) argp; - Tcl_Obj *name = Tcl_NewStringObj (REGISTER_NAME (regnum), -1); - Tcl_Obj *elt; - - if (numbers) - { - /* Build a tuple of the form "{REGNAME NUMBER}", and append it to - our result. */ - Tcl_Obj *array[2]; - - array[0] = name; - array[1] = Tcl_NewIntObj (regnum); - elt = Tcl_NewListObj (2, array); - } - else - elt = name; - - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, elt); -} - -/* This is a sort of mapcar function for operations on registers */ - -static int -map_arg_registers (Tcl_Interp *interp, int objc, Tcl_Obj **objv, - void (*func) (int regnum, void *argp), void *argp) -{ - int regnum, numregs; - - /* Note that the test for a valid register must include checking the - REGISTER_NAME because NUM_REGS may be allocated for the union of - the register sets within a family of related processors. In this - case, some entries of REGISTER_NAME will change depending upon - the particular processor being debugged. */ - - numregs = NUM_REGS + NUM_PSEUDO_REGS; - - if (objc == 0) /* No args, just do all the regs */ - { - result_ptr->flags |= GDBTK_MAKES_LIST; - for (regnum = 0; regnum < numregs; regnum++) - { - if (REGISTER_NAME (regnum) == NULL - || *(REGISTER_NAME (regnum)) == '\0') - continue; - func (regnum, argp); - } - 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 - && REGISTER_NAME (regnum) != NULL - && *REGISTER_NAME (regnum) != '\000') - func (regnum, argp); - else - { - Tcl_SetStringObj (result_ptr->obj_ptr, "bad register number", -1); - return TCL_ERROR; - } - } - return TCL_OK; -} - -static void -register_changed_p (int regnum, void *argp) -{ - char raw_buffer[MAX_REGISTER_SIZE]; - - if (deprecated_selected_frame == NULL - || !frame_register_read (deprecated_selected_frame, regnum, raw_buffer)) - return; - - if (memcmp (&old_regs[regnum * MAX_REGISTER_SIZE], raw_buffer, - REGISTER_RAW_SIZE (regnum)) == 0) - return; - - /* Found a changed register. Save new value and return its number. */ - - memcpy (&old_regs[regnum * MAX_REGISTER_SIZE], raw_buffer, - REGISTER_RAW_SIZE (regnum)); - - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj (regnum)); -} - -static void -setup_architecture_data () -{ - xfree (old_regs); - xfree (regformat); - xfree (regtype); - - old_regs = xcalloc (1, (NUM_REGS + NUM_PSEUDO_REGS) * MAX_REGISTER_SIZE + 1); - regformat = (int *)xcalloc ((NUM_REGS + NUM_PSEUDO_REGS) , sizeof(int)); - regtype = (struct type **)xcalloc ((NUM_REGS + NUM_PSEUDO_REGS), sizeof(struct type **)); -} - -/* gdb_regformat sets the format for a register */ -/* This is necessary to allow "gdb_reginfo value" to return a list */ -/* of registers and values. */ -/* Usage: gdb_reginfo format regno typeaddr format */ - -static int -gdb_regformat (ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj **objv) -{ - int fm, regno; - 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)); - - if (regno >= NUM_REGS + NUM_PSEUDO_REGS) - { - gdbtk_set_result (interp, "Register number %d too large", regno); - return TCL_ERROR; - } - - regformat[regno] = fm; - regtype[regno] = type; - - return TCL_OK; -} - - -/* gdb_reggrouplist returns the names of the register groups */ -/* for the current architecture. */ -/* Usage: gdb_reginfo groups */ - -static int -gdb_reggrouplist (ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj **objv) -{ - struct reggroup *const *groups; - int i = 0; - - if (objc != 0) - { - Tcl_WrongNumArgs (interp, 0, objv, "gdb_reginfo grouplist"); - return TCL_ERROR; - } - - groups = reggroups (current_gdbarch); - - while (groups[i] != NULL) { - if (reggroup_type (groups[i]) == USER_REGGROUP) - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewStringObj (reggroup_name(groups[i]), -1)); - i++; - } - return TCL_OK; -} - - -/* gdb_reggroup returns the names of the registers in a group. */ -/* Usage: gdb_reginfo group groupname */ - -static int -gdb_reggroup (ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj **objv) -{ - struct reggroup *const *group; - char *groupname; - int regnum; - - 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 = reggroups (current_gdbarch); *group != NULL; group++) - { - if (strcmp (groupname, reggroup_name (*group)) == 0) - break; - } - - if (*group == NULL) - return TCL_ERROR; - - for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) - { - if (gdbarch_register_reggroup_p (current_gdbarch, regnum, *group)) - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj (regnum)); - } - return TCL_OK; -} - |