Sun Studio 12 Update 1: Debugging a Program With dbx

Chapter 5 Controlling Program Execution

The commands used for running, stepping, and continuing (run, rerun, next, step, and cont) are called process control commands. Used together with the event management commands described in cont at Command, you can control the run-time behavior of a program as it executes under dbx.

This chapter is organized into the following sections:

Running a Program

When you first load a program into dbx, dbx navigates to the program’s “main” block (main for C, C++, and Fortran 90; MAIN for Fortran 77; the main class for Java code). dbx waits for you to issue further commands; you can navigate through code or use event management commands.

You can set breakpoints in the program before running it.

Note –

When debugging an application that is a mixture of JavaTM code and C JNI (Java Native Interface) code or C++ JNI code, you may want to set breakpoints in code that has not yet been loaded. For information on setting breakpoints on such code, see Setting Breakpoints in Native (JNI) Code .

Use the run command to start program execution.

To run a program in dbx without arguments, type:

(dbx) run

You can optionally add command-line arguments and redirection of input and output.

(dbx) run [arguments][ < input_file] [ > output_file]

Note –

You cannot redirect the input and output of a Java application.

Output from the run command overwrites an existing file even if you have set noclobber for the shell in which you are running dbx.

The run command without arguments restarts the program using the previous arguments and redirection. For more information, see run Command. The rerun command restarts the program and clears the original arguments and redirection. For more information, see rerun Command.

Attaching dbx to a Running Process

You might need to debug a program that is already running. You would attach to a running process if:

You can attach dbx to a running program by using the program’s process_id number as an argument to the dbx debug command.

Once you have debugged the program, you can then use the detach command to take the program out from the control of dbx without terminating the process.

If you quit dbx after attaching it to a running process, dbx implicitly detaches before terminating.

To attach dbx to a program that is running independently of dbx, you can use either the attach command or the debug command.

To attach dbx to a process that is already running, type:

(dbx) debug program_name process_id


(dbx) attach process_id

You can substitute a– (dash) for the program_name; dbx automatically finds the program associated with the process ID and loads it.

For more information, see debug Command and attach Command.

If dbx is not running, start dbx by typing:

% dbx program_name process_id

After you have attached dbx to a program, the program stops executing. You can examine it as you would any program loaded into dbx. You can use any event management or process control command to debug it.

When you attach dbx to a new process while you are debugging an existing process, the following occurs:

If the process to which you are attaching dbx is stopped due to a SIGSTOP signal, SIGTSTOP signal, SIGTTIN signal, or SIGTTOUT signal, the attach succeeds with a message like the following:

dbx76: warning: Process is stopped due to signal SIGSTOP

The process is inspectable, but to resume it you need to send it a SIGCONT signal with the cont command:

(dbx) cont -sig cont

You can use runtime checking on an attached process with certain exceptions. See Using Runtime Checking on an Attached Process.

Detaching dbx From a Process

When you have finished debugging the program, use the detach command to detach dbx from the program. The program then resumes running independently of dbx, unless you specify the -stop option when you detach it.

To detach a process from running under the control of dbx:

(dbx) detach

You can detach a process and leave it in a stopped state while you temporarily apply other /proc-based debugging tools that might be blocked when dbx has exclusive access. For example:

(dbx) oproc=$proc           # Remember the old process ID
(dbx) detach -stop
(dbx) /usr/proc/bin/pwdx $oproc
(dbx) attach $oproc

For more information, see detach Command.

Stepping Through a Program

dbx supports two basic single-step commands: next and step, plus two variants of the step command, called step up and step to. Both the next command and the step command let the program execute one source line before stopping again.

If the line executed contains a function call, the next command allows the call to be executed and stops at the following line (“steps over” the call). The step command stops at the first line in a called function (“steps into” the call).

The step up command returns the program to the caller function after you have stepped into a function.

The step to command attempts to step into a specified function in the current source line, or if no function is specified, into the last function called as determined by the assembly code for the current source line. The function call may not occur due to a conditional branch, or there may be no function called in the current source line. In these cases, step to steps over the current source line.

For more information on the next and step commands, see next Command and step Command.

Single Stepping

To single step a specified number of lines of code, use the dbx commands next or step followed by the number of lines [n] of code you want executed.

(dbx) next n


(dbx) step n

The step_granularity environment variable determines the unit by which the step command and next command step through your code (see Setting dbx Environment Variables). The unit can be either statement or line.

