LCOV - code coverage report
Current view: top level - subsys/testsuite/coverage - coverage.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 88 101 87.1 %
Date: 2022-08-18 11:36:24 Functions: 8 10 80.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 26 30 86.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2018 Intel Corporation
       3                 :            :  *
       4                 :            :  * SPDX-License-Identifier: Apache-2.0
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <zephyr.h>
       8                 :            : #include <stdio.h>
       9                 :            : #include <stdint.h>
      10                 :            : #include <errno.h>
      11                 :            : #include "coverage.h"
      12                 :            : 
      13                 :            : 
      14                 :            : #if defined(CONFIG_X86) || defined(CONFIG_SOC_SERIES_MPS2)
      15                 :            : #define MALLOC_MAX_HEAP_SIZE 32768
      16                 :            : #define MALLOC_MIN_BLOCK_SIZE 128
      17                 :            : #else
      18                 :            : #define MALLOC_MAX_HEAP_SIZE 16384
      19                 :            : #define MALLOC_MIN_BLOCK_SIZE 64
      20                 :            : #endif
      21                 :            : 
      22                 :            : 
      23                 :            : //K_HEAP_DEFINE(gcov_heap, MALLOC_MAX_HEAP_SIZE);
      24                 :            : K_HEAP_DEFINE(gcov_heap, 32768);
      25                 :            : 
      26                 :            : static struct gcov_info *gcov_info_head;
      27                 :            : 
      28                 :            : /**
      29                 :            :  * Is called by gcc-generated constructor code for each object file compiled
      30                 :            :  * with -fprofile-arcs.
      31                 :            :  */
      32                 :        212 : void __gcov_init(struct gcov_info *info)
      33                 :            : {
      34                 :        212 :         info->next = gcov_info_head;
      35                 :        212 :         gcov_info_head = info;
      36                 :        212 : }
      37                 :            : 
      38                 :          0 : void __gcov_merge_add(gcov_type *counters, unsigned int n_counters)
      39                 :            : {
      40                 :            :         /* Unused. */
      41                 :          0 : }
      42                 :            : 
      43                 :          0 : void __gcov_exit(void)
      44                 :            : {
      45                 :            :         /* Unused. */
      46                 :          0 : }
      47                 :            : 
      48                 :            : /**
      49                 :            :  * buff_write_u64 - Store 64 bit data on a buffer and return the size
      50                 :            :  */
      51                 :            : 
      52                 :            : #define MASK_32BIT (0xffffffffUL)
      53                 :       5995 : static inline void buff_write_u64(void *buffer, size_t *off, uint64_t v)
      54                 :            : {
      55                 :       5995 :         *((uint32_t *)((uint8_t *)buffer + *off) + 0) = (uint32_t)(v & MASK_32BIT);
      56                 :       5995 :         *((uint32_t *)((uint8_t *)buffer + *off) + 1) = (uint32_t)((v >> 32) &
      57                 :            :                                                           MASK_32BIT);
      58                 :       5995 :         *off = *off + sizeof(uint64_t);
      59                 :       5995 : }
      60                 :            : 
      61                 :            : /**
      62                 :            :  * buff_write_u32 - Store 32 bit data on a buffer and return the size
      63                 :            :  */
      64                 :      10690 : static inline void buff_write_u32(void *buffer, size_t *off, uint32_t v)
      65                 :            : {
      66                 :      10690 :         *((uint32_t *)((uint8_t *)buffer + *off)) = v;
      67                 :      10690 :         *off = *off + sizeof(uint32_t);
      68                 :      10690 : }
      69                 :            : 
      70                 :            : 
      71                 :         68 : size_t calculate_buff_size(struct gcov_info *info)
      72                 :            : {
      73                 :            :         uint32_t iter;
      74                 :            :         uint32_t iter_1;
      75                 :            :         uint32_t iter_2;
      76                 :            :         /* few Fixed values at the start version, stamp and magic number. */
      77                 :         68 :         uint32_t size = sizeof(uint32_t) * 3;
      78                 :            : 
      79         [ +  + ]:       1570 :         for (iter = 0U; iter < info->n_functions; iter++) {
      80                 :            :                 /* space for TAG_FUNCTION and FUNCTION_LENGTH
      81                 :            :                  * ident
      82                 :            :                  * lineno_checksum
      83                 :            :                  * cfg_checksum
      84                 :            :                  */
      85                 :       1502 :                 size += (sizeof(uint32_t) * 5);
      86                 :            : 
      87         [ +  + ]:      13518 :                 for (iter_1 = 0U; iter_1 < GCOV_COUNTERS; iter_1++) {
      88         [ +  + ]:      12016 :                         if (!info->merge[iter_1]) {
      89                 :      10514 :                                 continue;
      90                 :            :                         }
      91                 :            : 
      92                 :            :                         /*  for function counter and number of values  */
      93                 :       1502 :                         size += (sizeof(uint32_t) * 2);
      94                 :            : 
      95                 :       1502 :                         for (iter_2 = 0U;
      96         [ +  + ]:       7501 :                              iter_2 < info->functions[iter]->ctrs->num;
      97                 :       5999 :                              iter_2++) {
      98                 :            : 
      99                 :            :                                 /* Iter for values which is uint64_t */
     100                 :       5999 :                                 size += (sizeof(uint64_t));
     101                 :            :                         }
     102                 :            : 
     103                 :            :                 }
     104                 :            : 
     105                 :            : 
     106                 :            :         }
     107                 :            : 
     108                 :         68 :         return size;
     109                 :            : }
     110                 :            : 
     111                 :            : 
     112                 :            : /**
     113                 :            :  * populate_buffer - convert from gcov data set (info) to
     114                 :            :  * .gcda file format.
     115                 :            :  * This buffer will now have info similar to a regular gcda
     116                 :            :  * format.
     117                 :            :  */
     118                 :         68 : size_t populate_buffer(uint8_t *buffer, struct gcov_info *info)
     119                 :            : {
     120                 :            :         struct gcov_fn_info *functions;
     121                 :            :         struct gcov_ctr_info *counters_per_func;
     122                 :            :         uint32_t iter_functions;
     123                 :            :         uint32_t iter_counts;
     124                 :            :         uint32_t iter_counter_values;
     125                 :         68 :         size_t buffer_write_position = 0;
     126                 :            : 
     127                 :            :         /* File header. */
     128                 :         68 :         buff_write_u32(buffer,
     129                 :            :                        &buffer_write_position,
     130                 :            :                        GCOV_DATA_MAGIC);
     131                 :            : 
     132                 :         68 :         buff_write_u32(buffer,
     133                 :            :                        &buffer_write_position,
     134                 :            :                        info->version);
     135                 :            : 
     136                 :         68 :         buff_write_u32(buffer,
     137                 :            :                        &buffer_write_position,
     138                 :            :                        info->stamp);
     139                 :            : 
     140                 :         68 :         for (iter_functions = 0U;
     141         [ +  + ]:       1563 :              iter_functions < info->n_functions;
     142                 :       1495 :              iter_functions++) {
     143                 :            : 
     144                 :       1496 :                 functions = info->functions[iter_functions];
     145                 :            : 
     146                 :            : 
     147                 :       1496 :                 buff_write_u32(buffer,
     148                 :            :                                &buffer_write_position,
     149                 :            :                                GCOV_TAG_FUNCTION);
     150                 :            : 
     151                 :       1496 :                 buff_write_u32(buffer,
     152                 :            :                                &buffer_write_position,
     153                 :            :                                GCOV_TAG_FUNCTION_LENGTH);
     154                 :            : 
     155                 :       1496 :                 buff_write_u32(buffer,
     156                 :            :                                &buffer_write_position,
     157                 :            :                                functions->ident);
     158                 :            : 
     159                 :       1496 :                 buff_write_u32(buffer,
     160                 :            :                                &buffer_write_position,
     161                 :            :                                functions->lineno_checksum);
     162                 :            : 
     163                 :       1496 :                 buff_write_u32(buffer,
     164                 :            :                                &buffer_write_position,
     165                 :            :                                functions->cfg_checksum);
     166                 :            : 
     167                 :       1496 :                 counters_per_func = functions->ctrs;
     168                 :            : 
     169         [ +  + ]:      13456 :                 for (iter_counts = 0U;
     170                 :            :                      iter_counts < GCOV_COUNTERS;
     171                 :      11960 :                      iter_counts++) {
     172                 :            : 
     173         [ +  + ]:      11961 :                         if (!info->merge[iter_counts]) {
     174                 :      10465 :                                 continue;
     175                 :            :                         }
     176                 :            : 
     177                 :       1496 :                         buff_write_u32(buffer,
     178                 :            :                                        &buffer_write_position,
     179                 :       1496 :                                        GCOV_TAG_FOR_COUNTER(iter_counts));
     180                 :            : 
     181                 :       1496 :                         buff_write_u32(buffer,
     182                 :            :                                        &buffer_write_position,
     183                 :       1496 :                                        counters_per_func->num * 2U);
     184                 :            : 
     185                 :       1497 :                         for (iter_counter_values = 0U;
     186         [ +  + ]:       7480 :                              iter_counter_values < counters_per_func->num;
     187                 :       5983 :                              iter_counter_values++) {
     188                 :            : 
     189                 :       5985 :                                 buff_write_u64(buffer,
     190                 :            :                                                &buffer_write_position,
     191                 :       5985 :                                                counters_per_func->\
     192                 :       5985 :                                                values[iter_counter_values]);
     193                 :            :                         }
     194                 :            : 
     195                 :       1495 :                         counters_per_func++;
     196                 :            :                 }
     197                 :            :         }
     198                 :         67 :         return buffer_write_position;
     199                 :            : }
     200                 :            : 
     201                 :         67 : void dump_on_console(const char *filename, char *ptr, size_t len)
     202                 :            : {
     203                 :            :         uint32_t iter;
     204                 :            : 
     205                 :         67 :         printk("\n%c", FILE_START_INDICATOR);
     206         [ +  + ]:      11511 :         while (*filename != '\0') {
     207                 :      11444 :                 printk("%c", *filename++);
     208                 :            :         }
     209                 :         67 :         printk("%c", GCOV_DUMP_SEPARATOR);
     210                 :            : 
     211                 :            :         /* Data dump */
     212                 :            : 
     213         [ +  + ]:      90223 :         for (iter = 0U; iter < len; iter++) {
     214                 :      90156 :                 printk(" %02x", (uint8_t)*ptr++);
     215                 :            :         }
     216                 :         67 : }
     217                 :            : 
     218                 :            : /**
     219                 :            :  * Retrieves gcov coverage data and sends it over the given interface.
     220                 :            :  */
     221                 :          1 : void gcov_coverage_dump(void)
     222                 :            : {
     223                 :            :         uint8_t *buffer;
     224                 :            :         size_t size;
     225                 :            :         size_t written_size;
     226                 :          1 :         struct gcov_info *gcov_list_first = gcov_info_head;
     227                 :          1 :         struct gcov_info *gcov_list = gcov_info_head;
     228                 :            : 
     229                 :          1 :         k_sched_lock();
     230                 :          1 :         printk("\nGCOV_COVERAGE_DUMP_START");
     231         [ +  - ]:         68 :         while (gcov_list) {
     232                 :            : 
     233                 :         68 :                 size = calculate_buff_size(gcov_list);
     234                 :            : 
     235                 :         68 :                 buffer = k_heap_alloc(&gcov_heap, size, K_NO_WAIT);
     236         [ -  + ]:         68 :                 if (!buffer) {
     237                 :          0 :                         printk("No Mem available to continue dump\n");
     238                 :          0 :                         goto coverage_dump_end;
     239                 :            :                 }
     240                 :            : 
     241                 :         68 :                 written_size = populate_buffer(buffer, gcov_list);
     242         [ -  + ]:         67 :                 if (written_size != size) {
     243                 :          0 :                         printk("Write Error on buff\n");
     244                 :          0 :                         goto coverage_dump_end;
     245                 :            :                 }
     246                 :            : 
     247                 :         67 :                 dump_on_console(gcov_list->filename, buffer, size);
     248                 :            : 
     249                 :         67 :                 k_heap_free(&gcov_heap, buffer);
     250                 :         67 :                 gcov_list = gcov_list->next;
     251         [ -  + ]:         67 :                 if (gcov_list_first == gcov_list) {
     252                 :          0 :                         goto coverage_dump_end;
     253                 :            :                 }
     254                 :            :         }
     255                 :          0 : coverage_dump_end:
     256                 :          0 :         printk("\nGCOV_COVERAGE_DUMP_END\n");
     257                 :          0 :         k_sched_unlock();
     258                 :          0 :         return;
     259                 :            : }
     260                 :            : 
     261                 :            : 
     262                 :            : /* Initialize the gcov by calling the required constructors */
     263                 :          1 : void gcov_static_init(void)
     264                 :            : {
     265                 :            :         extern uintptr_t __init_array_start, __init_array_end;
     266                 :          1 :         uintptr_t func_pointer_start = (uintptr_t) &__init_array_start;
     267                 :          1 :         uintptr_t func_pointer_end = (uintptr_t) &__init_array_end;
     268                 :            : 
     269         [ +  + ]:        107 :         while (func_pointer_start < func_pointer_end) {
     270                 :            :                 void (**p)(void);
     271                 :            :                 /* get function pointer */
     272                 :        106 :                 p = (void (**)(void)) func_pointer_start;
     273                 :        106 :                 (*p)();
     274                 :        106 :                 func_pointer_start += sizeof(p);
     275                 :            :         }
     276                 :          1 : }

Generated by: LCOV version 1.14