1 /* File format for coverage information
2 Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2007,
3 2008 Free Software Foundation, Inc.
4 Contributed by Bob Manson <manson@cygnus.com>.
5 Completely remangled by Nathan Sidwell <nathan@codesourcery.com>.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 Under Section 7 of GPL version 3, you are granted additional
20 permissions described in the GCC Runtime Library Exception, version
21 3.1, as published by the Free Software Foundation.
23 You should have received a copy of the GNU General Public License and
24 a copy of the GCC Runtime Library Exception along with this program;
25 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
26 <http://www.gnu.org/licenses/>. */
28 /* Routines declared in gcov-io.h. This file should be #included by
29 another source file, after having #included gcov-io.h. */
31 /* Redefine these here, rather than using the ones in system.h since
32 * including system.h leads to conflicting definitions of other
33 * symbols and macros. */
35 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
38 static void gcov_write_block (unsigned);
39 static gcov_unsigned_t
*gcov_write_words (unsigned);
41 static const gcov_unsigned_t
*gcov_read_words (unsigned);
43 static void gcov_allocate (unsigned);
46 #ifdef __GCOV_KERNEL__
47 struct gcov_var gcov_var ATTRIBUTE_HIDDEN
;
50 static inline gcov_unsigned_t
from_file (gcov_unsigned_t value
)
55 value
= (value
>> 16) | (value
<< 16);
56 value
= ((value
& 0xff00ff) << 8) | ((value
>> 8) & 0xff00ff);
62 /* Open a gcov file. NAME is the name of the file to open and MODE
63 indicates whether a new file should be created, or an existing file
64 opened. If MODE is >= 0 an existing file will be opened, if
65 possible, and if MODE is <= 0, a new file will be created. Use
66 MODE=0 to attempt to reopen an existing file and then fall back on
67 creating a new one. If MODE < 0, the file will be opened in
68 read-only mode. Otherwise it will be opened for modification.
69 Return zero on failure, >0 on opening an existing file and <0 on
70 creating a new one. */
72 #ifndef __GCOV_KERNEL__
75 gcov_open (const char *name
)
77 gcov_open (const char *name
, int mode
)
87 s_flock
.l_whence
= SEEK_SET
;
89 s_flock
.l_len
= 0; /* Until EOF. */
90 s_flock
.l_pid
= getpid ();
93 gcc_assert (!gcov_var
.file
);
95 gcov_var
.offset
= gcov_var
.length
= 0;
96 gcov_var
.overread
= -1u;
104 /* Read-only mode - acquire a read-lock. */
105 s_flock
.l_type
= F_RDLCK
;
106 fd
= open (name
, O_RDONLY
);
110 /* Write mode - acquire a write-lock. */
111 s_flock
.l_type
= F_WRLCK
;
112 fd
= open (name
, O_RDWR
| O_CREAT
, 0666);
117 while (fcntl (fd
, F_SETLKW
, &s_flock
) && errno
== EINTR
)
120 gcov_var
.file
= fdopen (fd
, (mode
> 0) ? "rb" : "r+b");
134 if (fstat (fd
, &st
) < 0)
136 fclose (gcov_var
.file
);
143 gcov_var
.mode
= mode
* 2 + 1;
146 gcov_var
.mode
= mode
* 2 + 1;
149 gcov_var
.file
= fopen (name
, (mode
> 0) ? "rb" : "r+b");
155 gcov_var
.file
= fopen (name
, "w+b");
157 gcov_var
.mode
= mode
* 2 + 1;
163 setbuf (gcov_var
.file
, (char *)0);
167 #else /* __GCOV_KERNEL__ */
169 extern _GCOV_FILE
*gcov_current_file
;
172 gcov_open (const char *name
)
175 gcov_var
.offset
= gcov_var
.length
= 0;
176 gcov_var
.overread
= -1u;
178 gcov_var
.file
= gcov_current_file
;
183 #endif /* __GCOV_KERNEL__ */
185 /* Close the current gcov file. Flushes data to disk. Returns nonzero
186 on failure or error flag set. */
194 if (gcov_var
.offset
&& gcov_var
.mode
< 0)
195 gcov_write_block (gcov_var
.offset
);
197 _GCOV_fclose (gcov_var
.file
);
202 free (gcov_var
.buffer
);
207 return gcov_var
.error
;
211 /* Modify FILENAME to a canonical form after stripping known prefixes
212 in place. It removes '/proc/self/cwd' and '/proc/self/cwd/.'.
213 Returns the in-place modified filename. */
216 gcov_canonical_filename (char *filename
)
218 static char cwd_dot_str
[] = "/proc/self/cwd/./";
219 int cwd_dot_len
= strlen (cwd_dot_str
);
220 int cwd_len
= cwd_dot_len
- 2; /* without trailing './' */
221 int filename_len
= strlen (filename
);
222 /* delete the longer prefix first */
223 if (0 == strncmp (filename
, cwd_dot_str
, cwd_dot_len
))
225 memmove (filename
, filename
+ cwd_dot_len
, filename_len
- cwd_dot_len
);
226 filename
[filename_len
- cwd_dot_len
] = '\0';
230 if (0 == strncmp (filename
, cwd_dot_str
, cwd_len
))
232 memmove (filename
, filename
+ cwd_len
, filename_len
- cwd_len
);
233 filename
[filename_len
- cwd_len
] = '\0';
239 /* Read LEN words and construct load latency info LL_INFO. */
242 gcov_read_pmu_load_latency_info (gcov_pmu_ll_info_t
*ll_info
,
243 gcov_unsigned_t len ATTRIBUTE_UNUSED
)
245 const char *filename
;
246 ll_info
->counts
= gcov_read_unsigned ();
247 ll_info
->self
= gcov_read_unsigned ();
248 ll_info
->cum
= gcov_read_unsigned ();
249 ll_info
->lt_10
= gcov_read_unsigned ();
250 ll_info
->lt_32
= gcov_read_unsigned ();
251 ll_info
->lt_64
= gcov_read_unsigned ();
252 ll_info
->lt_256
= gcov_read_unsigned ();
253 ll_info
->lt_1024
= gcov_read_unsigned ();
254 ll_info
->gt_1024
= gcov_read_unsigned ();
255 ll_info
->wself
= gcov_read_unsigned ();
256 ll_info
->code_addr
= gcov_read_counter ();
257 ll_info
->line
= gcov_read_unsigned ();
258 ll_info
->discriminator
= gcov_read_unsigned ();
259 filename
= gcov_read_string ();
261 ll_info
->filename
= gcov_canonical_filename (xstrdup (filename
));
263 ll_info
->filename
= 0;
266 /* Read LEN words and construct branch mispredict info BRM_INFO. */
269 gcov_read_pmu_branch_mispredict_info (gcov_pmu_brm_info_t
*brm_info
,
270 gcov_unsigned_t len ATTRIBUTE_UNUSED
)
272 const char *filename
;
273 brm_info
->counts
= gcov_read_unsigned ();
274 brm_info
->self
= gcov_read_unsigned ();
275 brm_info
->cum
= gcov_read_unsigned ();
276 brm_info
->code_addr
= gcov_read_counter ();
277 brm_info
->line
= gcov_read_unsigned ();
278 brm_info
->discriminator
= gcov_read_unsigned ();
279 filename
= gcov_read_string ();
281 brm_info
->filename
= gcov_canonical_filename (xstrdup (filename
));
283 brm_info
->filename
= 0;
286 /* Read LEN words from an open gcov file and construct data into pmu
287 tool header TOOL_HEADER. */
289 GCOV_LINKAGE
void gcov_read_pmu_tool_header (gcov_pmu_tool_header_t
*header
,
290 gcov_unsigned_t len ATTRIBUTE_UNUSED
)
293 str
= gcov_read_string ();
294 header
->host_cpu
= str
? xstrdup (str
) : 0;
295 str
= gcov_read_string ();
296 header
->hostname
= str
? xstrdup (str
) : 0;
297 str
= gcov_read_string ();
298 header
->kernel_version
= str
? xstrdup (str
) : 0;
299 str
= gcov_read_string ();
300 header
->column_header
= str
? xstrdup (str
) : 0;
301 str
= gcov_read_string ();
302 header
->column_description
= str
? xstrdup (str
) : 0;
303 str
= gcov_read_string ();
304 header
->full_header
= str
? xstrdup (str
) : 0;
309 /* Check if MAGIC is EXPECTED. Use it to determine endianness of the
310 file. Returns +1 for same endian, -1 for other endian and zero for
314 gcov_magic (gcov_unsigned_t magic
, gcov_unsigned_t expected
)
316 if (magic
== expected
)
318 magic
= (magic
>> 16) | (magic
<< 16);
319 magic
= ((magic
& 0xff00ff) << 8) | ((magic
>> 8) & 0xff00ff);
320 if (magic
== expected
)
331 gcov_allocate (unsigned length
)
333 size_t new_size
= gcov_var
.alloc
;
336 new_size
= GCOV_BLOCK_SIZE
;
340 gcov_var
.alloc
= new_size
;
341 gcov_var
.buffer
= XRESIZEVAR (gcov_unsigned_t
, gcov_var
.buffer
, new_size
<< 2);
346 /* Write out the current block, if needs be. */
349 gcov_write_block (unsigned size
)
351 if (_GCOV_fwrite (gcov_var
.buffer
, size
<< 2, 1, gcov_var
.file
) != 1)
353 gcov_var
.start
+= size
;
354 gcov_var
.offset
-= size
;
358 /* Return the number of words STRING would need including the length
359 field in the output stream itself. This should be identical to
360 "alloc" calculation in gcov_write_string(). */
362 GCOV_LINKAGE gcov_unsigned_t
363 gcov_string_length (const char *string
)
365 gcov_unsigned_t len
= (string
) ? strlen (string
) : 0;
366 /* + 1 because of the length field. */
367 gcov_unsigned_t alloc
= 1 + ((len
+ 4) >> 2);
369 /* Can not write a bigger than GCOV_BLOCK_SIZE string yet */
370 gcc_assert (alloc
< GCOV_BLOCK_SIZE
);
375 /* Allocate space to write BYTES bytes to the gcov file. Return a
376 pointer to those bytes, or NULL on failure. */
378 static gcov_unsigned_t
*
379 gcov_write_words (unsigned words
)
381 gcov_unsigned_t
*result
;
383 gcc_assert (gcov_var
.mode
< 0);
385 if (gcov_var
.offset
+ words
>= GCOV_BLOCK_SIZE
)
387 gcov_write_block (MIN (gcov_var
.offset
, GCOV_BLOCK_SIZE
));
390 gcc_assert (gcov_var
.offset
< GCOV_BLOCK_SIZE
);
391 memcpy (gcov_var
.buffer
,
392 gcov_var
.buffer
+ GCOV_BLOCK_SIZE
,
393 gcov_var
.offset
<< 2);
397 if (gcov_var
.offset
+ words
> gcov_var
.alloc
)
398 gcov_allocate (gcov_var
.offset
+ words
);
400 result
= &gcov_var
.buffer
[gcov_var
.offset
];
401 gcov_var
.offset
+= words
;
406 /* Write unsigned VALUE to coverage file. Sets error flag
410 gcov_write_unsigned (gcov_unsigned_t value
)
412 gcov_unsigned_t
*buffer
= gcov_write_words (1);
417 /* Write counter VALUE to coverage file. Sets error flag
422 gcov_write_counter (gcov_type value
)
424 gcov_unsigned_t
*buffer
= gcov_write_words (2);
426 buffer
[0] = (gcov_unsigned_t
) value
;
427 if (sizeof (value
) > sizeof (gcov_unsigned_t
))
428 buffer
[1] = (gcov_unsigned_t
) (value
>> 32);
432 #endif /* IN_LIBGCOV */
434 /* Write STRING to coverage file. Sets error flag on file
435 error, overflow flag on overflow */
438 gcov_write_string (const char *string
)
442 gcov_unsigned_t
*buffer
;
446 length
= strlen (string
);
447 alloc
= (length
+ 4) >> 2;
450 buffer
= gcov_write_words (1 + alloc
);
454 memcpy (&buffer
[1], string
, length
);
458 /* Write a tag TAG and reserve space for the record length. Return a
459 value to be used for gcov_write_length. */
461 GCOV_LINKAGE gcov_position_t
462 gcov_write_tag (gcov_unsigned_t tag
)
464 gcov_position_t result
= gcov_var
.start
+ gcov_var
.offset
;
465 gcov_unsigned_t
*buffer
= gcov_write_words (2);
473 /* Write a record length using POSITION, which was returned by
474 gcov_write_tag. The current file position is the end of the
475 record, and is restored before returning. Returns nonzero on
479 gcov_write_length (gcov_position_t position
)
482 gcov_unsigned_t length
;
483 gcov_unsigned_t
*buffer
;
485 gcc_assert (gcov_var
.mode
< 0);
486 gcc_assert (position
+ 2 <= gcov_var
.start
+ gcov_var
.offset
);
487 gcc_assert (position
>= gcov_var
.start
);
488 offset
= position
- gcov_var
.start
;
489 length
= gcov_var
.offset
- offset
- 2;
490 buffer
= (gcov_unsigned_t
*) &gcov_var
.buffer
[offset
];
492 if (gcov_var
.offset
>= GCOV_BLOCK_SIZE
)
493 gcov_write_block (gcov_var
.offset
);
496 #else /* IN_LIBGCOV */
498 /* Write a tag TAG and length LENGTH. */
501 gcov_write_tag_length (gcov_unsigned_t tag
, gcov_unsigned_t length
)
503 gcov_unsigned_t
*buffer
= gcov_write_words (2);
509 /* Write a summary structure to the gcov file. Return nonzero on
513 gcov_write_summary (gcov_unsigned_t tag
, const struct gcov_summary
*summary
)
516 const struct gcov_ctr_summary
*csum
;
518 gcov_write_tag_length (tag
, GCOV_TAG_SUMMARY_LENGTH
);
519 gcov_write_unsigned (summary
->checksum
);
520 for (csum
= summary
->ctrs
, ix
= GCOV_COUNTERS_SUMMABLE
; ix
--; csum
++)
522 gcov_write_unsigned (csum
->num
);
523 gcov_write_unsigned (csum
->runs
);
524 gcov_write_counter (csum
->sum_all
);
525 gcov_write_counter (csum
->run_max
);
526 gcov_write_counter (csum
->sum_max
);
529 #endif /* IN_LIBGCOV */
533 /* Return a pointer to read BYTES bytes from the gcov file. Returns
534 NULL on failure (read past EOF). */
536 static const gcov_unsigned_t
*
537 gcov_read_words (unsigned words
)
539 const gcov_unsigned_t
*result
;
540 unsigned excess
= gcov_var
.length
- gcov_var
.offset
;
542 gcc_assert (gcov_var
.mode
> 0);
543 gcc_assert (words
< GCOV_BLOCK_SIZE
);
546 gcov_var
.start
+= gcov_var
.offset
;
550 gcc_assert (excess
< GCOV_BLOCK_SIZE
);
551 memmove (gcov_var
.buffer
, gcov_var
.buffer
+ gcov_var
.offset
, excess
* 4);
554 memmove (gcov_var
.buffer
, gcov_var
.buffer
+ gcov_var
.offset
, excess
* 4);
557 gcov_var
.length
= excess
;
559 excess
= (sizeof (gcov_var
.buffer
) / sizeof (gcov_var
.buffer
[0])) - gcov_var
.length
;
561 if (gcov_var
.length
+ words
> gcov_var
.alloc
)
562 gcov_allocate (gcov_var
.length
+ words
);
563 excess
= gcov_var
.alloc
- gcov_var
.length
;
565 excess
= _GCOV_fread (gcov_var
.buffer
+ gcov_var
.length
,
566 1, excess
<< 2, gcov_var
.file
) >> 2;
567 gcov_var
.length
+= excess
;
568 if (gcov_var
.length
< words
)
570 gcov_var
.overread
+= words
- gcov_var
.length
;
575 result
= &gcov_var
.buffer
[gcov_var
.offset
];
576 gcov_var
.offset
+= words
;
580 /* Read unsigned value from a coverage file. Sets error flag on file
581 error, overflow flag on overflow */
583 GCOV_LINKAGE gcov_unsigned_t
584 gcov_read_unsigned (void)
586 gcov_unsigned_t value
;
587 const gcov_unsigned_t
*buffer
= gcov_read_words (1);
591 value
= from_file (buffer
[0]);
595 /* Read counter value from a coverage file. Sets error flag on file
596 error, overflow flag on overflow */
598 GCOV_LINKAGE gcov_type
599 gcov_read_counter (void)
602 const gcov_unsigned_t
*buffer
= gcov_read_words (2);
606 value
= from_file (buffer
[0]);
607 if (sizeof (value
) > sizeof (gcov_unsigned_t
))
608 value
|= ((gcov_type
) from_file (buffer
[1])) << 32;
615 /* Read string from coverage file. Returns a pointer to a static
616 buffer, or NULL on empty string. You must copy the string before
617 calling another gcov function. */
619 GCOV_LINKAGE
const char *
620 gcov_read_string (void)
622 unsigned length
= gcov_read_unsigned ();
627 return (const char *) gcov_read_words (length
);
631 gcov_read_summary (struct gcov_summary
*summary
)
634 struct gcov_ctr_summary
*csum
;
636 summary
->checksum
= gcov_read_unsigned ();
637 for (csum
= summary
->ctrs
, ix
= GCOV_COUNTERS_SUMMABLE
; ix
--; csum
++)
639 csum
->num
= gcov_read_unsigned ();
640 csum
->runs
= gcov_read_unsigned ();
641 csum
->sum_all
= gcov_read_counter ();
642 csum
->run_max
= gcov_read_counter ();
643 csum
->sum_max
= gcov_read_counter ();
647 #if !IN_LIBGCOV && IN_GCOV != 1
648 /* Read LEN words (unsigned type) and construct MOD_INFO. */
651 gcov_read_module_info (struct gcov_module_info
*mod_info
,
654 gcov_unsigned_t src_filename_len
, filename_len
, i
, j
, num_strings
;
655 mod_info
->ident
= gcov_read_unsigned ();
656 mod_info
->is_primary
= gcov_read_unsigned ();
657 mod_info
->is_exported
= gcov_read_unsigned ();
658 mod_info
->lang
= gcov_read_unsigned ();
659 mod_info
->num_quote_paths
= gcov_read_unsigned ();
660 mod_info
->num_bracket_paths
= gcov_read_unsigned ();
661 mod_info
->num_cpp_defines
= gcov_read_unsigned ();
662 mod_info
->num_cpp_includes
= gcov_read_unsigned ();
663 mod_info
->num_cl_args
= gcov_read_unsigned ();
666 filename_len
= gcov_read_unsigned ();
667 mod_info
->da_filename
= (char *) xmalloc (filename_len
*
668 sizeof (gcov_unsigned_t
));
669 for (i
= 0; i
< filename_len
; i
++)
670 ((gcov_unsigned_t
*) mod_info
->da_filename
)[i
] = gcov_read_unsigned ();
671 len
-= (filename_len
+ 1);
673 src_filename_len
= gcov_read_unsigned ();
674 mod_info
->source_filename
= (char *) xmalloc (src_filename_len
*
675 sizeof (gcov_unsigned_t
));
676 for (i
= 0; i
< src_filename_len
; i
++)
677 ((gcov_unsigned_t
*) mod_info
->source_filename
)[i
] = gcov_read_unsigned ();
678 len
-= (src_filename_len
+ 1);
680 num_strings
= mod_info
->num_quote_paths
+ mod_info
->num_bracket_paths
+
681 mod_info
->num_cpp_defines
+ mod_info
->num_cpp_includes
+
682 mod_info
->num_cl_args
;
683 for (j
= 0; j
< num_strings
; j
++)
685 gcov_unsigned_t string_len
= gcov_read_unsigned ();
686 mod_info
->string_array
[j
] =
687 (char *) xmalloc (string_len
* sizeof (gcov_unsigned_t
));
688 for (i
= 0; i
< string_len
; i
++)
689 ((gcov_unsigned_t
*) mod_info
->string_array
[j
])[i
] =
690 gcov_read_unsigned ();
691 len
-= (string_len
+ 1);
698 /* Reset to a known position. BASE should have been obtained from
699 gcov_position, LENGTH should be a record length. */
702 gcov_sync (gcov_position_t base
, gcov_unsigned_t length
)
704 #ifdef __GCOV_KERNEL__
705 /* should not reach this point */
707 #else /* __GCOV_KERNEL__ */
708 gcc_assert (gcov_var
.mode
> 0);
710 if (base
- gcov_var
.start
<= gcov_var
.length
)
711 gcov_var
.offset
= base
- gcov_var
.start
;
714 gcov_var
.offset
= gcov_var
.length
= 0;
715 _GCOV_fseek (gcov_var
.file
, base
<< 2, SEEK_SET
);
716 gcov_var
.start
= _GCOV_ftell (gcov_var
.file
) >> 2;
718 #endif /* __GCOV_KERNEL__ */
723 /* Move to a given position in a gcov file. */
726 gcov_seek (gcov_position_t base
)
728 gcc_assert (gcov_var
.mode
< 0);
730 gcov_write_block (gcov_var
.offset
);
731 _GCOV_fseek (gcov_var
.file
, base
<< 2, SEEK_SET
);
732 gcov_var
.start
= _GCOV_ftell (gcov_var
.file
) >> 2;
735 /* Truncate the gcov file at the current position. */
740 #ifdef __GCOV_KERNEL__
741 /* should not reach this point */
743 #else /* __GCOV_KERNEL__ */
746 gcc_assert (gcov_var
.mode
< 0);
748 gcov_write_block (gcov_var
.offset
);
749 offs
= ftell (gcov_var
.file
);
750 filenum
= fileno (gcov_var
.file
);
751 if (offs
== -1 || filenum
== -1 || ftruncate (filenum
, offs
))
753 #endif /* __GCOV_KERNEL__ */
757 #ifndef __GCOV_KERNEL__
758 /* Convert an unsigned NUMBER to a percentage after dividing by
762 convert_unsigned_to_pct (const unsigned number
)
764 return (float)number
/ 100.0f
;
768 #if !IN_LIBGCOV && IN_GCOV != 1
769 /* Print load latency information given by LL_INFO in a human readable
770 format into an open output file pointed by FP. NEWLINE specifies
771 whether or not to print a trailing newline. */
774 print_load_latency_line (FILE *fp
, const gcov_pmu_ll_info_t
*ll_info
,
775 const enum print_newline newline
)
779 fprintf (fp
, " %u %.2f%% %.2f%% %.2f%% %.2f%% %.2f%% %.2f%% %.2f%% "
780 "%.2f%% %.2f%% " HOST_WIDEST_INT_PRINT_HEX
" %s %d %d",
782 convert_unsigned_to_pct (ll_info
->self
),
783 convert_unsigned_to_pct (ll_info
->cum
),
784 convert_unsigned_to_pct (ll_info
->lt_10
),
785 convert_unsigned_to_pct (ll_info
->lt_32
),
786 convert_unsigned_to_pct (ll_info
->lt_64
),
787 convert_unsigned_to_pct (ll_info
->lt_256
),
788 convert_unsigned_to_pct (ll_info
->lt_1024
),
789 convert_unsigned_to_pct (ll_info
->gt_1024
),
790 convert_unsigned_to_pct (ll_info
->wself
),
794 ll_info
->discriminator
);
795 if (newline
== add_newline
)
799 /* Print BRM_INFO into the file pointed by FP. NEWLINE specifies
800 whether or not to print a trailing newline. */
803 print_branch_mispredict_line (FILE *fp
, const gcov_pmu_brm_info_t
*brm_info
,
804 const enum print_newline newline
)
808 fprintf (fp
, " %u %.2f%% %.2f%% " HOST_WIDEST_INT_PRINT_HEX
" %s %d %d",
810 convert_unsigned_to_pct (brm_info
->self
),
811 convert_unsigned_to_pct (brm_info
->cum
),
815 brm_info
->discriminator
);
816 if (newline
== add_newline
)
820 /* Print TOOL_HEADER into the file pointed by FP. NEWLINE specifies
821 whether or not to print a trailing newline. */
824 print_pmu_tool_header (FILE *fp
, gcov_pmu_tool_header_t
*tool_header
,
825 const enum print_newline newline
)
829 fprintf (fp
, "\nhost_cpu: %s\n", tool_header
->host_cpu
);
830 fprintf (fp
, "hostname: %s\n", tool_header
->hostname
);
831 fprintf (fp
, "kernel_version: %s\n", tool_header
->kernel_version
);
832 fprintf (fp
, "column_header: %s\n", tool_header
->column_header
);
833 fprintf (fp
, "column_description: %s\n", tool_header
->column_description
);
834 fprintf (fp
, "full_header: %s\n", tool_header
->full_header
);
835 if (newline
== add_newline
)
841 /* Return the modification time of the current gcov file. */
848 if (fstat (fileno (gcov_var
.file
), &status
))
851 return status
.st_mtime
;
855 #ifdef __GCOV_KERNEL__
857 /* File fclose operation in kernel mode. */
860 kernel_file_fclose (gcov_kernel_vfile
*fp
)
865 /* File ftell operation in kernel mode. It currently should not
869 kernel_file_ftell (gcov_kernel_vfile
*fp
)
871 gcc_assert (0); /* should not reach here */
875 /* File fseek operation in kernel mode. It should only be called
876 with OFFSET==0 and WHENCE==0 to a freshly opened file. */
879 kernel_file_fseek (gcov_kernel_vfile
*fp
, long offset
, int whence
)
881 gcc_assert (offset
== 0 && whence
== 0 && fp
->count
== 0);
885 /* File ftruncate operation in kernel mode. It currently should not
889 kernel_file_ftruncate (gcov_kernel_vfile
*fp
, off_t value
)
891 gcc_assert (0); /* should not reach here */
895 /* File fread operation in kernel mode. It currently should not
899 kernel_file_fread (void *ptr
, size_t size
, size_t nitems
,
900 gcov_kernel_vfile
*fp
)
902 gcc_assert (0); /* should not reach here */
906 /* File fwrite operation in kernel mode. It outputs the data
907 to a buffer in the virual file. */
910 kernel_file_fwrite (const void *ptr
, size_t size
,
911 size_t nitems
, gcov_kernel_vfile
*fp
)
914 unsigned vsize
, vpos
;
926 "GCOV_KERNEL: something wrong: vbuf=%p vsize=%u vpos=%u\n",
936 memcpy (vbuf
+vpos
, ptr
, size
*len
);
937 fp
->count
+= len
*size
;
941 "GCOV_KERNEL: something wrong: size=%lu nitems=%lu ret=%d\n",
946 /* File fileno operation in kernel mode. It currently should not
950 kernel_file_fileno (gcov_kernel_vfile
*fp
)
952 gcc_assert (0); /* should not reach here */
955 #else /* __GCOV_KERNEL__ */
958 /* Delete pmu tool header TOOL_HEADER. */
961 destroy_pmu_tool_header (gcov_pmu_tool_header_t
*tool_header
)
965 if (tool_header
->host_cpu
)
966 free (tool_header
->host_cpu
);
967 if (tool_header
->hostname
)
968 free (tool_header
->hostname
);
969 if (tool_header
->kernel_version
)
970 free (tool_header
->kernel_version
);
971 if (tool_header
->column_header
)
972 free (tool_header
->column_header
);
973 if (tool_header
->column_description
)
974 free (tool_header
->column_description
);
975 if (tool_header
->full_header
)
976 free (tool_header
->full_header
);
980 #endif /* GCOV_KERNEL */