GDB (API)
|
00001 /* Tcl/Tk command definitions for Insight. 00002 Copyright (C) 1994-2013 Free Software Foundation, Inc. 00003 00004 Written by Stu Grossman <grossman@cygnus.com> of Cygnus Support. 00005 Substantially augmented by Martin Hunt, Keith Seitz & Jim Ingham of 00006 Cygnus Support. 00007 00008 This file is part of GDB. 00009 00010 This program is free software; you can redistribute it and/or modify 00011 it under the terms of the GNU General Public License as published by 00012 the Free Software Foundation; either version 2 of the License, or 00013 (at your option) any later version. 00014 00015 This program is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 GNU General Public License for more details. 00019 00020 You should have received a copy of the GNU General Public License 00021 along with this program; if not, write to the Free Software 00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, 00023 Boston, MA 02110-1301, USA. */ 00024 00025 #include "defs.h" 00026 #include "inferior.h" 00027 #include "source.h" 00028 #include "symfile.h" 00029 #include "objfiles.h" 00030 #include "gdbcore.h" 00031 #include "demangle.h" 00032 #include "linespec.h" 00033 #include "top.h" 00034 #include "annotate.h" 00035 #include "block.h" 00036 #include "dictionary.h" 00037 #include "filenames.h" 00038 #include "disasm.h" 00039 #include "value.h" 00040 #include "varobj.h" 00041 #include "exceptions.h" 00042 #include "language.h" 00043 #include "target.h" 00044 #include "valprint.h" 00045 #include "regcache.h" 00046 #include "arch-utils.h" 00047 #include "psymtab.h" 00048 #include <ctype.h> 00049 00050 /* tcl header files includes varargs.h unless HAS_STDARG is defined, 00051 but gdb uses stdarg.h, so make sure HAS_STDARG is defined. */ 00052 #define HAS_STDARG 1 00053 00054 #include <tcl.h> 00055 #include <tk.h> 00056 00057 #include "guitcl.h" 00058 #include "gdbtk.h" 00059 #include "gdbtk-wrapper.h" 00060 #include "gdbtk-cmds.h" 00061 00062 #include <signal.h> 00063 #include <fcntl.h> 00064 #ifdef HAVE_SYS_IOCTL_H 00065 #include <sys/ioctl.h> 00066 #endif 00067 #include <sys/time.h> 00068 #include "gdb_stat.h" 00069 00070 #include "gdb_string.h" 00071 #include "dis-asm.h" 00072 #include "gdbcmd.h" 00073 00074 #ifdef __CYGWIN__ 00075 #include <sys/cygwin.h> /* for cygwin_conv_to_full_win32_path */ 00076 #include <cygwin/version.h> 00077 # if CYGWIN_VERSION_DLL_MAKE_COMBINED(CYGWIN_VERSION_API_MAJOR,CYGWIN_VERSION_API_MINOR) >= 181 00078 # define __USEWIDE 00079 # else 00080 # define CCP_POSIX_TO_WIN_A 0 00081 # define CCP_POSIX_TO_WIN_W 1 00082 # define CCP_WIN_A_TO_POSIX 2 00083 # define CCP_WIN_W_TO_POSIX 3 00084 # define cygwin_conv_path(op, from, to, size) \ 00085 (op == CCP_WIN_A_TO_POSIX) ? \ 00086 cygwin_conv_to_full_posix_path (from, to) : \ 00087 cygwin_conv_to_win32_path (from, to) 00088 # define CW_SET_DOS_FILE_WARNING -1 /* no-op this for older Cygwin */ 00089 # endif 00090 #endif 00091 00092 #ifdef _WIN32 00093 #include <windows.h> /* For gdb_list_processes() */ 00094 #include <tlhelp32.h> 00095 #endif 00096 00097 /* Various globals we reference. */ 00098 extern char *source_path; 00099 00100 /* These two objects hold boolean true and false, 00101 and are shared by all the list objects that gdb_listfuncs 00102 returns. */ 00103 00104 static Tcl_Obj *mangled, *not_mangled; 00105 00106 /* These two control how the GUI behaves when gdb is either tracing or loading. 00107 They are used in this file & gdbtk_hooks.c */ 00108 00109 int No_Update = 0; 00110 int load_in_progress = 0; 00111 00112 /* This Structure is used in gdb_disassemble_driver. 00113 We need a different sort of line table from the normal one cuz we can't 00114 depend upon implicit line-end pc's for lines to do the 00115 reordering in this function. */ 00116 00117 struct my_line_entry 00118 { 00119 int line; 00120 CORE_ADDR start_pc; 00121 CORE_ADDR end_pc; 00122 }; 00123 00124 /* Use this to pass the Tcl Text widget command and the open file 00125 descriptor to the disassembly load command. */ 00126 00127 struct disassembly_client_data 00128 { 00129 FILE *fp; 00130 int file_opened_p; 00131 int widget_line_no; 00132 Tcl_Interp *interp; 00133 char *widget; 00134 Tcl_Obj *result_obj[3]; 00135 const char *asm_argv[14]; 00136 const char *source_argv[7]; 00137 char *map_arr; 00138 Tcl_DString src_to_line_prefix; 00139 Tcl_DString pc_to_line_prefix; 00140 Tcl_DString line_to_pc_prefix; 00141 Tcl_CmdInfo cmd; 00142 }; 00143 00144 /* This variable determines where memory used for disassembly is read 00145 from. See note in gdbtk.h for details. */ 00146 /* NOTE: cagney/2003-09-08: This variable is unused. */ 00147 int disassemble_from_exec = -1; 00148 00149 extern int gdb_variable_init (Tcl_Interp * interp); 00150 00151 /* 00152 * Declarations for routines exported from this file 00153 */ 00154 00155 int Gdbtk_Init (Tcl_Interp * interp); 00156 00157 /* 00158 * Declarations for routines used only in this file. 00159 */ 00160 00161 static int compare_lines (const PTR, const PTR); 00162 static int comp_files (const void *, const void *); 00163 static int gdb_clear_file (ClientData, Tcl_Interp * interp, int, 00164 Tcl_Obj * CONST[]); 00165 static int gdb_cmd (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00166 static int gdb_confirm_quit (ClientData, Tcl_Interp *, int, 00167 Tcl_Obj * CONST[]); 00168 static int gdb_entry_point (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00169 static int gdb_eval (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00170 static int gdb_find_file_command (ClientData, Tcl_Interp *, int, 00171 Tcl_Obj * CONST objv[]); 00172 static int gdb_force_quit (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00173 static int gdb_get_file_command (ClientData, Tcl_Interp *, int, 00174 Tcl_Obj * CONST objv[]); 00175 static int gdb_get_function_command (ClientData, Tcl_Interp *, int, 00176 Tcl_Obj * CONST objv[]); 00177 static int gdb_get_line_command (ClientData, Tcl_Interp *, int, 00178 Tcl_Obj * CONST objv[]); 00179 static int gdb_update_mem (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00180 static int gdb_set_mem (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00181 static int gdb_immediate_command (ClientData, Tcl_Interp *, int, 00182 Tcl_Obj * CONST[]); 00183 static int gdb_incr_addr (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00184 static int gdb_CA_to_TAS (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00185 static int gdb_listfiles (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00186 static int gdb_listfuncs (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00187 static int gdb_loadfile (ClientData, Tcl_Interp *, int, 00188 Tcl_Obj * CONST objv[]); 00189 static int gdb_load_disassembly (ClientData clientData, Tcl_Interp 00190 * interp, int objc, Tcl_Obj * CONST objv[]); 00191 static int gdb_get_inferior_args (ClientData clientData, 00192 Tcl_Interp *interp, 00193 int objc, Tcl_Obj * CONST objv[]); 00194 static int gdb_set_inferior_args (ClientData clientData, 00195 Tcl_Interp *interp, 00196 int objc, Tcl_Obj * CONST objv[]); 00197 static int gdb_load_info (ClientData, Tcl_Interp *, int, 00198 Tcl_Obj * CONST objv[]); 00199 static int gdb_loc (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00200 static int gdb_path_conv (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00201 static int gdb_prompt_command (ClientData, Tcl_Interp *, int, 00202 Tcl_Obj * CONST objv[]); 00203 static int gdb_restore_fputs (ClientData, Tcl_Interp *, int, 00204 Tcl_Obj * CONST[]); 00205 static int gdb_search (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST objv[]); 00206 static int gdb_stop (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); 00207 static int gdb_target_has_execution_command (ClientData, 00208 Tcl_Interp *, int, 00209 Tcl_Obj * CONST[]); 00210 static void gdbtk_load_source (ClientData clientData, 00211 struct symtab *symtab, 00212 int start_line, int end_line); 00213 static CORE_ADDR gdbtk_load_asm (ClientData clientData, CORE_ADDR pc, 00214 struct disassemble_info *di); 00215 static int gdb_disassemble_driver (CORE_ADDR low, CORE_ADDR high, 00216 int mixed_source_and_assembly, 00217 ClientData clientData, 00218 void (*print_source_fn) (ClientData, struct 00219 symtab *, int, 00220 int), 00221 CORE_ADDR (*print_asm_fn) (ClientData, 00222 CORE_ADDR, 00223 struct 00224 disassemble_info 00225 *)); 00226 static int perror_with_name_wrapper (PTR args); 00227 static int wrapped_call (PTR opaque_args); 00228 static int hex2bin (const char *hex, char *bin, int count); 00229 static int fromhex (int a); 00230 static int gdb_list_processes (ClientData, 00231 Tcl_Interp *, 00232 int, 00233 Tcl_Obj * CONST[]); 00234 00235 00236 00237 /* Gdbtk_Init 00238 * This loads all the Tcl commands into the Tcl interpreter. 00239 * 00240 * Arguments: 00241 * interp - The interpreter into which to load the commands. 00242 * 00243 * Result: 00244 * A standard Tcl result. 00245 */ 00246 00247 int 00248 Gdbtk_Init (Tcl_Interp *interp) 00249 { 00250 Tcl_CreateObjCommand (interp, "gdb_cmd", gdbtk_call_wrapper, gdb_cmd, NULL); 00251 Tcl_CreateObjCommand (interp, "gdb_immediate", gdbtk_call_wrapper, 00252 gdb_immediate_command, NULL); 00253 Tcl_CreateObjCommand (interp, "gdb_loc", gdbtk_call_wrapper, gdb_loc, NULL); 00254 Tcl_CreateObjCommand (interp, "gdb_path_conv", gdbtk_call_wrapper, gdb_path_conv, 00255 NULL); 00256 Tcl_CreateObjCommand (interp, "gdb_listfiles", gdbtk_call_wrapper, gdb_listfiles, 00257 NULL); 00258 Tcl_CreateObjCommand (interp, "gdb_listfuncs", gdbtk_call_wrapper, gdb_listfuncs, 00259 NULL); 00260 Tcl_CreateObjCommand (interp, "gdb_entry_point", gdbtk_call_wrapper, 00261 gdb_entry_point, NULL); 00262 Tcl_CreateObjCommand (interp, "gdb_update_mem", gdbtk_call_wrapper, gdb_update_mem, 00263 NULL); 00264 Tcl_CreateObjCommand (interp, "gdb_set_mem", gdbtk_call_wrapper, gdb_set_mem, 00265 NULL); 00266 Tcl_CreateObjCommand (interp, "gdb_stop", gdbtk_call_wrapper, gdb_stop, NULL); 00267 Tcl_CreateObjCommand (interp, "gdb_restore_fputs", gdbtk_call_wrapper, gdb_restore_fputs, 00268 NULL); 00269 Tcl_CreateObjCommand (interp, "gdb_eval", gdbtk_call_wrapper, gdb_eval, NULL); 00270 Tcl_CreateObjCommand (interp, "gdb_incr_addr", gdbtk_call_wrapper, gdb_incr_addr, NULL); 00271 Tcl_CreateObjCommand (interp, "gdb_CA_to_TAS", gdbtk_call_wrapper, gdb_CA_to_TAS, NULL); 00272 Tcl_CreateObjCommand (interp, "gdb_clear_file", gdbtk_call_wrapper, 00273 gdb_clear_file, NULL); 00274 Tcl_CreateObjCommand (interp, "gdb_confirm_quit", gdbtk_call_wrapper, 00275 gdb_confirm_quit, NULL); 00276 Tcl_CreateObjCommand (interp, "gdb_force_quit", gdbtk_call_wrapper, 00277 gdb_force_quit, NULL); 00278 Tcl_CreateObjCommand (interp, "gdb_target_has_execution", 00279 gdbtk_call_wrapper, 00280 gdb_target_has_execution_command, NULL); 00281 Tcl_CreateObjCommand (interp, "gdb_load_info", gdbtk_call_wrapper, gdb_load_info, 00282 NULL); 00283 Tcl_CreateObjCommand (interp, "gdb_get_function", gdbtk_call_wrapper, 00284 gdb_get_function_command, NULL); 00285 Tcl_CreateObjCommand (interp, "gdb_get_line", gdbtk_call_wrapper, 00286 gdb_get_line_command, NULL); 00287 Tcl_CreateObjCommand (interp, "gdb_get_file", gdbtk_call_wrapper, 00288 gdb_get_file_command, NULL); 00289 Tcl_CreateObjCommand (interp, "gdb_prompt", 00290 gdbtk_call_wrapper, gdb_prompt_command, NULL); 00291 Tcl_CreateObjCommand (interp, "gdb_find_file", 00292 gdbtk_call_wrapper, gdb_find_file_command, NULL); 00293 Tcl_CreateObjCommand (interp, "gdb_loadfile", gdbtk_call_wrapper, gdb_loadfile, 00294 NULL); 00295 Tcl_CreateObjCommand (interp, "gdb_load_disassembly", gdbtk_call_wrapper, 00296 gdb_load_disassembly, NULL); 00297 Tcl_CreateObjCommand (gdbtk_interp, "gdb_search", gdbtk_call_wrapper, 00298 gdb_search, NULL); 00299 Tcl_CreateObjCommand (interp, "gdb_get_inferior_args", gdbtk_call_wrapper, 00300 gdb_get_inferior_args, NULL); 00301 Tcl_CreateObjCommand (interp, "gdb_set_inferior_args", gdbtk_call_wrapper, 00302 gdb_set_inferior_args, NULL); 00303 Tcl_CreateObjCommand (interp, "gdb_list_processes", gdbtk_call_wrapper, 00304 gdb_list_processes, NULL); 00305 00306 /* gdb_context is used for debugging multiple threads or tasks */ 00307 Tcl_LinkVar (interp, "gdb_context_id", 00308 (char *) &gdb_context, 00309 TCL_LINK_INT | TCL_LINK_READ_ONLY); 00310 00311 /* Make gdb's notion of the pwd visible. This is read-only because 00312 (1) it doesn't make sense to change it directly and (2) it is 00313 allocated using xmalloc and not Tcl_Alloc. You might think we 00314 could just use the Tcl `pwd' command. However, Tcl (erroneously, 00315 imho) maintains a cache of the current directory name, and 00316 doesn't provide a way for gdb to invalidate the cache. */ 00317 Tcl_LinkVar (interp, "gdb_current_directory", 00318 (char *) ¤t_directory, 00319 TCL_LINK_STRING | TCL_LINK_READ_ONLY); 00320 00321 /* Current gdb source file search path. This is read-only for 00322 reasons similar to those for gdb_current_directory. */ 00323 Tcl_LinkVar (interp, "gdb_source_path", 00324 (char *) &source_path, 00325 TCL_LINK_STRING | TCL_LINK_READ_ONLY); 00326 00327 /* Init variable interface... */ 00328 if (gdb_variable_init (interp) != TCL_OK) 00329 return TCL_ERROR; 00330 00331 /* Init breakpoint module */ 00332 if (Gdbtk_Breakpoint_Init (interp) != TCL_OK) 00333 return TCL_ERROR; 00334 00335 /* Init stack module */ 00336 if (Gdbtk_Stack_Init (interp) != TCL_OK) 00337 return TCL_ERROR; 00338 00339 /* Init register module */ 00340 if (Gdbtk_Register_Init (interp) != TCL_OK) 00341 return TCL_ERROR; 00342 00343 /* Determine where to disassemble from */ 00344 Tcl_LinkVar (gdbtk_interp, "disassemble-from-exec", 00345 (char *) &disassemble_from_exec, 00346 TCL_LINK_INT); 00347 00348 Tcl_PkgProvide (interp, "Gdbtk", GDBTK_VERSION); 00349 return TCL_OK; 00350 } 00351 00352 /* This routine acts as a top-level for all GDB code called by Tcl/Tk. It 00353 handles cleanups, and uses catch_errors to trap calls to return_to_top_level 00354 (usually via error). 00355 This is necessary in order to prevent a longjmp out of the bowels of Tk, 00356 possibly leaving things in a bad state. Since this routine can be called 00357 recursively, it needs to save and restore the contents of the result_ptr as 00358 necessary. */ 00359 00360 int 00361 gdbtk_call_wrapper (ClientData clientData, Tcl_Interp *interp, 00362 int objc, Tcl_Obj *CONST objv[]) 00363 { 00364 struct wrapped_call_args wrapped_args; 00365 gdbtk_result new_result, *old_result_ptr; 00366 int wrapped_returned_error = 0; 00367 00368 old_result_ptr = result_ptr; 00369 result_ptr = &new_result; 00370 result_ptr->obj_ptr = Tcl_NewObj (); 00371 result_ptr->flags = GDBTK_TO_RESULT; 00372 00373 wrapped_args.func = (Tcl_ObjCmdProc *) clientData; 00374 wrapped_args.interp = interp; 00375 wrapped_args.objc = objc; 00376 wrapped_args.objv = objv; 00377 wrapped_args.val = TCL_OK; 00378 00379 if (!catch_errors (wrapped_call, &wrapped_args, "", RETURN_MASK_ALL)) 00380 { 00381 00382 wrapped_args.val = TCL_ERROR; /* Flag an error for TCL */ 00383 00384 /* Make sure the timer interrupts are turned off. */ 00385 gdbtk_stop_timer (); 00386 00387 gdb_flush (gdb_stderr); /* Flush error output */ 00388 gdb_flush (gdb_stdout); /* Sometimes error output comes here as well */ 00389 00390 /* If we errored out here, and the results were going to the 00391 console, then gdbtk_fputs will have gathered the result into the 00392 result_ptr. We also need to echo them out to the console here */ 00393 00394 gdb_flush (gdb_stderr); /* Flush error output */ 00395 gdb_flush (gdb_stdout); /* Sometimes error output comes here as well */ 00396 00397 /* In case of an error, we may need to force the GUI into idle 00398 mode because gdbtk_call_command may have bombed out while in 00399 the command routine. */ 00400 00401 running_now = 0; 00402 Tcl_Eval (interp, "gdbtk_tcl_idle"); 00403 00404 } 00405 else 00406 { 00407 /* If the wrapped call returned an error directly, then we don't 00408 want to reset the result. */ 00409 wrapped_returned_error = wrapped_args.val == TCL_ERROR; 00410 } 00411 00412 /* do not suppress any errors -- a remote target could have errored */ 00413 load_in_progress = 0; 00414 00415 /* 00416 * Now copy the result over to the true Tcl result. If 00417 * GDBTK_TO_RESULT flag bit is set, this just copies a null object 00418 * over to the Tcl result, which is fine because we should reset the 00419 * result in this case anyway. If the wrapped command returned an 00420 * error, then we assume that the result is already set correctly. 00421 */ 00422 if ((result_ptr->flags & GDBTK_IN_TCL_RESULT) || wrapped_returned_error) 00423 { 00424 Tcl_DecrRefCount (result_ptr->obj_ptr); 00425 } 00426 else 00427 { 00428 Tcl_SetObjResult (interp, result_ptr->obj_ptr); 00429 } 00430 00431 result_ptr = old_result_ptr; 00432 00433 #ifdef _WIN32 00434 close_bfds (); 00435 #endif 00436 00437 return wrapped_args.val; 00438 } 00439 00440 /* 00441 * This is the wrapper that is passed to catch_errors. 00442 */ 00443 00444 static int 00445 wrapped_call (PTR opaque_args) 00446 { 00447 struct wrapped_call_args *args = (struct wrapped_call_args *) opaque_args; 00448 args->val = (*args->func) (args->func, args->interp, args->objc, args->objv); 00449 return 1; 00450 } 00451 00452 00453 /* 00454 * This section contains the commands that control execution. 00455 */ 00456 00457 /* This implements the tcl command gdb_clear_file. 00458 00459 * Prepare to accept a new executable file. This is called when we 00460 * want to clear away everything we know about the old file, without 00461 * asking the user. The Tcl code will have already asked the user if 00462 * necessary. After this is called, we should be able to run the 00463 * `file' command without getting any questions. 00464 * 00465 * Arguments: 00466 * None 00467 * Tcl Result: 00468 * None 00469 */ 00470 00471 static int 00472 gdb_clear_file (ClientData clientData, Tcl_Interp *interp, 00473 int objc, Tcl_Obj *CONST objv[]) 00474 { 00475 if (objc != 1) 00476 { 00477 Tcl_WrongNumArgs (interp, 1, objv, NULL); 00478 return TCL_ERROR; 00479 } 00480 00481 if (! ptid_equal (inferior_ptid, null_ptid) && target_has_execution) 00482 { 00483 struct inferior *inf = current_inferior (); 00484 if (inf->attach_flag) 00485 target_detach (NULL, 0); 00486 else 00487 target_kill (); 00488 } 00489 00490 delete_command (NULL, 0); 00491 exec_file_clear (0); 00492 symbol_file_clear (0); 00493 00494 return TCL_OK; 00495 } 00496 00497 /* This implements the tcl command gdb_confirm_quit 00498 * Ask the user to confirm an exit request. 00499 * 00500 * Arguments: 00501 * None 00502 * Tcl Result: 00503 * A boolean, 1 if the user answered yes, 0 if no. 00504 */ 00505 00506 static int 00507 gdb_confirm_quit (ClientData clientData, Tcl_Interp *interp, 00508 int objc, Tcl_Obj *CONST objv[]) 00509 { 00510 int ret; 00511 00512 if (objc != 1) 00513 { 00514 Tcl_WrongNumArgs (interp, 1, objv, NULL); 00515 return TCL_ERROR; 00516 } 00517 00518 ret = quit_confirm (); 00519 Tcl_SetBooleanObj (result_ptr->obj_ptr, ret); 00520 return TCL_OK; 00521 } 00522 00523 /* This implements the tcl command gdb_force_quit 00524 * Quit without asking for confirmation. 00525 * 00526 * Arguments: 00527 * None 00528 * Tcl Result: 00529 * None 00530 */ 00531 00532 static int 00533 gdb_force_quit (ClientData clientData, Tcl_Interp *interp, 00534 int objc, Tcl_Obj *CONST objv[]) 00535 { 00536 if (objc != 1) 00537 { 00538 Tcl_WrongNumArgs (interp, 1, objv, NULL); 00539 return TCL_ERROR; 00540 } 00541 00542 quit_force ((char *) NULL, 1); 00543 return TCL_OK; 00544 } 00545 00546 /* Pressing the stop button on the source window should attempt to 00547 * stop the target. If, after some short time, this fails, a dialog 00548 * should appear allowing the user to detach. 00549 * 00550 * The global GDBTK_FORCE_DETACH is set when we wish to detach from a 00551 * target. This value is returned by deprecated_ui_loop_hook 00552 * (x_event), indicating to callers that they should detach. 00553 * 00554 * Read the comments before x_event to find out how we (try) to keep 00555 * gdbtk alive while some other event loop has stolen control from us. 00556 */ 00557 00558 /* 00559 * This command implements the tcl command gdb_stop, which 00560 * is used to either stop the target or detach. 00561 * Note that it is assumed that a simulator or native target 00562 * can ALWAYS be stopped. Doing a "detach" on them has no effect. 00563 * 00564 * Arguments: 00565 * None or "detach" 00566 * Tcl Result: 00567 * None 00568 */ 00569 00570 static int 00571 gdb_stop (ClientData clientData, Tcl_Interp *interp, 00572 int objc, Tcl_Obj *CONST objv[]) 00573 { 00574 int force = 0; 00575 char *s; 00576 00577 if (objc > 1) 00578 { 00579 s = Tcl_GetStringFromObj (objv[1], NULL); 00580 if (strcmp (s, "detach") == 0) 00581 force = 1; 00582 } 00583 00584 if (force) 00585 { 00586 /* Set the "forcibly detach from target" flag. x_event will 00587 return this value to callers when they should forcibly detach. */ 00588 gdbtk_force_detach = 1; 00589 } 00590 else 00591 { 00592 if (target_ignore != (void (*) (void)) current_target.to_stop) 00593 target_stop (gdbtk_get_ptid ()); 00594 else 00595 set_quit_flag (); /* hope something sees this */ 00596 } 00597 00598 return TCL_OK; 00599 } 00600 00601 /* 00602 * This command lists all processes in a system. Yet only implemented 00603 * for windows as the *nix part is handled directly from tcl code. 00604 * 00605 * Arguments: 00606 * None 00607 * Tcl Result: 00608 * A list of 2 elemented lists containing all running processes 00609 * and their pids. 00610 */ 00611 00612 static int 00613 gdb_list_processes (ClientData clientData, Tcl_Interp *interp, 00614 int objc, Tcl_Obj * CONST objv[]) 00615 { 00616 if (objc != 1) 00617 { 00618 Tcl_WrongNumArgs (interp, 1, objv, NULL); 00619 return TCL_ERROR; 00620 } 00621 00622 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL); 00623 00624 #ifdef _WIN32 00625 { 00626 HANDLE processSnap = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0); 00627 if (processSnap != INVALID_HANDLE_VALUE) 00628 { 00629 PROCESSENTRY32 processEntry; 00630 00631 processEntry.dwSize = sizeof(PROCESSENTRY32); 00632 00633 if (Process32First (processSnap, &processEntry)) 00634 { 00635 do 00636 { 00637 Tcl_Obj *pidProc[2]; 00638 pidProc[0] = Tcl_NewIntObj (processEntry.th32ProcessID); 00639 pidProc[1] = Tcl_NewStringObj (processEntry.szExeFile, -1); 00640 00641 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, 00642 Tcl_NewListObj (2, pidProc)); 00643 00644 } while(Process32Next (processSnap, &processEntry)); 00645 } 00646 00647 CloseHandle (processSnap); 00648 } 00649 } 00650 #endif 00651 00652 return TCL_OK; 00653 } 00654 00655 00656 00657 /* 00658 * This section contains Tcl commands that are wrappers for invoking 00659 * the GDB command interpreter. 00660 */ 00661 00662 00663 /* This implements the tcl command `gdb_eval'. 00664 * It uses the gdb evaluator to return the value of 00665 * an expression in the current language 00666 * 00667 * Tcl Arguments: 00668 * expression - the expression to evaluate. 00669 * format - optional format character. Valid chars are: 00670 * o - octal 00671 * x - hex 00672 * d - decimal 00673 * u - unsigned decimal 00674 * t - binary 00675 * f - float 00676 * a - address 00677 * c - char 00678 * Tcl Result: 00679 * The result of the evaluation. 00680 */ 00681 00682 static int 00683 gdb_eval (ClientData clientData, Tcl_Interp *interp, 00684 int objc, Tcl_Obj *CONST objv[]) 00685 { 00686 struct expression *expr; 00687 struct cleanup *old_chain = NULL; 00688 int format = 0; 00689 value_ptr val; 00690 struct ui_file *stb; 00691 long dummy; 00692 char *result; 00693 struct value_print_options opts; 00694 00695 if (objc != 2 && objc != 3) 00696 { 00697 Tcl_WrongNumArgs (interp, 1, objv, "expression [format]"); 00698 return TCL_ERROR; 00699 } 00700 00701 if (objc == 3) 00702 format = *(Tcl_GetStringFromObj (objv[2], NULL)); 00703 00704 get_formatted_print_options (&opts, format); 00705 00706 expr = parse_expression (Tcl_GetStringFromObj (objv[1], NULL)); 00707 old_chain = make_cleanup (free_current_contents, &expr); 00708 val = evaluate_expression (expr); 00709 00710 /* "Print" the result of the expression evaluation. */ 00711 stb = mem_fileopen (); 00712 make_cleanup_ui_file_delete (stb); 00713 common_val_print (val, stb, 0, &opts, current_language); 00714 result = ui_file_xstrdup (stb, &dummy); 00715 Tcl_SetObjResult (interp, Tcl_NewStringObj (result, -1)); 00716 xfree (result); 00717 result_ptr->flags |= GDBTK_IN_TCL_RESULT; 00718 00719 do_cleanups (old_chain); 00720 return TCL_OK; 00721 } 00722 00723 /* This implements the tcl command "gdb_cmd". 00724 00725 * It sends its argument to the GDB command scanner for execution. 00726 * This command will never cause the update, idle and busy hooks to be called 00727 * within the GUI. 00728 * 00729 * Tcl Arguments: 00730 * command - The GDB command to execute 00731 * from_tty - 1 indicates this comes to the console. 00732 * Pass this to the gdb command. 00733 * Tcl Result: 00734 * The output from the gdb command (except for the "load" & "while" 00735 * which dump their output to the console. 00736 */ 00737 00738 static int 00739 gdb_cmd (ClientData clientData, Tcl_Interp *interp, 00740 int objc, Tcl_Obj *CONST objv[]) 00741 { 00742 int from_tty = 0; 00743 00744 if (objc < 2 || objc > 3) 00745 { 00746 Tcl_WrongNumArgs (interp, 1, objv, "command ?from_tty?"); 00747 return TCL_ERROR; 00748 } 00749 00750 if (objc == 3) 00751 { 00752 if (Tcl_GetBooleanFromObj (NULL, objv[2], &from_tty) != TCL_OK) 00753 { 00754 gdbtk_set_result (interp, "from_tty must be a boolean."); 00755 return TCL_ERROR; 00756 } 00757 } 00758 00759 if (running_now || load_in_progress) 00760 return TCL_OK; 00761 00762 No_Update = 1; 00763 00764 /* for the load instruction (and possibly others later) we 00765 set turn off the GDBTK_TO_RESULT flag bit so gdbtk_fputs() 00766 will not buffer all the data until the command is finished. */ 00767 00768 if ((strncmp ("load ", Tcl_GetStringFromObj (objv[1], NULL), 5) == 0)) 00769 { 00770 result_ptr->flags &= ~GDBTK_TO_RESULT; 00771 load_in_progress = 1; 00772 } 00773 00774 execute_command (Tcl_GetStringFromObj (objv[1], NULL), from_tty); 00775 00776 if (load_in_progress) 00777 { 00778 load_in_progress = 0; 00779 result_ptr->flags |= GDBTK_TO_RESULT; 00780 } 00781 00782 bpstat_do_actions (); 00783 00784 return TCL_OK; 00785 } 00786 00787 /* 00788 * This implements the tcl command "gdb_immediate" 00789 * 00790 * It does exactly the same thing as gdb_cmd, except NONE of its outut 00791 * is buffered. This will also ALWAYS cause the busy, update, and idle 00792 * hooks to be called, contrasted with gdb_cmd, which NEVER calls them. 00793 * It turns off the GDBTK_TO_RESULT flag, which diverts the result 00794 * to the console window. 00795 * 00796 * Tcl Arguments: 00797 * command - The GDB command to execute 00798 * from_tty - 1 to indicate this is from the console. 00799 * Tcl Result: 00800 * None. 00801 */ 00802 00803 static int 00804 gdb_immediate_command (ClientData clientData, Tcl_Interp *interp, 00805 int objc, Tcl_Obj *CONST objv[]) 00806 { 00807 int from_tty = 0; 00808 00809 if (objc < 2 || objc > 3) 00810 { 00811 Tcl_WrongNumArgs (interp, 1, objv, "command ?from_tty?"); 00812 return TCL_ERROR; 00813 } 00814 00815 if (objc == 3) 00816 { 00817 if (Tcl_GetBooleanFromObj (NULL, objv[2], &from_tty) != TCL_OK) 00818 { 00819 gdbtk_set_result (interp, "from_tty must be a boolean."); 00820 return TCL_ERROR; 00821 } 00822 } 00823 00824 if (running_now || load_in_progress) 00825 return TCL_OK; 00826 00827 No_Update = 0; 00828 00829 result_ptr->flags &= ~GDBTK_TO_RESULT; 00830 00831 execute_command (Tcl_GetStringFromObj (objv[1], NULL), from_tty); 00832 00833 bpstat_do_actions (); 00834 00835 result_ptr->flags |= GDBTK_TO_RESULT; 00836 00837 return TCL_OK; 00838 } 00839 00840 /* This implements the tcl command "gdb_prompt" 00841 00842 * It returns the gdb interpreter's prompt. 00843 * 00844 * Tcl Arguments: 00845 * None. 00846 * Tcl Result: 00847 * The prompt. 00848 */ 00849 00850 static int 00851 gdb_prompt_command (ClientData clientData, Tcl_Interp *interp, 00852 int objc, Tcl_Obj *CONST objv[]) 00853 { 00854 Tcl_SetStringObj (result_ptr->obj_ptr, get_prompt (), -1); 00855 return TCL_OK; 00856 } 00857 00858 00859 /* 00860 * This section contains general informational commands. 00861 */ 00862 00863 /* This implements the tcl command "gdb_target_has_execution" 00864 00865 * Tells whether the target is executing. 00866 * 00867 * Tcl Arguments: 00868 * None 00869 * Tcl Result: 00870 * A boolean indicating whether the target is executing. 00871 */ 00872 00873 static int 00874 gdb_target_has_execution_command (ClientData clientData, Tcl_Interp *interp, 00875 int objc, Tcl_Obj *CONST objv[]) 00876 { 00877 int result = 0; 00878 00879 if (target_has_execution && ! ptid_equal (inferior_ptid, null_ptid)) 00880 result = 1; 00881 00882 Tcl_SetBooleanObj (result_ptr->obj_ptr, result); 00883 return TCL_OK; 00884 } 00885 00886 /* This implements the tcl command "gdb_get_inferior_args" 00887 00888 * Returns inferior command line arguments as a string 00889 * 00890 * Tcl Arguments: 00891 * None 00892 * Tcl Result: 00893 * A string containing the inferior command line arguments 00894 */ 00895 00896 static int 00897 gdb_get_inferior_args (ClientData clientData, Tcl_Interp *interp, 00898 int objc, Tcl_Obj *CONST objv[]) 00899 { 00900 if (objc != 1) 00901 { 00902 Tcl_WrongNumArgs (interp, 1, objv, NULL); 00903 return TCL_ERROR; 00904 } 00905 00906 Tcl_SetStringObj (result_ptr->obj_ptr, get_inferior_args (), -1); 00907 return TCL_OK; 00908 } 00909 00910 /* This implements the tcl command "gdb_set_inferior_args" 00911 00912 * Sets inferior command line arguments 00913 * 00914 * Tcl Arguments: 00915 * A string containing the inferior command line arguments 00916 * Tcl Result: 00917 * None 00918 */ 00919 00920 static int 00921 gdb_set_inferior_args (ClientData clientData, Tcl_Interp *interp, 00922 int objc, Tcl_Obj *CONST objv[]) 00923 { 00924 char *args; 00925 00926 if (objc != 2) 00927 { 00928 Tcl_WrongNumArgs (interp, 1, objv, "argument"); 00929 return TCL_ERROR; 00930 } 00931 00932 args = Tcl_GetStringFromObj (objv[1], NULL); 00933 set_inferior_args (args); 00934 00935 return TCL_OK; 00936 } 00937 00938 /* This implements the tcl command "gdb_load_info" 00939 00940 * It returns information about the file about to be downloaded. 00941 * 00942 * Tcl Arguments: 00943 * filename: The file to open & get the info on. 00944 * Tcl Result: 00945 * A list consisting of the name and size of each section. 00946 */ 00947 00948 static int 00949 gdb_load_info (ClientData clientData, Tcl_Interp *interp, 00950 int objc, Tcl_Obj *CONST objv[]) 00951 { 00952 bfd *loadfile_bfd; 00953 struct cleanup *old_cleanups; 00954 asection *s; 00955 Tcl_Obj *ob[2]; 00956 00957 char *filename = Tcl_GetStringFromObj (objv[1], NULL); 00958 00959 loadfile_bfd = bfd_openr (filename, gnutarget); 00960 if (loadfile_bfd == NULL) 00961 { 00962 gdbtk_set_result (interp, "Open of %s failed", filename); 00963 return TCL_ERROR; 00964 } 00965 old_cleanups = make_cleanup_bfd_unref (loadfile_bfd); 00966 00967 if (!bfd_check_format (loadfile_bfd, bfd_object)) 00968 { 00969 do_cleanups (old_cleanups); 00970 gdbtk_set_result (interp, "Bad Object File"); 00971 return TCL_ERROR; 00972 } 00973 00974 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL); 00975 00976 for (s = loadfile_bfd->sections; s; s = s->next) 00977 { 00978 if (s->flags & SEC_LOAD) 00979 { 00980 bfd_size_type size = bfd_get_section_size (s); 00981 if (size > 0) 00982 { 00983 ob[0] = Tcl_NewStringObj ((char *) 00984 bfd_get_section_name (loadfile_bfd, s), 00985 -1); 00986 ob[1] = Tcl_NewLongObj ((long) size); 00987 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, 00988 Tcl_NewListObj (2, ob)); 00989 } 00990 } 00991 } 00992 00993 do_cleanups (old_cleanups); 00994 return TCL_OK; 00995 } 00996 00997 00998 /* This implements the tcl command "gdb_get_line" 00999 01000 * It returns the linenumber for a given linespec. It will take any spec 01001 * that can be passed to decode_line_1 01002 * 01003 * Tcl Arguments: 01004 * linespec - the line specification 01005 * Tcl Result: 01006 * The line number for that spec. 01007 */ 01008 static int 01009 gdb_get_line_command (ClientData clientData, Tcl_Interp *interp, 01010 int objc, Tcl_Obj *CONST objv[]) 01011 { 01012 struct symtabs_and_lines sals; 01013 char *args; 01014 01015 if (objc != 2) 01016 { 01017 Tcl_WrongNumArgs (interp, 1, objv, "linespec"); 01018 return TCL_ERROR; 01019 } 01020 01021 args = Tcl_GetStringFromObj (objv[1], NULL); 01022 sals = decode_line_1 (&args, DECODE_LINE_FUNFIRSTLINE, NULL, 0); 01023 if (sals.nelts == 1) 01024 { 01025 Tcl_SetIntObj (result_ptr->obj_ptr, sals.sals[0].line); 01026 return TCL_OK; 01027 } 01028 01029 Tcl_SetStringObj (result_ptr->obj_ptr, "N/A", -1); 01030 return TCL_OK; 01031 01032 } 01033 01034 /* This implements the tcl command "gdb_get_file" 01035 01036 * It returns the file containing a given line spec. 01037 * 01038 * Tcl Arguments: 01039 * linespec - The linespec to look up 01040 * Tcl Result: 01041 * The file containing it. 01042 */ 01043 01044 static int 01045 gdb_get_file_command (ClientData clientData, Tcl_Interp *interp, 01046 int objc, Tcl_Obj *CONST objv[]) 01047 { 01048 struct symtabs_and_lines sals; 01049 char *args; 01050 01051 if (objc != 2) 01052 { 01053 Tcl_WrongNumArgs (interp, 1, objv, "linespec"); 01054 return TCL_ERROR; 01055 } 01056 01057 args = Tcl_GetStringFromObj (objv[1], NULL); 01058 sals = decode_line_1 (&args, DECODE_LINE_FUNFIRSTLINE, NULL, 0); 01059 if (sals.nelts == 1) 01060 { 01061 Tcl_SetStringObj (result_ptr->obj_ptr, 01062 sals.sals[0].symtab->filename, -1); 01063 return TCL_OK; 01064 } 01065 01066 Tcl_SetStringObj (result_ptr->obj_ptr, "N/A", -1); 01067 return TCL_OK; 01068 } 01069 01070 /* This implements the tcl command "gdb_get_function" 01071 01072 * It finds the function containing the given line spec. 01073 * 01074 * Tcl Arguments: 01075 * linespec - The line specification 01076 * Tcl Result: 01077 * The function that contains it, or "N/A" if it is not in a function. 01078 */ 01079 static int 01080 gdb_get_function_command (ClientData clientData, Tcl_Interp *interp, 01081 int objc, Tcl_Obj *CONST objv[]) 01082 { 01083 const char *function; 01084 struct symtabs_and_lines sals; 01085 char *args; 01086 01087 if (objc != 2) 01088 { 01089 Tcl_WrongNumArgs (interp, 1, objv, "linespec"); 01090 return TCL_ERROR; 01091 } 01092 01093 args = Tcl_GetStringFromObj (objv[1], NULL); 01094 sals = decode_line_1 (&args, DECODE_LINE_FUNFIRSTLINE, NULL, 0); 01095 if (sals.nelts == 1) 01096 { 01097 resolve_sal_pc (&sals.sals[0]); 01098 function = pc_function_name (sals.sals[0].pc); 01099 Tcl_SetStringObj (result_ptr->obj_ptr, function, -1); 01100 return TCL_OK; 01101 } 01102 01103 Tcl_SetStringObj (result_ptr->obj_ptr, "N/A", -1); 01104 return TCL_OK; 01105 } 01106 01107 /* This implements the tcl command "gdb_find_file" 01108 01109 * It searches the symbol tables to get the full pathname to a file. 01110 * 01111 * Tcl Arguments: 01112 * filename: the file name to search for. 01113 * Tcl Result: 01114 * The full path to the file, an empty string if the file was not 01115 * available or an error message if the file is not found in the symtab. 01116 */ 01117 01118 static int 01119 gdb_find_file_command (ClientData clientData, Tcl_Interp *interp, 01120 int objc, Tcl_Obj *CONST objv[]) 01121 { 01122 struct symtab *st; 01123 char *filename, *fullname = NULL; 01124 01125 if (objc != 2) 01126 { 01127 Tcl_WrongNumArgs (interp, 1, objv, "filename"); 01128 return TCL_ERROR; 01129 } 01130 01131 filename = Tcl_GetStringFromObj (objv[1], NULL); 01132 01133 /* Shortcut: There seems to be some mess in gdb dealing with 01134 files. While we should let gdb sort it out, it doesn't hurt 01135 to be a little defensive here. 01136 01137 If the filename is already an absolute filename, just try 01138 to stat it. If it's not found, then ask gdb to find it for us. */ 01139 if (IS_ABSOLUTE_PATH (filename)) 01140 { 01141 struct stat st; 01142 const int status = stat (filename, &st); 01143 01144 if (status == 0) 01145 { 01146 if (S_ISREG (st.st_mode)) 01147 fullname = filename; 01148 } 01149 } 01150 else 01151 { 01152 /* Ask gdb to find the file for us. */ 01153 st = lookup_symtab (filename); 01154 01155 /* We should always get a symtab. */ 01156 if (!st) 01157 { 01158 gdbtk_set_result (interp, "File not found in symtab (2)"); 01159 return TCL_ERROR; 01160 } 01161 01162 fullname = 01163 (st->fullname == NULL ? symtab_to_filename (st) : st->fullname); 01164 } 01165 01166 /* We may not be able to open the file (not available). */ 01167 if (fullname == NULL) 01168 { 01169 Tcl_SetStringObj (result_ptr->obj_ptr, "", -1); 01170 return TCL_OK; 01171 } 01172 01173 Tcl_SetStringObj (result_ptr->obj_ptr, fullname, -1); 01174 01175 return TCL_OK; 01176 } 01177 01178 /* An object of this type is passed to do_listfiles. */ 01179 01180 struct listfiles_info 01181 { 01182 int *numfilesp; 01183 int *files_sizep; 01184 const char ***filesp; 01185 int len; 01186 const char *pathname; 01187 }; 01188 01189 /* This is a helper function for gdb_listfiles that is used via 01190 map_partial_symbol_filenames. */ 01191 01192 static void 01193 do_listfiles (const char *filename, const char *fullname, void *data) 01194 { 01195 struct listfiles_info *info = data; 01196 01197 if (*info->numfilesp == *info->files_sizep) 01198 { 01199 *info->files_sizep *= 2; 01200 *info->filesp = xrealloc (*info->filesp, 01201 *info->files_sizep * sizeof (char *)); 01202 } 01203 01204 if (filename) 01205 { 01206 if (!info->len || !strncmp (info->pathname, filename, info->len) 01207 || !strcmp (filename, lbasename (filename))) 01208 { 01209 (*info->filesp)[(*info->numfilesp)++] = lbasename (filename); 01210 } 01211 } 01212 } 01213 01214 /* This implements the tcl command "gdb_listfiles" 01215 01216 * This lists all the files in the current executible. 01217 * 01218 * Note that this currently pulls in all sorts of filenames 01219 * that aren't really part of the executable. It would be 01220 * best if we could check each file to see if it actually 01221 * contains executable lines of code, but we can't do that 01222 * with psymtabs. 01223 * 01224 * Arguments: 01225 * ?pathname? - If provided, only files which match pathname 01226 * (up to strlen(pathname)) are included. THIS DOES NOT 01227 * CURRENTLY WORK BECAUSE PARTIAL_SYMTABS DON'T SUPPLY 01228 * THE FULL PATHNAME!!! 01229 * 01230 * Tcl Result: 01231 * A list of all matching files. 01232 */ 01233 static int 01234 gdb_listfiles (ClientData clientData, Tcl_Interp *interp, 01235 int objc, Tcl_Obj *CONST objv[]) 01236 { 01237 struct objfile *objfile; 01238 struct partial_symtab *psymtab; 01239 struct symtab *symtab; 01240 const char *lastfile, *pathname = NULL; 01241 const char **files; 01242 int files_size; 01243 int i, numfiles = 0, len = 0; 01244 struct listfiles_info info; 01245 01246 files_size = 1000; 01247 files = (const char **) xmalloc (sizeof (char *) * files_size); 01248 01249 if (objc > 2) 01250 { 01251 Tcl_WrongNumArgs (interp, 1, objv, "?pathname?"); 01252 return TCL_ERROR; 01253 } 01254 else if (objc == 2) 01255 pathname = Tcl_GetStringFromObj (objv[1], &len); 01256 01257 info.numfilesp = &numfiles; 01258 info.files_sizep = &files_size; 01259 info.filesp = &files; 01260 info.len = len; 01261 info.pathname = pathname; 01262 map_partial_symbol_filenames (do_listfiles, &info, 0); 01263 01264 ALL_SYMTABS (objfile, symtab) 01265 { 01266 if (numfiles == files_size) 01267 { 01268 files_size = files_size * 2; 01269 files = (const char **) xrealloc (files, sizeof (char *) * files_size); 01270 } 01271 if (symtab->filename && symtab->linetable && symtab->linetable->nitems) 01272 { 01273 if (!len || !strncmp (pathname, symtab->filename, len) 01274 || !strcmp (symtab->filename, lbasename (symtab->filename))) 01275 { 01276 files[numfiles++] = lbasename (symtab->filename); 01277 } 01278 } 01279 } 01280 01281 qsort (files, numfiles, sizeof (char *), comp_files); 01282 01283 lastfile = ""; 01284 01285 /* Discard the old result pointer, in case it has accumulated anything 01286 and set it to a new list object */ 01287 01288 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL); 01289 01290 for (i = 0; i < numfiles; i++) 01291 { 01292 if (strcmp (files[i], lastfile)) 01293 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, 01294 Tcl_NewStringObj (files[i], -1)); 01295 lastfile = files[i]; 01296 } 01297 01298 free (files); 01299 return TCL_OK; 01300 } 01301 01302 static int 01303 comp_files (const void *file1, const void *file2) 01304 { 01305 return strcmp (*(char **) file1, *(char **) file2); 01306 } 01307 01308 01309 /* This implements the tcl command "gdb_search" 01310 01311 01312 * Tcl Arguments: 01313 * option - One of "functions", "variables" or "types" 01314 * regexp - The regular expression to look for. 01315 * Then, optionally: 01316 * -files fileList 01317 * -static 1/0 01318 * -filename 1/0 01319 * Tcl Result: 01320 * A list of all the matches found. Optionally, if -filename is set to 1, 01321 * then the output is a list of two element lists, with the symbol first, 01322 * and the file in which it is found second. 01323 */ 01324 01325 static int 01326 gdb_search (ClientData clientData, Tcl_Interp *interp, 01327 int objc, Tcl_Obj *CONST objv[]) 01328 { 01329 struct symbol_search *ss = NULL; 01330 struct symbol_search *p; 01331 struct cleanup *old_chain = NULL; 01332 Tcl_Obj *CONST * switch_objv; 01333 int index, switch_objc, i, show_files = 0; 01334 domain_enum space = 0; 01335 char *regexp; 01336 int static_only, nfiles; 01337 Tcl_Obj **file_list; 01338 char **files; 01339 static const char *search_options[] = 01340 {"functions", "variables", "types", (char *) NULL}; 01341 static const char *switches[] = 01342 {"-files", "-filename", "-static", (char *) NULL}; 01343 enum search_opts 01344 { 01345 SEARCH_FUNCTIONS, SEARCH_VARIABLES, SEARCH_TYPES 01346 }; 01347 enum switches_opts 01348 { 01349 SWITCH_FILES, SWITCH_FILENAME, SWITCH_STATIC_ONLY 01350 }; 01351 01352 if (objc < 3) 01353 { 01354 Tcl_WrongNumArgs (interp, 1, objv, "option regexp ?arg ...?"); 01355 return TCL_ERROR; 01356 } 01357 01358 if (Tcl_GetIndexFromObj (interp, objv[1], search_options, "option", 0, 01359 &index) != TCL_OK) 01360 { 01361 result_ptr->flags |= GDBTK_IN_TCL_RESULT; 01362 return TCL_ERROR; 01363 } 01364 01365 /* Unfortunately, we cannot teach search_symbols to search on 01366 multiple regexps, so we have to do a two-tier search for 01367 any searches which choose to narrow the playing field. */ 01368 switch ((enum search_opts) index) 01369 { 01370 case SEARCH_FUNCTIONS: 01371 space = FUNCTIONS_DOMAIN; 01372 break; 01373 case SEARCH_VARIABLES: 01374 space = VARIABLES_DOMAIN; 01375 break; 01376 case SEARCH_TYPES: 01377 space = TYPES_DOMAIN; 01378 break; 01379 } 01380 01381 regexp = Tcl_GetStringFromObj (objv[2], NULL); 01382 /* Process any switches that refine the search */ 01383 switch_objc = objc - 3; 01384 switch_objv = objv + 3; 01385 01386 static_only = 0; 01387 nfiles = 0; 01388 files = (char **) NULL; 01389 while (switch_objc > 0) 01390 { 01391 if (Tcl_GetIndexFromObj (interp, switch_objv[0], switches, 01392 "option", 0, &index) != TCL_OK) 01393 { 01394 result_ptr->flags |= GDBTK_IN_TCL_RESULT; 01395 return TCL_ERROR; 01396 } 01397 01398 switch ((enum switches_opts) index) 01399 { 01400 case SWITCH_FILENAME: 01401 { 01402 if (switch_objc < 2) 01403 { 01404 Tcl_WrongNumArgs (interp, 3, objv, 01405 "?-files fileList -filename 1|0 -static 1|0?"); 01406 result_ptr->flags |= GDBTK_IN_TCL_RESULT; 01407 return TCL_ERROR; 01408 } 01409 if (Tcl_GetBooleanFromObj (interp, switch_objv[1], &show_files) 01410 != TCL_OK) 01411 { 01412 result_ptr->flags |= GDBTK_IN_TCL_RESULT; 01413 return TCL_ERROR; 01414 } 01415 switch_objc--; 01416 switch_objv++; 01417 } 01418 break; 01419 case SWITCH_FILES: 01420 { 01421 int result; 01422 if (switch_objc < 2) 01423 { 01424 Tcl_WrongNumArgs (interp, 3, objv, 01425 "?-files fileList -filename 1|0 -static 1|0?"); 01426 result_ptr->flags |= GDBTK_IN_TCL_RESULT; 01427 return TCL_ERROR; 01428 } 01429 result = Tcl_ListObjGetElements (interp, switch_objv[1], 01430 &nfiles, &file_list); 01431 if (result != TCL_OK) 01432 return result; 01433 01434 files = (char **) xmalloc (nfiles * sizeof (char *)); 01435 for (i = 0; i < nfiles; i++) 01436 files[i] = Tcl_GetStringFromObj (file_list[i], NULL); 01437 switch_objc--; 01438 switch_objv++; 01439 } 01440 break; 01441 case SWITCH_STATIC_ONLY: 01442 if (switch_objc < 2) 01443 { 01444 Tcl_WrongNumArgs (interp, 3, objv, 01445 "?-files fileList -filename 1|0 -static 1|0?"); 01446 result_ptr->flags |= GDBTK_IN_TCL_RESULT; 01447 return TCL_ERROR; 01448 } 01449 if (Tcl_GetBooleanFromObj (interp, switch_objv[1], &static_only) 01450 != TCL_OK) 01451 { 01452 result_ptr->flags |= GDBTK_IN_TCL_RESULT; 01453 return TCL_ERROR; 01454 } 01455 switch_objc--; 01456 switch_objv++; 01457 } 01458 switch_objc--; 01459 switch_objv++; 01460 } 01461 01462 search_symbols (regexp, space, nfiles, files, &ss); 01463 if (ss != NULL) 01464 old_chain = make_cleanup_free_search_symbols (&ss); 01465 01466 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL); 01467 01468 for (p = ss; p != NULL; p = p->next) 01469 { 01470 Tcl_Obj *elem; 01471 01472 if (static_only && p->block != STATIC_BLOCK) 01473 continue; 01474 01475 /* Strip off some C++ special symbols, like RTTI and global 01476 constructors/destructors. */ 01477 if ((p->symbol != NULL 01478 && strncmp (SYMBOL_LINKAGE_NAME (p->symbol), "__tf", 4) != 0 01479 && strncmp (SYMBOL_LINKAGE_NAME (p->symbol), "_GLOBAL_", 8) != 0) 01480 || p->msymbol.minsym != NULL) 01481 { 01482 elem = Tcl_NewListObj (0, NULL); 01483 01484 if (p->msymbol.minsym == NULL) 01485 Tcl_ListObjAppendElement (interp, elem, 01486 Tcl_NewStringObj (SYMBOL_PRINT_NAME (p->symbol), -1)); 01487 else 01488 Tcl_ListObjAppendElement (interp, elem, 01489 Tcl_NewStringObj (SYMBOL_PRINT_NAME (p->msymbol.minsym), -1)); 01490 01491 if (show_files) 01492 { 01493 if ((p->symtab != NULL) && (p->symtab->filename != NULL)) 01494 { 01495 Tcl_ListObjAppendElement (interp, elem, Tcl_NewStringObj 01496 (p->symtab->filename, -1)); 01497 } 01498 else 01499 { 01500 Tcl_ListObjAppendElement (interp, elem, 01501 Tcl_NewStringObj ("", 0)); 01502 } 01503 } 01504 01505 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, elem); 01506 } 01507 } 01508 01509 if (ss != NULL) 01510 do_cleanups (old_chain); 01511 01512 return TCL_OK; 01513 } 01514 01515 /* This implements the tcl command gdb_listfuncs 01516 01517 * It lists all the functions defined in a given file 01518 * 01519 * Arguments: 01520 * file - the file to look in 01521 * Tcl Result: 01522 * A list of two element lists, the first element is 01523 * the symbol name, and the second is a boolean indicating 01524 * whether the symbol is demangled (1 for yes). 01525 */ 01526 01527 static int 01528 gdb_listfuncs (ClientData clientData, Tcl_Interp *interp, 01529 int objc, Tcl_Obj *CONST objv[]) 01530 { 01531 struct symtab *symtab; 01532 struct blockvector *bv; 01533 struct block *b; 01534 struct symbol *sym; 01535 int i; 01536 struct block_iterator iter; 01537 Tcl_Obj *funcVals[2]; 01538 01539 if (objc != 2) 01540 { 01541 Tcl_WrongNumArgs (interp, 1, objv, "file"); 01542 return TCL_ERROR; 01543 } 01544 01545 symtab = lookup_symtab (Tcl_GetStringFromObj (objv[1], NULL)); 01546 if (!symtab) 01547 { 01548 gdbtk_set_result (interp, "No such file (%s)", 01549 Tcl_GetStringFromObj (objv[1], NULL)); 01550 return TCL_ERROR; 01551 } 01552 01553 if (mangled == NULL) 01554 { 01555 mangled = Tcl_NewBooleanObj (1); 01556 not_mangled = Tcl_NewBooleanObj (0); 01557 Tcl_IncrRefCount (mangled); 01558 Tcl_IncrRefCount (not_mangled); 01559 } 01560 01561 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL); 01562 01563 bv = BLOCKVECTOR (symtab); 01564 for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++) 01565 { 01566 b = BLOCKVECTOR_BLOCK (bv, i); 01567 ALL_BLOCK_SYMBOLS (b, iter, sym) 01568 { 01569 if (SYMBOL_CLASS (sym) == LOC_BLOCK) 01570 { 01571 01572 const char *name = SYMBOL_DEMANGLED_NAME (sym); 01573 01574 if (name) 01575 { 01576 /* strip out "global constructors" and 01577 * "global destructors" 01578 * because we aren't interested in them. */ 01579 01580 if (strncmp (name, "global ", 7)) 01581 { 01582 /* If the function is overloaded, 01583 * print out the functions 01584 * declaration, not just its name. */ 01585 01586 funcVals[0] = Tcl_NewStringObj (name, -1); 01587 funcVals[1] = mangled; 01588 } 01589 else 01590 continue; 01591 01592 } 01593 else 01594 { 01595 funcVals[0] = Tcl_NewStringObj (SYMBOL_PRINT_NAME (sym), -1); 01596 funcVals[1] = not_mangled; 01597 } 01598 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, 01599 Tcl_NewListObj (2, funcVals)); 01600 } 01601 } 01602 } 01603 return TCL_OK; 01604 } 01605 01606 /* This implements the TCL command `gdb_restore_fputs' 01607 It sets the fputs_unfiltered hook back to gdbtk_fputs. 01608 Its sole reason for being is that sometimes we move the 01609 fputs hook out of the way to specially trap output, and if 01610 we get an error which we weren't expecting, it won't get put 01611 back, so we run this at idle time as insurance. 01612 */ 01613 01614 static int 01615 gdb_restore_fputs (ClientData clientData, Tcl_Interp *interp, 01616 int objc, Tcl_Obj *CONST objv[]) 01617 { 01618 gdbtk_disable_fputs = 0; 01619 return TCL_OK; 01620 } 01621 01622 01623 /* This implements the tcl command gdb_load_disassembly 01624 * 01625 * Arguments: 01626 * widget - the name of a text widget into which to load the data 01627 * source_with_assm - must be "source" or "nosource" 01628 * low_address - the CORE_ADDR from which to start disassembly 01629 * ?hi_address? - the CORE_ADDR to which to disassemble, defaults 01630 * to the end of the function containing low_address. 01631 * Tcl Result: 01632 * The text widget is loaded with the data, and a list is returned. 01633 * The first element of the list is a two element list containing the 01634 * real low & high elements, the rest is a mapping between line number 01635 * in the text widget, and either the source line number of that line, 01636 * if it is a source line, or the assembly address. You can distinguish 01637 * between the two, because the address will start with 0x... 01638 */ 01639 01640 static int 01641 gdb_load_disassembly (ClientData clientData, Tcl_Interp *interp, 01642 int objc, Tcl_Obj *CONST objv[]) 01643 { 01644 CORE_ADDR low, high, orig; 01645 struct disassembly_client_data client_data; 01646 int mixed_source_and_assembly, ret_val, i; 01647 char *arg_ptr; 01648 char *map_name; 01649 Tcl_WideInt waddr; 01650 01651 if (objc != 6 && objc != 7) 01652 { 01653 Tcl_WrongNumArgs (interp, 1, objv, "[source|nosource] map_arr index_prefix low_address ?hi_address"); 01654 return TCL_ERROR; 01655 } 01656 01657 client_data.widget = Tcl_GetStringFromObj (objv[1], NULL); 01658 if ( Tk_NameToWindow (interp, client_data.widget, 01659 Tk_MainWindow (interp)) == NULL) 01660 { 01661 gdbtk_set_result (interp, "Invalid widget name."); 01662 return TCL_ERROR; 01663 } 01664 01665 if (!Tcl_GetCommandInfo (interp, client_data.widget, &client_data.cmd)) 01666 { 01667 gdbtk_set_result (interp, "Can't get widget command info"); 01668 return TCL_ERROR; 01669 } 01670 01671 arg_ptr = Tcl_GetStringFromObj (objv[2], NULL); 01672 if (*arg_ptr == 's' && strcmp (arg_ptr, "source") == 0) 01673 mixed_source_and_assembly = 1; 01674 else if (*arg_ptr == 'n' && strcmp (arg_ptr, "nosource") == 0) 01675 mixed_source_and_assembly = 0; 01676 else 01677 { 01678 gdbtk_set_result (interp, "Second arg must be 'source' or 'nosource'"); 01679 return TCL_ERROR; 01680 } 01681 01682 /* As we populate the text widget, we will also create an array in the 01683 caller's scope. The name is given by objv[3]. 01684 Each source line gets an entry or the form: 01685 array($prefix,srcline=$src_line_no) = $widget_line_no 01686 01687 Each assembly line gets two entries of the form: 01688 array($prefix,pc=$pc) = $widget_line_no 01689 array($prefix,line=$widget_line_no) = $src_line_no 01690 01691 Where prefix is objv[4]. 01692 */ 01693 01694 map_name = Tcl_GetStringFromObj (objv[3], NULL); 01695 01696 if (*map_name != '\0') 01697 { 01698 char *prefix; 01699 int prefix_len; 01700 01701 client_data.map_arr = "map_array"; 01702 if (Tcl_UpVar (interp, "1", map_name, client_data.map_arr, 0) != TCL_OK) 01703 { 01704 gdbtk_set_result (interp, "Can't link map array."); 01705 return TCL_ERROR; 01706 } 01707 01708 prefix = Tcl_GetStringFromObj (objv[4], &prefix_len); 01709 01710 Tcl_DStringInit(&client_data.src_to_line_prefix); 01711 Tcl_DStringAppend (&client_data.src_to_line_prefix, 01712 prefix, prefix_len); 01713 Tcl_DStringAppend (&client_data.src_to_line_prefix, ",srcline=", 01714 sizeof (",srcline=") - 1); 01715 01716 Tcl_DStringInit(&client_data.pc_to_line_prefix); 01717 Tcl_DStringAppend (&client_data.pc_to_line_prefix, 01718 prefix, prefix_len); 01719 Tcl_DStringAppend (&client_data.pc_to_line_prefix, ",pc=", 01720 sizeof (",pc=") - 1); 01721 01722 Tcl_DStringInit(&client_data.line_to_pc_prefix); 01723 Tcl_DStringAppend (&client_data.line_to_pc_prefix, 01724 prefix, prefix_len); 01725 Tcl_DStringAppend (&client_data.line_to_pc_prefix, ",line=", 01726 sizeof (",line=") - 1); 01727 01728 } 01729 else 01730 { 01731 client_data.map_arr = ""; 01732 } 01733 01734 /* Now parse the addresses */ 01735 if (Tcl_GetWideIntFromObj (interp, objv[5], &waddr) != TCL_OK) 01736 return TCL_ERROR; 01737 low = waddr; 01738 01739 orig = low; 01740 01741 if (objc == 6) 01742 { 01743 if (find_pc_partial_function (low, NULL, &low, &high) == 0) 01744 error ("No function contains address 0x%s", core_addr_to_string (orig)); 01745 } 01746 else 01747 { 01748 if (Tcl_GetWideIntFromObj (interp, objv[6], &waddr) != TCL_OK) 01749 return TCL_ERROR; 01750 high = waddr; 01751 } 01752 01753 /* Setup the client_data structure, and call the driver function. */ 01754 01755 client_data.file_opened_p = 0; 01756 client_data.widget_line_no = 0; 01757 client_data.interp = interp; 01758 for (i = 0; i < 3; i++) 01759 { 01760 client_data.result_obj[i] = Tcl_NewObj(); 01761 Tcl_IncrRefCount (client_data.result_obj[i]); 01762 } 01763 01764 /* Fill up the constant parts of the argv structures */ 01765 client_data.asm_argv[0] = client_data.widget; 01766 client_data.asm_argv[1] = "insert"; 01767 client_data.asm_argv[2] = "end"; 01768 client_data.asm_argv[3] = "-\t"; 01769 client_data.asm_argv[4] = "break_rgn_tag"; 01770 /* client_data.asm_argv[5] = address; */ 01771 client_data.asm_argv[6] = "break_rgn_tag"; 01772 /* client_data.asm_argv[7] = offset; */ 01773 client_data.asm_argv[8] = "break_rgn_tag"; 01774 client_data.asm_argv[9] = ":\t\t"; 01775 client_data.asm_argv[10] = "source_tag"; 01776 /* client_data.asm_argv[11] = code; */ 01777 client_data.asm_argv[12] = "source_tag"; 01778 client_data.asm_argv[13] = "\n"; 01779 01780 if (mixed_source_and_assembly) 01781 { 01782 client_data.source_argv[0] = client_data.widget; 01783 client_data.source_argv[1] = "insert"; 01784 client_data.source_argv[2] = "end"; 01785 /* client_data.source_argv[3] = line_number; */ 01786 client_data.source_argv[4] = ""; 01787 /* client_data.source_argv[5] = line; */ 01788 client_data.source_argv[6] = "source_tag2"; 01789 } 01790 01791 ret_val = gdb_disassemble_driver (low, high, mixed_source_and_assembly, 01792 (ClientData) &client_data, 01793 gdbtk_load_source, gdbtk_load_asm); 01794 01795 /* Now clean up the opened file, and the Tcl data structures */ 01796 01797 if (client_data.file_opened_p == 1) 01798 fclose(client_data.fp); 01799 01800 if (*client_data.map_arr != '\0') 01801 { 01802 Tcl_DStringFree(&client_data.src_to_line_prefix); 01803 Tcl_DStringFree(&client_data.pc_to_line_prefix); 01804 Tcl_DStringFree(&client_data.line_to_pc_prefix); 01805 } 01806 01807 for (i = 0; i < 3; i++) 01808 { 01809 Tcl_DecrRefCount (client_data.result_obj[i]); 01810 } 01811 01812 /* Finally, if we were successful, stick the low & high addresses 01813 into the Tcl result. */ 01814 01815 if (ret_val == TCL_OK) 01816 { 01817 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, 01818 Tcl_NewStringObj (core_addr_to_string (low), -1)); 01819 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, 01820 Tcl_NewStringObj (core_addr_to_string (high), -1)); 01821 } 01822 return ret_val; 01823 } 01824 01825 static void 01826 gdbtk_load_source (ClientData clientData, struct symtab *symtab, 01827 int start_line, int end_line) 01828 { 01829 struct disassembly_client_data *client_data = 01830 (struct disassembly_client_data *) clientData; 01831 char *buffer; 01832 int index_len; 01833 01834 index_len = Tcl_DStringLength (&client_data->src_to_line_prefix); 01835 01836 if (client_data->file_opened_p == 1) 01837 { 01838 const char **text_argv; 01839 char line[10000], line_number[18]; 01840 int found_carriage_return = 1; 01841 01842 /* First do some sanity checks on the requested lines */ 01843 01844 if (start_line < 1 01845 || end_line < start_line || end_line > symtab->nlines) 01846 { 01847 return; 01848 } 01849 01850 line_number[0] = '\t'; 01851 line[0] = '\t'; 01852 01853 text_argv = client_data->source_argv; 01854 01855 text_argv[3] = line_number; 01856 text_argv[5] = line; 01857 01858 if (fseek (client_data->fp, symtab->line_charpos[start_line - 1], 01859 SEEK_SET) < 0) 01860 { 01861 fclose(client_data->fp); 01862 client_data->file_opened_p = -1; 01863 return; 01864 } 01865 01866 for (; start_line < end_line; start_line++) 01867 { 01868 if (!fgets (line + 1, 9980, client_data->fp)) 01869 { 01870 fclose(client_data->fp); 01871 client_data->file_opened_p = -1; 01872 return; 01873 } 01874 01875 client_data->widget_line_no++; 01876 01877 sprintf (line_number + 1, "%d", start_line); 01878 01879 if (found_carriage_return) 01880 { 01881 char *p = strrchr(line, '\0') - 2; 01882 if (*p == '\r') 01883 { 01884 *p = '\n'; 01885 *(p + 1) = '\0'; 01886 } 01887 else 01888 found_carriage_return = 0; 01889 } 01890 01891 /* Run the command, then add an entry to the map array in 01892 the caller's scope, if requested. */ 01893 01894 client_data->cmd.proc (client_data->cmd.clientData, 01895 client_data->interp, 7, text_argv); 01896 01897 if (*client_data->map_arr != '\0') 01898 { 01899 01900 Tcl_DStringAppend (&client_data->src_to_line_prefix, 01901 line_number + 1, -1); 01902 01903 /* FIXME: Convert to Tcl_SetVar2Ex when we move to 8.2. This 01904 will allow us avoid converting widget_line_no into a string. */ 01905 01906 buffer = xstrprintf ("%d", client_data->widget_line_no); 01907 01908 Tcl_SetVar2 (client_data->interp, client_data->map_arr, 01909 Tcl_DStringValue (&client_data->src_to_line_prefix), 01910 buffer, 0); 01911 free(buffer); 01912 01913 Tcl_DStringSetLength (&client_data->src_to_line_prefix, index_len); 01914 } 01915 } 01916 01917 } 01918 else if (!client_data->file_opened_p) 01919 { 01920 int fdes; 01921 /* The file is not yet open, try to open it, then print the 01922 first line. If we fail, set FILE_OPEN_P to -1. */ 01923 01924 fdes = open_source_file (symtab); 01925 if (fdes < 0) 01926 { 01927 client_data->file_opened_p = -1; 01928 } 01929 else 01930 { 01931 /* FIXME: Convert to a Tcl File Channel and read from there. 01932 This will allow us to get the line endings and conversion 01933 to UTF8 right automatically when we move to 8.2. 01934 Need a Cygwin call to convert a file descriptor to the native 01935 Windows handler to do this. */ 01936 01937 client_data->file_opened_p = 1; 01938 client_data->fp = fdopen (fdes, FOPEN_RB); 01939 clearerr (client_data->fp); 01940 01941 if (symtab->line_charpos == 0) 01942 find_source_lines (symtab, fdes); 01943 01944 /* We are called with an actual load request, so call ourselves 01945 to load the first line. */ 01946 01947 gdbtk_load_source (clientData, symtab, start_line, end_line); 01948 } 01949 } 01950 else 01951 { 01952 /* If we couldn't open the file, or got some prior error, just exit. */ 01953 return; 01954 } 01955 } 01956 01957 01958 /* FIXME: cagney/2003-09-08: "di" is not used and unneeded. */ 01959 static CORE_ADDR 01960 gdbtk_load_asm (ClientData clientData, CORE_ADDR pc, 01961 struct disassemble_info *di) 01962 { 01963 struct disassembly_client_data * client_data 01964 = (struct disassembly_client_data *) clientData; 01965 const char **text_argv; 01966 int i, pc_to_line_len, line_to_pc_len; 01967 gdbtk_result new_result; 01968 int insn; 01969 struct cleanup *old_chain = NULL; 01970 01971 pc_to_line_len = Tcl_DStringLength (&client_data->pc_to_line_prefix); 01972 line_to_pc_len = Tcl_DStringLength (&client_data->line_to_pc_prefix); 01973 01974 text_argv = client_data->asm_argv; 01975 01976 /* Preserve the current Tcl result object, print out what we need, and then 01977 suck it out of the result, and replace... */ 01978 01979 old_chain = make_cleanup (gdbtk_restore_result_ptr, (void *) result_ptr); 01980 result_ptr = &new_result; 01981 result_ptr->obj_ptr = client_data->result_obj[0]; 01982 result_ptr->flags = GDBTK_TO_RESULT; 01983 01984 /* Null out the three return objects we will use. */ 01985 01986 for (i = 0; i < 3; i++) 01987 Tcl_SetObjLength (client_data->result_obj[i], 0); 01988 01989 fputs_filtered (paddress (get_current_arch (), pc), gdb_stdout); 01990 gdb_flush (gdb_stdout); 01991 01992 result_ptr->obj_ptr = client_data->result_obj[1]; 01993 print_address_symbolic (get_current_arch (), pc, gdb_stdout, 1, "\t"); 01994 gdb_flush (gdb_stdout); 01995 01996 result_ptr->obj_ptr = client_data->result_obj[2]; 01997 /* FIXME: cagney/2003-09-08: This should use gdb_disassembly. */ 01998 insn = gdb_print_insn (get_current_arch (), pc, gdb_stdout, NULL); 01999 gdb_flush (gdb_stdout); 02000 02001 client_data->widget_line_no++; 02002 02003 text_argv[5] = Tcl_GetStringFromObj (client_data->result_obj[0], NULL); 02004 text_argv[7] = Tcl_GetStringFromObj (client_data->result_obj[1], NULL); 02005 text_argv[11] = Tcl_GetStringFromObj (client_data->result_obj[2], NULL); 02006 02007 client_data->cmd.proc (client_data->cmd.clientData, 02008 client_data->interp, 14, text_argv); 02009 02010 if (*client_data->map_arr != '\0') 02011 { 02012 char *buffer; 02013 02014 /* Run the command, then add an entry to the map array in 02015 the caller's scope. */ 02016 02017 Tcl_DStringAppend (&client_data->pc_to_line_prefix, core_addr_to_string (pc), -1); 02018 02019 /* FIXME: Convert to Tcl_SetVar2Ex when we move to 8.2. This 02020 will allow us avoid converting widget_line_no into a string. */ 02021 02022 buffer = xstrprintf ("%d", client_data->widget_line_no); 02023 02024 Tcl_SetVar2 (client_data->interp, client_data->map_arr, 02025 Tcl_DStringValue (&client_data->pc_to_line_prefix), 02026 buffer, 0); 02027 02028 Tcl_DStringAppend (&client_data->line_to_pc_prefix, buffer, -1); 02029 02030 02031 Tcl_SetVar2 (client_data->interp, client_data->map_arr, 02032 Tcl_DStringValue (&client_data->line_to_pc_prefix), 02033 core_addr_to_string (pc), 0); 02034 02035 /* Restore the prefixes to their initial state. */ 02036 02037 Tcl_DStringSetLength (&client_data->pc_to_line_prefix, pc_to_line_len); 02038 Tcl_DStringSetLength (&client_data->line_to_pc_prefix, line_to_pc_len); 02039 02040 xfree (buffer); 02041 } 02042 02043 do_cleanups (old_chain); 02044 02045 return pc + insn; 02046 } 02047 02048 static int 02049 gdb_disassemble_driver (CORE_ADDR low, CORE_ADDR high, 02050 int mixed_source_and_assembly, 02051 ClientData clientData, 02052 void (*print_source_fn) (ClientData, struct symtab *, int, int), 02053 CORE_ADDR (*print_asm_fn) (ClientData, CORE_ADDR, struct disassemble_info *)) 02054 { 02055 CORE_ADDR pc; 02056 02057 /* If just doing straight assembly, all we need to do is disassemble 02058 everything between low and high. If doing mixed source/assembly, we've 02059 got a totally different path to follow. */ 02060 02061 if (mixed_source_and_assembly) 02062 { /* Come here for mixed source/assembly */ 02063 /* The idea here is to present a source-O-centric view of a function to 02064 the user. This means that things are presented in source order, with 02065 (possibly) out of order assembly immediately following. */ 02066 struct symtab *symtab; 02067 struct linetable_entry *le; 02068 int nlines; 02069 int newlines; 02070 struct my_line_entry *mle; 02071 struct symtab_and_line sal; 02072 int i; 02073 int out_of_order; 02074 int next_line; 02075 02076 /* Assume symtab is valid for whole PC range */ 02077 symtab = find_pc_symtab (low); 02078 02079 if (!symtab || !symtab->linetable) 02080 goto assembly_only; 02081 02082 /* First, convert the linetable to a bunch of my_line_entry's. */ 02083 02084 le = symtab->linetable->item; 02085 nlines = symtab->linetable->nitems; 02086 02087 if (nlines <= 0) 02088 goto assembly_only; 02089 02090 mle = (struct my_line_entry *) alloca (nlines * 02091 sizeof (struct my_line_entry)); 02092 02093 out_of_order = 0; 02094 02095 /* Copy linetable entries for this function into our data structure, 02096 creating end_pc's and setting out_of_order as appropriate. */ 02097 02098 /* First, skip all the preceding functions. */ 02099 02100 for (i = 0; i < nlines - 1 && le[i].pc < low; i++) ; 02101 02102 /* Now, copy all entries before the end of this function. */ 02103 02104 newlines = 0; 02105 for (; i < nlines - 1 && le[i].pc < high; i++) 02106 { 02107 if (le[i].line == le[i + 1].line 02108 && le[i].pc == le[i + 1].pc) 02109 continue; /* Ignore duplicates */ 02110 02111 /* Skip any end-of-function markers. */ 02112 if (le[i].line == 0) 02113 continue; 02114 02115 mle[newlines].line = le[i].line; 02116 if (le[i].line > le[i + 1].line) 02117 out_of_order = 1; 02118 mle[newlines].start_pc = le[i].pc; 02119 mle[newlines].end_pc = le[i + 1].pc; 02120 newlines++; 02121 } 02122 02123 /* If we're on the last line, and it's part of the function, then we 02124 need to get the end pc in a special way. */ 02125 02126 if (i == nlines - 1 02127 && le[i].pc < high) 02128 { 02129 mle[newlines].line = le[i].line; 02130 mle[newlines].start_pc = le[i].pc; 02131 sal = find_pc_line (le[i].pc, 0); 02132 mle[newlines].end_pc = sal.end; 02133 newlines++; 02134 } 02135 02136 /* Now, sort mle by line #s (and, then by addresses within lines). */ 02137 02138 if (out_of_order) 02139 qsort (mle, newlines, sizeof (struct my_line_entry), compare_lines); 02140 02141 /* Now, for each line entry, emit the specified lines (unless they have 02142 been emitted before), followed by the assembly code for that line. */ 02143 02144 next_line = 0; /* Force out first line */ 02145 for (i = 0; i < newlines; i++) 02146 { 02147 /* Print out everything from next_line to the current line. */ 02148 02149 if (mle[i].line >= next_line) 02150 { 02151 if (next_line != 0) 02152 print_source_fn (clientData, symtab, next_line, 02153 mle[i].line + 1); 02154 else 02155 print_source_fn (clientData, symtab, mle[i].line, 02156 mle[i].line + 1); 02157 02158 next_line = mle[i].line + 1; 02159 } 02160 02161 for (pc = mle[i].start_pc; pc < mle[i].end_pc; ) 02162 { 02163 QUIT; 02164 /* FIXME: cagney/2003-09-08: This entire function should 02165 be replaced by gdb_disassembly. */ 02166 pc = print_asm_fn (clientData, pc, NULL); 02167 } 02168 } 02169 } 02170 else 02171 { 02172 assembly_only: 02173 for (pc = low; pc < high; ) 02174 { 02175 QUIT; 02176 /* FIXME: cagney/2003-09-08: This entire function should be 02177 replaced by gdb_disassembly. */ 02178 pc = print_asm_fn (clientData, pc, NULL); 02179 } 02180 } 02181 02182 return TCL_OK; 02183 } 02184 02185 /* This will be passed to qsort to sort the results of the disassembly */ 02186 02187 static int 02188 compare_lines (const PTR mle1p, const PTR mle2p) 02189 { 02190 struct my_line_entry *mle1, *mle2; 02191 int val; 02192 02193 mle1 = (struct my_line_entry *) mle1p; 02194 mle2 = (struct my_line_entry *) mle2p; 02195 02196 val = mle1->line - mle2->line; 02197 02198 if (val != 0) 02199 return val; 02200 02201 return mle1->start_pc - mle2->start_pc; 02202 } 02203 02204 /* This implements the TCL command `gdb_loc', 02205 02206 * Arguments: 02207 * ?symbol? The symbol or address to locate - defaults to pc 02208 * Tcl Return: 02209 * a list consisting of the following: 02210 * basename, function name, filename, line number, address, current pc 02211 */ 02212 02213 static int 02214 gdb_loc (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) 02215 { 02216 char *filename; 02217 struct symtab_and_line sal; 02218 const char *fname; 02219 CORE_ADDR pc; 02220 02221 if (objc == 1) 02222 { 02223 /* This function can be called, before the target is properly 02224 set-up, the following prevents an error, by trying to 02225 read_pc when there is no pc to read. It defaults pc, 02226 before the target is connected to the entry point of the 02227 program */ 02228 if (!target_has_registers) 02229 { 02230 pc = entry_point_address (); 02231 sal = find_pc_line (pc, 0); 02232 } 02233 else 02234 { 02235 struct frame_info *frame; 02236 CORE_ADDR frame_pc, current_pc; 02237 02238 frame = get_selected_frame (NULL); 02239 current_pc = regcache_read_pc (get_current_regcache ()); 02240 frame_pc = get_frame_pc (frame); 02241 02242 if (frame_pc != current_pc) 02243 { 02244 /* Note - this next line is not correct on all architectures. 02245 For a graphical debugger we really want to highlight the 02246 assembly line that called the next function on the stack. 02247 Many architectures have the next instruction saved as the 02248 pc on the stack, so what happens is the next instruction 02249 is highlighted. FIXME */ 02250 pc = frame_pc; 02251 find_frame_sal (frame, &sal); 02252 } 02253 else 02254 { 02255 pc = current_pc; 02256 sal = find_pc_line (pc, 0); 02257 } 02258 } 02259 } 02260 else if (objc == 2) 02261 { 02262 struct symtabs_and_lines sals; 02263 int nelts; 02264 02265 sals = decode_line_with_current_source (Tcl_GetStringFromObj (objv[1], NULL), 1); 02266 02267 nelts = sals.nelts; 02268 sal = sals.sals[0]; 02269 free (sals.sals); 02270 02271 if (sals.nelts != 1) 02272 { 02273 gdbtk_set_result (interp, "Ambiguous line spec", -1); 02274 return TCL_ERROR; 02275 } 02276 resolve_sal_pc (&sal); 02277 pc = sal.pc; 02278 } 02279 else 02280 { 02281 Tcl_WrongNumArgs (interp, 1, objv, "?symbol?"); 02282 return TCL_ERROR; 02283 } 02284 02285 if (sal.symtab) 02286 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, 02287 Tcl_NewStringObj (sal.symtab->filename, -1)); 02288 else 02289 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, 02290 Tcl_NewStringObj ("", 0)); 02291 02292 fname = pc_function_name (pc); 02293 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, 02294 Tcl_NewStringObj (fname, -1)); 02295 02296 filename = symtab_to_filename (sal.symtab); 02297 if (filename == NULL) 02298 filename = ""; 02299 02300 /* file name */ 02301 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewStringObj (filename, -1)); 02302 /* line number */ 02303 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj (sal.line)); 02304 /* PC in current frame */ 02305 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, 02306 Tcl_NewStringObj (core_addr_to_string (pc), -1)); 02307 /* Real PC */ 02308 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, 02309 Tcl_NewStringObj (core_addr_to_string (stop_pc), -1)); 02310 /* shared library */ 02311 #ifdef PC_SOLIB 02312 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, 02313 Tcl_NewStringObj (PC_SOLIB (pc), -1)); 02314 #else 02315 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, 02316 Tcl_NewStringObj ("", -1)); 02317 #endif 02318 return TCL_OK; 02319 } 02320 02321 /* This implements the TCL command gdb_entry_point. It returns the current 02322 entry point address. */ 02323 02324 static int 02325 gdb_entry_point (ClientData clientData, Tcl_Interp *interp, 02326 int objc, Tcl_Obj *CONST objv[]) 02327 { 02328 char *addrstr; 02329 02330 /* If we have not yet loaded an exec file, then we have no 02331 entry point, so return an empty string.*/ 02332 if ((int) current_target.to_stratum > (int) dummy_stratum) 02333 { 02334 addrstr = (char *)core_addr_to_string (entry_point_address ()); 02335 Tcl_SetStringObj (result_ptr->obj_ptr, addrstr, -1); 02336 } 02337 else 02338 Tcl_SetStringObj (result_ptr->obj_ptr, "", -1); 02339 02340 return TCL_OK; 02341 } 02342 02343 /* Covert hex to binary. Stolen from remote.c, 02344 but added error handling */ 02345 static int 02346 fromhex (int a) 02347 { 02348 if (a >= '0' && a <= '9') 02349 return a - '0'; 02350 else if (a >= 'a' && a <= 'f') 02351 return a - 'a' + 10; 02352 else if (a >= 'A' && a <= 'F') 02353 return a - 'A' + 10; 02354 02355 return -1; 02356 } 02357 02358 static int 02359 hex2bin (const char *hex, char *bin, int count) 02360 { 02361 int i, m, n; 02362 int incr = 2; 02363 02364 02365 if (gdbarch_byte_order (get_current_arch ()) == BFD_ENDIAN_LITTLE) 02366 { 02367 /* need to read string in reverse */ 02368 hex += count - 2; 02369 incr = -2; 02370 } 02371 02372 for (i = 0; i < count; i += 2) 02373 { 02374 if (hex[0] == 0 || hex[1] == 0) 02375 { 02376 /* Hex string is short, or of uneven length. 02377 Return the count that has been converted so far. */ 02378 return i; 02379 } 02380 m = fromhex (hex[0]); 02381 n = fromhex (hex[1]); 02382 if (m == -1 || n == -1) 02383 return -1; 02384 *bin++ = m * 16 + n; 02385 hex += incr; 02386 } 02387 02388 return i; 02389 } 02390 02391 /* This implements the Tcl command 'gdb_set_mem', which 02392 * sets some chunk of memory. 02393 * 02394 * Arguments: 02395 * gdb_set_mem addr hexstr len 02396 * 02397 * addr: address of data to set 02398 * hexstr: ascii string of data to set 02399 * len: number of bytes of data to set 02400 */ 02401 static int 02402 gdb_set_mem (ClientData clientData, Tcl_Interp *interp, 02403 int objc, Tcl_Obj *CONST objv[]) 02404 { 02405 CORE_ADDR addr; 02406 gdb_byte buf[128]; 02407 char *hexstr; 02408 int len, size; 02409 02410 if (objc != 4) 02411 { 02412 Tcl_WrongNumArgs (interp, 1, objv, "addr hex_data len"); 02413 return TCL_ERROR; 02414 } 02415 02416 /* Address to write */ 02417 addr = string_to_core_addr (Tcl_GetStringFromObj (objv[1], NULL)); 02418 02419 /* String value to write: it's in hex */ 02420 hexstr = Tcl_GetStringFromObj (objv[2], NULL); 02421 if (hexstr == NULL) 02422 return TCL_ERROR; 02423 02424 /* Length of buf */ 02425 if (Tcl_GetIntFromObj (interp, objv[3], &len) != TCL_OK) 02426 return TCL_ERROR; 02427 02428 /* Convert hexstr to binary and write */ 02429 if (hexstr[0] == '0' && hexstr[1] == 'x') 02430 hexstr += 2; 02431 size = hex2bin (hexstr, (char *) buf, strlen (hexstr)); 02432 if (size < 0) 02433 { 02434 /* Error in input */ 02435 gdbtk_set_result (interp, "Invalid hexadecimal input: \"0x%s\"", hexstr); 02436 return TCL_ERROR; 02437 } 02438 02439 target_write_memory (addr, buf, len); 02440 return TCL_OK; 02441 } 02442 02443 /* This implements the Tcl command 'gdb_update_mem', which 02444 * updates a block of memory in the memory window 02445 * 02446 * Arguments: 02447 * gdb_update_mem data addr form size nbytes bpr aschar 02448 * 02449 * 1 data: variable that holds table's data 02450 * 2 addr: address of data to dump 02451 * 3 mform: a char indicating format 02452 * 4 size: size of each element; 1,2,4, or 8 bytes 02453 * 5 nbytes: the number of bytes to read 02454 * 6 bpr: bytes per row 02455 * 7 aschar: if present, an ASCII dump of the row is included. ASCHAR 02456 * used for unprintable characters. 02457 * 02458 * Return: 02459 * a list of three integers: {border_col_width data_col_width ascii_col_width} 02460 * which can be used to set the table's column widths. */ 02461 02462 static int 02463 gdb_update_mem (ClientData clientData, Tcl_Interp *interp, 02464 int objc, Tcl_Obj *CONST objv[]) 02465 { 02466 long dummy; 02467 char index[20]; 02468 CORE_ADDR addr; 02469 int nbytes, rnum, bpr; 02470 int size, asize, i, j, bc; 02471 int max_ascii_len, max_val_len, max_label_len; 02472 char format, aschar; 02473 char *data, *tmp; 02474 char buff[128], *bptr; 02475 gdb_byte *mbuf, *mptr, *cptr; 02476 struct ui_file *stb; 02477 struct type *val_type; 02478 struct cleanup *old_chain; 02479 02480 if (objc < 7 || objc > 8) 02481 { 02482 Tcl_WrongNumArgs (interp, 1, objv, "data addr format size bytes bytes_per_row ?ascii_char?"); 02483 return TCL_ERROR; 02484 } 02485 02486 /* Get table data and link to a local variable */ 02487 data = Tcl_GetStringFromObj (objv[1], NULL); 02488 if (data == NULL) 02489 { 02490 gdbtk_set_result (interp, "could not get data variable"); 02491 return TCL_ERROR; 02492 } 02493 02494 if (Tcl_UpVar (interp, "1", data, "data", 0) != TCL_OK) 02495 { 02496 gdbtk_set_result (interp, "could not link table data"); 02497 return TCL_ERROR; 02498 } 02499 02500 if (Tcl_GetIntFromObj (interp, objv[4], &size) != TCL_OK) 02501 return TCL_ERROR; 02502 else if (size <= 0) 02503 { 02504 gdbtk_set_result (interp, "Invalid size, must be > 0"); 02505 return TCL_ERROR; 02506 } 02507 02508 if (Tcl_GetIntFromObj (interp, objv[5], &nbytes) != TCL_OK) 02509 return TCL_ERROR; 02510 else if (nbytes <= 0) 02511 { 02512 gdbtk_set_result (interp, "Invalid number of bytes, must be > 0"); 02513 return TCL_ERROR; 02514 } 02515 02516 if (Tcl_GetIntFromObj (interp, objv[6], &bpr) != TCL_OK) 02517 return TCL_ERROR; 02518 else if (bpr <= 0) 02519 { 02520 gdbtk_set_result (interp, "Invalid bytes per row, must be > 0"); 02521 return TCL_ERROR; 02522 } 02523 02524 tmp = Tcl_GetStringFromObj (objv[2], NULL); 02525 if (tmp == NULL) 02526 { 02527 gdbtk_set_result (interp, "could not get address"); 02528 return TCL_ERROR; 02529 } 02530 addr = string_to_core_addr (tmp); 02531 02532 format = *(Tcl_GetStringFromObj (objv[3], NULL)); 02533 mbuf = (gdb_byte *) xmalloc (nbytes + 32); 02534 if (!mbuf) 02535 { 02536 gdbtk_set_result (interp, "Out of memory."); 02537 return TCL_ERROR; 02538 } 02539 02540 memset (mbuf, 0, nbytes + 32); 02541 mptr = cptr = mbuf; 02542 02543 /* Dispatch memory reads to the topmost target, not the flattened 02544 current_target. */ 02545 rnum = target_read (current_target.beneath, TARGET_OBJECT_MEMORY, NULL, 02546 mbuf, addr, nbytes); 02547 if (rnum <= 0) 02548 { 02549 gdbtk_set_result (interp, "Unable to read memory."); 02550 return TCL_ERROR; 02551 } 02552 02553 if (objc == 8) 02554 aschar = *(Tcl_GetStringFromObj (objv[7], NULL)); 02555 else 02556 aschar = 0; 02557 02558 switch (size) 02559 { 02560 case 1: 02561 val_type = builtin_type (get_current_arch ())->builtin_int8; 02562 asize = 'b'; 02563 break; 02564 case 2: 02565 val_type = builtin_type (get_current_arch ())->builtin_int16; 02566 asize = 'h'; 02567 break; 02568 case 4: 02569 val_type = builtin_type (get_current_arch ())->builtin_int32; 02570 asize = 'w'; 02571 break; 02572 case 8: 02573 val_type = builtin_type (get_current_arch ())->builtin_int64; 02574 asize = 'g'; 02575 break; 02576 default: 02577 val_type = builtin_type (get_current_arch ())->builtin_int8; 02578 asize = 'b'; 02579 } 02580 02581 bc = 0; /* count of bytes in a row */ 02582 bptr = &buff[0]; /* pointer for ascii dump */ 02583 02584 /* Open a memory ui_file that we can use to print memory values */ 02585 stb = mem_fileopen (); 02586 old_chain = make_cleanup_ui_file_delete (stb); 02587 02588 /* A little macro to do column indices. As a rule, given the current 02589 byte, i, of a total nbytes and the bytes per row, bpr, and the size of 02590 each cell, size, the row and column will be given by: 02591 02592 row = i/bpr 02593 col = (i%bpr)/size 02594 */ 02595 #define INDEX(row,col) sprintf (index, "%d,%d",(row),(col)) 02596 02597 /* Fill in address labels */ 02598 max_label_len = 0; 02599 for (i = 0; i < nbytes; i += bpr) 02600 { 02601 char s[130]; 02602 sprintf (s, "%s", core_addr_to_string (addr + i)); 02603 INDEX ((int) i/bpr, -1); 02604 Tcl_SetVar2 (interp, "data", index, s, 0); 02605 02606 /* The tcl code in MemWin::update_addr used to track the size 02607 of each cell. I don't see how these could change for any given 02608 update, so we don't loop over all cells. We just note the first 02609 size. */ 02610 if (max_label_len == 0) 02611 max_label_len = strlen (s); 02612 } 02613 02614 /* Fill in memory */ 02615 max_val_len = 0; /* Ditto the above comments about max_label_len */ 02616 max_ascii_len = 0; 02617 for (i = 0; i < nbytes; i += size) 02618 { 02619 INDEX ((int) i/bpr, (int) (i%bpr)/size); 02620 02621 if (i >= rnum) 02622 { 02623 /* Read fewer bytes than requested */ 02624 tmp = "N/A"; 02625 02626 if (aschar) 02627 { 02628 for (j = 0; j < size; j++) 02629 *bptr++ = 'X'; 02630 } 02631 } 02632 else 02633 { 02634 struct value_print_options opts; 02635 02636 get_formatted_print_options (&opts, format); 02637 02638 /* print memory to our uiout file and set the table's variable */ 02639 ui_file_rewind (stb); 02640 print_scalar_formatted (mptr, val_type, &opts, asize, stb); 02641 tmp = ui_file_xstrdup (stb, &dummy); 02642 02643 /* See comments above on max_*_len */ 02644 if (max_val_len == 0) 02645 max_val_len = strlen (tmp); 02646 02647 if (aschar) 02648 { 02649 for (j = 0; j < size; j++) 02650 { 02651 if (isprint (*cptr)) 02652 *bptr++ = *cptr++; 02653 else 02654 { 02655 *bptr++ = aschar; 02656 cptr++;; 02657 } 02658 } 02659 } 02660 } 02661 Tcl_SetVar2 (interp, "data", index, tmp, 0); 02662 02663 mptr += size; 02664 bc += size; 02665 02666 if (aschar && (bc >= bpr)) 02667 { 02668 /* end of row. Add it to the result and reset variables */ 02669 *bptr = '\000'; 02670 INDEX (i/bpr, bpr/size); 02671 Tcl_SetVar2 (interp, "data", index, buff, 0); 02672 02673 /* See comments above on max_*_len */ 02674 if (max_ascii_len == 0) 02675 max_ascii_len = strlen (buff); 02676 02677 bc = 0; 02678 bptr = &buff[0]; 02679 } 02680 } 02681 02682 /* return max_*_len so that column widths can be set */ 02683 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewIntObj (max_label_len + 1)); 02684 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewIntObj (max_val_len + 1)); 02685 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewIntObj (max_ascii_len + 1)); 02686 do_cleanups (old_chain); 02687 xfree (mbuf); 02688 return TCL_OK; 02689 #undef INDEX 02690 } 02691 02692 02693 /* This implements the tcl command "gdb_loadfile" 02694 * It loads a c source file into a text widget. 02695 * 02696 * Tcl Arguments: 02697 * widget: the name of the text widget to fill 02698 * filename: the name of the file to load 02699 * linenumbers: A boolean indicating whether or not to display line numbers. 02700 * Tcl Result: 02701 * 02702 */ 02703 02704 /* In this routine, we will build up a "line table", i.e. a 02705 * table of bits showing which lines in the source file are executible. 02706 * LTABLE_SIZE is the number of bytes to allocate for the line table. 02707 * 02708 * Its size limits the maximum number of lines 02709 * in a file to 8 * LTABLE_SIZE. This memory is freed after 02710 * the file is loaded, so it is OK to make this very large. 02711 * Additional memory will be allocated if needed. */ 02712 #define LTABLE_SIZE 20000 02713 static int 02714 gdb_loadfile (ClientData clientData, Tcl_Interp *interp, int objc, 02715 Tcl_Obj *CONST objv[]) 02716 { 02717 char *file, *widget; 02718 int linenumbers, ln, lnum, ltable_size; 02719 FILE *fp; 02720 char *ltable; 02721 struct symtab *symtab; 02722 struct linetable_entry *le; 02723 long mtime = 0; 02724 struct stat st; 02725 char line[10000], line_num_buf[18]; 02726 const char *text_argv[9]; 02727 Tcl_CmdInfo text_cmd; 02728 02729 02730 if (objc != 4) 02731 { 02732 Tcl_WrongNumArgs(interp, 1, objv, "widget filename linenumbers"); 02733 return TCL_ERROR; 02734 } 02735 02736 widget = Tcl_GetStringFromObj (objv[1], NULL); 02737 if ( Tk_NameToWindow (interp, widget, Tk_MainWindow (interp)) == NULL) 02738 { 02739 return TCL_ERROR; 02740 } 02741 02742 if (!Tcl_GetCommandInfo (interp, widget, &text_cmd)) 02743 { 02744 gdbtk_set_result (interp, "Can't get widget command info"); 02745 return TCL_ERROR; 02746 } 02747 02748 file = Tcl_GetStringFromObj (objv[2], NULL); 02749 Tcl_GetBooleanFromObj (interp, objv[3], &linenumbers); 02750 02751 symtab = lookup_symtab (file); 02752 if (!symtab) 02753 { 02754 gdbtk_set_result (interp, "File not found in symtab"); 02755 return TCL_ERROR; 02756 } 02757 02758 file = symtab_to_filename ( symtab ); 02759 if ((fp = fopen ( file, "r" )) == NULL) 02760 { 02761 gdbtk_set_result (interp, "Can't open file for reading"); 02762 return TCL_ERROR; 02763 } 02764 02765 if (stat (file, &st) < 0) 02766 { 02767 catch_errors (perror_with_name_wrapper, "gdbtk: get time stamp", "", 02768 RETURN_MASK_ALL); 02769 return TCL_ERROR; 02770 } 02771 02772 if (symtab && symtab->objfile && symtab->objfile->obfd) 02773 mtime = bfd_get_mtime(symtab->objfile->obfd); 02774 else if (exec_bfd) 02775 mtime = bfd_get_mtime(exec_bfd); 02776 02777 if (mtime && mtime < st.st_mtime) 02778 { 02779 gdbtk_ignorable_warning("file_times",\ 02780 "Source file is more recent than executable.\n"); 02781 } 02782 02783 02784 /* Source linenumbers don't appear to be in order, and a sort is */ 02785 /* too slow so the fastest solution is just to allocate a huge */ 02786 /* array and set the array entry for each linenumber */ 02787 02788 ltable_size = LTABLE_SIZE; 02789 ltable = (char *)malloc (LTABLE_SIZE); 02790 if (ltable == NULL) 02791 { 02792 fclose (fp); 02793 gdbtk_set_result (interp, "Out of memory."); 02794 return TCL_ERROR; 02795 } 02796 02797 memset (ltable, 0, LTABLE_SIZE); 02798 02799 if (symtab->linetable && symtab->linetable->nitems) 02800 { 02801 le = symtab->linetable->item; 02802 for (ln = symtab->linetable->nitems ;ln > 0; ln--, le++) 02803 { 02804 lnum = le->line >> 3; 02805 if (lnum >= ltable_size) 02806 { 02807 char *new_ltable; 02808 new_ltable = (char *)realloc (ltable, ltable_size*2); 02809 memset (new_ltable + ltable_size, 0, ltable_size); 02810 ltable_size *= 2; 02811 if (new_ltable == NULL) 02812 { 02813 free (ltable); 02814 fclose (fp); 02815 gdbtk_set_result (interp, "Out of memory."); 02816 return TCL_ERROR; 02817 } 02818 ltable = new_ltable; 02819 } 02820 ltable[lnum] |= 1 << (le->line % 8); 02821 } 02822 } 02823 02824 ln = 1; 02825 02826 line[0] = '\t'; 02827 text_argv[0] = widget; 02828 text_argv[1] = "insert"; 02829 text_argv[2] = "end"; 02830 text_argv[5] = line; 02831 text_argv[6] = "source_tag"; 02832 text_argv[8] = NULL; 02833 02834 if (linenumbers) 02835 { 02836 int found_carriage_return = 1; 02837 02838 line_num_buf[1] = '\t'; 02839 02840 text_argv[3] = line_num_buf; 02841 02842 while (fgets (line + 1, 9980, fp)) 02843 { 02844 /* Look for DOS style \r\n endings, and if found, 02845 * strip off the \r. We assume (for the sake of 02846 * speed) that ALL lines in the file have DOS endings, 02847 * or none do. 02848 */ 02849 02850 if (found_carriage_return) 02851 { 02852 char *p = strrchr(line, '\0') - 2; 02853 if (*p == '\r') 02854 { 02855 *p = '\n'; 02856 *(p + 1) = '\0'; 02857 } 02858 else 02859 found_carriage_return = 0; 02860 } 02861 02862 sprintf (line_num_buf+2, "%d", ln); 02863 if (ltable[ln >> 3] & (1 << (ln % 8))) 02864 { 02865 line_num_buf[0] = '-'; 02866 text_argv[4] = "break_rgn_tag"; 02867 } 02868 else 02869 { 02870 line_num_buf[0] = ' '; 02871 text_argv[4] = ""; 02872 } 02873 02874 text_cmd.proc(text_cmd.clientData, interp, 7, text_argv); 02875 ln++; 02876 } 02877 } 02878 else 02879 { 02880 int found_carriage_return = 1; 02881 02882 while (fgets (line + 1, 9980, fp)) 02883 { 02884 if (found_carriage_return) 02885 { 02886 char *p = strrchr(line, '\0') - 2; 02887 if (*p == '\r') 02888 { 02889 *p = '\n'; 02890 *(p + 1) = '\0'; 02891 } 02892 else 02893 found_carriage_return = 0; 02894 } 02895 02896 if (ltable[ln >> 3] & (1 << (ln % 8))) 02897 { 02898 text_argv[3] = "- "; 02899 text_argv[4] = "break_rgn_tag"; 02900 } 02901 else 02902 { 02903 text_argv[3] = " "; 02904 text_argv[4] = ""; 02905 } 02906 02907 text_cmd.proc(text_cmd.clientData, interp, 7, text_argv); 02908 ln++; 02909 } 02910 } 02911 02912 free (ltable); 02913 fclose (fp); 02914 return TCL_OK; 02915 } 02916 02917 /* 02918 * This section contains a bunch of miscellaneous utility commands 02919 */ 02920 02921 /* This implements the tcl command gdb_path_conv 02922 02923 * On Windows, it canonicalizes the pathname, 02924 * On Unix, it is a no op. 02925 * 02926 * Arguments: 02927 * path 02928 * Tcl Result: 02929 * The canonicalized path. 02930 */ 02931 02932 static int 02933 gdb_path_conv (ClientData clientData, Tcl_Interp *interp, 02934 int objc, Tcl_Obj *CONST objv[]) 02935 { 02936 if (objc != 2) 02937 { 02938 Tcl_WrongNumArgs (interp, 1, objv, NULL); 02939 return TCL_ERROR; 02940 } 02941 02942 #ifdef __CYGWIN__ 02943 { 02944 char pathname[256], *ptr; 02945 02946 cygwin_conv_path (CCP_POSIX_TO_WIN_A, Tcl_GetStringFromObj (objv[1], NULL), 02947 pathname, 256); 02948 for (ptr = pathname; *ptr; ptr++) 02949 { 02950 if (*ptr == '\\') 02951 *ptr = '/'; 02952 } 02953 Tcl_SetStringObj (result_ptr->obj_ptr, pathname, -1); 02954 } 02955 #else 02956 Tcl_SetStringObj (result_ptr->obj_ptr, Tcl_GetStringFromObj (objv[1], NULL), 02957 -1); 02958 #endif 02959 02960 return TCL_OK; 02961 } 02962 02963 /* 02964 * This section has utility routines that are not Tcl commands. 02965 */ 02966 02967 static int 02968 perror_with_name_wrapper (PTR args) 02969 { 02970 perror_with_name (args); 02971 return 1; 02972 } 02973 02974 /* Look for the function that contains PC and return the source 02975 (demangled) name for this function. 02976 02977 If no symbol is found, it returns an empty string. In either 02978 case, memory is owned by gdb. Do not attempt to free it. */ 02979 const char * 02980 pc_function_name (CORE_ADDR pc) 02981 { 02982 struct symbol *sym; 02983 const char *funcname = NULL; 02984 02985 /* First lookup the address in the symbol table... */ 02986 sym = find_pc_function (pc); 02987 if (sym != NULL) 02988 funcname = GDBTK_SYMBOL_SOURCE_NAME (sym); 02989 else 02990 { 02991 /* ... if that fails, look it up in the minimal symbols. */ 02992 struct bound_minimal_symbol msym; 02993 02994 msym = lookup_minimal_symbol_by_pc (pc); 02995 if (msym.minsym != NULL) 02996 funcname = GDBTK_SYMBOL_SOURCE_NAME (msym.minsym); 02997 } 02998 02999 if (funcname == NULL) 03000 funcname = ""; 03001 03002 return funcname; 03003 } 03004 03005 void 03006 gdbtk_set_result (Tcl_Interp *interp, const char *fmt,...) 03007 { 03008 va_list args; 03009 char *buf; 03010 03011 va_start (args, fmt); 03012 buf = xstrvprintf (fmt, args); 03013 va_end (args); 03014 Tcl_SetObjResult (interp, Tcl_NewStringObj (buf, -1)); 03015 xfree(buf); 03016 } 03017 03018 03019 /* This implements the tcl command 'gdb_incr_addr'. 03020 * It does address arithmetic and outputs a proper 03021 * hex string. This was originally implemented 03022 * when tcl did not support 64-bit values, but we keep 03023 * it because it saves us from having to call incr 03024 * followed by format to get the result in hex. 03025 * Also, it may be true in the future that CORE_ADDRs 03026 * will have their own ALU to deal properly with 03027 * architecture-specific address arithmetic. 03028 * 03029 * Tcl Arguments: 03030 * addr - CORE_ADDR 03031 * number - optional number to add to the address 03032 * default is 1. 03033 * 03034 * Tcl Result: 03035 * hex string containing the result of addr + number 03036 */ 03037 03038 static int 03039 gdb_incr_addr (ClientData clientData, Tcl_Interp *interp, 03040 int objc, Tcl_Obj *CONST objv[]) 03041 { 03042 CORE_ADDR address; 03043 int number = 1; 03044 03045 if (objc != 2 && objc != 3) 03046 { 03047 Tcl_WrongNumArgs (interp, 1, objv, "CORE_ADDR [number]"); 03048 return TCL_ERROR; 03049 } 03050 03051 address = string_to_core_addr (Tcl_GetStringFromObj (objv[1], NULL)); 03052 03053 if (objc == 3) 03054 { 03055 if (Tcl_GetIntFromObj (interp, objv[2], &number) != TCL_OK) 03056 return TCL_ERROR; 03057 } 03058 03059 address += number; 03060 03061 Tcl_SetStringObj (result_ptr->obj_ptr, (char *)core_addr_to_string (address), -1); 03062 03063 return TCL_OK; 03064 } 03065 03066 /* This implements the tcl command 'gdb_CAS_to_TAS'. 03067 * It takes a CORE_ADDR and outputs a string suitable 03068 * for displaying as the target address. 03069 * 03070 * Note that CORE_ADDRs are internal addresses which map 03071 * to target addresses in different ways depending on the 03072 * architecture. The target address string is a user-readable 03073 * string may be quite different than the CORE_ADDR. For example, 03074 * a CORE_ADDR of 0x02001234 might indicate a data address of 03075 * 0x1234 which this function might someday output as something 03076 * like "D:1234". 03077 * 03078 * Tcl Arguments: 03079 * address - CORE_ADDR 03080 * 03081 * Tcl Result: 03082 * string 03083 */ 03084 03085 static int 03086 gdb_CA_to_TAS (ClientData clientData, Tcl_Interp *interp, 03087 int objc, Tcl_Obj *CONST objv[]) 03088 { 03089 CORE_ADDR address; 03090 Tcl_WideInt wide_addr; 03091 03092 if (objc != 2) 03093 { 03094 Tcl_WrongNumArgs (interp, 1, objv, "CORE_ADDR"); 03095 return TCL_ERROR; 03096 } 03097 03098 /* Read address into a wideint, which is the largest tcl supports 03099 then convert to a CORE_ADDR */ 03100 if (Tcl_GetWideIntFromObj (interp, objv[1], &wide_addr) != TCL_OK) 03101 return TCL_ERROR; 03102 address = wide_addr; 03103 03104 /* This is not really correct. Using paddr_nz() will convert to hex and truncate 03105 to 32-bits when required but will otherwise not do what we really want. */ 03106 03107 Tcl_SetStringObj (result_ptr->obj_ptr, 03108 paddress (get_current_arch (), address), 03109 -1); 03110 03111 return TCL_OK; 03112 } 03113 03114 /* Another function that was removed in GDB and replaced 03115 * with something similar, but different enough to break 03116 * Insight. 03117 */ 03118 char * 03119 symtab_to_filename (struct symtab *s) 03120 { 03121 int r; 03122 03123 if (!s) 03124 return NULL; 03125 03126 /* Don't check s->fullname here, the file could have been 03127 deleted/moved/..., look for it again */ 03128 r = open_source_file (s); 03129 if (r) 03130 close (r); 03131 03132 if (s->fullname && *s->fullname) 03133 return s->fullname; 03134 return s->filename; 03135 }