Chapter 6. Controlling Program Execution
Prev |  | Next

## Chapter 6. Controlling Program Execution

A program typically runs until it exits or encounters an unrecoverable error. You can use `dbx`, however, to stop a program under various conditions, step through your program line by line, stop execution on receiving a signal, and execute conditional commands based on your program's status.

This chapter covers:

- “Setting Breakpoints”

- “Continuing Execution After a Breakpoint”

- “Tracing Program Execution”

- “Writing Conditional Commands”

- “Managing Breakpoints, Traces, and Conditional Commands”

- “Using Signal Processing”

- “Stopping at System Calls”

- “Stepping Through Your Program”

- “Starting at a Specified Line”

## Setting Breakpoints

Breakpoints allow you to stop execution of your program. Breakpoints can be unconditional, in which case they always stop your program, or conditional, in which case they stop your program only if a test condition that you specify is true.

| Note: All breakpoints halt program execution before executing the line on which they are set. Therefore, if you want to examine the effects of a line of code, you should set the breakpoint on the line of code following the one whose effects you want to study.

Each breakpoint is assigned a number when you create it. Use this number to reference a breakpoint in the various commands provided for manipulating breakpoints (for example, ```disable`, ```enable`, and ```delete`, all described in “Managing Breakpoints, Traces, and Conditional Commands”).

### Setting Unconditional Breakpoints

To set an unconditional breakpoint, you simply specify the point at which you want to stop program execution, using one of the following forms of the `stop` command:

`stop at` |  | Sets a breakpoint at the current source line.
`stop at` `line` |  | Sets a breakpoint at the specified source line in the current source file.
`stop in` `procedure` |  | Sets a breakpoint to stop execution upon entering the specified procedure.
`stop at` `file:line` |  | Sets a breakpoint in the specified file at the specified line.

| Caution: If your program has multiple source files, be sure to set the breakpoint in the correct file. To do so, you can explicitly set the source file using `dbx`'s `file` command (see “Changing Source Files”), or you can use the `func` command to go to a source file containing a specified function (see “Moving to a Specified Procedure”).

### Setting Conditional Breakpoints

An unconditional breakpoint is the simplest type of breakpoint; your program stops every time it reaches a specified place. On the other hand, a conditional breakpoint stops your program only if a condition that you specify is true. The two conditions that you can test are:

- Has the value of a variable or other memory location changed?

- Is a test expression true?

### Stopping If a Variable or Memory Location Has Changed

By including a variable clause in your `stop` command, you can cause `dbx` to stop if the value of a variable or the contents of a memory location has changed.

If you provide only a variable name in your variable clause, the breakpoint stops your program if the value of the variable has changed since the last time `dbx` checked it. If instead of a variable name, you provide an expression of type pointer,`dbx` checks the data pointed to. If the data pointed to is a structure, `dbx` checks that structure. If you provide an expression that's not of type pointer, `dbx` evaluates the expression and uses the result as an address in memory. The breakpoint stops your program if the contents of the memory location (32 bits) has changed since the last time `dbx` checked it.

The points at which `dbx` checks the value of a variable or memory location depend on the command that you use to set the breakpoint:

`stop` [`expression`| `variable`] |  | Inspects the value before executing each source line. If the expression is of type pointer, look at the data pointed to and watch until it changes. If the expression is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address). For example, consider the command:
    stop (struct s*) 0x12345678
This command checks the contents of the structure located at 0x12345678.
`stop` [`expression`| `variable`] `at` `line` |  | Inspects the value at the given source line. Stops if the value has changed. If the expression is of type pointer, look at the data pointed to and watch until it changes. If the expression is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).
`stop` [`expression`| `variable`] `in` `procedure` |  | Inspects the value at every source line within a given procedure. Stops if the value has changed. If the expression is of type pointer, look at the data pointed to and watch until it changes. If the expression is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).

### Using Fast Watchpoints

You can use fast watchpoints with the `stop` command. A fast watchpoint watches a specified variable or memory address without severely impacting the performance of the program being debugged.

