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