Implement line coverage collection and reporting!
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -19,3 +19,5 @@ kolibri.lst
|
|||||||
kolibri.prp
|
kolibri.prp
|
||||||
tags
|
tags
|
||||||
*.out
|
*.out
|
||||||
|
coverage.*
|
||||||
|
covpreproc
|
||||||
|
111
covpreproc.c
Normal file
111
covpreproc.c
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#define MAX_COVERED_CODE_SIZE (128*1024)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t to_cnt, from_cnt;
|
||||||
|
} branch;
|
||||||
|
|
||||||
|
branch branches[MAX_COVERED_CODE_SIZE];
|
||||||
|
|
||||||
|
uint32_t coverage_offset, coverage_begin, coverage_end;
|
||||||
|
|
||||||
|
void read_coverage_file(const char *fname) {
|
||||||
|
FILE *f = fopen(fname, "r+");
|
||||||
|
fseeko(f, 0, SEEK_END);
|
||||||
|
off_t fsize = ftello(f);
|
||||||
|
fseeko(f, 0, SEEK_SET);
|
||||||
|
size_t branch_cnt = fsize/(2*sizeof(uint32_t));
|
||||||
|
for (size_t i = 0; i < branch_cnt; i++) {
|
||||||
|
uint32_t from, to;
|
||||||
|
fread(&from, sizeof(uint32_t), 1, f);
|
||||||
|
fread(&to, sizeof(uint32_t), 1, f);
|
||||||
|
if (from >= coverage_begin && from < coverage_end /*&& to < 0x80000000u*/) {
|
||||||
|
from = from - coverage_begin + coverage_offset;
|
||||||
|
branches[from].from_cnt++;
|
||||||
|
}
|
||||||
|
if (to >= coverage_begin && to < coverage_end /*&& from < 0x80000000u*/) {
|
||||||
|
to = to - coverage_begin + coverage_offset;
|
||||||
|
branches[to].to_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t count_line_bytes(const char *s) {
|
||||||
|
size_t cnt = 0;
|
||||||
|
for (size_t i = 10; i <= 58; i += 3) {
|
||||||
|
if (s[i] == ' ') break;
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t count_block_bytes(FILE *f) {
|
||||||
|
char tmp[1024];
|
||||||
|
size_t cnt = 0;
|
||||||
|
if (fgets(tmp, 1024, f) && strspn(tmp, "0123456789ABCDEF") == 8) {
|
||||||
|
cnt = count_line_bytes(tmp);
|
||||||
|
while (fgets(tmp, 1024, f) && tmp[0] == ' ' && tmp[10] != ' ') {
|
||||||
|
cnt += count_line_bytes(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
if (argc < 6) {
|
||||||
|
fprintf(stderr, "usage: covpreproc <listing file> <coverage_begin offset> <coverage_begin address> <coverage_end address> <coverage files ...>\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
sscanf(argv[2], "%" SCNx32, &coverage_offset);
|
||||||
|
sscanf(argv[3], "%" SCNx32, &coverage_begin);
|
||||||
|
sscanf(argv[4], "%" SCNx32, &coverage_end);
|
||||||
|
|
||||||
|
for (int i = 5; i < argc; i++) {
|
||||||
|
read_coverage_file(argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *f = fopen(argv[1], "r");
|
||||||
|
char tmp[1024];
|
||||||
|
uint64_t cur = 0;
|
||||||
|
while (1) {
|
||||||
|
off_t fpos_before = ftello(f);
|
||||||
|
if (!fgets(tmp, 1024, f)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
off_t fpos_after = ftello(f);
|
||||||
|
if (strspn(tmp, "0123456789ABCDEF") == 8) {
|
||||||
|
fseeko(f, fpos_before, SEEK_SET);
|
||||||
|
size_t inst_len = count_block_bytes(f);
|
||||||
|
fseeko(f, fpos_after, SEEK_SET);
|
||||||
|
unsigned long pos = strtoul(tmp, NULL, 16);
|
||||||
|
size_t total_to = 0, total_from = 0;
|
||||||
|
for (size_t i = 0; i < inst_len; i++) {
|
||||||
|
total_to += branches[pos + i].to_cnt;
|
||||||
|
total_from += branches[pos + i].from_cnt;
|
||||||
|
}
|
||||||
|
cur += total_to;
|
||||||
|
if (cur) {
|
||||||
|
putchar(' ');
|
||||||
|
} else {
|
||||||
|
putchar('-');
|
||||||
|
}
|
||||||
|
if (total_from || total_to || cur) {
|
||||||
|
printf("%8" PRIu64 " %8" PRIu64 " %8" PRIu64, total_from, total_to, cur);
|
||||||
|
} else {
|
||||||
|
printf(" - - -");
|
||||||
|
}
|
||||||
|
cur -= total_from;
|
||||||
|
} else {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
printf(" : %s", tmp + 64);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
2
kofu.c
2
kofu.c
@@ -47,7 +47,7 @@ const char *last_dir = cur_dir;
|
|||||||
bool cur_dir_changed = true;
|
bool cur_dir_changed = true;
|
||||||
|
|
||||||
char cmd_buf[FGETS_BUF_LEN];
|
char cmd_buf[FGETS_BUF_LEN];
|
||||||
int trace = false;
|
int trace = true;
|
||||||
|
|
||||||
const char *f70_status_name[] = {
|
const char *f70_status_name[] = {
|
||||||
"success",
|
"success",
|
||||||
|
7
makefile
7
makefile
@@ -6,10 +6,13 @@ CFLAGS_32=-m32
|
|||||||
LDFLAGS=
|
LDFLAGS=
|
||||||
LDFLAGS_32=-m32
|
LDFLAGS_32=-m32
|
||||||
|
|
||||||
all: kofu kofuse kolibri.sym kolibri.prp kolibri.lst tags tools/mkdirrange tools/mkfilepattern
|
all: kofu kofuse kolibri.sym kolibri.prp kolibri.lst tags tools/mkdirrange tools/mkfilepattern covpreproc
|
||||||
|
|
||||||
|
covpreproc: covpreproc.c
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
kofu: kofu.o kolibri.o trace.o trace_lbr.o trace_lwp.o cio.o
|
kofu: kofu.o kolibri.o trace.o trace_lbr.o trace_lwp.o cio.o
|
||||||
$(CC) $(LDFLAGS) $(LDFLAGS_32) $^ -o $@
|
$(CC) $(LDFLAGS) $(LDFLAGS_32) $^ -o $@ -static
|
||||||
|
|
||||||
kofuse: kofuse.o kolibri.o cio.o
|
kofuse: kofuse.o kolibri.o cio.o
|
||||||
$(CC) $(LDFLAGS) $(LDFLAGS_32) $^ -o $@ `pkg-config fuse3 --libs`
|
$(CC) $(LDFLAGS) $(LDFLAGS_32) $^ -o $@ `pkg-config fuse3 --libs`
|
||||||
|
@@ -48,8 +48,8 @@ void handle_sigtrap() {
|
|||||||
|
|
||||||
if ((from >= (uintptr_t)coverage_begin && from < (uintptr_t)coverage_end) ||
|
if ((from >= (uintptr_t)coverage_begin && from < (uintptr_t)coverage_end) ||
|
||||||
(to >= (uintptr_t)coverage_begin && to < (uintptr_t)coverage_end)) {
|
(to >= (uintptr_t)coverage_begin && to < (uintptr_t)coverage_end)) {
|
||||||
write(covfd, &from, 8);
|
write(covfd, &from, 4);
|
||||||
write(covfd, &to, 8);
|
write(covfd, &to, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
wrmsr(0x1d9, 3);
|
wrmsr(0x1d9, 3);
|
||||||
@@ -72,7 +72,9 @@ void trace_lbr_begin() {
|
|||||||
perror("rdmsr: open");
|
perror("rdmsr: open");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
covfd = open("coverage", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
char coverage_filename[32];
|
||||||
|
sprintf(coverage_filename, "coverage.%i", getpid());
|
||||||
|
covfd = open(coverage_filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||||
set_eflags_tf(1);
|
set_eflags_tf(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user