ups - X11 and SunView based source level C debugger |
Version 3.37 |
CONTENTS |
Contents
Synopsis
Description
Getting Started
UPS Command Line Arguments
Environment Variables Affecting UPS
Interactively Adding Search Paths
Layout of the UPS window
The Display Area
The Source Region
File Name Box
Editable Fields
Edit History
Cut and Paste
Editing in the Output Window
Listing Matching Symbols For Breakpoints
Examining The Target´s State
Examining Variable Values
Examining Macro Values
Accelerators in the Display Area
Source Files Menu
Breakpoint Menus
Special handling for SIGSEGV and SIGBUS
Controlling Target Execution
The Typing Line Menus
Target Command Line
Target Command Line Arguments
Controlling The Display Of Variables
Changing Variable Values
Expressions in the Display Area
Examining Base Classes and Vector Tables
Examining Static Members of Classes
Pasting Expressions from the Source Window
Adding Interpreted Code
Examining Linked Data Structures
Displaying Memory
Environment Variables
Signals
Typing Line Shortcuts
X and SunView Command Line Flags
X Resources
Debugging FORTRAN Code
Support for C++
Initialization File
Multiple Linked Files
Saving State
Loading And Saving Breakpoints
See Also
Bugs
Acknowledgements
Authors
Enhancement Authors
SYNOPSIS |
ups target [ corefile | pid ] [ [:]srcdir[:srcdir ] ] [ -a target-args ]
DESCRIPTION |
Ups is a X based source level debugger for the C, C++ and Fortran programming languages. It supports both run time debugging with breakpoints and postmortem debugging from a core file. On Suns you can attach ups to a running process. Ups runs in its own window, thus not interfering with the target program´s I/O. The ups window has two major areas one showing a structured document representing the target state, the other showing the source that is being executed.
Ups makes heavy use of direct manipulation and feedback. When you add a breakpoint it is shown as a pseudo C statement (#stop) in the source display. The current point of execution is highlighted in the source display and you can watch it move as you step through loops and function calls. You can edit in fragments of interpreted C code (including assignments to variables and calls to target functions). There are powerful facilities for exploring linked data structures you can recursively expand and collapse structures to follow links.
Ups is primarily a C debugger, but it also has support for debugging Fortran 77 and Fortran 90 code. See the section DEBUGGING FORTRAN CODE for information on Fortran specific features.
Ups has reasonable support of C++. See the section SUPPORT FOR C++ for information on on this.
The URL for the ups web site is
http://ups.sourceforge.net/It is maintained by Ian Edwards (ian@concerto.demon.co.uk). It includes a FAQ, html man pages, site listings where ups can be found, supported architectures, a history of changes between versions and other information.
GETTING STARTED |
This is covered in the document Getting started with UPS.
UPS COMMAND LINE ARGUMENTS |
This section gives a complete description of the command line arguments accepted by ups. The command line syntax is :
ups target [corefile|pid] [[:]srcdir[:srcdir]] [-a target-args] [-nodemangle] [-nosavesigs] [-split[:screen]] [-fullpath] [-install]Ups accepts various other flags, but these are mostly to support maintenance and testing, and are not of interest to the general user. You can see a full list of the ups flags by giving the command ups -fullusage.
The only mandatory argument is the name of the executable file containing the program to be debugged (the target).
If a corefile argument is given it is taken to be the name of a core image dumped from target. If no corefile argument is given and there is a core image file called core in the directory of the target then that is taken as the core file. Old core files, and core files which weren´t dumped from the target, are silently ignored unless you give the name of the core file explicitly (in which case ups will use it, but give a warning message).
If the corefile argument consists solely of digits, it is taken to be the process id of the target. This allows you to attach ups to an already running process on machines with the necessary support (currently only Suns). If you subsequently quit ups while still attached in this way, it detaches from the target, allowing the target to continue.
By default ups looks for source files in the directory of the target. You can specify alternative source directories by giving a list of directories separated by : characters. An empty initial path (i.e. a leading :) means the directory of the target. On Suns running SunOS 4, the C compiler includes directory paths for source files, so ups will normally find source files in other directories even without the source path argument.
You can specify the arguments that the target should be invoked with by giving the -a option, followed by a single argument. You can give multiple arguments for the target by enclosing the list of arguments in single or double quotes. Ups will itself interpret metacharacters like * and > - see TARGET COMMAND LINE ARGUMENTS.
When the -nodemangle argument is specified, ups will do no demangling on function or variable names. This should result is slightly faster invocation time for pure C code. It is still possible to debug C++ code in this mode, although the names need some mental deciphering. A unique feature of this version of ups, is that even when C++ names are shown mangled, you can generally still click on variables in the source window, and ups will still find the name to display, albeit in a mangled state.
If you are saving state between debugging sessions by creating a ups-state directory, the command option, -nosavesigs stops ups from saving signal state to the ups state file.
By default, ups passes only the final component of the target filename to the process as argv[0]. Sometimes, the process needs the full path to itself, for example, to locate auxiliary files. If the -fullpath argument is specified, this default behaviour is suppressed and the target filename is passed directly from the ups command line to the process command line.
ENVIRONMENT VARIABLES AFFECTING UPS |
You can see all the symbol table names that are loaded and not loaded by setting VERBOSE to 1, e.g. if you use csh(1) by doing setenv VERBOSE 1 before calling ups. Setting VERBOSE to NOLOAD causes ups to list just the libraries that are not loaded.
The variable EDITOR is used, if set, as the editor for source files. If not set the default is vi(1). Unless the editor is emacs(1), or the name starts with an "x", it will be started in a new xterm(1) window.
You can change the source code language and compiler type that ups
assumes have been used by setting UPS_LANGUAGE or UPS_COMPILER as appropriate.
Note that these settings will be used for all files.
These might be useful if you use non-standard file extensions, or have
compiled C with a C++ compiler.
UPS_LANGUAGE can be C, C++, F77 or F90.
UPS_COMPILER can be
cc Sun C/C++ compilerOn Sun SPARC systems UPS_SUNOS_STEP controls whether Step will take you into a routine if it is in a shared library. If not set, or set to 1, you can step into shared libraries. If set to 0 then Step will continue to the next statement in the current routine.
gcc GNU gcc/g++/g77
clcc Centerline C++
f77 Sun Fortran
f90 EPCF90
Most software projects of any size develop formal or informal naming conventions that make it possible to specify the desired format for a variable based on the name and, possibly, the type, regardless of the context in which it appears. If, like most software engineers, you spend much of your time debugging the same code, you can set up a UPS_FORMATS string in your environment to specify the desired formats for frequently examined variables.
The following is an example of a UPS_FORMATS string :
export UPS_FORMATS=" \ unsigned : UHEX; /* Default unsigned to hex */ \ unsigned *any_int[NTLW] : UDML; \ char abyte: OCT; \ *bits* : UBIN; \ auto "
The first line of this format string causes ups to format unsigned variables in hex rather than decimal. The format string accepts C-style comments to allow for more readable .login or .cshrc files.
The second line specifies that any unsigned variable whose name matches the string *any_int[NTLW] is an exception and should be formatted in decimal. Pattern matching is as in shells such as sh, csh, or bash.
It is important that the exception come after the general rule specified in the first line.
Note that in the UPS_FORMATS string, char *foo means any variable of type char whose name ends in foo, not a variable named foo of type char*.
The third line specifies that any variable of type char and name abyte should be formatted in octal.
The forth line specifies that any variable of any basic type with the string bits in its name should be formatted in binary.
The last line specifies that any time the you change a format ups should automatically save the change and use it as the default format for any variable of the same name and type.
The syntax of the UPS_FORMATS string is :
format_string | ::= | format_spec [ ; format_string] [;] |
format_spec | ::= | format_request | auto_save_request |
format_request | ::= | [ unsigned ] [ type ] [ pattern ] : [ format ] |
type | ::= | char | short | int | long |
pattern | ::= | any C identifier with wild cards *, ? or [] |
format | ::= | UHEX | UOCT | UDML | UBIN | HEX | OCT | DML | ASCII | STRING |
auto_save_request | ::= | auto |
In the format request, if the type is omitted then either all unsigned basic types or all basic types regardless of sign are selected. If the pattern is omitted the default pattern is * so that all variables of the specified type are selected.
It is possible to insert pre-defined strings when editing text. This applies to all editing : in the typing line, in the display area, in breakpoint code and in the output window. The right mouse button invokes a menu of strings defined by environment variables of name UPS_F*_STR where * is a number from 1 through 12. When the cursor is over the typing line or output window, the mousehole shows "(menu)" for the right button as an indication that a custom menu may be available.
The UPS_F*_STR strings accept control, meta, and escape characters as follows :
\n, \r, or \e | Enter an escape character to terminate the edit |
^A, ^B, etc. | Enter the corresponding control character |
@f, @b, etc. | Enter the corresponding meta character. This allows movement by words |
\\ or \^ or \@ | Override the special meaning of \ or ^ |
As an example, it is often nice to have skeleton strings for printf() or cout statements in breakpoint code, or a directive for expanding linked lists for the typing line, or a string for setting breakpoints on cout statements in C++ code. Yet another string can be used to call strcmp() for a conditional breakpoint. The F6 string pastes in the X-windows selection and the F7 string sets a breakpoint in purified code.
To do this, if you use csh(1), put the following in your environment :
If your shell is sh(1) or bash(1) then use :setenv UPS_F1_STR ´$printf("\\n");´ setenv UPS_F2_STR ´if (strcmp(, ""))´ setenv UPS_F3_STR ´@name .next´ setenv UPS_F4_STR "ostream::operator<<" setenv UPS_F5_STR ´ostream::operator<<(&cout, "");´ setenv UPS_F6_STR "^e^u^y\n" setenv UPS_F7_STR "%b purify_stop_here\n"
export UPS_F1_STR=´$printf("\\n");´
etc.
INTERACTIVELY ADDING SEARCH PATHS |
Search paths can be given to ups at any time during debug by selecting the Source Files header in the display window and pressing Add source path. The typing line will prompt for input. It will display the last entry in the search path list as a default, if a list exists. Multiple paths may be entered at once by entering a colon separated list. This is the same syntax as the ups command line arguments. This enables the paths for source files to be found without the need to back out of the debugger and add the search path to the command line. Note that this will work only if the file is already an entry in the source file list, but cannot be listed. When this condition occurs, pressing the path caption will display the assumed path for the file, which must be in error. The program may have to be statically linked to find all source file names.
LAYOUT OF THE UPS WINDOW |
The ups window is divided into a number of rectangular regions. This section gives a brief description of each region.
THE DISPLAY AREA |
The display area is the large region in the upper half of the ups window. Its main use is to show the state of the program when it stopped, though it is also used for other control functions.
There are a number of captions in the display area, like Signals, Breakpoints etc. These are known as objects. To select an object, press and release the left mouse button over it.
Any objects that were previously selected are deselected, the object is inverted to show that it is selected, and a menu of commands applicable to that object appears in the second of the three slots at the top of the window. At any time this region of the display either contains a menu corresponding to a selected object, or is empty (painted a uniform grey) if there are no objects selected.
A command selected from the menu (by pressing and releasing the left mouse button over the caption) is applied to the currently selected objects. It is possible to apply a command to a group of objects. To do this, select a group of objects by pressing the left mouse button over the first object and then dragging the mouse over the other objects you wish to select before releasing the button. You cannot select objects of different types simultaneously as each different type of object has its own menu. Once the first object has been selected, only objects of the same type will be selected (and highlighted) as the cursor passes over them.
The right hand mouse button is used to toggle whether an object is selected - clicking it over a selected object deselects that object, and clicking over an object that isn´t selected adds that object to the selection. As with the left mouse button, you can drag the mouse with the right button down to toggle a group of objects.
Several of the menu commands add new objects to the display. For example, when you expand an entry in the stack trace all the local variables for the function it represents are added to the display (see EXAMINING VARIABLE VALUES below). These new objects can be selected in the same way as the existing ones, and have an associated menu of commands.
Once a few objects have been added to the display area, there is usually not enough room to display all of them at once. There is a scroll bar to the left of the display area which lets you scroll the display area up and down. To scroll, press and hold down the left mouse button whilst within the scroll bar, and move the mouse in the direction you wish the display to move. The further you move the mouse, the faster the scrolling.
You can also use the left and right mouse buttons to page up and down through the display in the same way as with the xterm(1) scroll bar. Clicking the left mouse button in the scroll bar pages the display down. Similarly, clicking the right button pages the display up. The distance paged depends on how far the cursor is from the top of the scroll bar.
The black blob in the scroll bar represents the proportion of the entire display that is currently visible, and the position of this visible part within the whole display. For example, if the black blob is one third the height of the scroll bar, and in the middle, it means that the total height of the objects is about three times the height of the display area, and the middle third is currently being displayed.
You can use the scroll bar to go directly to a given point in the display. Press and release the middle mouse button at a point in the scroll bar. The black blob is moved so that it centres around the point, and the display is moved correspondingly.
THE SOURCE REGION |
The source region is used to display the source line that the target is currently stopped at, or more precisely the line that is about to be executed. Like the display area, the source region has a scroll bar to the left of it, which behaves in the same way as the display area scroll bar.
Above and to the left of the source region is a box where the name of the current source file and the current line number is displayed. See the FILE NAME BOX section for details of the right button menu for this region.
To the right of this is the source region menu with commands Back, Search, Up and Down.
The Up and Down commands step up and down through the target program´s call stack. If you are looking at the source code of the currently executing function, Up switches the display to show the source of the function that called it. Repeatedly clicking on Up will take you all the way up the stack to main (or MAIN for Fortran programs). Similarly, Down steps one level down in the call stack.
When ups has been attached to a target, it is possible to detach without quitting the debugger by pressing the Detach caption at the bottom of the display window. At a later time, ups can then be attached to the same instance of the target, or to a new instance of the target by using the attach caption described below.
On an attach, the debugger will reload any shared libraries that have changed, as well as any new shared libraries that the target uses. If ups has been detached from the target as described above, or if the target terminates for any reason, it is possible to attach to the same or a new invocation of the target without quitting the debugger. The advantage of this is that it may take several minutes for ups to initially come up, but once the symbol tables have been read, the time to reattach will be at most, of the order of tens of seconds, and often just a few seconds. All breakpoints and even breakpoint code will still work. After pressing Attach you will be prompted to enter the PID number. The PID of the last attached process is displayed as a default. If the new invocation of the target has changed, the reattached session may not work correctly if statically linked object files have changed. ups will re-read any changed shared libraries when attaching.
A very handy use of the Attach item is for debugging spawned processes that can timeout unless a communications handshake or license check is performed quickly. If the spawned process is stopped at a pause while ups is invoked from scratch, the process may well timeout and exit before ups can read all the necessary symbol information. The solution is to first invoke ups on the target without a PID in the command line. After the symbols have been read, breakpoints can be set, then the real process to be debugged is spawned. Then press Attach and quickly enter the PID of the spawned process to debug.
Shared libraries are reloaded if they change between attach/detach cycles. So one can attach to a target, debug, detach and then rebuild a shared library that the target uses. Then after the target is rerun with the new library, ups can be attached again and the new library will be re-scanned and debugging can continue without quitting ups, and without the overhead of re-reading symbols for the other libraries. Breakpoints in the new library will need to be reset. Ups puts out a message about what libraries are being reloaded in such cases.
The Search command is used to search for regular expressions (using the same syntax as grep(1) patterns) in the currently displayed source file. First type in the pattern to be searched for (typed characters appear in the typing line at the top of the window on the left) then press and hold down the left mouse button over the Search caption. A popup menu appears with the options Backwards and Forwards. Move the mouse over the one you want and release the button. If the pattern is found, the matching text is made visible in the source region and highlighted.
You can click the left mouse button on any variable or function name in the source window to display it. Double clicks will alternately expand and compress the variable. Variables are added to the display area, as described in EXAMINING VARIABLE VALUES below. If you click on a function name, the source for that function is displayed (this is similar to the tags facility in emacs or vi). Ups maintains a stack of where you have been. After you have clicked on a function name you can use the Back command in the source menu to return to where you were. With a left click, ups reads the function symbols before navigating to the function. You can bypass the symbol reading by using the middle mouse button. So an unmodified left click looks up local symbols, then globals, a Shift-left click does an automatic add expr and a middle click edits breakpoint code, but if not over breakpoint code it looks up global symbol lookup only.
You can also get a function displayed by typing the name into the typing line at the top of the ups window. You do not need to type the whole name - just enough characters to uniquely identify the function. As for typing in a breakpoint, pressing ESC does partial name completion, and Shift-ESC, or Shift-RETURN will list the matching names in the output window. If a function appears by the same name in more than one source file, you can use the syntax filename:funcname to specify which function you want. Ups will also understand shell-style globbing with *(e.g. *foo_func*) for function and global variable names, with the restriction that the pattern must match only a single name.
Whenever the source region switches to a new source file, ups checks the last modified time of the source file against the last modified time of the target object file. If the source file is newer than the target you get a warning message and the source code is displayed with foreground and background colours reversed as a reminder that this source code might not correspond the object file you are debugging. See the section FILE NAME BOX below this for getting actual file dates.
You can select arbitrary text in the source window by dragging the mouse over it with the left button pressed. The selected text is highlighted, and can be pasted into other windows, or other areas in the ups window (such as the typing line). Note that dragging (press mouse button, move mouse, release) has a different effect than clicking (pressing and releasing the left mouse button without moving the mouse).
FILE NAME BOX |
There is a menu associated with this file name box above the source, and the mousehole and cursor also indicate that the right mouse button invokes a menu over the region The menu has options to edit the source, show used and assumed file paths, rematch and reload the file, and to show file dates. The latter is useful for an explanation of why ups may be showing reverse video for a file. In the bottom output window, it list the source file date, the associated shared library date if applicable, and the target file date. The menu is a convenient way to get information about a file without having to find the file in the source file list. For breakpoints, when the source is displayed, the menu provides a quick way to get at full file names and dates.
EDITABLE FIELDS |
All editable fields in ups work in the same way. To start editing you click the middle mouse button over the editable text. A black marker bar appears - characters that you type appear to the left of this marker bar. You can reposition the marker bar by clicking in the new position with the middle mouse button, or by using one of the cursor movement key sequences described below.
Clicking the left or right button confirms the edit. Clicking the middle mouse button outside the editable text area also confirms the edit. In both cases the mouse click is then interpreted as normal - this means that to confirm an edit you can simply move on to another activity. The final way to confirm an edit is to type ESC (the escape key) or click the left mouse button on the Enter Button (the small region to the right of the typing line with the << image).
To paste the current window system cut buffer, use Control-Y or click the middle mouse button on the Enter Button.
When you try to confirm an edit ups checks that the new field value is reasonable. If not you get an error message and you are left in the edit. An immediate second attempt to quit abandons the edit and restores the original field value.
Ups recognises a subset of the GNU emacs(1) key bindings when editing fields. In the current version there is no way to customise these key bindings. This will be fixed in a future release.
You can use most of the common emacs(1) key mappings when editing text (e.g. in the typing line, when adding breakpoints etc.). Here is a list of the supported mappings (C-x means Control-X, M-x means ALT-X, UP, DOWN, LEFT and RIGHT are the arrow keys, SPC is the space bar and DEL is the delete key) :
C-a | Move to start of line |
C-e | Move to end of line |
M-m | Move to first non-whitespace character |
M-@, M-SPC | Set mark |
C-w | Delete text between mark and point |
C-p, UP | Move up a line, if possible, otherwise retrieve the next previous item in the history buffer |
C-n, DOWN | Move down a line, if possible, otherwise retrieve the next later item in the history buffer |
C-b, LEFT | Move backwards one character |
C-f, RIGHT | Move forward one character |
M-b | Move backwards one word |
M-f | Move forward one word |
C-j, C-m | In an editable field, finish the edit. In the source window, start a new line. |
ESC | Finish edit, in both editable fields and the source window. |
C-c | Cancel edit (not an emacs binding). |
C-k | Delete to end of line |
C-u | Delete to start of line (not an emacsbinding ) |
C-d | Delete character under cursor |
M-d | Delete word starting at cursor |
DEL | Delete character before cursor |
M-DEL | Delete word before cursor |
C-y | Paste X selection |
M-> | Move to end of buffer |
M-< | Move to start of buffer |
If you run ups from a terminal (or a terminal emulator like xterm) it tries to discover what keys you are using for delete and line erase. If this fails it takes both ^H (backspace) and DEL to mean delete, and ^U to mean line erase.
EDIT HISTORY |
Most of the editable fields in ups have their own history of recently typed commands. For example there is a history of typing line commands, a history of breakpoint code entered, and a history of variable values changed.
Pressing the Left mouse button on the History Button, the small region to the right of the typing line with the triangular image, pops up a menu of recently entered data for that field.
When editing most single line fields, a Control-P, or up arrow moves the history pointer back one entry and replaces the current text with the previous entry. Typing a Control-N, or down arrow, moves the history pointer forward one entry.
Edit histories are saved between sessions of ups in ups-state/editHistory, if you use the ups-state feature, or in the file ~/.upsEditHistory if not.
CUT AND PASTE |
You can select text with highlighting by pressing the left mouse button and dragging. Releasing the left mouse button sets the X selection.
You can paste text into an edit with Control-Y or by clicking the middle mouse button on the Enter Button (the small region to the right of the typing line with the << image).
Another useful trick is to define paste strings by using control characters in a custom menu: e.g. define
then the right mouse button will invoke a menu: the first item clears the current text no matter where the text cursor is, and does a paste; the second just does a paste at the current location. See the section ENVIRONMENT VARIABLES AFFECTING UPS for details on custom menus.setenv UPS_F1_STR "^e^u^y" setenv UPS_F2_STR "^y"
In the source window there are some extra shortcuts :
In the display window, the left button selects objects for operations, and one can pan vertically to select groups of objects. Selecting objects for some operation is distinct from making an X text selection. However, while the button is down, if the horizontal distance from the original click exceeds a certain value, the window shifts from selecting objects to making an text selection. So one can easily just pan right to select a string for instance. The pixel value is 30 by defaults, but can be overridden with an X resource. See X RESOURCES for details.
EDITING IN THE OUTPUT WINDOW |
You can edit in the output window (the window where $printf output goes. Click with the middle mouse button to display a cursor. You can then append or delete text. This is useful for tidying up output to make it clearer, or for deleting uninteresting stuff.
You can also dump objects (like the stack trace) to the output window (the Window menu item to the left of Quit), and save or restore the output window contents from/to files (Load and Save in the output window menu).
LISTING MATCHING SYMBOLS FOR BREAKPOINTS |
Pressing Shift-ESC, or Shift-RETURN when setting a breakpoint lists matching functions in the output window. So * matches all function names, and file.c:* matches all function names for file.c. ESC states how many matching functions there are, while holding the shift key down lists them in the output window. To list all functions in a program (and there may be many thousands) enter * then Shift-ESC.
The full path names of source files are given when listing symbols.
Stripped libraries contain no symbol information or file names, so it is not possible to use the file_name:function_name syntax to specify a unique breakpoint via the Breakpoint header. For such cases, ups accepts a shared library name in conjunction with the function name. The syntax is
shared_lib_name:function_nameThis allows breakpoints to be set in specific shared libraries when there are name conflicts. The width of the breakpoint text has been doubled to allow for longer breakpoint specifications.
EXAMINING THE TARGET´S STATE |
When the target is stopped at a breakpoint or when ups has been started with a core file, the target´s state is show in the form of a stack trace in the display area. This consists of a line for each active function giving the name of the function, the source line number of the line that was being executed, and the name of the source file containing the function.
The stack trace appears under the Functions object in the display area. As an example, consider the following stack trace:
Functions main main.c:42 docmd commands.c:84 getline io.c:21
In this example, execution in function main() reached line 42, at which point main() called docmd(). In turn, docmd() at line 84 called getline(), which is stopped at line 21 (which is yet to be executed).
When the target stops, the source of the innermost function is displayed, with the line that is just about to be executed highlighted (displayed in reverse video). To look at the source of other functions in the stack trace :
If the initialization file has been used to load only certain libraries, unloaded libraries will be indicated by the sytax <full library name> in the stack trace. To load it, select the line and press Load library. As always for objects in the display window, multiple objects in the stack can be selected at once, and loaded as a group.
EXAMINING VARIABLE VALUES |
There are several ways to find the values of variables. The simplest and most often used is simply to click with the left mouse button on the name of a variable in the source region. A line is added to the display area which looks something like:
int <varname> 73
In this example, an integer variable called varname with a current value of 73 is shown. The meaning of the angle brackets around the name is explained later - ignore them for now.
If the variable is local to a function, it is added just below the line in the stack trace for that function. If the variable is global, an entry for the source file of the variable is added below the Source files object in the display area and the variable is displayed below that. In rare cases ups does not know the type of the variable, in which case it is assumed to be an integer and displayed under the Untyped variables object.
Once the variable is added to the display, it remains there until its function returns (for a local variable) or you explicitly delete it (see later for how to do this). This means that you can watch the value change as you control the execution of the target.
As well as selecting individual variables to be shown, you can add all the local variables of an active function to the display. Select the function in the stack trace whose variables you wish to see, and select Expand from the menu produced. This will produce a popup menu with the options Like before and Completely. The default option is Like before - it means to make the display look like it did last time you looked at the local variables for this function. If there is no last time, all the local variables are displayed. The second Expand option (Completely) always adds all the function´s local variables to the display.
To remove all the local variables select Collapse. You can subsequently put them back as they were using Expand, Like before. If you have saved state enabled, you can do this even after exiting ups and starting it again. See the SAVING STATE section for details.
When you use Expand to add all the local variables of a function, you may see some lines like this:
lines 84..93
These lines are added for variables declared within inner blocks of a function. In this example, there is an inner block starting at line 84 and ending at line 93 which contains local variable declarations (the line numbers are sometimes inaccurate because of bad information supplied by some compilers). If you click the left mouse button over one of these entries, a menu with the options Expand, Collapse, Add Expr Source, and Path, is produced. Selecting Expand adds to the display all variables declared in the block. Collapse removes them again, and Source makes the first line of the block visible in the source region. Selecting Path brings up a sub menu with Used, Assumed, Rematch, Reload and Dates items. The Used item shows what file is actually being displayed in the source window. The Assumed item displays the assumed path name of the selected file as suggested by the target binary. If the file could not be found under the Assumed name, the Used name will be the first good match in the source path list. For C code, there is normally no problem in finding the source and hence the Used and Assumed paths will be the same. For Centerline C++ code, the two are usually different. Ups uses symbol table function line number information to find the most likely match. This also allows different files of the same name to be located correctly.
This feature removes the need to constantly rearrange the Use paths in the ups init file to accommodate debugging different targets. Ups outputs a message for C++ files indicating what file was matched.
When no symbols are available for a function, both items print the library name for that function.
If for some reason the match process described above gets the wrong file, it is possible to find the next match in the search path list. To replace the file with the next match, select the Rematch item in the Path menu.
The Reload item will reload the currently selected file. A situation where this may be useful is, when in the middle of a debug session, it becomes apparent that the debugger is using version of a file that differs from the build version of the file. If the current version is newer than the object code, or the target, the file will appear in reverse video as a warning. To correct such a problem, restore the file, and reload. This will reload the text and also retest the file dates and remove the reverse video if appropriate.
The Dates item shows the full names and dates of the source file, shared library if used, and target binary.
See the later section CONTROLLING THE DISPLAY OF VARIABLES for information on (among other things) how to change the format of a displayed variable, indirect through pointers, expand structures and unions and step through the elements of an array.
EXAMINING MACRO VALUES |
It is also possible to examine the value of macros if that information has been included by the compiler. This can be done by clicking with the left mouse button on the name of a macro in the source region. A line is added to the display region which looks something like :
In this example, a macro called macroname with a value of 86 is shown. This line is actually an expression, as described in EXPRESSIONS IN THE DISPLAY AREA below.macroname 86
Because macros do not follow the normal language scoping rules, there is sometimes an ambiguity about what value to use for a macro. The rule used by ups is that the value of the macro on the first line of the function where you evaluate the macro is shown.
If you are using gcc(1) you need to use the -g3 command line option when compiling to include macro information.
ACCELERATORS IN THE DISPLAY AREA |
A Shift-left click or double left click does the most commonly used actions for the object listed below :
- env header
- Toggle between expanding and compressing the environment display.
- signal header
- Toggle between expanding and compressing the signal display.
- source header
- Toggle between expanding and compressing all source files. Files are expanded to like before state. If some files have variables or expressions displayed, such files will remain visible when the source file list is compressed. Use the menu item "completely" to remove all source files.
- source files
- Toggle between expanding and compressing all the global variables of the file
- file add expr
- See the actions under variable.
- function
- Toggle between expanding and compressing all the outermost local variables. Variables are expanded to like before state.
- function block
- Toggle between expanding and compressing all the local variables of the block
- func add expr
- See the actions under variable.
- variable
- If the variable is a struct or union, or pointer to a struct or union, toggle between expanding and compressing the current level of the variable. If the variable is a pointer to data of integer type, dereference the pointer one level. If the variable is of integer type, or fully dereferenced pointer to a such a variable, toggle between unsigned hex and signed decimal formats.
- bpt header
- By default, toggle the global breakpoint enable flag. The BreakPointHeaderAcceleratorAction X resource may be set to request that ups prompt for a new breakpoint instead.
- breakpoint
- By default, toggle the current breakpoint between the active and inactive states. The BreakPointAcceleratorAction X resource may be set to request that the breakpoint be removed instead. Double clicking ( but not shift-clicking) on the breakpoint in the source window selects has the same effect of toggling or removing breakpoint according to the BreakPointAcceleratorAction X resource.
SOURCE FILES MENU |
There is a menu for compressing the source file list. It has options of first level and completely. The Shift-left accelerator on the source file header is equivalent to first level. When globals are displayed in ups, they appear under the source file name. The first level item only removes files that do not have any globals or expressions displayed. This cleans up the display, just leaving items of interest. The completely item removes all file names and globals from the display.
If state has been saved from a prior usage of ups on the same target, by creating a ups-state directory, the next invocation of the debugger allows you to restore the globals shown before. After the target is running, simply expand the source file list to show all files and the chosen globals, then compress the list to the first level to leave just the globals.
BREAKPOINT MENUS |
By selecting a breakpoint, the Activate and Inactivate, captions control whether the breakpoint is either active or inactive. Active code is executed normally, whereas inactive code is ignored. The activation state is set by the two captions labeled Activate and Inactivate that appear after selecting the breakpoint object. The current state appears to the right of the breakpoint line number. The Execute caption can be used to execute breakpoint code whenever the target context allows it. The most common use for this is to repeatedly call a function, such as the Purify API functions purify_describe() or purify_all_leaks() without having to enter the call at every line in the source where it may be required.
By selecting the Breakpoints header object, the captions labeled Enable and Disable allow global control of processing of breakpoints. When globally enabled, all breakpoint code is examined, and if the breakpoint is active, the code is executed. Conversely, when breakpoint code is globally disabled, no breakpoint code is executed, regardless of its activation state. The current enabled state is implicitly shown by the shaded caption - so after pressing Disable, that caption is shaded and the Enable caption becomes normal.
When globally disabled or individually inactivated, the breakpoint code will still exist in the source, but the code will be ignored until re-enabled. The target will run at full speed for such breakpoints.
When typing in a breakpoint, pressing ESC does partial name completion whenever possible. So if a program has just two routines, process_key() and process_cmd(), typing p then ESC will expand the line to process_ and in the third line will be a message like process_ matches process_key and process_cmd. Then typing k then ESC will complete the line to process_key See the LISTING MATCHING SYMBOLS FOR BREAKPOINTS section for details on listing the matches.
SPECIAL HANDLING FOR SIGSEGV AND SIGBUS |
Some programs have exception handlers that allow the program to continue to run despite receiving SIGKILL, SIGSEGV or SIGBUS signals. If SIGSEGV or SIGBUS are changed from the default of Stop - ignore signal on continue to Stop - accept signal on continue, ups will stop on the exception, but allow the target to continue running upon pressing Cont, Next, or Step.
SIGSEGV or SIGBUS signals that intercepted by third party software such as ObjectStore can be handled by setting the signal to accept and continue. Do not use ignore as then the target never gets the signal and it will appear to hang. However, when set to accept and continue, the target can crash on bad code, but ups will not catch it. For such cases, set a breakpoint in the a target´s signal handler (if it has one), or change accept to stop.
CONTROLLING TARGET EXECUTION |
Once you have the target stopped at a breakpoint there are several ways of controlling its execution. Most of these are invoked from the target menu - the permanent menu just below the display area.
The usual way of debugging is to set a breakpoint in the function which you think is misbehaving and then step through its code one line at a time. The GETTING STARTED section above explains how to set breakpoints and start the target running. To step over a line of source, select Next from the target menu. The code on the highlighted line is executed, and the highlighting moves on to the next line to be executed.
The values of variables in the display area are updated every time the target stops, so you can watch values change as you step through the code. On colour displays variables are shown in a different colour if their values have changed since the last time the target stopped.
If the line to be executed calls a function, Step takes you to the first line of the called function, and stepping continues in the function. The step action may take some time occasionally; however the Stop command can be used to break out such a situation. If you don´t want to step through the code of called functions in this way, use the Next command. This behaves like Step, except that it never steps into called functions.
Both Next and Step work with respect to the currently displayed source. If you click on a function in the stack trace and select Source to display its source, a subsequent Next or Step moves to the next line of the displayed source. This makes it easy to get out of a function that you have stepped into by accident and don´t wish to step all the way through. Use the Source command to display the source of the calling function, then use Next or Step.
The Cont command in the target menu offers a third way to control the target - this command runs the target until it hits another breakpoint, gets a signal, or exits.
See the section THE SOURCE REGION for details about the Attach and Detach buttons.
Finally, you can drag execution in the target to a line in the source file. Move the mouse cursor over the line you wish to get to, and press and hold down the right mouse button. A popup menu appears, with the captions Add breakpoint Execute to here. Jump to here. and Edit source. Drag the mouse down so that the Execute to here caption is highlighted, and release the button. The effect of this is to set a temporary breakpoint at the line, temporarily disable all other breakpoints, and then continue the target. You can use this command to move past uninteresting bits of code without having to set up and remove breakpoints.
The second command on the popup menu, Add breakpoint, adds a breakpoint at the line of source you pointed at. Unfortunately, to set a breakpoint at (or execute to) a single statement that extends over several text lines, you must point at the last text line. This is due to limitations in the symbol table information put out by the compilers. The Jump to here command causes the target execution to jump to the current line without executing any intervening code. Use this with caution as it is possible to jump to a bad context where the data is bad or where there is no valid call stack. The safest usage is to jump over lines within a function. It can also be used to jump back within a function. If you try a jump to an invalid context, such as to a point up in the stack, you can use the stop button to restore the program to the state it had before the jump. When the current lowest level function has no symbols (such as "poll"), you will need to press the stop button twice to restore the program state. The Edit source command spawns an editor (typically either emacs or vi), and set the cursor at the current location in the file. The editor used is controlled by the EDITOR environment variable.
You can stop the target running at any time by clicking on Stop in the target control menu. The target will then stop wherever it is currently executing as if it had hit a breakpoint. In addition, if a symbol search puts the debugger in a long traversal of stack functions or files, the stop command will break it out of the search. The command is queued, and will be honored after completing the scan of the current function or file. In addition, the stop command will break out of a step command that is taking a long time.
The Kill command kills off the current instance target process. You can then use Start or Execute to here to start the target again. Quitting ups also kills the target process (unless you attached ups to a running process, in which case ups detaches from the process and leaves it to continue unmolested).
THE TYPING LINE MENUS |
The caption labeled Windows, just to the left of the Quit caption, provides a number of options loosely related to coordinating the various ups windows. The Snapshot Selected Objects item dumps objects (like the stack trace) to the output window. The Snapshot All Objects item dumps the complete display to the output window. The Message Logging item toggles on or off the copying of all subsequent messages printed to the message line to the bottom window. As well as providing a log of messages, this facility allows the text of messages to be selected for pasting. This allows a path that has been displayed with the path caption to be pasted when setting a breakpoint in a function name that is not unique.
The four items No Raise On Break, Raise On Break, Raise On Break/Lower On Run and Raise On Break/Iconify On Run select how ups manages its window(s) when the target process goes in or out of run. The default action is No Raise On Break, that is, no special action is taken. If Raise On Break is selected, ups will automatically raise its main window to the foreground when the debugged application stops. If Raise On Break/Lower On Run is selected, then in addition to raising the main window on a break, ups will lower the main window to the bottom of the window stack, after a brief delay, when the process goes into run. If Raise On Break/Iconify On Run is selected, then in addition to raising the main window on a break, ups will iconify the all windows, after a brief delay, when the process goes into run.
In split screen modes, these options raise or lower the window containing the source display and Start/Next/Step buttons.
The initial state of these options may be set using the WantRaiseOnBreak family of X Resources (see the section X RESOURCES below), or by the -raise_on_break, -lower_on_run, and -iconify_on_run command line options.
The button labeled Search to the left of the Windows button is used to search for regular expressions (using the same syntax as grep(1) patterns) in the display window. First type in the pattern to be searched for (typed characters appear in the typing line at the top of the window on the left) then press and hold down the left mouse button over the Search caption. A popup menu appears with the options Backwards and Forwards. Move the mouse over the one you want and release the button. If the pattern is found, the matching text is made visible in the display region and highlighted.
The button labeled Help to the left of the Search button provides simple textual help information on a variety of topics. Output is placed in the bottom output window. By default, the text is appended to the bottom of the window, with the scrollbar positioned so that the topic begins at the top of the window. The last item in the Help menu allows the window to be cleared before a new help topic is printed out.
TARGET COMMAND LINE |
The first line of the display area shows the command line that specifies the target to debug. It can be edited and changed to a different target at any time in order to debug a different target. It accepts csh(1) style tilde notation. When changing targets, ups will read new symbols as necessary and reinstate breakpoints and variables where possible. So if you are working on a shared library and you need to test it with different targets, simply enter the new target name and attach, and the debug state information will be preserved.
TARGET COMMAND LINE ARGUMENTS |
The second line of the display area shows the command line arguments that will be given to the target when it is next started. The arguments shown include the zero´th argument which is initially set to the name of the target.
You can specify an initial set of arguments for the target with the -a option when you start ups. If you don´t give the -a option and you are debugging from a core file, ups attempts to extract the command line arguments from the core file. Otherwise the command line contains no arguments other than the name of the target.
Ups parses the command line in a similar way to the shell. It supports Bourne shell type redirection (>, >>, <, >&dig, etc.) as well as the csh forms >& and >>&. Ups also understands most csh metacharacters - globbing with *, ? and [xyz], the ~, ~user and {a,b,c} shorthands, and quoting with single or double quotes and backslash. The current version of ups does not support $var type shell variable substitution.
You can edit the command line at any time to change the command line arguments (although the changes will only take effect when you next start the target).
The command name shown is just the zero´th argument and can be edited just like the other arguments. This is useful with programs which use the zero´th argument as a sort of hidden flag. Changing the command name only affects the arguments given to the target - it does not change which program is being debugged.
CONTROLLING THE DISPLAY OF VARIABLES |
When you add a variable to the display (see EXAMINING VARIABLE VALUES above) it is displayed in a default format. If you click the left button over the line for the variable, a menu appears in the top part of the window. You can use this menu to set the display format for the variable (Format), to change the level of indirection for pointers (* and &), to expand all base classes and show vector tables for a class (::), to show all the members of structures and unions (Expand and Collapse), to choose the format variables are displayed in Format, to duplicate or delete entries for variables (Dup and Del) and to control whether typedefs are used in displayed variables (Decl) and if watchpoints are available, add a watchpoint at the variable address (Watch).
The default for a pointer variable is simply to show the pointer value in hex. To take a common example, if you add a variable of type pointer to pointer to char called argv to the display, you will get a line like :
char **<argv> 0x7fffe184
The angle brackets separate the type from the value. In this example, what is shown is the value of argv, which is of type char **.
If you now click with the left mouse button on this line, and select * (the leftmost caption) in the variables menu, the format of the line changes to something like :
char *<argv{0}> 0x7fffe1d0
This says that what is shown is the value of argv[0], which is of type char *. The braces ({ and }) are used to distinguish a dereferenced pointer from a true array.
A second click on the * menu option changes the line to:
char <argv{0}{0}> "foo"
This is a special case in ups - variables of type char are displayed as strings if they are indirected pointers or members of arrays.
The & menu option is the opposite of * - it drops one level of indirection. You can only use this on indirected pointers. Use an expression if you want to see the address of a variable (see EXPRESSIONS IN THE DISPLAY AREA below).
Arrays are initially displayed with all subscripts zero. You can edit the subscript to another value by clicking on it with the middle mouse button. A marker bar appears, and you can use the delete key to delete the old subscript and type a new one. When you hit ESC, the value of the new array element is shown.
Often you wish to quickly scan through all the elements of an array. You can do this using either the arrow key or the > and < keys. When editing an array subscript, the > key adds one to the subscript value and displays the new element. Similarly, the < key subtracts one from the subscript value. Using these keys you can rapidly scan up or down an array. Note that the ReverseArrows X resource can be used to reverse the function of the arrow keys.
Emacs users can use C-P (Control-P) and C-N (Control-N) as synonyms for < and >. Vi users can use k and j similarly.
The arrow (or whatever) keys actually act on the digit to the left of the cursor, so by moving the cursor left you can step by tens, hundreds etc..
Note: in this section structures also include unions: they are simply treated as structures with all members having an offset of zero.
Variables that are structures or pointers to structures are initially displayed with just the address in hex. You can use the Expand command in the variables menu to add all the members of a structure to the display. The structure members are indented to make it clear which structure they belong to. Clicking on Expand will produce a popup menu with the options Expand Structure and Expand Static Variables. Selecting Expand Structure will display all the non-static members members of the structure except vector tables. ( See the section EXAMINING BASE CLASSES AND VECTOR TABLES below for vector tables.) If the selected item is a member of a class with static members, the Expand Static Variables option will show all the static members of the class. See the section EXAMINING STATIC MEMBERS OF CLASSES below.
If a structure element is itself a structure or a pointer to a structure, it can be expanded in turn to show all its members. In this way linked data structures can be explored. For a more selective way of exploring a linked data structure, see the EXAMINING LINKED DATA STRUCTURES section below.
Show size will display size of the arrays and structures (but not memory sizes that may have been allocated to a pointer - such variables will the standard 4 bytes). Note that in the display window, a variable formatted as type <name[0]> indicates an array, whereas type <name{0}> indicates a pointer.
To remove all the members of a structure from the display, use the Collapse command in the variables menu. This has a submenu with the options First level and Completely. The first of these removes all members except expanded ones; the second recursively collapses all expanded structures below the selected one.
By default integer variables are displayed in decimal and pointer values are shown in hex. You can change the format with the Format command in the variables menu. The possible formats are signed or unsigned decimal, hex, octal and binary, as well as ascii and string. The ascii format displays integers in C character notation (e.g. the value 65 is displayed as a). The string format is applicable to variables of type char that are indirected pointers or arrays - it treats the address as the first character of a NULL terminated string.
Floating point values are shown in the conventional notation (using the 0 format). You can use the Format command to display a hex representation of the value (it makes no difference whether you select signed or unsigned hex from the menu). This shows in hex the bit pattern used to represent the floating point value.
The Delete command in the variables menu deletes all selected variables from the display area. This is useful for tidying up the display by removing variables that are no longer of interest.
Sometimes it is useful to have a variable displayed more than once. One common case is where you want to see several elements of an array simultaneously. The Dup command in the variables menu duplicates the entries for all selected variables. So to see multiple elements of an array, use Dup to add an entry for each element you wish to see, then edit the subscripts separately for each entry. When duplicating a pointer variable for which the contents of the pointer is displayed, the array index is bumped by 1, or by 40 if a string is displayed.
If a structure, union or enum has a typedef name then ups will use it in the display area. Thus if you have the following in a function:
then clicking on variable f will add a line like:typedef struct foo_s { int x; int y; } foo_t; foo_t *f;
foo_t *<f> 0x40ec
to the display area. Typedefs are not used if they hide a level of indirection or an array, or if the typedefed type is not a struct, union or enum.
If you want to see the non-typedef type for a variable in the display area, select the variable and press and hold down the left mouse button over the Decl command in the variables menu. This produces a popup menu with the captions Use typedefs and Ignore typedefs. Release the mouse over Ignore typedefs and you will be shown the non-typedefed type for all the selected variables.
CHANGING VARIABLE VALUES |
You can change the value of a displayed variable simply by editing the displayed value (i.e. by clicking on it with the middle mouse button and editing in the new value). This works for C pointers and integral types (including enums), floating point values and strings.
You can use any of the integer display formats for the new value (decimal, hex, octal, binary or ASCII character). You can use enum constant names for new enum values, and function names for function pointers. When editing strings or characters you can use the standard C notation for special characters (\n, \b, \007 etc.).
Normally ups will not let you edit extra characters into a string as this would overwrite whatever was stored in memory just after the string. If space is known to exist (for example if the string is stored in an array of known size and there are unused bytes) then you can add as many characters as will fit. If you know you want to overwrite memory beyond the end of the string you can force ups to accept a long value by putting >> before the leading quote character of the string.
Normally a trailing NULL (\0) is added to the edited string in the normal C way. If you delete the trailing quote character then this is omitted.
EXPRESSIONS IN THE DISPLAY AREA |
You can add C expressions as well as variables to the display area. This is useful if you wish to see what an expression in the source code evaluates to. It also allows you to use casts when you know better than the source code what the type of a given variable is.
To add an expression, select a function in the stack trace and click on Add expr in the function menu. A marker bar appears, ready for you to enter an expression. When you have finished press ESC, and if the expression is legal the value will be displayed. If there is an error in the expression you will get an error message and the marker bar will be repositioned at the point of the error.
A workaround for dealing with preprocessor macros is to create a repltab file. Ups will look in ups-state/repltab below the current directory. If that file does not exist, it will look for $HOME/repltab. See the section PASTING EXPRESSIONS FROM THE SOURCE WINDOW for details on the repltab file.
In an expression you can use any variable name, structure tag or typedef name that is in scope in the function. If you want to add expressions using a variable in an inner block, you will have to add the expression to the appropriate inner block. The easiest way to get the inner block object displayed is to click on a variable in the inner block in the source region. Once it is displayed select the block header and click on Add expr in its menu.
If your compiler has included macro information as part of the debugging data then you can also use macro names in an expression. When you do this the macro is assumed to have the value which it held on the first line of the function where you have entered the expression.
You can bump numbers in expressions in a similar way to array subscripts. Hitting the down arrow (or Control-N) over a number while editing an expression increases the digit to the left of the marker bar and displays the new value of the expression. Similarly the up arrow (or Control-P) decreases the digit to the left of the marker bar and redisplays the expression value.
Expressions are reevaluated like variable values every time the target stops. They also have the same menu associated with them as variables, and you can have both expressions and variables in the same selection. All the menu commands work as they do on variables. This means in particular that if you add an expression whose type is pointer to struct(or union) you can use Expand to show the structure elements. You can also use Format to change the format used to display the expression value.
You can call target functions in expressions, but you can´t modify target data in a display area expression (thus operators like ++ are illegal).
EXAMINING BASE CLASSES AND VECTOR TABLES |
When the object selected is a class, clicking on :: (double colon) recursively adds all base classes for the object to the display, and displays the vector table(s), showing the address symbolically when possible. This is useful if you want to expand a base class to look at a member of a base class several levels deep in the class hierarchy, without expanding everything in between.
In addition, it is usually possible to tell from the name of the vector table which subclass of the current class the object is "really" a member of.
A special case worth knowing about occurs when the selected object has been deleted. In this case, the vector table will indicate that the object is a member of the root class for the class hierarchy, rather than of any subclass.
For example, consider the short C++ program :
If you stop at the start of B::bad(), click on this then select ::, you will see something like :class A { public: A() { cnt++;} virtual ~A() { cnt--;} private: static int cnt; }; int A::cnt; class B : public A { public: void bad(); virtual void v() {} }; class C : public B { public: virtual void v() {} }; void B::bad() { delete this; v(); } main() { C* c = new C; c->bad(); }
The _vtbl entry shows that this is really a C, a subclass of B.Functions main B::bad B* <this{0}> 0x12345678 struct A <A> 0x12345678 void *<_vtbl.> C::__vtbl Breakpoints
When you single step over the delete, the display changes to
Since class A is a base class for B, seeing that this is really an A in a method for class B is surely an error, and often results from object having been been deleted.Functions main B::bad B* <this{0}> 0x12345678 struct A <A> 0x12345678 void *<_vtbl.> A::__vtbl Breakpoints
The expansion of base classes only works for compilers that include base class information in their symbol tables, namely for g++ and Sun SC4. The symbolic representation of vector tables works for both of these and also for cfront.
EXAMINING STATIC MEMBERS OF CLASSES |
Static members of classes may be examined as other global data. In addition, depending on the compiler, they may be examined as members of a structure are examined.
In the example in the previous section, the static member A::cnt may be displayed by :
Typing A::cnt in the typing line.Clicking on A::cnt anywhere in the source window.
In addition, if the compiler supplies information about static members in the symbol table (g++ and Sun SC4 do this), A::cnt may be examined by :
While in a non-static method for class A, click on cnt in the source window.Select an object of type A and enter .cnt in the typing line.
Select an object of type A, press the Expand option then select Expand Static Variables from the resulting popup menu. This latter option displays all static members for class A.
PASTING EXPRESSIONS FROM THE SOURCE WINDOW |
It is often useful to display the value of an expression in the source. You could select Add expr as described in the previous section, and cut and paste the expression from the source window. This works, but there is a quicker way: simply select the text of the expression in the source window while holding the shift key down (i.e. press the shift key, then drag the mouse over the desired text). When you release the mouse button, the selected text is added as an expression in the display area. It is OK to drag over multiple lines.
You will notice that when you first press the left mouse button (with the shift key pressed), ups highlights some text. This is its guess as the to expression you would like to paste. If you are happy with this, release the mouse button without moving the mouse, and the highlighted text will be added as an expression. If the highlighted text is not what you want, drag the mouse to make the selection as described before.
Pasting expressions from the source window can often fail because of preprocessor macros which ups does not understand (e.g. NULL). The correct fix for this is for ups to understand #defines, but in the interim there is a workaround: if the file ups-state/repltab exists below the current directory ups will apply the substitutions specified there. If that file does not exist, it will look for $HOME/repltab. Here is a repltab file that would deal with NULL and EOF :
# Repltab for ups NULL 0 EOF (-1)
Hash comments and blank lines are ignored in the normal way. Any substitutions will be visible in the pasted expression.
Ups checks to see if the repltab file has been updated each time an expression is pasted, so you don´t have to restart ups to it to notice changes.
ADDING INTERPRETED CODE |
The ups display area gives a good picture of that state of a program at any one time. Often though, you want a record of what happened over a series of calls of a function. This is one of the reasons why people still tend to put print statements in code despite the availability of debuggers and the inconvenience of recompiling the code.
To make it easier to add diagnostic output statements, ups allows you to insert fragments of C code at any breakpoint. The default breakpoint action - stopping the target - is represented as a fragment of pseudo C code. This is the
#stop;
line that appears in the source region when you add a breakpoint.
You can change this to a fragment of C code, editing the text in the usual way by clicking the middle mouse button to position a marker bar. You can use the RETURN key to enter multi-line code fragments. As with other editable fields, you end the edit with ESC. If there is an error in the code, an error message is given and the marker is positioned at the point of the error.
For example, you could change the breakpoint action to :
printf("Entered function foo with x = 0\n", x);
From now on, whenever the target reaches this point in the program, it will call printf() rather than stopping.
Note that a breakpoint will not stop the target unless the special keyword #stop is executed. You can use this to set conditional breakpoints, like :
if (i == 72) #stop;
or, to use a more sophisticated example :
if (strcmp(p->p_name, "foo") == 0) #stop;
In the above examples, the function calls (printf() and strcmp()) are implemented as calls to functions in the target. You can call any target function from a breakpoint, but in the current version of ups all functions are assumed to return int. You can often get around this by casting the return value to the correct type.
One problem with calling functions like printf() to do diagnostic output is that the output is mixed up with the normal output of the target program. If you want the output kept separate, use the built in ups function $printf. This function creates a new region in the ups window the first time it is called, and sends output to that region. The menu at the top of the region allows you to search for regular expressions in the output, as well as page through it and clear all output.
The $printf function takes the same format string as printf(), with one addition. The %v format string can be used with any variable type, and means print in the default ups format for the type. The %v format character will print symbolic names for enum values and function pointers (i.e. you will get output like RED and close_callback rather than 23 and 0x5e748). In addition %v applied to a struct or union pointer will print the names and values of all the fields of the pointed-to struct or union.
You can declare your own variables in breakpoint code. This is useful when you want only want to stop at a breakpoint after it has been hit a given number of times. A code fragment to do this would look something like:
{ static int count = 0; if (++count == 74) #stop; }
This would stop the target the 74th time the breakpoint was encountered. Static variables are reinitialized every time the target is started. Automatic variables are uninitialized and do not preserve their values between separate executions of breakpoint code.
You can mix C interpreter variables with real target variables in expressions in breakpoint code, with some restrictions. You can assign to target variables, but making a target pointer point at an interpreter variable will not work, as interpreter variables do not exist in the target´s address space. On the other hand, the interpreter knows about the target address space, so you can point interpreter variables at target variables.
Note that you can only add interpreted code - you can´t directly affect the flow of control of the compiled code. For example adding a return statement will not cause the compiled function to return to the caller. It is sometimes possible to indirectly affect the flow of control by judicious changes to variable values.
You cannot add C interpreter variables to the display; if you click on a variable in interpreted code it is taken to be a variable from the target process.
[ You probably want to skip this paragraph. ]
For people who want to live at the ragged edge, the C interpreter uses copy-in copy-out semantics when passing interpreter addresses to the target. If you pass an argument of type pointer to T to a compiled target function then the interpreter copies sizeof(T) bytes to the target address space and passes a pointer to that copy. When the target function returns the same number of bytes are copied back from the target into the interpreter address space. Similarly when you pass an array, the contents of the array are copied in and out. Note that this mechanism does not work in general - it only copes with passing an array or a pointer to a single object. The main motivation for this feature was to make string literals (e.g. "hello") work as expected when passed to target functions like strcmp().
EXAMINING LINKED DATA STRUCTURES |
Ups has several facilities that are useful for examining linked data structures. Firstly, you can expand structures or structure pointers. By repeatedly expanding structures you can follow down a linked list or tree.
Often this adds too much information to the display, as you are probably not interested in all the structure elements. There is a more selective method of expanding lists and trees which lets you easily see just the elements you want.
Suppose you have a structure declaration like this:
struct linkst { struct linkst *prev, *next; int key; };
Suppose also that you have a variable linkptr displayed which is a pointer to this structure.
If you type in a . followed by the name of element, such as prev, that element of any selected structures or structure pointers will be added to the display and selected when you hit ESC.
Assume linkptr in the example above is displayed and selected. Typing .next followed by ESC will add the next field of linkptr to the display and select it, and deselect linkptr. Typing ESC again will add the next element of the list. Thus by repeatedly typing ESC you can easily walk down a linked list.
You can give many structure elements separated by spaces. Thus the line
.key .next
would add both fields to the display. In this way you can walk down a linked list with members of interest displayed as well as the links.
One problem with this way of looking at lists is that the indentation of structure elements tends to make the list wander off the right hand side of the display area. To avoid this you can say @member rather than .member. The @ character means do not indent - this is the only difference between it and .. Thus to get a nicely laid out list in the example above you could enter the line :
.key @next
and keep typing ESC to walk down the list.
One last wrinkle: if you add #nnn to the end of the typing line, where nnn is a decimal number, the effect is as if you had pressed ESC that number of times. This is handy if you want to see all of a 500 element linked list without having to type ESC 500 times.
In C interpreter code (described in ADDING INTERPRETED CODE) you can scan through a linked list as if it were an array using the (non-standard) ->[count] operator. This is a shorthand for applying the -> operator count times. You can use the arrow keys (or ^N and ^P) as described in EXPRESSIONS IN THE DISPLAY AREA to bump the count parameter up or down and step through a linked list one element at a time.
Thus in the example above, adding the following expression to the display area :
linkptr->[0]next
would just show the value of linkptr (the -> operator is being applied zero times). You can expand the structure and add and delete elements to get the display set up as you like. Then you can edit the 0 to 1 to see the next element of the list, and so on.
DISPLAYING MEMORY |
The contents of raw memory may be dumped to the output window in two ways. If the memory to be dumped is the address of a simple variable or structure, or is pointed to by a pointer variable, select the variable of interest, press the Expand option then select Dump Memory from the resulting popup menu. This option displays the contents of memory at the selected address. The length of memory displayed, and the grouping (as bytes, shorts, or longs) is based on the type of object selected. This option also prints in the output window the equivalent typing line command, which you may copy to the typing line and edit as required.
The commands to display memory through the typing line begin with %d (for dump) :
If the size is omitted, 16 bytes are displayed. If the grouping is unspecified, bytes or shorts are selected depending on target endidness.%d address [size|.. end_address] dump size bytes of memory at address %db address [size|.. end_address] dump size bytes of memory as bytes at address %ds address [size|.. end_address] dump size bytes of memory as shorts at address %dl address [size|.. end_address] dump size bytes of memory as longs at address
ENVIRONMENT VARIABLES |
By default the target inherits the same set of environment variables as ups. You can change this using the Environment object in the display area. Any changes to the target environment take effect the next time the target is started.
Selecting the Environment object produces a menu with the commands Expand, Collapse, Add entry and Reset env. The Expand command adds an entry to the display area for each environment variable. You edit an environment variable name or value by clicking on it in the normal way with the middle mouse button. Collapse removes all the entries from the display area.
To add a new entry select Add entry from the environment menu and type in the name=value string. Ups will accept any string as an entry, but gives a warning for odd-looking entries.
If you wish to abandon any changes you have made to the environment select Reset env. This resets to the environment to the state it was in when ups was started.
If you select an individual environment entry you get a menu with the options Hide, Delete and Append entry. The Hide command removes the entry from the display but not from the environment. This is useful for clearing the display of uninteresting entries. By contrast the Delete command removes the entry from the environment. The Append entry command allows you to add a new environment variable just after the one selected; this is useful if you need the environment set in a particular order.
SIGNALS |
When the target gets a signal control returns to ups. Depending on the signal and the way you have specified it should be handled, the target is either stopped or restarted (possibly with a display refresh), and the signal can either be passed on to the target or ignored.
Near the top of the main display area is a Signals object. Selecting this produces a menu with Expand and Collapse as options. Expanding the signals object produces a list of all signals, with the current way the signal is handled displayed for each signal. Selecting a signal produces a menu which lets you change the way it is handled.
You can control whether a given signal causes ups to stop the target, refresh the display and continue the target or just continue the target without refreshing the display. You can also control whether the signal should be passed on to the target.
You can trim the signals display by selecting the ones you aren´t interested in and clicking on Hide in the signals menu. This will remove those signals from the display area.
The Next and Step commands both step over functions called as a result of a signal. Breakpoints in signal handling functions work normally.
TYPING LINE SHORTCUTS |
A few frequent requests can be invoked by typing input as an alternative to mouse operations.
X AND SUNVIEW COMMAND LINE FLAGS |
Under SunView ups recognises the standard SunView tool flags. These can occur anywhere on the command line.
Under X ups recognises most common X11 command line arguments. The currently recognised flags are :
- -iconic
- Start up as an icon rather than as a window.
- -display displayname
- Create a window on the named display rather than using the value of the DISPLAY environment variable.
- -geometry geometry
- Use the specified X geometry for the window.
- -name name
- Use name rather than the default ups as the window and icon name. This name is also used when fetching X defaults.
- -fn fontname
- Use X font fontname rather than the default.
- -fg colorspec
- Use colorspec (which should be a standard X11 color specification) as the color of the foreground pixel.
- -bg colorspec
- Use colorspec as the color of the background pixel.
- -rv
- Reverse the foreground and background pixel colors.
These options are available under X and SunView :
- -mono
- Force monochrome mode even if when using a color display. Use this flag to stop ups interfering with the colormap on pseudocolor displays (e.g. when you are debugging a program with a colormap related problem). The flag is also useful on some Sun displays under SunView where using monochrome significantly increases the display speed.
- -wn_record filename
- Record mouse and keyboard events in file filename.
- -wn_replay filename
- Read mouse and keyboard input from file filename rather than the mouse and keyboard. The file filename must have been created with the -wn_record flag in a previous session.
- -wn_replay_warp
- When replaying events with -wn_replay, warp the mouse in the ups window to reflect the recorded mouse movement events.
X RESOURCES
Ups recognises a number of X defaults. By default it uses the last pathname component of the name you run it with as the application name when looking up resources (i.e. if you run it as /usr/bin/ups it will use ups). You change the name with the -name flag described above. If it fails to find a resource with the application name, ups does a lookup using Ups (note the initial upper case letter). A resource specified as Ups.xxx will thus always be noticed. Finally ups looks in the resource file /usr/lib/X11/app-defaults/Ups if a resource is not found anywhere else. (In addition to the above directory, ups looks for the file Ups in the colon separated list of directories given by the environment variable XUSERFILESEARCHPATH, and in the single directory given by the environment variable XAPPLRESDIR.)
The current list of recognised resources is :
- Font
- The name of the normal font. The default is fixed.
- MenuFont
- The font used for menu captions. The default is to use the normal font.
- SrcFont
- The font used for text in the source window. The default is to use the normal font.
- EditFont
- The font used for editable text in the source window. The default is a bold version of the normal font (using the name formed by replacing medium with bold in the font name). If this substitution cannot be made, ups tries -*-fixed-bold-r-normal--15-*-*-*-*-*-*-*. If this font is unavailable, ups complains and uses the normal font.
- Foreground
- The color of the foreground pixel. The default is whatever the BlackPixel macro returns for the display.
- Background
- The color of the background pixel. The default is whatever the WhitePixel macro returns for the display.
- ReverseVideo
- If this is set (to anything) it has the same effect as the -rv flag.
- WantInstalledColormap
- If this is set to yes then ups will install its own colormap, rather than use the default colormap. Use this if ups complains that it failed to allocate some colors. The same effect can be achieved by using the command line option -install. Note that the command line option of -noinstall will override the resource.
- Geometry
- The size and (optionally) position of the main ups window. The default is to suggest to the window manager a window 580 pixels wide by 550 pixels deep at a user-specified position. Most window managers will of course let you sweep out a window of the size you require.
In the split window modes, the source and output windows have their own geometry resources. Set the resource Ups.Src.Geometry to specify a geometry for the ups source window, and Ups.Output.Geometry to specify the geometry for the ups output window. Or set the resource Ups*Geometry to specify the same geometry for all ups windows.
- EditlinesColor
- The color used for editable text in the source window. The default is blue.
- ColorVars
- Can be set to off to disable coloring of variable names.
- VariableColor
- The color used for variable names in the display area. The default is purple.
- HighlightColor
- The color used to highlight variables in the display area whose values have changed since the last time the target stopped. The default is red.
- WantMenuColors
- If set to yes, ups will use foreground and background menu colors as listed below. If not set to yes, such settings are ignored, and the Foreground and Background resources are used.
- MenuForeground, MenuBackground
- The default colors for text and background in all buttons and menus. Sub menus inherit the colors of their parents unless specifically overwritten.
- DisabledTextColor
- The color for text that is disabled, such as the start caption after starting the target, or globally disabled breakpoints.
- LastButtonTextColor
- The text color of a busy button pressed (such as cont while the target is executing) or the parent menu item of a sub menu.
- SourceMenuForeground, SourceMenuBackground
- The text and background colors of the pop up menu for the source window.
- CustomMenuForeground, CustomMenuBackground
- The text and background colors of the custom pop up menu for editing text strings.
- FileBoxMenuForeground, FileBoxMenuBackground
- The text and background colors of the pop up menu for the file name and line number box that is directly above the source window.
- UnloadedLibMenuForeground, UnloadedLibMenuBackground
- The text and background colors of the pop up menu for the Load library menu invoked from the target line.
- text captionForeground, text captionBackground
- The text and background colors for a menu item with a specific text caption: for example Add breakpointForeground. Note that embedded spaces are allowed.
- AsteriskForeground, AsteriskBackground
- The text and background colors of the * menu caption that appears when selecting a variable. This caption uses a special resource name in order to resolve a conflict with main foreground and background resources.
- WantExtendedTextColors
- If set to yes, ups will use the colors for the text items in the display window as listed below. If not set to yes, such settings are ignored.
- SignalTextColor
- The text color of the signals listed under the Signal header.
- EnvironmentTextColor
- The text color of environment strings listed under the Environment header.
- SourceFileTextColor
- The text color of the file names listed under the Source files header.
- FunctionTextColor
- The text color of the function names in the stack under the Functions header.
- BreakpointTextColor
- The text color of active breakpoints listed under the Breakpoints header. Inactive breakpoints are in the main foreground color, as is the text of breakpoint code in the source window.
- WatchpointTextColor
- The text color of active watchpoints listed under the Watchpoints header. Inactive watchpoint are in the main foreground color.
- MouseholeWidth
- The width of the mousehole in pixels.
- WantWatchpoints
- If this is set to yes then watchpoints will be available. On x86 machines watchpoints are available by default but watchpoint action is unreliable on other machines at present, so on these it is not shown by default.
- WatchPointRefreshInterval
- This adjusts the interval between refreshes of the display when mprotect(2) style emulated watchpoints are being used.
- WantMousehole
- If this is set to yes the mousehole is removed from the display. This is useful if you use a large font and find the typing line is too small.
- TypingLineOnRight
- If this is set to yes, the top line of ups is flipped left to right so that the mousehole (if not disabled) is on the left, then the permanent menu, then the history and enter buttons, then the typing line.
- PermanentMenuWidth
- The width of the permanent menu (Quit, Help etc.) in pixels.
- SelectionThreshold
- The number of pixels to move right in order to activate text selection in the display window. Default is 30.
- NonFrameFunctions
- When set to on, ups does different processing of non frame (or frameless) pointer functions. This will normally make ups work better with software that inserts calls into the object code, such as Purify Purecov and Quantify. This should fix truncated stacks and anomalous next and step behaviour when debugging such code. However, it occasionally causes problems with ordinary targets, so this feature is disabled by default. Ups will automatically set the value to on if it detects the presence of Purify Purecov and Quantify. A value of off explicitly overrides such automatic setting.
- ScrollbarType
- Controls the scrollbar behavior. If set to anything other that UPS, such as MOTIF, then scrolling will move the viewport in the opposite direction to the mouse movement, this being the convention used by most X toolkits (for better or worse).
- ScrollbarWidth
- The width of all the scroll bars in pixels.
- ScrollDelay
- Set this if scrolling is too fast. A value of 25 or 50 is usually sufficient. The default is 25.
- SrcwinNameWidth
- The width in pixels of the box above the source window containing the current source file name and line number.
- SrcwinPercent
- The percentage of the window height used for the source window (after space used by the fixed size regions is subtracted). The default is 50 (i.e. half).
- SrcwinScrollUpButton, SrcwinScrollDownButton
- The mouse buttons which, when pressed, should cause the source window to scroll. This is normally used with wheel mice to make wheel movements cause the source window to scroll. There is no default.
- DisplayAreaPercent
- The percentage of the window height used for the display area (after space used by the fixed size regions is subtracted). The default is 50 (i.e. half). If DisplayAreaPercent and SrcwinPercent are both set they need not add up to 100 - the values actually specify a proportion of the total. Thus setting both to 20 (or any pair of identical values) results in a 50-50 split.
- DisplayAreaScrollUpButton, DisplayAreaScrollDownButton
- The mouse buttons which, when pressed, should cause the display area to scroll. This is normally used with wheel mice to make wheel movements cause the display area to scroll. There is no default.
- OutwinPercent
- The percentage of the window height used for the output window if and when it is added. The default is 10 (which actually means a tenth of the total - see the note about SrcwinPercent above).
- EnterButtonWidth
- The width of the text entry button in pixels.
- ReverseArrows
- if set to yes then ups reverses the sense of the up and down arrows which are used in an expression or variable index.
- HistoryButtonWidth
- The width of the history button in pixels.
- WantSplitWindows
- If this is set to yes then ups will start up with two windows. The source window, source menu, target menu, and output window and menu (if used) will be in one frame. The display window and the permanent menu (Quit, Help etc.) and dynamic menus (Expand, Collapse etc.) will be in another frame. The same effect can be achieved by using the command line option -split. To request a screen number for the second window, use the form yes:screen number.
- WantSplitOutputWindows
- If this is set to yes then ups will come up with 2 windows, or 3 windows if WantSplitWindows is also set, with separate frame for the output window. The same effect can be achieved by using the command line option -splitoutwin. To request a screen number for the second window, use the form yes:number.
- WantLogging
- If this is set to yes, ups will come up with error messages logged to the output window. The same effect can be achieved by using the command line option -logging or during the session by turning on the Message Logging option under the Windows popup menu.
- WantRaiseOnBreak, WantLowerOnRun, WantIconifyOnRun
- These resources set the initial state of the Raise On Break family of options in the Windows popup menu. These should be set to yes or no as to whether and how ups should manipulate its windows when the target process goes in or out of run. All are set to no by default. These are evaluated in the order listed, the last of these options set to yes being the initial state of the Raise On Break option.
- LowerOnRunTime
- When the Lower or Iconify on Run options in the Windows popup menu are active, this resource sets the time in milliseconds that ups waits for the process to break before lowering or iconifying itself. The default value is 1500, that is, a 1.5 second delay.
- ...Row
- The default vertical position of the objects in the display window can be specified by the following ...Row resources. Legal values are 1 to 9 inclusive: 1 indicates the top row and 9 the bottom. Only rows of interest need to be specified. Other rows are positioned according to their default values. For example, if one wants to put the breakpoints above the function stack (and one is not using Fortran), use:
Ups*BreakpointsRow: 6
- TargetRow
- The vertical position of the Target header in the display window. Default is 1. Note that this is a double height row.
- SignalsRow
- The vertical position of the Signals header in the display window. Default is 2.
- EnvironmentRow
- The vertical position of the Environment header in the display window. Default is 3.
- UntypedVariablesRow
- The vertical position of the Untyped variables header in the display window. Default is 4.
- SourceFilesRow
- The vertical position of the Source files header in the display window. Default is 5.
- ModulesRow
- The vertical position of the Modules header in the display window, for targets using Fortran modules. Default is 6.
- CommonBlocksRow
- The vertical position of the Common blocks header in the display window, for targets using Fortran common blocks. Default is 6 if no modules exist, 7 otherwise.
- FunctionsRow
- The vertical position of the Functions header in the display window. Default is 6 for non-Fortran targets, 7 or 8 if the target has Fortran modules or common blocks.
- BreakpointsRow
- The vertical position of the Breakpoints header in the display window. Default is 7 for non-Fortran targets, 8 or 9 if the target has Fortran modules or common blocks.
- WatchpointsRow
- The vertical position of the Watchpoints header in the display window. Default is 8 for non-Fortran targets, 9 or 10 if the target has Fortran modules or common blocks.
- WantTypedefs
- If this is set to no, then ups will not attempt to use typedefs in display area variable declarations. See Use of typedefs in the CONTROLLING THE DISPLAY OF VARIABLES section.
- TabWidth
- The width in characters of a tab character (for use in the source window). The default is eight.
- UseMono
- If this is set to yes then ups will always use mono even on colour displays. This resource has the same effect as the -mono flag (see above).
- MultiClickTime
- This resource specifies the maximum time in milliseconds between multi-click events. The default is 250 milliseconds.
- BreakPointAcceleratorAction
- This resource selects the accelerator action when shift-clicking or double clicking on a breakpoint in the source code or display area. The resource may be set to Toggle, to toggle the breakpoint between the active and inactive states, or Remove to remove the breakpoint. The default is to toggle the breakpoint.
- BreakPointHeaderAcceleratorAction
- This resource selects the accelerator action when shift-clicking or double clicking on the breakpoints header in the display area. The resource may be set to Toggle, to toggle the global breakpoint between the active and inactive states, or Add to to add a new breakpoint. The default is to toggle the global breakpoint state.
- WatchPointHeaderAcceleratorAction
- This resource selects the accelerator action when shift-clicking or double clicking on the watchpoints header in the display area. The resource may be set to Toggle, to toggle the global watchpoint between the active and inactive states, or Add to add a new watchpoint. The default is to toggle the global watchpoint state.
- SourceMenuDefault, AltSourceMenuDefault
- These resources control the default action when clicking the right mouse button in the source window to quickly select from the pop-up menu (without taking the time to actually select something). The AltSourceMenuDefault resource, if used, controls the selection when shift-clicking, while the SourceMenuDefault controls the selection otherwise. If AltSourceMenuDefault is not used, then SourceMenuDefault controls both; if SourceMenuDefault is not used, it defaults to LastSelection.
Possible values are:
- LastSelection
- Selects the most recently selected value.
- ResetDefault
- For the AltSourceMenuDefault resource only, causes the a selection made with shift button depressed to reset the default option used when quickly clicking.
- AddBreakPoint
- Selects the Add BreakPoint option.
- ExecuteToHere
- Selects the Execute to here option.
- JumpToHere
- Selects the Jump to here option.
- EditFile
- Selects the Edit file option.
- TypingLineHistorySize
- Sets the number of entries in the typing line history buffer. There are also resources to control the other edit histories. To determine their names, find the name of the history in the edit history file and append HistorySize.
DEBUGGING FORTRAN CODE
Ups has support for debugging code written in Fortran 77 and Fortran 90. The Fortran 77 support works with most compilers. The Fortran 90 support has only been tested with the epcf90 compiler running under SunOS 4.1.3.
The most visible difference with Fortran code is that variable types are displayed using Fortran rather than C syntax. Thus a typical stack display might look like :
Functions MAIN double precision acctim 0.0 integer*4 count 0 double precision table(168,10) [1,1] 0.0 logical dotrace .false.Variable names will usually be shown in lower case, even if you have used upper case in the source code. This transformation is done by the compiler, and ups has no control over it.
Notice that there are two sets of subscripts shown for the array table. The first set (in round brackets) show the actual size of the array. The second set shows the subscript of the element that is being displayed. These can be edited to show different elements in the same way as with C arrays.
If the program has any common blocks, these are shown under a Common blocks object in the display area. This can be expanded to show the list of common blocks, and individual common blocks can be expanded in turn to show the variables. If a given common block is declared differently in different functions, each different declaration gets its own entry in the list. Thus you might see :
Common blocks common /supp_defs/ (as defined in MAIN) common /supp_defs/ (as defined in foo)Fortran 90 user defined types are treated in much the same way as C structures. You can recursively expand them to follow linked lists and such.
If you are using Fortran 90 modules, ups adds a Modules object to the display area. You can expand this to show a list of modules. Module names can be expanded in their turn to show a list of functions and subroutines defined within the module. In the current version module variables are not displayed under the appropriate module heading; instead they appear under a common block entry. This will be fixed in a future release.
There is currently no support for interpreted code under Fortran. Nor can you add Fortran expressions to the display area. This will be fixed if and when someone writes a Fortran interpreter for ups.
SUPPORT FOR C++
Ups provides reasonable support for debugging C++ code compiled with cfront version 3, the Sun SC4 ompiler, and the GNU g++ compilers.
For C++ code, classes are shown as structs with the methods invisible. Function and variable names are demangled. The function stack and the breakpoint list use the class::method syntax. A restriction is that it is not possible to debug class templates. To debug executable code in header files, such as accessor functions defined in the class definition, turn off in-lining when compiling.
Function names in wrapper modules are unmangled and present no problems.
When you click on symbols in C++ source, ups searches local variables, and if that fails, it searches fields in the this pointer, and finally it searches for globals. In addition it searches in all unions for matching components - that is, the union tag does not have to appear in the source. When breakpoints are set on overloaded methods in C++ code, ups queries whether to place breakpoints on all matching names.
The tags operation works fairly well for C++ code. This is the facility that allows easy navigation through source code by simply clicking on a function name. You can click on methods and it will usually take you to the source. The back button returns to the original code. The target needs to be running to get it to work so it can look up the classes of variables. It won´t always get it right for inherited or virtual methods, but it is still a quick and useful way of navigating the code. You may have to click twice sometimes to first get it read a variable. If the source is in a library with no debug information, the message line will show the method name in the library.
In add expr and breakpoint code you can cast to un-typdef´ed structs, including classes in C++. Examples are (Class*)name where name is a variable, or (Class*)0x765678 for a numeric address. If you want to cast to a class that is undefined in the current context, try an add expr for the source file where the constructor is defined. This generally works, at the file level, but not always. It should always work for add expr in the constructor though. If you don´t know which file the constructor is defined in, enter the constructor name in the top typing line and press RETURN or ESC. The file name will be displayed just above the source window. You can then expand the source file list to find the file, select it, and enter the add expr code.
When a class is expanded in the display window, members of other classes are show as struct class_name <member> value or perhaps as undefined struct class_name <member> value. The class of the member is therefore the struct name, and the methods for that class can be listed as shown above.
You can set breakpoints on cout statements in C++ code in ups by breaking on the overloaded << operator. The general form of setting breakpoints in the display window of ups is :
<filename>:functionThe simplest way of breaking on cout statements in C++ code is :
ostream::operator<<Output can be flushed with a call to ostream::flush(&cout).
Similarly, in breakpoint code, character output can be sent to cout with the following syntax :
You can include standard sequences such as \t and \n in the text.ostream::operator<<(&cout, "some text");For character input, the syntax is similar :
istream::operator>>(&cin, &buffer);where buffer is some suitable character storage. Note that the code is linked with just the first overloaded methods in the iostream libraries, which is typically (const char*), so it won´t work for other data types.
Application defined operator methods can have breakpoints set in the same fashion. Ups asks whether to place breakpoints on all matching strings, so a string like class::operator can place breakpoints on all operator methods of the class. If you just want a particular one, such as ==, then add this at the end, i.e. class::operator==.
For cfront compiled C++ code, clicking on a variable name in the source window will case ups to find all matching names, including matches in the implicit this pointer as well as automatics.
INITIALIZATION FILE
The debugger reads an initialization file of name .upsinit in the current directory or, if that does not exist, the users home directory, upon invocation.
There are four basic commands that can be specified in the file. These are
use <directory> specify path to search for sources load <string> specify library to load noload <string> library not to load when reading symbols break function set breakpoint in function By only loading the minimum standard libraries, ups will start a lot faster. Other libraries can be loaded on the fly by selecting Target, then Load library, or by selecting an unloaded library name in the stack trace.
An example file is:
load *libc.so* load *libC.so* load /usr/lib/lib* load /usr/openwin/* load /usr/platform/* load /usr/dt/lib/* # for target specific libraries: load ./* load ../*The initialization file is also convenient for adding new source paths or loading additional libraries on the fly.
The source paths are needed for Centerline C++ because clcc typically creates C files in temporary directories, and the symbol tables suggest that this is where the parent C++ files are too. This is not a problem for SC4 or g++ however. The use command is equivalent to the colon separated list of directories that can be given on the command line for invoking ups, or during debugging with the add source path caption.
The load and noload allow you to just load symbols for the debugging area of interest, instead of always loading everything.
By ignoring all libraries of no interest, ups can be attached to even large targets (10s of megabytes) quite quickly. When all the long C++ names are ignored, the debugger is as quick as it was before with a pure C target in respect to setting breakpoints are examining data.
A caveat with using noload is that this causes ups to skip all information for the specified library, so functions and files for unloaded libraries will be invisible. Attempts to set breakpoints on such functions will results in no such function messages, and the files will not appear in the source file list. By using load rather than noload, ups will not be affected by different sets of libraries that each target may have.
Note that ./ has the meaning of the directory of the target, not of the directory where ups was started.
The load and noload keywords cannot be used together. Specifying neither means that all symbols are loaded. Wildcards can be used at the beginning or end of the string.
You can see all the symbol table names that are loaded and not loaded by doing a setenv VERBOSE 1 before calling ups. Setting VERBOSE to NOLOAD causes to list just the libraries that are not loaded.
You can specify breakpoints with the syntax break function. Unlike the -record style syntax, this does not require a file or a line number, hence the same breakpoints will work on different versions of the target source, provided the functions exist. Ups will silently skip breakpoints that it cannot set. The limitation is that the breakpoint will always be set at the beginning of the function.
You can create more complex commands for the initialization file by using the undocumented -record command line option. An example is ups target -record ./.upsinit The record file must not exist before it is created. When ups is next invoked, with a command like ups target, it will read the commands in ./.upsinit if such a file exists, otherwise $HOME/.upsinit. The record mode does not support interactions with the output window menus at present, nor search menus with the source window, Similarly mouse button modifiers are not recorded. Such actions will be ignored when the file is read. The following is an example of an initialization file that sets the SIGBUS and SIGSEGV signals to accept :
select sghead menu sghead show_all_signals select sghead|sigbus addselect sghead|sigsegv menu signal toggle_accept_ignore select sghead menu sghead hide_all_signals menu pmenu quit_upsThe last line, to quit the debugger, should be deleted with a text editor after creation. Some of the most commonly used syntax is :
breakpoint filename func_name line_no
menu menu_name action
MULTIPLE LINKED FILES
Ups now with multiple linked files. For such files, at least two versions of the code exist in the target.
Ups makes all duplicate files visible, with automatic replication in the duplicate file of any setting or modification of a multiple linked function breakpoint. In this manner, all breakpoint code is kept identical between duplicate files, and all breakpoints should be honored.
What this means in practice when using ups is that multiple linked function files are listed twice in the source file listing. Either one can be used to set a breakpoint, and a second breakpoint will be created automatically in the duplicate file.
The following actions maintain this automatic shadowing :
- Selecting a file and setting a breakpoint with the right mouse button in the source window.
- Setting a breakpoint by selecting the Breakpoints header and then pressing the Add new caption (or Shift-left accelerator on the Breakpoints header).
- Deleting a breakpoint.
- Renaming a breakpoint (works for all transitions between single instance and duplicate functions).
- Changing the line number of a breakpoint.
- Changing the activation state of a breakpoint.
- Selecting a file and using the right mouse button menu in the source window to execute to here.
SAVING STATE
When you quit ups, it normally forgets things like breakpoint locations and the way your variables are displayed. This can be a nuisance, especially if you have added interpreted code, or typed long expressions into the display area. To preserve these settings, ups will optionally save state information when you quit it, and reload this information when you start it again.
In addition, a state file can be explicitly created or loaded at any time by selecting the target name at the top of the display region. This will create a menu with four captions: Load library, Save state, Load state, Drop state, and Rescan init file.
Clicking on Load library Invokes a dynamic submenu of unloaded libraries. Choosing one will load that library. If all libraries are loaded, no submenu is displayed, but a message indicates that all libraries are loaded. See the section INITIALIZATION FILE for information on specifying what libraries to load.
Selecting Save state prompts you for a file name in which to save the current debugger state.
Selecting Load state asks for a state file name which will be then loaded.
Selecting Drop state deletes the temporary state file that ups uses to save information about breakpoints and what data have been displayed during a previous debug session. If you have previously attached to a process, and have been looking at global variables that take some time for ups to find, you can stop the debugger scanning again for the variables on reattaching to a rebuilt target by using the drop state button when unattached. You may also want to use it when attaching to a different process.
Rescan init file will re-read your ~/.upsint file, if it exists.
How state is saved and restored
This section describes how this state is saved and restored.
If the directory ups-state exists in the current directory, ups will use it to store state information between sessions. This includes breakpoint locations (and the interpreted code, if any), and the state of the variables display.
The saved state is used in several ways :
State is saved to the file ups-state/xxx.state, where xxx is the last component of the path of the file you are debugging. You can also create the file ups-state/xxx.config (perhaps by copying ups-state/xxx.state). The .config file is read at startup by ups, but not written. Also, breakpoints in the .config file are automatically restored on startup.
- After starting ups, you can select Restore from the Breakpoints menu to put breakpoints back as they were from the previous session. Ups tries to put breakpoints back in the right places, but it can be defeated by major changes to the source code.
- The default for the Expand option for stack trace and source file entries is Like before. This adds variables as they were in the last time you looked at them. If the ups-state directory exists, the state of the variables display is remembered across different ups sessions.
- When you add a variable the display format (hex, octal etc.) is taken from the way it was last time you displayed the variable.
- The attributes for signal handling are restored (i.e., whether accepted, ignored, cause the process to stop).
In future releases you will be able to use the .config file to add environment variable settings, etc. Currently the only directive (other than things specifying breakpoints, saved variable and signal state) is auto-start which takes a single argument yes or no. The line :
in the xxx.config file means start the target running as soon as ups has started up.auto-start yesUps also looks for saved state in the file $HOME/.upsrc and .upsrc (in the current directory). Thus the full set of files is :
$HOME/.upsrcFiles later in the sequence can override earlier settings.
.upsrc
ups-state/xxx.config
ups-state/xxx.state
LOADING AND SAVING BREAKPOINTS
You can explicitly load and save breakpoints to files. To save breakpoints, select one or more in the display area, then select Save from the menu. You will be prompted for a file name. If the file already exists you will be asked whether you want to cancel the save, overwrite the file or append to it. The submenu controls whether breakpoints loaded this way get saved in a statefile.
Saved breakpoints can be reloaded by selecting Load File and then Load - bpts NOT saved in statefile or Load - bpts saved in statefile from the Breakpoints header menu.
SEE ALSO
cc(1), f77(1), ld(1), dbx(1), gdb(1)
BUGS
On the SPARC you can´t step or next through the return statement of a function returning a struct or union (functions returning pointers to structs or unions work fine). This is due to the peculiar and undocumented protocol that the SPARC uses for returning structs and unions by value.
On the SPARC you get surprising behaviour if you use in interpreted code a struct or union that is a formal parameter. Your interpreted code must be written as if the variable is a pointer to a struct rather than a struct. This is again due to the SPARC structure passing protocol.
The SPARC C compiler emits an inline loop to implement structure assignmemt for large structs. Because of the way next and step are implemented in ups you have to hit Next or Step several times to step over a line containing such a struct assignment. Workaround: use Execute to here to get to the next line.
If you change a binary while you are debugging it ups will get very upset (read: will probably core dump with a fatal error message). This is unsatisfactory and will be fixed in a future release.
Core files dumped from dynamic executables are incomplete which means that you can only examine the non shared parts of the binary.
The Stop button in the target menu doesn´t work if you are hitting lots of fragments of interpreted code that don´t stop the target.
ACKNOWLEDGEMENTS
The work to support Solaris 2 was made possible by the generous support of the following people (in alphabetical order):
Ian Edwards Panorama Software Corporation Paul Friberg Incorporated Research Institutions for Seismology Robert L. Prehn AT&T Bell Labs Daniel Quinlan University of Colorado Ricardo Telichevesky Cadence Design Systems, Inc. Frank Vernon UC San Diego Special thanks to Dan Quinlan for all the work he put into organising the project.
The regular expression matching algorithm was written by Ozan S. Yigit of the Department of Computer Science, York University.
AUTHORS
Mark Russell, University of Kent.
Original version for the ICL Perq and many of the important ideas by John Bovey, University of Kent.
ENHANCEMENT AUTHORS
Ups includes fixes and enhancements by numerous people, including :
Rod Armstrong
Russ Browne
Ian Edwards
Daniel M. Quinlan
Callum Gibson
Craig Amey
Tom HughesFor a full list of contributors to recent releases see the CHANGES file supplied with ups.
Originally generated by manServer from ups.man using man macros. Subsequently hacked about by Ian Edwards.
UPS (1) May 2002