In previous versions of `dbx`, the debugger had to single-step the process being debugged and check if the value of a variable had changed after each instruction. With fast watchpoints, the debugger uses a hardware virtual memory `write protect mechanism` to allow the program to run freely until the variable being watched changes. The program being debugged stops only when the virtual memory page containing the variable is written to. If the value of the variable being watched does not changed, `dbx` continues the execution of the process. If a `write` modifies a watched variable, `dbx` notifies you of the change.

Consider a small program that contains a global variable called `global`:

    stop global

This command causes the program to stop if the value of the variable `global` changes. The program runs virtually at full speed until `global` gets assigned a new value. Similarly, consider the command:

    stop 0x100100

This command stops when the 32- bit integer residing at address `0x100100` is modified, and runs at nearly full speed until the value changes. This form of the `stop` command is useful for watching the contents of anonymous memory, such as the memory returned by `malloc()`.

`dbx` still needs to use the single-step approach if the `stop` command contains an expression to watch, such as in `stop if global == 1`. The performance of the debugged program can be greatly enhanced by including a variable to watch in the `stop` command.

For example, the previous `stop` command can be expressed equivalently as `stop global if global == 1`. This instructs the debugger to check only the expression `global == 1` if the value of `global` changes. For situations where the expression does not depend upon a particular variable getting modified such as `stop if global == x * 3`, the single-step approach is the only way to achieve the desired behavior.

### Stopping If a Test Expression Is True

By including a test clause in your `stop` command, you can cause `dbx` to stop if the value of an expression is true. You can use any valid numerical expression as a test. If the result of the expression is nonzero, the expression is true and the test is successful.

The point at which `dbx` evaluates the test expression depends on the command that you use to set the breakpoint:

`stop` `if` `expression` |  | Evaluates the expression before executing each source line. Note that execution is very slow if you choose this type of conditional breakpoint.
`stop` `at` `line` `if` `expression` |  | Evaluates the expression at the given line.
`stop` `in` `procedure` `if` `expression` |  | Evaluates the expression at every source line within a given procedure.

### Conditional Breakpoints Combining Variable and Test Clauses

You can create conditional breakpoints that combine both variable and test clauses. In these cases, the overall test evaluates to true only if both clauses are true.

The following forms of the `stop` command combine both the variable and test clauses:

`stop` [`expression1`| `variable`] `if` `expression` `2` |  | Tests both conditions before executing each source line. Stops if both conditions are true. If `expression1` is of type pointer, look at the data pointed to and watch until it changes. If `expression1` is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).
`stop` [`expression1`| `variable`] `at` `line` `if` `expression2` |  | Tests both conditions at the given source line. Stops if both conditions are true. If `expression1` is of type pointer, look at the data pointed to and watch until it changes. If `expression1` is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).
`stop` [`expression1`| `variable`] `in` `procedure` `if` `expression2` |  | Tests both conditions at every source line within a given procedure. Stops if both conditions are true. If `expression1` is of type pointer, look at the data pointed to and watch until it changes. If `expression1` is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).

### Continuing Execution After a Breakpoint

The ```cont` command allows you to continue execution after any type of breakpoint. In its simplest form, program execution continues until the end of the program or until another breakpoint is reached. You can also tell `dbx` to continue your program until it reaches a given line or procedure; this is similar to setting a temporary, “one-shot” breakpoint and then continuing.

The syntax of the `cont` command is:

`cont` |  | Continues execution with the current line.
`cont` {`at` | `to`} `line` |  | Sets a temporary breakpoint at the specified source line, then resumes execution with the current line. When your program reaches the breakpoint at `line`, `dbx` stops your program and deletes the temporary breakpoint. The keywords `at` and `to` are equivalent.
`cont` `in` `procedure` |  | Sets a temporary breakpoint to stop execution upon entering the specified procedure, then resumes execution with the current line. When your program reaches the breakpoint in `procedure`, `dbx` stops your program and deletes the temporary breakpoint.

If your program stopped because `dbx` caught a signal intended for your program, then `dbx` will send that signal to your program when you continue execution. You can also explicitly send a signal to your program when you continue execution. Sending signals to your program upon continuation is discussed in “Continuing After Catching a Signal”.

When you debug multiprocess programs, the ```resume` command can be more helpful than the `cont` command. Refer to “Resuming a Suspended Process” for more information about the `resume` command.

