##// END OF EJS Templates
Added gcov support...
jeandet -
r387:96eb9489ec21 No PWD scrub with... draft
parent child
Show More
@@ -0,0 +1,17
1 cmake_minimum_required(VERSION 3.6)
2 project(libgcov C)
3 include(sparc-rtems)
4 include(cppcheck)
5
6 set(LIB_GCOV_SOURCES
7 gcov-io.c
8 gcov-io.h
9 gcov-iov.h
10 libgcov.c
11 )
12
13 add_library(gcov STATIC ${LIB_GCOV_SOURCES})
14
15 add_custom_target(gcovr
16 COMMAND gcovr --exclude='.*gcov.*' --gcov-executable=${rtems_dir}/bin/sparc-rtems-gcov --object-directory ${CMAKE_BINARY_DIR} -r ${CMAKE_SOURCE_DIR} --html --html-details -o ${CMAKE_CURRENT_BINARY_DIR}/gcov.html && xdg-open ${CMAKE_CURRENT_BINARY_DIR}/gcov.html
17 )
@@ -0,0 +1,38
1 #!/usr/bin/env python3
2
3 __author__ = "Alexis Jeandet"
4 __copyright__ = "Copyright 2018, Laboratory of Plasma Physics"
5 __credits__ = []
6 __license__ = "GPLv2"
7 __version__ = "1.0.0"
8 __maintainer__ = "Alexis Jeandet"
9 __email__ = "alexis.jeandet@member.fsf.org"
10 __status__ = "Development"
11
12 import time
13 import sys
14 import os
15 import serial
16 import argparse
17 from datetime import datetime
18
19 parser = argparse.ArgumentParser()
20 parser.add_argument("-f", "--gcov-file", help="Gcov output file generated by record_lfr_console.py")
21 args = parser.parse_args()
22
23
24
25 def main():
26 with open(args.gcov_file,'r') as gcov:
27 for line in gcov.readlines():
28 head,dest_file,data = line.split(',')
29 if head == '_GCOV_':
30 print(f"Writing {dest_file}\n")
31 with open(dest_file,'wb') as gcda_file:
32 gcda_file.write(bytes([int(''.join(value),16) for value in zip(data[::2],data[1::2]) ]))
33 else:
34 raise
35
36
37 if __name__ == "__main__":
38 main()
This diff has been collapsed as it changes many lines, (820 lines changed) Show them Hide them
@@ -0,0 +1,820
1 /* Test for GCC >= 3.4.4 && <= 4.4.6 */
2 //#if ( ( __GNUC__ > 3 ) || \
3 // ( __GNUC__ == 3 && __GNUC_MINOR__ > 4 )|| \
4 // ( __GNUC__ == 3 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ >= 4 ) ) && \
5 // ( ( __GNUC__ < 4 ) || \
6 // ( __GNUC__ == 4 && __GNUC_MINOR__ < 4 )|| \
7 // ( __GNUC__ == 4 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ <= 6 ) )
8 /*
9 * =====================================================================================
10 *
11 * Filename: gcov-io.c
12 *
13 * Description: This is the I/O file for embedded systems
14 *
15 * Version: 1.0
16 * Created: 03/04/08 09:51:59
17 * Revision: none
18 * Compiler: gcc
19 *
20 * Author: Aitor Viana Sanchez (avs), aitor.viana.sanchez@esa.int
21 * Company: European Space Agency (ESA-ESTEC)
22 *
23 * =====================================================================================
24 */
25
26 /* File format for coverage information
27 Copyright (C) 1996, 1997, 1998, 2000, 2002,
28 2003 Free Software Foundation, Inc.
29 Contributed by Bob Manson <manson@cygnus.com>.
30 Completely remangled by Nathan Sidwell <nathan@codesourcery.com>.
31
32 This file is part of GCC.
33
34 GCC is free software; you can redistribute it and/or modify it under
35 the terms of the GNU General Public License as published by the Free
36 Software Foundation; either version 2, or (at your option) any later
37 version.
38
39 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
40 WARRANTY; without even the implied warranty of MERCHANTABILITY or
41 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
42 for more details.
43
44 You should have received a copy of the GNU General Public License
45 along with GCC; see the file COPYING. If not, write to the Free
46 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
47 02111-1307, USA. */
48
49 #include <stdio.h>
50 #include <stdlib.h> /* for atexit() */
51 #include <string.h>
52 #include "gcov-io.h"
53
54 /* Routines declared in gcov-io.h. This file should be #included by
55 another source file, after having #included gcov-io.h. */
56
57
58 /* This function shall be defined somewhere else */
59 //int send_data(unsigned char * buffer, unsigned int size);
60
61 /*-----------------------------------------------------------------------------
62 * PRIVATE INTERFACE
63 *-----------------------------------------------------------------------------*/
64
65 static void gcov_write_block (unsigned);
66 static gcov_unsigned_t *gcov_write_words (unsigned);
67 GCOV_LINKAGE int gcov_send (void);
68 GCOV_LINKAGE int gcov_close(void);
69 //static const gcov_unsigned_t *gcov_read_words (unsigned);
70
71 extern struct gcov_info * gcov_list;
72 extern gcov_unsigned_t gcov_crc32;
73
74 int dev_id = 0;
75
76 /*
77 * === FUNCTION ======================================================================
78 * Name: from_file
79 * Description: This function just return the given parameter
80 * =====================================================================================
81 */
82 static inline gcov_unsigned_t from_file (gcov_unsigned_t value)
83 {
84 return value;
85 }
86
87 /*
88 * === FUNCTION ======================================================================
89 * Name: gcov_version
90 * Description: This function returns TRUE (1) if the gcov version is the
91 * version expected. The function returns FALSE (0) in any other case.
92 * =====================================================================================
93 */
94 static int gcov_version (struct gcov_info *ptr, gcov_unsigned_t version)
95 {
96 if (version != GCOV_VERSION)
97 {
98 char v[4], e[4];
99
100 GCOV_UNSIGNED2STRING (v, version);
101 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
102
103 printf ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
104 ptr->filename, e, v);
105
106 return 0;
107 }
108 return 1;
109 }
110
111
112 /*-----------------------------------------------------------------------------
113 * PUBLIC INTERFACE
114 *-----------------------------------------------------------------------------*/
115
116 /* Dump the coverage counts. We merge with existing counts when
117 possible, to avoid growing the .da files ad infinitum. We use this
118 program's checksum to make sure we only accumulate whole program
119 statistics to the correct summary. An object file might be embedded
120 in two separate programs, and we must keep the two program
121 summaries separate. */
122
123 /*
124 * === FUNCTION ======================================================================
125 * Name: gcov_exit
126 * Description: This function dumps the coverage couns. The merging with
127 * existing counts is not done in embedded systems.
128 * =====================================================================================
129 */
130 void gcov_exit (void)
131 {
132 struct gcov_info *gi_ptr;
133 struct gcov_summary this_program;
134 struct gcov_summary all;
135 struct gcov_ctr_summary *cs_ptr;
136 const struct gcov_ctr_info *ci_ptr;
137 unsigned t_ix;
138 gcov_unsigned_t c_num;
139 unsigned long coreId = 0;
140
141 /* retrieve the id of the CPU the program is running on */
142 #ifdef LEON3
143 __asm__ __volatile__("rd %%asr17,%0\n\t"
144 "srl %0,28,%0" :
145 "=&r" (coreId) : );
146 #endif
147
148 printf("_GCOVEXIT_BEGIN_,core%d\n", coreId); /* see also _GCOVEXIT_END_ */
149
150 if(gcov_list == (void*)0x0)
151 printf("%s: gcov_list == NULL\n", __func__);
152
153 memset (&all, 0, sizeof (all));
154 /* Find the totals for this execution. */
155 memset (&this_program, 0, sizeof (this_program));
156 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
157 {
158
159 ci_ptr = gi_ptr->counts;
160 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
161 {
162 if (!((1 << t_ix) & gi_ptr->ctr_mask))
163 continue;
164
165 cs_ptr = &this_program.ctrs[t_ix];
166 cs_ptr->num += ci_ptr->num;
167 for (c_num = 0; c_num < ci_ptr->num; c_num++)
168 {
169 cs_ptr->sum_all += ci_ptr->values[c_num];
170 if (cs_ptr->run_max < ci_ptr->values[c_num])
171 cs_ptr->run_max = ci_ptr->values[c_num];
172 }
173 ci_ptr++;
174 }
175 }
176 /* Now merge each file. */
177 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
178 {
179 // struct gcov_summary this_object, object;
180 // struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
181 // int error = 0;
182 // gcov_unsigned_t tag, length;
183 // gcov_position_t summary_pos = 0;
184 struct gcov_summary program;
185 gcov_type *values[GCOV_COUNTERS];
186 const struct gcov_fn_info *fi_ptr;
187 unsigned fi_stride;
188 unsigned c_ix, f_ix, n_counts;
189
190 #if 0
191 memset (&this_object, 0, sizeof (this_object));
192 memset (&object, 0, sizeof (object));
193
194
195 /* Totals for this object file. */
196 ci_ptr = gi_ptr->counts;
197 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
198 {
199 if (!((1 << t_ix) & gi_ptr->ctr_mask))
200 continue;
201
202 cs_ptr = &this_object.ctrs[t_ix];
203 cs_ptr->num += ci_ptr->num;
204 for (c_num = 0; c_num < ci_ptr->num; c_num++)
205 {
206 cs_ptr->sum_all += ci_ptr->values[c_num];
207 if (cs_ptr->run_max < ci_ptr->values[c_num])
208 cs_ptr->run_max = ci_ptr->values[c_num];
209 }
210
211 ci_ptr++;
212 }
213 #endif
214
215 c_ix = 0;
216 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
217 if ((1 << t_ix) & gi_ptr->ctr_mask)
218 {
219 values[c_ix] = gi_ptr->counts[c_ix].values;
220 c_ix++;
221 }
222
223 /* Calculate the function_info stride. This depends on the
224 number of counter types being measured. */
225 fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned);
226 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
227 {
228 fi_stride += __alignof__ (struct gcov_fn_info) - 1;
229 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
230 }
231
232 if (!gcov_open (gi_ptr->filename))
233 {
234 printf ("profiling:%s:Cannot open\n", gi_ptr->filename);
235 continue;
236 }
237
238 #if 0
239 tag = gcov_read_unsigned ();
240 if (tag)
241 {
242 /* Merge data from file. */
243 if (tag != GCOV_DATA_MAGIC)
244 {
245 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
246 gi_ptr->filename);
247 read_fatal:;
248 gcov_close ();
249 continue;
250 }
251 length = gcov_read_unsigned ();
252 if (!gcov_version (gi_ptr, length))
253 goto read_fatal;
254
255 length = gcov_read_unsigned ();
256 if (length != gi_ptr->stamp)
257 {
258 /* Read from a different compilation. Overwrite the
259 file. */
260 gcov_truncate ();
261 goto rewrite;
262 }
263
264 /* Merge execution counts for each function. */
265 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
266 {
267 fi_ptr = (const struct gcov_fn_info *)
268 ((const char *) gi_ptr->functions + f_ix * fi_stride);
269 tag = gcov_read_unsigned ();
270 length = gcov_read_unsigned ();
271
272 /* Check function. */
273 if (tag != GCOV_TAG_FUNCTION
274 || length != GCOV_TAG_FUNCTION_LENGTH
275 || gcov_read_unsigned () != fi_ptr->ident
276 || gcov_read_unsigned () != fi_ptr->checksum)
277 {
278 read_mismatch:;
279 fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
280 gi_ptr->filename,
281 f_ix + 1 ? "function" : "summaries");
282 goto read_fatal;
283 }
284
285 c_ix = 0;
286 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
287 {
288 gcov_merge_fn merge;
289
290 if (!((1 << t_ix) & gi_ptr->ctr_mask))
291 continue;
292
293 n_counts = fi_ptr->n_ctrs[c_ix];
294 merge = gi_ptr->counts[c_ix].merge;
295
296 tag = gcov_read_unsigned ();
297 length = gcov_read_unsigned ();
298 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
299 || length != GCOV_TAG_COUNTER_LENGTH (n_counts))
300 goto read_mismatch;
301 (*merge) (values[c_ix], n_counts);
302 values[c_ix] += n_counts;
303 c_ix++;
304 }
305 if ((error = gcov_is_error ()))
306 goto read_error;
307 }
308
309 f_ix = ~0u;
310 /* Check program & object summary */
311 while (1)
312 {
313 gcov_position_t base = gcov_position ();
314 int is_program;
315
316 tag = gcov_read_unsigned ();
317 if (!tag)
318 break;
319 length = gcov_read_unsigned ();
320 is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
321 if (length != GCOV_TAG_SUMMARY_LENGTH
322 || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY))
323 goto read_mismatch;
324 gcov_read_summary (is_program ? &program : &object);
325 if ((error = gcov_is_error ()))
326 goto read_error;
327 if (is_program && program.checksum == gcov_crc32)
328 {
329 summary_pos = base;
330 goto rewrite;
331 }
332 }
333 }
334
335 if (!gcov_is_eof ())
336 {
337 read_error:;
338 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
339 : "profiling:%s:Error merging\n", gi_ptr->filename);
340 goto read_fatal;
341 }
342 rewrite:;
343 gcov_rewrite ();
344 if (!summary_pos)
345 memset (&program, 0, sizeof (program));
346 /* Merge the summaries. */
347 f_ix = ~0u;
348 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
349 {
350 cs_obj = &object.ctrs[t_ix];
351 cs_tobj = &this_object.ctrs[t_ix];
352 cs_prg = &program.ctrs[t_ix];
353 cs_tprg = &this_program.ctrs[t_ix];
354 cs_all = &all.ctrs[t_ix];
355
356 if ((1 << t_ix) & gi_ptr->ctr_mask)
357 {
358 if (!cs_obj->runs++)
359 cs_obj->num = cs_tobj->num;
360 else if (cs_obj->num != cs_tobj->num)
361 goto read_mismatch;
362 cs_obj->sum_all += cs_tobj->sum_all;
363 if (cs_obj->run_max < cs_tobj->run_max)
364 cs_obj->run_max = cs_tobj->run_max;
365 cs_obj->sum_max += cs_tobj->run_max;
366
367 if (!cs_prg->runs++)
368 cs_prg->num = cs_tprg->num;
369 else if (cs_prg->num != cs_tprg->num)
370 goto read_mismatch;
371 cs_prg->sum_all += cs_tprg->sum_all;
372 if (cs_prg->run_max < cs_tprg->run_max)
373 cs_prg->run_max = cs_tprg->run_max;
374 cs_prg->sum_max += cs_tprg->run_max;
375 }
376 else if (cs_obj->num || cs_prg->num)
377 goto read_mismatch;
378
379 if (!cs_all->runs && cs_prg->runs)
380 memcpy (cs_all, cs_prg, sizeof (*cs_all));
381 else if (!all.checksum
382 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
383 && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
384 {
385 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
386 gi_ptr->filename, GCOV_LOCKED
387 ? "" : " or concurrent update without locking support");
388 all.checksum = ~0u;
389 }
390 }
391
392 c_ix = 0;
393 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
394 if ((1 << t_ix) & gi_ptr->ctr_mask)
395 {
396 values[c_ix] = gi_ptr->counts[c_ix].values;
397 c_ix++;
398 }
399
400 #endif
401 program.checksum = gcov_crc32;
402
403 /* Write out the data. */
404 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
405 gcov_write_unsigned (gi_ptr->stamp);
406
407 /* Write execution counts for each function. */
408 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
409 {
410 fi_ptr = (const struct gcov_fn_info *)
411 ((const char *) gi_ptr->functions + f_ix * fi_stride);
412
413 /* Announce function. */
414 gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH);
415 gcov_write_unsigned (fi_ptr->ident);
416 gcov_write_unsigned (fi_ptr->checksum);
417
418 c_ix = 0;
419 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
420 {
421 gcov_type *c_ptr;
422
423 if (!((1 << t_ix) & gi_ptr->ctr_mask))
424 continue;
425
426 n_counts = fi_ptr->n_ctrs[c_ix];
427
428 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
429 GCOV_TAG_COUNTER_LENGTH (n_counts));
430 c_ptr = values[c_ix];
431 while (n_counts--)
432 gcov_write_counter (*c_ptr++);
433
434 values[c_ix] = c_ptr;
435 c_ix++;
436 }
437 }
438
439 /* Object file summary. */
440 // gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
441
442 /* Generate whole program statistics. */
443 // gcov_seek (summary_pos);
444 // gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
445 gcov_send();
446 gcov_close();
447 /* if ((error = gcov_send ()))
448 fprintf (stderr, error < 0 ?
449 "profiling:%s:Overflow writing\n" :
450 "profiling:%s:Error writing\n",
451 gi_ptr->filename);*/
452 }
453
454 printf("_GCOVEXIT_END_,core%d\n", coreId);
455 }
456
457
458 /* Called before fork or exec - write out profile information gathered so
459 far and reset it to zero. This avoids duplication or loss of the
460 profile information gathered so far. */
461
462 void
463 __gcov_flush (void)
464 {
465 const struct gcov_info *gi_ptr;
466
467 gcov_exit ();
468 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
469 {
470 unsigned t_ix;
471 const struct gcov_ctr_info *ci_ptr;
472
473 for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
474 if ((1 << t_ix) & gi_ptr->ctr_mask)
475 {
476 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
477 ci_ptr++;
478 }
479 }
480 }
481
482
483
484 /* Open a gcov file. NAME is the name of the file to open and MODE
485 indicates whether a new file should be created, or an existing file
486 opened for modification. If MODE is >= 0 an existing file will be
487 opened, if possible, and if MODE is <= 0, a new file will be
488 created. Use MODE=0 to attempt to reopen an existing file and then
489 fall back on creating a new one. Return zero on failure, >0 on
490 opening an existing file and <0 on creating a new one. */
491 GCOV_LINKAGE int gcov_open(const char *name)
492 {
493 // gcov_var.start is cleared in the gcov_close function.
494 // If this variable is not cleared...ERROR
495 if( gcov_var.start != 0 )
496 return 0;
497
498 // Clear everything
499 gcov_var.start = 0;
500 gcov_var.offset = gcov_var.length = 0;
501 gcov_var.overread = -1u;
502 gcov_var.error = 0;
503
504
505 // copy the filename in the gcov_var structure
506 strcpy(gcov_var.filename, name);
507
508
509 // return 1 means everything is OK
510 return 1;
511 }
512
513 /* Close the current gcov file. Flushes data to disk. Returns nonzero
514 on failure or error flag set. */
515
516 GCOV_LINKAGE int gcov_send (void)
517 {
518 /*printf("%s: file %s\n", __func__, gcov_var.filename);*/
519 if (gcov_var.offset)
520 gcov_write_block (gcov_var.offset);
521
522 gcov_var.length = 0;
523 return gcov_var.error;
524 }
525
526 GCOV_LINKAGE int gcov_close(void)
527 {
528 /*printf("%s: %s\n", __func__, gcov_var.filename);*/
529 memset(gcov_var.filename, 0, strlen(gcov_var.filename));
530
531 // Clear the start variable because will be tested in the gcov_open
532 // function
533 gcov_var.start = 0;
534
535 // Return the error, not sure whether the error is modifed.
536 return gcov_var.error;
537 }
538
539 /* Write out the
540 current block, if needs be. */
541 /*static void gcov_write_block (unsigned size) {
542 unsigned int bw = 0;
543 unsigned int i;
544
545 printf("_GCOV_,%s,", gcov_var.filename);
546 for(i = 0; i < size << 2; i++) {
547 char str[5] = {0};
548
549 printf("%02X", ((unsigned char*)(gcov_var.buffer))[i]);
550 }
551 printf("\n");
552
553 gcov_var.start += size;
554 gcov_var.offset -= size;
555 }*/
556
557 static void gcov_write_block (unsigned size) {
558 unsigned char *buffer = (unsigned char*) gcov_var.buffer;
559 unsigned int i;
560
561 printf("_GCOV_,%s,", gcov_var.filename);
562 /* to speed up the printing process, we display bytes 4 by 4 */
563 for(i = 0; i < size; i++) {
564 printf("%02X%02X%02X%02X", (unsigned int)(buffer[0]),
565 (unsigned int)(buffer[1]),
566 (unsigned int)(buffer[2]),
567 (unsigned int)(buffer[3]));
568
569 buffer += sizeof(gcov_unsigned_t);
570 }
571 printf("\n");
572
573 gcov_var.start += size;
574 gcov_var.offset -= size;
575 }
576
577 /* Allocate space to write BYTES bytes to the gcov file. Return a
578 pointer to those bytes, or NULL on failure. */
579
580 static gcov_unsigned_t *gcov_write_words (unsigned words) {
581 gcov_unsigned_t *result;
582
583 GCOV_CHECK_WRITING ();
584 if (gcov_var.offset >= GCOV_BLOCK_SIZE)
585 {
586 gcov_write_block (GCOV_BLOCK_SIZE);
587 if (gcov_var.offset)
588 {
589 GCOV_CHECK (gcov_var.offset == 1);
590 memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4);
591 }
592 }
593 result = &gcov_var.buffer[gcov_var.offset];
594 gcov_var.offset += words;
595
596 return result;
597 }
598
599 /* Write unsigned VALUE to coverage file. Sets error flag
600 appropriately. */
601
602 GCOV_LINKAGE void
603 gcov_write_unsigned (gcov_unsigned_t value)
604 {
605 gcov_unsigned_t *buffer = gcov_write_words (1);
606
607 buffer[0] = value;
608 }
609
610 /* Write counter VALUE to coverage file. Sets error flag
611 appropriately. */
612
613 GCOV_LINKAGE void
614 gcov_write_counter (gcov_type value)
615 {
616 gcov_unsigned_t *buffer = gcov_write_words (2);
617
618 buffer[0] = (gcov_unsigned_t) value;
619 if (sizeof (value) > sizeof (gcov_unsigned_t))
620 buffer[1] = (gcov_unsigned_t) (value >> 32);
621 else
622 buffer[1] = 0;
623
624 // if (value < 0)
625 // gcov_var.error = -1;
626 }
627
628 /* Write a tag TAG and length LENGTH. */
629
630 GCOV_LINKAGE void
631 gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length)
632 {
633 gcov_unsigned_t *buffer = gcov_write_words (2);
634
635 buffer[0] = tag;
636 buffer[1] = length;
637 }
638
639 /* Write a summary structure to the gcov file. Return nonzero on
640 overflow. */
641
642 GCOV_LINKAGE void
643 gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary)
644 {
645 unsigned ix;
646 const struct gcov_ctr_summary *csum;
647
648 gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH);
649 gcov_write_unsigned (summary->checksum);
650 for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++)
651 {
652 gcov_write_unsigned (csum->num);
653 gcov_write_unsigned (csum->runs);
654 gcov_write_counter (csum->sum_all);
655 gcov_write_counter (csum->run_max);
656 gcov_write_counter (csum->sum_max);
657 }
658 }
659
660 /* Return a pointer to read BYTES bytes from the gcov file. Returns
661 NULL on failure (read past EOF). */
662 #if 0
663 GCOV_LINKAGE const gcov_unsigned_t *
664 gcov_read_words (unsigned words)
665 {
666 const gcov_unsigned_t *result;
667 unsigned excess = gcov_var.length - gcov_var.offset;
668
669 GCOV_CHECK_READING ();
670 if (excess < words)
671 {
672 gcov_var.start += gcov_var.offset;
673 if (excess)
674 {
675 GCOV_CHECK (excess == 1);
676 memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4);
677 }
678 gcov_var.offset = 0;
679 gcov_var.length = excess;
680 GCOV_CHECK (!gcov_var.length || gcov_var.length == 1);
681 excess = GCOV_BLOCK_SIZE;
682 excess = fread (gcov_var.buffer + gcov_var.length,
683 1, excess << 2, gcov_var.file) >> 2;
684 gcov_var.length += excess;
685 if (gcov_var.length < words)
686 {
687 gcov_var.overread += words - gcov_var.length;
688 gcov_var.length = 0;
689 return 0;
690 }
691 }
692 result = &gcov_var.buffer[gcov_var.offset];
693 gcov_var.offset += words;
694 return result;
695 }
696
697
698 /* Read unsigned value from a coverage file. Sets error flag on file
699 error, overflow flag on overflow */
700
701 GCOV_LINKAGE gcov_unsigned_t
702 gcov_read_unsigned (void)
703 {
704 gcov_unsigned_t value;
705 const gcov_unsigned_t *buffer = gcov_read_words (1);
706
707 if (!buffer)
708 return 0;
709 value = from_file (buffer[0]);
710 return value;
711 }
712
713 /* Read counter value from a coverage file. Sets error flag on file
714 error, overflow flag on overflow */
715 #endif
716 GCOV_LINKAGE gcov_type
717 gcov_read_counter (void)
718 {
719 #if 0
720 gcov_type value;
721 const gcov_unsigned_t *buffer = gcov_read_words (2);
722
723 if (!buffer)
724 return 0;
725 value = from_file (buffer[0]);
726 if (sizeof (value) > sizeof (gcov_unsigned_t))
727 value |= ((gcov_type) from_file (buffer[1])) << 32;
728 else if (buffer[1])
729 gcov_var.error = -1;
730
731 if (value < 0)
732 gcov_var.error = -1;
733 return value;
734 #endif
735 return 0;
736 }
737 #if 0
738
739 /* Read string from coverage file. Returns a pointer to a static
740 buffer, or NULL on empty string. You must copy the string before
741 calling another gcov function. */
742
743 GCOV_LINKAGE void
744 gcov_read_summary (struct gcov_summary *summary)
745 {
746 unsigned ix;
747 struct gcov_ctr_summary *csum;
748
749 summary->checksum = gcov_read_unsigned ();
750 for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++)
751 {
752 csum->num = gcov_read_unsigned ();
753 csum->runs = gcov_read_unsigned ();
754 csum->sum_all = gcov_read_counter ();