Speed up coverage, not drastically

This commit is contained in:
Ivan Baravy 2022-06-13 23:46:48 +02:00
parent bf1af355fe
commit 395f75d1f7
8 changed files with 81 additions and 66 deletions

View File

@ -44,7 +44,7 @@ endif
ifeq ($(HOST),linux) ifeq ($(HOST),linux)
all: umka_shell umka_fuse umka_os umka_gen_devices_dat umka.sym umka.prp \ all: umka_shell umka_fuse umka_os umka_gen_devices_dat umka.sym umka.prp \
umka.lst tags covpreproc default.skn skin.skn umka.lst tags default.skn skin.skn
else ifeq ($(HOST),windows) else ifeq ($(HOST),windows)
all: umka_shell umka.sym umka.prp \ all: umka_shell umka.sym umka.prp \
umka.lst default.skn skin.skn umka.lst default.skn skin.skn
@ -57,9 +57,6 @@ endif
test: umka_shell test: umka_shell
@cd test && make clean all && cd ../ @cd test && make clean all && cd ../
covpreproc: covpreproc.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
umka_shell: umka_shell.o umka.o shell.o trace.o trace_lbr.o vdisk.o vnet.o \ umka_shell: umka_shell.o umka.o shell.o trace.o trace_lbr.o vdisk.o vnet.o \
lodepng.o pci.o thread.o util.o optparse.o bestline.o lodepng.o pci.o thread.o util.o optparse.o bestline.o
$(CC) $(LDFLAGS_32) $^ -o $@ -T umka.ld $(CC) $(LDFLAGS_32) $^ -o $@ -T umka.ld

View File

@ -67,7 +67,7 @@ else
endif endif
collect_coverage: collect_coverage:
../covpreproc ../umka.lst 0x34 coverage.* > ../umka.cov ../tools/covpreproc ../umka.lst coverage.* > ../umka.cov
clean: clean:
rm -f *.out.log *.out.png coverage.* rm -f *.out.log *.out.png coverage.*

View File

