13 /* section layout (all little endian):
14 32bit offset to executable/so file name
18 64bit function start line
19 64bits end_line(28bits) / start_line(28bits) / flag=0xff(8bits)
24 executable/so file name \0
27 typedef struct tcov_line
{
30 unsigned long long count
;
33 typedef struct tcov_function
{
35 unsigned int first_line
;
41 typedef struct tcov_file
{
46 struct tcov_file
*next
;
49 static FILE *open_tcov_file (char *cov_filename
)
55 lock
.l_type
= F_WRLCK
;
56 lock
.l_whence
= SEEK_SET
;
58 lock
.l_len
= 0; /* Until EOF. */
59 lock
.l_pid
= getpid ();
61 fd
= open (cov_filename
, O_RDWR
| O_CREAT
, 0666);
66 while (fcntl (fd
, F_SETLKW
, &lock
) && errno
== EINTR
)
70 OVERLAPPED overlapped
= { 0 };
71 LockFileEx((HANDLE
)_get_osfhandle(fd
), LOCKFILE_EXCLUSIVE_LOCK
,
72 0, 1, 0, &overlapped
);
76 return fdopen (fd
, "r+");
79 static unsigned long long get_value(unsigned char *p
, int size
)
81 unsigned long long value
= 0;
85 value
= (value
<< 8) | *--p
;
89 static int sort_func (const void *p
, const void *q
)
91 const tcov_function
*pp
= (const tcov_function
*) p
;
92 const tcov_function
*pq
= (const tcov_function
*) q
;
94 return pp
->first_line
> pq
->first_line
? 1 :
95 pp
->first_line
< pq
->first_line
? -1 : 0;
98 static int sort_line (const void *p
, const void *q
)
100 const tcov_line
*pp
= (const tcov_line
*) p
;
101 const tcov_line
*pq
= (const tcov_line
*) q
;
103 return pp
->fline
> pq
->fline
? 1 :
104 pp
->fline
< pq
->fline
? -1 :
105 pp
->count
< pq
->count
? 1 :
106 pp
->count
> pq
->count
? -1 : 0;
109 /* sort to let inline functions work */
110 static tcov_file
*sort_test_coverage (unsigned char *p
)
113 unsigned char *start
= p
;
114 tcov_file
*file
= NULL
;
119 char *filename
= (char *)p
;
120 size_t len
= strlen (filename
);
124 if (strcmp (nfile
->filename
, filename
) == 0)
129 nfile
= malloc (sizeof(tcov_file
));
131 fprintf (stderr
, "Malloc error test_coverage\n");
134 nfile
->filename
= filename
;
142 tcov_file
*lfile
= file
;
152 char *function
= (char *)p
;
155 p
+= strlen (function
) + 1;
156 p
+= -(p
- start
) & 7;
157 for (i
= 0; i
< nfile
->n_func
; i
++) {
158 func
= &nfile
->func
[i
];
159 if (strcmp (func
->function
, function
) == 0)
162 if (i
== nfile
->n_func
) {
163 if (nfile
->n_func
>= nfile
->m_func
) {
164 nfile
->m_func
= nfile
->m_func
== 0 ? 4 : nfile
->m_func
* 2;
165 nfile
->func
= realloc (nfile
->func
,
167 sizeof (tcov_function
));
168 if (nfile
->func
== NULL
) {
169 fprintf (stderr
, "Realloc error test_coverage\n");
173 func
= &nfile
->func
[nfile
->n_func
++];
174 func
->function
= function
;
175 func
->first_line
= get_value (p
, 8);
183 unsigned long long val
;
185 if (func
->n_line
>= func
->m_line
) {
186 func
->m_line
= func
->m_line
== 0 ? 4 : func
->m_line
* 2;
187 func
->line
= realloc (func
->line
,
188 func
->m_line
* sizeof (tcov_line
));
189 if (func
->line
== NULL
) {
190 fprintf (stderr
, "Realloc error test_coverage\n");
194 line
= &func
->line
[func
->n_line
++];
195 val
= get_value (p
, 8);
196 line
->fline
= (val
>> 8) & 0xfffffffULL
;
197 line
->lline
= val
>> 36;
198 line
->count
= get_value (p
+ 8, 8);
207 qsort (nfile
->func
, nfile
->n_func
, sizeof (tcov_function
), sort_func
);
208 for (i
= 0; i
< nfile
->n_func
; i
++) {
209 tcov_function
*func
= &nfile
->func
[i
];
210 qsort (func
->line
, func
->n_line
, sizeof (tcov_line
), sort_line
);
217 /* merge with previous tcov file */
218 static void merge_test_coverage (tcov_file
*file
, FILE *fp
,
228 if (fgets(str
, sizeof(str
), fp
) &&
229 (p
= strrchr (str
, ':')) &&
230 (sscanf (p
+ 1, "%u", &runs
) == 1))
234 size_t len
= strlen (file
->filename
);
236 while (fgets(str
, sizeof(str
), fp
) &&
237 (p
= strstr(str
, "0:File:")) == NULL
) {}
238 if ((p
= strstr(str
, "0:File:")) == NULL
||
239 strncmp (p
+ strlen("0:File:"), file
->filename
, len
) != 0 ||
240 p
[strlen("0:File:") + len
] != ' ')
242 for (i
= 0; i
< file
->n_func
; i
++) {
244 tcov_function
*func
= &file
->func
[i
];
245 unsigned int next_zero
= 0;
246 unsigned int curline
= 0;
248 for (j
= 0; j
< func
->n_line
; j
++) {
249 tcov_line
*line
= &func
->line
[j
];
250 unsigned int fline
= line
->fline
;
251 unsigned long long count
;
255 while (curline
< fline
&&
256 fgets(str
, sizeof(str
), fp
))
257 if ((p
= strchr(str
, ':')) &&
258 sscanf (p
+ 1, "%u", &tmp
) == 1)
260 if (sscanf (str
, "%llu%c\n", &count
, &c
) == 2) {
262 line
->count
+= count
;
263 next_zero
= c
== '*';
271 /* store tcov data in file */
272 void __store_test_coverage (unsigned char * p
)
278 unsigned int blocks_run
;
280 char *cov_filename
= (char *)p
+ get_value (p
, 4);
287 fp
= open_tcov_file (cov_filename
);
289 fprintf (stderr
, "Cannot create coverage file: %s\n", cov_filename
);
292 file
= sort_test_coverage (p
);
293 merge_test_coverage (file
, fp
, &runs
);
294 fseek (fp
, 0, SEEK_SET
);
295 fprintf (fp
, " -: 0:Runs:%u\n", runs
);
303 for (i
= 0; i
< nfile
->n_func
; i
++) {
304 func
= &nfile
->func
[i
];
306 for (j
= 0; j
< func
->n_line
; j
++) {
308 blocks_run
+= func
->line
[j
].count
!= 0;
315 fprintf (fp
, " -: 0:All:%s Files:%u Functions:%u %.02f%%\n",
316 cov_filename
, files
, funcs
, 100.0 * (double) blocks_run
/ blocks
);
319 FILE *src
= fopen (nfile
->filename
, "r");
320 unsigned int curline
= 1;
328 for (i
= 0; i
< nfile
->n_func
; i
++) {
329 func
= &nfile
->func
[i
];
331 for (j
= 0; j
< func
->n_line
; j
++) {
333 blocks_run
+= func
->line
[j
].count
!= 0;
338 fprintf (fp
, " -: 0:File:%s Functions:%u %.02f%%\n",
339 nfile
->filename
, funcs
, 100.0 * (double) blocks_run
/ blocks
);
340 for (i
= 0; i
< nfile
->n_func
; i
++) {
341 func
= &nfile
->func
[i
];
343 while (curline
< func
->first_line
&&
344 fgets(str
, sizeof(str
), src
))
345 fprintf (fp
, " -:%5u:%s", curline
++, str
);
348 for (j
= 0; j
< func
->n_line
; j
++) {
350 blocks_run
+= func
->line
[j
].count
!= 0;
354 fprintf (fp
, " -: 0:Function:%s %.02f%%\n",
355 func
->function
, 100.0 * (double) blocks_run
/ blocks
);
357 for (j
= 0; j
< func
->n_line
; j
++) {
358 unsigned int fline
= func
->line
[j
].fline
;
359 unsigned int lline
= func
->line
[j
].lline
;
360 unsigned long long count
= func
->line
[j
].count
;
362 fprintf (fp
, "%u %u %llu\n", fline
, lline
, count
);
365 for (j
= 0; j
< func
->n_line
;) {
366 unsigned int fline
= func
->line
[j
].fline
;
367 unsigned int lline
= func
->line
[j
].lline
;
368 unsigned long long count
= func
->line
[j
].count
;
369 unsigned int has_zero
= 0;
370 unsigned int same_line
= fline
== lline
;
373 while (j
< func
->n_line
) {
374 unsigned int nfline
= func
->line
[j
].fline
;
375 unsigned int nlline
= func
->line
[j
].lline
;
376 unsigned long long ncount
= func
->line
[j
].count
;
378 if (fline
== nfline
) {
381 else if (ncount
> count
)
383 same_line
= nfline
== nlline
;
393 while (curline
< fline
&&
394 fgets(str
, sizeof(str
), src
))
395 fprintf (fp
, " -:%5u:%s", curline
++, str
);
396 while (curline
< lline
&&
397 fgets(str
, sizeof(str
), src
)) {
399 fprintf (fp
, " #####:%5u:%s",
402 fprintf (fp
, "%8llu*:%5u:%s",
403 count
, curline
, str
);
405 fprintf (fp
, "%9llu:%5u:%s",
406 count
, curline
, str
);
411 while (fgets(str
, sizeof(str
), src
))
412 fprintf (fp
, " -:%5u:%s", curline
++, str
);
418 for (i
= 0; i
< file
->n_func
; i
++) {
419 func
= &file
->func
[i
];