PowerAda Commands to Control Program Execution

From OC Systems Wiki!
Jump to: navigation, search


The commands in this section control the debugger's execution of the target program. For example, you can use them to inform the debugger when and where to suspend and continue program execution for debugging purposes and to specify what debugging information should be captured.

Setting and Displaying Breakpoints: BREAK

This command allows you to set and examine places in the source program where execution will be suspended.

There are two basic ways to specify where a break is to occur in a program: by a simple line number (or extended line number when debugging generics), or by a sublibrary entry or exit. For example:

break 42,sec/tape_handler
break sorter:exit

In the first example, a breakpoint is set at line 42 of the secondary unit of TAPE_HANDLER; in the second, a break is set at the exit of subprogram SORTER. A breakpoint occurs every time you execute the code where the breakpoint is set. Optionally, you can set conditions or use counts to bypass some of the breakpoints. You can also set multiple breakpoints at a single location with a different condition on each one of them.

When a location at which a breakpoint is set is reached and all conditions are satisfied, the debugger stops the target program and allows you to examine and change the state of the program and its variables. You can resume program execution with the CONTINUE command.

Breakpoints remain set until you remove them with the UNBREAK command. Breakpoints can be set only after the target program has been started with the LOAD command.

Syntax

The various forms of syntax for using BREAK to set breakpoints are:

break [{LineNumber | ExtendedLineNumber} 
      [, CompilationUnit]
      [Condition][then Command]]
break [CompilationUnit.]Subprogram[(Position)]:entry
      [Condition] [then Command]
break [CompilationUnit.]Subprogram[(Position)]:exit
      [Condition] [then Command]

where:

LineNumber is an integer that identifies any line in the compilation (not the compilation unit) where you can set a breakpoint. This is used when you are not debugging generics. ExtendedLineNumber is an ordered sequence of integers separated by periods and followed by an optional s as Integer.Integer[s].... The leftmost Integer is any line in the compilation where you instantiate the generic. The second Integer, when followed by an s, identifies the line in the specification of the generic that is being instantiated. The second Integer (without the s) specifies the line number of the body of the generic that is being instantiated. = See "Debugging Generic Instantiations" in Chapter 6 for a description of the extended line number. For example:break 42.7,sec/tape_handler
-- breakpoint in the body of
-- a generic instantiation CompilationUnit is any compilation unit in the program being debugged or, if omitted, the current unit. Condition specifies the condition under which you want that breakpoint to cause program execution to stop. Such a condition could be "at every third occurrence", or "each time....", or when an expression is true. Condition is useful if you don't want the target to stop every time a location is reached. Condition has the following syntax:[count N | every N | when Expression] Using COUNT causes the program to stop only when the location has been reached the specified number of times. Using EVERY causes the target program to stop each time the location has been reached some multiple of the specified number of times. Note that specifying no condition is equivalent to specifying every 1. For example, entering:break 16 count 5 causes the program to stop the fifth time line 16 is reached, while entering:break 16 every 5 causes the program to stop every fifth time (the fifth, tenth, and fifteenth times, and so on). Note that the number specified is relative to the current program state: if line 16 has already been reached three times, the commandbreak 16 count 4 causes the program to stop the seventh time line 16 is reached. Using WHEN Expression causes the program to stop only when Expression is true. For example,break 16 when a=4 causes the program to stop when the variable a contains the value 4. Subprogram is the name of the subprogram in the compilation at which a breakpoint upon entry or exit is to occur. The subprogram name must be followed by :ENTRY or :EXIT. For example:break display:exit Position is used to distinguish between overloaded subprograms. Position must be enclosed in parentheses. For example, the commandbreak display(2):exit sets a breakpoint at the exit of the second subprogram named DISPLAY that is in the compilation. 'then Command
can be used to specify a debugger command to be executed when the breakpoint is encountered. This command is executed as soon as the breakpoint is activated. The debugger will not prompt for further commands until the execution of this command is completed.'

Displaying Breakpoints

Entering BREAK with no parameters displays a list of all currently set breakpoints. For each breakpoint, the debugger displays the line number (which can be an extended line number when you are debugging generic instantiations), the compilation unit name, and the enclosing program unit name. Locations that have multiple breakpoints are displayed only once; the condition of each breakpoint is displayed separately, preceded by a number that can be used in the UNBREAK command to remove the breakpoint.

