GDB (API)
|
00001 /* TUI display locator. 00002 00003 Copyright (C) 1998-2013 Free Software Foundation, Inc. 00004 00005 Contributed by Hewlett-Packard Company. 00006 00007 This file is part of GDB. 00008 00009 This program is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 3 of the License, or 00012 (at your option) any later version. 00013 00014 This program is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00021 00022 #include "defs.h" 00023 #include "symtab.h" 00024 #include "breakpoint.h" 00025 #include "frame.h" 00026 #include "command.h" 00027 #include "inferior.h" 00028 #include "target.h" 00029 #include "top.h" 00030 #include "gdb-demangle.h" 00031 #include "gdb_string.h" 00032 #include "source.h" 00033 #include "tui/tui.h" 00034 #include "tui/tui-data.h" 00035 #include "tui/tui-stack.h" 00036 #include "tui/tui-wingeneral.h" 00037 #include "tui/tui-source.h" 00038 #include "tui/tui-winsource.h" 00039 #include "tui/tui-file.h" 00040 00041 #include "gdb_curses.h" 00042 00043 /* Get a printable name for the function at the address. 00044 The symbol name is demangled if demangling is turned on. 00045 Returns a pointer to a static area holding the result. */ 00046 static char *tui_get_function_from_frame (struct frame_info *fi); 00047 00048 /* Set the full_name portion of the locator. */ 00049 static void tui_set_locator_fullname (const char *fullname); 00050 00051 /* Update the locator, with the provided arguments. */ 00052 static void tui_set_locator_info (struct gdbarch *gdbarch, 00053 const char *fullname, 00054 const char *procname, 00055 int lineno, CORE_ADDR addr); 00056 00057 static void tui_update_command (char *, int); 00058 00059 00060 /* Create the status line to display as much information as we can on 00061 this single line: target name, process number, current function, 00062 current line, current PC, SingleKey mode. */ 00063 static char* 00064 tui_make_status_line (struct tui_locator_element *loc) 00065 { 00066 char *string; 00067 char line_buf[50], *pname; 00068 char *buf; 00069 int status_size; 00070 int i, proc_width; 00071 const char *pid_name; 00072 const char *pc_buf; 00073 int target_width; 00074 int pid_width; 00075 int line_width; 00076 int pc_width; 00077 struct ui_file *pc_out; 00078 00079 if (ptid_equal (inferior_ptid, null_ptid)) 00080 pid_name = "No process"; 00081 else 00082 pid_name = target_pid_to_str (inferior_ptid); 00083 00084 target_width = strlen (target_shortname); 00085 if (target_width > MAX_TARGET_WIDTH) 00086 target_width = MAX_TARGET_WIDTH; 00087 00088 pid_width = strlen (pid_name); 00089 if (pid_width > MAX_PID_WIDTH) 00090 pid_width = MAX_PID_WIDTH; 00091 00092 status_size = tui_term_width (); 00093 string = (char *) xmalloc (status_size + 1); 00094 buf = (char*) alloca (status_size + 1); 00095 00096 /* Translate line number and obtain its size. */ 00097 if (loc->line_no > 0) 00098 xsnprintf (line_buf, sizeof (line_buf), "%d", loc->line_no); 00099 else 00100 strcpy (line_buf, "??"); 00101 line_width = strlen (line_buf); 00102 if (line_width < MIN_LINE_WIDTH) 00103 line_width = MIN_LINE_WIDTH; 00104 00105 /* Translate PC address. */ 00106 pc_out = tui_sfileopen (128); 00107 fputs_filtered (loc->gdbarch? paddress (loc->gdbarch, loc->addr) : "??", 00108 pc_out); 00109 pc_buf = tui_file_get_strbuf (pc_out); 00110 pc_width = strlen (pc_buf); 00111 00112 /* First determine the amount of proc name width we have available. 00113 The +1 are for a space separator between fields. 00114 The -1 are to take into account the \0 counted by sizeof. */ 00115 proc_width = (status_size 00116 - (target_width + 1) 00117 - (pid_width + 1) 00118 - (sizeof (PROC_PREFIX) - 1 + 1) 00119 - (sizeof (LINE_PREFIX) - 1 + line_width + 1) 00120 - (sizeof (PC_PREFIX) - 1 + pc_width + 1) 00121 - (tui_current_key_mode == TUI_SINGLE_KEY_MODE 00122 ? (sizeof (SINGLE_KEY) - 1 + 1) 00123 : 0)); 00124 00125 /* If there is no room to print the function name, try by removing 00126 some fields. */ 00127 if (proc_width < MIN_PROC_WIDTH) 00128 { 00129 proc_width += target_width + 1; 00130 target_width = 0; 00131 if (proc_width < MIN_PROC_WIDTH) 00132 { 00133 proc_width += pid_width + 1; 00134 pid_width = 0; 00135 if (proc_width <= MIN_PROC_WIDTH) 00136 { 00137 proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1; 00138 pc_width = 0; 00139 if (proc_width < 0) 00140 { 00141 proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1; 00142 line_width = 0; 00143 if (proc_width < 0) 00144 proc_width = 0; 00145 } 00146 } 00147 } 00148 } 00149 00150 /* Now convert elements to string form. */ 00151 pname = loc->proc_name; 00152 00153 /* Now create the locator line from the string version of the 00154 elements. We could use sprintf() here but that wouldn't ensure 00155 that we don't overrun the size of the allocated buffer. 00156 strcat_to_buf() will. */ 00157 *string = (char) 0; 00158 00159 if (target_width > 0) 00160 { 00161 sprintf (buf, "%*.*s ", 00162 -target_width, target_width, target_shortname); 00163 strcat_to_buf (string, status_size, buf); 00164 } 00165 if (pid_width > 0) 00166 { 00167 sprintf (buf, "%*.*s ", 00168 -pid_width, pid_width, pid_name); 00169 strcat_to_buf (string, status_size, buf); 00170 } 00171 00172 /* Show whether we are in SingleKey mode. */ 00173 if (tui_current_key_mode == TUI_SINGLE_KEY_MODE) 00174 { 00175 strcat_to_buf (string, status_size, SINGLE_KEY); 00176 strcat_to_buf (string, status_size, " "); 00177 } 00178 00179 /* Procedure/class name. */ 00180 if (proc_width > 0) 00181 { 00182 if (strlen (pname) > proc_width) 00183 sprintf (buf, "%s%*.*s* ", PROC_PREFIX, 00184 1 - proc_width, proc_width - 1, pname); 00185 else 00186 sprintf (buf, "%s%*.*s ", PROC_PREFIX, 00187 -proc_width, proc_width, pname); 00188 strcat_to_buf (string, status_size, buf); 00189 } 00190 00191 if (line_width > 0) 00192 { 00193 sprintf (buf, "%s%*.*s ", LINE_PREFIX, 00194 -line_width, line_width, line_buf); 00195 strcat_to_buf (string, status_size, buf); 00196 } 00197 if (pc_width > 0) 00198 { 00199 strcat_to_buf (string, status_size, PC_PREFIX); 00200 strcat_to_buf (string, status_size, pc_buf); 00201 } 00202 00203 00204 for (i = strlen (string); i < status_size; i++) 00205 string[i] = ' '; 00206 string[status_size] = (char) 0; 00207 00208 ui_file_delete (pc_out); 00209 return string; 00210 } 00211 00212 /* Get a printable name for the function at the address. The symbol 00213 name is demangled if demangling is turned on. Returns a pointer to 00214 a static area holding the result. */ 00215 static char* 00216 tui_get_function_from_frame (struct frame_info *fi) 00217 { 00218 static char name[256]; 00219 struct ui_file *stream = tui_sfileopen (256); 00220 char *p; 00221 00222 print_address_symbolic (get_frame_arch (fi), get_frame_pc (fi), 00223 stream, demangle, ""); 00224 p = tui_file_get_strbuf (stream); 00225 00226 /* Use simple heuristics to isolate the function name. The symbol 00227 can be demangled and we can have function parameters. Remove 00228 them because the status line is too short to display them. */ 00229 if (*p == '<') 00230 p++; 00231 strncpy (name, p, sizeof (name) - 1); 00232 name[sizeof (name) - 1] = 0; 00233 p = strchr (name, '('); 00234 if (!p) 00235 p = strchr (name, '>'); 00236 if (p) 00237 *p = 0; 00238 p = strchr (name, '+'); 00239 if (p) 00240 *p = 0; 00241 ui_file_delete (stream); 00242 return name; 00243 } 00244 00245 void 00246 tui_show_locator_content (void) 00247 { 00248 char *string; 00249 struct tui_gen_win_info *locator; 00250 00251 locator = tui_locator_win_info_ptr (); 00252 00253 if (locator != NULL && locator->handle != (WINDOW *) NULL) 00254 { 00255 struct tui_win_element *element; 00256 00257 element = (struct tui_win_element *) locator->content[0]; 00258 00259 string = tui_make_status_line (&element->which_element.locator); 00260 wmove (locator->handle, 0, 0); 00261 /* We ignore the return value from wstandout and wstandend, casting 00262 them to void in order to avoid a compiler warning. The warning 00263 itself was introduced by a patch to ncurses 5.7 dated 2009-08-29, 00264 changing these macro to expand to code that causes the compiler 00265 to generate an unused-value warning. */ 00266 (void) wstandout (locator->handle); 00267 waddstr (locator->handle, string); 00268 wclrtoeol (locator->handle); 00269 (void) wstandend (locator->handle); 00270 tui_refresh_win (locator); 00271 wmove (locator->handle, 0, 0); 00272 xfree (string); 00273 locator->content_in_use = TRUE; 00274 } 00275 } 00276 00277 00278 /* Set the filename portion of the locator. */ 00279 static void 00280 tui_set_locator_fullname (const char *fullname) 00281 { 00282 struct tui_gen_win_info *locator = tui_locator_win_info_ptr (); 00283 struct tui_locator_element *element; 00284 00285 if (locator->content[0] == NULL) 00286 { 00287 tui_set_locator_info (NULL, fullname, NULL, 0, 0); 00288 return; 00289 } 00290 00291 element = &((struct tui_win_element *) 00292 locator->content[0])->which_element.locator; 00293 element->full_name[0] = 0; 00294 strcat_to_buf (element->full_name, MAX_LOCATOR_ELEMENT_LEN, fullname); 00295 } 00296 00297 /* Update the locator, with the provided arguments. */ 00298 static void 00299 tui_set_locator_info (struct gdbarch *gdbarch, 00300 const char *fullname, 00301 const char *procname, 00302 int lineno, 00303 CORE_ADDR addr) 00304 { 00305 struct tui_gen_win_info *locator = tui_locator_win_info_ptr (); 00306 struct tui_locator_element *element; 00307 00308 /* Allocate the locator content if necessary. */ 00309 if (locator->content_size <= 0) 00310 { 00311 locator->content = (void **) tui_alloc_content (1, locator->type); 00312 locator->content_size = 1; 00313 } 00314 00315 element = &((struct tui_win_element *) 00316 locator->content[0])->which_element.locator; 00317 element->proc_name[0] = (char) 0; 00318 strcat_to_buf (element->proc_name, MAX_LOCATOR_ELEMENT_LEN, procname); 00319 element->line_no = lineno; 00320 element->addr = addr; 00321 element->gdbarch = gdbarch; 00322 tui_set_locator_fullname (fullname); 00323 } 00324 00325 /* Update only the full_name portion of the locator. */ 00326 void 00327 tui_update_locator_fullname (const char *fullname) 00328 { 00329 tui_set_locator_fullname (fullname); 00330 tui_show_locator_content (); 00331 } 00332 00333 /* Function to print the frame information for the TUI. */ 00334 void 00335 tui_show_frame_info (struct frame_info *fi) 00336 { 00337 struct tui_win_info *win_info; 00338 int i; 00339 00340 if (fi) 00341 { 00342 int start_line, i; 00343 CORE_ADDR low; 00344 struct tui_gen_win_info *locator = tui_locator_win_info_ptr (); 00345 int source_already_displayed; 00346 struct symtab_and_line sal; 00347 CORE_ADDR pc; 00348 00349 find_frame_sal (fi, &sal); 00350 00351 source_already_displayed = sal.symtab != 0 00352 && tui_source_is_displayed (symtab_to_fullname (sal.symtab)); 00353 00354 if (get_frame_pc_if_available (fi, &pc)) 00355 tui_set_locator_info (get_frame_arch (fi), 00356 (sal.symtab == 0 00357 ? "??" : symtab_to_fullname (sal.symtab)), 00358 tui_get_function_from_frame (fi), 00359 sal.line, 00360 pc); 00361 else 00362 tui_set_locator_info (get_frame_arch (fi), 00363 "??", _("<unavailable>"), sal.line, 0); 00364 00365 tui_show_locator_content (); 00366 start_line = 0; 00367 for (i = 0; i < (tui_source_windows ())->count; i++) 00368 { 00369 union tui_which_element *item; 00370 00371 win_info = (tui_source_windows ())->list[i]; 00372 00373 item = &((struct tui_win_element *) 00374 locator->content[0])->which_element; 00375 if (win_info == TUI_SRC_WIN) 00376 { 00377 start_line = (item->locator.line_no - 00378 (win_info->generic.viewport_height / 2)) + 1; 00379 if (start_line <= 0) 00380 start_line = 1; 00381 } 00382 else 00383 { 00384 if (find_pc_partial_function (get_frame_pc (fi), 00385 (const char **) NULL, 00386 &low, (CORE_ADDR) 0) == 0) 00387 { 00388 /* There is no symbol available for current PC. There is no 00389 safe way how to "disassemble backwards". */ 00390 low = get_frame_pc (fi); 00391 } 00392 else 00393 low = tui_get_low_disassembly_address (get_frame_arch (fi), 00394 low, get_frame_pc (fi)); 00395 } 00396 00397 if (win_info == TUI_SRC_WIN) 00398 { 00399 struct tui_line_or_address l; 00400 00401 l.loa = LOA_LINE; 00402 l.u.line_no = start_line; 00403 if (!(source_already_displayed 00404 && tui_line_is_displayed (item->locator.line_no, 00405 win_info, TRUE))) 00406 tui_update_source_window (win_info, get_frame_arch (fi), 00407 sal.symtab, l, TRUE); 00408 else 00409 { 00410 l.u.line_no = item->locator.line_no; 00411 tui_set_is_exec_point_at (l, win_info); 00412 } 00413 } 00414 else 00415 { 00416 if (win_info == TUI_DISASM_WIN) 00417 { 00418 struct tui_line_or_address a; 00419 00420 a.loa = LOA_ADDRESS; 00421 a.u.addr = low; 00422 if (!tui_addr_is_displayed (item->locator.addr, 00423 win_info, TRUE)) 00424 tui_update_source_window (win_info, get_frame_arch (fi), 00425 sal.symtab, a, TRUE); 00426 else 00427 { 00428 a.u.addr = item->locator.addr; 00429 tui_set_is_exec_point_at (a, win_info); 00430 } 00431 } 00432 } 00433 tui_update_exec_info (win_info); 00434 } 00435 } 00436 else 00437 { 00438 tui_set_locator_info (NULL, NULL, NULL, 0, (CORE_ADDR) 0); 00439 tui_show_locator_content (); 00440 for (i = 0; i < (tui_source_windows ())->count; i++) 00441 { 00442 win_info = (tui_source_windows ())->list[i]; 00443 tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT); 00444 tui_update_exec_info (win_info); 00445 } 00446 } 00447 } 00448 00449 /* Function to initialize gdb commands, for tui window stack 00450 manipulation. */ 00451 00452 /* Provide a prototype to silence -Wmissing-prototypes. */ 00453 extern initialize_file_ftype _initialize_tui_stack; 00454 00455 void 00456 _initialize_tui_stack (void) 00457 { 00458 add_com ("update", class_tui, tui_update_command, 00459 _("Update the source window and locator to " 00460 "display the current execution point.\n")); 00461 } 00462 00463 /* Command to update the display with the current execution point. */ 00464 static void 00465 tui_update_command (char *arg, int from_tty) 00466 { 00467 char cmd[sizeof("frame 0")]; 00468 00469 strcpy (cmd, "frame 0"); 00470 execute_command (cmd, from_tty); 00471 }