## Tracing Program Execution

The `trace` command allows you to observe the progress of your program as it executes. With it, you can print:

- values of variables at specific points in your program or whenever variables change value

- parameters passed to and values returned from functions

Each trace is assigned a number when you create it. Use this number to reference the trace in the various commands provided for manipulating traces (for example, ```disable`, ```enable`, and ```delete`, all described in “Managing Breakpoints, Traces, and Conditional Commands”).

The syntax of the `trace` command is:

`trace` `variable` |  | Whenever the specified variable changes, `dbx` prints the old and new values of that variable.
`trace` `procedure` |  | Prints the values of the parameters passed to the specified procedure whenever your program calls it. Upon return, `dbx` prints the return value.
`trace` [`expression`| `variable`] `at` `line` |  | Whenever your program reaches the specified line, `dbx` prints the value of the variable if its value has changed. If the expression is of type pointer, look at the data pointed to and watch until it changes. If the expression is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).
`trace` [`expression`| `variable`] `in` `procedure` |  | Whenever the variable changes within the procedure, `dbx` prints the old and new values of that variable. If the expression is of type pointer, look at the data pointed to and watch until it changes. If the expression is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).
`trace` [`expression1`| `variable`] `at` `line` `if` `expression2` |  | Prints the value of the variable (if changed) whenever your program reaches the specified line and the given expression is true. If `expression1` is of type pointer, look at the data pointed to and watch until it changes. If `expression1` is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).
`trace` [`expression1`| `variable`] `in` `procedure` `if` `expression2` |  | Whenever the variable changes within the procedure that you specify, `dbx` prints the old and new values of that variable, if the given expression is true. If `expression1` is of type pointer, look at the data pointed to and watch until it changes. If `expression1` is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).

To examine the parameters passed to and values returned from a function, you can trace that function. For example, if the function name is `foo`, set the trace by entering:

    (dbx) trace foo

When you execute your program, `dbx` prints the values of the parameters passed to `foo` whenever your program calls it. Upon return from `foo`, `dbx` prints the return value:

    (dbx) run
    [3] calling foo(text = 0x10000484 = "Processing...\n", i = 4) from function main
    [4] foo returning -1 from foo

In the example shown above, `foo` receives two parameters: a character string variable named text containing the value “Processing...\n” and an integer variable named i containing the value 4. The trace also indicates that `foo` returns a value of -1.

You can also examine a variable as it changes values. For example, you can monitor the value of a string variable named curarg as you use it to process an argument list. To set the trace, enter:

    (dbx) trace curarg
    Process 2395: [6] trace .test.main.curarg in main

When you set a trace on a variable, examine the confirmation that `dbx` prints. If you use the same variable name in multiple functions in your program, `dbx` may not set the trace on the variable that you want. If `dbx` sets the trace on an incorrect variable, delete the trace and set a new trace using a qualified variable format as described in “Qualifying Variable Names”. For more information on deleting traces, see “Deleting Breakpoints, Traces, and Conditional Commands”.

So, in this example, if you use the variable curarg in both `main` and a function called `arg_process`, and you want to trace the curarg in `arg_process`, first delete this trace and then set a new trace:

    (dbx) delete 6
    (dbx) trace arg_process.curarg
    Process 2395: [7] trace .test.arg_process.curarg in arg_process

When you execute your program, whenever curarg changes, `dbx` prints its old and new values:

    (dbx) run
    [7] curarg changed before [arg_process: line 53]:
                    new value = (nil);
    [7] curarg changed before [arg_process: line 86]:
                    old value = 0;
                    new value = 0x7fffc7e5 = "-i";
    [7] curarg changed before [arg_process: line 86]:
                    old value = 2147469285;
                    new value = 0x7fffc7eb = "names.out";
    [7] curarg changed before [arg_process: line 86]:
                    old value = 2147469291;
                    new value = 0x7fffc7f5 = "names.in";

## Writing Conditional Commands

A conditional command created with the `when` command is similar to a breakpoint set with the `stop` command, except that rather than stopping when certain conditions are met, `dbx` executes a list of commands. The command list can consist of any `dbx` commands, separated by semicolons if you include more than one command in the command list. Additionally, you can use the keyword `stop` in the command list to stop execution, just like a breakpoint.

