1 /* TUI display registers in window. 2 3 Copyright (C) 1998-2013 Free Software Foundation, Inc. 4 5 Contributed by Hewlett-Packard Company. 6 7 This file is part of GDB. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 22 #include "defs.h" 23 #include "arch-utils.h" 24 #include "tui/tui.h" 25 #include "tui/tui-data.h" 26 #include "symtab.h" 27 #include "gdbtypes.h" 28 #include "gdbcmd.h" 29 #include "frame.h" 30 #include "regcache.h" 31 #include "inferior.h" 32 #include "target.h" 33 #include "gdb_string.h" 34 #include "tui/tui-layout.h" 35 #include "tui/tui-win.h" 36 #include "tui/tui-windata.h" 37 #include "tui/tui-wingeneral.h" 38 #include "tui/tui-file.h" 39 #include "tui/tui-regs.h" 40 #include "reggroups.h" 41 #include "valprint.h" 42 43 #include "gdb_curses.h" 44 45 46 /***************************************** 47 ** STATIC LOCAL FUNCTIONS FORWARD DECLS ** 48 ******************************************/ 49 static void 50 tui_display_register (struct tui_data_element *data, 51 struct tui_gen_win_info *win_info); 52 53 static enum tui_status tui_show_register_group (struct reggroup *group, 54 struct frame_info *frame, 55 int refresh_values_only); 56 57 static enum tui_status tui_get_register (struct frame_info *frame, 58 struct tui_data_element *data, 59 int regnum, int *changedp); 60 61 static void tui_register_format (struct frame_info *, 62 struct tui_data_element*, int); 63 64 static void tui_scroll_regs_forward_command (char *, int); 65 static void tui_scroll_regs_backward_command (char *, int); 66 67 68 69 /***************************************** 70 ** PUBLIC FUNCTIONS ** 71 ******************************************/ 72 73 /* Answer the number of the last line in the regs display. If there 74 are no registers (-1) is returned. */ 75 int 76 tui_last_regs_line_no (void) 77 { 78 int num_lines = (-1); 79 80 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) 81 { 82 num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count / 83 TUI_DATA_WIN->detail.data_display_info.regs_column_count); 84 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count % 85 TUI_DATA_WIN->detail.data_display_info.regs_column_count) 86 num_lines++; 87 } 88 return num_lines; 89 } 90 91 92 /* Answer the line number that the register element at element_no is 93 on. If element_no is greater than the number of register elements 94 there are, -1 is returned. */ 95 int 96 tui_line_from_reg_element_no (int element_no) 97 { 98 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count) 99 { 100 int i, line = (-1); 101 102 i = 1; 103 while (line == (-1)) 104 { 105 if (element_no < 106 (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i)) 107 line = i - 1; 108 else 109 i++; 110 } 111 112 return line; 113 } 114 else 115 return (-1); 116 } 117 118 119 /* Answer the index of the first element in line_no. If line_no is 120 past the register area (-1) is returned. */ 121 int 122 tui_first_reg_element_no_inline (int line_no) 123 { 124 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) 125 <= TUI_DATA_WIN->detail.data_display_info.regs_content_count) 126 return ((line_no + 1) * 127 TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 128 TUI_DATA_WIN->detail.data_display_info.regs_column_count; 129 else 130 return (-1); 131 } 132 133 134 /* Show the registers of the given group in the data window 135 and refresh the window. */ 136 void 137 tui_show_registers (struct reggroup *group) 138 { 139 enum tui_status ret = TUI_FAILURE; 140 struct tui_data_info *display_info; 141 142 /* Make sure the curses mode is enabled. */ 143 tui_enable (); 144 145 /* Make sure the register window is visible. If not, select an 146 appropriate layout. */ 147 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible) 148 tui_set_layout_for_display_command (DATA_NAME); 149 150 display_info = &TUI_DATA_WIN->detail.data_display_info; 151 if (group == 0) 152 group = general_reggroup; 153 154 /* Say that registers should be displayed, even if there is a 155 problem. */ 156 display_info->display_regs = TRUE; 157 158 if (target_has_registers && target_has_stack && target_has_memory) 159 { 160 ret = tui_show_register_group (group, get_current_frame (), 161 group == display_info->current_group); 162 } 163 if (ret == TUI_FAILURE) 164 { 165 display_info->current_group = 0; 166 tui_erase_data_content (NO_REGS_STRING); 167 } 168 else 169 { 170 int i; 171 172 /* Clear all notation of changed values. */ 173 for (i = 0; i < display_info->regs_content_count; i++) 174 { 175 struct tui_gen_win_info *data_item_win; 176 struct tui_win_element *win; 177 178 data_item_win = &display_info->regs_content[i] 179 ->which_element.data_window; 180 win = (struct tui_win_element *) data_item_win->content[0]; 181 win->which_element.data.highlight = FALSE; 182 } 183 display_info->current_group = group; 184 tui_display_all_data (); 185 } 186 } 187 188 189 /* Set the data window to display the registers of the register group 190 using the given frame. Values are refreshed only when 191 refresh_values_only is TRUE. */ 192 193 static enum tui_status 194 tui_show_register_group (struct reggroup *group, 195 struct frame_info *frame, 196 int refresh_values_only) 197 { 198 struct gdbarch *gdbarch = get_frame_arch (frame); 199 enum tui_status ret = TUI_FAILURE; 200 int nr_regs; 201 int allocated_here = FALSE; 202 int regnum, pos; 203 char title[80]; 204 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info; 205 206 /* Make a new title showing which group we display. */ 207 snprintf (title, sizeof (title) - 1, "Register group: %s", 208 reggroup_name (group)); 209 xfree (TUI_DATA_WIN->generic.title); 210 TUI_DATA_WIN->generic.title = xstrdup (title); 211 212 /* See how many registers must be displayed. */ 213 nr_regs = 0; 214 for (regnum = 0; 215 regnum < gdbarch_num_regs (gdbarch) 216 + gdbarch_num_pseudo_regs (gdbarch); 217 regnum++) 218 { 219 const char *name; 220 221 /* Must be in the group. */ 222 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group)) 223 continue; 224 225 /* If the register name is empty, it is undefined for this 226 processor, so don't display anything. */ 227 name = gdbarch_register_name (gdbarch, regnum); 228 if (name == 0 || *name == '\0') 229 continue; 230 231 nr_regs++; 232 } 233 234 if (display_info->regs_content_count > 0 && !refresh_values_only) 235 { 236 tui_free_data_content (display_info->regs_content, 237 display_info->regs_content_count); 238 display_info->regs_content_count = 0; 239 } 240 241 if (display_info->regs_content_count <= 0) 242 { 243 display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN); 244 allocated_here = TRUE; 245 refresh_values_only = FALSE; 246 } 247 248 if (display_info->regs_content != (tui_win_content) NULL) 249 { 250 if (!refresh_values_only || allocated_here) 251 { 252 TUI_DATA_WIN->generic.content = (void*) NULL; 253 TUI_DATA_WIN->generic.content_size = 0; 254 tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs); 255 display_info->regs_content 256 = (tui_win_content) TUI_DATA_WIN->generic.content; 257 display_info->regs_content_count = nr_regs; 258 } 259 260 /* Now set the register names and values. */ 261 pos = 0; 262 for (regnum = 0; 263 regnum < gdbarch_num_regs (gdbarch) 264 + gdbarch_num_pseudo_regs (gdbarch); 265 regnum++) 266 { 267 struct tui_gen_win_info *data_item_win; 268 struct tui_data_element *data; 269 const char *name; 270 271 /* Must be in the group. */ 272 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group)) 273 continue; 274 275 /* If the register name is empty, it is undefined for this 276 processor, so don't display anything. */ 277 name = gdbarch_register_name (gdbarch, regnum); 278 if (name == 0 || *name == '\0') 279 continue; 280 281 data_item_win = 282 &display_info->regs_content[pos]->which_element.data_window; 283 data = &((struct tui_win_element *) 284 data_item_win->content[0])->which_element.data; 285 if (data) 286 { 287 if (!refresh_values_only) 288 { 289 data->item_no = regnum; 290 data->name = name; 291 data->highlight = FALSE; 292 } 293 tui_get_register (frame, data, regnum, 0); 294 } 295 pos++; 296 } 297 298 TUI_DATA_WIN->generic.content_size = 299 display_info->regs_content_count + display_info->data_content_count; 300 ret = TUI_SUCCESS; 301 } 302 303 return ret; 304 } 305 306 /* Function to display the registers in the content from 307 'start_element_no' until the end of the register content or the end 308 of the display height. No checking for displaying past the end of 309 the registers is done here. */ 310 void 311 tui_display_registers_from (int start_element_no) 312 { 313 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info; 314 315 if (display_info->regs_content != (tui_win_content) NULL 316 && display_info->regs_content_count > 0) 317 { 318 int i = start_element_no; 319 int j, item_win_width, cur_y; 320 321 int max_len = 0; 322 for (i = 0; i < display_info->regs_content_count; i++) 323 { 324 struct tui_data_element *data; 325 struct tui_gen_win_info *data_item_win; 326 char *p; 327 int len; 328 329 data_item_win 330 = &display_info->regs_content[i]->which_element.data_window; 331 data = &((struct tui_win_element *) 332 data_item_win->content[0])->which_element.data; 333 len = 0; 334 p = data->content; 335 if (p != 0) 336 while (*p) 337 { 338 if (*p++ == '\t') 339 len = 8 * ((len / 8) + 1); 340 else 341 len++; 342 } 343 344 if (len > max_len) 345 max_len = len; 346 } 347 item_win_width = max_len + 1; 348 i = start_element_no; 349 350 display_info->regs_column_count = 351 (TUI_DATA_WIN->generic.width - 2) / item_win_width; 352 if (display_info->regs_column_count == 0) 353 display_info->regs_column_count = 1; 354 item_win_width = 355 (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count; 356 357 /* Now create each data "sub" window, and write the display into 358 it. */ 359 cur_y = 1; 360 while (i < display_info->regs_content_count 361 && cur_y <= TUI_DATA_WIN->generic.viewport_height) 362 { 363 for (j = 0; 364 j < display_info->regs_column_count 365 && i < display_info->regs_content_count; 366 j++) 367 { 368 struct tui_gen_win_info *data_item_win; 369 struct tui_data_element *data_element_ptr; 370 371 /* Create the window if necessary. */ 372 data_item_win = &display_info->regs_content[i] 373 ->which_element.data_window; 374 data_element_ptr = &((struct tui_win_element *) 375 data_item_win->content[0])->which_element.data; 376 if (data_item_win->handle != (WINDOW*) NULL 377 && (data_item_win->height != 1 378 || data_item_win->width != item_win_width 379 || data_item_win->origin.x != (item_win_width * j) + 1 380 || data_item_win->origin.y != cur_y)) 381 { 382 tui_delete_win (data_item_win->handle); 383 data_item_win->handle = 0; 384 } 385 386 if (data_item_win->handle == (WINDOW *) NULL) 387 { 388 data_item_win->height = 1; 389 data_item_win->width = item_win_width; 390 data_item_win->origin.x = (item_win_width * j) + 1; 391 data_item_win->origin.y = cur_y; 392 tui_make_window (data_item_win, DONT_BOX_WINDOW); 393 scrollok (data_item_win->handle, FALSE); 394 } 395 touchwin (data_item_win->handle); 396 397 /* Get the printable representation of the register 398 and display it. */ 399 tui_display_register (data_element_ptr, data_item_win); 400 i++; /* Next register. */ 401 } 402 cur_y++; /* Next row. */ 403 } 404 } 405 } 406 407 408 /* Function to display the registers in the content from 409 'start_element_no' on 'start_line_no' until the end of the register 410 content or the end of the display height. This function checks 411 that we won't display off the end of the register display. */ 412 static void 413 tui_display_reg_element_at_line (int start_element_no, 414 int start_line_no) 415 { 416 if (TUI_DATA_WIN->detail.data_display_info.regs_content 417 != (tui_win_content) NULL 418 && TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) 419 { 420 int element_no = start_element_no; 421 422 if (start_element_no != 0 && start_line_no != 0) 423 { 424 int last_line_no, first_line_on_last_page; 425 426 last_line_no = tui_last_regs_line_no (); 427 first_line_on_last_page 428 = last_line_no - (TUI_DATA_WIN->generic.height - 2); 429 if (first_line_on_last_page < 0) 430 first_line_on_last_page = 0; 431 432 /* If there is no other data displayed except registers, and 433 the element_no causes us to scroll past the end of the 434 registers, adjust what element to really start the 435 display at. */ 436 if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0 437 && start_line_no > first_line_on_last_page) 438 element_no 439 = tui_first_reg_element_no_inline (first_line_on_last_page); 440 } 441 tui_display_registers_from (element_no); 442 } 443 } 444 445 446 447 /* Function to display the registers starting at line line_no in the 448 data window. Answers the line number that the display actually 449 started from. If nothing is displayed (-1) is returned. */ 450 int 451 tui_display_registers_from_line (int line_no, 452 int force_display) 453 { 454 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) 455 { 456 int line, element_no; 457 458 if (line_no < 0) 459 line = 0; 460 else if (force_display) 461 { /* If we must display regs (force_display is true), then 462 make sure that we don't display off the end of the 463 registers. */ 464 if (line_no >= tui_last_regs_line_no ()) 465 { 466 if ((line = tui_line_from_reg_element_no ( 467 TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0) 468 line = 0; 469 } 470 else 471 line = line_no; 472 } 473 else 474 line = line_no; 475 476 element_no = tui_first_reg_element_no_inline (line); 477 if (element_no 478 < TUI_DATA_WIN->detail.data_display_info.regs_content_count) 479 tui_display_reg_element_at_line (element_no, line); 480 else 481 line = (-1); 482 483 return line; 484 } 485 486 return (-1); /* Nothing was displayed. */ 487 } 488 489 490 /* This function check all displayed registers for changes in values, 491 given a particular frame. If the values have changed, they are 492 updated with the new value and highlighted. */ 493 void 494 tui_check_register_values (struct frame_info *frame) 495 { 496 if (TUI_DATA_WIN != NULL 497 && TUI_DATA_WIN->generic.is_visible) 498 { 499 struct tui_data_info *display_info 500 = &TUI_DATA_WIN->detail.data_display_info; 501 502 if (display_info->regs_content_count <= 0 503 && display_info->display_regs) 504 tui_show_registers (display_info->current_group); 505 else 506 { 507 int i; 508 509 for (i = 0; (i < display_info->regs_content_count); i++) 510 { 511 struct tui_data_element *data; 512 struct tui_gen_win_info *data_item_win_ptr; 513 int was_hilighted; 514 515 data_item_win_ptr = &display_info->regs_content[i]-> 516 which_element.data_window; 517 data = &((struct tui_win_element *) 518 data_item_win_ptr->content[0])->which_element.data; 519 was_hilighted = data->highlight; 520 521 tui_get_register (frame, data, 522 data->item_no, &data->highlight); 523 524 if (data->highlight || was_hilighted) 525 { 526 tui_display_register (data, data_item_win_ptr); 527 } 528 } 529 } 530 } 531 } 532 533 /* Display a register in a window. If hilite is TRUE, then the value 534 will be displayed in reverse video. */ 535 static void 536 tui_display_register (struct tui_data_element *data, 537 struct tui_gen_win_info *win_info) 538 { 539 if (win_info->handle != (WINDOW *) NULL) 540 { 541 int i; 542 543 if (data->highlight) 544 /* We ignore the return value, casting it to void in order to avoid 545 a compiler warning. The warning itself was introduced by a patch 546 to ncurses 5.7 dated 2009-08-29, changing this macro to expand 547 to code that causes the compiler to generate an unused-value 548 warning. */ 549 (void) wstandout (win_info->handle); 550 551 wmove (win_info->handle, 0, 0); 552 for (i = 1; i < win_info->width; i++) 553 waddch (win_info->handle, ' '); 554 wmove (win_info->handle, 0, 0); 555 if (data->content) 556 waddstr (win_info->handle, data->content); 557 558 if (data->highlight) 559 /* We ignore the return value, casting it to void in order to avoid 560 a compiler warning. The warning itself was introduced by a patch 561 to ncurses 5.7 dated 2009-08-29, changing this macro to expand 562 to code that causes the compiler to generate an unused-value 563 warning. */ 564 (void) wstandend (win_info->handle); 565 tui_refresh_win (win_info); 566 } 567 } 568 569 static void 570 tui_reg_next_command (char *arg, int from_tty) 571 { 572 struct gdbarch *gdbarch = get_current_arch (); 573 574 if (TUI_DATA_WIN != 0) 575 { 576 struct reggroup *group 577 = TUI_DATA_WIN->detail.data_display_info.current_group; 578 579 group = reggroup_next (gdbarch, group); 580 if (group == 0) 581 group = reggroup_next (gdbarch, 0); 582 583 if (group) 584 tui_show_registers (group); 585 } 586 } 587 588 static void 589 tui_reg_float_command (char *arg, int from_tty) 590 { 591 tui_show_registers (float_reggroup); 592 } 593 594 static void 595 tui_reg_general_command (char *arg, int from_tty) 596 { 597 tui_show_registers (general_reggroup); 598 } 599 600 static void 601 tui_reg_system_command (char *arg, int from_tty) 602 { 603 tui_show_registers (system_reggroup); 604 } 605 606 static struct cmd_list_element *tuireglist; 607 608 static void 609 tui_reg_command (char *args, int from_tty) 610 { 611 printf_unfiltered (_("\"tui reg\" must be followed by the name of a " 612 "tui reg command.\n")); 613 help_list (tuireglist, "tui reg ", -1, gdb_stdout); 614 } 615 616 /* Provide a prototype to silence -Wmissing-prototypes. */ 617 extern initialize_file_ftype _initialize_tui_regs; 618 619 void 620 _initialize_tui_regs (void) 621 { 622 struct cmd_list_element **tuicmd; 623 624 tuicmd = tui_get_cmd_list (); 625 626 add_prefix_cmd ("reg", class_tui, tui_reg_command, 627 _("TUI commands to control the register window."), 628 &tuireglist, "tui reg ", 0, 629 tuicmd); 630 631 add_cmd ("float", class_tui, tui_reg_float_command, 632 _("Display only floating point registers."), 633 &tuireglist); 634 add_cmd ("general", class_tui, tui_reg_general_command, 635 _("Display only general registers."), 636 &tuireglist); 637 add_cmd ("system", class_tui, tui_reg_system_command, 638 _("Display only system registers."), 639 &tuireglist); 640 add_cmd ("next", class_tui, tui_reg_next_command, 641 _("Display next register group."), 642 &tuireglist); 643 644 if (xdb_commands) 645 { 646 add_com ("fr", class_tui, tui_reg_float_command, 647 _("Display only floating point registers\n")); 648 add_com ("gr", class_tui, tui_reg_general_command, 649 _("Display only general registers\n")); 650 add_com ("sr", class_tui, tui_reg_system_command, 651 _("Display only special registers\n")); 652 add_com ("+r", class_tui, tui_scroll_regs_forward_command, 653 _("Scroll the registers window forward\n")); 654 add_com ("-r", class_tui, tui_scroll_regs_backward_command, 655 _("Scroll the register window backward\n")); 656 } 657 } 658 659 660 /***************************************** 661 ** STATIC LOCAL FUNCTIONS ** 662 ******************************************/ 663 664 extern int pagination_enabled; 665 666 static void 667 tui_restore_gdbout (void *ui) 668 { 669 ui_file_delete (gdb_stdout); 670 gdb_stdout = (struct ui_file*) ui; 671 pagination_enabled = 1; 672 } 673 674 /* Get the register from the frame and make a printable representation 675 of it in the data element. */ 676 static void 677 tui_register_format (struct frame_info *frame, 678 struct tui_data_element *data_element, 679 int regnum) 680 { 681 struct gdbarch *gdbarch = get_frame_arch (frame); 682 struct ui_file *stream; 683 struct ui_file *old_stdout; 684 const char *name; 685 struct cleanup *cleanups; 686 char *p, *s; 687 688 name = gdbarch_register_name (gdbarch, regnum); 689 if (name == 0 || *name == '\0') 690 return; 691 692 pagination_enabled = 0; 693 old_stdout = gdb_stdout; 694 stream = tui_sfileopen (256); 695 gdb_stdout = stream; 696 cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout); 697 gdbarch_print_registers_info (gdbarch, stream, frame, regnum, 1); 698 699 /* Save formatted output in the buffer. */ 700 p = tui_file_get_strbuf (stream); 701 702 /* Remove the possible \n. */ 703 s = strrchr (p, '\n'); 704 if (s && s[1] == 0) 705 *s = 0; 706 707 xfree (data_element->content); 708 data_element->content = xstrdup (p); 709 do_cleanups (cleanups); 710 } 711 712 /* Get the register value from the given frame and format it for the 713 display. When changep is set, check if the new register value has 714 changed with respect to the previous call. */ 715 static enum tui_status 716 tui_get_register (struct frame_info *frame, 717 struct tui_data_element *data, 718 int regnum, int *changedp) 719 { 720 enum tui_status ret = TUI_FAILURE; 721 722 if (changedp) 723 *changedp = FALSE; 724 if (target_has_registers) 725 { 726 struct value *old_val = data->value; 727 728 data->value = get_frame_register_value (frame, regnum); 729 release_value (data->value); 730 if (changedp) 731 { 732 struct gdbarch *gdbarch = get_frame_arch (frame); 733 int size = register_size (gdbarch, regnum); 734 735 /* We only know whether a value chunk is available if we've 736 tried to read it. */ 737 if (value_lazy (data->value)) 738 value_fetch_lazy (data->value); 739 if (value_lazy (old_val)) 740 value_fetch_lazy (old_val); 741 742 if (value_optimized_out (data->value) != value_optimized_out (old_val) 743 || !value_available_contents_eq (data->value, 0, 744 old_val, 0, size)) 745 *changedp = TRUE; 746 } 747 748 value_free (old_val); 749 750 /* Reformat the data content if the value changed. */ 751 if (changedp == 0 || *changedp == TRUE) 752 tui_register_format (frame, data, regnum); 753 754 ret = TUI_SUCCESS; 755 } 756 return ret; 757 } 758 759 static void 760 tui_scroll_regs_forward_command (char *arg, int from_tty) 761 { 762 tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1); 763 } 764 765 766 static void 767 tui_scroll_regs_backward_command (char *arg, int from_tty) 768 { 769 tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1); 770 } 771