#!/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 trace { my ($experiment) = @_; # Util::notify("Tracing $experiment..."); my $trace_command = 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", # "-Wf,--full-trace", # "-Wf,--check-bounds", ">$remote_builds_dir/$experiment/1_trace.log" ); say "Trace command: $trace_command"; system($trace_command); } sub import_trace { my ($experiment) = @_; # 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 my $import_mem_command = 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", ">$remote_builds_dir/$experiment/2_import_mem.log" ); say "Import MEM command: $import_mem_command"; system($import_mem_command); # Benchmark: regs my $import_regs_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 regs", "--flags", # Inject flags register ">$remote_builds_dir/$experiment/2_import_regs.log" ); say "Import REGS command: $import_regs_command"; system($import_regs_command); # Import fulltrace for VisualFAIL # system( # join " ", # ( # "$fail_import", # "--database-option-file $remote_db_conf", # "-t $remote_builds_dir/$experiment/trace.pb", # "-i FullTraceImporter", # "-e $remote_builds_dir/$experiment/system.elf", # "-v $experiment", # ) # ); # 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", # "-b ip", # "--objdump objdump", # # # "--sources", # ) # ); # 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", # "-b mem", # "--objdump objdump", # # # "--sources", # ) # ); # 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", # "-b regs", # "--objdump objdump", # # # "--sources", # ) # ); my $prune_command = join " ", ( "$fail_prune", "--database-option-file $remote_db_conf", "-v $experiment", "-b %%", "--overwrite", ">$remote_builds_dir/$experiment/2_prune.log" ); say "Prune command: $prune_command"; system($prune_command); } sub inject { my ($experiment) = @_; my $count = Util::cpu_count(); 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..."; my $pid = fork(); die "fork failed: $!" unless defined $pid; if ( $pid == 0 ) { # child -> server say "Running server in child process..."; exec($server_command) == 0 or die "exec server failed: $!"; } # parent -> client say "Waiting for server..."; sleep(10); say "Running client with $count cores in parent process"; system($client_command) == 0 or die "client failed: $?"; say "Killing server with pid $pid..."; kill 'TERM', $pid; waitpid( $pid, 0 ); } sub results { my ($experiment) = @_; my @queries = Util::find_files("$remote_root/scripts/Queries"); foreach (@queries) { my $query = $_; $query =~ s/\.pm//g; # Util::notify("Running query $query for $experiment..."); Util::execute_query( $experiment, $query, $remote_db_conf, $remote_builds_dir, 1 ); } } # Run experiments my @experiments = Util::find_subdirs($remote_builds_dir); for my $experiment (@experiments) { Util::rewrite_file( $remote_db_conf, "database=", "database=${db_prefix}_$experiment\n" ); trace($experiment); import_trace($experiment); inject($experiment); results($experiment); } Util::notify("Finished all experiments");