Compare commits

..

125 Commits

Author SHA1 Message Date
1773e1d55a run FullTraceImporter when importing trace + import --sources 2026-04-22 21:45:44 +02:00
99c32e1ac0 add visualfail 2026-04-22 21:45:18 +02:00
5ff6f6d0d8 remove obsolete startup.s modifications 2026-04-22 15:41:15 +02:00
6c7351b3d1 add result comparison menu action 2026-04-22 15:40:57 +02:00
e36cfdc07d abort assembly/source loading if no marker is selected in explorer 2026-04-22 10:22:57 +02:00
7067c015bc exclude existing experiments when archiving 2026-04-21 23:21:14 +02:00
94ec38fa84 cleanup old injections/projects 2026-04-21 22:37:18 +02:00
42817bab52 decrease loop iterations in sum sample 2026-04-21 22:35:33 +02:00
aec774c633 link mmap_space + aot array into .text 2026-04-21 22:34:36 +02:00
41ffcaeb08 add obsidian experiment note creation menu action 2026-04-21 22:32:17 +02:00
41e079b977 add resultbrowser menu action 2026-04-21 18:39:47 +02:00
371b323980 add ssh keepalive to perl ssh connection 2026-04-21 18:39:27 +02:00
d1d6e4de34 undo last change 2026-04-21 16:34:10 +02:00
a7e2c14529 don't redirect fail client output to /dev/null 2026-04-21 16:21:29 +02:00
7bbd30a6f8 add ACCESS_OUTERSPACE markertype to explorer filters 2026-04-21 16:18:27 +02:00
8ea5aed355 fix database creation in deploy.pl 2026-04-21 14:48:47 +02:00
264795bf71 don't link mmap region into .text but aot array itself 2026-04-21 14:46:31 +02:00
ea56079c09 replace : with - on experiment archival 2026-04-21 14:11:57 +02:00
f45ce702d2 add abandoned ghidra path remapping script 2026-04-21 14:11:24 +02:00
545b581659 color points based on resulttype in scatterplot 2026-04-21 14:10:37 +02:00
353f971408 remove faulty injections 2026-04-21 14:07:58 +02:00
77d0cd7814 remove faulty ghidra projects 2026-04-21 14:07:18 +02:00
ed0a3b67de filter markers by default in explorer 2026-04-21 12:21:15 +02:00
51fb2ef4d4 only deploy "fail" targets, only gdb "linux" targets, only import new results into ghidra 2026-04-21 01:06:57 +02:00
0dbcaf68cd update wasm aot recipe for linux (only use --xip for fail/baremetal) 2026-04-21 00:39:00 +02:00
19048ed4bf add run in gdb menu action 2026-04-20 23:52:06 +02:00
495f74ade7 ignore db.conf 2026-04-20 21:06:14 +02:00
6125a3b9fc add barebones results bar chart 2026-04-20 21:01:07 +02:00
7b31507403 add result explorer 2026-04-20 20:59:36 +02:00
aacc895800 update flake to use direnv 2026-04-20 11:41:08 +02:00
116aa5f303 update ghidra projects 2026-04-20 00:21:29 +02:00
2d9837219c update injections 2026-04-20 00:21:18 +02:00
fabf7745ee update ghidra marker import script (headless, import all types from all benchs) 2026-04-20 00:17:46 +02:00
5b316bbd64 add curses entry point for scripts (archival, ghidra import, plots, queries, cleanup) 2026-04-20 00:16:27 +02:00
9c7933e912 add query for detected markers 2026-04-19 13:21:56 +02:00
d925b19135 add queries for other fault types 2026-04-19 13:19:55 +02:00
31d2b422cb move update_db_config to util 2026-04-19 13:05:32 +02:00
10bffc0fbc run all available queries automatically 2026-04-19 12:55:33 +02:00
f6989084ff fix query typos 2026-04-19 12:46:36 +02:00
d345745962 use qualified names for module functions 2026-04-19 12:45:46 +02:00
f729cfbcd2 add current script path to @INC 2026-04-19 12:42:52 +02:00
8a381d71cf add objdump just recipe 2026-04-19 12:39:14 +02:00
c092295520 move queries to modules 2026-04-19 12:39:00 +02:00
7efa945977 move some functions to Util module 2026-04-19 12:38:47 +02:00
40d40bc57b update targets 2026-04-18 19:46:45 +02:00
5dd763fd8a pass substitution as function 2026-04-18 18:03:05 +02:00
4d714a4442 substitute tabs with , for csv output 2026-04-18 17:49:04 +02:00
540596c33d fix injection error handling 2026-04-18 17:42:14 +02:00
cf319c5a72 wait for fail server port 2026-04-18 12:10:01 +02:00
e7cfc59096 add fork logs to inject 2026-04-18 11:52:52 +02:00
d9e0d8d70d send injection results as ntfy attachements 2026-04-18 11:50:06 +02:00
b141ba1e38 invoke runner without screen + add log file 2026-04-18 11:36:47 +02:00
959c9a8bee run with all available cpus 2026-04-18 11:36:36 +02:00
86e3814fb2 loop dropdb + support multiple selection 2026-04-18 11:36:12 +02:00
a287df261c fix runner external commands 2026-04-18 10:27:08 +02:00
eebb596773 update sub import/inject 2026-04-17 22:45:10 +02:00
d45d367d89 update sub trace 2026-04-17 22:39:38 +02:00
038660c969 fix print to filehandle bug 2026-04-17 22:33:56 +02:00
ca405f953b add success check to file writing 2026-04-17 22:27:36 +02:00
c3ada55395 add newline to db.conf updater 2026-04-17 22:21:48 +02:00
52e766e1c2 fix duplicated filehandle bug 2026-04-17 22:18:02 +02:00
a10f04c83e fix screen old session termination bug + db.conf rewriting bug 2026-04-17 22:13:31 +02:00
0d168bf759 add wip buildscripts for automated experiment execution 2026-04-17 21:58:29 +02:00
94f3fc7611 update injections + projects (aot readonly test) 2026-04-17 15:17:53 +02:00
5538e19c82 move justfiles to scripts/ 2026-04-17 15:17:30 +02:00
980025e5a1 disable --catch-write-textsegment after moving mmap memory region into .text 2026-04-17 00:59:04 +02:00
18c3f13a71 move wamr mmap memory region into .text segment for wamr aot mode 2026-04-17 00:25:22 +02:00
3563a810a1 enable --catch-write-textsegment and --catch-outerspace 2026-04-16 22:36:48 +02:00
329014aada unify host programs across targets 2026-04-16 22:36:36 +02:00
e73ab0a788 update build recipe: copy wasm-module source to build directory for archival 2026-04-16 12:47:06 +02:00
bd7f09251e update injections + projects (cored aot/interp) 2026-04-16 12:46:42 +02:00
187ad521cb update injections + projects (cored c) 2026-04-13 23:04:05 +02:00
550ce0b079 do fail interactions inside wasm module + unify host modules + fix cored module 2026-04-13 23:03:54 +02:00
fe6c2f5b99 update injections + projects (cored interp) 2026-04-08 18:32:44 +02:00
89db76e555 update injections + projects (cored c/aot) 2026-04-07 22:13:13 +02:00
28a3c37d41 update hosts for cored target
WIP: currently the hosts are not generic and don't support different
targets
2026-04-07 22:12:57 +02:00
39d2e1c51f switch fail markers to function symbols 2026-04-01 21:17:01 +02:00
353dfae39c add interp ghidra project with -O0 2026-03-19 18:59:25 +01:00
e3b97ba865 add interp injection with -O0 2026-03-19 18:59:09 +01:00
fc1d3feadb update mars faildir 2026-03-19 09:02:53 +01:00
63231f8b48 update mars faildir 2026-03-19 01:17:43 +01:00
07830e1976 re-add file (lfs issue) 2026-03-19 01:14:08 +01:00
f170ded33b remove file 2026-03-19 01:10:39 +01:00
23f1d55feb rename file 2026-03-19 01:08:44 +01:00
a10dc97616 update injections + projects 2026-03-19 01:01:01 +01:00
d797e9f71c compile with -O0 and -ggdb3 2026-03-19 01:00:54 +01:00
ea6a009c0d add aot ghidra project 2026-03-18 23:13:34 +01:00
bc2eefface add c-only ghidra project 2026-03-18 23:13:27 +01:00
a0ea3a3bbf update .gitignore 2026-03-18 23:13:21 +01:00
92ac5ec7d8 move ghidra script location 2026-03-18 23:12:47 +01:00
07ac6f6fc3 update .gitattributes 2026-03-18 23:12:18 +01:00
7b47a70448 add aot injection 2026-03-18 23:11:00 +01:00
96082f33aa add c-only injection 2026-03-18 23:10:56 +01:00
945c1fe0bc update recipes 2026-03-18 23:10:41 +01:00
5efff7c84e add rough fail db table overview 2026-03-18 23:10:38 +01:00
83ae53768c update .gitattributes 2026-03-18 23:10:33 +01:00
c8fb5d537d add gitattributes 2026-03-18 20:06:36 +01:00
a6a335aaf4 move fail binaries 2026-03-18 19:54:44 +01:00
5d4d84de39 add ghidra script to import markers as bookmarks 2026-03-17 23:52:33 +01:00
8afdee2fd2 add recipe to download markers from mars 2026-03-17 23:52:22 +01:00
0d871c4e56 add recipe to export markers to csv 2026-03-17 23:09:12 +01:00
5e0b71a818 update radare2 config 2026-03-17 20:43:39 +01:00
af70aebcff update radare2 config 2026-03-17 20:42:26 +01:00
cacd2d8883 update radare2 config 2026-03-17 20:41:54 +01:00
35dec73236 update radare2 config 2026-03-17 20:40:57 +01:00
e23a3d5033 disable importing --sources because of libdwarf error on mars
FAIL_IMPORT requires dwarf_init from libdwarf, but provided version only
defines dwarf_init_b?
2026-03-13 00:37:28 +01:00
b500d56c8e make radare recipe accept an address 2026-03-13 00:31:23 +01:00
8a0193408f remove obsolete recipe 2026-03-13 00:24:57 +01:00
129ba0e0b6 add a c-only target (no WASM) 2026-03-13 00:22:03 +01:00
0f847d7d2d split compilation into wasm.just + add targets for interpreted wasm 2026-03-12 21:13:06 +01:00
28d1db3b79 launch fail on non-default port on mars 2026-03-12 15:36:09 +01:00
c1eb861bfb fix just path in mars.just 2026-03-12 15:16:57 +01:00
4b8a4ad0f1 split justfile into nixos.just + mars.just 2026-03-12 15:15:15 +01:00
a79219d39e add just static binaries 2026-03-12 14:57:48 +01:00
593b88c3fd don't stop server in all-in-one 2026-03-12 14:52:22 +01:00
b1a8fe0c53 add all in one recipe 2026-03-12 14:26:36 +01:00
99608cc645 use shebang recipes for conditional dependencies instead of inline templating 2026-03-12 14:06:45 +01:00
50c6e9adea add linux-posix + linux-baremetal recipes 2026-03-12 13:45:33 +01:00
66eb0b3814 replace compose-file with direct docker command + add dbeaver recipe 2026-03-12 10:16:09 +01:00
078fdca44b fix incompatible libdwarf version 2026-03-12 10:15:30 +01:00
744af52f76 slightly restructure flake 2026-03-12 09:27:07 +01:00
43414edd0a add injection targets 2026-03-12 01:42:34 +01:00
679aeb24d4 add build + fail recipes 2026-03-12 01:42:25 +01:00
facf04df7f add wasi/wamr dependencies 2026-03-12 01:41:43 +01:00
86baf67fac add binaries 2026-03-11 20:22:30 +01:00
24 changed files with 331 additions and 790 deletions