Each conditional command is assigned a number when you create it. You use this number to reference the conditional command in the various commands provided for manipulating conditional commands (for example, `disable`, `enable`, and `delete`, all described in “Managing Breakpoints, Traces, and Conditional Commands”).

The syntax of the `when` command is:

`when` [`expression`| `variable`] `{` `command-list``}` |  | Inspects the value before executing each source line. If it has changed, executes the command list. If the expression is of type pointer, look at the data pointed to and watch until it changes. If the expression is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).
`when` [`expression`| `variable`] `at` `line` `{` `command-list``}` |  | Inspects the value at the given source line. If it has changed, executes the command list. If the expression is of type pointer, look at the data pointed to and watch until it changes. If the expression is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).
`when` [`expression`| `variable`] `in` `procedure` `{` `command-list``}` |  | Inspects the value at every source line within a given procedure. If it has changed, executes the command list. If the expression is of type pointer, look at the data pointed to and watch until it changes. If the expression is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).
`when` `if` `expression` `{` `command-list``}` |  | Evaluates the expression before executing each source line. If it is true, executes the command list. Note that execution is slow if you choose this type of conditional command execution.
`when` `at` `line` `if` `expression` `{` `command-list``}` |  | Evaluates the expression at the given line. If it is true, executes the command list.
`when` `in` `procedure` `if` `expression` `{` `command-list``}` |  | Evaluates the expression at every source line within a given procedure. If it is true, executes the command list.
`when` [`expression1`| `variable`] `if` `expression2` `{` `command-list``}` |  | Checks if the value of the variable has changed. If it has changed and the expression is true, executes the command list. If `expression1` is of type pointer, look at the data pointed to and watch until it changes. If `expression1` is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).
`when` [`expression1`| `variable`] `at` `line` `if` `expression2` `{` `command-list``}` |  | Checks if the value of the variable has changed each time the line is executed. If the value has changed and the expression is true, executes the command list. If `expression1` is of type pointer, look at the data pointed to and watch until it changes. If `expression1` is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).
`when` [`expression1`| `variable`] `in` `procedure` `if` `expression2` `{` `command-list``}` |  | Checks if the value of variable has changed at each source line of the given procedure. If the value has changed and the expression is true, executes the command list. If `expression1` is of type pointer, look at the data pointed to and watch until it changes. If `expression1` is not of type pointer, look at the 32 bits at that address (assume the expression evaluates to an address).

## Managing Breakpoints, Traces, and Conditional Commands

`dbx` provides commands that allow you to disable, enable, delete, and examine the status of the breakpoints, traces, and conditional commands that you set in your programs.

Each breakpoint, trace, and conditional command is assigned a number when you create it. Use these numbers as identifiers in the various commands provided for manipulating these debugging controls.

### Listing Breakpoints, Traces, and Conditional Commands

The ```status` command lists all of the breakpoints, traces, and conditional commands that you have set and indicates whether they are enabled or disabled.

For example, consider executing the following commands while debugging a program called `test`:

    (dbx) stop in foo
    Process     0: [3] stop in foo
    (dbx) r
    Process 22631 (test) started
    [3] Process 22631 (test) stopped at [foo:38 ,0x10001050]
      38  r = foo2(i+1);
    (dbx) trace total
    Process 22631: [4] trace total in foo
    (dbx) when at 60 {print i,j }
    Process 22631: [5] when at “/usr/var/tmp/dbx_examples/test.c”:60 { print i, j }

If you enter `status`, you see the following:

    (dbx) status
    Process 22631: [3] stop in foo
    Process 22631: [4] trace total in foo
    Process 22631: [5] when at “/usr/var/tmp/dbx_examples/test.c”:60 { print i, j }

### Disabling Breakpoints, Traces, and Conditional Commands

The ```disable` command allows you to temporarily disable a breakpoint, trace, or conditional command so that it is inoperative and has no effect on program execution. `dbx` remembers all information about a disabled breakpoint, trace, or conditional command, and you may enable it using the `enable` command described in “Enabling Breakpoints, Traces, and Conditional Commands”.

