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