diff mbox

[Google/4_8] Support for embedding build info into gcda files

Message ID CAAe5K+XKywnv1He-EJRc-WXFsBmyVrsaWkN6AQ6QSscEhzL+9A@mail.gmail.com
State New
Headers show

Commit Message

Teresa Johnson May 23, 2014, 8:59 p.m. UTC
Done. Passes manual testing, rerunning regression testing. New patch attached.

Thanks,
Teresa

On Fri, May 23, 2014 at 11:35 AM, Xinliang David Li <davidxl@google.com> 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 <tejohnson@google.com> 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

Comments

Xinliang David Li May 23, 2014, 9:28 p.m. UTC | #1
for (i = 0; i < num_strings; i++)
+        {
+          if (strcmp (build_info_strings[i], gi_ptr->build_info[i]))

Add also check of gi_ptr->build_info:

   if (!gi_ptr->build_info || strcmp (.... )


+            {
+              gcov_error ("profiling:%s:Mismatched build info string "


+      else if (tag == GCOV_TAG_BUILD_INFO)
+        {

Add comment about not consumed by compiler, skipping the data ...

+          gcov_unsigned_t num_strings;
+          char **build_info_strings = gcov_read_build_info (length,
+                                                            &num_strings);


@@ -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 ();


Why building it in init, not finalize routine as the rest of the gcov info?


David

On Fri, May 23, 2014 at 1:59 PM, Teresa Johnson <tejohnson@google.com> wrote:
> Done. Passes manual testing, rerunning regression testing. New patch attached.
>
> Thanks,
> Teresa
>
> On Fri, May 23, 2014 at 11:35 AM, Xinliang David Li <davidxl@google.com> 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 <tejohnson@google.com> 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
>
>
>
> --
> Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413
Teresa Johnson May 23, 2014, 9:50 p.m. UTC | #2
On Fri, May 23, 2014 at 2:28 PM, Xinliang David Li <davidxl@google.com> wrote:
>       for (i = 0; i < num_strings; i++)
> +        {
> +          if (strcmp (build_info_strings[i], gi_ptr->build_info[i]))
>
> Add also check of gi_ptr->build_info:
>
>    if (!gi_ptr->build_info || strcmp (.... )

Added the check earlier, just above this walk over strings. If we
reached here the stamps were the same so if we had see a build info
tag then we should have a non-null build_info.

>
>
> +            {
> +              gcov_error ("profiling:%s:Mismatched build info string "
>
>
> +      else if (tag == GCOV_TAG_BUILD_INFO)
> +        {
>
> Add comment about not consumed by compiler, skipping the data ...

Ok.

>
> +          gcov_unsigned_t num_strings;
> +          char **build_info_strings = gcov_read_build_info (length,
> +                                                            &num_strings);
>
>
> @@ -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 ();
>
>
> Why building it in init, not finalize routine as the rest of the gcov info?

Not sure what the issue is? We are just reading in the file here.

Teresa

>
>
> David
>
> On Fri, May 23, 2014 at 1:59 PM, Teresa Johnson <tejohnson@google.com> wrote:
>> Done. Passes manual testing, rerunning regression testing. New patch attached.
>>
>> Thanks,
>> Teresa
>>
>> On Fri, May 23, 2014 at 11:35 AM, Xinliang David Li <davidxl@google.com> 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 <tejohnson@google.com> 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
>>
>>
>>
>> --
>> Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413
Xinliang David Li May 23, 2014, 9:56 p.m. UTC | #3
On Fri, May 23, 2014 at 2:50 PM, Teresa Johnson <tejohnson@google.com> wrote:
> On Fri, May 23, 2014 at 2:28 PM, Xinliang David Li <davidxl@google.com> wrote:
>>       for (i = 0; i < num_strings; i++)
>> +        {
>> +          if (strcmp (build_info_strings[i], gi_ptr->build_info[i]))
>>
>> Add also check of gi_ptr->build_info:
>>
>>    if (!gi_ptr->build_info || strcmp (.... )
>
> Added the check earlier, just above this walk over strings. If we
> reached here the stamps were the same so if we had see a build info
> tag then we should have a non-null build_info.
>
>>
>>
>> +            {
>> +              gcov_error ("profiling:%s:Mismatched build info string "
>>
>>
>> +      else if (tag == GCOV_TAG_BUILD_INFO)
>> +        {
>>
>> Add comment about not consumed by compiler, skipping the data ...
>
> Ok.
>
>>
>> +          gcov_unsigned_t num_strings;
>> +          char **build_info_strings = gcov_read_build_info (length,
>> +                                                            &num_strings);
>>
>>
>> @@ -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 ();
>>
>>
>> Why building it in init, not finalize routine as the rest of the gcov info?
>
> Not sure what the issue is? We are just reading in the file here.
>

It is better to consolidate all the gcov info build related thing in
one place. Is it doable inside build_info () function?

David



> Teresa
>
>>
>>
>> David
>>
>> On Fri, May 23, 2014 at 1:59 PM, Teresa Johnson <tejohnson@google.com> wrote:
>>> Done. Passes manual testing, rerunning regression testing. New patch attached.
>>>
>>> Thanks,
>>> Teresa
>>>
>>> On Fri, May 23, 2014 at 11:35 AM, Xinliang David Li <davidxl@google.com> 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 <tejohnson@google.com> 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
>>>
>>>
>>>
>>> --
>>> Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413
>
>
>
> --
> Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413
Xinliang David Li May 23, 2014, 10:16 p.m. UTC | #4
ok

On Fri, May 23, 2014 at 3:14 PM, Teresa Johnson <tejohnson@google.com> wrote:
>
> On May 23, 2014 2:56 PM, "Xinliang David Li" <davidxl@google.com> wrote:
>>
>> On Fri, May 23, 2014 at 2:50 PM, Teresa Johnson <tejohnson@google.com>
>> wrote:
>> > On Fri, May 23, 2014 at 2:28 PM, Xinliang David Li <davidxl@google.com>
>> > wrote:
>> >>       for (i = 0; i < num_strings; i++)
>> >> +        {
>> >> +          if (strcmp (build_info_strings[i], gi_ptr->build_info[i]))
>> >>
>> >> Add also check of gi_ptr->build_info:
>> >>
>> >>    if (!gi_ptr->build_info || strcmp (.... )
>> >
>> > Added the check earlier, just above this walk over strings. If we
>> > reached here the stamps were the same so if we had see a build info
>> > tag then we should have a non-null build_info.
>> >
>> >>
>> >>
>> >> +            {
>> >> +              gcov_error ("profiling:%s:Mismatched build info string "
>> >>
>> >>
>> >> +      else if (tag == GCOV_TAG_BUILD_INFO)
>> >> +        {
>> >>
>> >> Add comment about not consumed by compiler, skipping the data ...
>> >
>> > Ok.
>> >
>> >>
>> >> +          gcov_unsigned_t num_strings;
>> >> +          char **build_info_strings = gcov_read_build_info (length,
>> >> +
>> >> &num_strings);
>> >>
>> >>
>> >> @@ -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 ();
>> >>
>> >>
>> >> Why building it in init, not finalize routine as the rest of the gcov
>> >> info?
>> >
>> > Not sure what the issue is? We are just reading in the file here.
>> >
>>
>> It is better to consolidate all the gcov info build related thing in
>> one place. Is it doable inside build_info () function?
>
> Ok. Will move there and retest. Ok with these changes if tests pass?
>
> Thanks,
> Teresa
>
>
>>
>> David
>>
>>
>>
>> > Teresa
>> >
>> >>
>> >>
>> >> David
>> >>
>> >> On Fri, May 23, 2014 at 1:59 PM, Teresa Johnson <tejohnson@google.com>
>> >> wrote:
>> >>> Done. Passes manual testing, rerunning regression testing. New patch
>> >>> attached.
>> >>>
>> >>> Thanks,
>> >>> Teresa
>> >>>
>> >>> On Fri, May 23, 2014 at 11:35 AM, Xinliang David Li
>> >>> <davidxl@google.com> 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
>> >>>> <tejohnson@google.com> 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
>> >>>
>> >>>
>> >>>
>> >>> --
>> >>> Teresa Johnson | Software Engineer | tejohnson@google.com |
>> >>> 408-460-2413
>> >
>> >
>> >
>> > --
>> > Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413
diff mbox

Patch

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<constructor_elt,va_gc> *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<constructor_elt, va_gc> *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.  */