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)
|
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
|
||||||
|
@ -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.*
|
||||||
|
@ -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 {
|
@ -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
|
||||||
|
32
trace_lbr.c
32
trace_lbr.c
@ -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
|
||||||
|
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 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
8
umka.h
@ -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[];
|
||||||
|
|
||||||
|
10
umka_shell.c
10
umka_shell.c
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user