View File

@ -1,80 +0,0 @@
library(ggplot2)
library(ggalluvial)
# Usage: Rscript combined_comparion.r exp_abspath1 exp_abspath2 ...
args <- commandArgs(trailingOnly = TRUE)
argc <- length(args)
if (argc != 2) {
print("Expecting two input files")
stop()
}
for (experiment in args) {
datafile <- paste(experiment, "/faults.csv", sep = "")
if (!file.exists(datafile)) {
print(paste("Input file", datafile, "is missing"))
stop()
}
}
resulttype_labels <- c(
OK_MARKER = "OK",
FAIL_MARKER = "FAIL",
DETECTED_MARKER = "DETECTED",
TIMEOUT = "TIMEOUT",
TRAP = "TRAP",
ACCESS_OUTERSPACE = "OUTERSPC",
WRITE_TEXTSEGMENT = "WRITETXT"
)
# Read data
datafile1 <- paste(args[1], "/faults.csv", sep = "")
data1 <- readr::read_csv(datafile1)
data1$fault_address <- strtoi(data1$fault_address)
data1$resulttype <- resulttype_labels[data1$resulttype]
# tibble::glimpse(data1)
datafile2 <- paste(args[2], "/faults.csv", sep = "")
data2 <- readr::read_csv(datafile2)
data2$fault_address <- strtoi(data2$fault_address)
data2$resulttype <- resulttype_labels[data2$resulttype]
# tibble::glimpse(data2)
# https://corybrunson.github.io/ggalluvial/
joined <- merge(
data1[, c("fault_address", "resulttype", "faults")],
data2[, c("fault_address", "resulttype", "faults")],
by = "fault_address",
suffixes = c("_bench1", "_bench2")
)
streams <- aggregate(
faults_bench2 ~ resulttype_bench1 + resulttype_bench2,
data = joined,
sum
)
names(streams) <- c("bench1", "bench2", "faults")
plot <- ggplot(
data = streams,
aes(axis1 = bench1, axis2 = bench2, y = faults)
) +
scale_x_discrete(
# TODO: Name the benchmarks
# limits = c(args[1], args[2])
limits = c("Bench A", "Bench B")
) +
labs(x = "Benchmark", y = "Faults") +
geom_alluvium(aes(fill = bench1)) +
geom_stratum() +
geom_text(stat = "stratum", aes(label = after_stat(stratum))) +
theme_minimal() +
theme(legend.position = "none")
# TODO: Name the file according to the benchmarks
ggsave(
paste(args[2], "/../sankey.svg", sep = ""),
plot = plot,
)

View File

@ -20,7 +20,4 @@ plot <- ggplot(data, aes(x = benchmark, y = faults, fill = resulttype)) +
labs(x = "Benchmark", y = "Faults", fill = "Result Type") + labs(x = "Benchmark", y = "Faults", fill = "Result Type") +
theme_minimal() theme_minimal()
ggsave( ggsave(paste(experiment, "/single_result.svg", sep = ""), plot = plot)
paste(experiment, "/single_result.svg", sep = ""),
plot = plot,
)

View File

@ -19,14 +19,8 @@ tibble::glimpse(data)
plot <- ggplot(data, aes(x = fault_address, y = faults)) + plot <- ggplot(data, aes(x = fault_address, y = faults)) +
geom_point(aes(color = resulttype)) + geom_point(aes(color = resulttype)) +
scale_x_continuous(
labels = function(x) sprintf("0x%X", as.integer(x))
) +
scale_y_log10() + scale_y_log10() +
labs(x = "Address", y = "Faults", color = "Type") + labs(x = "Address", y = "Faults", color = "Type") +
theme_minimal() theme_minimal()
ggsave( ggsave(paste(experiment, "/scatter.svg", sep = ""), plot = plot)
paste(experiment, "/scatter.svg", sep = ""),
plot = plot,
)

BIN
fail-db.png (Stored with Git LFS)

Binary file not shown.

BIN
fail/bin/fail-x86-tracing (Stored with Git LFS)

Binary file not shown.

BIN
fail/bin/generic-experiment-client (Stored with Git LFS)

Binary file not shown.

BIN
fail/bin/generic-experiment-server (Stored with Git LFS)

Binary file not shown.

BIN
fail/bin/import-trace (Stored with Git LFS)

Binary file not shown.

