GDB (API)
|
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, ®num) != 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], ®no) != 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