Re: [Patch] Improve path lookup of absolute source file

Francois Rigault
2009-03-17T14:37:50Z

Hello

I think we can come up with a solution that does not
introduce the holes from the previous one.

In the patch below, the file name lookup is done in 2 times :

The first pass will try to resolve the file name only if basenames
match. The second pass will try to resolve the file name as before,
resolving all the files path from the symtab.

This guarantee that the files will be found as before even if the
basenames differ. Also, there is a strong probability that the lookup
will end after the first pass, which is a huge time saver when the
lookup is done on a slow IO file system.

In the patch below, the lookup routine has been put in a new
function, and is called 2 times (one in each passes). The lookup
routine itself has been optimized so that psymtab_to_fullname
is not called twice both for full_path lookup and real_path lookup.

Here, our binary being compiled with all the sources on NFS,
this approach just suppress the 30s freeze when putting the first
breakpoint.

Please see the patch against CVS head below.

Best regards,

Francois

----------

--- gdb/symtab.c 2009-03-13 22:02:58.000000000 +0100
+++ gdb/symtab.c 2009-03-17 15:06:28.000011000 +0100
@@ -110,6 +110,10 @@ struct symbol *lookup_symbol_aux_psymtab

static int file_matches (char *, char **, int);

+static int
+file_matches_symbol(const char *full_path, const char *real_path,
+ struct partial_symtab *pst);
+
static void print_symbol_info (domain_enum,
struct symtab *, struct symbol *, int, char
*);

@@ -251,6 +255,45 @@ got_symtab:
goto got_symtab;
}

+/* Check if a file identified by its full_path (possibly NULL) and
+ its real_path (possibly NULL) matches the given symbol. */
+
+static int
+file_matches_symbol(const char *full_path, const char *real_path,
+ struct partial_symtab *pst)
+{
+ if ( (full_path != NULL) || (real_path != NULL) )
+ {
+ psymtab_to_fullname(pst);
+ }
+
+
+ if (full_path != NULL)
+ {
+ if (pst->fullname != NULL
+ && FILENAME_CMP (full_path, pst->fullname) == 0)
+ {
+ return 1;
+ }
+ }
+
+ if (real_path != NULL)
+ {
+ char *rp = NULL;
+ if (pst->fullname != NULL)
+ {
+ rp = gdb_realpath (pst->fullname);
+ make_cleanup (xfree, rp);
+ }
+ if (rp != NULL && FILENAME_CMP (real_path, rp) == 0)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/* Lookup the partial symbol table of a source file named NAME.
*If* there is no '/' in the name, a match after a '/'
in the psymtab filename will also work. */
@@ -273,6 +316,12 @@ lookup_partial_symtab (const char *name)
make_cleanup (xfree, real_path);
}

+ /* If the user gave us an absolute path, try to find the file in
+ this symtab and use its absolute path. */
+
+ /* Do a first quick pass where we try to match symbol and files
+ using their names. This phase is inexpensive in IOs, and will
+ match for most of the symbols. */
ALL_PSYMTABS (objfile, pst)
{
if (FILENAME_CMP (name, pst->filename) == 0)
@@ -280,31 +329,23 @@ lookup_partial_symtab (const char *name)
return (pst);
}

- /* 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)
+ if (FILENAME_CMP (lbasename(name), lbasename(pst->filename)) == 0)
{
- psymtab_to_fullname (pst);
- if (pst->fullname != NULL
- && FILENAME_CMP (full_path, pst->fullname) == 0)
- {
- return pst;
- }
+ if (file_matches_symbol(full_path, real_path, pst))
+ {
+ return (pst);
+ }
}
+ }

- if (real_path != NULL)
+ /* Do a second pass. Here we will try to match the absolute file
+ path with the absolute file path from the symtab. Since there can
+ be a lot of files in the symtab, this pass is expensive in IOs. */
+ ALL_PSYMTABS (objfile, pst)
+ {
+ if (file_matches_symbol(full_path, real_path, pst))
{
- char *rp = NULL;
- psymtab_to_fullname (pst);
- if (pst->fullname != NULL)
- {
- rp = gdb_realpath (pst->fullname);
- make_cleanup (xfree, rp);
- }
- if (rp != NULL && FILENAME_CMP (real_path, rp) == 0)
- {
- return pst;
- }
+ return (pst);
}
}