When analyzing optimized code, you can:
Stop execution at the start of any function (stop in function command)
Evaluate, display, or modify arguments
Evaluate, display, or modify global, local, or static variables
Single-step from one line to another (next or step command)
When programs are compiled with optimization and debugging enabled at the same time (using the -O -g options), dbx operates in a restricted mode.
The details about which compilers emit which kind of symbolic information under what circumstances is considered an unstable interface and is likely to change from release to release.
Source line information is available, but the code for one source line might appear in several different places for an optimized program, so stepping through a program by source line results in the “current line” jumping around in the source file, depending on how the code was scheduled by the optimizer.
Tail call optimization can result in missing stack frames when the last effective operation in a function is a call to another function.
Generally, symbolic information for parameters, local variables, and global variables is available for optimized programs. Type information about structs, unions, C++ classes, and the types and names of local variables, global variables, and parameters should be available. The C++ compiler does not provide symbolic type information about local variables; the C compiler does.
Information about the location of parameters and local variables is often missing in optimized code. If the compiler generates Dwarf location lists, dbx uses this information to print the values of local variables and parameters. If you stop at the first instruction of an optimized function, dbx can print the values of parameters, because the values will be in ABI-conforming registers or stack locations. To see the values of local variables, you might also need to set the dbx environment variable optim_local_vars.
A simple location in the debug information describes one register or stack location. A location list describes different locations for a variable at different points in the code, which makes location lists better for describing optimized code.
Sun Studio compilers, starting with the Sun Studio 12 release, do not emit location lists, but they do produce simple locations for some optimized code. Newer versions of GNU compilers use location lists for describing the frame pointer, and for describing some parameters and local variables. How this information is recorded by the compiler can change from release to release.
You can print global variables and assign values to them, although they might have inaccurate values if the final register-to-memory store has not happened yet.
Chapter 8 of the Sun Studio 11 Performance Analyzer manual includes information on compiler optimizations that might be helpful when debugging an optimized program.
For OpenMP programs, compiling with the -xopenmp=noopt option instructs the compiler not to apply any optimizations. However, the optimizer still processes the code in order to implement the OpenMP directives, so some of the problems described might occur in programs compiled with -xopenmp=noopt.
While most debugging support requires that a program be compiled with -g, dbx still provides the following level of support for code compiled without -g:
Backtrace (dbx where command)
Calling a function (but without parameter checking)
Checking global variables
Note, however, that dbx cannot display source code unless the code was compiled with the -g option. This restriction also applies to code that has had strip -x applied to it.
For full support, a shared library must also be compiled with the -g option. If you build a program with shared library modules that were not compiled with the -g option, you can still debug the program. However, full dbx support is not possible because the information was not generated for those library modules.
The dbx tool can debug programs that have been completely stripped. These programs contain some information that can be used to debug your program, but only externally visible functions are available. Some runtime checking works on stripped programs or load objects: memory use checking works, and access checking works with code stripped with strip -x but not with code stripped with strip.