The syntax of the `disable` command is:

`disable` `item` [, `item` ... ] |  | Disables the specified breakpoint(s), trace(s), or conditional command(s). This command has no effect if the item you specify is already disabled.

For example, to disable the conditional command set in “Listing Breakpoints, Traces, and Conditional Commands” enter:

    (dbx) disable 4

If you enter `status`, you see the following:

    (dbx) status
    Process 22631: [3] stop in foo
    Process 22631: [4] (disabled) trace total in foo
    Process 22631: [5] when at “/usr/var/tmp/dbx_examples/test.c”:60 { print i, j

### Enabling Breakpoints, Traces, and Conditional Commands

The `enable` command reverses the effects of a `disable` command: The breakpoint, trace, or conditional command that you specify is enabled and once again affects the execution of your program. The syntax of the `enable` command is:

`enable` `item` [, `item` ...] |  | Enables the specified breakpoint(s), trace(s), or conditional command(s).

For example, to enable the conditional command disabled in “Disabling Breakpoints, Traces, and Conditional Commands” enter:

    (dbx) enable 4

Executing the `status` command shows that the condition command is now enabled:

    (dbx) status
    Process 22631: [3] stop in foo
    Process 22631: [4] trace total in foo
    Process 22631: [5] when at “/usr/var/tmp/dbx_examples/test.c”:60 { print i, j

### Deleting Breakpoints, Traces, and Conditional Commands

The ```delete` command allows you to delete breakpoints, traces, and conditional commands:

`delete` { `item` [, `item` ...] | `all`} |  | Deletes the item or items specified. If you use the keyword `all` instead of listing individual items, `dbx` deletes all breakpoints, traces, and conditional commands.

For example, to delete the breakpoint and trace set in “Listing Breakpoints, Traces, and Conditional Commands” enter:

    (dbx) delete 3, 4

If you enter `status`, you see the following:

    (dbx) status
    Process 22631: [5] when at “/usr/var/tmp/dbx_examples/test.c”:60 { print i, j }

To delete all breakpoints, traces, and conditional commands, enter:

    (dbx) delete all

## Using Signal Processing

`dbx` can detect any signals sent to your program while it is running and, at your option, stop the program.

### Catching and Ignoring Signals

With the `catch` command, you can instruct `dbx` to stop your program when it receives any specified signal. The ```ignore` command undoes the effects of a `catch` command.

The `catch` and `ignore` commands have the following syntax:

`catch` { `signal` | `all`} |  | Instructs `dbx` to stop your program whenever it receives the specified signal. If you use the keyword `all` rather than giving a specific signal, `dbx` catches all signals.
`ignore` { `signal` | `all`} |  | Instructs `dbx` to ignore the specified signal. All ignored signals are passed to your program normally. If you use the keyword `all` rather than giving a specific signal, `dbx` ignores all signals.
`catch` |  | Prints a list of all signals caught.
`ignore` |  | Prints a list of all signals ignored.

You can use the signal names and numbers as listed in the `signal`(2) reference page. You can also abbreviate the signal names by omitting the “SIG” portion of the name. You can use uppercase or lowercase for the signal names.

| Note: Because “int” (in lowercase) is a `dbx` keyword, you cannot use it as an abbreviation for the SIGINT signal. You must use uppercase (“INT”), the full signal name (“SIGINT” or “sigint”), or the signal number (“2”). SIGINT is the only signal name with such a restriction.

If you instruct `dbx` to catch a signal, whenever that signal is directed to your program, `dbx` intercepts it and stops your program. Your program does not see this signal until you continue your program with the `cont` command. If your program did not declare a signal handler for a signal, your program does not see the signal when `dbx` continues it.

If you issue a SIGINT signal at the keyboard (usually by pressing `<Ctrl-C>`) while you are running an application under dbx, what happens depends on the circumstances:

- If the process is in the same IRIX process group as dbx, the interrupt signal is sent to both dbx and the process. Both dbx and the process stop running. You are left at the `dbx` command line.

- If the process was added with `addproc`, `dbx –P`, or `dbx –p`, it is not in the same IRIX process group as dbx. In this case, the signal interrupt is sent to dbx but not to the process. dbx stops running, but the process continues to run. Use the showproc command to see whether the process is still running. Then use the suspend command to stop the process.

### Continuing After Catching a Signal

The ```cont` command allows you to continue execution after catching a signal. You can also use the `cont` command to specify a different signal to send to your program than the one that `dbx` caught. Using the same syntax, you can also send a signal to your program when you continue, even if your program did not stop because of a caught signal.

Use the following forms of the `cont` command when handling signals. In each case, if you do not provide a signal, but your program stopped because `dbx` caught a signal intended for your program, then `dbx` sends that signal to your program when you continue execution:

`cont` [ `signal`] |  | Continues execution with the current line and sends the specified signal to your program.
`cont` [ `signal`] {`at` | `to`} `line` |  | Sets a temporary breakpoint at the specified source line, then resumes execution with the current line and sends the specified signal to your program.
`cont` [ `signal`] `in` `procedure` |  | Sets a temporary breakpoint to stop execution upon entering the specified procedure, then resumes execution with the current line and sends the specified signal to your program.

For example, if your program stopped because `dbx` caught a SIGINT signal, `dbx` will automatically send that signal to your program, if you enter:

    (dbx) cont

Suppose you have a procedure called `alarm_handler` to handle an alarm signal sent to your program. If you want to test this procedure by single-stepping through it, you can execute the following command:

    (dbx) cont SIGALRM in alarm_handler

This sets a temporary breakpoint to stop your program upon entering `alarm_handler`, continues execution of your program, and sends a SIGALRM signal to your program. Your program then enters the `alarm_handler` procedure and stops. You can then single-step through the procedure and observe execution.

Debugging a program that attempts to catch signals can be awkward if you also catch the signal in `dbx`. For example, if your program wants to catch SIGFPEs and you issue the command:

    (dbx) catch sigfpe

Then, after `dbx` catches the signal, you must execute the command:

    (dbx) ignore sigfpe

This prevents `dbx` from catching the signal again when you resume execution of your program.

If you want to catch further instances of that signal in your program, you must regain `dbx` control (the best way is to set a breakpoint before executing the `cont`) to re-execute the `catch sigfpe` command.

## Stopping at System Calls

Because system calls are part of the operating system and their source is generally not available for debugging purposes, you cannot set breakpoints in system calls using the same method that you use for your program's procedures. Instead, `dbx` provides the ```syscall` command to allow you to stop your program when it executes system calls. With the `syscall` command you can catch (breakpoint) system calls either at the entry to the system call or at the return from the system call.

The syntax of the `syscall` command is:

`syscall catch` {`call` | `return`} { `system_call` | `all`} |  | Sets a breakpoint to stop execution upon entering ( `call`) or returning from ( `return`) the specified system call. Note that you can set `dbx` to catch both the call and the return of a system call. If you use the keyword `all` rather than giving a specific system call, `dbx` catches all system calls.
`syscall ignore` {`call` | `return`} { `system_call` | `all`} |  | Clears the breakpoint to stop execution upon entering ( `call`) or returning from ( `return`) the specified system call. If you use the keyword `all` rather than giving a specific system call, `dbx` clears the breakpoints to stop execution upon entering (`call`) or returning from ( `return`) all system calls.
`syscall catch` [{`call` | `return`}] |  | Prints a list of all system calls caught upon entry ( `call`) or return ( `return`). If you provide neither the `call` nor `return` keyword, `dbx` lists all system calls that are caught.
`syscall ignore` [{`call` | `return`}] |  | Prints a list of all system calls not caught upon entry ( `call`) or return ( `return`). If you provide neither the `call` nor `return` keyword, `dbx` lists all system calls that are ignored.
`syscall` |  | Prints a summary of the catch and ignore status of all system calls. The summary is divided into four sections: 1) caught at call, 2) caught at return, 3) ignored at call, and 4) ignored at return.