Counted breakpoints are followed by the number of additional times the location must be reached before the breakpoint stops the target program. If the program is stopped at a breakpoint, an asterisk (*) appears after the breakpoint that caused the program to stop. Finally, a dash (-) follows COUNT breakpoints that have already stopped the program. These breakpoints will not stop the program again during the current execution.

Determining Where to Set A Breakpoint

You can use the SOURCE command to determine which source lines can have breakpoints set on them. To set a breakpoint at the entry or exit point of an overloaded subprogram, you must specify the position of the subprogram within the compilation along with the subprogram name. The SHOW SUBPROGRAMS command displays a list of all subprograms with a specified name and their positions. Note: The entry point of a subprogram is often equivalent to its first executable line.

See "Specifying Locations for the Debugger" for a description of how the debugger indicates on a source display those lines where you can set breakpoints. The following guidelines specify the location and behavior of breakpoints:

  1. A breakpoint on a line is associated with the first statement that starts on that line.
  2. Breakpoints on WHILE loops occur every time the condition is evaluated.
  3. Breakpoints on FOR loops occur before entry into the loop.
  4. Breakpoints cannot be set at LOOP statements, but they can be set at statements within a loop.
  5. A loop label is treated as the beginning of a loop control statement.
  6. A breakpoint cannot be set on the condition evaluation of an ELSE or ELSIF.
  7. You cannot set breakpoints on lines with BEGIN and closing designators (for instance, END, END IF).
  8. Occasionally the debugger will indicate that you can set a breakpoint on a line, but a breakpoint set at the line is never executed or is executed at an unexpected point during program execution. The reason for this behavior is that the line has been associated with compiler-generated code that is executed at some other point in the program.
  9. Breakpoints may only be set after the target program has been started using the LOAD command.
  10. Breakpoints remain set until they are explicitly removed by the UNBREAK command, even if you restart the program.

Setting a Breakpoint in Common Code

Sometimes, you need to set a breakpoint in common code executed by a number of tasks but only want to stop when a certain task is executing that code. You can do this by constructing a breakpoint that examines the value of the "view_task" debugger variable. For example, if you want to stop at a source line when the task fred is executing there, you would set a breakpoint like this:

BREAK 20,my_package WHEN view_task = "fred"

Completing Execution of a Subprogram: RETURN

This command allows one to execute the remainder of a subprogram and return to the point of its invocation. It does not allow one to specify return values for functions. Its syntax is:

return

Continuing Execution After Breakpoint: CONTINUE

This command allows the target program to resume execution after a breakpoint or after a trapped exception. Its syntax is:

continue

You can use CONTINUE after you have started the program with LOAD and before the program has ended. (The debugger reports when a program has completed after a CONTINUE command.) Enter CONTINUE when you are ready to resume program execution, such as after having set, displayed, or removed breakpoints or after examining variables. Execution then continues until one of these events takes place:

  1. The program stops because of a breakpoint (see BREAK and .BREAK).

  2. The program ends.

  3. An unhandled exception occurs.

  4. A handled exception occurs, and you are stopping the program at handled exceptions with the TRAP command

    For example, in the debugger session below, you set breakpoints at lines 64 and 73 in the unit PART2 and then enter continue to tell the debugger to proceed to the next breakpoint. After the breakpoint on line 64 is encountered, you remove it and enter continue to proceed to the next breakpoint:

Debug> break  64,part2
  Breakpoint set at 64,sec/part2 (task_activation)
Debug> break  73,part2
  Breakpoint set at 73,sec/part2 (task_activation)
Debug> continue
  64>            accept Dont_Call_Me;
  Breakpoint encountered at 64,sec/part2(task_activation)
Debug> unbr  64
Debug> cont
  73>            Called_Consumer_Type.Item := Item;
  Breakpoint encountered at 73,sec/part2(called_consumer_type)
Debug>

Changing the Default Compilation Unit: DEFAULT

Having a compilation unit identified as the default eliminates repetitive typing while you are issuing multiple commands to the debugger that refer to the same compilation unit. When you start the debugging session and enter run, the debugger sets the default to the body of the first sublibrary that receives control. Thereafter, each time the debugger stops the program at a breakpoint, it sets the default to the compilation unit in which the target program has stopped. The default remains until another breakpoint establishes a new compilation unit as default or until you reset the default by using the DEFAULT command.

