1 /**
2  * \file gcov_support.h
3  * \brief Support helpers to use gcov for embedded targets.
4  * \author Erich Styger
5  * \copyright
6  * Web:         https://mcuoneclipse.com
7  * SourceForge: https://sourceforge.net/projects/mcuoneclipse
8  * Git:         https://github.com/ErichStyger/McuOnEclipse_PEx
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification,
12  * are permitted provided that the following conditions are met:
13  *
14  * - Redistributions of source code must retain the above copyright notice, this list
15  *   of conditions and the following disclaimer.
16  *
17  * - Redistributions in binary form must reproduce the above copyright notice, this
18  *   list of conditions and the following disclaimer in the documentation and/or
19  *   other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  * ###################################################################*/
32 
33 #include <stdint.h>
34 #include <stdio.h>
35 #include "gcov_support.h"
36 
37 #if GCOV_USE_TCOV
38 #include "tcov.h"
39 #endif
40 
41 /* If MCUXPresso IDE was selected, enable the gcov function. */
42 #if defined(__GNUC__) && !(defined(__CC_ARM) || defined(__ARMCC_VERSION)) && !(defined(__XCC__))
43 void __gcov_flush(void); /* internal gcov function to write data */
44 
gcov_check(void)45 int gcov_check(void)
46 {
47 #if GCOV_DO_COVERAGE && defined(__MCUXPRESSO)
48     FILE *file = NULL;
49 
50     file = fopen("c:\\tmp\\test.txt", "w");
51     if (file != NULL)
52     {
53         fputs("hello world with file I/O\r\n", file);
54         (void)fwrite("hello\r\n", sizeof("hello\r\n") - 1, 1, file);
55         fclose(file);
56         return 1; /* ok */
57     }
58     return 0; /* failed */
59 #else
60     return 1; /* ok */
61 #endif
62 }
63 
gcov_write(void)64 void gcov_write(void)
65 {
66 #if GCOV_USE_TCOV
67     tcov_print_all(); /* print coverage information */
68 #elif GCOV_USE_GCOV_EMBEDDED
69     void gcov_exit(void);
70 
71     gcov_exit();
72 #elif GCOV_DO_COVERAGE
73     __gcov_flush();
74 #endif
75 }
76 
77 /* call the coverage initializers if not done by startup code */
gcov_init(void)78 void gcov_init(void)
79 {
80 #if GCOV_DO_COVERAGE && defined(__MCUXPRESSO)
81     void (**p)(void);
82     extern uint32_t __init_array_start, __init_array_end; /* linker defined symbols, array of function pointers */
83     uint32_t beg = (uint32_t)&__init_array_start;
84     uint32_t end = (uint32_t)&__init_array_end;
85 
86     while (beg < end)
87     {
88         p = (void (**)(void))beg; /* get function pointer */
89         (*p)();                   /* call constructor */
90         beg += sizeof(p);         /* next pointer */
91     }
92 #endif /* GCOV_DO_COVERAGE */
93 }
94 
95 #if 0 && GCOV_USE_GCOV_EMBEDDED
96 
97 #include <stdio.h>
98 #include <stdlib.h>
99 #include "libgcov.h"
100 
101 typedef struct tagGcovInfo {
102     struct gcov_info *info;
103     struct tagGcovInfo *next;
104 } GcovInfo;
105 static GcovInfo *headGcov = NULL;
106 
107 void exit(int i) {
108   for(;;)  {}
109 }
110 
111 /*
112  * __gcov_init is called by gcc-generated constructor code for each object
113  * file compiled with -fprofile-arcs.
114  */
115 void __gcov_init(struct gcov_info *info)
116 {
117     //printf("__gcov_init called for %s!\n", gcov_info_filename(info));
118     //fflush(stdout);
119     GcovInfo *newHead = malloc(sizeof(GcovInfo));
120     if (!newHead) {
121         puts("Out of memory error!");
122         exit(1);
123     }
124     newHead->info = info;
125     newHead->next = headGcov;
126     headGcov = newHead;
127 }
128 
129 void __gcov_merge_add(gcov_type *counters, unsigned int n_counters) {
130   puts("__gcov_merge_add isn't called, right? Right? RIGHT?");
131   fflush(stdout);
132   exit(1);
133 }
134 
135 #endif /* GCOV_USE_GCOV_EMBEDDED */
136 
137 #endif /* MCUXPresso IDE used. */
138