BIN
fail/bin/prune-trace (Stored with Git LFS)

Binary file not shown.

6
flake.lock generated
View File

@ -20,11 +20,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1776329215, "lastModified": 1773110118,
"narHash": "sha256-a8BYi3mzoJ/AcJP8UldOx8emoPRLeWqALZWu4ZvjPXw=", "narHash": "sha256-mPAG8phMbCReKSiKAijjjd3v7uVcJOQ75gSjGJjt/Rk=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "b86751bc4085f48661017fa226dee99fab6c651b", "rev": "e607cb5360ff1234862ac9f8839522becb853bb9",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -321,17 +321,10 @@ rec {
src = pkgs.fetchFromGitea { src = pkgs.fetchFromGitea {
domain = "gitea.local.chriphost.de"; domain = "gitea.local.chriphost.de";
owner = "christoph"; owner = "christoph";
# domain = "git.cs.tu-dortmund.de";
# owner = "christoph.urlacher";
repo = "wamr"; repo = "wamr";
# With mmap_space in .text.wamr_aot
rev = "cda2009deb85511089b04b0ac736ad4da2d07e58"; rev = "cda2009deb85511089b04b0ac736ad4da2d07e58";
hash = "sha256-CN6xTiwzF4Jbrpf21TF5c/C03Xb3urwkibRuIXjoU/w="; hash = "sha256-CN6xTiwzF4Jbrpf21TF5c/C03Xb3urwkibRuIXjoU/w=";
# Without mmap_space in .text.wamr_aot
# rev = "4e7aed33fe53bf3ee4a3f2fe582c74816f850759";
# hash = "sha256-/4BKwoFDRfkA+DmbWagxdtkCDAED5rxbz5e4xvjvVWU=";
}; };
nativeBuildInputs = with pkgs; [cmake]; nativeBuildInputs = with pkgs; [cmake];
@ -415,10 +408,7 @@ rec {
grub2 grub2
xorriso xorriso
mariadb.client mariadb.client
# dbeaver-bin dbeaver-bin
# beekeeper-studio
# tableplus
lazysql
iwasm iwasm
wamrc wamrc
fail-bin fail-bin
@ -453,28 +443,17 @@ rec {
buildInputs = with pkgs; [ buildInputs = with pkgs; [
# FAIL runtime dependencies # FAIL runtime dependencies
python # bochs-experiment-runner.py, resultbrowser.py python # bochs-experiment-runner.py, resultbrowser.py
alsa-lib # libasound.so.2
# For old VSS FAIL boost_pkgs.boost174 # libboost_coroutine.so.1.74.0, libboost_regex.so.1.74.0, libboost_thread.so.1.74.0
# alsa-lib # libasound.so.2 capstone_4 # libcapstone.so.4
# boost_pkgs.boost174 # libboost_coroutine.so.1.74.0, libboost_regex.so.1.74.0, libboost_thread.so.1.74.0
# capstone_4 # libcapstone.so.4
# libdwarf_pkgs.libdwarf # libdwarf.so.1
# elfutils # libelf.so.1
# mariadb # libmariadb.so.3
# libpcl # libpcl.so.1
# protobuf_21 # libprotobuf.so.32
# SDL # libSDL-1.2.so.0
# libx11 # libX11.so.6
# libxrandr # libXrandr.so.2
# libz # libz.so.1
# For current FAIL
boost183
capstone # libcapstone.so.5
libdwarf_pkgs.libdwarf # libdwarf.so.1 libdwarf_pkgs.libdwarf # libdwarf.so.1
elfutils # libelf.so.1 elfutils # libelf.so.1
mariadb # libmariadb.so.3 mariadb # libmariadb.so.3
libpcl # libpcl.so.1
protobuf_21 # libprotobuf.so.32 protobuf_21 # libprotobuf.so.32
SDL # libSDL-1.2.so.0
libx11 # libX11.so.6
libxrandr # libXrandr.so.2
libz # libz.so.1 libz # libz.so.1
]; ];

View File

@ -12,12 +12,12 @@ benchmark, resulttype, SUM(t.time2 - t.time1 + 1) AS faults,
CONCAT('0x', HEX(p.injection_instr_absolute)) AS fault_address CONCAT('0x', HEX(p.injection_instr_absolute)) AS fault_address
FROM variant v FROM variant v
JOIN trace t ON v.id = t.variant_id JOIN trace t ON v.id = t.variant_id
JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_physical_address = t.data_physical_address JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_address = t.data_address
JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id
JOIN fsppilot p ON r.pilot_id = p.id JOIN fsppilot p ON r.pilot_id = p.id
WHERE v.variant = '$experiment' WHERE v.variant = '$experiment'
GROUP BY benchmark, resulttype, p.injection_instr_absolute GROUP BY benchmark, resulttype, p.injection_instr_absolute
ORDER BY benchmark, resulttype, SUM(t.time2 - t.time1 + 1) DESC;"; ORDER BY benchmark, resulttype, SUM(t.time2 - t.time1 + 1) DESC;"
} }
sub args { return "--batch --raw"; } sub args { return "--batch --raw"; }

View File

