Using the graphical interface of debug

Learning to use the graphical debugger

The following section provides a tutorial for some of the more commonly used debugger features. It is based on the default configuration of the debugger, which consists of six windows: the Command, Disassembly, Event, Process, Source and Symbols windows.

The program being debugged is a simple macro processor that reads from standard input and writes to standard output. Macros may be defined in the input stream or on the command line. This program is one of several used in similar tutorial sessions for the debugger's command line interface. See ``Using the command line interface of debug'' for more details. Please read the following sections in sequential order.

A glimpse at the program macros

The source files making up the program are found in /usr/ccs/lib/tutorial. You may use those files to follow this session on your own terminal.

  1. Copy Main.c, Macro.c, Macro.h, and test1 from /usr/ccs/lib/tutorial into your home directory.

  2. Compile macros:
    cc -g -o macros Macro.c Main.c
    The screen displays the following:

  3. Try running the program:
    macros -DMAC=123 <test1 >result
    Warning, X redefined

  4. Look at the output with the cat command:
    cat result
    This is what you should have seen:
    this is a test

    this is a test test this is a test

    x 1 2 3 4 123

    Instead, this is what you will see:
    this is a test

    this is a test test this is a test

    x A1 123

The problem is that the macro A1 is not being expanded. The steps below describe how to find the source of this bug with the graphical debugger. The following debugging session focuses on the analysis of the lookup and insert functions defined in macro.c.

The debugging session

Given the background on the program macros and its problems, you are now ready to try the graphical debugger.

1. Starting the graphical Debugger

Make sure that you are sitting in front of an xterm window, running the CDE desktop. Access the debugger in one of the following three ways:

  1. If you are already in the desktop, click on the Debug icon from the Desktop_tools folder of the Application Manager.

  2. If you are at the shell prompt in an xterm window, type debug from the Command Line.

  3. If you have the File Manager on your desktop, click the right mouse button on the program you wish to debug, and select Debug from the popup menu.

For both of these methods, the Source window is displayed:

2. Choosing the program to debug

The ``Create'' command is used to get a program ready to run under the control of the debugger. This command is found under the ``Debug menu'' of the Source window.

NOTE: Throughout this tutorial session, placement of options is based on the default configuration. You may change the placement of any button, as well as the layout of the panes in the windows. See ``Configuration'' for details.

  1. Select Debug and the Debug menu popup is displayed.

  2. Select Create from the Debug menu popup and the ``Create'' window appears. Type in the name of a program that you wish to debug in the ``Command Line'' field. Since you want to debug the program macros in this session, enter:
    macros -DMAC=123 <test1 >test.out
    This is how the Create window should look like at this point:

  3. Click on the Create button or press <Return.>

    NOTE: To activate a selection from most of the popups, you can either click on the desired button or press the <Return> key.

The Source window now displays the following:

The ``Status pane'' on the top section of the window shows the current process. The ``Stack pane'' in the middle shows the stack trace for the current process, with a pointer next to the current frame. The ``Source pane'' at the bottom shows the source for the current function in the current process. These panes will be updated as the tutorial continues.

3. Creating events

lookup is the function that looks for macro definitions. Check to see if lookup is being called for A1 by setting a breakpoint (a type of ``stop event'') on lookup. The commands that create events are all found in the ``Event menu''.

  1. Select Event from the menus at the top of the Source window.

  2. When the event menu popup appears, select ``Stop on Function''. This will bring up a popup window displaying a list that contains the name of the executable file and all the shared objects making up your program; in this case the list contains simply and macros.

  3. Click SELECT on macros. That will make the debugger display in the lower half of the popup window a list of all the functions defined in the macros executable. Scroll through the list until you find lookup as shown in the following popup:

  4. Select lookup. Click on Stop on Function or press <Return.> For a shortcut, simply double-click the lookup item.
You have now created a stop event at every call to lookup.

