README.GDBTK Written by Stu Grossman Updated 9/26/95 by Fred Fish for gdb 4.15 release Updated 4/18/97 by Martin Hunt This file describes how to build, install, use and hack on GDBtk, a TK based GUI for GDB, the GNU debugger. Introduction ============ GDBtk is a version of GDB that uses Tcl/Tk to implement a graphical user inter-face. It is a fully integrated GUI, not a separate front-end program. The interface consists of several seperate windows, which use standard elements like buttons, scrollbars, entry boxes and such to create a fairly easy to use interface. Each window has a distinct content and purpose, and can be enabled or disabled individually. The windows contain things like the current source file, a disassembly of the current function, text commands (for things that aren't accessible via a button), and so forth. Building and installing ======================= Building GDBtk is very straightforward. The main difference is that you will need to use the `--enable-gdbtk' option when you run configure in the top level directory. You will also need to install Tcl version 7.6 and Tk version 4.2. On Unix machines, you will also need to have X11 (R4/R5/R6) installed (this is a prerequisite to installing Tk). For Windows, you can obtain Tcl/Tk from ftp://ftp.smli.com:/pub/tcl/win76p2.exe. There is a bug in this version of Tcl/tk that requires you to set the environmental variable TK_LIBRARY to where the tk library directory is installed. There is also a problem with the colors in images on 16-bit displays under Windows, so some icons may look strange. [See the GDB README file for more details on configure options and such.] For example: host> cd gdbtk host> ./configure --enable-gdbtk host> make host> make install Using GDBtk =========== Just run it like you would a normal GDB (in fact, it's actually called `gdb'). If everything goes well, you should have several windows pop up. To get going, hit the start button, and go exploring. If you want to use GDB in command line mode, just use the -nw option. Or, you can undefine the DISPLAY environment variable. In the current version, you can have up to 6 windows active at once. They are: 1) Command 2) Source 3) Assembly 4) Register 5) Auto Command 6) Expression Most windows have a similar layout consisting of a menubar, display area, scrollbar, status box and window-specific buttons. The menubar contains the following items: File - General file control. Also has window close and quit buttons. Options - Window specific options. Window - A menu of other windows that can be popped up or created. Help - Mostly unimplemented. The status box indicates things like the current file and function, or the current PC and function depending upon the window. Command window: This can be used to type commands at GDB (useful for when there isn't a button for what you want to do). Source window: This contains the current source file. The margin displays line numbers, and has an indicator for lines that actually contain code (and therefore can have breakpoints as well). When a breakpoint is set at that line, the indicator is replaced with a stop sign icon. The buttons are: Start - Put a breakpoint at main, and then run. Stop - Stop the program (only active when program is running). Step, Next, Cont[inue], Finish, Up, Down - Same as the corresponding GDB command. (Finish runs the current subroutine until it's done.) Bottom - Does a `frame 0' to put you at the innermost call frame. There are also accelerators for various buttons (just type the letter without any control/meta/alt/shift in the text frame): s - Step n - Next c - Continue f - Finish u - Up d - Down The mouse can also be used to set and clear breakpoints when clicked in the margin (on a breakpoint indicator). Assembly window: This displays a disassembly of the current function. It's buttons are similar to those of the source window, except that it uses Stepi and Nexti to run one instruction at a time instead of one statement at a time. The accelerators and mouse actions are also similar. Additionally, there is an option to enable mixed source and assembly. Register window: This displays the registers. It may have to be resized to properly display all the registers. The displayed registers can be selected via the Options|Config menu item. Auto Command window: Using this window, you can specify a command to be executed frequently. The output will be automatically updated. Options|Accumulate-output can be used to avoid clearing the window each time so that you can accumulate a history. Expressions: The expression window can be used to just calculate an expression, or to watch the value of an expression (ala the `display' command), using the Update button. The expression window will also pop up automatically when an expression is double-clicked in the source window. Customizing GDBtk ================= There are three primary ways to customize GDBtk. One is to modifiy the appropriate X resources. The other is to hack a ~/.gdbtkinit file. The last is to change the files in gdbtcl, which defines the most basic interface elements. X resources give you control over things like the choice of fonts, color schemes and some geometry info. For more serious customizations, you will probably need to hack your ~/.gdbtkinit or gdbtcl files. X Resources =========== The class name for GDBtk is `Gdb', and it's appname is `gdb'. The top- level windows have instance names of `src', 'asm', 'reg', and 'cmd'. The main display area in each has the class `Text'. So, to change the font in all the main display areas, something like the following will do: Gdb*Text*font: fixed To change the font in only the source window: Gdb*src*Text*font: fixed To find out the names of the widgets do the following (in the command window): tk info comm .* To get the list of resources (and their classes) for a given widget, do some- thing like: tk .asm.text config This will return a list of lists, where each sublist looks something like this: {-height height Height 24 25} The first item is the name of the config option used when creating the widget. The second item is the instance name of this resource, the third is the class name. The fourth item is the default value, and the last item is the current value. To get info about a single resource, add the config option name to the end of the previous command. Ie: tk .asm.text config -font will return just the info about the font. To find out the class of a window, just do: tk winfo class .asm.text Note that some things may be explicitly overridden by gdbtk.tcl. In particular, the `tk colormodel . monochrome' command should probably be disabled if you want to use color. Hacking ~/.gdbtkinit and gdbtcl ================================== ~/.gdbtkinit is sourced at the end of gdbtk.tcl. Currently there is no good doc on this. See gdbtcl/main.tcl for see what you can change. The GUI is primarily implemented by Tcl/Tk code which lives in gdbtcl and a C file called gdbtk.c. The Tcl/Tk code determines the look and feel, the layout, and the functions associated with all of the interface elements. The C code is mostly just glue between GDB internals and Tclland. In essence, all of the policy is implemented in Tcl/Tk, and is easily changed without recompiling. To make more serious changes to the interface, such as adding a new window or changing the framework, you will have to hack the tcl code. This directory is installed in $(libdir) (probably /usr/local/lib/). But, you will probably want to hack on your own private copy before putting it up for the rest of the users. To find the GDB tcl code, GDB first checks for the environment variable GDBTK_LIBRARY. This can be a directory name or a list of directories seperated by colons (semicolons on Windows). GDB will check each directory in order until it finds "main.tcl". If GDBTK_LIBRARY is not set, GDB will look for "gdbtcl/main.tcl" in the current directory, and finally, it will try to find the tcl directory in the sources. Note that the old GDBTK_FILENAME environment variable is no longer used. Internally, GDBtk is basically GDB, linked with Tcl/Tk, and some glue code that interfaces GDB internals to Tclland. This means that GDBtk operates as a single program, not a front-end to GDB. All GDB commands, and a great deal of the target program state are accessible to the Tcl programmer. In addition, there are many callbacks from GDB to notify Tclland of important events. Here is a brief rundown of the GDB<=>Tcl interfaces: Tcl->GDB calls: gdb_cmd - sends a text command to gdb. Returns the result gdb_loc - takes PC, and returns a list consisting of a short file name, the function name, a long file name, the line number and the PC (in case you didn't supply it). gdb_sourcelines - Takes a filename, and returns a list of lines that contain code. gdb_listfiles - Returns a list of all of the source files. gdb_stop - Stops the target process. gdb_regnames - Returns a list of all of the register names. gdb_fetch_registers - Returns the contents of the specified registers. gdb_changed_register_list - Returns a list of registers that have changed since the last call. gdb_disassemble - Takes a function or PC. Returns the text of a dis- assembly of the entire function. gdb_eval - Takes an expression. Returns it's value. gdb_get_breakpoint_list - Does the obvious. gdb_get_breakpoint_info - Takes a breakpoint number. Returns a list of info about that breakpoint. GDB->Tcl callbacks: gdb_tcl_fputs - Sends output into Tcl for the command window. gdb_tcl_query - Pops up a query window. gdbtk_tcl_breakpoint - Notifies Tcl of changes to a breakpoint. gdbtk_tcl_idle - Notifies Tcl that debugged process is now idle. gdbtk_tcl_busy - Notifies Tcl that debugged process is now running. For details, see the usage in gdbtk.tcl, or the definitions in gdbtk.c. Additionally, there is a new GDB command `tk', which can be used to poke at Tk/Tcl from the command window. Problems ======== During building, you may run into problems with finding Tcl, Tk or X11. Look in gdb/Makefile, and fix TCL_CFLAGS, TCL, TK_CFLAGS, TK, and ENABLE_CLIBS as appropriate. If you one of the following messages when you run gdb: Tcl_Init failed: can't find init.tcl; perhaps you need to install Tcl or set your TCL_LIBRARY environment variable? or Tk_Init failed: can't find tk.tcl; perhaps you need to install Tk or set your TK_LIBRARY environment variable? then you haven't installed Tcl or TK properly. Fix the appropriate environment variable to point at the {tcl tk}/library directory, and restart gdb. If you get the following: /usr/local/lib/gdbtk.tcl:1: couldn't read file "/usr/local/lib/gdbtk.tcl": No such file or directory Stack trace: can't unset "auto_index": no such variable while executing "unset auto_index" then GDBtk wasn't installed properly. You can set the GDBTK_FILENAME environment variable to point at the gdbtk.tcl in your source directory. Note that the stack trace displayed here is not valid. If you actually get an error in gdbtk.tcl, the stack trace is useful to pinpoint the location. Known Bugs ========== generic problems o If you open an Assembly window before you have run the program, gdbtk pops up a dialog box titled "Error in Tcl Script" with the contents "Error: No function contains the specified address". Trying to then do other things brings up a dialog box with the contents "Error: can't read 'current_asm_label': no such variable. Solution: Close Assembly window when there is no program running. o If you open Registers window before you have run the program, gdbtk pops up a dialog box titled "Error in Tcl Script" with the contents "Error: No registers". Trying to then do other things, like use the Start button to run the program, repeatedly produce the same dialog box and the action is not performed. Solution: Close Registers window when there is no program running. o Expressions are sometimes not displayed correctly in the Expression window. I.E. "argc" works, as does "*(argv+argc)" but not "argv[argc]". Solution: None [ I believe this problem is fixed, but I have not tested it ] o The Breakpoint window does not get automatically updated and changes made in the window are not reflected back in the results from "info br". I.E. the breakpoint count in the window is not updated at each hit and enabling/disabling the breakpoint from the Breakpoint window has no effect. Solution: Use the command interface to control breakpoints and don't open a Breakpoint window. o Sometimes while an expression window is active you get a dialog box that complains "Error: invalide command name ".expr.e5.expr" for example. The Tcl stack trace looks something like: invalid command name ".expr.e5.expr" while executing "$e.expr get 0.0 end" invoked from within "set expr [$e.expr get 0.0 end]..." (procedure "update_expr" line 17) invoked from within "update_expr $expr_num" invoked from within "if $expr_update_list($expr_num) { update_expr $expr_num . . . Solution: None except close expression window and reopen it. o If you select the "Down" button in either the Source or Assembly window while in the bottom (innermost) frame, the error message that results goes just to the command window and may be missed if the command window is not open. This may also apply to other messages as well. It should probably put up a notification box instead. Solution: Keep Command window open to see error messages. o Not really a problem, but it would be nice to have a backtrace window. Solution: Do bt in command window? o Also not really a problem, but it might be nice to have a frame/stack window that displays the last N words on the stack, along with indications about which function owns a particular frame, how the frame pointers are chained, and possibly the names of variables alongside their frame slots. m68k-hp-hpux9.00: o Attempting to use a Register window results in a Tcl Script Error "Error: Erroneous arithmetic operation". The Tcl stack trace is: while executing "gdb_fetch_registers $reg_format $regnum" invoked from within "set regval [gdb_fetch_registers $reg_format $regnum]..." ("foreach" body line 2) invoked from within "foreach regnum $reg_display_list { set regval [gdb_fetch_registers $reg_format $regnum] set regval [format "%-*s" $valwidth $regval] $win del ..." invoked from within "if {$which == "all"} { set lineindex 1 foreach regnum $reg_display_list { set regval [gdb_fetch_registers $reg_format $regnum] set regval [f ..." (procedure "update_registers" line 16) invoked from within "update_registers all" . . .