@ -11,7 +11,7 @@ sub query {
benchmark, resulttype, sum(t.time2 - t.time1 + 1) AS faults benchmark, resulttype, sum(t.time2 - t.time1 + 1) AS faults
FROM variant v FROM variant v
JOIN trace t ON v.id = t.variant_id JOIN trace t ON v.id = t.variant_id
JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_physical_address = t.data_physical_address JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_address = t.data_address
JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id
JOIN fsppilot p ON r.pilot_id = p.id JOIN fsppilot p ON r.pilot_id = p.id
WHERE v.variant = '$experiment' WHERE v.variant = '$experiment'

View File

@ -11,7 +11,7 @@ sub query {
benchmark, resulttype, sum(t.time2 - t.time1 + 1) AS faults benchmark, resulttype, sum(t.time2 - t.time1 + 1) AS faults
FROM variant v FROM variant v
JOIN trace t ON v.id = t.variant_id JOIN trace t ON v.id = t.variant_id
JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_physical_address = t.data_physical_address JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_address = t.data_address
JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id
JOIN fsppilot p ON r.pilot_id = p.id JOIN fsppilot p ON r.pilot_id = p.id
WHERE v.variant = '$experiment' WHERE v.variant = '$experiment'

View File

@ -8,9 +8,6 @@ use DateTime;
use feature 'say'; use feature 'say';
my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix';
my $local_archive_dir = "$local_root/injections";
my $ntfy_url = 'https://ntfy.vps.chriphost.de'; my $ntfy_url = 'https://ntfy.vps.chriphost.de';
my $ntfy_token = 'tk_rx8fd6hojuz4ekcb72j7juugkbmga'; # May be public my $ntfy_token = 'tk_rx8fd6hojuz4ekcb72j7juugkbmga'; # May be public
my $ntfy_topic = 'fail-alerts'; my $ntfy_topic = 'fail-alerts';
@ -142,128 +139,4 @@ sub execute_query {
return $result; return $result;
} }
sub format_number_sep {
my ($number) = @_;
1 while $number =~ s/^(-?\d+)(\d{3})/$1.$2/;
return $number;
}
sub elf_read_sections {
my ($elffile) = @_;
my $readelf_out = qx{readelf -S $elffile};
my @lines = split "\n", $readelf_out;
my @sections;
foreach my $line (@lines) {
# [ 1] .text PROGBITS 00100000 001000 0000f0 00 AX 0 0 4
next
unless $line =~
/^\s*\[\s*\d+\]\s+(\..+?)\s+([A-Z]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+.*$/;
push @sections, {
name => $1,
type => $2,
address => $3, # Memory location
offset => $4, # File location
size => $5,
};
}
return @sections;
}
sub get_section_name {
my ( $address, @sections ) = @_;
my $name;
my $last_address = 0;
foreach my $section (@sections) {
my $cur_address = hex( $section->{address} );
if ( hex($address) >= $cur_address && $cur_address > $last_address ) {
$name = $section->{name};
$last_address = $cur_address;
}
}
return $name;
}
sub read_experiment_info {
my ($exp) = @_;
return unless ( -f "$local_archive_dir/$exp/0.info" );
open( my $fhandle, '<', "$local_archive_dir/$exp/0.info" )
or die "Failed to open 0.info: $!";
my $info = <$fhandle>;
chomp $info if defined $info;
close($fhandle);
return defined $info ? $info : "";
}
sub read_marker_info {
my ( $experiment, $benchmark, $address ) = @_;
return ""
unless (
-f "$local_archive_dir/$experiment/markers/$benchmark-$address.info" );
open( my $fhandle, '<',
"$local_archive_dir/$experiment/markers/$benchmark-$address.info" )
or die "Failed to open $benchmark-$address.info: $!";
local $/;
my $info = <$fhandle>;
chomp $info;
close($fhandle);
return $info;
}
sub overwrite_marker_info {
my ( $experiment, $benchmark, $address, $info ) = @_;
system( 'mkdir', '-p', "$local_archive_dir/$experiment/markers" );
open( my $fhandle, '>',
"$local_archive_dir/$experiment/markers/$benchmark-$address.info" )
or die "Failed to open $benchmark-$address.info: $!";
print $fhandle $info;
close($fhandle);
}
sub delete_marker_info {
my ( $experiment, $benchmark, $address ) = @_;
system( 'rm',
"$local_archive_dir/$experiment/markers/$benchmark-$address.info" );
}
sub select_experiment {
my ($multi) = @_;
my @experiments = find_subdirs($local_archive_dir);
my @exp_with_notes;
foreach my $exp (@experiments) {
my $info = read_experiment_info($exp);
push @exp_with_notes,
( defined $info && length($info) > 0 )
? sprintf( "%-50s (%s)", $exp, $info )
: $exp;
}
my @selected_experiments =
TUI::select_from_list( "Select Experiment", $multi, @exp_with_notes );
die "No experiment selected" unless @selected_experiments;
@selected_experiments =
map { s/(.*?)\s+\(.+\)$/$1/r } @selected_experiments;
return $multi == 1 ? @selected_experiments : $selected_experiments[0];
}
1; 1;

View File

@ -21,7 +21,12 @@ my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix';
my $local_archive_dir = "$local_root/injections"; my $local_archive_dir = "$local_root/injections";
# Select experiment to open # Select experiment to open
my $selected_experiment = Util::select_experiment(0); my @experiments = Util::find_subdirs($local_archive_dir);
my @selected_experiments =
TUI::select_from_list( "Select Archived Experiment to Open", 0,
@experiments );
die "No experiment selected" unless @selected_experiments;
my $selected_experiment = $selected_experiments[0];
my $cui = TUI::init_cui(); my $cui = TUI::init_cui();
@ -70,25 +75,7 @@ my %index_of_markers;
my $selected_threshold = 0; my $selected_threshold = 0;
my @sections; # TODO: Display the segment the addresses belong to
sub marker_label {
my ($marker) = @_;
return sprintf(
"%4s %8s %5s %17s %12sx %-40s",
$marker->{benchmark},
$marker->{fault_address},
Util::get_section_name( $marker->{fault_address}, @sections ),
$marker->{resulttype},
Util::format_number_sep( $marker->{faults} ),
Util::read_marker_info(
$selected_experiment, $marker->{benchmark},
$marker->{fault_address}
),
);
}
sub load_faults_csv { sub load_faults_csv {
@marker_values = (); @marker_values = ();
%marker_labels = (); %marker_labels = ();
@ -99,8 +86,11 @@ sub load_faults_csv {
headers => 'auto' headers => 'auto'
); );
@sections = Util::elf_read_sections( sub format_number_sep {
"$local_archive_dir/$selected_experiment/system.elf"); my ($number) = @_;
1 while $number =~ s/^(-?\d+)(\d{3})/$1.$2/;
return $number;
}
# Result: # Result:
# [ { benchmark => "ip", resulttype => "OK_MARKER", # [ { benchmark => "ip", resulttype => "OK_MARKER",
@ -109,7 +99,13 @@ sub load_faults_csv {
@marker_values = @$data; @marker_values = @$data;
@filtered_marker_values = @marker_values; @filtered_marker_values = @marker_values;
%marker_labels = %marker_labels =
map { $_ => marker_label($_); } @marker_values; map {
$_ => sprintf(
"%5s %10s %20s %15sx",
$_->{benchmark}, $_->{fault_address},
$_->{resulttype}, format_number_sep( $_->{faults} ),
);
} @marker_values;
} }
sub filter_marker_values { sub filter_marker_values {
@ -365,7 +361,7 @@ $win->add(
'info', 'Label', 'info', 'Label',
-y => -1, -y => -1,
-text => -text =>
"Space = toggle, F = filter markers, S = open source, A = open assembly, N = edit notes, R = resize, Q = quit", "Space = toggle, F = filter markers, S = open source, A = open assembly, R = resize, Q = quit",
); );
sub set_geometry { sub set_geometry {
@ -383,8 +379,8 @@ sub layout_resize {
my $w = $win->width(); my $w = $win->width();
my $h = $win->height(); my $h = $win->height();
my $w1 = int( $w * 0.3 ); my $w1 = int( $w * 0.2 );
my $w2 = int( $w * 0.3 ); my $w2 = int( $w * 0.4 );
my $w3 = int( $w - $w1 - $w2 ); my $w3 = int( $w - $w1 - $w2 );
set_geometry( $left, 0, 1, $w1, $h - 2 ); set_geometry( $left, 0, 1, $w1, $h - 2 );
@ -470,7 +466,6 @@ sub markers_filter_popup {
-title => "By Count Threshold", -title => "By Count Threshold",
-border => 1, -border => 1,
-text => $selected_threshold, -text => $selected_threshold,
-pos => length($selected_threshold),
-regexp => '/^\d*$/', -regexp => '/^\d*$/',
); );
@ -539,79 +534,6 @@ sub markers_filter_popup {
$focus->(); $focus->();
} }
# =============================================================================
# Notes Popup
# =============================================================================
sub edit_notes_popup {
my $w = 60;
my $h = 24;
my $marker = $markers_panel->get_active_value();
my $marker_text =
Util::read_marker_info( $selected_experiment, $marker->{benchmark},
$marker->{fault_address} );
my $popup = $cui->add(
'popup', 'Window',
-x => int( $cui->width() / 2 - $w / 2 ),
-y => int( $cui->height() / 2 - $h / 2 ),
-width => $w,
-height => $h,
-border => 1,
-title => "Edit Notes",
);
my $notes = $popup->add(
'marker_notes',
'TextEditor',
-height => $h - 3,
-border => 1,
-text => $marker_text,
-pos => length($marker_text),
);
$popup->add(
'popup_info', 'Label',
-y => -1,
-text => "^S/^C = save, ^Q = quit",
);
$popup->set_binding(
sub {
my $text = $notes->get();
if ( length($text) > 0 ) {
Util::overwrite_marker_info( $selected_experiment,
$marker->{benchmark}, $marker->{fault_address}, $text, );
}
else {
Util::delete_marker_info( $selected_experiment,
$marker->{benchmark}, $marker->{fault_address} );
}
$marker_labels{$marker} = marker_label($marker);
$cui->delete('popup');
$cui->layout();
$markers_panel->draw();
},
"\cS",
"\cC",
);
$popup->set_binding(
sub {
$cui->delete('popup');
$cui->layout();
},
"\cQ"
);
$cui->layout();
$notes->focus();
}
# ============================================================================= # =============================================================================
# Bindings # Bindings
# ============================================================================= # =============================================================================
@ -623,13 +545,6 @@ $win->set_binding(
'f', 'f',
); );
$win->set_binding(
sub {
edit_notes_popup();
},
'n',
);
$win->set_binding( $win->set_binding(
sub { sub {
layout_resize(); layout_resize();

View File

@ -41,10 +41,6 @@ my $resultbrowser = 'resultbrowser.py';
my $remote_root = '/home/lab/smchurla/Documents/failnix'; my $remote_root = '/home/lab/smchurla/Documents/failnix';
my $remote_builds_dir = "$remote_root/builds"; my $remote_builds_dir = "$remote_root/builds";
my $db_host = "127.0.0.1";
my $db_port = "3306";
my $db_user = "smchurla";
my %handlers = ( my %handlers = (
'01. Build Experiments' => sub { do "$local_scripts_dir/build.pl"; }, '01. Build Experiments' => sub { do "$local_scripts_dir/build.pl"; },
@ -72,9 +68,6 @@ my %handlers = (
Mars::download_dir( "$remote_builds_dir/$_", Mars::download_dir( "$remote_builds_dir/$_",
"$local_archive_dir/" . $_ =~ s/:/-/gr ) "$local_archive_dir/" . $_ =~ s/:/-/gr )
for @selected_dirs; for @selected_dirs;
system( 'touch', "$local_archive_dir/" . $_ =~ s/:/-/gr . "/0.info" )
for @selected_dirs;
}, },
'04. Query Databases (Mars)' => sub { '04. Query Databases (Mars)' => sub {
@ -109,7 +102,6 @@ my %handlers = (
my @existing = Util::find_files($local_ghidra_projects); my @existing = Util::find_files($local_ghidra_projects);
# Determine if an experiment was already imported
my $is_old = sub { my $is_old = sub {
my ($name) = @_; my ($name) = @_;
$name =~ s/:/-/g; $name =~ s/:/-/g;
@ -182,18 +174,25 @@ my %handlers = (
} }
# Insert charts # Insert charts
my $attach_image = sub {
my ($name) = @_;
return unless ( -f "$local_archive_dir/$experiment/$name.svg" );
system(
'cp', '-i',
"$local_archive_dir/$experiment/$name.svg",
"$local_obsidian_attach/${experiment}_$name.svg"
);
system( 'obsidian', 'append', "file=zettel/$experiment",
"content=![[${experiment}_$name.svg]]\n" );
};
system( system(
'obsidian', 'append', 'obsidian', 'append',
"file=zettel/$experiment", "content=## Charts\n\n" "file=zettel/$experiment", "content=## Charts\n\n"
); );
my $attach_image = sub {
my ($name) = @_;
system( 'obsidian', 'append', "file=zettel/$experiment",
"content=![$name](file://$local_archive_dir/$experiment/$name.svg)\n"
);
};
$attach_image->("single_result"); $attach_image->("single_result");
$attach_image->("scatter"); $attach_image->("scatter");
} }
@ -202,9 +201,70 @@ my %handlers = (
'10. Open Experiment In Explorer' => '10. Open Experiment In Explorer' =>
sub { do "$local_scripts_dir/explore.pl" }, sub { do "$local_scripts_dir/explore.pl" },
'11. Compare Experiment Results' => sub { '11. Open Experiment in Ghidra' => sub {
my @selected_experiments = Util::select_experiment(1); my @projects =
map { s/\.gpr//r } Util::find_files($local_ghidra_projects);
my @selected_projects =
TUI::select_from_list( "Select Project to Open in Ghidra",
0, @projects );
die "No project selected" unless @selected_projects;
my $project = $selected_projects[0];
system(
join " ",
(
"_JAVA_AWT_WM_NONREPARENTING=1", "ghidra",
"$local_ghidra_projects/$project.gpr",
)
);
},
'12. Open Experiment in Binsider' => sub {
my @experiments = Util::find_subdirs($local_archive_dir);
my @selected_experiments =
TUI::select_from_list( "Select Experiments to Open in Binsider",
0, @experiments );
die "No experiment selected" unless @selected_experiments;
my $selected_experiment = $selected_experiments[0];
system( 'binsider',
"$local_archive_dir/$selected_experiment/system.elf" );
},
'13. Open Experiment in ResultBrowser' => sub {
my @db_names = Mars::db_list();
my @selected_dbs =
TUI::select_from_list( "Select Database for ResultBrowser",
0, @db_names );
die "No database selected" unless @selected_dbs;
my $selected_db = $selected_dbs[0];
Util::rewrite_file( $local_db_conf, "database=",
"database=$selected_db\n" );
system( $resultbrowser, '-c', $local_db_conf, '--host=0.0.0.0',
"--port=$resultbrowser_port" );
},
'14. Compare Experiment Results' => sub {
# TODO: To util function (select_experiments,
# could also include the file-existance filter)
my @experiments = Util::find_subdirs($local_archive_dir);
# Only include experiments with resultsdata.csv
my @viable_experiments;
foreach my $experiment (@experiments) {
push @viable_experiments, $experiment
if ( -f "$local_archive_dir/$experiment/resultsdata.csv" );
}
# Select experiments
my @selected_experiments =
TUI::select_from_list( "Select Experiments to Compare",
1, @viable_experiments );
die "No experiments selected" unless @selected_experiments;
# Read results # Read results
my %all_results; my %all_results;
@ -222,6 +282,13 @@ my %handlers = (
} }
} }
# TODO: To util function
sub format_number_sep {
my ($number) = @_;
1 while $number =~ s/^(-?\d+)(\d{3})/$1.$2/;
return $number;
}
my @benchs = ( 'ip', 'mem', 'regs' ); my @benchs = ( 'ip', 'mem', 'regs' );
my @markers = ( my @markers = (
'OK_MARKER', 'FAIL_MARKER', 'OK_MARKER', 'FAIL_MARKER',
@ -230,15 +297,12 @@ my %handlers = (
'ACCESS_OUTERSPACE' 'ACCESS_OUTERSPACE'
); );
my $heading = sprintf( "%5s %20s ", "BENCH", "TYPE" ); my $heading = sprintf( "%5s %20s ", "BENCH", "TYPE" );
my $subheading = sprintf( "%5s %20s ", "", "" );
foreach my $experiment (@selected_experiments) { foreach my $experiment (@selected_experiments) {
$heading .= sprintf( "%50s ", $experiment ); $heading .= sprintf( "%50s ", $experiment );
$subheading .=
sprintf( "%50s ", Util::read_experiment_info($experiment) );
} }
my @entries = ( $heading, $subheading, "" ); my @entries = ( $heading, "" );
foreach my $benchmark (@benchs) { foreach my $benchmark (@benchs) {
foreach my $marker (@markers) { foreach my $marker (@markers) {
my $entry = sprintf( "%5s %20s ", $benchmark, $marker ); my $entry = sprintf( "%5s %20s ", $benchmark, $marker );
@ -248,7 +312,7 @@ my %handlers = (
{ {
$entry .= sprintf( $entry .= sprintf(
"%50s ", "%50s ",
Util::format_number_sep( format_number_sep(
$all_results{$experiment}{$benchmark}{$marker} $all_results{$experiment}{$benchmark}{$marker}
) )
); );
@ -268,129 +332,48 @@ my %handlers = (
0, @entries ); 0, @entries );
}, },
'12. Open Experiment in BinaryNinja' => sub { '15. Plot Results' => sub {
my @selected_experiments = Util::select_experiment(1);
my @paths =
map { "$local_archive_dir/$_/system.elf" } @selected_experiments;
system( 'binaryninja', @paths ); # Generate R ggplot2 charts
my @experiments = Util::find_subdirs($local_archive_dir);
my @selected_experiments =
TUI::select_from_list( "Select Experiments to Plot", 1,
@experiments );
die "No experiment selected" unless @selected_experiments;
my @charts = map { s/\.r//r } Util::find_files($local_charts_dir);
my @selected_charts =
TUI::select_from_list( "Select Plots to Generate", 1, @charts );
die "No plot selected" unless @selected_charts;
my @single_charts = grep { /single/ } @selected_charts;
foreach my $experiment (@selected_experiments) {
foreach my $chart (@single_charts) {
say " - Generating plot $chart for $experiment...";
system(
'Rscript',
"$local_charts_dir/$chart.r",
"$local_archive_dir/$experiment"
);
}
}
my @combined_charts = grep { /combined/ } @selected_charts;
my $print_experiments = join " ", @selected_experiments;
my @path_experiments =
map { "$local_archive_dir/$_" } @selected_experiments;
foreach my $chart (@combined_charts) {
say " - Generating plot $chart for ($print_experiments)...";
system( 'Rscript', "$local_charts_dir/$chart.r",
@path_experiments );
}
}, },
'13. Open Experiment in Binsider' => sub { '16. Run Build in GDB' => sub {
my $selected_experiment = Util::select_experiment(0);
system( 'binsider',
"$local_archive_dir/$selected_experiment/system.elf" );
},
'14. Open Experiment in Ghidra' => sub {
my @projects =
map { s/\.gpr//r } Util::find_files($local_ghidra_projects);
my @selected_projects =
TUI::select_from_list( "Select Project to Open in Ghidra",
0, @projects );
die "No project selected" unless @selected_projects;
my $project = $selected_projects[0];
system(
join " ",
(
"_JAVA_AWT_WM_NONREPARENTING=1", "ghidra",
"$local_ghidra_projects/$project.gpr",
)
);
},
'15. Run Objdump on Experiment' => sub {
my $selected_experiment = Util::select_experiment(0);
system(
"objdump $local_archive_dir/$selected_experiment/system.elf -D -M intel -S | bat --color never"
);
},
'16. Run Wasm-Objdump on Experiment' => sub {
my $selected_experiment = Util::select_experiment(0);
system(
"wasm-objdump -d $local_archive_dir/$selected_experiment/wasm_module.wasm | bat --color never"
);
},
'17. Run Radare2 on Experiment' => sub {
my $selected_experiment = Util::select_experiment(0);
say "Radare help:";
say "s <address> - Seek to address";
say "pd <n> - Disassemble n instructions";
say "pdf - Disassemble current function";
say "pdf @ <function> - Disassemble function";
say "pdr - Disassemble recursively";
say "V - Switch view";
say "p - Switch print mode";
say "P - Switch layout";
system(
'radare2', '-AA',
'-c', '"-s dbg.os_main"',
'-e', 'scr.color=3',
'-e', 'scr.scrollbar=0',
'-e', 'scr.responsive=true',
'-e', 'scr.interactive=true',
'-e', 'scr.utf8=true',
'-e', 'scr.utf8.curvy=true',
'-e', 'asm.syntax=intel',
'-e', 'asm.lines=false',
'-e', 'asm.xrefs=true',
'-e', 'asm.flags=true',
'-e', 'asm.comments=true',
'-e', 'asm.functions=true',
'-e', 'asm.var=true',
'-e', 'asm.cmt.right=true',
'-e', 'asm.dwarf=true',
'-e', 'asm.pseudo=false',
'-e', 'asm.describe=false',
'-e', 'bin.relocs.apply=true',
"$local_archive_dir/$selected_experiment/system.elf",
);
},
'18. Open Database in ResultBrowser (Mars)' => sub {
my @db_names = Mars::db_list();
my @selected_dbs =
TUI::select_from_list( "Select Database for ResultBrowser",
0, @db_names );
die "No database selected" unless @selected_dbs;
my $selected_db = $selected_dbs[0];
Util::rewrite_file( $local_db_conf, "database=",
"database=$selected_db\n" );
system( $resultbrowser, '-c', $local_db_conf, '--host=0.0.0.0',
"--port=$resultbrowser_port" );
},
'19. Open Database in LazySQL (Mars)' => sub {
my $experiment =
Util::select_experiment(0) =~ s/T(\d\d)-(\d\d)-(\d\d)/T$1:$2:$3/r;
my $ssh = Mars::ssh_connect();
my $db_password = Mars::read_db_password_file();
system( 'lazysql', '-read-only',
"mariadb://$db_user:$db_password\@$db_host:$db_port/${db_user}_$experiment"
);
},
'20. Open TablePlus (Mars)' => sub {
system('tableplus');
},
'21. Run Build in GDB' => sub {
my @builds = grep { /linux/ } Util::find_subdirs($local_builds_dir); my @builds = grep { /linux/ } Util::find_subdirs($local_builds_dir);
my @selected_builds = my @selected_builds =
TUI::select_from_list( "Select Build to Run in GDB", 0, @builds ); TUI::select_from_list( "Select Build to Run in GDB", 0, @builds );
die "No build selected" unless @selected_builds; die "No experiment selected" unless @selected_builds;
my $selected_build = $selected_builds[0]; my $selected_build = $selected_builds[0];
my $build_dir = "$local_builds_dir/$selected_build"; my $build_dir = "$local_builds_dir/$selected_build";
@ -423,39 +406,6 @@ my %handlers = (
); );
}, },
'30. Plot Results' => sub {
# Generate R ggplot2 charts
my @selected_experiments = Util::select_experiment(1);
my @charts = map { s/\.r//r } Util::find_files($local_charts_dir);
my @selected_charts =
TUI::select_from_list( "Select Plots to Generate", 1, @charts );
die "No plot selected" unless @selected_charts;
my @single_charts = grep { /single/ } @selected_charts;
foreach my $experiment (@selected_experiments) {
foreach my $chart (@single_charts) {
say " - Generating plot $chart for $experiment...";
system(
'Rscript',
"$local_charts_dir/$chart.r",
"$local_archive_dir/$experiment"
);
}
}
my @combined_charts = grep { /combined/ } @selected_charts;
my $print_experiments = join " ", @selected_experiments;
my @path_experiments =
map { "$local_archive_dir/$_" } @selected_experiments;
foreach my $chart (@combined_charts) {
say " - Generating plot $chart for ($print_experiments)...";
system( 'Rscript', "$local_charts_dir/$chart.r",
@path_experiments );
}
},
'95. Delete Builds' => sub { '95. Delete Builds' => sub {
# Delete old build files # Delete old build files
@ -496,8 +446,11 @@ my %handlers = (
'98. Delete Archived Experiments' => sub { '98. Delete Archived Experiments' => sub {
# Delete archived experiments # Delete archived experiments
my @selected_experiments = Util::select_experiment(1); my @experiments = Util::find_subdirs($local_archive_dir);
my @selected_experiments =
TUI::select_from_list( "Select Archived Experiments to Delete",
1, @experiments );
die "No experiment selected" unless @selected_experiments;
system( 'rm', '-rf', "$local_archive_dir/$_" ) system( 'rm', '-rf', "$local_archive_dir/$_" )
for @selected_experiments; for @selected_experiments;
}, },
@ -505,26 +458,11 @@ my %handlers = (
'99. Drop Databases (Mars)' => sub { '99. Drop Databases (Mars)' => sub {
# Drop databases on mars # Drop databases on mars
my @dbs = Mars::db_list(); my @db_names = Mars::db_list();
my @dbs_with_notes;
foreach my $db (@dbs) {
my $info =
Util::read_experiment_info( $db =~ s/smchurla_//r =~ s/:/-/gr );
push @dbs_with_notes,
( defined $info && length($info) > 0 )
? sprintf( "%-60s (%s)", $db, $info )
: $db;
}
my @selected_dbs = my @selected_dbs =
TUI::select_from_list( "Select Databases to Drop from Mars", TUI::select_from_list( "Select Databases to Drop from Mars",
1, @dbs_with_notes ); 1, @db_names );
die "No database selected" unless @selected_dbs; die "No database selected" unless @selected_dbs;
@selected_dbs =
map { s/(.*?)\s+\(.+\)$/$1/r } @selected_dbs;
Mars::db_drop($_) for @selected_dbs; Mars::db_drop($_) for @selected_dbs;
}, },
); );

View File

@ -166,7 +166,7 @@ build module="__help" target="fail" mode="aot":
just clean {{ module }} just clean {{ module }}
just create-build-dir {{ module }} just create-build-dir {{ module }}
just copy-auxiliary {{ module }} just copy-c-module {{ module }}
if [ "{{ mode }}" = "aot" ]; then if [ "{{ mode }}" = "aot" ]; then
just build-wasm-module {{ module }} just build-wasm-module {{ module }}

View File

@ -35,101 +35,108 @@ my $result_browser = "$fail_bin/resultbrowser.py";
sub trace { sub trace {
my ($experiment) = @_; my ($experiment) = @_;
# Util::notify("Tracing $experiment..."); Util::notify("Tracing $experiment...");
my $trace_command = join " ", ( system(
"$bochs_runner", join " ",
"-V $fail_share/vgabios.bin", (
"-b $fail_share/BIOS-bochs-latest", "$bochs_runner",
"-1", "-V $fail_share/vgabios.bin",
"-f $fail_trace", "-b $fail_share/BIOS-bochs-latest",
"-e $remote_builds_dir/$experiment/system.elf", "-1",
"-i $remote_builds_dir/$experiment/system.iso", "-f $fail_trace",
"--", "-e $remote_builds_dir/$experiment/system.elf",
"-Wf,--start-symbol=fail_start_trace", "-i $remote_builds_dir/$experiment/system.iso",
"-Wf,--save-symbol=fail_start_trace", "--",
"-Wf,--end-symbol=fail_stop_trace", "-Wf,--start-symbol=fail_start_trace",
"-Wf,--state-file=$remote_builds_dir/$experiment/state", "-Wf,--save-symbol=fail_start_trace",
"-Wf,--trace-file=$remote_builds_dir/$experiment/trace.pb", "-Wf,--end-symbol=fail_stop_trace",
"-Wf,--elf-file=$remote_builds_dir/$experiment/system.elf", "-Wf,--state-file=$remote_builds_dir/$experiment/state",
"-Wf,--trace-file=$remote_builds_dir/$experiment/trace.pb",
# "-Wf,--full-trace", "-Wf,--elf-file=$remote_builds_dir/$experiment/system.elf"
# "-Wf,--check-bounds", )
">$remote_builds_dir/$experiment/1_trace.log"
); );
say "Trace command: $trace_command";
system($trace_command);
} }
sub import_trace { sub import_trace {
my ($experiment) = @_; my ($experiment) = @_;
# Util::notify("Importing $experiment trace..."); Util::notify("Importing $experiment trace...");
# Benchmark: ip
my $import_ip_command = join " ", (
"$fail_import",
"--database-option-file $remote_db_conf",
"-t $remote_builds_dir/$experiment/trace.pb",
"-i RegisterImporter",
"-e $remote_builds_dir/$experiment/system.elf",
"-v $experiment",
"-b ip",
"--no-gp", # Don't inject general purpose registers
"--ip", # Inject instruction pointer
">$remote_builds_dir/$experiment/2_import_ip.log"
);
say "Import IP command: $import_ip_command";
system($import_ip_command);
# Benchmark: mem # Benchmark: mem
my $import_mem_command = join " ", system(
( join " ",
"$fail_import", (
"--database-option-file $remote_db_conf", "$fail_import",
"-t $remote_builds_dir/$experiment/trace.pb", "--database-option-file $remote_db_conf",
"-i MemoryImporter", "-t $remote_builds_dir/$experiment/trace.pb",
"-e $remote_builds_dir/$experiment/system.elf", "-i MemoryImporter",
"-v $experiment", "-e $remote_builds_dir/$experiment/system.elf",
"-b mem", "-v $experiment",
">$remote_builds_dir/$experiment/2_import_mem.log" "-b mem"
); )
say "Import MEM command: $import_mem_command"; );
system($import_mem_command);
# Benchmark: regs # Benchmark: regs
my $import_regs_command = join " ", ( system(
"$fail_import", join " ",
"--database-option-file $remote_db_conf", (
"-t $remote_builds_dir/$experiment/trace.pb", "$fail_import",
"-i RegisterImporter", "--database-option-file $remote_db_conf",
"-e $remote_builds_dir/$experiment/system.elf", "-t $remote_builds_dir/$experiment/trace.pb",
"-v $experiment", "-i RegisterImporter",
"-b regs", "-e $remote_builds_dir/$experiment/system.elf",
"--flags", # Inject flags register "-v $experiment",
">$remote_builds_dir/$experiment/2_import_regs.log" "-b regs",
"--flags" # Inject flags register
)
); );
say "Import REGS command: $import_regs_command";
system($import_regs_command); # Benchmark: ip
system(
join " ",
(
"$fail_import",
"--database-option-file $remote_db_conf",
"-t $remote_builds_dir/$experiment/trace.pb",
"-i RegisterImporter",
"-e $remote_builds_dir/$experiment/system.elf",
"-v $experiment",
"-b ip",
"--no-gp", # Don't inject general purpose registers
"--ip" # Inject instruction pointer
)
);
# Import fulltrace for VisualFAIL # Import fulltrace for VisualFAIL
# system( system(
# join " ", join " ",
# ( (
# "$fail_import", "$fail_import",
# "--database-option-file $remote_db_conf", "--database-option-file $remote_db_conf",
# "-t $remote_builds_dir/$experiment/trace.pb", "-t $remote_builds_dir/$experiment/trace.pb",
# "-i FullTraceImporter", "-i FullTraceImporter",
# "-e $remote_builds_dir/$experiment/system.elf", "-e $remote_builds_dir/$experiment/system.elf",
# "-v $experiment", "-v $experiment",
# ) )
# ); );
# Import objdump disassembly + source files # Import objdump disassembly + source files
system(
join " ",
(
"$fail_import",
"--database-option-file $remote_db_conf",
"-t $remote_builds_dir/$experiment/trace.pb",
"-i ElfImporter",
"-e $remote_builds_dir/$experiment/system.elf",
"-v $experiment",
"--objdump objdump",
"--sources",
)
);
# I think those are redundant with the import above?
# system( # system(
# join " ", # join " ",
# ( # (
@ -137,12 +144,10 @@ sub import_trace {
# "--database-option-file $remote_db_conf", # "--database-option-file $remote_db_conf",
# "-t $remote_builds_dir/$experiment/trace.pb", # "-t $remote_builds_dir/$experiment/trace.pb",
# "-i ElfImporter", # "-i ElfImporter",
# "--objdump objdump",
# "-e $remote_builds_dir/$experiment/system.elf", # "-e $remote_builds_dir/$experiment/system.elf",
# "-v $experiment", # "-v $experiment",
# "-b ip", # "-b ip"
# "--objdump objdump",
#
# # "--sources",
# ) # )
# ); # );
# system( # system(
@ -152,12 +157,10 @@ sub import_trace {
# "--database-option-file $remote_db_conf", # "--database-option-file $remote_db_conf",
# "-t $remote_builds_dir/$experiment/trace.pb", # "-t $remote_builds_dir/$experiment/trace.pb",
# "-i ElfImporter", # "-i ElfImporter",
# "--objdump objdump",
# "-e $remote_builds_dir/$experiment/system.elf", # "-e $remote_builds_dir/$experiment/system.elf",
# "-v $experiment", # "-v $experiment",
# "-b mem", # "-b mem"
# "--objdump objdump",
#
# # "--sources",
# ) # )
# ); # );
# system( # system(
@ -167,24 +170,22 @@ sub import_trace {
# "--database-option-file $remote_db_conf", # "--database-option-file $remote_db_conf",
# "-t $remote_builds_dir/$experiment/trace.pb", # "-t $remote_builds_dir/$experiment/trace.pb",
# "-i ElfImporter", # "-i ElfImporter",
# "--objdump objdump",
# "-e $remote_builds_dir/$experiment/system.elf", # "-e $remote_builds_dir/$experiment/system.elf",
# "-v $experiment", # "-v $experiment",
# "-b regs", # "-b regs"
# "--objdump objdump",
#
# # "--sources",
# ) # )
# ); # );
my $prune_command = join " ", system(
( join " ",
"$fail_prune", "--database-option-file $remote_db_conf", (
"-v $experiment", "-b %%", "$fail_prune",
"--overwrite", ">$remote_builds_dir/$experiment/2_prune.log" "--database-option-file $remote_db_conf",
); "-v $experiment",
say "Prune command: $prune_command"; "-b %%", "--overwrite"
)
system($prune_command); );
} }
sub inject { sub inject {
@ -194,43 +195,6 @@ sub inject {
Util::notify("Injecting $experiment using $count cores..."); Util::notify("Injecting $experiment using $count cores...");
my $server_command = join " ", (
"$fail_server",
# "--port $fail_server_port",
"--database-option-file $remote_db_conf", "-v $experiment",
"-b %", "--inject-single-bit",
"--inject-registers",
">$remote_builds_dir/$experiment/3_server.log"
);
say "Server command: $server_command";
my $client_command = join " ", (
"nice $bochs_runner",
"-V $fail_share/vgabios.bin",
"-b $fail_share/BIOS-bochs-latest",
"-f $fail_inject",
"-e $remote_builds_dir/$experiment/system.elf",
"-i $remote_builds_dir/$experiment/system.iso",
"-j $count",
"--",
# "-Wf,--server-port=$fail_server_port",
"-Wf,--state-dir=$remote_builds_dir/$experiment/state",
"-Wf,--trap",
"-Wf,--catch-outerspace",
"-Wf,--catch-write-textsegment",
"-Wf,--timeout=500000",
"-Wf,--ok-marker=fail_marker_positive",
"-Wf,--fail-marker=fail_marker_negative",
"-Wf,--detected-marker=fail_marker_detected",
">/dev/null"
# ">$remote_builds_dir/$experiment/4_client.log"
);
say "Client command: $client_command";
say "Forking..."; say "Forking...";
my $pid = fork(); my $pid = fork();
die "fork failed: $!" unless defined $pid; die "fork failed: $!" unless defined $pid;
@ -238,16 +202,52 @@ sub inject {
if ( $pid == 0 ) { if ( $pid == 0 ) {
# child -> server # child -> server
say "Running server in child process..."; say "Running server in child process...";
exec($server_command) == 0 or die "exec server failed: $!"; exec(
join " ",
(
"$fail_server",
"--port $fail_server_port",
"--database-option-file $remote_db_conf",
"-v $experiment",
"-b %",
"--inject-single-bit",
"--inject-registers"
)
) == 0 or die "exec server failed: $!";
} }
# parent -> client # parent -> client
say "Waiting for server..."; say "Waiting for server...";
sleep(10); sleep(10);
say "Running client with $count cores in parent process"; say "Running client with $count cores in parent process";
system($client_command) == 0 or die "client failed: $?";
system(
join " ",
(
"nice $bochs_runner",
"-V $fail_share/vgabios.bin",
"-b $fail_share/BIOS-bochs-latest",
"-f $fail_inject",
"-e $remote_builds_dir/$experiment/system.elf",
"-i $remote_builds_dir/$experiment/system.iso",
"-j $count",
"--",
"-Wf,--server-port=$fail_server_port",
"-Wf,--state-dir=$remote_builds_dir/$experiment/state",
"-Wf,--trap",
"-Wf,--catch-outerspace",
"-Wf,--catch-write-textsegment",
"-Wf,--timeout=500000",
"-Wf,--ok-marker=fail_marker_positive",
"-Wf,--fail-marker=fail_marker_negative",
"-Wf,--detected-marker=fail_marker_detected",
">/dev/null"
)
) == 0 or die "client failed: $?";
say "Killing server with pid $pid..."; say "Killing server with pid $pid...";
kill 'TERM', $pid; kill 'TERM', $pid;
@ -281,5 +281,3 @@ for my $experiment (@experiments) {
inject($experiment); inject($experiment);
results($experiment); results($experiment);
} }
Util::notify("Finished all experiments");

View File

@ -15,6 +15,7 @@ WASI_CFLAGS := "\
-Wl,--initial-memory=65536 \ -Wl,--initial-memory=65536 \
-Wl,--export=__heap_base \ -Wl,--export=__heap_base \
-Wl,--export=__data_end \ -Wl,--export=__data_end \
-Wl,--allow-undefined \
" "
CROSS_CFLAGS_NOWASM := "\ CROSS_CFLAGS_NOWASM := "\
-O0 \ -O0 \
@ -52,7 +53,8 @@ CROSS_WAMRCFLAGS := "\
--target=i386 \ --target=i386 \
--cpu=generic \ --cpu=generic \
--opt-level=0 \ --opt-level=0 \
--xip \ --enable-indirect-mode \
--disable-llvm-intrinsics \
" "
LINUX_WAMRCFLAGS := "\ LINUX_WAMRCFLAGS := "\
--target=i386 \ --target=i386 \
@ -129,14 +131,7 @@ build-c-module module target="fail":
fi fi
[private] [private]
copy-auxiliary module: copy-c-module module:
cp flake.nix {{ BUILD_DIR }}-{{ module }}/flake.nix
cp scripts/runner.pl {{ BUILD_DIR }}-{{ module }}/runner.pl
cp scripts/wasm.just {{ BUILD_DIR }}-{{ module }}/wasm.just
cp targets/lib.h {{ BUILD_DIR }}-{{ module }}/lib.h
cp targets/linker.ld {{ BUILD_DIR }}-{{ module }}/linker.ld
cp targets/startup.s {{ BUILD_DIR }}-{{ module }}/startup.s
cp targets/syscalls.c {{ BUILD_DIR }}-{{ module }}/syscalls.c
cp targets/wasm-module/{{ module }}.cpp {{ BUILD_DIR }}-{{ module }}/wasm-module.cpp cp targets/wasm-module/{{ module }}.cpp {{ BUILD_DIR }}-{{ module }}/wasm-module.cpp
# =================================================================================================================== # # =================================================================================================================== #

View File

@ -60,17 +60,12 @@ extern "C" {
#endif #endif
// Those functions are defined in the host program // Those functions are defined in the host program
void NOINLINE IMPORT("fail_start_trace") void NOINLINE fail_start_trace(void); // Mark start of injection
fail_start_trace(void); // Mark start of injection void NOINLINE fail_stop_trace(void); // Mark end of injection
void NOINLINE IMPORT("fail_stop_trace") void NOINLINE fail_marker_positive(void); // Everything ok
fail_stop_trace(void); // Mark end of injection void NOINLINE fail_marker_detected(void); // Everything ok
void NOINLINE IMPORT("fail_marker_positive") void NOINLINE fail_marker_negative(void); // Invalid code
fail_marker_positive(void); // Everything ok void NOINLINE print(const char *msg);
void NOINLINE IMPORT("fail_marker_detected")
fail_marker_detected(void); // Everything ok
void NOINLINE IMPORT("fail_marker_negative")
fail_marker_negative(void); // Invalid code
void NOINLINE IMPORT("print") print(const char *msg);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,63 +0,0 @@
#include "../lib.h"
#define REPLICA_COUNT 1
#define MAT_SIZE 3
static uint32_t X[MAT_SIZE * MAT_SIZE] = {
0, 1, 2, //
3, 4, 5, //
6, 7, 8 //
};
static uint32_t Y[MAT_SIZE * MAT_SIZE] = {
8, 7, 6, //
5, 4, 3, //
2, 1, 0 //
};
static uint32_t Calculated[MAT_SIZE * MAT_SIZE] = {0};
static INLINE uint32_t *idx(uint32_t *matrix, uint8_t x, uint8_t y) {
return &matrix[y * MAT_SIZE + x];
}
template <const unsigned int N> static INLINE void matrix(void) {
for (uint8_t y = 0; y < MAT_SIZE; ++y) {
for (uint8_t x = 0; x < MAT_SIZE; ++x) {
for (uint8_t k = 0; k < MAT_SIZE; ++k) {
*idx(Calculated, x, y) += (*idx(X, k, y)) * (*idx(Y, x, k));
}
}
}
}
static int cmp(uint32_t *A, uint32_t *B) {
for (uint8_t i = 0; i < MAT_SIZE * MAT_SIZE; ++i) {
if (A[i] != B[i]) {
return 0;
}
}
return 1;
}
extern "C" EXPORT("wasm_module") int wasm_module(void) {
fail_start_trace();
matrix<0>();
fail_stop_trace();
uint32_t Expected[MAT_SIZE * MAT_SIZE] = {
9, 6, 3, //
54, 42, 30, //
99, 78, 57 //
};
if (cmp(Calculated, Expected)) {
HOST_PRINT("result correct.\n");
fail_marker_positive();
return 0;
} else {
HOST_PRINT("result incorrect.\n");
fail_marker_negative();
return 1;
}
}