aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/gcov-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/gcov-io.c')
-rw-r--r--gcc-4.9/gcc/gcov-io.c195
1 files changed, 170 insertions, 25 deletions
diff --git a/gcc-4.9/gcc/gcov-io.c b/gcc-4.9/gcc/gcov-io.c
index f226cbf0e..fc5e32e63 100644
--- a/gcc-4.9/gcc/gcov-io.c
+++ b/gcc-4.9/gcc/gcov-io.c
@@ -41,7 +41,7 @@ static void gcov_allocate (unsigned);
GCOV_LINKAGE struct gcov_var
{
- FILE *file;
+ _GCOV_FILE *file;
gcov_position_t start; /* Position of first byte of block */
unsigned offset; /* Read/write position within the block. */
unsigned length; /* Read limit in the block. */
@@ -94,7 +94,7 @@ gcov_rewrite (void)
gcov_var.mode = -1;
gcov_var.start = 0;
gcov_var.offset = 0;
- fseek (gcov_var.file, 0L, SEEK_SET);
+ _GCOV_fseek (gcov_var.file, 0L, SEEK_SET);
}
#endif
@@ -120,6 +120,7 @@ static inline gcov_unsigned_t from_file (gcov_unsigned_t value)
Return zero on failure, >0 on opening an existing file and <0 on
creating a new one. */
+#ifndef __KERNEL__
GCOV_LINKAGE int
#if IN_LIBGCOV
gcov_open (const char *name)
@@ -190,7 +191,7 @@ gcov_open (const char *name, int mode)
if (fstat (fd, &st) < 0)
{
- fclose (gcov_var.file);
+ _GCOV_fclose (gcov_var.file);
gcov_var.file = 0;
return 0;
}
@@ -203,13 +204,13 @@ gcov_open (const char *name, int mode)
gcov_var.mode = mode * 2 + 1;
#else
if (mode >= 0)
- gcov_var.file = fopen (name, (mode > 0) ? "rb" : "r+b");
+ gcov_var.file = _GCOV_fopen (name, (mode > 0) ? "rb" : "r+b");
if (gcov_var.file)
gcov_var.mode = 1;
else if (mode <= 0)
{
- gcov_var.file = fopen (name, "w+b");
+ gcov_var.file = _GCOV_fopen (name, "w+b");
if (gcov_var.file)
gcov_var.mode = mode * 2 + 1;
}
@@ -221,6 +222,24 @@ gcov_open (const char *name, int mode)
return 1;
}
+#else /* __KERNEL__ */
+
+extern _GCOV_FILE *gcov_current_file;
+
+GCOV_LINKAGE int
+gcov_open (const char *name)
+{
+ gcov_var.start = 0;
+ gcov_var.offset = gcov_var.length = 0;
+ gcov_var.overread = -1u;
+ gcov_var.error = 0;
+ gcov_var.file = gcov_current_file;
+ gcov_var.mode = 1;
+
+ return 1;
+}
+#endif /* __KERNEL__ */
+
/* Close the current gcov file. Flushes data to disk. Returns nonzero
on failure or error flag set. */
@@ -234,7 +253,7 @@ gcov_close (void)
if (gcov_var.offset && gcov_var.mode < 0)
gcov_write_block (gcov_var.offset);
#endif
- fclose (gcov_var.file);
+ _GCOV_fclose (gcov_var.file);
gcov_var.file = 0;
gcov_var.length = 0;
}
@@ -290,7 +309,7 @@ gcov_allocate (unsigned length)
static void
gcov_write_block (unsigned size)
{
- if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1)
+ if (_GCOV_fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1)
gcov_var.error = 1;
gcov_var.start += size;
gcov_var.offset -= size;
@@ -336,6 +355,47 @@ gcov_write_unsigned (gcov_unsigned_t value)
buffer[0] = value;
}
+/* Compute the total length in words required to write NUM_STRINGS
+ in STRING_ARRAY as unsigned. */
+
+GCOV_LINKAGE gcov_unsigned_t
+gcov_compute_string_array_len (char **string_array,
+ gcov_unsigned_t num_strings)
+{
+ gcov_unsigned_t len = 0, i;
+ for (i = 0; i < num_strings; i++)
+ {
+ gcov_unsigned_t string_len
+ = (strlen (string_array[i]) + sizeof (gcov_unsigned_t))
+ / sizeof (gcov_unsigned_t);
+ len += string_len;
+ len += 1; /* Each string is lead by a length. */
+ }
+ return len;
+}
+
+/* Write NUM_STRINGS in STRING_ARRAY as unsigned. */
+
+GCOV_LINKAGE void
+gcov_write_string_array (char **string_array, gcov_unsigned_t num_strings)
+{
+ gcov_unsigned_t i, j;
+ for (j = 0; j < num_strings; j++)
+ {
+ gcov_unsigned_t *aligned_string;
+ gcov_unsigned_t string_len =
+ (strlen (string_array[j]) + sizeof (gcov_unsigned_t)) /
+ sizeof (gcov_unsigned_t);
+ aligned_string = (gcov_unsigned_t *)
+ alloca ((string_len + 1) * sizeof (gcov_unsigned_t));
+ memset (aligned_string, 0, (string_len + 1) * sizeof (gcov_unsigned_t));
+ aligned_string[0] = string_len;
+ strcpy ((char*) (aligned_string + 1), string_array[j]);
+ for (i = 0; i < (string_len + 1); i++)
+ gcov_write_unsigned (aligned_string[i]);
+ }
+}
+
/* Write counter VALUE to coverage file. Sets error flag
appropriately. */
@@ -517,7 +577,7 @@ gcov_read_words (unsigned words)
gcov_allocate (gcov_var.length + words);
excess = gcov_var.alloc - gcov_var.length;
#endif
- excess = fread (gcov_var.buffer + gcov_var.length,
+ excess = _GCOV_fread (gcov_var.buffer + gcov_var.length,
1, excess << 2, gcov_var.file) >> 2;
gcov_var.length += excess;
if (gcov_var.length < words)
@@ -586,6 +646,20 @@ gcov_read_string (void)
}
#endif
+#ifdef __KERNEL__
+static int
+k_popcountll (long long x)
+{
+ int c = 0;
+ while (x)
+ {
+ c++;
+ x &= (x-1);
+ }
+ return c;
+}
+#endif
+
GCOV_LINKAGE void
gcov_read_summary (struct gcov_summary *summary)
{
@@ -612,8 +686,12 @@ gcov_read_summary (struct gcov_summary *summary)
hwint.h (where popcount_hwi is declared). However, libgcov.a
is built by the bootstrapped compiler and therefore the builtins
are always available. */
+#ifndef __KERNEL__
h_cnt += __builtin_popcount (histo_bitvector[bv_ix]);
#else
+ h_cnt += k_popcountll (histo_bitvector[bv_ix]);
+#endif
+#else
h_cnt += popcount_hwi (histo_bitvector[bv_ix]);
#endif
}
@@ -650,6 +728,78 @@ gcov_read_summary (struct gcov_summary *summary)
}
}
+/* Read LENGTH words (unsigned type) from a zero profile fixup record with the
+ number of function flags saved in NUM_FNS. Returns the int flag array, which
+ should be deallocated by caller, or NULL on error. */
+
+GCOV_LINKAGE int *
+gcov_read_comdat_zero_fixup (gcov_unsigned_t length,
+ gcov_unsigned_t *num_fns)
+{
+#ifndef __KERNEL__
+ unsigned ix, f_ix;
+ gcov_unsigned_t num = gcov_read_unsigned ();
+ /* The length consists of 1 word to hold the number of functions,
+ plus enough 32-bit words to hold 1 bit/function. */
+ gcc_assert ((num + 31) / 32 + 1 == length);
+ int *zero_fixup_flags = (int *) xcalloc (num, sizeof (int));
+ for (ix = 0; ix < length - 1; ix++)
+ {
+ gcov_unsigned_t bitvector = gcov_read_unsigned ();
+ f_ix = ix * 32;
+ while (bitvector)
+ {
+ if (bitvector & 0x1)
+ zero_fixup_flags[f_ix] = 1;
+ f_ix++;
+ bitvector >>= 1;
+ }
+ }
+ *num_fns = num;
+ return zero_fixup_flags;
+#else
+ return NULL;
+#endif
+}
+
+/* Read NUM_STRINGS strings (as an unsigned array) in STRING_ARRAY, and return
+ the number of words read. */
+
+GCOV_LINKAGE gcov_unsigned_t
+gcov_read_string_array (char **string_array, gcov_unsigned_t num_strings)
+{
+ gcov_unsigned_t i, j, len = 0;
+
+ for (j = 0; j < num_strings; j++)
+ {
+ gcov_unsigned_t string_len = gcov_read_unsigned ();
+ string_array[j] =
+ (char *) xmalloc (string_len * sizeof (gcov_unsigned_t));
+ for (i = 0; i < string_len; i++)
+ ((gcov_unsigned_t *) string_array[j])[i] = gcov_read_unsigned ();
+ len += (string_len + 1);
+ }
+ return len;
+}
+
+/* Read LENGTH words (unsigned type) from a build info record with the number
+ of strings read saved in NUM_STRINGS. Returns the string array, which
+ should be deallocated by caller, or NULL on error. */
+
+GCOV_LINKAGE char **
+gcov_read_build_info (gcov_unsigned_t length, gcov_unsigned_t *num_strings)
+{
+ gcov_unsigned_t num = gcov_read_unsigned ();
+ char **build_info_strings = (char **)
+ xmalloc (sizeof (char *) * num);
+ gcov_unsigned_t len = gcov_read_string_array (build_info_strings,
+ num);
+ if (len != length - 1)
+ return NULL;
+ *num_strings = num;
+ return build_info_strings;
+}
+
#if (!IN_LIBGCOV && IN_GCOV != 1) || defined (IN_GCOV_TOOL)
/* Read LEN words (unsigned type) and construct MOD_INFO. */
@@ -657,7 +807,7 @@ GCOV_LINKAGE void
gcov_read_module_info (struct gcov_module_info *mod_info,
gcov_unsigned_t len)
{
- gcov_unsigned_t src_filename_len, filename_len, i, j, num_strings;
+ gcov_unsigned_t src_filename_len, filename_len, i, num_strings;
mod_info->ident = gcov_read_unsigned ();
mod_info->is_primary = gcov_read_unsigned ();
mod_info->flags = gcov_read_unsigned ();
@@ -689,16 +839,7 @@ gcov_read_module_info (struct gcov_module_info *mod_info,
+ mod_info->num_system_paths
+ mod_info->num_cpp_defines + mod_info->num_cpp_includes
+ mod_info->num_cl_args;
- for (j = 0; j < num_strings; j++)
- {
- gcov_unsigned_t string_len = gcov_read_unsigned ();
- mod_info->string_array[j] =
- (char *) xmalloc (string_len * sizeof (gcov_unsigned_t));
- for (i = 0; i < string_len; i++)
- ((gcov_unsigned_t *) mod_info->string_array[j])[i] =
- gcov_read_unsigned ();
- len -= (string_len + 1);
- }
+ len -= gcov_read_string_array (mod_info->string_array, num_strings);
gcc_assert (!len);
}
#endif
@@ -719,8 +860,8 @@ gcov_sync (gcov_position_t base, gcov_unsigned_t length)
else
{
gcov_var.offset = gcov_var.length = 0;
- fseek (gcov_var.file, base << 2, SEEK_SET);
- gcov_var.start = ftell (gcov_var.file) >> 2;
+ _GCOV_fseek (gcov_var.file, base << 2, SEEK_SET);
+ gcov_var.start = _GCOV_ftell (gcov_var.file) >> 2;
}
}
#endif
@@ -734,8 +875,8 @@ gcov_seek (gcov_position_t base)
gcc_assert (gcov_var.mode < 0);
if (gcov_var.offset)
gcov_write_block (gcov_var.offset);
- fseek (gcov_var.file, base << 2, SEEK_SET);
- gcov_var.start = ftell (gcov_var.file) >> 2;
+ _GCOV_fseek (gcov_var.file, base << 2, SEEK_SET);
+ gcov_var.start = _GCOV_ftell (gcov_var.file) >> 2;
}
/* Truncate the gcov file at the current position. */
@@ -743,15 +884,19 @@ gcov_seek (gcov_position_t base)
GCOV_LINKAGE void
gcov_truncate (void)
{
+#ifdef __KERNEL__
+ gcc_assert (0);
+#else
long offs;
int filenum;
gcc_assert (gcov_var.mode < 0);
if (gcov_var.offset)
gcov_write_block (gcov_var.offset);
- offs = ftell (gcov_var.file);
+ offs = _GCOV_ftell (gcov_var.file);
filenum = fileno (gcov_var.file);
- if (offs == -1 || filenum == -1 || ftruncate (filenum, offs))
+ if (offs == -1 || filenum == -1 || _GCOV_ftruncate (filenum, offs))
gcov_var.error = 1;
+#endif /* __KERNEL__ */
}
#endif