UPS(1) UPS(1)
NAME
ups - X11 and SunView based source level C debugger
SYNOPSIS
ups target [corefile|pid] [[:]srcdir[:srcdir]] [-a target-
args]
DESCRIPTION
Ups is a graphical source level debugger for the C pro-
gramming language running under the X11 and SunView window
systems. It supports both run time debugging with break-
points and post-mortem 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 pro-
gram'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 exe-
cuted.
Ups makes heavy use of direct manipulation and feedback.
When you add a breakpoint it is shown as a pseudo C state-
ment (#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.
GETTING STARTED
This section gives step by step instructions on how to use
ups on a small example C program. The idea is to get a
feel for how to use ups without getting bogged down in
details. After following the instructions here you should
be able to explore a little on your own and then be ready
to have a look at the reference material that follows.
Here is the sample source code:
struct argst { char *aname; struct argst *anext; };
struct argst *listhead = 0;
void stash(name)
char *name;
{
struct argst *a;
char *malloc();
a = (struct argst *)malloc(sizeof(struct argst));
a->aname = name;
a->anext = listhead;
listhead = a;
}
16 March 1991 1
UPS(1) UPS(1)
int main()
{
stash("foo");
stash("bar");
}
We skip error checking code here in the interests of
brevity. Put a copy of the code above into a .c file
(e.g. sample.c) by cut-and-paste or by snarfing the lines
from the file that contains this manual page. If you have
the source directory of ups around you will find this code
below there in the file ups/doc/sample.c.
Assuming you have a copy of the above code in a file and
you are sitting at a workstation or X terminal and have an
X or Sunview session running, here is what you do:
o Compile and link the code with the -g flag to cc(1) or
gcc(1).
The -g flag directs the compilers to include extra
symbol table information in the object file that is
needed by debuggers.
o Give the command `ups a.out' (or whatever you called the
object file). After a short pause a window will be cre-
ated; the details obviously depend on your window manager.
This is the simplest way of invoking ups. For a
complete description of the command line flags and
arguments see UPS COMMAND LINE ARGUMENTS.
In the window you should see a display divided into
various rectangular boxes and menus, with two large
regions in the upper and lower halves of the win-
dow. The top region is the display area - it con-
tains captions looking roughly like:
Target a.out
a.out
Signals
Environment
Untyped variables
Source files
Functions
Breakpoints
In the lower region you should see the start of
main() displayed. Note: the layout of the window
is explained in detail in a later section.
o Move the mouse cursor over the Breakpoints caption in the
upper region, and press and release the left mouse button.
16 March 1991 2
UPS(1) UPS(1)
You should see two things happen: the caption is
inverted to show that it is selected, and a menu
appears near the top of the window with the cap-
tions Add new breakpoint and Remove all break-
points.
All the objects in the display area (except Func-
tions) can be selected like this and have their own
menus. Selecting an object (or many objects) and
clicking on one of the commands in its associated
menu is the primary way of issuing commands to ups.
o Click (press and release) the left mouse button over the
Add new breakpoint menu caption.
You should see a line below the Breakpoints caption
looking like:
Function:| line:0
The vertical line is a marker bar - it indicates
where characters will appear when you type.
o Type `main'
You can use the delete key as you would expect to
fix typos. There are various other useful control
characters - see the EDITABLE FIELDS section for
details.
o Press ESC (the escape key).
This confirms the edit. You should see the text
#stop;
appear at the start of main in the source region.
Ups represents breakpoints as this fragment of
pseudo C. You can edit breakpoints to do things
other than just stop (e.g. call a target function
or only stop if a certain condition is true). This
is covered later in this section, and described
fully in the section ADDING INTERPRETED CODE.
You can also add breakpoints by pointing at the
appropriate line in the source region - this is
described later in this section.
o Click the left button over the caption Start at the left
hand side of the menu just below the display area.
This menu is the target control menu. Here is a
brief description of what the other commands in
this menu do (these are explained in more detail in
16 March 1991 3
UPS(1) UPS(1)
the CONTROLLING TARGET EXECUTIION section). As you
have just seen Start starts the target running.
Step and Next step execution over single lines of
code (Step steps into function calls, Next
doesn't). Cont makes the target process run until
it hits a breakpoint or exits. Stop stops a run-
ning target process, and Exit kills off the target
process, ready for another run using Start.
You should see the first line of code in main high-
lighted. This means that execution has stopped
just before this line. If you look at the display
area you will also see that a new line has appeared
under the Functions object. This should look like:
main sample.c:18
This shows that you are stopped at line 18 of sam-
ple.c in function main.
At this point you are in the usual state for ups:
you have the target stopped, with the line that is
about to be executed highlighted in the source win-
dow and your current position in the source file
shown under the Functions object in the display
area.
o Click on Step in the target control menu.
The source display switches to function stash,
which you have just stepped into. You will also
see an extra line under Functions - the display
should look like:
main sample.c:18
stash sample.c:10
As you can see this is a stack trace, showing you
which function called which starting from main and
working inwards towards the function you are cur-
rently stopped in.
o In the source region move the mouse over the `a' at the
start of the highlighted line and click the left mouse
button.
You should see a line added to the stack trace,
making it look like:
main sample.c:18
stash sample.c:10
struct argst *<a> 0x4
This is one of the main strengths of ups: to see
16 March 1991 4
UPS(1) UPS(1)
the type and value of any variable that is visible
in the source window you simply click on its name.
This is showing that a is a variable of type struct
argst * with the value 4. Ignore the angle brack-
ets round the `a' for now - they will be explained
later. This is an uninitialised variable, so the
value you see will probably be different from this.
You will also notice that the menu near the top of
the display area has changed. Every object in the
display area has an associated menu, which is dis-
played when that object is selected. Ignore the
menu for now.
o Click on Step in the target control menu.
The value displayed for the variable a changes to
whatever is returned by malloc. This shows another
key feature of ups - displayed variables remain in
the display area as you step through the program
code so you can watch the values change.
o Now click the left mouse button over the displayed line
for the variable a.
The line will be inverted to show that it is
selected and a menu will appear as before near the
top of the display area.
o Click on Expand in the menu that was produced by the last
step.
You will see an entry added for each member of the
structure, giving a display under the Functions
object that looks something like:
main sample.c:18
stash sample.c:11
struct argst <a{0}> 0x60c8
char <aname{0}> *NULL
struct argst *<anext> 0x0
The member types and values are shown in the same
way as the structure pointer `a' itself. As before
the values are uninitialised, so the values you see
will depend on the exact behaviour of your malloc
implementation.
o Click on next in the target menu.
The highlighting in the source window will move on
to the next line, and the value displayed for the
aname field will change.
16 March 1991 5
UPS(1) UPS(1)
This sort of interaction is typical use of ups -
you expand structures to see members of interest,
and then step through the source code watching how
they change.
o Move the mouse over the highlighted source line, press
and hold down the right hand mouse button then release it.
When you pressed the mouse button you will have
seen a popup menu with the captions Add breakpoint
and Execute to here. You will also have seen an
arrow to the left of the menu pointing at the
source line you pressed the mouse over.
When you release the mouse button a breakpoint is
added just before the source line. You will see
the text #stop; appear.
This is the simplest and most common way of adding
breakpoints in ups. The normal sequence of actions
is:
o Type the name of the function you are inter-
ested in (or enough of it to uniquely iden-
tify it) and hit ESC (the escape key). The
source of the function is displayed in the
source window.
o Scroll the source to make visible the line
where you want to add a breakpoint.
o Add a breakpoint by clicking the right mouse
button over the source line.
o Click on Cont in the target control menu.
The target continues until it hits a breakpoint.
In this case the target stops in the second call of
stash from main. You will notice that in the dis-
play area the displayed value of aname has
changed.
o Click on Cont again.
The target continues to completion and exits. The
stack trace and variables disappear from the dis-
play area, and all the target control menu captions
except Start are greyed out to indicate that they
are unavailable while the target is stopped.
We are almost at the end of this example. These last
steps are to show how you can add printf calls (in fact
any interpreted C). The actions we are about to cover
are:
16 March 1991 6
UPS(1) UPS(1)
o Editing some interpreted C into a breakpoint.
o Scrolling the source window to show the other
breakpoint and removing it.
o Re-running the target to see the effect of the
interpreted code.
o Move the mouse over the `#stop;' text that indicates the
breakpoint in the stash function and click the middle
mouse button.
You should see a marker bar (a thick vertical bar)
appear. If it is not at the end of the `#stop;'
text then click the middle mouse button further to
the right.
o Use the delete key to delete the `#stop;' text.
o Type the following text: $printf("Setting a->aname to
%s\n", a->aname);
$printf is a built in ups function with an inter-
face almost identical to printf except that it
sends output to an region in the ups display.
o Hit ESC (the escape key)
If you haven't made any errors ups will silently
accept the line and the marker bar will disappear.
If you have made a syntax error ups will beep, give
you an error message and put the marker bar at the
point of the error. You can then correct the
error.
o Press and hold down the left mouse button in the scroll
bar to the left of the source window, and with the mouse
button pressed move the mouse button a few pixels towards
the top of the window.
You should see the source text scrolling slowly
upwards. The more you move the mouse from the
place you first pressed it, the faster the source
scrolls.
o When you see the source of main appear in the source win-
dow release the mouse button.
The scrolling will stop.
o Click the left mouse button on the #stop at the start of
main.
16 March 1991 7
UPS(1) UPS(1)
You will see the breakpoint entry in the display is
highlighted, as well as a menu with the captions
Remove and Source near the top of the window.
o Click on Remove in the menu
You will see the breakpoint entry in the display
area disappear, along with the #stop; line in the
source window.
o Click on Start in the target control menu.
You should see a third subregion appear in the dis-
play. This looks similar to the source window,
with a controlling menu above it and a scroll bar
on the left hand side.
This is the output region. It is where output from
the built in function $printf appears. This region
appears the first time $printf is called by inter-
preted code.
You will see that the text
Setting a->aname to foo
Setting a->aname to bar
has appeared. This was produced by the interpreted
code that you added.
Note that the target ran to completion without
stopping. A breakpoint only stops the target if
the pseudo C statement #stop is executed. This
lets you add conditional breakpoints simply by
putting an if statement around them.
One final point: you can call target functions
(like stash in this example) from interpreted
breakpoint code. This is often used to call printf
in cases where you do want the debugging output
interspersed with the target program's output.
Here endeth the example. It certainly hasn't covered all
of the features of ups, but hopefully it has given you a
feel for the way it works. Some basic points:
o The two important areas in the display are the dis-
play area (top) and the source region (bottom).
o The display area contains captions representing
objects of different types.
o You can select an object by clicking on it with the
left mouse button.
16 March 1991 8
UPS(1) UPS(1)
o Each different object type has an associated menu
which appears near the top of the ups window when
the object is selected.
o Commands selected from these menus act on the cur-
rently selected objects.
o The source region displays the currently executing
source code, with the line that is about to be exe-
cuted highlighted.
o You can add any variable to the display area by
clicking on an instance of it in the source window
with the left mouse button.
o You can add breakpoints by pointing at lines of
source.
o You can edit breakpoints to add printf statements
and conditional breakpoints.
o You can expand and collapse structures to explore
data structures.
o Variables remain in the display area as you step
through the code so you can watch the values
change.
The rest of this manual page gives a complete description
of ups . You should probably skim through it at first
reading before playing with ups on some of your own code
for a while. When you are more familiar with ups reread
these sections in more detail.
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]
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 argu-
ment 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).
16 March 1991 9
UPS(1) UPS(1)
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 directo-
ries 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.
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. It won't make much sense unless you are also
looking at an ups window.
o At the top of the window on the left is the typing
line. On startup a vertical bar known as a marker
bar is shown. Typed characters appear in this
region, and some ups commands use the text in this
window as an argument (e.g., the command to search
for a regular expression in a source file).
o Below the typing line is the dynamic menu area. On
startup this area is greyed out. See THE DISPLAY
AREA below for a description of the dynamic menu.
o Below the dynamic menu area is a region where mes-
sages from ups appear (usually with a beep).
o To the right of the above three regions is a mouse-
hole. This has a representation of the three mouse
buttons, and captions for each button saying what
that button will do. The captions change as you
move from region to region, reflecting the fact
that the mouse buttons have different functions in
different regions.
o Below the preceding four regions is the display
area - a large region used to display and investi-
gate the current state of the target. There is a
16 March 1991 10
UPS(1) UPS(1)
scroll bar to the left of the display area. See
THE DISPLAY AREA.
o Below the display area is the target menu. This
has a set of commands for controlling target execu-
tion. See CONTROLLING TARGET EXECUTION below.
o Below the target menu is the source menu, with a
set of commands for managing the source region,
which is below this menu. There is a scroll bar to
the left of the source region. See THE SOURCE
REGION below.
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 releas-
ing 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 simultane-
ously 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 dis-
play. For example, when you expand an entry in the stack
16 March 1991 11
UPS(1) UPS(1)
trace all the local variables for the function it repre-
sents 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.
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 also 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. To the right of this is the source
region menu with commands back, search, up and down. The
up and down commands scroll the source region up and down
half a page respectively - they are an alternative to the
scroll bar for paging through a source file.
The search command is used to search for regular expres-
sions (using the same syntax as grep(1) patterns) in the
currently displayed source file. First type in the pat-
tern 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
16 March 1991 12
UPS(1) UPS(1)
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 function name
in the source window to display the source for that func-
tion (this is similar to the tags facility in vi(1)). Ups
maintains a stack of where you've 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.
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. 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
(e.g. `*foofunc*') 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.
EDITABLE FIELDS
All editable fields in ups work in the same way. To start
editing you click the middle mouse button over the
editible text. A vertical marker bar appears - characters
that you type appear to to the left of the marker bar.
You can reposition the marker bar by clicking in the new
position with the middle mouse button.
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 activ-
ity. The final way to confirm an edit is to type ESC (the
escape key).
To paste the current window system cut buffer, click on
the middle mouse button with the shift key down.
When you try to confirm an edit ups checks that the new
field value is reasonable. If not you get an error mes-
sage and you are left in the edit. An immediate second
attempt to quit abandons the edit and restores the origi-
nal field value.
16 March 1991 13
UPS(1) UPS(1)
The following special characters are recognised while
editing text:
^C (control-C)
Cancel the edit and restore the original text.
DEL (the delete key)
Delete the character just before the marker bar.
^U Delete the text from the start of the line to the
marker bar.
ESC (the escape key)
Confirm the edit.
^H (backspace)
Move the marker bar back one character.
^L Move the marker bar forward one character.
Note: Don't resize the ups window in the middle of an edit
as this cancels the edit. This misfeature will be fixed
in a future release.
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. Getline is stopped at line 21
(which is yet to be executed).
When the target stops, the source of the innermost func-
tion 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:
o Click the left mouse button over a line in the
stack trace. The line is highlighted, and a menu
16 March 1991 14
UPS(1) UPS(1)
appears near the top of the window with the cap-
tions Expand, Collapse, Add expr and Source.
o Click on Source in the menu. The source corre-
sponding to the selected line in the stack trace is
shown, with the line that is currently executing
highlighted.
In this way you can see exactly where the target is
stopped at any level in the stack.
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 con-
trol the execution of the target.
As well as selecting individual variables to be shown, you
can add all the local variables of a function in the stack
trace to the display. Select the function in the stack
trace whose variables you wish to see, and select Expand
from the menu produced. To remove all the variables
select Collapse.
16 March 1991 15
UPS(1) UPS(1)
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 con-
tains 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 and Source 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.
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.
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
Step 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. 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 dis-
played source. If you click on a function in the stack
trace and select Source to display its source, a
16 March 1991 16
UPS(1) UPS(1)
subsequent Next or Step moves to the next line of the dis-
played source. This makes it easy to get out of a func-
tion 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.
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 and Execute to here. 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 tempo-
rary 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 with-
out having to set up and remove breakpoints.
The other command on the popup menu, Add breakpoint, adds
a breakpoint at the line of source you pointed at. Unfor-
tunately, 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.
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.
The Exit 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 tar-
get process (unless you attached ups to a running process,
in which case ups detaches from the process and leaves it
to continue unmolested).
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 argu-
ments other than the name of the target.
16 March 1991 17
UPS(1) UPS(1)
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 use-
ful 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 for-
mat. 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 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)..
Pointers
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
16 March 1991 18
UPS(1) UPS(1)
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
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 the `>' and '<' keys.
When editing an array subscript, the '>' key adds one to
the subscript value and displays the new element. Simi-
larly, the '<' key subtracts one from the subscript value.
Using these keys you can rapidly scan up or down an array.
Vi users can use 'j' and 'k' instead of '>' and '<'.
Structures
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 struc-
ture members are indented to make it clear which structure
they belong to.
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 EXPLORING LINKED DATA STRUCTURES
section below.
16 March 1991 19
UPS(1) UPS(1)
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 struc-
tures below the selected one.
Changing formats
By default integer variables are displayed in decimal and
pointer values are shown in hex. You can change the for-
mat 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 NUL terminated string.
Floating point values are shown in the conventional nota-
tion (using the printf %g 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.
Duplicating and deleting entries
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 sev-
eral 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.
Use of typedefs
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:
typedef struct foos {
int x;
int y;
} foot;
16 March 1991 20
UPS(1) UPS(1)
foot *f;
then clicking on variable f will add a line like:
foot *<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 cap-
tions 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 mem-
ory 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 NUL ('\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 dis-
play 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
16 March 1991 21
UPS(1) UPS(1)
have finished type 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.
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 appro-
priate 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.
You can `bump' numbers in expressions in a similar way to
array subscripts. Hitting ^J (control-J) over a number
while editing an expression increases the digit to the
right of the marker bar and displays the new value of the
expression. Similarly ^K (control-K) decreases the digit
to the right of the marker bar an redisplays the expres-
sion value.
Expressions are reevaluated like variable values every
time the target stops. They also disappear like variables
when the target exits or the function they are attached to
returns. In a future release of ups expressions in the
display area will be made less ephemeral.
Expressions have the same menu associated with them as
variables, and you can have both expressions and variables
in the same selection. The `*' and `&' menu commands
don't work on expressions, but all the others 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't call target functions or modify target data in a
display area expression (thus operators like `++' are
illegal).
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 func-
tion. 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 break-
point. The default breakpoint action - stopping the tar-
get - is represented as a fragment of pseudo C code. This
16 March 1991 22
UPS(1) UPS(1)
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 = %d\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->pname, "foo") == 0)
#stop;
In the above examples, the function calls (printf and str-
cmp) 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 diag-
nostic output is that the output is mixed up with the nor-
mal 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
16 March 1991 23
UPS(1) UPS(1)
default ups format for the type. The `%v' format charac-
ter will print symbolic names for enum values and function
pointers (i.e. you will get output like RED and
closecallback 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 break-
point 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 reinitialised every
time the target is started. Automatic variables are
uninitialised and do not preserve their values between
separate executions of breakpoint code.
You can mix C interpreter variables with real target vari-
ables 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 inter-
preter 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 some-
times possible to indirectly affect the flow of control by
judicious changes to variable values.
You cannot add C interpreter variables to the display;
clicking the left mouse button anywhere over breakpoint
code just selects the corresponding breakpoint object in
the display area. This may change in future releases of
ups.
[ 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 inter-
preter copies sizeof(T) bytes to the target address space
16 March 1991 24
UPS(1) UPS(1)
and passes a pointer to that copy. When the target func-
tion 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 struc-
tures 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 ele-
ments. There is a more selective method of expanding
lists and trees which lets you easily see just the ele-
ments you want.
Suppose you have a structure declaration like this:
struct linkst {
struct linkst *liprev, *linext;
int likey;
};
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 liprev, 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 .linext followed by ESC will add the
linext field of linkptr to the display and select it, and
deselect linkptr. Typing ESC again will add the next ele-
ment 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
.likey .linext
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
16 March 1991 25
UPS(1) UPS(1)
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:
.likey @linext
and keep typing ESC to walk down the list.
One last wrinkle: if you add `#nnn' to the end of the typ-
ing 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 the previous section)
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 ^J and ^K as described in the previous section 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]linext
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.
ENVIRONMENT VARIABLES
By default the target inherits the same set of environment
variables as ups . You can change this using the Environ-
ment object in the display area. Any changes to the tar-
get 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.
16 March 1991 26
UPS(1) UPS(1)
If you wish to abandon any changes you have made to the
environment select Reset env. This resets to the environ-
ment 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 sig-
nal 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.
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 argu-
ments. The currently recognised flags are:
-iconic
Start up as an icon rather than as a window.
16 March 1991 27
UPS(1) UPS(1)
-display displayname
Create a window on the named display rather than
using the value of the DISPLAY environment vari-
able.
-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 fetch-
ing 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.
-wnrecord filename
Record mouse and keyboard events in file filename.
-wnreplay filename
Read mouse and keyboard input from file filename
rather than the mouse and keyboard. The file file-
name must have been created with the -wnrecord
flag in a previous session.
-wnreplaywarp
When replaying events with -wnreplay, 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
16 March 1991 28
UPS(1) UPS(1)
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.
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 win-
dow. The default under X11 is `-*-fixed-bold-r-
normal--15-140-*-*-*-*-*-*'. Under SunView the
default is `screen.b.14'.
Foreground
The color of the foreground pixel. The default is
whatever the BlackPixel macro returns for the dis-
play.
Background
The color of the background pixel. The default is
whatever the WhitePixel macro returns for the dis-
play.
ReverseVideo
If this is set (to anything) it has the same effect
as the -rv flag.
Geometry
The size and (optionally) position of the ups win-
dow. The default is to suggest to the window man-
ager a window 650 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.
EditlinesColor
The color used for editable text in the source win-
dow. The default is yellow.
16 March 1991 29
UPS(1) UPS(1)
HighlightColor
The color used to highlight variables in the dis-
play area whose values have changed since the last
time the target stopped. The default is yellow.
MouseholeWidth
The width of the mousehole in pixels.
PermanentMenuWidth
The width of the `Quit' menu in pixels.
ScrollbarWidth
The width of all the scroll bars in pixels.
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).
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 val-
ues) results in a 50-50 split.
OutwinPercent
The percentage of the window height used for the
output window if and when it is added. The default
is 50 (which actually means a third of the total -
see the note about SrcwinPercent above.
WantTypedefs
If this is set to `no', then ups will not attempt
to use typedefs in display area variable declara-
tions. 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
16 March 1991 30
UPS(1) UPS(1)
exactly the same effect as the -mono flag (see
above).
SEE ALSO
cc(1), f77(1), ld(1), dbx(1)
BUGS
On the SPARC you can't step or next through the return
statement of a function returning a struct or union (func-
tions 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 surpising behaviour if you use in
interpreted code a struct or union that is a formal param-
eter. 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.
The Step command does not step into routines from SunOS
shared libraries - it steps over them as if Next had been
selected. Breakpoints in shared library routines do work,
however. 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.
If you resize the ups window while you are in the middle
of an edit, the edit is cancelled.
There should be a way to remember breakpoint code and
other configuration information between sessions. This
will be added in a future major release.
Expressions and variables in the display area should be
less ephemeral.
ACKNOWLEDGEMENTS
The regular expression matching algorithm was written by
16 March 1991 31
UPS(1) UPS(1)
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.
16 March 1991 32