GDB (API)
/home/stan/gdb/src/gdb/gdbtk/generic/gdbtk-register.c
Go to the documentation of this file.
00001 /* Tcl/Tk command definitions for Insight - Registers
00002    Copyright (C) 2001-2013 Free Software Foundation, Inc.
00003 
00004    This file is part of GDB.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019    Boston, MA 02110-1301, USA.  */
00020 
00021 #include "defs.h"
00022 #include "frame.h"
00023 #include "regcache.h"
00024 #include "reggroups.h"
00025 #include "value.h"
00026 #include "target.h"
00027 #include "gdb_string.h"
00028 #include "language.h"
00029 #include "valprint.h"
00030 #include "arch-utils.h"
00031 
00032 #include <tcl.h>
00033 #include "gdbtk.h"
00034 #include "gdbtk-cmds.h"
00035 
00036 /* Argument passed to our register-mapping functions */
00037 typedef union
00038 {
00039   int integer;
00040   void *ptr;
00041 } map_arg;
00042 
00043 /* Type of our mapping functions */
00044 typedef void (*map_func)(int, map_arg);
00045 
00046 static int gdb_register_info (ClientData, Tcl_Interp *, int, Tcl_Obj **);
00047 static void get_register (int, map_arg);
00048 static void get_register_name (int, map_arg);
00049 static void get_register_size (int, map_arg);
00050 static int map_arg_registers (Tcl_Interp *, int, Tcl_Obj **,
00051                               map_func, map_arg);
00052 static void register_changed_p (int, map_arg);
00053 static void setup_architecture_data (void);
00054 static int gdb_regformat (ClientData, Tcl_Interp *, int, Tcl_Obj **);
00055 static int gdb_reggroup (ClientData, Tcl_Interp *, int, Tcl_Obj **);
00056 static int gdb_reggrouplist (ClientData, Tcl_Interp *, int, Tcl_Obj **);
00057 
00058 static void get_register_types (int regnum, map_arg);
00059 
00060 /* This contains the previous values of the registers, since the last call to
00061    gdb_changed_register_list.
00062 
00063    It is an array of (NUM_REGS+NUM_PSEUDO_REGS)*MAX_REGISTER_RAW_SIZE bytes. */
00064 
00065 static char *old_regs = NULL;
00066 static int old_regs_count = 0;
00067 static int *regformat = (int *)NULL;
00068 static struct type **regtype = (struct type **)NULL;
00069 
00070 int
00071 Gdbtk_Register_Init (Tcl_Interp *interp)
00072 {
00073   Tcl_CreateObjCommand (interp, "gdb_reginfo", gdbtk_call_wrapper,
00074                         gdb_register_info, NULL);
00075   Tcl_CreateObjCommand (interp, "gdb_reg_arch_changed", gdbtk_call_wrapper,
00076                         setup_architecture_data, NULL);
00077 
00078   /* Register/initialize any architecture specific data */
00079   setup_architecture_data ();
00080 
00081   return TCL_OK;
00082 }
00083 
00084 /* This implements the tcl command "gdb_reginfo".
00085  * It returns the requested information about registers.
00086  *
00087  * Tcl Arguments:
00088  *    OPTION    - "changed", "name", "size", "value" (see below)
00089  *    REGNUM(S) - the register(s) for which info is requested
00090  *
00091  * Tcl Result:
00092  *    The requested information
00093  *
00094  * Options:
00095  * changed
00096  *    Returns a list of registers whose values have changed since the
00097  *    last time the proc was called.
00098  *
00099  *    usage: gdb_reginfo changed [regnum0, ..., regnumN]
00100  *
00101  * name
00102  *    Return a list containing the names of the registers whose numbers
00103  *    are given by REGNUM ... .  If no register numbers are given, return
00104  *    all the registers' names.
00105  *
00106  *    usage: gdb_reginfo name [-numbers] [regnum0, ..., regnumN]
00107  *
00108  *    Note that some processors have gaps in the register numberings:
00109  *    even if there is no register numbered N, there may still be a
00110  *    register numbered N+1.  So if you call gdb_regnames with no
00111  *    arguments, you can't assume that the N'th element of the result is
00112  *    register number N.
00113  *
00114  *    Given the -numbers option, gdb_regnames returns, not a list of names,
00115  *    but a list of pairs {NAME NUMBER}, where NAME is the register name,
00116  *    and NUMBER is its number.
00117  *
00118  * size
00119  *    Returns the raw size of the register(s) in bytes.
00120  *
00121  *    usage: gdb_reginfo size [regnum0, ..., regnumN]
00122  *
00123  * value
00124  *    Returns a list of register values.
00125  *
00126  *    usage: gdb_reginfo value [regnum0, ..., regnumN]
00127  */
00128 static int
00129 gdb_register_info (ClientData clientData, Tcl_Interp *interp, int objc,
00130                    Tcl_Obj **objv)
00131 {
00132   int index;
00133   map_arg arg;
00134   map_func func;
00135   static const char *commands[] = {"changed", "name", "size", "value", "type", 
00136                              "format", "group", "grouplist", NULL};
00137   enum commands_enum { REGINFO_CHANGED, REGINFO_NAME, REGINFO_SIZE, REGINFO_VALUE, 
00138                        REGINFO_TYPE, REGINFO_FORMAT, REGINFO_GROUP, REGINFO_GROUPLIST };
00139 
00140   if (objc < 2)
00141     {
00142       Tcl_WrongNumArgs (interp, 1, objv, "name|size|value|type|format|groups [regnum1 ... regnumN]");
00143       return TCL_ERROR;
00144     }
00145 
00146   if (Tcl_GetIndexFromObj (interp, objv[1], commands, "options", 0,
00147                            &index) != TCL_OK)
00148     {
00149       result_ptr->flags |= GDBTK_IN_TCL_RESULT;
00150       return TCL_ERROR;
00151     }
00152   
00153   /* Skip the option */
00154   objc -= 2;
00155   objv += 2;
00156 
00157   switch ((enum commands_enum) index)
00158     {
00159     case REGINFO_CHANGED:
00160       func = register_changed_p;
00161       arg.ptr = NULL;
00162       break;
00163 
00164     case REGINFO_NAME:
00165       {
00166         int len;
00167         char *s = Tcl_GetStringFromObj (objv[0], &len);
00168         if (objc != 0 && strncmp (s, "-numbers", len) == 0)
00169           {
00170             arg.integer = 1;
00171             objc--;
00172             objv++;
00173           }
00174         else
00175           arg.ptr = NULL;
00176 
00177         func = get_register_name;
00178       }
00179       break;
00180 
00181     case REGINFO_SIZE:
00182       func = get_register_size;
00183       arg.ptr = NULL;
00184       break;
00185 
00186     case REGINFO_VALUE:
00187       func = get_register;
00188       arg.ptr = NULL;
00189       break;
00190 
00191     case REGINFO_TYPE:
00192       func = get_register_types;
00193       arg.ptr = NULL;
00194       break;
00195 
00196     case REGINFO_FORMAT:
00197       return gdb_regformat (clientData, interp, objc, objv);
00198 
00199     case REGINFO_GROUP:
00200       return gdb_reggroup (clientData, interp, objc, objv);
00201 
00202     case REGINFO_GROUPLIST:
00203       return gdb_reggrouplist (clientData, interp, objc, objv);
00204 
00205     default:
00206       return TCL_ERROR;
00207     }
00208 
00209   return map_arg_registers (interp, objc, objv, func, arg);
00210 }
00211 
00212 static void
00213 get_register_size (int regnum, map_arg arg)
00214 {
00215   Tcl_ListObjAppendElement (gdbtk_interp, result_ptr->obj_ptr,
00216                             Tcl_NewIntObj (register_size (get_current_arch (),
00217                                                           regnum)));
00218 }
00219 
00220 /* returns a list of valid types for a register */
00221 /* Normally this will be only one type, except for SIMD and other */
00222 /* special registers. */
00223 
00224 static void
00225 get_register_types (int regnum, map_arg arg)
00226 { 
00227   struct type *reg_vtype;
00228   int i,n;
00229 
00230   reg_vtype = register_type (get_current_arch (), regnum);
00231   
00232   if (TYPE_CODE (reg_vtype) == TYPE_CODE_UNION)
00233     {
00234       n = TYPE_NFIELDS (reg_vtype);
00235       /* limit to 16 types */
00236       if (n > 16) 
00237         n = 16;
00238       
00239       for (i = 0; i < n; i++)
00240         {
00241           Tcl_Obj *ar[3], *list;
00242           char *buff;
00243           buff = xstrprintf ("%s", host_address_to_string (
00244                                      TYPE_FIELD_TYPE (reg_vtype, i)));
00245           ar[0] = Tcl_NewStringObj (TYPE_FIELD_NAME (reg_vtype, i), -1);
00246           ar[1] = Tcl_NewStringObj (buff, -1);
00247           if (TYPE_CODE (TYPE_FIELD_TYPE (reg_vtype, i)) == TYPE_CODE_FLT)
00248             ar[2] = Tcl_NewStringObj ("float", -1);
00249           else
00250             ar[2] = Tcl_NewStringObj ("int", -1);           
00251           list = Tcl_NewListObj (3, ar);
00252           Tcl_ListObjAppendElement (gdbtk_interp, result_ptr->obj_ptr, list);
00253           xfree (buff);
00254         }
00255     }
00256   else
00257     {
00258       Tcl_Obj *ar[3], *list;
00259       char *buff;
00260       buff = xstrprintf ("%s", host_address_to_string (reg_vtype));
00261       ar[0] = Tcl_NewStringObj (TYPE_NAME(reg_vtype), -1);
00262       ar[1] = Tcl_NewStringObj (buff, -1);
00263       if (TYPE_CODE (reg_vtype) == TYPE_CODE_FLT)
00264         ar[2] = Tcl_NewStringObj ("float", -1);
00265       else
00266         ar[2] = Tcl_NewStringObj ("int", -1);       
00267       list = Tcl_NewListObj (3, ar);
00268       xfree (buff);
00269       Tcl_ListObjAppendElement (gdbtk_interp, result_ptr->obj_ptr, list);
00270     }
00271 }
00272 
00273 
00274 static void
00275 get_register (int regnum, map_arg arg)
00276 {
00277   CORE_ADDR addr;
00278   enum lval_type lval;
00279   struct type *reg_vtype;
00280   int format;
00281   struct cleanup *old_chain = NULL;
00282   struct ui_file *stb;
00283   long dummy;
00284   char *res;
00285   struct gdbarch *gdbarch;
00286   struct value *val;
00287   struct frame_info *frame;
00288 
00289   format = regformat[regnum];
00290   if (format == 0)
00291     format = 'x';
00292   
00293   reg_vtype = regtype[regnum];
00294   if (reg_vtype == NULL)
00295     reg_vtype = register_type (get_current_arch (), regnum);
00296 
00297   if (!target_has_registers)
00298     {
00299       if (result_ptr->flags & GDBTK_MAKES_LIST)
00300         Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewStringObj ("", -1));
00301       else
00302         Tcl_SetStringObj (result_ptr->obj_ptr, "", -1);
00303       return;
00304     }
00305 
00306   frame = get_selected_frame (NULL);
00307   gdbarch = get_frame_arch (frame);
00308   val = get_frame_register_value (frame, regnum);
00309 
00310   if (value_optimized_out (val))
00311     {
00312       Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
00313                                 Tcl_NewStringObj ("Optimized out", -1));
00314       return;
00315     }
00316 
00317   stb = mem_fileopen ();
00318   old_chain = make_cleanup_ui_file_delete (stb);
00319 
00320   if (format == 'r')
00321     {
00322       /* shouldn't happen. raw format is deprecated */
00323       int j;
00324       char *ptr, buf[1024];
00325       const gdb_byte *valaddr = value_contents_for_printing (val);
00326 
00327       strcpy (buf, "0x");
00328       ptr = buf + 2;
00329       for (j = 0; j < register_size (gdbarch, regnum); j++)
00330         {
00331           int idx = ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
00332                      ? j : register_size (gdbarch, regnum) - 1 - j);
00333           sprintf (ptr, "%02x", (unsigned char) valaddr[idx]);
00334           ptr += 2;
00335         }
00336       fputs_unfiltered (buf, stb);
00337     }
00338   else
00339     {
00340       struct value_print_options opts;
00341 
00342       get_formatted_print_options (&opts, format);
00343       opts.deref_ref = 1;
00344       opts.prettyformat = Val_prettyformat_default;
00345       val_print (reg_vtype, value_contents_for_printing (val),
00346                  value_embedded_offset (val), 0,
00347                  stb, 0, val, &opts, current_language);
00348     }
00349   
00350   res = ui_file_xstrdup (stb, &dummy);
00351 
00352   if (result_ptr->flags & GDBTK_MAKES_LIST)
00353     Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewStringObj (res, -1));
00354   else
00355     Tcl_SetStringObj (result_ptr->obj_ptr, res, -1);
00356 
00357   xfree (res);
00358   do_cleanups (old_chain);
00359 }
00360 
00361 static void
00362 get_register_name (int regnum, map_arg arg)
00363 {
00364   /* Non-zero if the caller wants the register numbers, too.  */
00365   int numbers = arg.integer;
00366   Tcl_Obj *name
00367     = Tcl_NewStringObj (gdbarch_register_name (get_current_arch (), regnum), -1);
00368   Tcl_Obj *elt;
00369 
00370   if (numbers)
00371     {
00372       /* Build a tuple of the form "{REGNAME NUMBER}", and append it to
00373          our result.  */
00374       Tcl_Obj *array[2];
00375 
00376       array[0] = name;
00377       array[1] = Tcl_NewIntObj (regnum);
00378       elt = Tcl_NewListObj (2, array);
00379     }
00380   else
00381     elt = name;
00382 
00383   Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, elt);
00384 }
00385 
00386 /* This is a sort of mapcar function for operations on registers */
00387 
00388 static int
00389 map_arg_registers (Tcl_Interp *interp, int objc, Tcl_Obj **objv,
00390                    map_func func, map_arg arg)
00391 {
00392   int regnum, numregs;
00393 
00394   /* Note that the test for a valid register must include checking the
00395      gdbarch_register_name because gdbarch_num_regs may be allocated for
00396      the union of the register sets within a family of related processors.
00397      In this case, some entries of gdbarch_register_name will change
00398      depending upon the particular processor being debugged.  */
00399 
00400   numregs = (gdbarch_num_regs (get_current_arch ())
00401              + gdbarch_num_pseudo_regs (get_current_arch ()));
00402 
00403   if (objc == 0)                /* No args, just do all the regs */
00404     {
00405       result_ptr->flags |= GDBTK_MAKES_LIST;
00406       for (regnum = 0; regnum < numregs; regnum++)
00407         {
00408           if (gdbarch_register_name (get_current_arch (), regnum) == NULL
00409               || *(gdbarch_register_name (get_current_arch (), regnum)) == '\0')
00410             continue;
00411           func (regnum, arg);
00412         }      
00413       return TCL_OK;
00414     }
00415 
00416   if (objc == 1)
00417     if (Tcl_ListObjGetElements (interp, *objv, &objc, &objv ) != TCL_OK)
00418       return TCL_ERROR;
00419 
00420   if (objc > 1)
00421     result_ptr->flags |= GDBTK_MAKES_LIST;
00422 
00423   /* Else, list of register #s, just do listed regs */
00424   for (; objc > 0; objc--, objv++)
00425     {
00426       if (Tcl_GetIntFromObj (NULL, *objv, &regnum) != TCL_OK)
00427         {
00428           result_ptr->flags |= GDBTK_IN_TCL_RESULT;
00429           return TCL_ERROR;
00430         }
00431 
00432       if (regnum >= 0  && regnum < numregs)
00433         func (regnum, arg);
00434       else
00435         {
00436           Tcl_SetStringObj (result_ptr->obj_ptr, "bad register number", -1);
00437           return TCL_ERROR;
00438         }
00439     }
00440   return TCL_OK;
00441 }
00442 
00443 static void
00444 register_changed_p (int regnum, map_arg arg)
00445 {
00446   struct value *val;
00447   gdb_assert (regnum < old_regs_count);
00448 
00449   if (!target_has_registers)
00450     return;
00451 
00452   val = get_frame_register_value (get_selected_frame (NULL), regnum);
00453   if (value_optimized_out (val) || !value_entirely_available (val))
00454     return;
00455 
00456   if (memcmp (&old_regs[regnum * MAX_REGISTER_SIZE],
00457               value_contents_all (val),
00458               register_size (get_current_arch (), regnum)) == 0)
00459     return;
00460 
00461   /* Found a changed register.  Save new value and return its number. */
00462 
00463   memcpy (&old_regs[regnum * MAX_REGISTER_SIZE],
00464           value_contents_all (val),
00465           register_size (get_current_arch (), regnum));
00466 
00467   Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj (regnum));
00468 }
00469 
00470 static void
00471 setup_architecture_data (void)
00472 {
00473   int numregs;
00474 
00475   xfree (old_regs);
00476   xfree (regformat);
00477   xfree (regtype);
00478 
00479   numregs = (gdbarch_num_regs (get_current_arch ())
00480              + gdbarch_num_pseudo_regs (get_current_arch ()));
00481   old_regs_count = numregs;
00482   old_regs = xcalloc (1, numregs * MAX_REGISTER_SIZE + 1);
00483   regformat = (int *)xcalloc (numregs, sizeof(int));
00484   regtype = (struct type **)xcalloc (numregs, sizeof(struct type **));
00485 }
00486 
00487 /* gdb_regformat sets the format for a register */
00488 /* This is necessary to allow "gdb_reginfo value" to return a list */
00489 /* of registers and values. */
00490 /* Usage: gdb_reginfo format regno typeaddr format */
00491 
00492 static int
00493 gdb_regformat (ClientData clientData, Tcl_Interp *interp,
00494                int objc, Tcl_Obj **objv)
00495 {
00496   int fm, regno, numregs;
00497   struct type *type;
00498 
00499   if (objc != 3)
00500     {
00501       Tcl_WrongNumArgs (interp, 0, objv, "gdb_reginfo regno type format");
00502       return TCL_ERROR;
00503     }
00504 
00505   if (Tcl_GetIntFromObj (interp, objv[0], &regno) != TCL_OK)
00506     return TCL_ERROR;
00507 
00508   #ifdef _WIN64
00509   type = (struct type *)strtoll (Tcl_GetStringFromObj (objv[1], NULL), NULL, 16);  
00510   #else
00511   type = (struct type *)strtol (Tcl_GetStringFromObj (objv[1], NULL), NULL, 16);  
00512   #endif
00513   fm = (int)*(Tcl_GetStringFromObj (objv[2], NULL));
00514 
00515   numregs = (gdbarch_num_regs (get_current_arch ())
00516              + gdbarch_num_pseudo_regs (get_current_arch ()));
00517   if (regno >= numregs)
00518     {
00519       gdbtk_set_result (interp, "Register number %d too large", regno);
00520       return TCL_ERROR;
00521     }
00522   
00523   regformat[regno] = fm;
00524   regtype[regno] = type;
00525 
00526   return TCL_OK;
00527 }
00528 
00529 
00530 /* gdb_reggrouplist returns the names of the register groups */
00531 /* for the current architecture. */
00532 /* Usage: gdb_reginfo groups */
00533 
00534 static int
00535 gdb_reggrouplist (ClientData clientData, Tcl_Interp *interp,
00536                   int objc, Tcl_Obj **objv)
00537 {
00538   struct reggroup *group;
00539   int i = 0;
00540 
00541   if (objc != 0)
00542     {
00543       Tcl_WrongNumArgs (interp, 0, objv, "gdb_reginfo grouplist");
00544       return TCL_ERROR;
00545     }
00546 
00547   for (group = reggroup_next (get_current_arch (), NULL);
00548        group != NULL;
00549        group = reggroup_next (get_current_arch (), group))
00550     {
00551       if (reggroup_type (group) == USER_REGGROUP)
00552         Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewStringObj (reggroup_name (group), -1));
00553     }
00554   return TCL_OK;
00555 }
00556 
00557 
00558 /* gdb_reggroup returns the names of the registers in a group. */
00559 /* Usage: gdb_reginfo group groupname */
00560 
00561 static int
00562 gdb_reggroup (ClientData clientData, Tcl_Interp *interp,
00563               int objc, Tcl_Obj **objv)
00564 {
00565   struct reggroup *group;
00566   char *groupname;
00567   int regnum, num;
00568 
00569   if (objc != 1)
00570     {
00571       Tcl_WrongNumArgs (interp, 0, objv, "gdb_reginfo group groupname");
00572       return TCL_ERROR;
00573     }
00574   
00575   groupname = Tcl_GetStringFromObj (objv[0], NULL);
00576   if (groupname == NULL)
00577     {
00578       gdbtk_set_result (interp, "could not read groupname");
00579       return TCL_ERROR;
00580     }
00581 
00582   for (group = reggroup_next (get_current_arch (), NULL);
00583        group != NULL;
00584        group = reggroup_next (get_current_arch (), group))
00585     {
00586       if (strcmp (groupname, reggroup_name (group)) == 0)
00587         break;
00588     }
00589 
00590   if (group == NULL)
00591     return TCL_ERROR;
00592 
00593   num = (gdbarch_num_regs (get_current_arch ())
00594          + gdbarch_num_pseudo_regs (get_current_arch ()));
00595   for (regnum = 0; regnum < num; regnum++)
00596     {
00597       if (gdbarch_register_reggroup_p (get_current_arch (), regnum, group))
00598         Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj (regnum));
00599     }
00600   return TCL_OK;
00601 }
00602 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines