Oracle® Solaris Studio 12.4: Debugging a Program With dbx

Exit Print View

Updated: January 2015
 
 

Macros

By default, selected expressions are macro expanded before being evaluated, including expressions you specify with the print, display, and watch commands; the –if option of the stop, trace, and when commands; and the $[] construct. Macro expansion is also applied to balloon evaluation and watches in the IDE or dbxtool.

Additional Uses of Macro Expansion

Macro expansion is applied to both the variable and the expression in an assign command.

In the call command, macro expansion is applied to the name of the function being called as well as to the parameters being passed.

The macro command takes any expression and macro and expands the macro. For example:

(dbx) macro D(1, 2)
    Expansion of: D(1, 2)
              is: d(1,2)

If you give the whatis command a macro, it shows the macro's definition. For example:

(dbx) whatis B
    #define B(x) b(x)

If you give the which command a macro, it shows where the macro that is currently active in the scope is defined. For example:

(dbx) which B2
    `a.out`macro_wh.c`B2    # defined at defs2.h:3
            # included from defs1.h:3
            # included from macro_wh.c:23

If you give the whereis command a macro, it shows all of the places where the macro has been defined. The list is limited to modules for which dbx has already read debugging information. For example:

(dbx) whereis U
    macro:          U       # defined at macro_wh.c:21
    macro:          U       # undefined at defs1.h:5

The dbxenv variable macro_expand controls whether these commands expand macros. It is set to on by default.

In general, the +m option in dbx commands causes the commands to bypass macro expansion. The –m option forces macro expansion even if the dbxenv variable macro_expand is set to off. An exception is the –m option within the $[] construct, where –m only causes macros to be expanded, with no evaluation taking place. This exception facilitates macro expansion in shell scripts.

Macro Definitions

dbx can recognize macro definitions in two ways:

  • Definitions are provided by the compilers when you compile with the –g3 option if you use the default DWARF format for debugging information. They are not provided if you specify the –xdebugformat=stabs option when compiling.

  • dbx can re-create definitions by skimming the source file and its include files. Accurate re-creation depends on access to the original sources and include files. It also depends on the availability of the path name to the compiler used, and on compiler options like –D and –I. This information is available in both DWARF and stabs formats from Oracle Solaris Studio compiler, but not from GNU compilers. See Skimming Errors and Using the pathmap Command to Improve Skimming for information about ensuring successful skimming.

The dbxenv variable macro_source (see Table 3–1 in Chapter 3, Customizing dbx) controls which one of the two methods dbx uses to recognize macro definitions.

There are several factors to take into account in choosing which method you want dbx to use.

Compiler and Compiler Options

One factor in choosing a macro definition method is the availability of various types of information that depend on which compiler and compiler options you used to build your code. The following table shows which methods you can choose depending on the compiler and debugging information options.

Table C-1  Macro Definition Methods Available for Various Build Options
Compiler
–g option
Debug Information Format
Methods That Work
Oracle Solaris Studio
–g
DWARF
Skimming
Oracle Solaris Studio
–g
stabs
Skimming
Oracle Solaris Studio
–g3
DWARF
Skimming and from compiler
Oracle Solaris Studio
–g3
stabs
Skimming (–g3 option with –xdebugformat=stabs option is not supported)
GNU
–g
DWARF
Neither
GNU
–g
stabs
N/A
GNU
–g3
DWARF
From compiler
GNU
–g3
stabs
N/A

Tradeoffs in Functionality

Another factor to take into account in choosing a macro definition method is the tradeoffs in functionality depending on which method you choose:

  • Size of executable. The main advantage of the skimming method is that it does not require compilation with the –g3 option because it works with the smaller executables produced by compiling with the –g option.

  • Debugging format. Skimming works with both DWARF and stabs. Compiling with the –g3 option to get the definitions from the compiler works only with DWARF.

  • Speed. Skimming takes up to one second the first time an expression is evaluated for a module for which dbx has not yet read the debugging information.

  • Accuracy. Information provided by the compilers when you compile with the –g3 option is more stable and accurate than information provided by skimming.

  • Availability of the build environment. Skimming requires that the compilers, source code files, and include files be available during debugging. dbx does not check for these items becoming out of date, so if they are likely to change, accuracy might deteriorate and compiling with the –g3 option might be better than depending on skimming.

  • Debugging on a different system from the one where the code was compiled. If you compiled the code on system A and are debugging it on system B, dbx accesses files on system A using NFS with some help from the pathmap command.

    The pathmap command also helps facilitate file access during skimming. Although it works for your program's source files and include files, it might not work for system include files because /usr/include is not usually available through NFS. Macro definitions therefore are extracted from /usr/include on the debugging system instead of on the build system.

    You can choose to be aware of and tolerant of possible discrepancies between system include files, or choose to compile with the –g3 option.

Limitations

  • Although Fortran compilers support macros through the cpp(1) function or the fpp(1) function, dbx does not support macro expansion for Fortran.

  • dbx ignores macro information generated by compiling with the –g3 option and the –xdebugformat=stabs option.

    For more information about the stabs index, see the Stab Interface guide,found with the path install-dir/solarisstudio12.4/READMEs/stabs.pdf.

  • Skimming works with code compiled with the –g option and the –xdebugformat=stabs option.

Skimming Errors

You are depending on macro skimming if you did not compile your code with the –g3 option and have the macro_source dbxenv variable set to skim_unless_compiler or skim.

For skimming to succeed for a module, the following conditions need to be true:

  • The module must have been compiled with a Oracle Solaris Studio compiler using the –g option.

  • The compiler used to compile the module must be accessible by dbx.

  • The source file for the module must be accessible by dbx.

  • Files included by the source code of the module must be available, that is, the path given to the –I options when the module was compiled must be accessible by dbx.

  • The source code must be lexically sound. For example, it cannot contain unterminated strings of comments or be missing #endifs.

If the source code or include files are not accessible by dbx, you can use the pathmap command to make them accessible.

Using the pathmap Command to Improve Skimming

If you move your source files after compiling, build on one machine and debug on another, or are in one of the other situations described in Finding Source and Object Files, macro skimming might not be able to find include files in the file it is skimming. The solution, as with other cases of files not being found, is to use the pathmap command to help the macro skimmer locate include directories. Imagine, for example, that you compile with the option –I/export/home/proj1/include and have the statement #include "module1/api.h" in your code. Then, if you rename proj1 to proj2, the following pathmap command will help the macro skimmer locate your files:

pathmap /export/home/proj1 /export/home/proj2

The pathmap is not applied to the compilers used to compile the original code.

When you are working with macros, you must reload your application in order to have pathmaps take effect, unlike other situations when a file is not found and you can use the pathmap command to make changes in a pathmapping that are immediately effective.

The pathmap command helps dbx find the correct files when you build on one machine and debug on another. However, system include files such as /usr/include/stdio.h are typically not exported from the build machine, so the macro skimmer is likely to use the files on the debug machine. In some cases, a system include file might not be available on the debug machine. The value of system-specific and system-dependent macros also might not be the same on the debug machine as on the build machine.

If the pathmap command does not solve your skimming problems, consider compiling your code with the –g3 option and setting the macro_source dbxenv variable to skim_unless_compiler or compiler.