d6d3f03341
2013-11-12 Rong Xu <xur@google.com> The patch re-factors libgcov.c to make it better modulelized. It contains two pieces of work: 1. break gcov_exit() into the following structure: gcov_exit() --> gcov_exit_compute_summary() --> allocate_filename_struct() for gi_ptr in gcov_list --> gcov_exit_dump_gcov() --> gcov_exit_open_gcda_file() --> gcov_exit_merge_gcda () --> gcov_exit_merge_summary () --> gcov_exit_write_gcda () 2. split libgcov.c into the following files: libgcov-profiler.c libgcov-merge.c libgcov-interface.c libgcov-driver.c libgcov-driver-system.c (source included into libgcov-driver.c) * libgcc/libgcov.c: Delete as part of re-factoring. * gcc/gcov-io.h (__gcov_indirect_call_profiler): Add the decl to avoid warning. * libgcc/libgcov-interface.c (init_mx): Moved from libgcov.c. (init_mx_once): Ditto. (__gcov_flush): Ditto. (__gcov_reset): Ditto. (__gcov_dump): Ditto. (__gcov_fork): Ditto. (__gcov_execl): Ditto. (__gcov_execlp): Ditto. (__gcov_execle): Ditto. (__gcov_execv): Ditto. (__gcov_execvp): Ditto. (__gcov_execve): Ditto. * libgcc/libgcov-merge.c (__gcov_merge_time_profile): Moved from libgcov.c. (__gcov_merge_add): Ditto. (__gcov_merge_ior): Ditto. (__gcov_merge_single): Ditto. (__gcov_merge_delta): Ditto. * libgcc/libgcov-profiler.c (__gcov_interval_profiler): Ditto. (__gcov_pow2_profiler): Ditto. (__gcov_one_value_profiler_body): Ditto. (__gcov_one_value_profiler): Ditto. (__gcov_indirect_call_profiler): Ditto. (__gcov_indirect_call_profiler_v2): Ditto. (__gcov_time_profiler): Ditto. (__gcov_average_profiler): Ditto. (__gcov_ior_profiler): Ditto. * libgcc/libgcov-driver.c (set_gcov_list): New. (get_gcov_dump_complete): Ditto. (set_gcov_dump_complete):Ditto. (reset_gcov_dump_complete):Ditto. (gcov_exit_compute_summary): New function split from gcov_exit(). (gcov_exit_merge_gcda): Ditto. (gcov_exit_write_gcda): Ditto. (gcov_exit_merge_summary): Ditto. (gcov_exit_dump_gcov): Ditto. (struct gcov_fn_buffer): Moved from libgcov.c (struct gcov_summary_buffer): Ditto. (free_fn_data): Ditto. (buffer_fn_data): Ditto. (crc32_unsigned): Ditto. (gcov_version): Ditto. (gcov_histogram_insert): Ditto. (gcov_compute_histogram): Ditto. (gcov_exit): Ditto. (gcov_clear): Ditto. (__gcov_init): Ditto. (this_prg): Make it file scope static variable. (all_prg): Ditto. (crc32): Ditto. (gi_filename): Ditto. (fn_buffer): Ditto. (sum_buffer): Ditto. (struct gcov_filename_aux): New types to store auxiliary information for gi_filename. * libgcc/libgcov-driver-system.c (gcov_error): New utility function. (allocate_filename_struct): New function split from gcov_exit(). (gcov_exit_open_gcda_file): Ditto. (create_file_directory): Moved from libgcov.c * libgcc/Makefile.in: Change to build newly added files. From-SVN: r204730
204 lines
5.5 KiB
C
204 lines
5.5 KiB
C
/* Routines required for instrumenting a program. */
|
|
/* Compile this one with gcc. */
|
|
/* Copyright (C) 1989-2013 Free Software Foundation, Inc.
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
Under Section 7 of GPL version 3, you are granted additional
|
|
permissions described in the GCC Runtime Library Exception, version
|
|
3.1, as published by the Free Software Foundation.
|
|
|
|
You should have received a copy of the GNU General Public License and
|
|
a copy of the GCC Runtime Library Exception along with this program;
|
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
/* A utility function for outputing errors. */
|
|
|
|
static int __attribute__((format(printf, 1, 2)))
|
|
gcov_error (const char *fmt, ...)
|
|
{
|
|
int ret;
|
|
va_list argp;
|
|
va_start (argp, fmt);
|
|
ret = vfprintf (stderr, fmt, argp);
|
|
va_end (argp);
|
|
return ret;
|
|
}
|
|
|
|
/* Make sure path component of the given FILENAME exists, create
|
|
missing directories. FILENAME must be writable.
|
|
Returns zero on success, or -1 if an error occurred. */
|
|
|
|
static int
|
|
create_file_directory (char *filename)
|
|
{
|
|
#if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
|
|
(void) filename;
|
|
return -1;
|
|
#else
|
|
char *s;
|
|
|
|
s = filename;
|
|
|
|
if (HAS_DRIVE_SPEC(s))
|
|
s += 2;
|
|
if (IS_DIR_SEPARATOR(*s))
|
|
++s;
|
|
for (; *s != '\0'; s++)
|
|
if (IS_DIR_SEPARATOR(*s))
|
|
{
|
|
char sep = *s;
|
|
*s = '\0';
|
|
|
|
/* Try to make directory if it doesn't already exist. */
|
|
if (access (filename, F_OK) == -1
|
|
#ifdef TARGET_POSIX_IO
|
|
&& mkdir (filename, 0755) == -1
|
|
#else
|
|
&& mkdir (filename) == -1
|
|
#endif
|
|
/* The directory might have been made by another process. */
|
|
&& errno != EEXIST)
|
|
{
|
|
gcov_error ("profiling:%s:Cannot create directory\n", filename);
|
|
*s = sep;
|
|
return -1;
|
|
};
|
|
|
|
*s = sep;
|
|
};
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
allocate_filename_struct (struct gcov_filename_aux *gf)
|
|
{
|
|
const char *gcov_prefix;
|
|
int gcov_prefix_strip = 0;
|
|
size_t prefix_length;
|
|
char *gi_filename_up;
|
|
|
|
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);
|
|
/* Do not consider negative values. */
|
|
if (gcov_prefix_strip < 0)
|
|
gcov_prefix_strip = 0;
|
|
}
|
|
}
|
|
|
|
/* 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;
|
|
|
|
/* If no prefix was specified and a prefix stip, then we assume
|
|
relative. */
|
|
if (gcov_prefix_strip != 0 && prefix_length == 0)
|
|
{
|
|
gcov_prefix = ".";
|
|
prefix_length = 1;
|
|
}
|
|
/* Allocate and initialize the filename scratch space plus one. */
|
|
gi_filename = (char *) malloc (prefix_length + gcov_max_filename + 2);
|
|
if (prefix_length)
|
|
memcpy (gi_filename, gcov_prefix, prefix_length);
|
|
gi_filename_up = gi_filename + prefix_length;
|
|
|
|
gf->gi_filename_up = gi_filename_up;
|
|
gf->prefix_length = prefix_length;
|
|
gf->gcov_prefix_strip = gcov_prefix_strip;
|
|
}
|
|
|
|
/* 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)
|
|
{
|
|
int gcov_prefix_strip;
|
|
size_t prefix_length;
|
|
char *gi_filename_up;
|
|
const char *fname, *s;
|
|
|
|
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)
|
|
{
|
|
int level = 0;
|
|
|
|
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))
|
|
{
|
|
fname = s;
|
|
level++;
|
|
}
|
|
}
|
|
|
|
/* Update complete filename with stripped original. */
|
|
if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname))
|
|
{
|
|
/* If prefix is given, add directory separator. */
|
|
strcpy (gi_filename_up, "/");
|
|
strcpy (gi_filename_up + 1, fname);
|
|
}
|
|
else
|
|
strcpy (gi_filename_up, fname);
|
|
|
|
if (!gcov_open (gi_filename))
|
|
{
|
|
/* Open failed likely due to missed directory.
|
|
Create directory and retry to open file. */
|
|
if (create_file_directory (gi_filename))
|
|
{
|
|
fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
|
|
return -1;
|
|
}
|
|
if (!gcov_open (gi_filename))
|
|
{
|
|
fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|