From c011a4f469702871cbd5a1e7fecdb57d322642bd Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Tue, 15 Nov 2011 17:40:02 +0000 Subject: [PATCH] * NEWS: Mention new parameter basenames-may-differ. * dwarf2read.c (dw2_lookup_symtab): Avoid calling gdb_realpath if ! basenames_may_differ. * psymtab.c (lookup_partial_symtab): Ditto. * symtab.c (lookup_symtab): Ditto. (basenames_may_differ): New global. (_initialize_symtab): New parameter basenames-may-differ. * symtab.h (basenames_may_differ): Declare. doc/ * gdb.texinfo (Files): Document basenames-may-differ. --- gdb/ChangeLog | 11 +++++++++++ gdb/NEWS | 11 +++++++++++ gdb/doc/ChangeLog | 4 ++++ gdb/doc/gdb.texinfo | 27 +++++++++++++++++++++++++++ gdb/dwarf2read.c | 9 ++++++++- gdb/psymtab.c | 9 ++++++++- gdb/symtab.c | 26 ++++++++++++++++++++++++++ gdb/symtab.h | 2 ++ 8 files changed, 97 insertions(+), 2 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2e866ba..98f7c7d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2011-11-15 Doug Evans + + * NEWS: Mention new parameter basenames-may-differ. + * dwarf2read.c (dw2_lookup_symtab): Avoid calling gdb_realpath if + ! basenames_may_differ. + * psymtab.c (lookup_partial_symtab): Ditto. + * symtab.c (lookup_symtab): Ditto. + (basenames_may_differ): New global. + (_initialize_symtab): New parameter basenames-may-differ. + * symtab.h (basenames_may_differ): Declare. + 2011-11-15 Pedro Alves Luis Machado diff --git a/gdb/NEWS b/gdb/NEWS index bce8e3c..c4e59c4 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -165,6 +165,17 @@ show debug entry-values Control display of debugging info for determining frame argument values at function entry and virtual tail call frames. +set basenames-may-differ +show basenames-may-differ + Set whether a source file may have multiple base names. + (A "base name" is the name of a file with the directory part removed. + Example: The base name of "/home/user/hello.c" is "hello.c".) + If set, GDB will canonicalize file names (e.g., expand symlinks) + before comparing them. Canonicalization is an expensive operation, + but it allows the same file be known by more than one base name. + If not set (the default), all source files are assumed to have just + one base name, and gdb will do file name comparisons more efficiently. + * New remote packets QTEnable diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 15659d6..4975cd2 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2011-11-15 Doug Evans + + * gdb.texinfo (Files): Document basenames-may-differ. + 2011-11-14 Doug Evans * gdb.texinfo (Shell Commands): Document "!". diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 9255b89..f4f7f1e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -15705,6 +15705,33 @@ This is the default. @end table @end table +@cindex file name canonicalization +@cindex base name differences +When processing file names provided by the user, @value{GDBN} +frequently needs to compare them to the file names recorded in the +program's debug info. Normally, @value{GDBN} compares just the +@dfn{base names} of the files as strings, which is reasonably fast +even for very large programs. (The base name of a file is the last +portion of its name, after stripping all the leading directories.) +This shortcut in comparison is based upon the assumption that files +cannot have more than one base name. This is usually true, but +references to files that use symlinks or similar filesystem +facilities violate that assumption. If your program records files +using such facilities, or if you provide file names to @value{GDBN} +using symlinks etc., you can set @code{basenames-may-differ} to +@code{true} to instruct @value{GDBN} to completely canonicalize each +pair of file names it needs to compare. This will make file-name +comparisons accurate, but at a price of a significant slowdown. + +@table @code +@item set basenames-may-differ +@kindex set basenames-may-differ +Set whether a source file may have multiple base names. + +@item show basenames-may-differ +@kindex show basenames-may-differ +Show whether a source file may have multiple base names. +@end table @node Separate Debug Files @section Debugging Information in Separate Files diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 5e5ee7c..5e279de 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -2445,7 +2445,8 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name, struct symtab **result) { int i; - int check_basename = lbasename (name) == name; + const char *name_basename = lbasename (name); + int check_basename = name_basename == name; struct dwarf2_per_cu_data *base_cu = NULL; dw2_setup (objfile); @@ -2478,6 +2479,12 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name, && FILENAME_CMP (lbasename (this_name), name) == 0) base_cu = per_cu; + /* Before we invoke realpath, which can get expensive when many + files are involved, do a quick comparison of the basenames. */ + if (! basenames_may_differ + && FILENAME_CMP (lbasename (this_name), name_basename) != 0) + continue; + if (full_path != NULL) { const char *this_real_name = dw2_get_real_path (objfile, diff --git a/gdb/psymtab.c b/gdb/psymtab.c index 6012118..6c4507d 100644 --- a/gdb/psymtab.c +++ b/gdb/psymtab.c @@ -134,6 +134,7 @@ lookup_partial_symtab (struct objfile *objfile, const char *name, const char *full_path, const char *real_path) { struct partial_symtab *pst; + const char *name_basename = lbasename (name); ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) { @@ -142,6 +143,12 @@ lookup_partial_symtab (struct objfile *objfile, const char *name, return (pst); } + /* Before we invoke realpath, which can get expensive when many + files are involved, do a quick comparison of the basenames. */ + if (! basenames_may_differ + && FILENAME_CMP (name_basename, lbasename (pst->filename)) != 0) + continue; + /* If the user gave us an absolute path, try to find the file in this symtab and use its absolute path. */ if (full_path != NULL) @@ -172,7 +179,7 @@ lookup_partial_symtab (struct objfile *objfile, const char *name, /* Now, search for a matching tail (only if name doesn't have any dirs). */ - if (lbasename (name) == name) + if (name_basename == name) ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) { if (FILENAME_CMP (lbasename (pst->filename), name) == 0) diff --git a/gdb/symtab.c b/gdb/symtab.c index 1628f31..3d94e6b 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -112,6 +112,11 @@ void _initialize_symtab (void); /* */ +/* Non-zero if a file may be known by two different basenames. + This is the uncommon case, and significantly slows down gdb. + Default set to "off" to not slow down the common case. */ +int basenames_may_differ = 0; + /* Allow the user to configure the debugger behavior with respect to multiple-choice menus when more than one symbol matches during a symbol lookup. */ @@ -155,6 +160,7 @@ lookup_symtab (const char *name) char *real_path = NULL; char *full_path = NULL; struct cleanup *cleanup; + const char* base_name = lbasename (name); cleanup = make_cleanup (null_cleanup, NULL); @@ -180,6 +186,12 @@ got_symtab: return s; } + /* Before we invoke realpath, which can get expensive when many + files are involved, do a quick comparison of the basenames. */ + if (! basenames_may_differ + && FILENAME_CMP (base_name, lbasename (s->filename)) != 0) + continue; + /* If the user gave us an absolute path, try to find the file in this symtab and use its absolute path. */ @@ -4885,5 +4897,19 @@ Show how the debugger handles ambiguities in expressions."), _("\ Valid values are \"ask\", \"all\", \"cancel\", and the default is \"all\"."), NULL, NULL, &setlist, &showlist); + add_setshow_boolean_cmd ("basenames-may-differ", class_obscure, + &basenames_may_differ, _("\ +Set whether a source file may have multiple base names."), _("\ +Show whether a source file may have multiple base names."), _("\ +(A \"base name\" is the name of a file with the directory part removed.\n\ +Example: The base name of \"/home/user/hello.c\" is \"hello.c\".)\n\ +If set, GDB will canonicalize file names (e.g., expand symlinks)\n\ +before comparing them. Canonicalization is an expensive operation,\n\ +but it allows the same file be known by more than one base name.\n\ +If not set (the default), all source files are assumed to have just\n\ +one base name, and gdb will do file name comparisons more efficiently."), + NULL, NULL, + &setlist, &showlist); + observer_attach_executable_changed (symtab_observer_executable_changed); } diff --git a/gdb/symtab.h b/gdb/symtab.h index e5bf155..39a61f4 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1306,4 +1306,6 @@ void fixup_section (struct general_symbol_info *ginfo, struct objfile *lookup_objfile_from_block (const struct block *block); +extern int basenames_may_differ; + #endif /* !defined(SYMTAB_H) */ -- 2.7.4