Why Can't dbx Find My Fdunction?

By Maxim Kartashev, Sun Microsystems, April 11, 2006  
The Sun Studio debugger, dbx, will complain when it can't find all the debug information it needs for your program. This article will show you the error messages that might appear, explain what could go wrong, and suggest how to fix things. » Read Russian version

Errors you might see

             stop in foo

dbx: warning: 'foo' has no debugger info -- will trigger on first



             stop at b.c:5

dbx: no executable code at line "b.c":5


dbx: warning: can't find file "/.../a.o"

dbx: warning: see `help finding-files'


             stop at a.c:5

dbx: cannot find object file corresponding to "a.c"


             list foo

dbx: no source lines for "foo"

Possible causes

Object files might have been compiled without -g
Check your makefiles and/or build log to see if the -g compiler option has been specified. See also how to determine if your a.out/.so/.o has debug info in the section below.
Load objects might have been stripped
Check your makefiles to see if a.out/.so was stripped after being built and eliminate strip command.
Object files might not be where dbx expects them to be
They may have been moved since the loadobject was created, or the directory might be mounted at a different location. In this case, pathmap dbx command should help. See how to use pathmap below. This problem only affects stabs information, not dwarf. See below for more information.
A shared library might not be loaded yet

If you are trying to debug a shared library ( .so), it might be that it has not been loaded yet. This can be determined with loadobject -list | grep <your library>. You can often just run your program once through quickly to cause the libraries to be loaded, and then re-run it to debug it. This will have the side effect of loading all the libraries. You could also load the library explicitly using the dbx command loadobject -load <your .so path>.
After it is loaded, you should be able to debug this shared library. Note: libraries linked in with -l will be loaded automatically by dbx, but libraries loading using the dlopen function call will not be seen by dbx until the program is run.

How to determine what went wrong

In the case where you know the name of the function you wish to debug (let it be foo(), for examle), issue

(dbx) whereis foo

If you see something like

function: `a.out`#__1cDfoo6Fipc_i_ [non -g, demangles to: foo(int,char*)]

( note absence of source file name after a.out) you can be sure that file containing this function was compiled without debug info or has been stripped. In order to be able to debug foo(), you need to recompile it with -g and eliminate any kind of strip commands from the build script.

The following output ( note presence of a.c after a.out)

function: `a.out` a.c`#__1cDbar6Fi_pc_ [non -g, demangles to: bar(int)]

means that object file containing this function (as well as debug information) was not found by dbx. Use the pathmap command ( see below) to tell dbx where to find it.

And finally, no output means that dbx does not see any symbol with the specified name. If you are sure that it exists, it means that the function resides in a library that has not been loaded yet. Use the loadobject -load command to load it ( see above).

If you know the object file name that contains functions you wish to debug, you can take advantage of module -v dbx command.

Issue module -v <your .o file> and check its output. If dbx says that the object file is not available, then it was compiled without -g.

If it prints the original (expected) .o file path and also prints that it cannot be found, then .o file has been moved from its original (build) location. Make sure this .o file exists and use pathmap in this case.

And if dbx prints "Can't find module ...", then either your loadobject does not have debug info or the object file you are looking for does not belong to any of the loaded loadobjects (i.e. executables or shared libraries). Use loadobject -list to see which shared libraries are currently loaded.

How to determine if your a.out/.so/.o has debug info

The Sun Studio compilers can generate debug information in either stabs or dwarf format. ( See below) In Sun Studio 11, the C compiler will generate dwarf by default, and the C++ and Fortran compilers will generate stabs. In a future release, all the compilers will eventually migrate to using dwarf by default.

When you are in doubt whether an object file has debug info or not, use the SunStudio dwarfdump/dumpstabs utilities (one per debug info type - dwarf and stabs respectively). Both commands are suitable for any ELF file ( a.out/.so/.o). The main problem here is that absence of one type of debug info does not mean a thing -- you have to have a complete picture before you can be sure about debug info presence.

Try executing dwarfdump:

$ dwarfdump -l <a.out/.so/.o>

If it prints "No DWARF information present in a.out", then either a.out is compiled with stabs or without debug info.

If dwarfdump prints a .debug_line section, check to see if it contains any line info. If it is empty, then debug info type for a.out is definitely dwarf, but debug information is absent (it is the case when -xdebugformat=dwarf has been specified, but -g has not). And if .debug_line is not empty, dwarf debug info is present.

If no dwarf debug info is found, try

$ dumpstabs -s <a.out/.so/.o>

For a file without debug info, the Index Stab Table that is printed with this command is either absent or contains a small number of entries (three). If there's more (tens, hundreds, thousands, etc) - this file has stabs debug info.

How to use pathmap to point to your object files

If you debug your program from different location (NFS mounts or suchlike) or .o files have been moved from their original (build) locations, dbx is unable to find them because index debug information refers to the files by their full pathnames.

To workaround this problem, use the pathmap command. Suppose your files were built in /home/me/program/ directory, but you are debugging the program from a different machine and accessing the files via NFS using /net/machine/myprogram mount point.

In this case you can issue

(dbx) pathmap /home/me/program /net/machine/myprogram

and dbx translates all references to old location ( /home/me/program) to new location ( /net/machine/myprogram).

More information

help finding-files
The following Sun Studio compiler options are related to debug info generation, and apply to C, C++, and Fortran compilers:
  • -g - generate debug info. Even without this option, a small amount of stabs or dwarf information will be put into the .o file.
  • -xs - this option causes all the debug information to be generated into the .o files in such a way that it will end up collected into the a.out or shared library when it is linked. This has little impact on dbx performance or the run-time performance of the program, but it does take more disk space. Only useful when debug info type is stabs.
  • -xdebugformat=[stabs|dwarf] - specify debug info format to be stabs or dwarf 
Some useful dbx commands are:

(use help <command> in dbx to find out more).

Some other useful resources are:

Stabs is older debug information format; it is still generated by Sun Studio 11 C++ and Fortran compilers by default, though. More information can be found here: http://blogs.sun.com/roller/page/quenelle?entry=the_story_of_lazy_stabs
DWARF (Debug With Arbitrary Record Format) is newer and extensible debug format, now supported by SunStuio compilers; later g++ and Sun Studio C compiler generate dwarf by default.