NOTE: Breakpoints may be created with the ``Stop on Function'' and ``Set Breakpoint'' options. You may also set breakpoints by clicking the SELECT button in the left margin of a line in the ``Source pane''. Watchpoints may be created with the ``Set Watchpoint'' option in the Symbols window. Breakpoints and watchpoints are specialized forms of stop events; more powerful stop events may be created with the ``Stop'' popup window. See ``Stop expression'' for a complete description of the different types of stop events.

4. Running the program

The ``Run'' command allows you to start the execution of the program being debugged. You can access this command from the button bar of the Source window (or from the ``Control menu'' in any window). To use this command, select Run from the button bar at the top of the Source window. The debugger will let the process run until it hits the breakpoint on lookup. When that happens, the source window will look like this:

The Source pane now shows the source for the new current function. Note how the pointing finger is next to lookup in the Stack pane.

5. Examining symbols

The program has reached the stop event in lookup. Check to see what it is looking for by displaying what name points to using the ``Show Value'' popup. Show Value makes it easy for you to dereference a pointer.

  1. First bring up the Symbols window. The Symbols window displays values of variables visible from the current context. The information displayed for each variable includes its location and type.

    1. Select Next Panel in the button bar at the top of the Source window. This will display another set of buttons which are commands to bring up each of the other debugger windows.

    2. Select Symbols in the button bar to bring up the Symbols window.

  2. Double-click on name from the ``Symbol pane'' in the Symbols window to bring up the ``Show Value'' popup window.

    NOTE: This is not the most efficient way to bring up the Show Value dialog from the Source window, but was chosen to illustrate the use of the Symbols window. You could also bring up Show Value by

  3. The Show Value window will be initialized with the selected variable, and the Result area will show its value. Since name is a pointer, the value will be displayed as a hexadecimal address.

  4. To see what name points to, select the Expand button in the Show Value window. Since name is a pointer to a structure, the debugger will display all of the members of the structure.

  5. Close the Show Value window by clicking SELECT on the Close button.

6. Associating commands with events

The program may have to call lookup several times before macros calls it with A1. Checking what name points to every time the program stops at lookup could get tedious. You can tell debug to automatically print what name points to whenever the stop event triggers. You can also create a debugger variable to track the number of times lookup is called. Here is how you would do it.

  1. Select View in the Source window's Menu bar and the ``View menu'' popup is displayed.

  2. Select Set Value and the ``Set value'' popup is displayed. Type the following in the ``Expression'' field of the window:
     $ncalls = 1

  3. Press <Return> or click on the Set Value button.

  4. Select Event in the Menu bar. Select On Stop from the ``Event menu''. Type the following in the Commands screen of the ``On Stop'' popup:
     print name->string, ++$ncalls; run

    NOTE: See debug(1) for debugger commands.

  5. Click on the On Stop button. The command sequence will be executed whenever the process stops, allowing you to see how many times lookup is called before it reaches A1.

  6. Select Next Panel again in the button bar in the Source window to bring back the original set of command buttons.

  7. Select Run from the button bar to run the program again. The following notice will appear:

    Click on OK to continue. All the panes in the Source Window will be blanked out, indicating that the process has exited.

  8. Bring up the Command window to see the output of the Onstop event. Access this window as follows:

    1. Select the File button.

    2. Select Windows from the popup.

    3. Drag the mouse over to the submenu and select Command.

    NOTE: You could also access the Command Window by clicking SELECT on Next Panel in the Button Bar, followed by clicking SELECT on Command. The ``Windows'' submenu is simply an alternative way to bring up any of the debugger's windows.

    The Command Window shows you that lookup was called for A1 on the twentieth call.

7. Repeating the debugging session

Take a closer look at what is going on in lookup. Start up the program again and run it until lookup is called with A1:

  1. Click on the Source window and select Debug. The ``Debug menu'' popup is displayed. Select Create and you get the following:

  2. The ``Command Line'' field still has the text to invoke the program macros so all you have to do to recreate the program is click on the Create button. The Source window will now show you the new program macros (process p2), stopped at the first statement in main.

8. Removing events

The events that you created the first time through are still there. Check the events in the Event window. Access this window as follows:

  1. Select the File button and select Windows from the popup.

  2. Drag the mouse over to the submenu and select Event. The Event Window displays the following:

    You don't need those events this time so delete them. Select the events in each pane (by clicking on any column) as shown in the following window:

  3. Select Delete from the button bar in the Event window.

