LCOV - code coverage report
Current view: top level - libgcov - gcov-io.c (source / functions) Hit Total Coverage
Test: trace.info Lines: 115 150 76.7 %
Date: 2023-02-20 11:47:18 Functions: 10 13 76.9 %

          Line data    Source code
       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 "gcov-io.h"
      50             : #include <stdio.h>
      51             : #include <stdlib.h> /* for atexit() */
      52             : #include <string.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             : 
      70             : extern struct gcov_info* gcov_list;
      71             : extern gcov_unsigned_t gcov_crc32;
      72             : 
      73             : int dev_id = 0;
      74             : 
      75             : /*
      76             :  * ===  FUNCTION  ======================================================================
      77             :  *         Name:  from_file
      78             :  *  Description:  This function just return the given parameter
      79             :  * =====================================================================================
      80             :  */
      81             : static inline gcov_unsigned_t from_file(gcov_unsigned_t value)
      82             : {
      83             :     return value;
      84             : }
      85             : 
      86             : /*
      87             :  * ===  FUNCTION  ======================================================================
      88             :  *         Name:  gcov_version
      89             :  *  Description:  This function returns TRUE (1) if the gcov version is the
      90             :  *  version expected. The function returns FALSE (0) in any other case.
      91             :  * =====================================================================================
      92             :  */
      93             : static int gcov_version(struct gcov_info* ptr, gcov_unsigned_t version)
      94             : {
      95         414 :     if (version != GCOV_VERSION)
      96             :     {
      97             :         char v[4], e[4];
      98             : 
      99           0 :         GCOV_UNSIGNED2STRING(v, version);
     100           0 :         GCOV_UNSIGNED2STRING(e, GCOV_VERSION);
     101             : 
     102           0 :         printf("profiling:%s:Version mismatch - expected %.4s got %.4s\n", ptr->filename, e, v);
     103             : 
     104           0 :         return 0;
     105             :     }
     106         414 :     return 1;
     107             : }
     108             : 
     109             : 
     110             : /*-----------------------------------------------------------------------------
     111             :  *  PUBLIC INTERFACE
     112             :  *-----------------------------------------------------------------------------*/
     113             : 
     114             : /* Dump the coverage counts. We merge with existing counts when
     115             :    possible, to avoid growing the .da files ad infinitum. We use this
     116             :    program's checksum to make sure we only accumulate whole program
     117             :    statistics to the correct summary. An object file might be embedded
     118             :    in two separate programs, and we must keep the two program
     119             :    summaries separate.  */
     120             : 
     121             : /*
     122             :  * ===  FUNCTION  ======================================================================
     123             :  *         Name:  gcov_exit
     124             :  *  Description:  This function dumps the coverage couns. The merging with
     125             :  *  existing counts is not done in embedded systems.
     126             :  * =====================================================================================
     127             :  */
     128          18 : void gcov_exit(void)
     129             : {
     130             :     struct gcov_info* gi_ptr;
     131             :     struct gcov_summary this_program;
     132             :     struct gcov_summary all;
     133             :     struct gcov_ctr_summary* cs_ptr;
     134             :     const struct gcov_ctr_info* ci_ptr;
     135             :     unsigned t_ix;
     136             :     gcov_unsigned_t c_num;
     137          18 :     unsigned long coreId = 0;
     138             : 
     139             : /* retrieve the id of the CPU the program is running on */
     140             : #ifdef LEON3
     141             :     __asm__ __volatile__(
     142             :         "rd     %%asr17,%0\n\t"
     143             :         "srl    %0,28,%0"
     144             :         : "=&r"(coreId)
     145             :         :);
     146             : #endif
     147             : 
     148          18 :     printf("_GCOVEXIT_BEGIN_,core%d\n", coreId); /* see also _GCOVEXIT_END_ */
     149             : 
     150          18 :     if (gcov_list == (void*)0x0)
     151           0 :         printf("%s: gcov_list == NULL\n", __func__);
     152             : 
     153          18 :     memset(&all, 0, sizeof(all));
     154             :     /* Find the totals for this execution.  */
     155          18 :     memset(&this_program, 0, sizeof(this_program));
     156         432 :     for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
     157             :     {
     158             : 
     159         414 :         ci_ptr = gi_ptr->counts;
     160         828 :         for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
     161             :         {
     162         414 :             if (!((1 << t_ix) & gi_ptr->ctr_mask))
     163           0 :                 continue;
     164             : 
     165         414 :             cs_ptr = &this_program.ctrs[t_ix];
     166         414 :             cs_ptr->num += ci_ptr->num;
     167       37638 :             for (c_num = 0; c_num < ci_ptr->num; c_num++)
     168             :             {
     169       37224 :                 cs_ptr->sum_all += ci_ptr->values[c_num];
     170       37224 :                 if (cs_ptr->run_max < ci_ptr->values[c_num])
     171         200 :                     cs_ptr->run_max = ci_ptr->values[c_num];
     172             :             }
     173         414 :             ci_ptr++;
     174             :         }
     175             :     }
     176             :     /* Now merge each file.  */
     177         396 :     for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
     178             :     {
     179             : 
     180             :         struct gcov_summary program;
     181             :         gcov_type* values[GCOV_COUNTERS];
     182             :         const struct gcov_fn_info* fi_ptr;
     183             :         unsigned fi_stride;
     184             :         unsigned c_ix, f_ix, n_counts;
     185             : 
     186         396 :         c_ix = 0;
     187        2376 :         for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
     188        1980 :             if ((1 << t_ix) & gi_ptr->ctr_mask)
     189             :             {
     190         396 :                 values[c_ix] = gi_ptr->counts[c_ix].values;
     191         396 :                 c_ix++;
     192             :             }
     193             : 
     194             :         /* Calculate the function_info stride. This depends on the
     195             :            number of counter types being measured.  */
     196         396 :         fi_stride = sizeof(struct gcov_fn_info) + c_ix * sizeof(unsigned);
     197             :         if (__alignof__(struct gcov_fn_info) > sizeof(unsigned))
     198             :         {
     199             :             fi_stride += __alignof__(struct gcov_fn_info) - 1;
     200             :             fi_stride &= ~(__alignof__(struct gcov_fn_info) - 1);
     201             :         }
     202             : 
     203         396 :         if (!gcov_open(gi_ptr->filename))
     204             :         {
     205           0 :             printf("profiling:%s:Cannot open\n", gi_ptr->filename);
     206           0 :             continue;
     207             :         }
     208             : 
     209         396 :         program.checksum = gcov_crc32;
     210             : 
     211             :         /* Write out the data.  */
     212         396 :         gcov_write_tag_length(GCOV_DATA_MAGIC, GCOV_VERSION);
     213         396 :         gcov_write_unsigned(gi_ptr->stamp);
     214             : 
     215             :         /* Write execution counts for each function.  */
     216        5580 :         for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
     217             :         {
     218        5202 :             fi_ptr
     219        5202 :                 = (const struct gcov_fn_info*)((const char*)gi_ptr->functions + f_ix * fi_stride);
     220             : 
     221             :             /* Announce function.  */
     222        5202 :             gcov_write_tag_length(GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH);
     223        5202 :             gcov_write_unsigned(fi_ptr->ident);
     224        5202 :             gcov_write_unsigned(fi_ptr->checksum);
     225             : 
     226        5202 :             c_ix = 0;
     227       31122 :             for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
     228             :             {
     229             :                 gcov_type* c_ptr;
     230             : 
     231       25938 :                 if (!((1 << t_ix) & gi_ptr->ctr_mask))
     232       20736 :                     continue;
     233             : 
     234        5202 :                 n_counts = fi_ptr->n_ctrs[c_ix];
     235             : 
     236        5202 :                 gcov_write_tag_length(
     237        5202 :                     GCOV_TAG_FOR_COUNTER(t_ix), GCOV_TAG_COUNTER_LENGTH(n_counts));
     238        5202 :                 c_ptr = values[c_ix];
     239       46998 :                 while (n_counts--)
     240       36612 :                     gcov_write_counter(*c_ptr++);
     241             : 
     242        5184 :                 values[c_ix] = c_ptr;
     243        5184 :                 c_ix++;
     244             :             }
     245             :         }
     246             : 
     247         378 :         gcov_send();
     248         378 :         gcov_close();
     249             :     }
     250             : 
     251           0 :     printf("_GCOVEXIT_END_,core%d\n", coreId);
     252           0 : }
     253             : 
     254             : 
     255             : /* Called before fork or exec - write out profile information gathered so
     256             :    far and reset it to zero.  This avoids duplication or loss of the
     257             :    profile information gathered so far.  */
     258             : 
     259           0 : void __gcov_flush(void)
     260             : {
     261             :     const struct gcov_info* gi_ptr;
     262             : 
     263           0 :     gcov_exit();
     264           0 :     for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
     265             :     {
     266             :         unsigned t_ix;
     267             :         const struct gcov_ctr_info* ci_ptr;
     268             : 
     269           0 :         for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
     270           0 :             if ((1 << t_ix) & gi_ptr->ctr_mask)
     271             :             {
     272           0 :                 memset(ci_ptr->values, 0, sizeof(gcov_type) * ci_ptr->num);
     273           0 :                 ci_ptr++;
     274             :             }
     275             :     }
     276           0 : }
     277             : 
     278             : 
     279             : /* Open a gcov file. NAME is the name of the file to open and MODE
     280             :    indicates whether a new file should be created, or an existing file
     281             :    opened for modification. If MODE is >= 0 an existing file will be
     282             :    opened, if possible, and if MODE is <= 0, a new file will be
     283             :    created. Use MODE=0 to attempt to reopen an existing file and then
     284             :    fall back on creating a new one.  Return zero on failure, >0 on
     285             :    opening an existing file and <0 on creating a new one.  */
     286         396 : GCOV_LINKAGE int gcov_open(const char* name)
     287             : {
     288             :     //  gcov_var.start is cleared in the gcov_close function.
     289             :     //  If this variable is not cleared...ERROR
     290         396 :     if (gcov_var.start != 0)
     291           0 :         return 0;
     292             : 
     293             :     // Clear everything
     294         396 :     gcov_var.start = 0;
     295         396 :     gcov_var.offset = gcov_var.length = 0;
     296         396 :     gcov_var.overread = -1u;
     297         396 :     gcov_var.error = 0;
     298             : 
     299             : 
     300             :     // copy the filename in the gcov_var structure
     301         396 :     strcpy(gcov_var.filename, name);
     302             : 
     303             : 
     304             :     // return 1 means everything is OK
     305         396 :     return 1;
     306             : }
     307             : 
     308             : /* Close the current gcov file. Flushes data to disk. Returns nonzero
     309             :    on failure or error flag set.  */
     310             : 
     311         378 : GCOV_LINKAGE int gcov_send(void)
     312             : {
     313             :     /*printf("%s: file %s\n", __func__, gcov_var.filename);*/
     314         378 :     if (gcov_var.offset)
     315         378 :         gcov_write_block(gcov_var.offset);
     316             : 
     317         378 :     gcov_var.length = 0;
     318         378 :     return gcov_var.error;
     319             : }
     320             : 
     321         378 : GCOV_LINKAGE int gcov_close(void)
     322             : {
     323         378 :     memset(gcov_var.filename, 0, strlen(gcov_var.filename));
     324             : 
     325             :     //  Clear the start variable because will be tested in the gcov_open
     326             :     //  function
     327         378 :     gcov_var.start = 0;
     328             : 
     329             :     //  Return the error, not sure whether the error is modifed.
     330         378 :     return gcov_var.error;
     331             : }
     332             : 
     333             : 
     334         378 : static void gcov_write_block(unsigned size)
     335             : {
     336         378 :     unsigned char* buffer = (unsigned char*)gcov_var.buffer;
     337             :     unsigned int i;
     338             : 
     339         378 :     printf("_GCOV_,%s,", gcov_var.filename);
     340             :     /* to speed up the printing process, we display bytes 4 by 4 */
     341      102456 :     for (i = 0; i < size; i++)
     342             :     {
     343      306234 :         printf("%02X%02X%02X%02X", (unsigned int)(buffer[0]), (unsigned int)(buffer[1]),
     344      204156 :             (unsigned int)(buffer[2]), (unsigned int)(buffer[3]));
     345             : 
     346      102078 :         buffer += sizeof(gcov_unsigned_t);
     347             :     }
     348         378 :     printf("\n");
     349             : 
     350         378 :     gcov_var.start += size;
     351         378 :     gcov_var.offset -= size;
     352         378 : }
     353             : 
     354             : /* Allocate space to write BYTES bytes to the gcov file. Return a
     355             :    pointer to those bytes, or NULL on failure.  */
     356             : 
     357       56862 : static gcov_unsigned_t* gcov_write_words(unsigned words)
     358             : {
     359             :     gcov_unsigned_t* result;
     360             : 
     361             :     GCOV_CHECK_WRITING();
     362       56862 :     if (gcov_var.offset >= GCOV_BLOCK_SIZE)
     363             :     {
     364           0 :         gcov_write_block(GCOV_BLOCK_SIZE);
     365           0 :         if (gcov_var.offset)
     366             :         {
     367             :             GCOV_CHECK(gcov_var.offset == 1);
     368           0 :             memcpy(gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4);
     369             :         }
     370             :     }
     371       56862 :     result = &gcov_var.buffer[gcov_var.offset];
     372       56862 :     gcov_var.offset += words;
     373             : 
     374       56862 :     return result;
     375             : }
     376             : 
     377             : /* Write unsigned VALUE to coverage file.  Sets error flag
     378             :    appropriately.  */
     379             : 
     380       10620 : GCOV_LINKAGE void gcov_write_unsigned(gcov_unsigned_t value)
     381             : {
     382       10620 :     gcov_unsigned_t* buffer = gcov_write_words(1);
     383             : 
     384       10620 :     buffer[0] = value;
     385       10620 : }
     386             : 
     387             : /* Write counter VALUE to coverage file.  Sets error flag
     388             :    appropriately.  */
     389             : 
     390       35946 : GCOV_LINKAGE void gcov_write_counter(gcov_type value)
     391             : {
     392       35946 :     gcov_unsigned_t* buffer = gcov_write_words(2);
     393             : 
     394       35964 :     buffer[0] = (gcov_unsigned_t)value;
     395             :     if (sizeof(value) > sizeof(gcov_unsigned_t))
     396       35964 :         buffer[1] = (gcov_unsigned_t)(value >> 32);
     397             :     else
     398             :         buffer[1] = 0;
     399       35964 : }
     400             : 
     401             : /* Write a tag TAG and length LENGTH.  */
     402             : 
     403       10548 : GCOV_LINKAGE void gcov_write_tag_length(gcov_unsigned_t tag, gcov_unsigned_t length)
     404             : {
     405       10548 :     gcov_unsigned_t* buffer = gcov_write_words(2);
     406             : 
     407       10548 :     buffer[0] = tag;
     408       10548 :     buffer[1] = length;
     409       10548 : }
     410             : 
     411             : /* Write a summary structure to the gcov file.  Return nonzero on
     412             :    overflow.  */
     413             : 
     414           0 : GCOV_LINKAGE void gcov_write_summary(gcov_unsigned_t tag, const struct gcov_summary* summary)
     415             : {
     416             :     unsigned ix;
     417             :     const struct gcov_ctr_summary* csum;
     418             : 
     419           0 :     gcov_write_tag_length(tag, GCOV_TAG_SUMMARY_LENGTH);
     420           0 :     gcov_write_unsigned(summary->checksum);
     421           0 :     for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++)
     422             :     {
     423           0 :         gcov_write_unsigned(csum->num);
     424           0 :         gcov_write_unsigned(csum->runs);
     425           0 :         gcov_write_counter(csum->sum_all);
     426           0 :         gcov_write_counter(csum->run_max);
     427           0 :         gcov_write_counter(csum->sum_max);
     428             :     }
     429           0 : }
     430             : 
     431           0 : GCOV_LINKAGE gcov_type gcov_read_counter(void)
     432             : {
     433           0 :     return 0;
     434             : }
     435             : 
     436             : /* Add a new object file onto the bb chain.  Invoked automatically
     437             :    when running an object file's global ctors.  */
     438             : 
     439         414 : void __gcov_init(struct gcov_info* info)
     440             : {
     441         414 :     if (!info->version)
     442             :         return;
     443         828 :     if (gcov_version(info, info->version))
     444             :     {
     445         414 :         const char* ptr = info->filename;
     446         414 :         gcov_unsigned_t crc32 = gcov_crc32;
     447             : 
     448             :         /* Added by LESIA*/
     449         414 :         printf("Covered file: %s\n", info->filename);
     450             :         /* End of Added by LESIA*/
     451             : 
     452             :         do
     453             :         {
     454             :             unsigned ix;
     455       33606 :             gcov_unsigned_t value = *ptr << 24;
     456             : 
     457      302454 :             for (ix = 8; ix--; value <<= 1)
     458             :             {
     459             :                 gcov_unsigned_t feedback;
     460             : 
     461      268848 :                 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
     462      268848 :                 crc32 <<= 1;
     463      268848 :                 crc32 ^= feedback;
     464             :             }
     465       33606 :         } while (*ptr++);
     466             : 
     467         414 :         gcov_crc32 = crc32;
     468             : 
     469             : #ifdef GCOV_USE_EXIT
     470         414 :         if (!gcov_list)
     471          18 :             atexit(gcov_exit);
     472             : #endif
     473             : 
     474         414 :         info->next = gcov_list;
     475         414 :         gcov_list = info;
     476             :     }
     477             :     else
     478           0 :         printf("%s: Version mismatch\n", "WARNING");
     479         414 :     info->version = 0;
     480             : }
     481             : //#endif /* __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__ */

Generated by: LCOV version 1.14