Speed up coverage, not drastically
This commit is contained in:
parent
bf1af355fe
commit
395f75d1f7
5
makefile
5
makefile
@ -44,7 +44,7 @@ endif
|
||||
|
||||
ifeq ($(HOST),linux)
|
||||
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)
|
||||
all: umka_shell umka.sym umka.prp \
|
||||
umka.lst default.skn skin.skn
|
||||
@ -57,9 +57,6 @@ endif
|
||||
test: umka_shell
|
||||
@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 \
|
||||
lodepng.o pci.o thread.o util.o optparse.o bestline.o
|
||||
$(CC) $(LDFLAGS_32) $^ -o $@ -T umka.ld
|
||||
|
@ -67,7 +67,7 @@ else
|
||||
endif
|
||||
|
||||
collect_coverage:
|
||||
../covpreproc ../umka.lst 0x34 coverage.* > ../umka.cov
|
||||
../tools/covpreproc ../umka.lst coverage.* > ../umka.cov
|
||||
|
||||
clean:
|
||||
rm -f *.out.log *.out.png coverage.*
|
||||
|
@ -3,44 +3,33 @@
|
||||
|
||||
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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#define MAX_COVERED_CODE_SIZE (256*1024)
|
||||
#define COVERAGE_TABLE_SIZE (512*1024)
|
||||
|
||||
typedef struct {
|
||||
uint64_t to_cnt, from_cnt;
|
||||
} branch;
|
||||
struct coverage_branch {
|
||||
uint64_t to_cnt;
|
||||
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) {
|
||||
FILE *f = fopen(fname, "r");
|
||||
fseeko(f, 0, SEEK_END);
|
||||
off_t fsize = ftello(f);
|
||||
fseeko(f, 0, SEEK_SET);
|
||||
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++) {
|
||||
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++;
|
||||
}
|
||||
for (size_t i = 0; i < COVERAGE_TABLE_SIZE; i++) {
|
||||
uint64_t from, to;
|
||||
fread(&to, 1, sizeof(uint64_t), f);
|
||||
fread(&from, 1, sizeof(uint64_t), f);
|
||||
branches[i].to_cnt += to;
|
||||
branches[i].from_cnt += from;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
@ -98,19 +87,19 @@ int is_cond_jump(const char *s) {
|
||||
|| !strncmp(s, "jpe", 3)
|
||||
|| !strncmp(s, "jnp", 3)
|
||||
|| !strncmp(s, "jpo", 3)
|
||||
|| !strncmp(s, "loop", 4)
|
||||
|| !strncmp(s, "jcxz", 4)
|
||||
|| !strncmp(s, "jecxz", 5);
|
||||
return found;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 4) {
|
||||
fprintf(stderr, "usage: covpreproc <listing file> <coverage_begin offset> <coverage files ...>\n");
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "usage: covpreproc <listing file> <coverage files ...>\n");
|
||||
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]);
|
||||
}
|
||||
|
||||
@ -131,9 +120,10 @@ int main(int argc, char **argv) {
|
||||
unsigned long pos = strtoul(tmp, NULL, 16);
|
||||
size_t total_to = 0, total_from = 0;
|
||||
for (size_t i = 0; i < inst_len; i++) {
|
||||
if (pos + i < coverage_end - coverage_begin + coverage_offset) {
|
||||
total_to += branches[pos + i].to_cnt;
|
||||
total_from += branches[pos + i].from_cnt;
|
||||
if (pos + i >= coverage_begin
|
||||
&& pos + i < coverage_begin + COVERAGE_TABLE_SIZE) {
|
||||
total_to += branches[pos + i - coverage_begin].to_cnt;
|
||||
total_from += branches[pos + i - coverage_begin].from_cnt;
|
||||
}
|
||||
}
|
||||
cur += total_to;
|
||||
@ -154,7 +144,8 @@ int main(int argc, char **argv) {
|
||||
putchar('-');
|
||||
}
|
||||
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)
|
||||
putchar(' ');
|
||||
} else {
|
@ -7,7 +7,7 @@ CFLAGS=$(WARNINGS) $(NOWARNINGS) -std=c11 -O2 \
|
||||
-DNDEBUG -D_POSIX_C_SOURCE=200809L -fno-pie
|
||||
LDFLAGS=-no-pie
|
||||
|
||||
all: mkdirrange mkfilepattern lfbviewx randdir
|
||||
all: mkdirrange mkfilepattern lfbviewx randdir covpreproc
|
||||
|
||||
mkdirrange: mkdirrange.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
|
||||
@ -21,7 +21,10 @@ lfbviewx: lfbviewx.c
|
||||
randdir: randdir.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
|
||||
|
||||
covpreproc: covpreproc.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
clean:
|
||||
rm -f *.o mkdirrange mkfilepattern lfbviewx
|
||||
rm -f *.o mkdirrange mkfilepattern lfbviewx randdir covpreproc
|
||||
|
32
trace_lbr.c
32
trace_lbr.c
@ -3,7 +3,7 @@
|
||||
|
||||
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>
|
||||
*/
|
||||
|
||||
@ -18,11 +18,13 @@
|
||||
|
||||
#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_LASTBRANCHTOIP 0x1dc
|
||||
|
||||
int covfd, msrfd;
|
||||
int msrfd;
|
||||
|
||||
uint64_t rdmsr(uint32_t reg)
|
||||
{
|
||||
@ -66,13 +68,15 @@ void handle_sigtrap() {
|
||||
uint64_t from = rdmsr(MSR_IA32_LASTBRANCHFROMIP);
|
||||
uint64_t to = rdmsr(MSR_IA32_LASTBRANCHTOIP);
|
||||
|
||||
if ((from >= (uintptr_t)coverage_begin && from < (uintptr_t)coverage_end) ||
|
||||
(to >= (uintptr_t)coverage_begin && to < (uintptr_t)coverage_end)) {
|
||||
write(covfd, &from, 4);
|
||||
write(covfd, &to, 4);
|
||||
if (from >= (uintptr_t)coverage_begin && from < (uintptr_t)coverage_end) {
|
||||
coverage_table[from - (uintptr_t)coverage_begin].from_cnt++;
|
||||
}
|
||||
|
||||
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
|
||||
printf("STUB: %s:%d", __FILE__, __LINE__);
|
||||
#endif
|
||||
@ -87,19 +91,12 @@ void trace_lbr_begin() {
|
||||
action.sa_flags = SA_SIGINFO;
|
||||
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);
|
||||
if (msrfd < 0) {
|
||||
perror("rdmsr: open");
|
||||
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
|
||||
printf("STUB: %s:%d", __FILE__, __LINE__);
|
||||
#endif
|
||||
@ -107,9 +104,8 @@ void trace_lbr_begin() {
|
||||
|
||||
void trace_lbr_end() {
|
||||
#ifndef _WIN32
|
||||
wrmsr(MSR_IA32_DEBUGCTLMSR, 0);
|
||||
wrmsr(MSR_IA32_DEBUGCTL, 0);
|
||||
close(msrfd);
|
||||
close(covfd);
|
||||
#else
|
||||
printf("STUB: %s:%d", __FILE__, __LINE__);
|
||||
#endif
|
||||
|
24
umka.asm
24
umka.asm
@ -88,12 +88,12 @@ pubsym irq_serv.irq_10, 'kos_irq_serv_irq10'
|
||||
pubsym attach_int_handler, 'kos_attach_int_handler', 12
|
||||
pubsym fs_execute, 'kos_fs_execute', 4
|
||||
pubsym set_keyboard_data, 'kos_set_keyboard_data'
|
||||
pubsym KEY_COUNT as 'kos_key_count'
|
||||
pubsym KEY_BUFF as 'kos_key_buff'
|
||||
pubsym keyboard_mode as 'kos_keyboard_mode'
|
||||
pubsym sys_getkey as 'kos_get_key'
|
||||
pubsym syslang as 'kos_syslang'
|
||||
pubsym keyboard as 'kos_keyboard'
|
||||
pubsym KEY_COUNT, 'kos_key_count'
|
||||
pubsym KEY_BUFF, 'kos_key_buff'
|
||||
pubsym keyboard_mode, 'kos_keyboard_mode'
|
||||
pubsym sys_getkey, 'kos_get_key'
|
||||
pubsym syslang, 'kos_syslang'
|
||||
pubsym keyboard, 'kos_keyboard'
|
||||
|
||||
pubsym disk_add, 16
|
||||
pubsym disk_del, 4
|
||||
@ -991,6 +991,18 @@ restore org,sys_msg_board,delay_ms
|
||||
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
|
||||
BOOT boot_data
|
||||
virtual at BOOT
|
||||
|
8
umka.h
8
umka.h
@ -833,6 +833,14 @@ umka_cli(void);
|
||||
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_end[];
|
||||
|
||||
|
10
umka_shell.c
10
umka_shell.c
@ -13,6 +13,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "optparse.h"
|
||||
#include "shell.h"
|
||||
#include "umka.h"
|
||||
@ -104,8 +105,15 @@ main(int argc, char **argv) {
|
||||
|
||||
run_test(&ctx);
|
||||
|
||||
if (coverage)
|
||||
if (coverage) {
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user