|Debugging with GDB|
Executable programs sometimes do not record the directories of the source files from which they were compiled, just the names. Even when they do, the directories could be moved between the compilation and your debugging session. gdb has a list of directories to search for source files; this is called the source path. Each time gdb wants a source file, it tries all the directories in the list, in the order they are present in the list, until it finds a file with the desired name.
For example, suppose an executable references the file /usr/src/foo-1.0/lib/foo.c, and our source path is /mnt/cross. The file is first looked up literally; if this fails, /mnt/cross/usr/src/foo-1.0/lib/foo.c is tried; if this fails, /mnt/cross/foo.c is opened; if this fails, an error message is printed. gdb does not look up the parts of the source file name, such as /mnt/cross/src/foo-1.0/lib/foo.c. Likewise, the subdirectories of the source path are not searched: if the source path is /mnt/cross, and the binary refers to foo.c, gdb would not find it under /mnt/cross/usr/src/foo-1.0/lib.
Plain file names, relative file names with leading directories, file names containing dots, etc. are all treated as described above; for instance, if the source path is /mnt/cross, and the source file is recorded as ../lib/foo.c, gdb would first try ../lib/foo.c, then /mnt/cross/../lib/foo.c, and after that—/mnt/cross/foo.c.
Note that the executable search path is not used to locate the source files.
Whenever you reset or rearrange the source path, gdb clears out any information it has cached about where source files are found and where each line is in the file.
The search path is used to find both program source files and gdb script files (read using the ‘-command’ option and ‘source’ command).
In addition to the source path, gdb provides a set of commands that manage a list of source path substitution rules. A substitution rule specifies how to rewrite source directories stored in the program's debug information in case the sources were moved to a different directory between compilation and debugging. A rule is made of two strings, the first specifying what needs to be rewritten in the path, and the second specifying how it should be rewritten. In set substitute-path, we name these two parts from and to respectively. gdb does a simple string replacement of from with to at the start of the directory part of the source file name, and uses that result instead of the original file name to look up the sources.
Using the previous example, suppose the foo-1.0 tree has been
moved from /usr/src to /mnt/cross, then you can tell
gdb to replace /usr/src in all source path names with
/mnt/cross. The first lookup will then be
/mnt/cross/foo-1.0/lib/foo.c in place of the original location
of /usr/src/foo-1.0/lib/foo.c. To define a source path
substitution rule, use the
set substitute-path command
(see set substitute-path).
To avoid unexpected substitution results, a rule is applied only if the from part of the directory name ends at a directory separator. For instance, a rule substituting /usr/source into /mnt/cross will be applied to /usr/source/foo-1.0 but not to /usr/sourceware/foo-2.0. And because the substitution is applied only at the beginning of the directory name, this rule will not be applied to /root/usr/source/baz.c either.
In many cases, you can achieve the same result using the
set substitute-path can be more efficient in
the case where the sources are organized in a complex tree with multiple
subdirectories. With the
directory command, you need to add each
subdirectory of your project. If you moved the entire tree while
preserving its internal organization, then
allows you to direct the debugger to all the sources with one single
set substitute-path is also more than just a shortcut command.
The source path is only used if the file at the original location no
longer exists. On the other hand,
set substitute-path modifies
the debugger behavior to look at the rewritten location instead. So, if
for any reason a source file that is not relevant to your executable is
located at the original location, a substitution rule is the only
method available to point gdb at the new location.
You can configure a default source path substitution rule by configuring gdb with the ‘--with-relocated-sources=dir’ option. The dir should be the name of a directory under gdb's configured prefix (set with ‘--prefix’ or ‘--exec-prefix’), and directory names in debug information under dir will be adjusted automatically if the installed gdb is moved to a new location. This is useful if gdb, libraries or executables with debug information and corresponding source code are being moved together.
You can use the string ‘$cdir’ to refer to the compilation
directory (if one is recorded), and ‘$cwd’ to refer to the current
working directory. ‘$cwd’ is not the same as ‘.’—the former
tracks the current working directory as it changes during your gdb
session, while the latter is immediately expanded to the current
directory at the time you add an entry to the source path.
set substitute-pathfrom to
For example, if the file /foo/bar/baz.c was moved to /mnt/cross/baz.c, then the command
(gdb) set substitute-path /usr/src /mnt/cross
will tell gdb to replace ‘/usr/src’ with ‘/mnt/cross’, which will allow gdb to find the file baz.c even though it was moved.
In the case when more than one substitution rule have been defined, the rules are evaluated one by one in the order where they have been defined. The first one matching, if any, is selected to perform the substitution.
For instance, if we had entered the following commands:
(gdb) set substitute-path /usr/src/include /mnt/include (gdb) set substitute-path /usr/src /mnt/src
gdb would then rewrite /usr/src/include/defs.h into
/mnt/include/defs.h by using the first rule. However, it would
use the second rule to rewrite /usr/src/lib/foo.c into
unset substitute-path [path]
If no path is specified, then all substitution rules are deleted.
show substitute-path [path]
If no path is specified, then print all existing source path substitution rules.
If your source path is cluttered with directories that are no longer of interest, gdb may sometimes cause confusion by finding the wrong versions of source. You can correct the situation as follows:
directorywith no argument to reset the source path to its default value.
directorywith suitable arguments to reinstall the directories you want in the source path. You can add all the directories in one command.