@ -3,44 +3,33 @@
UMKa - User-Mode KolibriOS developer tools UMKa - User-Mode KolibriOS developer tools
Copyright (C) 2020 Ivan Baravy <dunkaist@gmail.com> Copyright (C) 2020,2022 Ivan Baravy <dunkaist@gmail.com>
*/ */
#include <inttypes.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <inttypes.h>
#define MAX_COVERED_CODE_SIZE (256*1024) #define COVERAGE_TABLE_SIZE (512*1024)
typedef struct { struct coverage_branch {
uint64_t to_cnt, from_cnt; uint64_t to_cnt;
} branch; uint64_t from_cnt;
};
branch branches[MAX_COVERED_CODE_SIZE]; struct coverage_branch branches[COVERAGE_TABLE_SIZE];
uint32_t coverage_offset, coverage_begin, coverage_end; uint32_t coverage_begin = 0x34; // TODD: detect in runtime
void read_coverage_file(const char *fname) { void read_coverage_file(const char *fname) {
FILE *f = fopen(fname, "r"); FILE *f = fopen(fname, "r");
fseeko(f, 0, SEEK_END); for (size_t i = 0; i < COVERAGE_TABLE_SIZE; i++) {
off_t fsize = ftello(f); uint64_t from, to;
fseeko(f, 0, SEEK_SET); fread(&to, 1, sizeof(uint64_t), f);
fread(&coverage_begin, sizeof(uint32_t), 1, f); fread(&from, 1, sizeof(uint64_t), f);
fread(&coverage_end, sizeof(uint32_t), 1, f); branches[i].to_cnt += to;
size_t branch_cnt = (fsize-4*2)/(2*4); branches[i].from_cnt += from;
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) {
from = from - coverage_begin + coverage_offset;
branches[from].from_cnt++;
}
if (to >= coverage_begin && to < coverage_end) {
to = to - coverage_begin + coverage_offset;
branches[to].to_cnt++;
}
} }
fclose(f); fclose(f);
} }
@ -98,19 +87,19 @@ int is_cond_jump(const char *s) {
|| !strncmp(s, "jpe", 3) || !strncmp(s, "jpe", 3)
|| !strncmp(s, "jnp", 3) || !strncmp(s, "jnp", 3)
|| !strncmp(s, "jpo", 3) || !strncmp(s, "jpo", 3)
|| !strncmp(s, "loop", 4)
|| !strncmp(s, "jcxz", 4) || !strncmp(s, "jcxz", 4)
|| !strncmp(s, "jecxz", 5); || !strncmp(s, "jecxz", 5);
return found; return found;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
if (argc < 4) { if (argc < 3) {
fprintf(stderr, "usage: covpreproc <listing file> <coverage_begin offset> <coverage files ...>\n"); fprintf(stderr, "usage: covpreproc <listing file> <coverage files ...>\n");
exit(1); exit(1);
} }
sscanf(argv[2], "%" SCNx32, &coverage_offset);
for (int i = 3; i < argc; i++) { for (int i = 2; i < argc; i++) {
read_coverage_file(argv[i]); read_coverage_file(argv[i]);
} }
@ -131,9 +120,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++) {
if (pos + i < coverage_end - coverage_begin + coverage_offset) { if (pos + i >= coverage_begin
total_to += branches[pos + i].to_cnt; && pos + i < coverage_begin + COVERAGE_TABLE_SIZE) {
total_from += branches[pos + i].from_cnt; total_to += branches[pos + i - coverage_begin].to_cnt;
total_from += branches[pos + i - coverage_begin].from_cnt;
} }
} }
cur += total_to; cur += total_to;
@ -154,7 +144,8 @@ int main(int argc, char **argv) {
putchar('-'); putchar('-');
} }
if (is_cond) { if (is_cond) {
int spaces = 19 - printf("%10" PRIu64 "/%" PRIu64, taken, not_taken); int spaces = 19 - printf("%10" PRIu64 "/%" PRIu64, taken,
not_taken);
while (spaces-- > 0) while (spaces-- > 0)
putchar(' '); putchar(' ');
} else { } else {

View File

@ -7,7 +7,7 @@ CFLAGS=$(WARNINGS) $(NOWARNINGS) -std=c11 -O2 \
-DNDEBUG -D_POSIX_C_SOURCE=200809L -fno-pie -DNDEBUG -D_POSIX_C_SOURCE=200809L -fno-pie
LDFLAGS=-no-pie LDFLAGS=-no-pie
all: mkdirrange mkfilepattern lfbviewx randdir all: mkdirrange mkfilepattern lfbviewx randdir covpreproc
mkdirrange: mkdirrange.c mkdirrange: mkdirrange.c
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
@ -21,7 +21,10 @@ lfbviewx: lfbviewx.c
randdir: randdir.c randdir: randdir.c
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
covpreproc: covpreproc.c
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
.PHONY: all clean .PHONY: all clean
clean: clean:
rm -f *.o mkdirrange mkfilepattern lfbviewx rm -f *.o mkdirrange mkfilepattern lfbviewx randdir covpreproc

View File

@ -3,7 +3,7 @@
UMKa - User-Mode KolibriOS developer tools UMKa - User-Mode KolibriOS developer tools
Copyright (C) 2019-2020 Ivan Baravy <dunkaist@gmail.com> Copyright (C) 2019-2020,2022 Ivan Baravy <dunkaist@gmail.com>
Copyright (C) 2021 Magomed Kostoev <mkostoevr@yandex.ru> Copyright (C) 2021 Magomed Kostoev <mkostoevr@yandex.ru>
*/ */
@ -18,11 +18,13 @@
#include "umka.h" #include "umka.h"
#define MSR_IA32_DEBUGCTLMSR 0x1d9 #define MSR_IA32_DEBUGCTL 0x1d9
#define MSR_IA32_DEBUGCTL_LBR 0x1 // enable profiling
#define MSR_IA32_DEBUGCTL_BTF 0x2 // profile only branches if EFLAGS.TF
#define MSR_IA32_LASTBRANCHFROMIP 0x1db #define MSR_IA32_LASTBRANCHFROMIP 0x1db
#define MSR_IA32_LASTBRANCHTOIP 0x1dc #define MSR_IA32_LASTBRANCHTOIP 0x1dc
int covfd, msrfd; int msrfd;
uint64_t rdmsr(uint32_t reg) uint64_t rdmsr(uint32_t reg)
{ {
@ -66,13 +68,15 @@ void handle_sigtrap() {
uint64_t from = rdmsr(MSR_IA32_LASTBRANCHFROMIP); uint64_t from = rdmsr(MSR_IA32_LASTBRANCHFROMIP);
uint64_t to = rdmsr(MSR_IA32_LASTBRANCHTOIP); 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)) { coverage_table[from - (uintptr_t)coverage_begin].from_cnt++;
write(covfd, &from, 4);
write(covfd, &to, 4);
} }
wrmsr(MSR_IA32_DEBUGCTLMSR, 3); if (to >= (uintptr_t)coverage_begin && to < (uintptr_t)coverage_end) {
coverage_table[to - (uintptr_t)coverage_begin].to_cnt++;
}
wrmsr(MSR_IA32_DEBUGCTL, MSR_IA32_DEBUGCTL_LBR + MSR_IA32_DEBUGCTL_BTF);
#else #else
printf("STUB: %s:%d", __FILE__, __LINE__); printf("STUB: %s:%d", __FILE__, __LINE__);
#endif #endif
@ -87,19 +91,12 @@ void trace_lbr_begin() {
action.sa_flags = SA_SIGINFO; action.sa_flags = SA_SIGINFO;
sigaction(SIGTRAP, &action, NULL); sigaction(SIGTRAP, &action, NULL);
wrmsr(MSR_IA32_DEBUGCTLMSR, 3); wrmsr(MSR_IA32_DEBUGCTL, MSR_IA32_DEBUGCTL_LBR + MSR_IA32_DEBUGCTL_BTF);
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");
exit(1); exit(1);
} }
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 | 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);
#else #else
printf("STUB: %s:%d", __FILE__, __LINE__); printf("STUB: %s:%d", __FILE__, __LINE__);
#endif #endif
@ -107,9 +104,8 @@ void trace_lbr_begin() {
void trace_lbr_end() { void trace_lbr_end() {
#ifndef _WIN32 #ifndef _WIN32
wrmsr(MSR_IA32_DEBUGCTLMSR, 0); wrmsr(MSR_IA32_DEBUGCTL, 0);
close(msrfd); close(msrfd);
close(covfd);
#else #else
printf("STUB: %s:%d", __FILE__, __LINE__); printf("STUB: %s:%d", __FILE__, __LINE__);
#endif #endif

View File

@ -88,12 +88,12 @@ pubsym irq_serv.irq_10, 'kos_irq_serv_irq10'
pubsym attach_int_handler, 'kos_attach_int_handler', 12 pubsym attach_int_handler, 'kos_attach_int_handler', 12
pubsym fs_execute, 'kos_fs_execute', 4 pubsym fs_execute, 'kos_fs_execute', 4
pubsym set_keyboard_data, 'kos_set_keyboard_data' pubsym set_keyboard_data, 'kos_set_keyboard_data'
pubsym KEY_COUNT as 'kos_key_count' pubsym KEY_COUNT, 'kos_key_count'
pubsym KEY_BUFF as 'kos_key_buff' pubsym KEY_BUFF, 'kos_key_buff'
pubsym keyboard_mode as 'kos_keyboard_mode' pubsym keyboard_mode, 'kos_keyboard_mode'
pubsym sys_getkey as 'kos_get_key' pubsym sys_getkey, 'kos_get_key'
pubsym syslang as 'kos_syslang' pubsym syslang, 'kos_syslang'
pubsym keyboard as 'kos_keyboard' pubsym keyboard, 'kos_keyboard'
pubsym disk_add, 16 pubsym disk_add, 16
pubsym disk_del, 4 pubsym disk_del, 4
@ -991,6 +991,18 @@ restore org,sys_msg_board,delay_ms
coverage_end: coverage_end:
section '.bss.coverage' executable writable align 64
struct coverage_branch
to_cnt DQ ?
from_cnt DQ ?
ends
COVERAGE_TABLE_SIZE = 512*1024 ; 512k should be enough for the kernel
coverage_table rb COVERAGE_TABLE_SIZE * sizeof.coverage_branch
pubsym coverage_table
section '.data.boot' writeable align 0x1000 section '.data.boot' writeable align 0x1000
BOOT boot_data BOOT boot_data
virtual at BOOT virtual at BOOT

8
umka.h
View File

@ -833,6 +833,14 @@ umka_cli(void);
void void
umka_sti(void); umka_sti(void);
#define COVERAGE_TABLE_SIZE (512*1024)
struct coverage_branch {
uint64_t to_cnt;
uint64_t from_cnt;
};
extern struct coverage_branch coverage_table[];
extern uint8_t coverage_begin[]; extern uint8_t coverage_begin[];
extern uint8_t coverage_end[]; extern uint8_t coverage_end[];

View File

@ -13,6 +13,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "optparse.h" #include "optparse.h"
#include "shell.h" #include "shell.h"
#include "umka.h" #include "umka.h"
@ -104,8 +105,15 @@ main(int argc, char **argv) {
run_test(&ctx); run_test(&ctx);
if (coverage) if (coverage) {
trace_end(); trace_end();
char coverage_filename[32];
sprintf(coverage_filename, "coverage.%i", getpid());
FILE *f = fopen(coverage_filename, "w");
fwrite(coverage_table,
COVERAGE_TABLE_SIZE * sizeof(struct coverage_branch), 1, f);
fclose(f);
}
return 0; return 0;
} }