| Note: The `fork` and `sproc` system calls are treated specially as they invoke new processes. The returns from these system calls are controlled by the `dbx` variables $promptonfork and $mp_program, not by `syscall`. This is discussed in “Handling fork System Calls” and “Handling sproc System Calls and Process Group Debugging”.The `execv` and `execve` system calls are treated specially as they change a process into a new program. For more information, see “Handling exec System Calls”.

The system calls are listed in `/usr/include/sys.s`. `dbx` ignores the case of the system call names in all `syscall` commands; therefore, you can use uppercase or lowercase in these commands.

A particularly useful setting is:

    (dbx) syscall catch call exit

This stops your program upon entry to `exit`. With your program stopped, you can do a stack trace before the termination to see why `exit` was called.

## Stepping Through Your Program

Stepping is a process of executing your program for a fixed number of lines and then automatically returning control to `dbx`. `dbx` provides two commands for stepping through lines of code: ```step` and ```next`.

For both `step` and `next`, `dbx` counts only those source lines that actually contain code; for the purposes of stepping`, dbx` ignores blank lines and lines consisting solely of comments.

The `next` and `step` commands differ in their treatment of procedure calls. When `step` encounters a procedure call, it usually “steps into” the procedure and continues stepping through the procedure (counting each line of source). On the other hand, when `next` encounters a procedure call, it “steps over” the procedure—executing it without stopping but not counting lines in the procedure—and continues stepping through the current procedure.

