From 1c255baad5572e39f1c9f4e1351244cf1b185488 Mon Sep 17 00:00:00 2001 From: herman ten brugge Date: Wed, 27 Jan 2021 13:27:10 +0100 Subject: [PATCH] test coverage update Add myself to RELICENSING file Use locking when writing tcov file Fixed sometimes last line of function not shown Merge tcc_tcov_add_file and tcc_add_tcov Allow absolute file names Count case labels with no code better --- RELICENSING | 1 + lib/tcov.c | 52 ++++++++++++++++++++++++++++++++++++++++++---------- tcc.h | 1 - tccelf.c | 15 ++++++--------- tccgen.c | 20 ++++++++++++++------ tccpe.c | 2 -- 6 files changed, 63 insertions(+), 28 deletions(-) diff --git a/RELICENSING b/RELICENSING index 20841a73..500fa03e 100644 --- a/RELICENSING +++ b/RELICENSING @@ -35,6 +35,7 @@ Frédéric Féret YES x86 64/16 bit asm grischka YES tccpe.c Henry Kroll YES + Herman ten Brugge YES Joe Soroka YES Kirill Smelkov YES mingodad YES diff --git a/lib/tcov.c b/lib/tcov.c index aa46e14b..dac7adbe 100644 --- a/lib/tcov.c +++ b/lib/tcov.c @@ -1,6 +1,14 @@ #include #include #include +#include +#ifndef _WIN32 +#include +#include +#else +#include +#include +#endif /* section layout (all little endian): 32bit offset to executable/so file name @@ -38,6 +46,32 @@ typedef struct tcov_file { struct tcov_file *next; } tcov_file; +static FILE *open_tcov_file (char *cov_filename) +{ + int fd; +#ifndef _WIN32 + struct flock lock; + + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; /* Until EOF. */ + lock.l_pid = getpid (); +#endif + fd = open (cov_filename, O_RDWR | O_CREAT, 0666); + if (fd < 0) + return NULL; + +#ifndef _WIN32 + while (fcntl (fd, F_SETLKW, &lock) && errno == EINTR) + continue; +#else + LockFile((HANDLE)_get_osfhandle(fd), 0, 0, 1, 0); +#endif + + return fdopen (fd, "r+"); +} + static unsigned long long get_value(unsigned char *p, int size) { unsigned long long value = 0; @@ -176,11 +210,10 @@ static tcov_file *sort_test_coverage (unsigned char *p) } /* merge with previous tcov file */ -static void merge_test_coverage (tcov_file *file, char *cov_filename, +static void merge_test_coverage (tcov_file *file, FILE *fp, unsigned int *pruns) { unsigned int runs; - FILE *fp = fopen (cov_filename, "r"); char *p; char str[10000]; @@ -228,7 +261,6 @@ static void merge_test_coverage (tcov_file *file, char *cov_filename, } file = file->next; } - fclose (fp); } /* store tcov data in file */ @@ -247,13 +279,14 @@ void __store_test_coverage (unsigned char * p) tcov_file *nfile; tcov_function *func; - file = sort_test_coverage (p); - merge_test_coverage (file, cov_filename, &runs); - fp = fopen (cov_filename, "w"); + fp = open_tcov_file (cov_filename); if (fp == NULL) { fprintf (stderr, "Cannot create coverage file: %s\n", cov_filename); return; } + file = sort_test_coverage (p); + merge_test_coverage (file, fp, &runs); + fseek (fp, 0, SEEK_SET); fprintf (fp, " -: 0:Runs:%u\n", runs); files = 0; funcs = 0; @@ -346,12 +379,11 @@ void __store_test_coverage (unsigned char * p) lline = nlline; j++; } - else { - if (same_line) - lline++; + else break; - } } + if (same_line) + lline++; while (curline < fline) if (fgets(str, sizeof(str), src)) diff --git a/tcc.h b/tcc.h index 691f649c..3f8647d1 100644 --- a/tcc.h +++ b/tcc.h @@ -1467,7 +1467,6 @@ ST_FUNC void tcc_debug_end(TCCState *s1); ST_FUNC void tcc_debug_bincl(TCCState *s1); ST_FUNC void tcc_debug_eincl(TCCState *s1); ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename); -ST_FUNC void tcc_add_tcov(TCCState *s1); ST_FUNC void tccgen_init(TCCState *s1); ST_FUNC int tccgen_compile(TCCState *s1); diff --git a/tccelf.c b/tccelf.c index d3b1f3cb..64623cac 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1438,9 +1438,13 @@ static void tcc_tcov_add_file(TCCState *s1, const char *filename) section_ptr_add(tcov_section, 1); write32le (tcov_section->data, tcov_section->data_offset); - getcwd (wd, sizeof(wd)); cstr_new (&cstr); - cstr_printf (&cstr, "%s/%s.tcov", wd, filename); + if (filename[0] == '/') + cstr_printf (&cstr, "%s.tcov", filename); + else { + getcwd (wd, sizeof(wd)); + cstr_printf (&cstr, "%s/%s.tcov", wd, filename); + } ptr = section_ptr_add(tcov_section, cstr.size + 1); strncpy((char *)ptr, cstr.data, cstr.size); unlink((char *)ptr); @@ -1448,11 +1452,6 @@ static void tcc_tcov_add_file(TCCState *s1, const char *filename) normalize_slashes((char *)ptr); #endif cstr_free (&cstr); -} - -ST_FUNC void tcc_add_tcov(TCCState *s1) -{ - CString cstr; cstr_new(&cstr); cstr_printf(&cstr, @@ -1512,8 +1511,6 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) tcc_add_btstub(s1); } #endif - if (s1->test_coverage) - tcc_add_tcov(s1); if (strlen(TCC_LIBTCC1) > 0) tcc_add_support(s1, TCC_LIBTCC1); #if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD diff --git a/tccgen.c b/tccgen.c index d7511f16..5f7c16d8 100644 --- a/tccgen.c +++ b/tccgen.c @@ -208,7 +208,6 @@ static struct debug_info { static struct { unsigned long offset; - unsigned long last_offset; unsigned long last_file_name; unsigned long last_func_name; int ind; @@ -822,6 +821,7 @@ static void tcc_tcov_block_begin(void) { SValue sv; void *ptr; + unsigned long last_offset = tcov_data.offset; tcc_tcov_block_end (0); if (tcc_state->test_coverage == 0 || nocode_wanted) @@ -837,11 +837,17 @@ static void tcc_tcov_block_begin(void) section_ptr_add(tcov_section, 1); if (tcov_data.last_file_name) section_ptr_add(tcov_section, 1); - getcwd (wd, sizeof(wd)); - tcov_data.last_file_name = tcov_section->data_offset + strlen(wd) + 1; tcov_data.last_func_name = 0; cstr_new (&cstr); - cstr_printf (&cstr, "%s/%s", wd, file->true_filename); + if (file->true_filename[0] == '/') { + tcov_data.last_file_name = tcov_section->data_offset; + cstr_printf (&cstr, "%s", file->true_filename); + } + else { + getcwd (wd, sizeof(wd)); + tcov_data.last_file_name = tcov_section->data_offset + strlen(wd) + 1; + cstr_printf (&cstr, "%s/%s", wd, file->true_filename); + } ptr = section_ptr_add(tcov_section, cstr.size + 1); strncpy((char *)ptr, cstr.data, cstr.size); #ifdef _WIN32 @@ -865,7 +871,7 @@ static void tcc_tcov_block_begin(void) write64le (ptr, file->line_num); } if (ind == tcov_data.ind && tcov_data.line == file->line_num) - tcov_data.offset = tcov_data.last_offset; + tcov_data.offset = last_offset; else { Sym label = {0}; label.type.t = VT_LLONG | VT_STATIC; @@ -903,7 +909,6 @@ static void tcc_tcov_block_end(int line) unsigned long long nline = line ? line : file->line_num; write64le (ptr, (read64le (ptr) & 0xfffffffffull) | (nline << 36)); - tcov_data.last_offset = tcov_data.offset; tcov_data.offset = 0; } } @@ -5744,6 +5749,7 @@ static inline int is_memory_model(const SValue *sv) * Ideally we should check whether the model matches 1:1. * If it is possible, we should check by the name of the value. */ +int t = 0; // XXX: HACK return (((t & VT_BTYPE) == VT_INT) && (sv->c.i < 6)); } @@ -7576,6 +7582,7 @@ again: || (cur_switch->sv.type.t & VT_UNSIGNED && (uint64_t)cr->v2 < (uint64_t)cr->v1)) tcc_warning("empty case range"); } + tcov_data.ind = 0; cr->sym = gind(); dynarray_add(&cur_switch->p, &cur_switch->n, cr); skip(':'); @@ -7587,6 +7594,7 @@ again: expect("switch"); if (cur_switch->def_sym) tcc_error("too many 'default'"); + tcov_data.ind = 0; cur_switch->def_sym = gind(); skip(':'); is_expr = 0; diff --git a/tccpe.c b/tccpe.c index 161e85ca..3f5965fd 100644 --- a/tccpe.c +++ b/tccpe.c @@ -1915,8 +1915,6 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) tcc_add_btstub(s1); } #endif - if (s1->test_coverage) - tcc_add_tcov(s1); /* grab the startup code from libtcc1.a */ #ifdef TCC_IS_NATIVE