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:17 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          23 :     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          23 :     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           1 : 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           1 :     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           1 :     printf("_GCOVEXIT_BEGIN_,core%d\n", coreId); /* see also _GCOVEXIT_END_ */
     149             : 
     150           1 :     if (gcov_list == (void*)0x0)
     151           0 :         printf("%s: gcov_list == NULL\n", __func__);
     152             : 
     153           1 :     memset(&all, 0, sizeof(all));
     154             :     /* Find the totals for this execution.  */
     155           1 :     memset(&this_program, 0, sizeof(this_program));
     156          24 :     for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
     157             :     {
     158             : 
     159          23 :         ci_ptr = gi_ptr->counts;
     160          46 :         for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
     161             :         {
     162          23 :             if (!((1 << t_ix) & gi_ptr->ctr_mask))
     163           0 :                 continue;
     164             : 
     165          23 :             cs_ptr = &this_program.ctrs[t_ix];
     166          23 :             cs_ptr->num += ci_ptr->num;
     167        2091 :             for (c_num = 0; c_num < ci_ptr->num; c_num++)
     168             :             {
     169        2068 :                 cs_ptr->sum_all += ci_ptr->values[c_num];
     170        2068 :                 if (cs_ptr->run_max < ci_ptr->values[c_num])
     171          12 :                     cs_ptr->run_max = ci_ptr->values[c_num];
     172             :             }
     173          23 :             ci_ptr++;
     174             :         }
     175             :     }
     176             :     /* Now merge each file.  */
     177          22 :     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          22 :         c_ix = 0;
     187         132 :         for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
     188         110 :             if ((1 << t_ix) & gi_ptr->ctr_mask)
     189             :             {
     190          22 :                 values[c_ix] = gi_ptr->counts[c_ix].values;
     191          22 :                 c_ix++;
     192             :             }
     193             : 
     194             :         /* Calculate the function_info stride. This depends on the
     195             :            number of counter types being measured.  */
     196          22 :         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          22 :         if (!gcov_open(gi_ptr->filename))
     204             :         {
     205           0 :             printf("profiling:%s:Cannot open\n", gi_ptr->filename);
     206           0 :             continue;
     207             :         }
     208             : 
     209          22 :         program.checksum = gcov_crc32;
     210             : 
     211             :         /* Write out the data.  */
     212          22 :         gcov_write_tag_length(GCOV_DATA_MAGIC, GCOV_VERSION);
     213          22 :         gcov_write_unsigned(gi_ptr->stamp);
     214             : 
     215             :         /* Write execution counts for each function.  */
     216         310 :         for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
     217             :         {
     218         289 :             fi_ptr
     219         289 :                 = (const struct gcov_fn_info*)((const char*)gi_ptr->functions + f_ix * fi_stride);
     220             : 
     221             :             /* Announce function.  */
     222         289 :             gcov_write_tag_length(GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH);
     223         289 :             gcov_write_unsigned(fi_ptr->ident);
     224         289 :             gcov_write_unsigned(fi_ptr->checksum);
     225             : 
     226         289 :             c_ix = 0;
     227        1729 :             for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
     228             :             {
     229             :                 gcov_type* c_ptr;
     230             : 
     231        1441 :                 if (!((1 << t_ix) & gi_ptr->ctr_mask))
     232        1152 :                     continue;
     233             : 
     234         289 :                 n_counts = fi_ptr->n_ctrs[c_ix];
     235             : 
     236         289 :                 gcov_write_tag_length(
     237         289 :                     GCOV_TAG_FOR_COUNTER(t_ix), GCOV_TAG_COUNTER_LENGTH(n_counts));
     238         289 :                 c_ptr = values[c_ix];
     239        2611 :                 while (n_counts--)
     240        2034 :                     gcov_write_counter(*c_ptr++);
     241             : 
     242         288 :                 values[c_ix] = c_ptr;
     243         288 :                 c_ix++;
     244             :             }
     245             :         }
     246             : 
     247          21 :         gcov_send();
     248          21 :         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          22 : 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          22 :     if (gcov_var.start != 0)
     291           0 :         return 0;
     292             : 
     293             :     // Clear everything
     294          22 :     gcov_var.start = 0;
     295          22 :     gcov_var.offset = gcov_var.length = 0;
     296          22 :     gcov_var.overread = -1u;
     297          22 :     gcov_var.error = 0;
     298             : 
     299             : 
     300             :     // copy the filename in the gcov_var structure
     301          22 :     strcpy(gcov_var.filename, name);
     302             : 
     303             : 
     304             :     // return 1 means everything is OK
     305          22 :     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          21 : GCOV_LINKAGE int gcov_send(void)
     312             : {
     313             :     /*printf("%s: file %s\n", __func__, gcov_var.filename);*/
     314          21 :     if (gcov_var.offset)
     315          21 :         gcov_write_block(gcov_var.offset);
     316             : 
     317          21 :     gcov_var.length = 0;
     318          21 :     return gcov_var.error;
     319             : }
     320             : 
     321          21 : GCOV_LINKAGE int gcov_close(void)
     322             : {
     323          21 :     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          21 :     gcov_var.start = 0;
     328             : 
     329             :     //  Return the error, not sure whether the error is modifed.
     330          21 :     return gcov_var.error;
     331             : }
     332             : 
     333             : 
     334          21 : static void gcov_write_block(unsigned size)
     335             : {
     336          21 :     unsigned char* buffer = (unsigned char*)gcov_var.buffer;
     337             :     unsigned int i;
     338             : 
     339          21 :     printf("_GCOV_,%s,", gcov_var.filename);
     340             :     /* to speed up the printing process, we display bytes 4 by 4 */
     341        5692 :     for (i = 0; i < size; i++)
     342             :     {
     343       17013 :         printf("%02X%02X%02X%02X", (unsigned int)(buffer[0]), (unsigned int)(buffer[1]),
     344       11342 :             (unsigned int)(buffer[2]), (unsigned int)(buffer[3]));
     345             : 
     346        5671 :         buffer += sizeof(gcov_unsigned_t);
     347             :     }
     348          21 :     printf("\n");
     349             : 
     350          21 :     gcov_var.start += size;
     351          21 :     gcov_var.offset -= size;
     352          21 : }
     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        3159 : static gcov_unsigned_t* gcov_write_words(unsigned words)
     358             : {
     359             :     gcov_unsigned_t* result;
     360             : 
     361             :     GCOV_CHECK_WRITING();
     362        3159 :     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        3159 :     result = &gcov_var.buffer[gcov_var.offset];
     372        3159 :     gcov_var.offset += words;
     373             : 
     374        3159 :     return result;
     375             : }
     376             : 
     377             : /* Write unsigned VALUE to coverage file.  Sets error flag
     378             :    appropriately.  */
     379             : 
     380         590 : GCOV_LINKAGE void gcov_write_unsigned(gcov_unsigned_t value)
     381             : {
     382         590 :     gcov_unsigned_t* buffer = gcov_write_words(1);
     383             : 
     384         590 :     buffer[0] = value;
     385         590 : }
     386             : 
     387             : /* Write counter VALUE to coverage file.  Sets error flag
     388             :    appropriately.  */
     389             : 
     390        1997 : GCOV_LINKAGE void gcov_write_counter(gcov_type value)
     391             : {
     392        1997 :     gcov_unsigned_t* buffer = gcov_write_words(2);
     393             : 
     394        1998 :     buffer[0] = (gcov_unsigned_t)value;
     395             :     if (sizeof(value) > sizeof(gcov_unsigned_t))
     396        1998 :         buffer[1] = (gcov_unsigned_t)(value >> 32);
     397             :     else
     398             :         buffer[1] = 0;
     399        1998 : }
     400             : 
     401             : /* Write a tag TAG and length LENGTH.  */
     402             : 
     403         586 : GCOV_LINKAGE void gcov_write_tag_length(gcov_unsigned_t tag, gcov_unsigned_t length)
     404             : {
     405         586 :     gcov_unsigned_t* buffer = gcov_write_words(2);
     406             : 
     407         586 :     buffer[0] = tag;
     408         586 :     buffer[1] = length;
     409         586 : }
     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          23 : void __gcov_init(struct gcov_info* info)
     440             : {
     441          23 :     if (!info->version)
     442             :         return;
     443          46 :     if (gcov_version(info, info->version))
     444             :     {
     445          23 :         const char* ptr = info->filename;
     446          23 :         gcov_unsigned_t crc32 = gcov_crc32;
     447             : 
     448             :         /* Added by LESIA*/
     449          23 :         printf("Covered file: %s\n", info->filename);
     450             :         /* End of Added by LESIA*/
     451             : 
     452             :         do
     453             :         {
     454             :             unsigned ix;
     455        1867 :             gcov_unsigned_t value = *ptr << 24;
     456             : 
     457       16803 :             for (ix = 8; ix--; value <<= 1)
     458             :             {
     459             :                 gcov_unsigned_t feedback;
     460             : 
     461       14936 :                 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
     462       14936 :                 crc32 <<= 1;
     463       14936 :                 crc32 ^= feedback;
     464             :             }
     465        1867 :         } while (*ptr++);
     466             : 
     467          23 :         gcov_crc32 = crc32;
     468             : 
     469             : #ifdef GCOV_USE_EXIT
     470          23 :         if (!gcov_list)
     471           1 :             atexit(gcov_exit);
     472             : #endif
     473             : 
     474          23 :         info->next = gcov_list;
     475          23 :         gcov_list = info;
     476             :     }
     477             :     else
     478           0 :         printf("%s: Version mismatch\n", "WARNING");
     479          23 :     info->version = 0;
     480             : }
     481             : //#endif /* __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__ */

Generated by: LCOV version 1.14