xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/gcov-io.c (revision 63ce0b47aeb8b4c6792d02a0de9ecf8182e299ac)
1 /* File format for coverage information
2    Copyright (C) 1996-2016 Free Software Foundation, Inc.
3    Contributed by Bob Manson <manson@cygnus.com>.
4    Completely remangled by Nathan Sidwell <nathan@codesourcery.com>.
5 
6 This file is part of GCC.
7 
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12 
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17 
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
21 
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25 <http://www.gnu.org/licenses/>.  */
26 
27 /* Routines declared in gcov-io.h.  This file should be #included by
28    another source file, after having #included gcov-io.h.  */
29 
30 #if !IN_GCOV
31 static void gcov_write_block (unsigned);
32 static gcov_unsigned_t *gcov_write_words (unsigned);
33 #endif
34 static const gcov_unsigned_t *gcov_read_words (unsigned);
35 #if !IN_LIBGCOV
36 static void gcov_allocate (unsigned);
37 #endif
38 
39 /* Optimum number of gcov_unsigned_t's read from or written to disk.  */
40 #define GCOV_BLOCK_SIZE (1 << 10)
41 
42 struct gcov_var
43 {
44   FILE *file;
45   gcov_position_t start;	/* Position of first byte of block */
46   unsigned offset;		/* Read/write position within the block.  */
47   unsigned length;		/* Read limit in the block.  */
48   unsigned overread;		/* Number of words overread.  */
49   int error;			/* < 0 overflow, > 0 disk error.  */
50   int mode;	                /* < 0 writing, > 0 reading */
51 #if IN_LIBGCOV
52   /* Holds one block plus 4 bytes, thus all coverage reads & writes
53      fit within this buffer and we always can transfer GCOV_BLOCK_SIZE
54      to and from the disk. libgcov never backtracks and only writes 4
55      or 8 byte objects.  */
56   gcov_unsigned_t buffer[GCOV_BLOCK_SIZE + 1];
57 #else
58   int endian;			/* Swap endianness.  */
59   /* Holds a variable length block, as the compiler can write
60      strings and needs to backtrack.  */
61   size_t alloc;
62   gcov_unsigned_t *buffer;
63 #endif
64 } gcov_var;
65 
66 /* Save the current position in the gcov file.  */
67 /* We need to expose this function when compiling for gcov-tool.  */
68 #ifndef IN_GCOV_TOOL
69 static inline
70 #endif
71 gcov_position_t
72 gcov_position (void)
73 {
74   gcov_nonruntime_assert (gcov_var.mode > 0);
75   return gcov_var.start + gcov_var.offset;
76 }
77 
78 /* Return nonzero if the error flag is set.  */
79 /* We need to expose this function when compiling for gcov-tool.  */
80 #ifndef IN_GCOV_TOOL
81 static inline
82 #endif
83 int
84 gcov_is_error (void)
85 {
86   return gcov_var.file ? gcov_var.error : 1;
87 }
88 
89 #if IN_LIBGCOV
90 /* Move to beginning of file and initialize for writing.  */
91 GCOV_LINKAGE inline void
92 gcov_rewrite (void)
93 {
94   gcov_var.mode = -1;
95   gcov_var.start = 0;
96   gcov_var.offset = 0;
97   fseek (gcov_var.file, 0L, SEEK_SET);
98 }
99 #endif
100 
101 static inline gcov_unsigned_t from_file (gcov_unsigned_t value)
102 {
103 #if !IN_LIBGCOV
104   if (gcov_var.endian)
105     {
106       value = (value >> 16) | (value << 16);
107       value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff);
108     }
109 #endif
110   return value;
111 }
112 
113 /* Open a gcov file. NAME is the name of the file to open and MODE
114    indicates whether a new file should be created, or an existing file
115    opened. If MODE is >= 0 an existing file will be opened, if
116    possible, and if MODE is <= 0, a new file will be created. Use
117    MODE=0 to attempt to reopen an existing file and then fall back on
118    creating a new one.  If MODE < 0, the file will be opened in
119    read-only mode.  Otherwise it will be opened for modification.
120    Return zero on failure, >0 on opening an existing file and <0 on
121    creating a new one.  */
122 
123 GCOV_LINKAGE int
124 #if IN_LIBGCOV
125 gcov_open (const char *name)
126 #else
127 gcov_open (const char *name, int mode)
128 #endif
129 {
130 #if IN_LIBGCOV
131   const int mode = 0;
132 #endif
133 #if GCOV_LOCKED
134   struct flock s_flock;
135   int fd;
136 
137   s_flock.l_whence = SEEK_SET;
138   s_flock.l_start = 0;
139   s_flock.l_len = 0; /* Until EOF.  */
140   s_flock.l_pid = getpid ();
141 #endif
142 
143   gcov_nonruntime_assert (!gcov_var.file);
144   gcov_var.start = 0;
145   gcov_var.offset = gcov_var.length = 0;
146   gcov_var.overread = -1u;
147   gcov_var.error = 0;
148 #if !IN_LIBGCOV
149   gcov_var.endian = 0;
150 #endif
151 #if GCOV_LOCKED
152   if (mode > 0)
153     {
154       /* Read-only mode - acquire a read-lock.  */
155       s_flock.l_type = F_RDLCK;
156       /* pass mode (ignored) for compatibility */
157       fd = open (name, O_RDONLY, S_IRUSR | S_IWUSR);
158     }
159   else if (mode < 0)
160      {
161        /* Write mode - acquire a write-lock.  */
162        s_flock.l_type = F_WRLCK;
163       fd = open (name, O_RDWR | O_CREAT | O_TRUNC, 0666);
164     }
165   else /* mode == 0 */
166     {
167       /* Read-Write mode - acquire a write-lock.  */
168       s_flock.l_type = F_WRLCK;
169       fd = open (name, O_RDWR | O_CREAT, 0666);
170     }
171   if (fd < 0)
172     return 0;
173 
174   while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR)
175     continue;
176 
177   gcov_var.file = fdopen (fd, (mode > 0) ? "rb" : "r+b");
178 
179   if (!gcov_var.file)
180     {
181       close (fd);
182       return 0;
183     }
184 
185   if (mode > 0)
186     gcov_var.mode = 1;
187   else if (mode == 0)
188     {
189       struct stat st;
190 
191       if (fstat (fd, &st) < 0)
192 	{
193 	  fclose (gcov_var.file);
194 	  gcov_var.file = 0;
195 	  return 0;
196 	}
197       if (st.st_size != 0)
198 	gcov_var.mode = 1;
199       else
200 	gcov_var.mode = mode * 2 + 1;
201     }
202   else
203     gcov_var.mode = mode * 2 + 1;
204 #else
205   if (mode >= 0)
206     gcov_var.file = fopen (name, (mode > 0) ? "rb" : "r+b");
207 
208   if (gcov_var.file)
209     gcov_var.mode = 1;
210   else if (mode <= 0)
211     {
212       gcov_var.file = fopen (name, "w+b");
213       if (gcov_var.file)
214 	gcov_var.mode = mode * 2 + 1;
215     }
216   if (!gcov_var.file)
217     return 0;
218 #endif
219 
220   setbuf (gcov_var.file, (char *)0);
221 
222   return 1;
223 }
224 
225 /* Close the current gcov file. Flushes data to disk. Returns nonzero
226    on failure or error flag set.  */
227 
228 GCOV_LINKAGE int
229 gcov_close (void)
230 {
231   if (gcov_var.file)
232     {
233 #if !IN_GCOV
234       if (gcov_var.offset && gcov_var.mode < 0)
235 	gcov_write_block (gcov_var.offset);
236 #endif
237       fclose (gcov_var.file);
238       gcov_var.file = 0;
239       gcov_var.length = 0;
240     }
241 #if !IN_LIBGCOV
242   free (gcov_var.buffer);
243   gcov_var.alloc = 0;
244   gcov_var.buffer = 0;
245 #endif
246   gcov_var.mode = 0;
247   return gcov_var.error;
248 }
249 
250 #if !IN_LIBGCOV
251 /* Check if MAGIC is EXPECTED. Use it to determine endianness of the
252    file. Returns +1 for same endian, -1 for other endian and zero for
253    not EXPECTED.  */
254 
255 GCOV_LINKAGE int
256 gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected)
257 {
258   if (magic == expected)
259     return 1;
260   magic = (magic >> 16) | (magic << 16);
261   magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff);
262   if (magic == expected)
263     {
264       gcov_var.endian = 1;
265       return -1;
266     }
267   return 0;
268 }
269 #endif
270 
271 #if !IN_LIBGCOV
272 static void
273 gcov_allocate (unsigned length)
274 {
275   size_t new_size = gcov_var.alloc;
276 
277   if (!new_size)
278     new_size = GCOV_BLOCK_SIZE;
279   new_size += length;
280   new_size *= 2;
281 
282   gcov_var.alloc = new_size;
283   gcov_var.buffer = XRESIZEVAR (gcov_unsigned_t, gcov_var.buffer, new_size << 2);
284 }
285 #endif
286 
287 #if !IN_GCOV
288 /* Write out the current block, if needs be.  */
289 
290 static void
291 gcov_write_block (unsigned size)
292 {
293   if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1)
294     gcov_var.error = 1;
295   gcov_var.start += size;
296   gcov_var.offset -= size;
297 }
298 
299 /* Allocate space to write BYTES bytes to the gcov file. Return a
300    pointer to those bytes, or NULL on failure.  */
301 
302 static gcov_unsigned_t *
303 gcov_write_words (unsigned words)
304 {
305   gcov_unsigned_t *result;
306 
307   gcov_nonruntime_assert (gcov_var.mode < 0);
308 #if IN_LIBGCOV
309   if (gcov_var.offset >= GCOV_BLOCK_SIZE)
310     {
311       gcov_write_block (GCOV_BLOCK_SIZE);
312       if (gcov_var.offset)
313 	{
314 	  memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4);
315 	}
316     }
317 #else
318   if (gcov_var.offset + words > gcov_var.alloc)
319     gcov_allocate (gcov_var.offset + words);
320 #endif
321   result = &gcov_var.buffer[gcov_var.offset];
322   gcov_var.offset += words;
323 
324   return result;
325 }
326 
327 /* Write unsigned VALUE to coverage file.  Sets error flag
328    appropriately.  */
329 
330 GCOV_LINKAGE void
331 gcov_write_unsigned (gcov_unsigned_t value)
332 {
333   gcov_unsigned_t *buffer = gcov_write_words (1);
334 
335   buffer[0] = value;
336 }
337 
338 /* Write counter VALUE to coverage file.  Sets error flag
339    appropriately.  */
340 
341 #if IN_LIBGCOV
342 GCOV_LINKAGE void
343 gcov_write_counter (gcov_type value)
344 {
345   gcov_unsigned_t *buffer = gcov_write_words (2);
346 
347   buffer[0] = (gcov_unsigned_t) value;
348   if (sizeof (value) > sizeof (gcov_unsigned_t))
349     buffer[1] = (gcov_unsigned_t) (value >> 32);
350   else
351     buffer[1] = 0;
352 }
353 #endif /* IN_LIBGCOV */
354 
355 #if !IN_LIBGCOV
356 /* Write STRING to coverage file.  Sets error flag on file
357    error, overflow flag on overflow */
358 
359 GCOV_LINKAGE void
360 gcov_write_string (const char *string)
361 {
362   unsigned length = 0;
363   unsigned alloc = 0;
364   gcov_unsigned_t *buffer;
365 
366   if (string)
367     {
368       length = strlen (string);
369       alloc = (length + 4) >> 2;
370     }
371 
372   buffer = gcov_write_words (1 + alloc);
373 
374   buffer[0] = alloc;
375 
376   if (alloc > 0)
377     {
378       buffer[alloc] = 0; /* place nul terminators.  */
379       memcpy (&buffer[1], string, length);
380     }
381 }
382 #endif
383 
384 #if !IN_LIBGCOV
385 /* Write a tag TAG and reserve space for the record length. Return a
386    value to be used for gcov_write_length.  */
387 
388 GCOV_LINKAGE gcov_position_t
389 gcov_write_tag (gcov_unsigned_t tag)
390 {
391   gcov_position_t result = gcov_var.start + gcov_var.offset;
392   gcov_unsigned_t *buffer = gcov_write_words (2);
393 
394   buffer[0] = tag;
395   buffer[1] = 0;
396 
397   return result;
398 }
399 
400 /* Write a record length using POSITION, which was returned by
401    gcov_write_tag.  The current file position is the end of the
402    record, and is restored before returning.  Returns nonzero on
403    overflow.  */
404 
405 GCOV_LINKAGE void
406 gcov_write_length (gcov_position_t position)
407 {
408   unsigned offset;
409   gcov_unsigned_t length;
410   gcov_unsigned_t *buffer;
411 
412   gcov_nonruntime_assert (gcov_var.mode < 0);
413   gcov_nonruntime_assert (position + 2 <= gcov_var.start + gcov_var.offset);
414   gcov_nonruntime_assert (position >= gcov_var.start);
415   offset = position - gcov_var.start;
416   length = gcov_var.offset - offset - 2;
417   buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset];
418   buffer[1] = length;
419   if (gcov_var.offset >= GCOV_BLOCK_SIZE)
420     gcov_write_block (gcov_var.offset);
421 }
422 
423 #else /* IN_LIBGCOV */
424 
425 /* Write a tag TAG and length LENGTH.  */
426 
427 GCOV_LINKAGE void
428 gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length)
429 {
430   gcov_unsigned_t *buffer = gcov_write_words (2);
431 
432   buffer[0] = tag;
433   buffer[1] = length;
434 }
435 
436 /* Write a summary structure to the gcov file.  Return nonzero on
437    overflow.  */
438 
439 GCOV_LINKAGE void
440 gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary)
441 {
442   unsigned ix, h_ix, bv_ix, h_cnt = 0;
443   const struct gcov_ctr_summary *csum;
444   unsigned histo_bitvector[GCOV_HISTOGRAM_BITVECTOR_SIZE];
445 
446   /* Count number of non-zero histogram entries, and fill in a bit vector
447      of non-zero indices. The histogram is only currently computed for arc
448      counters.  */
449   for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
450     histo_bitvector[bv_ix] = 0;
451   csum = &summary->ctrs[GCOV_COUNTER_ARCS];
452   for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
453     {
454       if (csum->histogram[h_ix].num_counters > 0)
455         {
456           histo_bitvector[h_ix / 32] |= 1 << (h_ix % 32);
457           h_cnt++;
458         }
459     }
460   gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH (h_cnt));
461   gcov_write_unsigned (summary->checksum);
462   for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++)
463     {
464       gcov_write_unsigned (csum->num);
465       gcov_write_unsigned (csum->runs);
466       gcov_write_counter (csum->sum_all);
467       gcov_write_counter (csum->run_max);
468       gcov_write_counter (csum->sum_max);
469       if (ix != GCOV_COUNTER_ARCS)
470         {
471           for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
472             gcov_write_unsigned (0);
473           continue;
474         }
475       for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
476         gcov_write_unsigned (histo_bitvector[bv_ix]);
477       for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
478         {
479           if (!csum->histogram[h_ix].num_counters)
480             continue;
481           gcov_write_unsigned (csum->histogram[h_ix].num_counters);
482           gcov_write_counter (csum->histogram[h_ix].min_value);
483           gcov_write_counter (csum->histogram[h_ix].cum_value);
484         }
485     }
486 }
487 #endif /* IN_LIBGCOV */
488 
489 #endif /*!IN_GCOV */
490 
491 /* Return a pointer to read BYTES bytes from the gcov file. Returns
492    NULL on failure (read past EOF).  */
493 
494 static const gcov_unsigned_t *
495 gcov_read_words (unsigned words)
496 {
497   const gcov_unsigned_t *result;
498   unsigned excess = gcov_var.length - gcov_var.offset;
499 
500   gcov_nonruntime_assert (gcov_var.mode > 0);
501   if (excess < words)
502     {
503       gcov_var.start += gcov_var.offset;
504       if (excess)
505 	{
506 #if IN_LIBGCOV
507 	  memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4);
508 #else
509 	  memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset,
510 		   excess * 4);
511 #endif
512 	}
513       gcov_var.offset = 0;
514       gcov_var.length = excess;
515 #if IN_LIBGCOV
516       excess = GCOV_BLOCK_SIZE;
517 #else
518       if (gcov_var.length + words > gcov_var.alloc)
519 	gcov_allocate (gcov_var.length + words);
520       excess = gcov_var.alloc - gcov_var.length;
521 #endif
522       excess = fread (gcov_var.buffer + gcov_var.length,
523 		      1, excess << 2, gcov_var.file) >> 2;
524       gcov_var.length += excess;
525       if (gcov_var.length < words)
526 	{
527 	  gcov_var.overread += words - gcov_var.length;
528 	  gcov_var.length = 0;
529 	  return 0;
530 	}
531     }
532   result = &gcov_var.buffer[gcov_var.offset];
533   gcov_var.offset += words;
534   return result;
535 }
536 
537 /* Read unsigned value from a coverage file. Sets error flag on file
538    error, overflow flag on overflow */
539 
540 GCOV_LINKAGE gcov_unsigned_t
541 gcov_read_unsigned (void)
542 {
543   gcov_unsigned_t value;
544   const gcov_unsigned_t *buffer = gcov_read_words (1);
545 
546   if (!buffer)
547     return 0;
548   value = from_file (buffer[0]);
549   return value;
550 }
551 
552 /* Read counter value from a coverage file. Sets error flag on file
553    error, overflow flag on overflow */
554 
555 GCOV_LINKAGE gcov_type
556 gcov_read_counter (void)
557 {
558   gcov_type value;
559   const gcov_unsigned_t *buffer = gcov_read_words (2);
560 
561   if (!buffer)
562     return 0;
563   value = from_file (buffer[0]);
564   if (sizeof (value) > sizeof (gcov_unsigned_t))
565     value |= ((gcov_type) from_file (buffer[1])) << 32;
566   else if (buffer[1])
567     gcov_var.error = -1;
568 
569   return value;
570 }
571 
572 /* We need to expose the below function when compiling for gcov-tool.  */
573 
574 #if !IN_LIBGCOV || defined (IN_GCOV_TOOL)
575 /* Read string from coverage file. Returns a pointer to a static
576    buffer, or NULL on empty string. You must copy the string before
577    calling another gcov function.  */
578 
579 GCOV_LINKAGE const char *
580 gcov_read_string (void)
581 {
582   unsigned length = gcov_read_unsigned ();
583 
584   if (!length)
585     return 0;
586 
587   return (const char *) gcov_read_words (length);
588 }
589 #endif
590 
591 GCOV_LINKAGE void
592 gcov_read_summary (struct gcov_summary *summary)
593 {
594   unsigned ix, h_ix, bv_ix, h_cnt = 0;
595   struct gcov_ctr_summary *csum;
596   unsigned histo_bitvector[GCOV_HISTOGRAM_BITVECTOR_SIZE];
597   unsigned cur_bitvector;
598 
599   summary->checksum = gcov_read_unsigned ();
600   for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++)
601     {
602       csum->num = gcov_read_unsigned ();
603       csum->runs = gcov_read_unsigned ();
604       csum->sum_all = gcov_read_counter ();
605       csum->run_max = gcov_read_counter ();
606       csum->sum_max = gcov_read_counter ();
607       memset (csum->histogram, 0,
608               sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
609       for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
610         {
611           histo_bitvector[bv_ix] = gcov_read_unsigned ();
612 #if IN_LIBGCOV
613           /* When building libgcov we don't include system.h, which includes
614              hwint.h (where popcount_hwi is declared). However, libgcov.a
615              is built by the bootstrapped compiler and therefore the builtins
616              are always available.  */
617           h_cnt += __builtin_popcount (histo_bitvector[bv_ix]);
618 #else
619           h_cnt += popcount_hwi (histo_bitvector[bv_ix]);
620 #endif
621         }
622       bv_ix = 0;
623       h_ix = 0;
624       cur_bitvector = 0;
625       while (h_cnt--)
626         {
627           /* Find the index corresponding to the next entry we will read in.
628              First find the next non-zero bitvector and re-initialize
629              the histogram index accordingly, then right shift and increment
630              the index until we find a set bit.  */
631           while (!cur_bitvector)
632             {
633               h_ix = bv_ix * 32;
634               if (bv_ix >= GCOV_HISTOGRAM_BITVECTOR_SIZE)
635                 gcov_error ("corrupted profile info: summary histogram "
636                             "bitvector is corrupt");
637               cur_bitvector = histo_bitvector[bv_ix++];
638             }
639           while (!(cur_bitvector & 0x1))
640             {
641               h_ix++;
642               cur_bitvector >>= 1;
643             }
644           if (h_ix >= GCOV_HISTOGRAM_SIZE)
645             gcov_error ("corrupted profile info: summary histogram "
646                         "index is corrupt");
647 
648           csum->histogram[h_ix].num_counters = gcov_read_unsigned ();
649           csum->histogram[h_ix].min_value = gcov_read_counter ();
650           csum->histogram[h_ix].cum_value = gcov_read_counter ();
651           /* Shift off the index we are done with and increment to the
652              corresponding next histogram entry.  */
653           cur_bitvector >>= 1;
654           h_ix++;
655         }
656     }
657 }
658 
659 /* We need to expose the below function when compiling for gcov-tool.  */
660 
661 #if !IN_LIBGCOV || defined (IN_GCOV_TOOL)
662 /* Reset to a known position.  BASE should have been obtained from
663    gcov_position, LENGTH should be a record length.  */
664 
665 GCOV_LINKAGE void
666 gcov_sync (gcov_position_t base, gcov_unsigned_t length)
667 {
668   gcov_nonruntime_assert (gcov_var.mode > 0);
669   base += length;
670   if (base - gcov_var.start <= gcov_var.length)
671     gcov_var.offset = base - gcov_var.start;
672   else
673     {
674       gcov_var.offset = gcov_var.length = 0;
675       fseek (gcov_var.file, base << 2, SEEK_SET);
676       gcov_var.start = ftell (gcov_var.file) >> 2;
677     }
678 }
679 #endif
680 
681 #if IN_LIBGCOV
682 /* Move to a given position in a gcov file.  */
683 
684 GCOV_LINKAGE void
685 gcov_seek (gcov_position_t base)
686 {
687   if (gcov_var.offset)
688     gcov_write_block (gcov_var.offset);
689   fseek (gcov_var.file, base << 2, SEEK_SET);
690   gcov_var.start = ftell (gcov_var.file) >> 2;
691 }
692 #endif
693 
694 #if IN_GCOV > 0
695 /* Return the modification time of the current gcov file.  */
696 
697 GCOV_LINKAGE time_t
698 gcov_time (void)
699 {
700   struct stat status;
701 
702   if (fstat (fileno (gcov_var.file), &status))
703     return 0;
704   else
705     return status.st_mtime;
706 }
707 #endif /* IN_GCOV */
708 
709 #if !IN_GCOV
710 /* Determine the index into histogram for VALUE. */
711 
712 #if IN_LIBGCOV
713 static unsigned
714 #else
715 GCOV_LINKAGE unsigned
716 #endif
717 gcov_histo_index (gcov_type value)
718 {
719   gcov_type_unsigned v = (gcov_type_unsigned)value;
720   unsigned r = 0;
721   unsigned prev2bits = 0;
722 
723   /* Find index into log2 scale histogram, where each of the log2
724      sized buckets is divided into 4 linear sub-buckets for better
725      focus in the higher buckets.  */
726 
727   /* Find the place of the most-significant bit set.  */
728   if (v > 0)
729     {
730 #if IN_LIBGCOV
731       /* When building libgcov we don't include system.h, which includes
732          hwint.h (where floor_log2 is declared). However, libgcov.a
733          is built by the bootstrapped compiler and therefore the builtins
734          are always available.  */
735       r = sizeof (long long) * __CHAR_BIT__ - 1 - __builtin_clzll (v);
736 #else
737       /* We use floor_log2 from hwint.c, which takes a HOST_WIDE_INT
738          that is 64 bits and gcov_type_unsigned is 64 bits.  */
739       r = floor_log2 (v);
740 #endif
741     }
742 
743   /* If at most the 2 least significant bits are set (value is
744      0 - 3) then that value is our index into the lowest set of
745      four buckets.  */
746   if (r < 2)
747     return (unsigned)value;
748 
749   gcov_nonruntime_assert (r < 64);
750 
751   /* Find the two next most significant bits to determine which
752      of the four linear sub-buckets to select.  */
753   prev2bits = (v >> (r - 2)) & 0x3;
754   /* Finally, compose the final bucket index from the log2 index and
755      the next 2 bits. The minimum r value at this point is 2 since we
756      returned above if r was 2 or more, so the minimum bucket at this
757      point is 4.  */
758   return (r - 1) * 4 + prev2bits;
759 }
760 
761 /* Merge SRC_HISTO into TGT_HISTO. The counters are assumed to be in
762    the same relative order in both histograms, and are matched up
763    and merged in reverse order. Each counter is assigned an equal portion of
764    its entry's original cumulative counter value when computing the
765    new merged cum_value.  */
766 
767 static void gcov_histogram_merge (gcov_bucket_type *tgt_histo,
768                                   gcov_bucket_type *src_histo)
769 {
770   int src_i, tgt_i, tmp_i = 0;
771   unsigned src_num, tgt_num, merge_num;
772   gcov_type src_cum, tgt_cum, merge_src_cum, merge_tgt_cum, merge_cum;
773   gcov_type merge_min;
774   gcov_bucket_type tmp_histo[GCOV_HISTOGRAM_SIZE];
775   int src_done = 0;
776 
777   memset (tmp_histo, 0, sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
778 
779   /* Assume that the counters are in the same relative order in both
780      histograms. Walk the histograms from largest to smallest entry,
781      matching up and combining counters in order.  */
782   src_num = 0;
783   src_cum = 0;
784   src_i = GCOV_HISTOGRAM_SIZE - 1;
785   for (tgt_i = GCOV_HISTOGRAM_SIZE - 1; tgt_i >= 0 && !src_done; tgt_i--)
786     {
787       tgt_num = tgt_histo[tgt_i].num_counters;
788       tgt_cum = tgt_histo[tgt_i].cum_value;
789       /* Keep going until all of the target histogram's counters at this
790          position have been matched and merged with counters from the
791          source histogram.  */
792       while (tgt_num > 0 && !src_done)
793         {
794           /* If this is either the first time through this loop or we just
795              exhausted the previous non-zero source histogram entry, look
796              for the next non-zero source histogram entry.  */
797           if (!src_num)
798             {
799               /* Locate the next non-zero entry.  */
800               while (src_i >= 0 && !src_histo[src_i].num_counters)
801                 src_i--;
802               /* If source histogram has fewer counters, then just copy over the
803                  remaining target counters and quit.  */
804               if (src_i < 0)
805                 {
806                   tmp_histo[tgt_i].num_counters += tgt_num;
807                   tmp_histo[tgt_i].cum_value += tgt_cum;
808                   if (!tmp_histo[tgt_i].min_value ||
809                       tgt_histo[tgt_i].min_value < tmp_histo[tgt_i].min_value)
810                     tmp_histo[tgt_i].min_value = tgt_histo[tgt_i].min_value;
811                   while (--tgt_i >= 0)
812                     {
813                       tmp_histo[tgt_i].num_counters
814                           += tgt_histo[tgt_i].num_counters;
815                       tmp_histo[tgt_i].cum_value += tgt_histo[tgt_i].cum_value;
816                       if (!tmp_histo[tgt_i].min_value ||
817                           tgt_histo[tgt_i].min_value
818                           < tmp_histo[tgt_i].min_value)
819                         tmp_histo[tgt_i].min_value = tgt_histo[tgt_i].min_value;
820                     }
821 
822                   src_done = 1;
823                   break;
824                 }
825 
826               src_num = src_histo[src_i].num_counters;
827               src_cum = src_histo[src_i].cum_value;
828             }
829 
830           /* The number of counters to merge on this pass is the minimum
831              of the remaining counters from the current target and source
832              histogram entries.  */
833           merge_num = tgt_num;
834           if (src_num < merge_num)
835             merge_num = src_num;
836 
837           /* The merged min_value is the sum of the min_values from target
838              and source.  */
839           merge_min = tgt_histo[tgt_i].min_value + src_histo[src_i].min_value;
840 
841           /* Compute the portion of source and target entries' cum_value
842              that will be apportioned to the counters being merged.
843              The total remaining cum_value from each entry is divided
844              equally among the counters from that histogram entry if we
845              are not merging all of them.  */
846           merge_src_cum = src_cum;
847           if (merge_num < src_num)
848             merge_src_cum = merge_num * src_cum / src_num;
849           merge_tgt_cum = tgt_cum;
850           if (merge_num < tgt_num)
851             merge_tgt_cum = merge_num * tgt_cum / tgt_num;
852           /* The merged cum_value is the sum of the source and target
853              components.  */
854           merge_cum = merge_src_cum + merge_tgt_cum;
855 
856           /* Update the remaining number of counters and cum_value left
857              to be merged from this source and target entry.  */
858           src_cum -= merge_src_cum;
859           tgt_cum -= merge_tgt_cum;
860           src_num -= merge_num;
861           tgt_num -= merge_num;
862 
863           /* The merged counters get placed in the new merged histogram
864              at the entry for the merged min_value.  */
865           tmp_i = gcov_histo_index (merge_min);
866           gcov_nonruntime_assert (tmp_i < GCOV_HISTOGRAM_SIZE);
867           tmp_histo[tmp_i].num_counters += merge_num;
868           tmp_histo[tmp_i].cum_value += merge_cum;
869           if (!tmp_histo[tmp_i].min_value ||
870               merge_min < tmp_histo[tmp_i].min_value)
871             tmp_histo[tmp_i].min_value = merge_min;
872 
873           /* Ensure the search for the next non-zero src_histo entry starts
874              at the next smallest histogram bucket.  */
875           if (!src_num)
876             src_i--;
877         }
878     }
879 
880   gcov_nonruntime_assert (tgt_i < 0);
881 
882   /* In the case where there were more counters in the source histogram,
883      accumulate the remaining unmerged cumulative counter values. Add
884      those to the smallest non-zero target histogram entry. Otherwise,
885      the total cumulative counter values in the histogram will be smaller
886      than the sum_all stored in the summary, which will complicate
887      computing the working set information from the histogram later on.  */
888   if (src_num)
889     src_i--;
890   while (src_i >= 0)
891     {
892       src_cum += src_histo[src_i].cum_value;
893       src_i--;
894     }
895   /* At this point, tmp_i should be the smallest non-zero entry in the
896      tmp_histo.  */
897   gcov_nonruntime_assert (tmp_i >= 0 && tmp_i < GCOV_HISTOGRAM_SIZE
898                           && tmp_histo[tmp_i].num_counters > 0);
899   tmp_histo[tmp_i].cum_value += src_cum;
900 
901   /* Finally, copy the merged histogram into tgt_histo.  */
902   memcpy (tgt_histo, tmp_histo,
903 	  sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
904 }
905 #endif /* !IN_GCOV */
906 
907 /* This is used by gcov-dump (IN_GCOV == -1) and in the compiler
908    (!IN_GCOV && !IN_LIBGCOV).  */
909 #if IN_GCOV <= 0 && !IN_LIBGCOV
910 /* Compute the working set information from the counter histogram in
911    the profile summary. This is an array of information corresponding to a
912    range of percentages of the total execution count (sum_all), and includes
913    the number of counters required to cover that working set percentage and
914    the minimum counter value in that working set.  */
915 
916 GCOV_LINKAGE void
917 compute_working_sets (const struct gcov_ctr_summary *summary,
918                       gcov_working_set_t *gcov_working_sets)
919 {
920   gcov_type working_set_cum_values[NUM_GCOV_WORKING_SETS];
921   gcov_type ws_cum_hotness_incr;
922   gcov_type cum, tmp_cum;
923   const gcov_bucket_type *histo_bucket;
924   unsigned ws_ix, c_num, count;
925   int h_ix;
926 
927   /* Compute the amount of sum_all that the cumulative hotness grows
928      by in each successive working set entry, which depends on the
929      number of working set entries.  */
930   ws_cum_hotness_incr = summary->sum_all / NUM_GCOV_WORKING_SETS;
931 
932   /* Next fill in an array of the cumulative hotness values corresponding
933      to each working set summary entry we are going to compute below.
934      Skip 0% statistics, which can be extrapolated from the
935      rest of the summary data.  */
936   cum = ws_cum_hotness_incr;
937   for (ws_ix = 0; ws_ix < NUM_GCOV_WORKING_SETS;
938        ws_ix++, cum += ws_cum_hotness_incr)
939     working_set_cum_values[ws_ix] = cum;
940   /* The last summary entry is reserved for (roughly) 99.9% of the
941      working set. Divide by 1024 so it becomes a shift, which gives
942      almost exactly 99.9%.  */
943   working_set_cum_values[NUM_GCOV_WORKING_SETS-1]
944       = summary->sum_all - summary->sum_all/1024;
945 
946   /* Next, walk through the histogram in decending order of hotness
947      and compute the statistics for the working set summary array.
948      As histogram entries are accumulated, we check to see which
949      working set entries have had their expected cum_value reached
950      and fill them in, walking the working set entries in increasing
951      size of cum_value.  */
952   ws_ix = 0; /* The current entry into the working set array.  */
953   cum = 0; /* The current accumulated counter sum.  */
954   count = 0; /* The current accumulated count of block counters.  */
955   for (h_ix = GCOV_HISTOGRAM_SIZE - 1;
956        h_ix >= 0 && ws_ix < NUM_GCOV_WORKING_SETS; h_ix--)
957     {
958       histo_bucket = &summary->histogram[h_ix];
959 
960       /* If we haven't reached the required cumulative counter value for
961          the current working set percentage, simply accumulate this histogram
962          entry into the running sums and continue to the next histogram
963          entry.  */
964       if (cum + histo_bucket->cum_value < working_set_cum_values[ws_ix])
965         {
966           cum += histo_bucket->cum_value;
967           count += histo_bucket->num_counters;
968           continue;
969         }
970 
971       /* If adding the current histogram entry's cumulative counter value
972          causes us to exceed the current working set size, then estimate
973          how many of this histogram entry's counter values are required to
974          reach the working set size, and fill in working set entries
975          as we reach their expected cumulative value.  */
976       for (c_num = 0, tmp_cum = cum;
977            c_num < histo_bucket->num_counters && ws_ix < NUM_GCOV_WORKING_SETS;
978            c_num++)
979         {
980           count++;
981           /* If we haven't reached the last histogram entry counter, add
982              in the minimum value again. This will underestimate the
983              cumulative sum so far, because many of the counter values in this
984              entry may have been larger than the minimum. We could add in the
985              average value every time, but that would require an expensive
986              divide operation.  */
987           if (c_num + 1 < histo_bucket->num_counters)
988             tmp_cum += histo_bucket->min_value;
989           /* If we have reached the last histogram entry counter, then add
990              in the entire cumulative value.  */
991           else
992             tmp_cum = cum + histo_bucket->cum_value;
993 
994 	  /* Next walk through successive working set entries and fill in
995 	     the statistics for any whose size we have reached by accumulating
996 	     this histogram counter.  */
997 	  while (ws_ix < NUM_GCOV_WORKING_SETS
998 		 && tmp_cum >= working_set_cum_values[ws_ix])
999             {
1000               gcov_working_sets[ws_ix].num_counters = count;
1001               gcov_working_sets[ws_ix].min_counter
1002                   = histo_bucket->min_value;
1003               ws_ix++;
1004             }
1005         }
1006       /* Finally, update the running cumulative value since we were
1007          using a temporary above.  */
1008       cum += histo_bucket->cum_value;
1009     }
1010   gcov_nonruntime_assert (ws_ix == NUM_GCOV_WORKING_SETS);
1011 }
1012 #endif /* IN_GCOV <= 0 && !IN_LIBGCOV */
1013