Index: buildsym.c =================================================================== --- buildsym.c (revision 44) +++ buildsym.c (working copy) @@ -574,13 +574,32 @@ make_blockvector (struct objfile *objfil return (blockvector); } + +static int +paths_likely_equal_p (const char *path1, const char *path2) +{ + /* The purpose of this function is to handle situations where + the path contains ".", or ".." or double-directory separators. + Before doing the comparison, we manually resolve the paths in + so that ".", ".." and double directory separators no longer + appear. This will allow us to performe a pure string comparison + to determine whether two paths are identical or not. */ + + /* If the paths are already identical, then obviously they are equal. */ + if (FILENAME_CMP (path1, path2) == 0) + return 1; + + /* Normalize path1 and path2, and redo the comparison. */ + [...] +} + /* Start recording information about source code that came from an included (or otherwise merged-in) source file with a different name. NAME is the name of the file (cannot be NULL), DIRNAME is the directory in which the file was compiled (or NULL if not known). */ void -start_subfile (char *name, char *dirname) +start_subfile_1 (char *name, char *dirname) { struct subfile *subfile; @@ -589,27 +608,24 @@ start_subfile (char *name, char *dirname for (subfile = subfiles; subfile; subfile = subfile->next) { - char *subfile_name; - - /* If NAME is an absolute path, and this subfile is not, then - attempt to create an absolute path to compare. */ - if (IS_ABSOLUTE_PATH (name) - && !IS_ABSOLUTE_PATH (subfile->name) - && subfile->dirname != NULL) - subfile_name = concat (subfile->dirname, SLASH_STRING, - subfile->name, NULL); - else - subfile_name = subfile->name; - - if (FILENAME_CMP (subfile_name, name) == 0) - { + /* First, verify that the basename matches. */ + if (FILENAME_CMP (subfile->name, name) != 0) + continue; + + /* Next, verify that the directory name matches too. Some programs + may include two files with the same name but in a different + directory. + + If either DIRNAME or SUBFILE->DIRNAME is NULL, then we cannot + do the verification. In that case, we cannot do the verification, + but the safest bet is that the files are identical. */ + if (dirname == NULL + || subfile->dirname == NULL + || paths_likely_equal_p (dirname, subfile->dirname)) + { current_subfile = subfile; - if (subfile_name != subfile->name) - xfree (subfile_name); return; - } - if (subfile_name != subfile->name) - xfree (subfile_name); + } } /* This subfile is not known. Add an entry for it. Make an entry @@ -681,6 +697,53 @@ start_subfile (char *name, char *dirname } } +/* This function is a wrapper around start_subfile_1 which rewrites + a bit NAME and DIRNAME to make sure that we are always consistent + in how we create subfiles: Turn NAME into a basename, and adjust + DIRNAME accordingly. */ + +void +start_subfile (char *name, char *dirname) +{ + char *new_name, new_dir_name; + + new_name = lbasename (name); + + /* The simple usual case: NAME is the name of a file without any path + (in other words, it's already a basename). In that case, we use + DIR_NAME as is. */ + if (FILENAME_CMP (new_name, name) == 0) + new_dir_name = dir_name; + + /* Another simple case: NAME is an absolute PATH. In that case, + we can ignore the compilation dir, and use the path inside NAME + as the dir name. */ + else if (IS_ABSOLUTE_PATH (name)) + new_dir_name = ldirname (name); + + /* Otherwise, NAME is a relative PATH, so we extract the relative + path from name, and append it at the end of DIRNAME. IF DIRNAME + is NULL, then we use that relative path as the DIRNAME. */ + else + { + char *name_relative_path = ldirname (name); + + if (dirname != NULL) + { + new_dir_name = concat (dirname, SLASH_STRING, name_relative_path, + NULL); + xfree (name_relative_path); + } + else + new_dir_name = name_relative_path; + } + + start_subfile_1 (new_name, new_dir_name); + + xfree (new_name); + xfree (new_dir_name); +} + /* For stabs readers, the first N_SO symbol is assumed to be the source file name, and the subfile struct is initialized using that assumption. If another N_SO symbol is later seen, immediately