Index: symtab.c =================================================================== RCS file: /cvs/src/src/gdb/symtab.c,v retrieving revision 1.200 diff -u -p -r1.200 symtab.c --- symtab.c 3 Jan 2009 05:57:53 -0000 1.200 +++ symtab.c 14 Jan 2009 17:10:27 -0000 @@ -281,8 +281,48 @@ lookup_partial_symtab (const char *name) } /* 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) + this symtab and use its absolute path. + + psymtab_to_fullname has a significant cost as it calls + find_and_open_source, which itself does some I/O operation + (e.g. open). In cumulative, it can take several seconds with + large systems (around 4000 files), if the file is accessed + through a slow file system (e.g. NFS). Here is a shell script + that you can use to generate such a large system: + + echo "void main () {}" > t.c + gcc -c -g t.c + previous="" + for i in 0 1 2 3 ; do + for j in 0 1 2 3 4 5 6 7 8 9 ; do + for k in 0 1 2 3 4 5 6 7 8 9 ; do + for l in 0 1 2 3 4 5 6 7 8 9 ; do + name="${i}${j}${k}${l}" + echo "void f_$name () {}" >> f_$name.c + gcc -c -g f_$name.c + ld -r f_$name.o $previous -o main_$name + rm f_*.o + rm $previous + previous=main_$name + done + done + done + done + gcc $previous t.o -o main + + Using the following GDB commands should demonstrate the problem: + list /f_0000.c:1 + list /f_3999.c:1 + + To reduce the cost, the full comparison is done if and only if + the base names are not different. This would have a low cost, + as it only does string manipulations. This optimisation has no + impact on relatives path (e.g. the more common 'list + f_0000.c:1'), as in this case full_path == NULL. */ + + if (full_path != NULL + && FILENAME_CMP (lbasename (full_path), + lbasename (pst->filename)) == 0) { psymtab_to_fullname (pst); if (pst->fullname != NULL @@ -292,7 +332,9 @@ lookup_partial_symtab (const char *name) } } - if (real_path != NULL) + if (real_path != NULL + && FILENAME_CMP (lbasename (full_path), + lbasename (pst->filename)) == 0) { char *rp = NULL; psymtab_to_fullname (pst);