Coverage collection speed up 4x!
Also, adjust disk cache size and move set_eflags_tf() to trace_lbr.c.
This commit is contained in:
parent
2a4cfff503
commit
67f7873e27
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,6 +17,7 @@ umka.fas
|
|||||||
umka.sym
|
umka.sym
|
||||||
umka.lst
|
umka.lst
|
||||||
umka.prp
|
umka.prp
|
||||||
|
umka.cov
|
||||||
tags
|
tags
|
||||||
*.out
|
*.out
|
||||||
coverage.*
|
coverage.*
|
||||||
|
24
covpreproc.c
24
covpreproc.c
@ -3,7 +3,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#define MAX_COVERED_CODE_SIZE (128*1024)
|
#define MAX_COVERED_CODE_SIZE (256*1024)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t to_cnt, from_cnt;
|
uint64_t to_cnt, from_cnt;
|
||||||
@ -18,16 +18,18 @@ void read_coverage_file(const char *fname) {
|
|||||||
fseeko(f, 0, SEEK_END);
|
fseeko(f, 0, SEEK_END);
|
||||||
off_t fsize = ftello(f);
|
off_t fsize = ftello(f);
|
||||||
fseeko(f, 0, SEEK_SET);
|
fseeko(f, 0, SEEK_SET);
|
||||||
size_t branch_cnt = fsize/(2*sizeof(uint32_t));
|
fread(&coverage_begin, sizeof(uint32_t), 1, f);
|
||||||
|
fread(&coverage_end, sizeof(uint32_t), 1, f);
|
||||||
|
size_t branch_cnt = (fsize-4*2)/(2*4);
|
||||||
for (size_t i = 0; i < branch_cnt; i++) {
|
for (size_t i = 0; i < branch_cnt; i++) {
|
||||||
uint32_t from, to;
|
uint32_t from, to;
|
||||||
fread(&from, sizeof(uint32_t), 1, f);
|
fread(&from, sizeof(uint32_t), 1, f);
|
||||||
fread(&to, sizeof(uint32_t), 1, f);
|
fread(&to, sizeof(uint32_t), 1, f);
|
||||||
if (from >= coverage_begin && from < coverage_end /*&& to < 0x80000000u*/) {
|
if (from >= coverage_begin && from < coverage_end) {
|
||||||
from = from - coverage_begin + coverage_offset;
|
from = from - coverage_begin + coverage_offset;
|
||||||
branches[from].from_cnt++;
|
branches[from].from_cnt++;
|
||||||
}
|
}
|
||||||
if (to >= coverage_begin && to < coverage_end /*&& from < 0x80000000u*/) {
|
if (to >= coverage_begin && to < coverage_end) {
|
||||||
to = to - coverage_begin + coverage_offset;
|
to = to - coverage_begin + coverage_offset;
|
||||||
branches[to].to_cnt++;
|
branches[to].to_cnt++;
|
||||||
}
|
}
|
||||||
@ -94,15 +96,13 @@ int is_cond_jump(const char *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if (argc < 6) {
|
if (argc < 4) {
|
||||||
fprintf(stderr, "usage: covpreproc <listing file> <coverage_begin offset> <coverage_begin address> <coverage_end address> <coverage files ...>\n");
|
fprintf(stderr, "usage: covpreproc <listing file> <coverage_begin offset> <coverage files ...>\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
sscanf(argv[2], "%" SCNx32, &coverage_offset);
|
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++) {
|
for (int i = 3; i < argc; i++) {
|
||||||
read_coverage_file(argv[i]);
|
read_coverage_file(argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,8 +123,10 @@ int main(int argc, char **argv) {
|
|||||||
unsigned long pos = strtoul(tmp, NULL, 16);
|
unsigned long pos = strtoul(tmp, NULL, 16);
|
||||||
size_t total_to = 0, total_from = 0;
|
size_t total_to = 0, total_from = 0;
|
||||||
for (size_t i = 0; i < inst_len; i++) {
|
for (size_t i = 0; i < inst_len; i++) {
|
||||||
total_to += branches[pos + i].to_cnt;
|
if (pos + i < coverage_end - coverage_begin + coverage_offset) {
|
||||||
total_from += branches[pos + i].from_cnt;
|
total_to += branches[pos + i].to_cnt;
|
||||||
|
total_from += branches[pos + i].from_cnt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cur += total_to;
|
cur += total_to;
|
||||||
if (is_cond) {
|
if (is_cond) {
|
||||||
|
@ -110,8 +110,8 @@ typedef struct {
|
|||||||
int (*querymedia)(void *userdata, diskmediainfo_t *info) __attribute__((__stdcall__));
|
int (*querymedia)(void *userdata, diskmediainfo_t *info) __attribute__((__stdcall__));
|
||||||
int (*read)(void *userdata, void *buffer, off_t startsector, size_t *numsectors) __attribute__((__stdcall__));
|
int (*read)(void *userdata, void *buffer, off_t startsector, size_t *numsectors) __attribute__((__stdcall__));
|
||||||
int (*write)(void *userdata, void *buffer, off_t startsector, size_t *numsectors) __attribute__((__stdcall__));
|
int (*write)(void *userdata, void *buffer, off_t startsector, size_t *numsectors) __attribute__((__stdcall__));
|
||||||
int (*flush)(void* userdata) __attribute__((__stdcall__));
|
int (*flush)(void *userdata) __attribute__((__stdcall__));
|
||||||
unsigned int (*adjust_cache_size)(uint32_t suggested_size) __attribute__((__stdcall__));
|
unsigned int (*adjust_cache_size)(void *userdata, uint32_t suggested_size) __attribute__((__stdcall__));
|
||||||
} diskfunc_t;
|
} diskfunc_t;
|
||||||
|
|
||||||
struct disk_t {
|
struct disk_t {
|
||||||
@ -231,7 +231,6 @@ typedef struct {
|
|||||||
void kos_init(void);
|
void kos_init(void);
|
||||||
void i40(void);
|
void i40(void);
|
||||||
uint32_t kos_time_to_epoch(uint32_t *time);
|
uint32_t kos_time_to_epoch(uint32_t *time);
|
||||||
void set_eflags_tf(int x);
|
|
||||||
|
|
||||||
void *disk_add(diskfunc_t *disk, const char *name, void *userdata, uint32_t flags) __attribute__((__stdcall__));
|
void *disk_add(diskfunc_t *disk, const char *name, void *userdata, uint32_t flags) __attribute__((__stdcall__));
|
||||||
void *disk_media_changed(diskfunc_t *disk, int inserted) __attribute__((__stdcall__));
|
void *disk_media_changed(diskfunc_t *disk, int inserted) __attribute__((__stdcall__));
|
||||||
|
16
makefile
16
makefile
@ -4,7 +4,7 @@ WARNINGS=-Wall -Wextra -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wre
|
|||||||
CFLAGS=$(WARNINGS) -g -O0 -D_FILE_OFFSET_BITS=64 -Wno-address-of-packed-member -DNDEBUG -masm=intel
|
CFLAGS=$(WARNINGS) -g -O0 -D_FILE_OFFSET_BITS=64 -Wno-address-of-packed-member -DNDEBUG -masm=intel
|
||||||
CFLAGS_32=$(CFLAGS) -m32
|
CFLAGS_32=$(CFLAGS) -m32
|
||||||
LDFLAGS=
|
LDFLAGS=
|
||||||
LDFLAGS_32=-m32
|
LDFLAGS_32=$(LDFLAGS) -m32
|
||||||
|
|
||||||
all: umka_shell umka_fuse umka.sym umka.prp umka.lst tags tools/mkdirrange tools/mkfilepattern covpreproc
|
all: umka_shell umka_fuse umka.sym umka.prp umka.lst tags tools/mkdirrange tools/mkfilepattern covpreproc
|
||||||
|
|
||||||
@ -12,10 +12,10 @@ covpreproc: covpreproc.c
|
|||||||
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
|
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
umka_shell: umka_shell.o umka.o trace.o trace_lbr.o vdisk.o lodepng.o
|
umka_shell: umka_shell.o umka.o trace.o trace_lbr.o vdisk.o lodepng.o
|
||||||
$(CC) $(LDFLAGS) $(LDFLAGS_32) $^ -o $@ -static
|
$(CC) $(LDFLAGS_32) $^ -o $@ -static
|
||||||
|
|
||||||
umka_fuse: umka_fuse.o umka.o vdisk.o
|
umka_fuse: umka_fuse.o umka.o vdisk.o
|
||||||
$(CC) $(LDFLAGS) $(LDFLAGS_32) $^ -o $@ `pkg-config fuse3 --libs`
|
$(CC) $(LDFLAGS_32) $^ -o $@ `pkg-config fuse3 --libs`
|
||||||
|
|
||||||
umka.o umka.fas: umka.asm skin.skn
|
umka.o umka.fas: umka.asm skin.skn
|
||||||
INCLUDE="$(KOLIBRI)/kernel/trunk;$(KOLIBRI)/programs/develop/libraries/libcrash/trunk" $(FASM) $< umka.o -s umka.fas -m 1234567
|
INCLUDE="$(KOLIBRI)/kernel/trunk;$(KOLIBRI)/programs/develop/libraries/libcrash/trunk" $(FASM) $< umka.o -s umka.fas -m 1234567
|
||||||
@ -39,19 +39,19 @@ tags: umka.sym
|
|||||||
fasmtags.py $<
|
fasmtags.py $<
|
||||||
|
|
||||||
trace.o: trace.c trace.h trace_lbr.h
|
trace.o: trace.c trace.h trace_lbr.h
|
||||||
$(CC) $(CFLAGS) $(CFLAGS_32) -c $<
|
$(CC) $(CFLAGS_32) -c $<
|
||||||
|
|
||||||
trace_lbr.o: trace_lbr.c trace_lbr.h kolibri.h
|
trace_lbr.o: trace_lbr.c trace_lbr.h kolibri.h
|
||||||
$(CC) $(CFLAGS) $(CFLAGS_32) -c $<
|
$(CC) $(CFLAGS_32) -c $<
|
||||||
|
|
||||||
vdisk.o: vdisk.c
|
vdisk.o: vdisk.c
|
||||||
$(CC) $(CFLAGS) $(CFLAGS_32) -c $<
|
$(CC) $(CFLAGS_32) -c $<
|
||||||
|
|
||||||
umka_shell.o: umka_shell.c kolibri.h trace.h syscalls.h
|
umka_shell.o: umka_shell.c kolibri.h trace.h syscalls.h
|
||||||
$(CC) $(CFLAGS) $(CFLAGS_32) -c $< -std=c99 -D_POSIX_C_SOURCE=2
|
$(CC) $(CFLAGS_32) -c $< -std=c99 -D_POSIX_C_SOURCE=2
|
||||||
|
|
||||||
umka_fuse.o: umka_fuse.c kolibri.h
|
umka_fuse.o: umka_fuse.c kolibri.h
|
||||||
$(CC) $(CFLAGS) $(CFLAGS_32) `pkg-config fuse3 --cflags` -c $< -std=gnu99
|
$(CC) $(CFLAGS_32) `pkg-config fuse3 --cflags` -c $< -std=gnu99
|
||||||
|
|
||||||
tools/mkdirrange: tools/mkdirrange.c
|
tools/mkdirrange: tools/mkdirrange.c
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
|
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
|
||||||
|
@ -37,3 +37,11 @@ draw: $(draw_tests)
|
|||||||
$(UMKA_SHELL) < $*.t > $@
|
$(UMKA_SHELL) < $*.t > $@
|
||||||
@ cmp $@ $<
|
@ cmp $@ $<
|
||||||
@ if [ -f "$*.ref.png" ]; then cmp $*.out.png $*.ref.png; fi
|
@ if [ -f "$*.ref.png" ]; then cmp $*.out.png $*.ref.png; fi
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
../covpreproc ../umka.lst 0x34 coverage.* > ../umka.cov
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ???_*.out.{log,png} coverage coverage.*
|
||||||
|
|
||||||
|
.PHONY: clean coverage
|
||||||
|
34
trace_lbr.c
34
trace_lbr.c
@ -10,6 +10,12 @@
|
|||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include "kolibri.h"
|
#include "kolibri.h"
|
||||||
|
|
||||||
|
#define MSR_IA32_DEBUGCTLMSR 0x1d9
|
||||||
|
#define MSR_IA32_LASTBRANCHFROMIP 0x1db
|
||||||
|
#define MSR_IA32_LASTBRANCHTOIP 0x1dc
|
||||||
|
#define MSR_IA32_LASTINTFROMIP 0x1dd
|
||||||
|
#define MSR_IA32_LASTINTTOIP 0x1de
|
||||||
|
|
||||||
int covfd, msrfd;
|
int covfd, msrfd;
|
||||||
|
|
||||||
uint64_t rdmsr(uint32_t reg)
|
uint64_t rdmsr(uint32_t reg)
|
||||||
@ -43,8 +49,8 @@ void wrmsr(uint32_t reg, uint64_t data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void handle_sigtrap() {
|
void handle_sigtrap() {
|
||||||
uint64_t from = rdmsr(0x1db);
|
uint64_t from = rdmsr(MSR_IA32_LASTBRANCHFROMIP);
|
||||||
uint64_t to = rdmsr(0x1dc);
|
uint64_t to = rdmsr(MSR_IA32_LASTBRANCHTOIP);
|
||||||
|
|
||||||
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)) {
|
||||||
@ -52,7 +58,21 @@ void handle_sigtrap() {
|
|||||||
write(covfd, &to, 4);
|
write(covfd, &to, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
wrmsr(0x1d9, 3);
|
wrmsr(MSR_IA32_DEBUGCTLMSR, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_eflags_tf(uint32_t tf) {
|
||||||
|
__asm__ __inline__ __volatile__ (
|
||||||
|
"pushfd;"
|
||||||
|
"pop eax;"
|
||||||
|
"shl ecx, 8;" // TF
|
||||||
|
"and eax, ~(1 << 8);"
|
||||||
|
"or eax, ecx;"
|
||||||
|
"push eax;"
|
||||||
|
"popfd"
|
||||||
|
:
|
||||||
|
: "c"(tf)
|
||||||
|
: "eax", "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
void trace_lbr_begin() {
|
void trace_lbr_begin() {
|
||||||
@ -66,7 +86,7 @@ void trace_lbr_begin() {
|
|||||||
CPU_ZERO(&my_set);
|
CPU_ZERO(&my_set);
|
||||||
CPU_SET(0, &my_set);
|
CPU_SET(0, &my_set);
|
||||||
sched_setaffinity(0, sizeof(cpu_set_t), &my_set);
|
sched_setaffinity(0, sizeof(cpu_set_t), &my_set);
|
||||||
wrmsr(0x1d9, 3);
|
wrmsr(MSR_IA32_DEBUGCTLMSR, 3);
|
||||||
msrfd = open("/dev/cpu/0/msr", O_RDONLY);
|
msrfd = open("/dev/cpu/0/msr", O_RDONLY);
|
||||||
if (msrfd < 0) {
|
if (msrfd < 0) {
|
||||||
perror("rdmsr: open");
|
perror("rdmsr: open");
|
||||||
@ -75,12 +95,16 @@ void trace_lbr_begin() {
|
|||||||
char coverage_filename[32];
|
char coverage_filename[32];
|
||||||
sprintf(coverage_filename, "coverage.%i", getpid());
|
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);
|
covfd = open(coverage_filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||||
|
void *coverage_begin_addr = &coverage_begin;
|
||||||
|
void *coverage_end_addr = &coverage_end;
|
||||||
|
write(covfd, &coverage_begin_addr, 4);
|
||||||
|
write(covfd, &coverage_end_addr, 4);
|
||||||
set_eflags_tf(1);
|
set_eflags_tf(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void trace_lbr_end() {
|
void trace_lbr_end() {
|
||||||
set_eflags_tf(0);
|
set_eflags_tf(0);
|
||||||
wrmsr(0x1d9, 0);
|
wrmsr(MSR_IA32_DEBUGCTLMSR, 0);
|
||||||
close(msrfd);
|
close(msrfd);
|
||||||
close(covfd);
|
close(covfd);
|
||||||
}
|
}
|
||||||
|
14
umka.asm
14
umka.asm
@ -19,7 +19,6 @@ public coverage_begin
|
|||||||
public coverage_end
|
public coverage_end
|
||||||
|
|
||||||
public sha3_256_oneshot as 'hash_oneshot'
|
public sha3_256_oneshot as 'hash_oneshot'
|
||||||
public set_eflags_tf
|
|
||||||
public kos_time_to_epoch
|
public kos_time_to_epoch
|
||||||
public kos_init
|
public kos_init
|
||||||
|
|
||||||
@ -145,19 +144,6 @@ proc sha3_256_oneshot c uses ebx esi edi ebp, _ctx, _data, _len
|
|||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
; TODO: move to trace_lbr
|
|
||||||
set_eflags_tf:
|
|
||||||
pushfd
|
|
||||||
pop eax
|
|
||||||
mov ecx, [esp + 4]
|
|
||||||
and ecx, 1
|
|
||||||
shl ecx, 8 ; TF
|
|
||||||
and eax, NOT (1 SHL 8)
|
|
||||||
or eax, ecx
|
|
||||||
push eax
|
|
||||||
popfd
|
|
||||||
ret
|
|
||||||
|
|
||||||
proc kos_time_to_epoch c uses ebx esi edi ebp, _time
|
proc kos_time_to_epoch c uses ebx esi edi ebp, _time
|
||||||
mov esi, [_time]
|
mov esi, [_time]
|
||||||
call fsCalculateTime
|
call fsCalculateTime
|
||||||
|
@ -62,14 +62,14 @@ diskfunc_t vdisk_functions = {
|
|||||||
.read = vdisk_read,
|
.read = vdisk_read,
|
||||||
.write = vdisk_write,
|
.write = vdisk_write,
|
||||||
.flush = NULL,
|
.flush = NULL,
|
||||||
.adjust_cache_size = NULL,
|
.adjust_cache_size = vdisk_adjust_cache_size,
|
||||||
};
|
};
|
||||||
char cur_dir[PATH_MAX] = "/";
|
char cur_dir[PATH_MAX] = "/";
|
||||||
const char *last_dir = cur_dir;
|
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;
|
int trace = 0;
|
||||||
|
|
||||||
const char *f70_status_name[] = {
|
const char *f70_status_name[] = {
|
||||||
"success",
|
"success",
|
||||||
@ -974,7 +974,7 @@ void *run_test(const char *infile_name) {
|
|||||||
usage();
|
usage();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
strcpy(last_dot, ".out");
|
strcpy(last_dot, ".out.log");
|
||||||
infile = fopen(infile_name, "r");
|
infile = fopen(infile_name, "r");
|
||||||
outfile = fopen(outfile_name, "w");
|
outfile = fopen(outfile_name, "w");
|
||||||
if (!infile || !outfile) {
|
if (!infile || !outfile) {
|
||||||
|
7
vdisk.c
7
vdisk.c
@ -60,3 +60,10 @@ int vdisk_querymedia(void *userdata, diskmediainfo_t *minfo) {
|
|||||||
minfo->capacity = vdisk->sect_cnt;
|
minfo->capacity = vdisk->sect_cnt;
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((__stdcall__))
|
||||||
|
unsigned int vdisk_adjust_cache_size(void *userdata, unsigned int suggested_size) {
|
||||||
|
(void)userdata;
|
||||||
|
(void)suggested_size;
|
||||||
|
return 64*1024;
|
||||||
|
}
|
||||||
|
3
vdisk.h
3
vdisk.h
@ -19,4 +19,7 @@ int vdisk_write(void *userdata, void *buffer, off_t startsector, size_t *numsect
|
|||||||
__attribute__((__stdcall__))
|
__attribute__((__stdcall__))
|
||||||
int vdisk_querymedia(void *userdata, diskmediainfo_t *minfo);
|
int vdisk_querymedia(void *userdata, diskmediainfo_t *minfo);
|
||||||
|
|
||||||
|
__attribute__((__stdcall__))
|
||||||
|
unsigned int vdisk_adjust_cache_size(void *userdata, unsigned int suggested_size);
|
||||||
|
|
||||||
#endif // VDISK_H_INCLUDED
|
#endif // VDISK_H_INCLUDED
|
||||||
|
Loading…
Reference in New Issue
Block a user