The step_events environment variable controls whether breakpoints are enabled during a step (see Setting dbx Environment Variables).

The step_abflow environment variable controls whether dbx stops when it detects that an abnormal control flow change is about to happen (see Setting dbx Environment Variables). Such a control flow change can be caused by a call to siglongjmp() or longjmp() or an exception throw.

Stepping Into a Function

To step into a function called from the current source code line, use the step to command. For example, to step into the function GetDiscount()(), type:

step to GetDiscount

To step into the last function called, type:

step to

Continuing Execution of a Program

To continue a program, use the cont command.

(dbx) cont

The cont command has a variant, cont at line_number, which lets you specify a line other than the current program location line at which to resume program execution. This allows you to skip over one or more lines of code that you know are causing problems, without having to recompile.

To continue a program at a specified line, type:

(dbx) cont at 124

The line number is evaluated relative to the file in which the program is stopped; the line number given must be within the scope of the current function.

Using the cont at line_number command with the assign command, you can avoid executing a line of code that contains a call to a function that might be incorrectly computing the value of some variable.

ProcedureTo Resume Program Execution at a Specific Line

  1. Use the assign command to give the variable a correct value.

  2. Use cont at line_number to skip the line that contains the function call that would have computed the value incorrectly.

    Assume that a program is stopped at line 123. Line 123 calls a function, how_fast(), that computes incorrectly a variable, speed. You know what the value of speed should be, so you assign a value to speed. Then you continue program execution at line 124, skipping the call to how_fast().

    (dbx) assign speed = 180; cont at 124;

    For more information, see cont Command.

    If you use the cont command with a when breakpoint command, the program skips the call to how_fast() each time the program attempts to execute line 123.

    (dbx) when at 123 { assign speed = 180; cont at 124;}

    For more information on the when command, see:

Calling a Function

When a program is stopped, you can call a function using the dbx call command, which accepts values for the parameters that must be passed to the called function.

To call a procedure, type the name of the function and supply its parameters. For example:

(dbx) call change_glyph(1,3)

While the parameters are optional, you must type the parentheses after the function_name. For example:

(dbx) call type_vehicle()

You can call a function explicitly, using the call command, or implicitly, by evaluating an expression containing function calls or using a conditional modifier such as stop in glyph -if animate().

A C++ virtual function can be called like any other function using the print command or call command (see print Command or call Command), or any other command that executes a function call.

If the source file in which the function is defined was compiled with the– g option, or if the prototype declaration is visible at the current scope, dbx checks the number and type of arguments and issues an error message if there is a mismatch. Otherwise, dbx does not check the number of parameters and proceeds with the call.

By default, after every call command, dbx automatically calls fflush(stdout) to ensure that any information stored in the I/O buffer is printed. To turn off automatic flushing, set the dbx environment variable output_auto_flush to off.

For C++, dbx handles the implicit this pointer, default arguments, and function overloading. The C++ overloaded functions are resolved automatically if possible. If any ambiguity remains (for example, functions not compiled with -g), dbx displays a list of the overloaded names.

When you use the call command, dbx behaves as though you used the next command, returning from the called function. However, if the program encounters a breakpoint in the called function, dbx stops the program at the breakpoint and issues a message. If you now type a where command, the stack trace shows that the call originated from dbx command level.

If you continue execution, the call returns normally. If you attempt to kill, run, rerun, or debug, the command aborts as dbx tries to recover from the nesting. You can then re-issue the command. Alternatively, you can use the command pop -c to pop all frames up to the most recent call.

Call Safety

Making calls into the process you are debugging, either by using the call command or by printing expressions that contain calls, has the potential for causing severe non-obvious disruptions. Here are some scenarios to watch out for and how you can extricate yourself from them.

Some calls made by dbx are performed “safely.” If a problem, typically a segmentation fault, is encountered instead of the usual “Stopped with call to ...”, dbx:

dbx uses safe calls for:

Using Ctrl+C to Stop a Process

You can stop a process running in dbx by pressing Ctrl+C (^C). When you stop a process using ^C, dbx ignores the ^C, but the child process accepts it as a SIGINT and stops. You can then inspect the process as if it had been stopped by a breakpoint.

To resume execution after stopping a program with ^C, use the cont command. You do not need to use the cont optional modifier, sig signal_name, to resume execution. The cont command resumes the child process after cancelling the pending signal.