343 lines
9.8 KiB
Perl
343 lines
9.8 KiB
Perl
#!/usr/bin/env perl
|
|
|
|
use strict;
|
|
use warnings;
|
|
use diagnostics;
|
|
|
|
use FindBin;
|
|
use lib $FindBin::Bin;
|
|
|
|
use Util;
|
|
|
|
use feature 'say';
|
|
|
|
my $remote_root = '/home/lab/smchurla/Documents/failnix';
|
|
my $remote_db_conf = "$remote_root/db.conf";
|
|
my $remote_builds_dir = "$remote_root/builds";
|
|
my $remote_runner = "$remote_root/scripts/runner.pl";
|
|
|
|
my $db_user = "smchurla";
|
|
my $db_prefix = "$db_user";
|
|
|
|
my $fail_server_port = '22941';
|
|
my $resultbrowser_port = '22941';
|
|
my $fail_bin = "$remote_root/fail/bin";
|
|
my $fail_share = "$remote_root/fail/share";
|
|
my $bochs_runner = "$fail_bin/bochs-experiment-runner.py";
|
|
my $fail_trace = "$fail_bin/fail-x86-tracing";
|
|
my $fail_dump = "$fail_bin/dump-trace";
|
|
my $fail_import = "$fail_bin/import-trace";
|
|
my $fail_prune = "$fail_bin/prune-trace";
|
|
my $fail_server = "$fail_bin/generic-experiment-server";
|
|
my $fail_inject = "$fail_bin/generic-experiment-client";
|
|
my $result_browser = "$fail_bin/resultbrowser.py";
|
|
|
|
sub update_db_config {
|
|
my ($experiment) = @_;
|
|
|
|
open( my $readhandle, '<', $remote_db_conf )
|
|
or die "failed to open db.conf: $!";
|
|
my @lines;
|
|
my $found = 0;
|
|
while ( my $line = <$readhandle> ) {
|
|
if ( rindex( $line, 'database=', 0 ) == 0 ) {
|
|
$line = "database=${db_prefix}_$experiment\n";
|
|
$found = 1;
|
|
}
|
|
push @lines, $line;
|
|
}
|
|
close($readhandle) or die "failed to close db.conf: $!";
|
|
|
|
die "no database= line found in $remote_db_conf for some reason"
|
|
unless $found;
|
|
|
|
open( my $writehandle, '>', $remote_db_conf )
|
|
or die "failed to open db.conf: $!";
|
|
print $writehandle @lines or die "failed to write db.conf: $!";
|
|
close($writehandle) or die "failed to close db.conf: $!";
|
|
|
|
say "Updated db.conf for database $db_prefix\_$experiment";
|
|
}
|
|
|
|
sub cpu_count {
|
|
open( my $handle, '/proc/cpuinfo' ) or die "Can't open cpuinfo: $!\n";
|
|
my $count = scalar( map /^processor/, <$handle> );
|
|
close $handle;
|
|
|
|
return $count;
|
|
}
|
|
|
|
# Find new experiments
|
|
# opendir( my $dhandle, $remote_builds_dir )
|
|
# or die "opendir($remote_builds_dir): $!";
|
|
# my @experiments = grep { $_ ne '.' && $_ ne '..' && -d "$remote_builds_dir/$_" }
|
|
# readdir($dhandle);
|
|
# closedir($dhandle);
|
|
|
|
my @experiments = Util::find_subdirs($remote_builds_dir);
|
|
|
|
sub trace {
|
|
my ($experiment) = @_;
|
|
|
|
Util::notify("Tracing $experiment...");
|
|
|
|
system(
|
|
join " ",
|
|
(
|
|
"$bochs_runner",
|
|
"-V $fail_share/vgabios.bin",
|
|
"-b $fail_share/BIOS-bochs-latest",
|
|
"-1",
|
|
"-f $fail_trace",
|
|
"-e $remote_builds_dir/$experiment/system.elf",
|
|
"-i $remote_builds_dir/$experiment/system.iso",
|
|
"--",
|
|
"-Wf,--start-symbol=fail_start_trace",
|
|
"-Wf,--save-symbol=fail_start_trace",
|
|
"-Wf,--end-symbol=fail_stop_trace",
|
|
"-Wf,--state-file=$remote_builds_dir/$experiment/state",
|
|
"-Wf,--trace-file=$remote_builds_dir/$experiment/trace.pb",
|
|
"-Wf,--elf-file=$remote_builds_dir/$experiment/system.elf"
|
|
)
|
|
);
|
|
|
|
# notify("Tracing $experiment complete.");
|
|
}
|
|
|
|
sub import_trace {
|
|
my ($experiment) = @_;
|
|
|
|
Util::notify("Importing $experiment trace...");
|
|
|
|
system(
|
|
join " ",
|
|
(
|
|
"$fail_import",
|
|
"--database-option-file $remote_db_conf",
|
|
"-t $remote_builds_dir/$experiment/trace.pb",
|
|
"-i MemoryImporter",
|
|
"-e $remote_builds_dir/$experiment/system.elf",
|
|
"-v $experiment",
|
|
"-b mem"
|
|
)
|
|
);
|
|
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 regs",
|
|
"--flags"
|
|
)
|
|
);
|
|
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",
|
|
"--ip"
|
|
)
|
|
);
|
|
|
|
system(
|
|
join " ",
|
|
(
|
|
"$fail_import",
|
|
"--database-option-file $remote_db_conf",
|
|
"-t $remote_builds_dir/$experiment/trace.pb",
|
|
"-i ElfImporter",
|
|
"--objdump objdump",
|
|
"-e $remote_builds_dir/$experiment/system.elf",
|
|
"-v $experiment",
|
|
"-b ip"
|
|
)
|
|
);
|
|
system(
|
|
join " ",
|
|
(
|
|
"$fail_import",
|
|
"--database-option-file $remote_db_conf",
|
|
"-t $remote_builds_dir/$experiment/trace.pb",
|
|
"-i ElfImporter",
|
|
"--objdump objdump",
|
|
"-e $remote_builds_dir/$experiment/system.elf",
|
|
"-v $experiment",
|
|
"-b mem"
|
|
)
|
|
);
|
|
system(
|
|
join " ",
|
|
(
|
|
"$fail_import",
|
|
"--database-option-file $remote_db_conf",
|
|
"-t $remote_builds_dir/$experiment/trace.pb",
|
|
"-i ElfImporter",
|
|
"--objdump objdump",
|
|
"-e $remote_builds_dir/$experiment/system.elf",
|
|
"-v $experiment",
|
|
"-b regs"
|
|
)
|
|
);
|
|
|
|
system(
|
|
join " ",
|
|
(
|
|
"$fail_prune",
|
|
"--database-option-file $remote_db_conf",
|
|
"-v $experiment",
|
|
"-b %%", "--overwrite"
|
|
)
|
|
);
|
|
|
|
# notify("Importing $experiment trace complete.");
|
|
}
|
|
|
|
sub inject {
|
|
my ($experiment) = @_;
|
|
|
|
# my $count = 1;
|
|
my $count = cpu_count();
|
|
|
|
Util::notify("Injecting $experiment using $count cores...");
|
|
|
|
say "Forking...";
|
|
my $pid = fork();
|
|
die "fork failed: $!" unless defined $pid;
|
|
|
|
if ( $pid == 0 ) {
|
|
|
|
# child -> server
|
|
|
|
say "Running server in child process...";
|
|
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
|
|
|
|
say "Waiting for server...";
|
|
sleep(10);
|
|
|
|
say "Running client with $count cores in parent process";
|
|
|
|
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...";
|
|
kill 'TERM', $pid;
|
|
waitpid( $pid, 0 );
|
|
|
|
# notify("Injecting $experiment complete.");
|
|
}
|
|
|
|
# sub query {
|
|
# my ( $experiment, $query, $args, $file, $postprocess ) = @_;
|
|
#
|
|
# say "Running query $query";
|
|
#
|
|
# my $result = qx{mariadb --defaults-file=$remote_db_conf $args -e "$query"};
|
|
# die "Query failed: $?" if $? != 0;
|
|
#
|
|
# if ( defined $postprocess ) {
|
|
# $postprocess->($result);
|
|
# }
|
|
#
|
|
# open( my $results_handle, '>', "$remote_builds_dir/$experiment/$file" )
|
|
# or die "failed to open file: $!";
|
|
# print $results_handle $result;
|
|
# close($results_handle) or die "failed to close file: $!";
|
|
#
|
|
# notify_file("$remote_builds_dir/$experiment/$file");
|
|
# }
|
|
|
|
sub results {
|
|
my ($experiment) = @_;
|
|
|
|
Util::notify("Querying $experiment...");
|
|
|
|
Util::execute_query( $experiment, "Results", $remote_db_conf,
|
|
$remote_builds_dir );
|
|
Util::execute_query( $experiment, "FaultsFailed", $remote_db_conf,
|
|
$remote_builds_dir );
|
|
|
|
# my $results_overview_query = "SELECT
|
|
# variant, benchmark, resulttype, sum(t.time2 - t.time1 + 1) AS faults
|
|
# FROM variant v
|
|
# 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_address = t.data_address
|
|
# JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id
|
|
# JOIN fsppilot p ON r.pilot_id = p.id
|
|
# WHERE v.variant = '$experiment'
|
|
# GROUP BY v.id, resulttype
|
|
# ORDER BY variant, benchmark, resulttype;";
|
|
#
|
|
# query( $experiment, $results_overview_query, "-t", "results.txt" );
|
|
#
|
|
# my $fail_markers_query = "SELECT
|
|
# CONCAT('0x', HEX(p.injection_instr_absolute)) AS fault_address,
|
|
# SUM(t.time2 - t.time1 + 1) AS total_fail_markers
|
|
# FROM trace t
|
|
# JOIN variant v ON v.id = t.variant_id
|
|
# 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 fsppilot p ON p.id = r.pilot_id
|
|
# WHERE v.variant = '$experiment' AND r.resulttype = 'FAIL_MARKER'
|
|
# GROUP BY p.injection_instr_absolute
|
|
# ORDER BY SUM(t.time2 - t.time1 + 1) DESC;";
|
|
#
|
|
# query( $experiment, $fail_markers_query, "--batch --raw",
|
|
# "markers.csv", sub { $_[0] =~ s/\t/,/g } );
|
|
}
|
|
|
|
# Run experiments
|
|
for my $experiment (@experiments) {
|
|
update_db_config($experiment);
|
|
|
|
# trace($experiment);
|
|
# import_trace($experiment);
|
|
# inject($experiment);
|
|
results($experiment);
|
|
}
|