9. Creating an event on the nth call

Rather than creating a stop event on every call to lookup, you can request the debugger to create one on the nth call. Since the search was on the twentieth call to lookup, create a stop event that takes you there directly.

  1. Click on the Source window. (You can also do this from the Event window.) Select Stop in the ``Event menu''.

  2. Type lookup in the ``Expression'' field and 20 in the ``Count'' field of the ``Stop'' window to create a stop event.

  3. Click on the Stop button.

  4. Click Run from the button bar in the Source window to run the program again. The Command window comes up automatically to display the program's output:

    Note the warning message that X has been redefined.

  5. Make sure this is really the right call. Select View in the Source Window's Menu bar. The ``View menu'' is displayed.

  6. Select Show Value and type *name in the ``Expression'' field of the ``Show Value'' window. Then, click on the Show Value button. The window displays the following:

10. Stepping through the program

lookup maintains a binary tree of nodes that point to macro definitions. Step through lookup until you see whether or not lookup can find A1. Stepping through a program means executing the program one or several statements or instructions at a time. Here's how you do this:

  1. Select ``Step Statement'' from the Source Window's button bar until the program reaches line 90. This will take four steps and the Source window will look like this:

  2. Now look at the value of val in the Symbols window. It will be -1 (the value returned by strcmp(3C)). A return value of -1 means that the first string comes before the second string alphabetically, so the definition of A1 should be in the left branch of the tree.

  3. However, if you look at the value of node, you will see that node->left is zero. Check the value of node by typing *node in the ``Expression'' field in the ``Show Value'' window. Then, click on the Show Value button. The window displays the result:

  4. If you let the program go a little further, you will see that the left branch is empty. It stops looking and returns ``0'', which means that it couldn't find A1. Step through the program again by selecting ``Step'' from the ``Control menu'':

    Step three times by selecting Step Count Times and entering 3 in the count line.

  5. The Source window now shows the following changes:

  6. Since A1 is not in the binary tree, the problem is apparently further back in insert, when it was building the tree, so you will have to start over again.

11. Analyzing insert

Re-create macros by clicking on Debug in the Source window and selecting ``Create'' from the ``Debug menu''.

  1. Click on the Kill Processes From Previous Create to enable the option. Then, click on the Create button.

  2. Delete the stop event on lookup: select File and Windows to select the Event window as you did previously.

  3. Highlight the following line in the Event window:
    3 STOP  p3   lookup  20
    Select Delete in the button bar to delete the stop event.

  4. Add a new stop event on the fifth call to insert. (A1 is the fifth macro definition): select Stop from the ``Event menu''. Type insert in the ``Expression'' field and 5 in the ``Count'' field:

  5. Click on the Stop button or press <Return> to create the event.

  6. Run the program as you did previously. The Command window automatically pops up. The Transcript area of the Command pane displays the command and the result:

    The Source window will reflect the change. Note how the pointing finger is next to insert:

  7. Make sure it is in the right call by typing name->string in the ``Expression'' field in the ``Show Value'' window. ``"A1"'' is displayed in the ``Result of Evaluation Expression'' area of the Show Value window. Close the window by clicking SELECT on the Close button.

  8. Scroll through the source for insert in the Source window. You will see that nothing happens to the tree until it gets into the for loop. Set a breakpoint at line 48 (after the call to strcmp(3C)) by clicking on the line number in the left margin. Then run the program by choosing the Run option in the button bar. The Source window reflects the change:

  9. The value returned by strcmp should be -1, and it should go off down the left branch, just as in lookup.

  10. The Symbols window now shows that val is equal to -1. If you step twice more you will see that the program is making the assignment to the right branch, which explains why it couldn't find A1 later by looking down the left branch.

12. Exiting the debugger

Select ``Exit'' in the ``File menu'' to exit the debugger.

The following popup is displayed:

Click on the Exit button to quit the debugger.

Next topic: Exploring the debugger's panes
Previous topic: Invoking the debugger

© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004