From patchwork Fri May 23 20:59:17 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Teresa Johnson X-Patchwork-Id: 352036 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 2896D140082 for ; Sat, 24 May 2014 06:59:38 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; q=dns; s=default; b=QFINTRLlT6LB6oMNIZ qSYebc7FcpPNruVKq4xbmJJZr7OzQl7cbG2OKd/QGxlTnYHdYLqwXMLjF3WMY7Za GgeGAvVFmyuQH7ldXz8VXE23H/D8BGBOiNnFzJL+K6GB7meiwxRWqlg8TOzPx78M VFAFAAcdESyOxt1BPtFJZjDpw= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; s=default; bh=tjaPKoTbn0kZ/QZ+RDU+TAZH BhY=; b=nAJTYc1cKrNEX9u+2EulHCKNJIOQrTpyEF6/lE6cjZLOXHlzcuMCbIS2 b7FKpi92vfmDF40fEu0kPZU9FvIIB6odM2UgVe3LGMrzIRUR9oV6mPhhMdXHDSEW u0qEsBF4RIRgD4TeJbQeWWjoZpIKlwPCZG7jruEwTn0n/RGKpRk= Received: (qmail 29447 invoked by alias); 23 May 2014 20:59:26 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 29343 invoked by uid 89); 23 May 2014 20:59:25 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.3 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qc0-f172.google.com Received: from mail-qc0-f172.google.com (HELO mail-qc0-f172.google.com) (209.85.216.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Fri, 23 May 2014 20:59:20 +0000 Received: by mail-qc0-f172.google.com with SMTP id l6so8983719qcy.3 for ; Fri, 23 May 2014 13:59:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc:content-type; bh=HCvWgwCxdkeqMcU5/pSmefBihi/2HeLNaG+ayqyxkxY=; b=UwNzCBnB2sRY96NLtnJIjykT1zAXVfgVT5Q9hHiQEy0oqhvsWwjgGxSBnoq+Fc3QXI kKZCUMm+TSGcmbgP3qsGpXAgykz2xoU3KAQqPsscQKYFn88xl5KYWL5h5hjZY7vULfDC ba6YJWVGSpc5sXx25RHZh6M68DWcUWeU5X9f8+Qf6Qgooe82uDYLzdOO79/7dfL7XOjf bA0Bz5vIdD3Grsj/Twa6DE4zNZeJr1dgyK2ZcJw7GP/Qa6oFGWB0mgKvq7R6kLDiS0tO iW5wifsi2V+2+q+KSUiy0wrkee4vOangNJtaR847Zp199/9l1qC6oa+aiK9SJNqWoC3i /fcQ== X-Gm-Message-State: ALoCoQnaUQvWb/0T7G9b/tp0apFYftoo42akHkVado7h/XgRXsiwdZRs2GwY/zptlqX9YByoN6H2 MIME-Version: 1.0 X-Received: by 10.224.165.148 with SMTP id i20mr10429296qay.41.1400878758336; Fri, 23 May 2014 13:59:18 -0700 (PDT) Received: by 10.229.167.129 with HTTP; Fri, 23 May 2014 13:59:17 -0700 (PDT) In-Reply-To: References: Date: Fri, 23 May 2014 13:59:17 -0700 Message-ID: Subject: Re: [Google/4_8] Support for embedding build info into gcda files From: Teresa Johnson To: Xinliang David Li Cc: "gcc-patches@gcc.gnu.org" X-IsSubscribed: yes Done. Passes manual testing, rerunning regression testing. New patch attached. Thanks, Teresa On Fri, May 23, 2014 at 11:35 AM, Xinliang David Li wrote: > The change makes gcov_info a variable length array, which is not ideal. > > Better just add one more field (instead of two): > > struct gcov_info { > ... > char ** build_info; > }; > > For regular case, it is null, for case where the build info is > available, make it point to a string array (with an null end marker > string). > > David > > > > > > On Fri, May 23, 2014 at 11:08 AM, Teresa Johnson wrote: >> Support for embedding arbitrary build information from the profile-generate >> compile into the gcda file in a new BUILD_INFO record. Lines from a file >> passed to the -fprofile-generate compile via a new >> -fprofile-generate-buildinfo=filename option are embedded as strings >> in the gcov_info struct and emitted as-is to a new GCOV_TAG_BUILD_INFO >> record. They are ignored on profile-use compiles, but emitted by gcov-dump. >> This is useful for recording information about, for example, source revision >> info that can be helpful for diagnosing profile mis-matches. >> >> For example: >> >> $ cat buildinfo.txt >> Build timestamp xxxx >> Build source revision r12345 >> Other random build data >> >> $ g++ foo.cc -fprofile-generate -fprofile-generate-buildinfo=buildinfo.txt >> >> $ a.out >> $ gcov-dump foo.gcda >> foo.gcda:data:magic `gcda':version `408*' >> foo.gcda:stamp 708902860 >> foo.gcda: a3000000: 22:PROGRAM_SUMMARY checksum=0x86a3bc55 >> foo.gcda: counts=1, runs=1, sum_all=1, run_max=1, sum_max=1 >> foo.gcda: counter histogram: >> foo.gcda: 1: num counts=1, min counter=1, cum_counter=1 >> foo.gcda: a7000000: 24:BUILD INFO num_strings=3 >> foo.gcda: Build timestamp xxxx >> foo.gcda: Build source revision r12345 >> foo.gcda: Other random build data >> foo.gcda: 01000000: 3:FUNCTION ident=1, lineno_checksum=0x17c79156, >> cfg_checksum=0xdb5de9e8 >> foo.gcda: 01a10000: 2:COUNTERS arcs 1 counts >> >> Tested manually, passes regression tests. Ok for Google/4_8? >> >> Thanks, >> Teresa >> >> -- >> Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413 Index: gcc/common.opt =================================================================== --- gcc/common.opt (revision 210862) +++ gcc/common.opt (working copy) @@ -1798,6 +1798,10 @@ fprofile-generate-sampling Common Var(flag_profile_generate_sampling) Turn on instrumentation sampling with -fprofile-generate with rate set by --param profile-generate-sampling-rate or environment variable GCOV_SAMPLING_RATE +fprofile-generate-buildinfo= +Common RejectNegative Joined Var(flag_profile_generate_buildinfo) +-fprofile-generate-buildinfo=filename Read build info to include in gcda file from filename + femit-function-names Common Var(flag_emit_function_names) Print to stderr the mapping from module name and function id to assembler Index: gcc/coverage.c =================================================================== --- gcc/coverage.c (revision 210862) +++ gcc/coverage.c (working copy) @@ -154,6 +154,10 @@ static unsigned num_cpp_defines = 0; static struct str_list *cpp_includes_head = NULL, *cpp_includes_tail = NULL; static unsigned num_cpp_includes = 0; +/* List of lines read from -fprofile-generate-buildinfo=filename. */ +struct str_list *build_info_array_head = NULL, *build_info_array_tail = NULL; +static unsigned num_build_info = 0; + /* True if the current module has any asm statements. */ static bool has_asm_statement; @@ -792,6 +796,15 @@ read_counts_file (const char *da_file_name, unsign } else if (tag == GCOV_TAG_PARAMETERS) gcov_parameter_values = gcov_read_parameters (length); + else if (tag == GCOV_TAG_BUILD_INFO) + { + gcov_unsigned_t num_strings; + char **build_info_strings = gcov_read_build_info (length, + &num_strings); + for (unsigned i = 0; i < num_strings; i++) + free (build_info_strings[i]); + free (build_info_strings); + } else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident) { counts_entry_t **slot, *entry, elt; @@ -1699,6 +1712,7 @@ build_info_type (tree type, tree fn_info_ptr_type) { tree field, fields = NULL_TREE; tree merge_fn_type, mod_type; + tree string_type, string_ptr_type; /* Version ident */ field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, @@ -1766,6 +1780,17 @@ build_info_type (tree type, tree fn_info_ptr_type) DECL_CHAIN (field) = fields; fields = field; + /* build_info string array */ + string_type = build_pointer_type ( + build_qualified_type (char_type_node, + TYPE_QUAL_CONST)); + string_ptr_type = build_pointer_type + (build_qualified_type (string_type, TYPE_QUAL_CONST)); + field = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, string_ptr_type); + DECL_CHAIN (field) = fields; + fields = field; + finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE); } @@ -2163,6 +2188,40 @@ build_gcov_module_info_value (tree mod_type) return mod_info; } +/* Returns the value of the build info string read earlier. */ + +static tree +build_gcov_build_info_value (void) +{ + tree build_info; + tree value = NULL_TREE; + tree string_type, index_type, string_array_type; + vec *v = NULL; + char name_buf[50]; + + string_type = build_pointer_type ( + build_qualified_type (char_type_node, + TYPE_QUAL_CONST)); + index_type = build_index_type (build_int_cst (NULL_TREE, num_build_info)); + string_array_type = build_array_type (string_type, index_type); + + build_str_array_value (string_type, &v, + build_info_array_head); + value = build_constructor (string_array_type, v); + + build_info = build_decl (BUILTINS_LOCATION, VAR_DECL, + NULL_TREE, TREE_TYPE (value)); + TREE_STATIC (build_info) = 1; + ASM_GENERATE_INTERNAL_LABEL (name_buf, "BUILDINFO", 0); + DECL_NAME (build_info) = get_identifier (name_buf); + DECL_INITIAL (build_info) = value; + + /* Build structure. */ + varpool_finalize_decl (build_info); + + return build_info; +} + /* Returns a CONSTRUCTOR for the gcov_info object. INFO_TYPE is the gcov_info structure type, FN_ARY is the array of pointers to function info objects. */ @@ -2174,6 +2233,7 @@ build_info (tree info_type, tree fn_ary) tree merge_fn_type, n_funcs; unsigned ix; tree mod_value = NULL_TREE; + tree buildinfo_value = NULL_TREE; tree filename_string; int da_file_name_len; vec *v1 = NULL; @@ -2256,6 +2316,18 @@ build_info (tree info_type, tree fn_ary) build1 (ADDR_EXPR, TREE_TYPE (info_fields), fn_ary)); info_fields = DECL_CHAIN (info_fields); + /* build_info string array */ + if (num_build_info) + { + buildinfo_value = build_gcov_build_info_value (); + CONSTRUCTOR_APPEND_ELT (v1, info_fields, + build1 (ADDR_EXPR, TREE_TYPE (info_fields), + buildinfo_value)); + } + else + CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node); + info_fields = DECL_CHAIN (info_fields); + gcc_assert (!info_fields); return build_constructor (info_type, v1); } @@ -2286,6 +2358,62 @@ build_init_ctor (tree gcov_info_type) cgraph_build_static_cdtor ('I', ctor, DEFAULT_INIT_PRIORITY); } +/* Add S to the end of the string-list, the head and tail of which are + pointed-to by HEAD and TAIL, respectively. */ + +static void +str_list_append (struct str_list **head, struct str_list **tail, const char *s) +{ + struct str_list *e = XNEW (struct str_list); + e->str = XNEWVEC (char, strlen (s) + 1); + strcpy (e->str, s); + e->next = NULL; + if (*tail) + (*tail)->next = e; + else + *head = e; + *tail = e; +} + +/* Read file specified to -fprofile-generate-buildinfo=filename option and + create a list of strings to include in build_info array. */ + +static void +read_buildinfo (void) +{ + char buf[1024]; + FILE *buildinfo = fopen (flag_profile_generate_buildinfo, "r"); + if (!buildinfo) + { + error ("could not open -fprofile-generate-buildinfo file %qs: %m", + flag_profile_generate_buildinfo); + } + + while (fgets (buf, sizeof buf, buildinfo) != NULL) + { + /* Remove end of line. */ + int len = strlen (buf); + if (len >= 1 && buf[len - 1] =='\n') + buf[len - 1] = '\0'; + str_list_append (&build_info_array_head, &build_info_array_tail, buf); + num_build_info++; + } + /* Terminate with an empty string. */ + str_list_append (&build_info_array_head, &build_info_array_tail, ""); + num_build_info++; + if (ferror (buildinfo)) + { + error ("error reading -fprofile-generate-buildinfo file %qs: %m", + flag_profile_generate_buildinfo); + } + + if (fclose (buildinfo)) + { + error ("could not close -fprofile-generate-buildinfo file %qs: %m", + flag_profile_generate_buildinfo); + } +} + /* Create the gcov_info types and object. Does not generate the initializer for the object. Returns TRUE if coverage data is being emitted. */ @@ -2307,6 +2435,9 @@ coverage_obj_init (void) if (cgraph_dump_file) fprintf (cgraph_dump_file, "Using data file %s\n", da_file_name); + if (flag_profile_generate_buildinfo) + read_buildinfo (); + /* Prune functions. */ if (!flag_dyn_ipa) /* in lipo mode, coverage_finish is called when function struct is cleared, @@ -2812,23 +2943,6 @@ set_profile_parameters (struct cpp_reader *parse_i dump_finish (pass_profile.pass.static_pass_number); } -/* Add S to the end of the string-list, the head and tail of which are - pointed-to by HEAD and TAIL, respectively. */ - -static void -str_list_append (struct str_list **head, struct str_list **tail, const char *s) -{ - struct str_list *e = XNEW (struct str_list); - e->str = XNEWVEC (char, strlen (s) + 1); - strcpy (e->str, s); - e->next = NULL; - if (*tail) - (*tail)->next = e; - else - *head = e; - *tail = e; -} - /* Copies the macro def or undef CPP_DEF and saves the copy in a list. IS_DEF is a flag indicating if CPP_DEF represents a -D or -U. */ Index: gcc/gcov.c =================================================================== --- gcc/gcov.c (revision 210862) +++ gcc/gcov.c (working copy) @@ -1432,6 +1432,15 @@ read_count_file (function_t *fns) } else if (tag == GCOV_TAG_PARAMETERS) gcov_read_parameters (length); + else if (tag == GCOV_TAG_BUILD_INFO) + { + gcov_unsigned_t num_strings; + char **build_info_strings = gcov_read_build_info (length, + &num_strings); + for (unsigned i = 0; i < num_strings; i++) + free (build_info_strings[i]); + free (build_info_strings); + } else if (tag == GCOV_TAG_FUNCTION && !length) ; /* placeholder */ else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH) Index: gcc/gcov-dump.c =================================================================== --- gcc/gcov-dump.c (revision 210862) +++ gcc/gcov-dump.c (working copy) @@ -40,6 +40,7 @@ static void tag_lines (const char *, unsigned, uns static void tag_counters (const char *, unsigned, unsigned); static void tag_summary (const char *, unsigned, unsigned); static void tag_parameters (const char *, unsigned, unsigned); +static void tag_build_info (const char *, unsigned, unsigned); static void dump_working_sets (const char *filename ATTRIBUTE_UNUSED, const struct gcov_ctr_summary *summary); static void tag_module_info (const char *, unsigned, unsigned); @@ -80,6 +81,7 @@ static const tag_format_t tag_table[] = {GCOV_TAG_PROGRAM_SUMMARY, "PROGRAM_SUMMARY", tag_summary}, {GCOV_TAG_PARAMETERS, "PARAMETERS", tag_parameters}, {GCOV_TAG_MODULE_INFO, "MODULE INFO", tag_module_info}, + {GCOV_TAG_BUILD_INFO, "BUILD INFO", tag_build_info}, {0, NULL, NULL} }; @@ -596,6 +598,28 @@ tag_module_info (const char *filename ATTRIBUTE_UN } static void +tag_build_info (const char *filename, + unsigned tag ATTRIBUTE_UNUSED, unsigned length) +{ + gcov_unsigned_t num_strings = 0; + char **build_info_strings = gcov_read_build_info (length, &num_strings); + if (!build_info_strings) + { + printf ("%s:error reading build info\n", filename); + return; + } + printf (" num_strings=%u", num_strings); + for (unsigned i = 0; i < num_strings; i++) + { + printf ("\n"); + print_prefix (filename, 0, 0); + printf ("\t\t%s", build_info_strings[i]); + free (build_info_strings[i]); + } + free (build_info_strings); +} + +static void dump_working_sets (const char *filename ATTRIBUTE_UNUSED, const struct gcov_ctr_summary *summary) { Index: gcc/gcov-io.c =================================================================== --- gcc/gcov-io.c (revision 210862) +++ gcc/gcov-io.c (working copy) @@ -341,6 +341,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. */ @@ -701,6 +742,44 @@ gcov_read_summary (struct gcov_summary *summary) } } +/* 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_GCOV_TOOL || !IN_LIBGCOV && IN_GCOV != 1 /* Read LEN words (unsigned type) and construct MOD_INFO. */ @@ -708,7 +787,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 (); @@ -740,16 +819,7 @@ gcov_read_module_info (struct gcov_module_info *mo + 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 Index: gcc/gcov-io.h =================================================================== --- gcc/gcov-io.h (revision 210862) +++ gcc/gcov-io.h (working copy) @@ -129,7 +129,7 @@ see the files COPYING3 and COPYING.RUNTIME respect blocks they are for. The data file contains the following records. - data: {unit summary:program* parameter-data function-data*}* + data: {unit summary:program* build_info parameter-data function-data*}* unit: header int32:checksum function-data: announce_function present counts announce_function: header int32:ident @@ -143,6 +143,7 @@ see the files COPYING3 and COPYING.RUNTIME respect histogram-buckets: int32:num int64:min int64:sum parameter-data: header parm-value* parm-value: string:macro_name int64:value + build_info: string:info* The ANNOUNCE_FUNCTION record is the same as that in the note file, but without the source location. The COUNTS gives the @@ -153,6 +154,11 @@ see the files COPYING3 and COPYING.RUNTIME respect each with a unique checksum. Note that the data file might contain information from several runs concatenated, or the data might be merged. + BUILD_INFO record contains a list of strings that is used + to include in the data file information about the profile generate + build. For example, it can be used to include source revision + information that is useful in diagnosing profile mis-matches. + This file is included by both the compiler, gcov tools and the runtime support library libgcov. IN_LIBGCOV and IN_GCOV are used to distinguish which case is which. If IN_LIBGCOV is nonzero, @@ -259,6 +265,7 @@ typedef unsigned HOST_WIDEST_INT gcov_type_unsigne #define GCOV_TAG_SUMMARY_LENGTH(NUM) \ (1 + GCOV_COUNTERS_SUMMABLE * (10 + 3 * 2) + (NUM) * 5) #define GCOV_TAG_PARAMETERS ((gcov_unsigned_t)0xa5000000) +#define GCOV_TAG_BUILD_INFO ((gcov_unsigned_t)0xa7000000) #define GCOV_TAG_MODULE_INFO ((gcov_unsigned_t)0xab000000) #define GCOV_TAG_AFDO_FILE_NAMES ((gcov_unsigned_t)0xaa000000) #define GCOV_TAG_AFDO_FUNCTION ((gcov_unsigned_t)0xac000000) @@ -468,11 +475,15 @@ GCOV_LINKAGE int gcov_close (void) ATTRIBUTE_HIDDE GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void) ATTRIBUTE_HIDDEN; GCOV_LINKAGE gcov_type gcov_read_counter (void) ATTRIBUTE_HIDDEN; GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE char **gcov_read_build_info (gcov_unsigned_t, gcov_unsigned_t *) + ATTRIBUTE_HIDDEN; GCOV_LINKAGE struct gcov_parameter_value *gcov_read_parameters (gcov_unsigned_t) ATTRIBUTE_HIDDEN; GCOV_LINKAGE const char *gcov_read_string (void); GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/, gcov_unsigned_t /*length */); +GCOV_LINKAGE gcov_unsigned_t gcov_read_string_array (char **, gcov_unsigned_t) + ATTRIBUTE_HIDDEN; #if !IN_LIBGCOV && IN_GCOV != 1 GCOV_LINKAGE void gcov_read_module_info (struct gcov_module_info *mod_info, @@ -482,6 +493,11 @@ GCOV_LINKAGE void gcov_read_module_info (struct gc #if !IN_GCOV /* Available outside gcov */ GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE gcov_unsigned_t gcov_compute_string_array_len (char **, + gcov_unsigned_t) + ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_write_string_array (char **, gcov_unsigned_t) + ATTRIBUTE_HIDDEN; GCOV_LINKAGE void gcov_write_string (const char *); #endif Index: libgcc/dyn-ipa.c =================================================================== --- libgcc/dyn-ipa.c (revision 210862) +++ libgcc/dyn-ipa.c (working copy) @@ -2233,7 +2233,7 @@ static void gcov_write_module_info (const struct gcov_info *mod_info, unsigned is_primary) { - gcov_unsigned_t len = 0, filename_len = 0, src_filename_len = 0, i, j; + gcov_unsigned_t len = 0, filename_len = 0, src_filename_len = 0, i; gcov_unsigned_t num_strings; gcov_unsigned_t *aligned_fname; struct gcov_module_info *module_info = mod_info->mod_info; @@ -2248,14 +2248,8 @@ gcov_write_module_info (const struct gcov_info *mo + module_info->num_system_paths + module_info->num_cpp_defines + module_info->num_cpp_includes + module_info->num_cl_args; - for (i = 0; i < num_strings; i++) - { - gcov_unsigned_t string_len - = (strlen (module_info->string_array[i]) + sizeof (gcov_unsigned_t)) - / sizeof (gcov_unsigned_t); - len += string_len; - len += 1; /* Each string is lead by a length. */ - } + len += gcov_compute_string_array_len (module_info->string_array, + num_strings); len += 11; /* 11 more fields */ @@ -2288,20 +2282,7 @@ gcov_write_module_info (const struct gcov_info *mo gcov_write_unsigned (aligned_fname[i]); /* Now write the string array. */ - for (j = 0; j < num_strings; j++) - { - gcov_unsigned_t *aligned_string; - gcov_unsigned_t string_len = - (strlen (module_info->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), module_info->string_array[j]); - for (i = 0; i < (string_len + 1); i++) - gcov_write_unsigned (aligned_string[i]); - } + gcov_write_string_array (module_info->string_array, num_strings); } /* Write out MOD_INFO and its imported modules into gcda file. */ Index: libgcc/libgcov-driver.c =================================================================== --- libgcc/libgcov-driver.c (revision 210862) +++ libgcc/libgcov-driver.c (working copy) @@ -482,7 +482,7 @@ gcov_exit_merge_gcda (struct gcov_info *gi_ptr, struct gcov_parameter_value **merged_parameters) { gcov_unsigned_t tag, length, version, stamp; - unsigned t_ix, f_ix; + unsigned t_ix, f_ix, i; int error = 0; struct gcov_summary_buffer **sum_tail = &sum_buffer; @@ -535,6 +535,36 @@ gcov_exit_merge_gcda (struct gcov_info *gi_ptr, next_summary:; } + if (tag == GCOV_TAG_BUILD_INFO) + { + length = gcov_read_unsigned (); + gcov_unsigned_t num_strings = 0; + char **build_info_strings = gcov_read_build_info (length, &num_strings); + if (!build_info_strings) + { + gcov_error ("profiling:%s:Error reading build info\n", gi_filename); + return -1; + } + + for (i = 0; i < num_strings; i++) + { + if (strcmp (build_info_strings[i], gi_ptr->build_info[i])) + { + gcov_error ("profiling:%s:Mismatched build info string " + "(expected %s, read %s)\n", + gi_filename, gi_ptr->build_info[i], + build_info_strings[i]); + return -1; + } + free (build_info_strings[i]); + } + free (build_info_strings); + + /* Since the stamps matched if we got here, this should be from + the same compilation and the build info strings should match. */ + tag = gcov_read_unsigned (); + } + if (tag == GCOV_TAG_PARAMETERS) { length = gcov_read_unsigned (); @@ -607,6 +637,28 @@ read_error:; } +/* Write build_info strings from GI_PTR to a gcda file starting from its current + location. */ + +static void +gcov_write_build_info (struct gcov_info *gi_ptr) +{ + gcov_unsigned_t num = 0; + gcov_unsigned_t len = 1; + + if (!gi_ptr->build_info) + return; + + /* Count the number of strings, which is terminated with an empty string. */ + while (gi_ptr->build_info[num][0]) + num++; + + len += gcov_compute_string_array_len (gi_ptr->build_info, num); + gcov_write_tag_length (GCOV_TAG_BUILD_INFO, len); + gcov_write_unsigned (num); + gcov_write_string_array (gi_ptr->build_info, num); +} + /* Write counters in GI_PTR to a gcda file starting from its current location. */ @@ -693,6 +745,8 @@ gcov_exit_write_gcda (struct gcov_info *gi_ptr, sum_buffer = next_sum_buffer; } + gcov_write_build_info (gi_ptr); + if (merged_parameters) { gcov_write_parameters (merged_parameters); Index: libgcc/libgcov.h =================================================================== --- libgcc/libgcov.h (revision 210862) +++ libgcc/libgcov.h (working copy) @@ -172,6 +172,7 @@ typedef unsigned gcov_type_unsigned __attribute__ #define gcov_read_counter __gcov_read_counter #define gcov_read_summary __gcov_read_summary #define gcov_read_parameters __gcov_read_parameters +#define gcov_read_buildinfo __gcov_read_buildinfo #define gcov_read_string __gcov_read_string #define gcov_read_module_info __gcov_read_module_info #define gcov_sort_n_vals __gcov_sort_n_vals @@ -237,6 +238,8 @@ struct gcov_info #else const struct gcov_fn_info **functions; #endif /* !IN_GCOV_TOOL */ + char **build_info; /* strings to include in BUILD_INFO + section of gcda file. */ }; /* Information about a single imported module. */