The syntax of DEFAULT is:

default [CompilationUnit]

where CompilationUnit is the name of the compilation unit to become the default.

DEFAULT with no parameter displays the current default compilation unit. DEFAULT with a CompilationUnit parameter sets the current default compilation unit, overriding the default value set by the debugger. The DEFAULT command in the example below sets the default compilation unit to be the secondary unit of package SYS_STATS:

default sys_stats

Use of the WHERE command identifies the unit in which the target program was stopped so that you can reset the default to that unit.

Ending a Debugging Session: DETACH

detach

DETACH ends a debugging session but leaves the target program running, if possible Upon exiting the debugger, the log file is closed. If DETACH occurs in a script, the debugger closes the log file, ends, and does not process the rest of the script

Executing a Target Procedure: INVOKE

This command allows you to execute a procedure within the program being debugged from the debugger command line. The syntax for the INVOKE command is:

invoke [procedure name {"(" [parameters] ")"}

where parameters are the parameters to the procedure. Note that the parameters must be program variables not debugger variables. Note also that the procedure is executed and any global variables that the procedure may query or set will influence the outcome of the procedure.

This command works only with procedures. The ? command can be used to execute a function call. = See "Displaying the Result of a Function Call" for more information.

Loading the Target Program: LOAD

This command prepares a program for debugging. The program is actually executed when you enter the next CONTINUE command. The syntax for LOAD is:

load [Parameters]

where Parameters are input parameters to the program being debugged. Any parameter you pass must be an identifier, an integer, or a quoted string. The contents of a quoted string are then interpreted for quoting and split into multiple parameters in a Korn-shell fashion. The RUN command is provided for compatibility with earlier versions and has exactly the same effect as LOAD.

Note: You can use the -R option on adbg to redirect input, output or error when you are in the UNIX windows Environment. In the curses environment, you will not be able to perform I/O redirection for the target program. Here are some examples of the LOAD command:

load
load "-- This is passed to the target program"
load "'one string' ""one string"" -- multiple strings"
load  a  b  10  "hello world!" c
load  "a  b  10  hello world!  c"

When you issue the LOAD command, the debugger loads the target program and prepares for debugging. If the debugger cannot find the executable file, or if its attempt to load the program fails, the debugger reports an error and returns control of the program back to you. You can then issue any command that is valid to use prior to the LOAD command. In this instance, you usually issue the EXIT command.

If you reissue the LOAD command after the target program has completed execution, the debugger restarts the program, reestablishing all breakpoints that existed in the final state of the previous run. If you reissue the LOAD command while the target program is running, the debugger ends the current instance of the program you are debugging and restarts it. All existing source level breakpoints remain set for the new run of the program unless you explicitly remove them by using the UNBREAK command.

The ability to restart the program without exiting the debugger is useful for quickly returning to and debugging problem areas within the program. There is no limit on the number of times you can run the program.

Stepping through Source Instructions: SKIP, STEP

Both SKIP and STEP cause the execution of instructions corresponding to one or more Ada statements, after which the program stops. SKIP treats a subprogram call as a single statement and stops program execution at the statement immediately following the subprogram call. STEP executes every line of the Ada source, including the lines within the called subprogram. SKIP is more useful when you want to work only within the calling subprogram. For both commands, execution can be continued with the CONTINUE command.

The syntax is:

skip [N]
step [N]

where N is the number of source statements the debugger is to step through before its stops the programs. If you use either command without a number, the debugger advances one statement.

If the program stops outside of the Ada program the effect of either command is to cause the debugger to execute machine instructions until it arrives at an instruction associated with an Ada statement. You may continue execution with the CONTINUE command.

Monitoring Specific Variables: TRACK

The TRACK command executes a statement if a debugger variable changes. Its syntax is:

track [Variable then Statement]

Without the qualifiers, TRACK displays a list of active actions. The string Variable THEN Statement defines an action to take when the specified variable changes value.

After every command, the debugger checks tracked debugger variables to see if their values have changed. It then executes statements associated with the ones that have changed.

The debugger variables CURRENT_LOCATION and EXECUTION_COUNT are especially useful with this command. You can use assignment commands to change the value of a debugger variable with an attached action.

You can only associate one statement with each debugger variable. That statement, however, can be composed of an arbitrary number of commands by using a BEGIN...END structured statement.

Here are some examples of TRACK:

track
track execution_count then ? a
-- Show a's value whenever the program moves

Displaying and Setting Exception Traps: TRAP

Under normal circumstances, the debugger ignores exceptions. The TRAP command tells the debugger to report exceptions that occur as the Ada program executes. The syntax of the command is:

trap [ExceptionName | unhandled | all]

where ExceptionName is the Ada name of a specific exception to be trapped, UNHANDLED causes unhandled exceptions to be trapped, and ALL causes all exceptions to be trapped.

If you use the TRAP command with no parameters, the current status of exception trapping will be displayed.

When an exception is trapped, the debugger stops the program at the statement raising the exception, just as if a breakpoint had been placed there, and displays pertinent information about the exception. This information includes the name, reason, and (for handled exceptions) the next statement to be executed as a result of the exception.

The following is a sample report of a handled exception caught by using TRAP ALL:

Exception the_test.task_excp
Raised at 69,sec/the_test (raise_one)
Handled - program continues to exception handler
69:         raise Task_Excp;

The exception was raised on line 69 and program control proceeds to the correct exception handler.

The display of line 69 indicates that the program has stopped at that line and that the user can examine the stack at that point.

The following is a sample report of an unhandled exception:

Exception STORAGE_ERROR                  (Task_Stack_Failure)
Raised at address 00007A96
Unhandled - program is terminating.

This report provides a detailed reason, Task_Stack_Failure, for the standard STORAGE_ERROR exception. The source line or address given for an unhandled exception indicates the point at which the exception was first raised, in this case at a location with no source line information.

Note that all exceptions (unhandled or not) are caught before they are raised, so the program state can be examined at the point where the exception is raised.

Removing Breakpoints: UNBREAK

UNBREAK removes a .gif from the specified location; see BREAK and .BREAK for a description of breakpoint locations. Breakpoints can be removed from locations with multiple breakpoints either by specifying the condition of the breakpoint to be removed, or by giving the number listed before the breakpoint in the most recent breakpoint display. The forms of syntax for the command are:

unbreak   Location   [Condition]
unbreak   Location   [(BreakPointNumber)]
unbreak   [Location]   all

where:

Location is one of the following: {LineNumber | ExtendedLineNumber}[,CompilationUnit]
[CompilationUnit.]Subprogram[(Position)]:entry
[CompilationUnit.]Subprogram[(Position)]:exit
LineNumber, ExtendedLineNumber, CompilationUnit, Subprogram, and Position are as defined for BREAK. Condition is equivalent to: count N | every N | when Expression BreakpointNumber
is the breakpoint indicated in the previous break display. For example, unbreak display:exit(2) removes the second breakpoint at the exit point of subprogram DISPLAY. The command

unbreak [Location] all

removes all breakpoints from the specified location, or, if no location is specified, removes all breakpoints from the target program.

The following examples of UNBREAK commands remove the breakpoints set in the section describing BREAK:

unbreak 42,sec/tape_handler
unbreak display(2):exit
unbreak sorter:exit
unbreak 16 every 5
unbreak 16 count 5
        -- or --
unbreak all

Cancelling Variable Tracking: UNTRACK

The UNTRACK command removes variables from the list tracked by the debugger. Its syntax is:

untrack Variable

The Variable qualifier specifies the variable you no longer want tracked. For example:

untrack execution_count

After execution of this command, the debugger no longer checks the specified Variable for changes after each command. Use the TRACK command to specify a new action to be performed when the variable changes.

Removing Exception Traps: UNTRAP

This command removes exception traps previously entered with the TRAP command. UNTRAP ALL removes every trap and UNTRAP UNHANDLED removes traps of unhandled exceptions. The syntax of UNTRAP is:

untrap [ExceptionName | unhandled | all]

where ExceptionName is the name of a predefined Ada exception or a user-defined exception.

Giving a specific exception name to the UNTRAP command causes the debugger to remove a particular exception trap. UNTRAP can be used to remove the effects of a previous TRAP command. The command can also be used after a TRAP ALL command to specify a set of exceptions that is not to be reported by the debugger.

In the following examples, TRAP and UNTRAP are used to specify which exceptions are to be reported:

To set a trap for a particular exception:

trap constraint_error

To remove a trap:

untrap constraint_error

To report all exceptions except one:

trap all
untrap numeric_error