2014-07-26 Nathan Sidwell * libgcov-driver.c (struct gcov_filename_aux): Rename ... (struct gcov_filename): ... here. Include buffer and max length fields. (gcov_max_filename): Remove. (gi_filename): Remove. (gcov_exit_compute_summary): Compute max filename here. (gcov_exit_merge_gcda): Add filename parm, adjust. (gcov_exit_merge_summary): Likewise. (gcov_exit_dump_gcov): Adjust for struct gcov_filename changes. (gcov_exit): Likewise. (__gcov_init): Don't calculate max length here. * libgcov_util.c (max_filename_len): Remove. (read_gcda_file): Don't calculate max length here. (gcov_read_profile_dir): Don't propagate here. * libgcov-driver-system.c (alloc_filename_struct): Adjust for struct gcov_filename changes. (gcov_exit_open_gcda_file): Likewise. Index: libgcc/libgcov-driver-system.c =================================================================== --- libgcc/libgcov-driver-system.c (revision 213058) +++ libgcc/libgcov-driver-system.c (working copy) @@ -83,118 +83,105 @@ create_file_directory (char *filename) } static void -allocate_filename_struct (struct gcov_filename_aux *gf) +allocate_filename_struct (struct gcov_filename *gf) { const char *gcov_prefix; - int gcov_prefix_strip = 0; size_t prefix_length; - char *gi_filename_up; + int strip = 0; - gcc_assert (gf); { /* Check if the level of dirs to strip off specified. */ char *tmp = getenv("GCOV_PREFIX_STRIP"); if (tmp) { - gcov_prefix_strip = atoi (tmp); + strip = atoi (tmp); /* Do not consider negative values. */ - if (gcov_prefix_strip < 0) - gcov_prefix_strip = 0; + if (strip < 0) + strip = 0; } } + gf->strip = strip; /* Get file name relocation prefix. Non-absolute values are ignored. */ gcov_prefix = getenv("GCOV_PREFIX"); - if (gcov_prefix) - { - prefix_length = strlen(gcov_prefix); - - /* Remove an unnecessary trailing '/' */ - if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) - prefix_length--; - } - else - prefix_length = 0; + prefix_length = gcov_prefix ? strlen (gcov_prefix) : 0; + + /* Remove an unnecessary trailing '/' */ + if (prefix_length && IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) + prefix_length--; /* If no prefix was specified and a prefix stip, then we assume relative. */ - if (gcov_prefix_strip != 0 && prefix_length == 0) + if (!prefix_length && gf->strip) { gcov_prefix = "."; prefix_length = 1; } - /* Allocate and initialize the filename scratch space plus one. */ - gi_filename = (char *) xmalloc (prefix_length + gcov_max_filename + 2); - if (prefix_length) - memcpy (gi_filename, gcov_prefix, prefix_length); - gi_filename_up = gi_filename + prefix_length; + gf->prefix = prefix_length; - gf->gi_filename_up = gi_filename_up; - gf->prefix_length = prefix_length; - gf->gcov_prefix_strip = gcov_prefix_strip; + /* Allocate and initialize the filename scratch space. */ + gf->filename = (char *) xmalloc (gf->max_length + prefix_length + 2); + if (prefix_length) + memcpy (gf->filename, gcov_prefix, prefix_length); } /* Open a gcda file specified by GI_FILENAME. Return -1 on error. Return 0 on success. */ static int -gcov_exit_open_gcda_file (struct gcov_info *gi_ptr, struct gcov_filename_aux *gf) +gcov_exit_open_gcda_file (struct gcov_info *gi_ptr, + struct gcov_filename *gf) { - int gcov_prefix_strip; - size_t prefix_length; - char *gi_filename_up; - const char *fname, *s; + const char *fname = gi_ptr->filename; + char *dst = gf->filename + gf->prefix; - gcov_prefix_strip = gf->gcov_prefix_strip; - gi_filename_up = gf->gi_filename_up; - prefix_length = gf->prefix_length; fname = gi_ptr->filename; - /* Avoid to add multiple drive letters into combined path. */ - if (prefix_length != 0 && HAS_DRIVE_SPEC(fname)) - fname += 2; - /* Build relocated filename, stripping off leading directories from the initial filename if requested. */ - if (gcov_prefix_strip > 0) + if (gf->strip > 0) { - int level = 0; + const char *probe = fname; + int level; - s = fname; - if (IS_DIR_SEPARATOR(*s)) - ++s; - - /* Skip selected directory levels. */ - for (; (*s != '\0') && (level < gcov_prefix_strip); s++) - if (IS_DIR_SEPARATOR(*s)) + /* Remove a leading separator, without counting it. */ + if (IS_DIR_SEPARATOR (*probe)) + probe++; + + /* Skip selected directory levels. If we fall off the end, we + keep the final part. */ + for (level = gf->strip; *probe && level; probe++) + if (IS_DIR_SEPARATOR (*probe)) { - fname = s; - level++; + fname = probe; + level--; } } /* Update complete filename with stripped original. */ - if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname)) + if (gf->prefix) { - /* If prefix is given, add directory separator. */ - strcpy (gi_filename_up, "/"); - strcpy (gi_filename_up + 1, fname); + /* Avoid to add multiple drive letters into combined path. */ + if (HAS_DRIVE_SPEC(fname)) + fname += 2; + + if (!IS_DIR_SEPARATOR (*fname)) + *dst++ = '/'; } - else - strcpy (gi_filename_up, fname); + strcpy (dst, fname); - if (!gcov_open (gi_filename)) + if (!gcov_open (gf->filename)) { /* Open failed likely due to missed directory. Create directory and retry to open file. */ - if (create_file_directory (gi_filename)) + if (create_file_directory (gf->filename)) { - fprintf (stderr, "profiling:%s:Skip\n", gi_filename); + fprintf (stderr, "profiling:%s:Skip\n", gf->filename); return -1; } - if (!gcov_open (gi_filename)) + if (!gcov_open (gf->filename)) { - fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename); + fprintf (stderr, "profiling:%s:Cannot open\n", gf->filename); return -1; } } Index: libgcc/libgcov-driver.c =================================================================== --- libgcc/libgcov-driver.c (revision 213058) +++ libgcc/libgcov-driver.c (working copy) @@ -66,6 +66,17 @@ struct gcov_summary_buffer struct gcov_summary summary; }; +/* A struct that bundles all the related information about the + gcda filename. */ + +struct gcov_filename +{ + char *filename; /* filename buffer */ + size_t max_length; /* maximum filename length */ + int strip; /* leading chars to strip from filename */ + size_t prefix; /* chars to prepend to filename */ +}; + /* Chain of per-object gcov structures. */ #ifndef IN_GCOV_TOOL /* We need to expose this static variable when compiling for gcov-tool. */ @@ -73,13 +84,6 @@ static #endif struct gcov_info *gcov_list; -/* Size of the longest file name. */ -/* We need to expose this static variable when compiling for gcov-tool. */ -#ifndef IN_GCOV_TOOL -static -#endif -size_t gcov_max_filename = 0; - /* Flag when the profile has already been dumped via __gcov_dump(). */ static int gcov_dump_complete; @@ -275,8 +279,6 @@ gcov_compute_histogram (struct gcov_summ } } -/* gcda filename. */ -static char *gi_filename; /* buffer for the fn_data from another program. */ static struct gcov_fn_buffer *fn_buffer; /* buffer for summary from other programs to be written out. */ @@ -286,11 +288,13 @@ static struct gcov_summary_buffer *sum_b functions executed once may mistakely become cold. */ static int run_accounted = 0; -/* This funtions computes the program level summary and the histo-gram. - It computes and returns CRC32 and stored summary in THIS_PRG. */ +/* This function computes the program level summary and the histo-gram. + It computes and returns CRC32 and stored summary in THIS_PRG. + Also determines the longest filename length of the info files. */ static gcov_unsigned_t -gcov_exit_compute_summary (struct gcov_summary *this_prg) +gcov_exit_compute_summary (struct gcov_summary *this_prg, + size_t *max_length) { struct gcov_info *gi_ptr; const struct gcov_fn_info *gfi_ptr; @@ -303,8 +307,13 @@ gcov_exit_compute_summary (struct gcov_s /* Find the totals for this execution. */ memset (this_prg, 0, sizeof (*this_prg)); + *max_length = 0; for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) { + size_t len = strlen (gi_ptr->filename); + if (len > *max_length) + *max_length = len; + crc32 = crc32_unsigned (crc32, gi_ptr->stamp); crc32 = crc32_unsigned (crc32, gi_ptr->n_functions); @@ -345,14 +354,6 @@ gcov_exit_compute_summary (struct gcov_s return crc32; } -/* A struct that bundles all the related information about the - gcda filename. */ -struct gcov_filename_aux{ - char *gi_filename_up; - int gcov_prefix_strip; - size_t prefix_length; -}; - /* Including system dependent components. */ #include "libgcov-driver-system.c" @@ -361,7 +362,8 @@ struct gcov_filename_aux{ Return -1 on error. In this case, caller will goto read_fatal. */ static int -gcov_exit_merge_gcda (struct gcov_info *gi_ptr, +gcov_exit_merge_gcda (const char *filename, + struct gcov_info *gi_ptr, struct gcov_summary *prg_p, struct gcov_summary *this_prg, gcov_position_t *summary_pos_p, @@ -376,7 +378,7 @@ gcov_exit_merge_gcda (struct gcov_info * struct gcov_summary_buffer **sum_tail = &sum_buffer; length = gcov_read_unsigned (); - if (!gcov_version (gi_ptr, length, gi_filename)) + if (!gcov_version (gi_ptr, length, filename)) return -1; length = gcov_read_unsigned (); @@ -451,8 +453,7 @@ gcov_exit_merge_gcda (struct gcov_info * it back out -- we'll be inserting data before this point, so cannot simply keep the data in the file. */ - fn_tail = buffer_fn_data (gi_filename, - gi_ptr, fn_tail, f_ix); + fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix); if (!fn_tail) goto read_mismatch; continue; @@ -494,14 +495,14 @@ gcov_exit_merge_gcda (struct gcov_info * { read_mismatch:; gcov_error ("profiling:%s:Merge mismatch for %s %u\n", - gi_filename, f_ix >= 0 ? "function" : "summary", + filename, f_ix >= 0 ? "function" : "summary", f_ix < 0 ? -1 - f_ix : f_ix); return -1; } return 0; read_error: - gcov_error ("profiling:%s:%s merging\n", gi_filename, + gcov_error ("profiling:%s:%s merging\n", filename, error < 0 ? "Overflow": "Error"); return -1; } @@ -606,7 +607,8 @@ gcov_exit_write_gcda (const struct gcov_ Return -1 on error. Return 0 on success. */ static int -gcov_exit_merge_summary (const struct gcov_info *gi_ptr, struct gcov_summary *prg, +gcov_exit_merge_summary (const char *filename, + const struct gcov_info *gi_ptr, struct gcov_summary *prg, struct gcov_summary *this_prg, gcov_unsigned_t crc32, struct gcov_summary *all_prg __attribute__ ((unused))) { @@ -644,7 +646,7 @@ gcov_exit_merge_summary (const struct gc else if (cs_prg->runs) { gcov_error ("profiling:%s:Merge mismatch for summary.\n", - gi_filename); + filename); return -1; } #if !GCOV_LOCKED @@ -670,7 +672,7 @@ gcov_exit_merge_summary (const struct gc { gcov_error ("profiling:%s:Data file mismatch - some " "data files may have been concurrently " - "updated without locking support\n", gi_filename); + "updated without locking support\n", filename); all_prg->checksum = ~0u; } #endif @@ -689,7 +691,7 @@ gcov_exit_merge_summary (const struct gc summaries separate. */ static void -gcov_exit_dump_gcov (struct gcov_info *gi_ptr, struct gcov_filename_aux *gf, +gcov_exit_dump_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf, gcov_unsigned_t crc32, struct gcov_summary *all_prg, struct gcov_summary *this_prg) { @@ -712,11 +714,11 @@ gcov_exit_dump_gcov (struct gcov_info *g /* Merge data from file. */ if (tag != GCOV_DATA_MAGIC) { - gcov_error ("profiling:%s:Not a gcov data file\n", gi_filename); + gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename); goto read_fatal; } - error = gcov_exit_merge_gcda (gi_ptr, &prg, this_prg, &summary_pos, &eof_pos, - crc32); + error = gcov_exit_merge_gcda (gf->filename, gi_ptr, &prg, this_prg, + &summary_pos, &eof_pos, crc32); if (error == -1) goto read_fatal; } @@ -729,7 +731,8 @@ gcov_exit_dump_gcov (struct gcov_info *g summary_pos = eof_pos; } - error = gcov_exit_merge_summary (gi_ptr, &prg, this_prg, crc32, all_prg); + error = gcov_exit_merge_summary (gf->filename, gi_ptr, &prg, this_prg, + crc32, all_prg); if (error == -1) goto read_fatal; @@ -744,7 +747,7 @@ read_fatal:; gcov_error (error < 0 ? "profiling:%s:Overflow writing\n" : "profiling:%s:Error writing\n", - gi_filename); + gf->filename); } @@ -756,7 +759,7 @@ void gcov_exit (void) { struct gcov_info *gi_ptr; - struct gcov_filename_aux gf; + struct gcov_filename gf; gcov_unsigned_t crc32; struct gcov_summary all_prg; struct gcov_summary this_prg; @@ -767,8 +770,8 @@ gcov_exit (void) return; gcov_dump_complete = 1; - - crc32 = gcov_exit_compute_summary (&this_prg); + + crc32 = gcov_exit_compute_summary (&this_prg, &gf.max_length); allocate_filename_struct (&gf); #if !GCOV_LOCKED @@ -780,8 +783,7 @@ gcov_exit (void) gcov_exit_dump_gcov (gi_ptr, &gf, crc32, &all_prg, &this_prg); run_accounted = 1; - if (gi_filename) - free (gi_filename); + free (gf.filename); } /* Reset all counters to zero. */ @@ -826,12 +828,6 @@ __gcov_init (struct gcov_info *info) return; if (gcov_version (info, info->version, 0)) { - size_t filename_length = strlen(info->filename); - - /* Refresh the longest file name information */ - if (filename_length > gcov_max_filename) - gcov_max_filename = filename_length; - if (!gcov_list) atexit (gcov_exit); Index: libgcc/libgcov-util.c =================================================================== --- libgcc/libgcov-util.c (revision 213058) +++ libgcc/libgcov-util.c (working copy) @@ -38,7 +38,6 @@ see the files COPYING3 and COPYING.RUNTI extern gcov_position_t gcov_position(); extern int gcov_is_error(); -extern size_t gcov_max_filename; /* Verbose mode for debug. */ static int verbose; @@ -78,8 +77,6 @@ static int k_ctrs_mask[GCOV_COUNTERS]; static struct gcov_ctr_info k_ctrs[GCOV_COUNTERS]; /* Number of kind of counters that have been seen. */ static int k_ctrs_types; -/* The longest length of all the filenames. */ -static int max_filename_len; /* Merge functions for counters. */ #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) __gcov_merge ## FN_TYPE, @@ -301,13 +298,11 @@ read_gcda_file (const char *filename) num_fn_info = 0; curr_fn_info = 0; { - char *str_dup = (char*) xmalloc (strlen (filename) + 1); - int len; + size_t len = strlen (filename) + 1; + char *str_dup = (char*) xmalloc (len); - strcpy (str_dup, filename); + memcpy (str_dup, filename, len); obj_info->filename = str_dup; - if ((len = strlen (filename)) > max_filename_len) - max_filename_len = len; } /* Read stamp. */ @@ -433,8 +428,7 @@ read_profile_dir_init (void) /* Driver for read a profile directory and convert into gcov_info list in memory. Return NULL on error, - Return the head of gcov_info list on success. - Note the file static variable GCOV_MAX_FILENAME is also set. */ + Return the head of gcov_info list on success. */ struct gcov_info * gcov_read_profile_dir (const char* dir_name, int recompute_summary ATTRIBUTE_UNUSED) @@ -462,11 +456,6 @@ gcov_read_profile_dir (const char* dir_n free (pwd); - /* gcov_max_filename is defined in libgcov.c that records the - max filename len. We need to set it here to allocate the - array for dumping. */ - gcov_max_filename = max_filename_len; - return gcov_info_head;; }