[Bug gcov-profile/94570] -fprofile-dir is broken on Cygwin
marxin at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Wed Apr 15 07:47:30 GMT 2020
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94570
--- Comment #2 from Martin Liška <marxin at gcc dot gnu.org> ---
(In reply to John Selbie from comment #0)
> The following bug is unique to gcc and g++ running on Cygwin. I can repro
> this on both gcc 9.2 and 9.3.
>
> Using almost any source file, execute the following to start the first phase
> of a profile guided optimization on Cygwin with a target directory to store
> .gcda files:
>
> $ g++ anyprogram.cpp -o anyprogram -fprofile-generate
> -fprofile-dir=profiledata
>
> Then run the compiled code to start the program:
>
> $ ./anyprogram.exe
>
> After the program completes, the following output is revealed to show that
> the coverage code couldn't save the gcda file:
>
> profiling:profiledata/#home#jselbie\anyprogram.gcda:Skip
>
> The .gcda file is not crated.
Thank you for the report and the analysis.
I see, we mix '/' and *separator (in this case '\'). So a possible fix could
be:
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 30ae84df90f..aa1d1b0d120 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -1199,6 +1199,13 @@ coverage_obj_finish (vec<constructor_elt, va_gc> *ctor)
void
coverage_init (const char *filename)
{
+#if HAVE_DOS_BASED_FILE_SYSTEM
+ const char *dir_separator = "\\";
+#else
+ const char *dir_separator = "/";
+#endif
+
+
int len = strlen (filename);
int prefix_len = 0;
@@ -1215,12 +1222,7 @@ coverage_init (const char *filename)
of filename in order to prevent file path clashing. */
if (profile_data_prefix)
{
-#if HAVE_DOS_BASED_FILE_SYSTEM
- const char *separator = "\\";
-#else
- const char *separator = "/";
-#endif
- filename = concat (getpwd (), separator, filename, NULL);
+ filename = concat (getpwd (), dir_separator, filename, NULL);
filename = mangle_path (filename);
len = strlen (filename);
}
@@ -1238,7 +1240,7 @@ coverage_init (const char *filename)
if (profile_data_prefix)
{
memcpy (da_file_name, profile_data_prefix, prefix_len);
- da_file_name[prefix_len++] = '/';
+ da_file_name[prefix_len++] = *dir_separator;
}
memcpy (da_file_name + prefix_len, filename, len);
strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
>
> You can even see the mangled string it in the resulting binary:
>
> $ strings anyprogram.exe | grep jselbie
> profiledata/#home#jselbie\anyprogram.gcda
>
>
> I see two possible issues that's causing this.
>
> First, the anyprogram.gcda string is getting appended with a back slash
> instead of a forward slash
>
> A quick cursory glace of GCC sources would suggest the issue is in
> \gcc\coverage.c. Looking at the code for coverage_init inside
> gcc/converage.c reveals the following:
>
> if (profile_data_prefix)
> {
> #if HAVE_DOS_BASED_FILE_SYSTEM
> const char *separator = "\\";
> #else
> const char *separator = "/";
> #endif
> filename = concat (getpwd (), separator, filename, NULL);
> filename = mangle_path (filename);
> len = strlen (filename);
> }
>
>
> Another cursory search of gcc sources suggest HAVE_DOS_BASED_FILE_SYSTEM is
> defined by this preprocessor stuff:
>
> #if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined
> (__CYGWIN__)
> # ifndef HAVE_DOS_BASED_FILE_SYSTEM
> # define HAVE_DOS_BASED_FILE_SYSTEM 1
> # endif
>
> Because HAVE_DOS_BASED_FILE_SYSTEM is getting defined for Cygwin, then
> coverage_init is going to use a backslash separator as well. Whether CYGWIN
> should be considered a DOS based file system or a special exception needs to
> be made in coverage_init, well, I'm not sure.
I guess we should use backslashes, or?
>
> The second issue is with the way the path gets mangled with # chars. That's
> not consistent with the Linux build (at least with g++ 7.5 that I have
> going).
Yes, that's expected and it's the answer for PR85759.
>
>
> The workaround for now is to skip using the -fprofile-dir flag and allow
> default save behavior for the gcda flag.
More information about the Gcc-bugs
mailing list