1 /*
2 * Debugger
3 *
4 * Copyright 1990-2009 Green Hills Software, Inc.
5 *
6 * This program is the property of Green Hills Software, Inc,
7 * its contents are proprietary information and no part of it
8 * is to be disclosed to anyone except employees of Green Hills
9 * Software, Inc., or as agreed in writing signed by the President
10 * of Green Hills Software, Inc.
11 */
12 /* ind_bcnt.c: compiler internal functions for Block Coverage Profiling. */
13
14 #if defined(EMBEDDED) || defined(__OSE)
15
16 #include "indos.h"
17 #include "ind_io.h"
18 #include "ind_exit.h"
19 #include "ind_thrd.h"
20
21 struct blk { void (*addr)(void); unsigned int cnt; };
22 struct bhdr { int len; struct blk *info; int inserted; struct bhdr *next; };
23 static struct bhdr *blocklisthead;
24
25 /* Macro for printing errors */
26 #define PERROR(msg) write(2, msg, sizeof(msg)-1);
27
28 /* File System I/O Calls to write the file to the host */
29 #if defined(__INTEGRITY) || defined(__INTEGRITY_SHARED_LIBS)
30 #define HOSTIO_CREAT hostio_creat
31 #define HOSTIO_WRITE write
32 #define HOSTIO_CLOSE close
33 #else
34 #define HOSTIO_CREAT __ghs_hostio_creat
35 #define HOSTIO_WRITE __ghs_hostio_write
36 #define HOSTIO_CLOSE __ghs_hostio_close
37 #endif
38
39 /**
40 * Clears the coverage information. This can be used as a command line
41 * procedure call from MULTI to make it possible to generate coverage
42 * information only for a specific interval in a run of a program.
43 * Stop the program, call __ghs_prof_clear_coverage(), run to another
44 * point, dump.
45 *
46 * The functions remain in the linked list so that any future block
47 * coverage data gathered within a function, such as a main loop,
48 * that is currently executing but that is not called again,
49 * will be output by __ghs_prof_dump_coverage.
50 *
51 */
__ghs_prof_clear_coverage(void)52 void __ghs_prof_clear_coverage(void)
53 {
54 int i;
55 struct bhdr *p, *next;
56
57 for (p = blocklisthead; p; p = next) {
58 next = p->next;
59 if (p->len > 0) {
60 /* Reset all counts to 0 except the last block's count. */
61 for (i = 0; i < p->len - 1; i++)
62 p->info[i].cnt = 0;
63 /* The last block's count can be either a special -1 marker or a
64 normal run count. */
65 if (p->info[p->len - 1].cnt != (unsigned int)-1)
66 p->info[p->len - 1].cnt = 0;
67 }
68 }
69 }
70
71 #define _0644 0x1a4 /* MISRA C does not allow octal constants */
72
73 /* This routine is global to allow it to be called from MULTI */
__ghs_prof_dump_coverage(void)74 void __ghs_prof_dump_coverage(void)
75 {
76 int fd;
77 struct bhdr *test;
78
79 /*
80 * Use hostio, since the file belongs on the host system, not
81 * the target system.
82 */
83 fd = HOSTIO_CREAT("bmon.out", _0644);
84
85 if (fd == -1) {
86 PERROR("bcount: could not create bmon.out\n");
87 return;
88 }
89 for (test = blocklisthead; test; test = test->next) {
90 int contains_nonzero_count = 0;
91 int i;
92 int cnt;
93 if (test->len > 0) {
94 for (i = 0; i < test->len - 1; i++) {
95 if (test->info[i].cnt != 0) {
96 contains_nonzero_count = 1;
97 break;
98 }
99 }
100 /* The last block can have either a special -1 marker count or a
101 normal run count. */
102 if (test->info[test->len - 1].cnt != 0 &&
103 test->info[test->len - 1].cnt != (unsigned int)-1)
104 contains_nonzero_count = 1;
105 }
106 /* Don't write out any block count data if no block in this function
107 has executed. This can happen if __ghs_prof_clear_coverage was run,
108 as from the MULTI command "profilemode clear". */
109 if(contains_nonzero_count == 0)
110 continue;
111 #if __PTR_BIT <= 32
112 cnt = sizeof(struct blk)*test->len;
113 if (HOSTIO_WRITE(fd, test->info, cnt) != cnt) {
114 PERROR("bcount: write failed for bmon.out\n");
115 HOSTIO_CLOSE(fd);
116 return;
117 }
118 #else /* __PTR_BIT */
119 cnt = sizeof(void *) + sizeof(int);
120 for( i=0; i<test->len; i++ ) {
121 /* only write the packed data */
122 if(HOSTIO_WRITE(fd, &(test->info[i]), cnt) != cnt ) {
123 PERROR("bcount: write failed for bmon.out\n");
124 HOSTIO_CLOSE(fd);
125 return;
126 }
127 }
128 #endif /* __PTR_BIT */
129 }
130 HOSTIO_CLOSE(fd);
131 }
132
__ghs_bcount(struct bhdr * routinfo,void (* routaddr)(void))133 void __ghs_bcount(struct bhdr *routinfo, void (*routaddr)(void))
134 {
135 __ghs_ProfileLock();
136 if (routinfo->inserted) {
137 __ghs_ProfileUnlock();
138 return;
139 }
140 if (!blocklisthead) {
141 static struct __GHS_AT_EXIT gae;
142 if (!gae.func) {
143 gae.func = __ghs_prof_dump_coverage;
144 __ghs_at_exit(&gae);
145 }
146 }
147
148 routinfo->inserted = 1;
149 routinfo->next = blocklisthead;
150 blocklisthead = routinfo;
151 __ghs_ProfileUnlock();
152 }
153
154 #endif /* defined(EMBEDDED) */
155