On 12/21/2017 10:13 AM, Martin Liška wrote:
> On 12/20/2017 06:45 PM, Jakub Jelinek wrote:
>> Another thing is that the "/" in there is wrong, so
>> const char dir_separator_str[] = { DIR_SEPARATOR, '\0' };
>> char *b = concat (profile_data_prefix, dir_separator_str, pwd, NULL);
>> needs to be used instead.
>
> This looks much nicer, I forgot about DIR_SEPARATOR.
>
>> Does profile_data_prefix have any dir separators stripped from the end?
>
> That's easy to achieve..
>
>> Is pwd guaranteed to be relative in this case?
>
> .. however this is absolute path, which would be problematic on a DOC based
> FS.
> Maybe we should do the same path mangling as we do for purpose of gcov:
>
> https://github.com/gcc-mirror/gcc/blob/master/gcc/gcov.c#L2424
Hi.
I decided to implement that. Which means for:
$ gcc -fprofile-generate=/tmp/myfolder empty.c -O2 && ./a.out
we get following file:
/tmp/myfolder/#home#marxin#Programming#testcases#tmp#empty.gcda
That guarantees we have a unique file path. As seen in the PR it
can produce a funny ICE.
I've been testing the patch.
Ready after it finishes tests?
Martin
>
> What do you think about it?
> Regarding the string manipulation: I'm not an expert, but work with string in
> C
> is for me always a pain :)
>
> Martin
>
>From 386a4561a4d1501e8959871791289e95f6a89af5 Mon Sep 17 00:00:00 2001
From: marxin <[email protected]>
Date: Wed, 16 Aug 2017 10:22:57 +0200
Subject: [PATCH] When using -fprofile-generate=/some/path mangle absolute path
of file (PR lto/85759).
gcc/ChangeLog:
2018-05-16 Martin Liska <[email protected]>
PR lto/85759
* coverage.c (coverage_init): Mangle full path name.
* doc/invoke.texi: Document the change.
* gcov-io.c (mangle_path): New.
* gcov-io.h (mangle_path): Likewise.
* gcov.c (mangle_name): Use mangle_path for path mangling.
---
gcc/coverage.c | 20 ++++++++++++++++++--
gcc/doc/invoke.texi | 3 +++
gcc/gcov-io.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
gcc/gcov-io.h | 1 +
gcc/gcov.c | 37 +------------------------------------
5 files changed, 72 insertions(+), 38 deletions(-)
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 32ef298a11f..6e621c3ff96 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -1227,8 +1227,24 @@ coverage_init (const char *filename)
g->get_passes ()->get_pass_profile ()->static_pass_number;
g->get_dumps ()->dump_start (profile_pass_num, NULL);
- if (!profile_data_prefix && !IS_ABSOLUTE_PATH (filename))
- profile_data_prefix = getpwd ();
+ if (!IS_ABSOLUTE_PATH (filename))
+ {
+ /* When a profile_data_prefix is provided, then mangle full path
+ 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 = mangle_path (filename);
+ len = strlen (filename);
+ }
+ else
+ profile_data_prefix = getpwd ();
+ }
if (profile_data_prefix)
prefix_len = strlen (profile_data_prefix);
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ca3772bbebf..4859cec0ab5 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -11253,6 +11253,9 @@ and used by @option{-fprofile-use} and @option{-fbranch-probabilities}
and its related options. Both absolute and relative paths can be used.
By default, GCC uses the current directory as @var{path}, thus the
profile data file appears in the same directory as the object file.
+In order to prevent filename clashing, if object file name is not an absolute
+path, we mangle absolute path of @file{@var{sourcename}.gcda} file and
+use it as file name of a @file{.gcda} file.
@item -fprofile-generate
@itemx -fprofile-generate=@var{path}
diff --git a/gcc/gcov-io.c b/gcc/gcov-io.c
index 3fe1e613ebc..68660d6d3cf 100644
--- a/gcc/gcov-io.c
+++ b/gcc/gcov-io.c
@@ -576,6 +576,55 @@ gcov_read_counter (void)
return value;
}
+/* Mangle filename path of BASE and output new allocated pointer with
+ mangled path. */
+
+char *
+mangle_path (char const *base)
+{
+ /* Convert '/' to '#', convert '..' to '^',
+ convert ':' to '~' on DOS based file system. */
+ const char *probe;
+ char *buffer = (char *)xmalloc (strlen (base) + 10);
+ char *ptr = buffer;
+
+#if HAVE_DOS_BASED_FILE_SYSTEM
+ if (base[0] && base[1] == ':')
+ {
+ ptr[0] = base[0];
+ ptr[1] = '~';
+ ptr += 2;
+ base += 2;
+ }
+#endif
+ for (; *base; base = probe)
+ {
+ size_t len;
+
+ for (probe = base; *probe; probe++)
+ if (*probe == '/')
+ break;
+ len = probe - base;
+ if (len == 2 && base[0] == '.' && base[1] == '.')
+ *ptr++ = '^';
+ else
+ {
+ memcpy (ptr, base, len);
+ ptr += len;
+ }
+ if (*probe)
+ {
+ *ptr++ = '#';
+ probe++;
+ }
+ }
+
+ /* Terminate the string. */
+ *ptr = '\0';
+
+ return buffer;
+}
+
/* We need to expose the below function when compiling for gcov-tool. */
#if !IN_LIBGCOV || defined (IN_GCOV_TOOL)
diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index d6389c48908..cdf9f4cac3f 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -381,6 +381,7 @@ GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *) ATTRIBUTE_HIDDEN;
GCOV_LINKAGE const char *gcov_read_string (void);
GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/,
gcov_unsigned_t /*length */);
+char *mangle_path (char const *base);
#if !IN_GCOV
/* Available outside gcov */
diff --git a/gcc/gcov.c b/gcc/gcov.c
index 6bbfe33ca33..7c1950d5df9 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -2434,42 +2434,7 @@ mangle_name (char const *base, char *ptr)
ptr += len;
}
else
- {
- /* Convert '/' to '#', convert '..' to '^',
- convert ':' to '~' on DOS based file system. */
- const char *probe;
-
-#if HAVE_DOS_BASED_FILE_SYSTEM
- if (base[0] && base[1] == ':')
- {
- ptr[0] = base[0];
- ptr[1] = '~';
- ptr += 2;
- base += 2;
- }
-#endif
- for (; *base; base = probe)
- {
- size_t len;
-
- for (probe = base; *probe; probe++)
- if (*probe == '/')
- break;
- len = probe - base;
- if (len == 2 && base[0] == '.' && base[1] == '.')
- *ptr++ = '^';
- else
- {
- memcpy (ptr, base, len);
- ptr += len;
- }
- if (*probe)
- {
- *ptr++ = '#';
- probe++;
- }
- }
- }
+ ptr = mangle_path (base);
return ptr;
}
--
2.16.3