The following code fragment illustrates the difference between `step` and `next`:

     55  foo( arg1, arg2 )
     56  int arg1, arg2;
     57  {
     58        if ( arg1 < arg2 ) {
     ...       ...
     78        return( 0 );
     79  }
     ...
    211  x = foo( i, j );
    212  y = 2 * x;

In this example, if at line 211 you execute a `step` command to advance one line, `dbx` allows the process to proceed to line 58 (the first code line of the `foo` procedure). However, if you execute a `next` command, `dbx` executes line 211—calling `foo`—and advances the process to line 212.

### Stepping Using the `step` Command

The format of the `step` command is:

`step` [ `integer`] |  | Executes the specified number of lines of source code, stepping into procedures. If you do not provide an argument, `step` executes one line. If `step` encounters any breakpoints, it immediately stops execution.

By default, `step` steps into only those procedures that are compiled with the debugging option `–` `g`. Note that this does not include standard library routines because they are not compiled using debugging options.

You can modify this behavior, even force `dbx` to step into procedures not compiled with full debugging information, by changing the value of the `dbx` variable $stepintoall. Table 6-1 summarizes how the value of $stepintoall affects `dbx`'s treatment of the `step` command.

Table 6-1. Effect of $stepintoall Variable on the step Command

$stepintoall value | Effect on `step` Command
--- | ---
0 (default) | `step` steps into only those procedures that are compiled with the debugging option `–` `g`. step steps over all other procedures.
1 or 2 | `step` steps into all procedures. Note that when you debug a source file compiled without symbols or compiled with optimization, the line numbers may sometimes jump erratically. Also note that if `dbx` cannot locate a source file, then it cannot display source lines as you step through a procedure.

### Stepping Using the `next` Command

The format of the `next` command is:

`next` [ `integer`] |  | Executes the specified number of lines of source code, stepping over procedures. If you do not provide an argument, `next` executes one line. If `next` encounters any breakpoints, even in procedures that it steps over, it immediately stops execution.

### Using the return Command

If you step into a procedure and then decide you don't want to step through the rest of it, use ```return` to finish executing the procedure and return to the calling procedure.

The format of the `return` command is:

`return` |  | Continues execution until control returns to the procedure that invoked the `return` command.
`return` proc |  | Continues execution until control returns to the named procedure. Execution continues, unless stopped by a breakpoint, until the latest invocation of the procedure named by proc at the time the command was issued is reached. Execution doesn't stop at subsequent invocations of the same procedure. The search for the frame to return to starts with the previous frame, because the current frame is skipped in looking for a frame whose name matches proc. If execution is stopped for any reason, this command is cancelled.

## Starting at a Specified Line

When you continue your program, you typically do so at the place where it stopped using the ```cont` command. However, you can also force your program to continue at a different address by using the `goto` command:

`goto` `line` |  | Begins execution at the specified line. You may not use the `goto` command to resume execution with a line outside of the current procedure.

Prev | Table of Contents | Next
Chapter 5. Examining and Changing Data |  | Chapter 7. Debugging Machine Language Code