Files
failnix/scripts/menu.pl

378 lines
13 KiB
Perl

#!/usr/bin/env perl
use strict;
use warnings;
use diagnostics;
use FindBin;
use lib $FindBin::Bin;
use Util;
use Mars;
use TUI;
use feature 'say';
my $local_obsidian = '/home/christoph/Notes/Obsidian/Chriphost';
my $local_obsidian_attach = "$local_obsidian/attach";
my $local_wamr = '/home/christoph/Notes/TU/MastersThesis/05 WAMR';
my $local_newlib = '/home/christoph/Notes/TU/MastersThesis/07 NewLib';
my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix';
my $local_scripts_dir = "$local_root/scripts";
my $local_builds_dir = "$local_root/builds";
my $local_archive_dir = "$local_root/injections";
my $local_charts_dir = "$local_root/charts";
my $local_ghidra_projects = "$local_root/ghidra/projects";
my $local_ghidra_scripts = "$local_root/ghidra/scripts";
my $local_db_conf = "$local_root/db.conf";
my $resultbrowser_port = '5000';
my $resultbrowser = 'resultbrowser.py';
my $remote_root = '/home/lab/smchurla/Documents/failnix';
my $remote_builds_dir = "$remote_root/builds";
my %handlers = (
'01. Build Experiments' => sub { do "$local_scripts_dir/build.pl"; },
'02. Deploy Experiments (Mars)' =>
sub { do "$local_scripts_dir/deploy.pl"; },
'03. Archive Experiments (Downloads from Mars)' => sub {
# Download ran experiments from mars
my @dirs = Mars::find_remote_subdirs($remote_builds_dir);
my @selected_dirs =
TUI::select_from_list( "Select Experiments to Download from Mars",
1, @dirs );
die "No experiment selected" unless @selected_dirs;
Mars::download_dir( "$remote_builds_dir/$_",
"$local_archive_dir/" . $_ =~ s/:/-/gr )
for @selected_dirs;
},
'04. Query Databases (Mars)' => sub {
# Select databases
my @db_names = Mars::db_list();
my @selected_dbs =
TUI::select_from_list( "Select Databases to Query", 1, @db_names );
die "No database selected" unless @selected_dbs;
# Select queries
my @queries =
map { s/\.pm//r } Util::find_files("$local_root/scripts/Queries");
my @selected_queries =
TUI::select_from_list( "Select Queries to Run", 1, @queries );
die "No query selected" unless @selected_queries;
# Run queries on databases
foreach my $db (@selected_dbs) {
foreach my $query (@selected_queries) {
Util::rewrite_file( $local_db_conf, "database=",
"database=$db\n" );
say "Running $query on $db...";
Util::execute_query( $db =~ s/smchurla_//r,
$query, $local_db_conf, $local_archive_dir, 0 );
}
}
},
'05. Import Experiments Into Ghidra' => sub {
my @existing = Util::find_files($local_ghidra_projects);
my $is_old = sub {
my ($name) = @_;
$name =~ s/:/-/g;
return grep { /^$name.gpr$/ } @existing;
};
# Import archived experiments into ghidra
my @dirs =
grep { !$is_old->($_) } Util::find_subdirs($local_archive_dir);
my @selected_dirs =
TUI::select_from_list( "Select Experiments to Import into Ghidra",
1, @dirs );
foreach (@selected_dirs) {
say "Creating Ghidra project for $_...";
system(
'ghidra-analyzeHeadless',
$local_ghidra_projects, $_ =~ s/:/-/gr,
'-import', "$local_archive_dir/$_/system.elf",
'-scriptPath', $local_ghidra_scripts,
'-postScript', 'DWARFLineInfoSourceMapScript',
'-postScript', 'DWARFLineInfoCommentScript',
'-postScript', 'ImportMarkersAsBookmarks',
"$local_archive_dir/$_/faults.csv"
);
}
},
'06. Import Experiments Into Obsidian' => sub {
my @experiments = Util::find_subdirs($local_archive_dir);
# Filter experiments that already have notes
my @new_experiments;
my @existing_notes = split "\n", qx{obsidian files};
foreach my $experiment (@experiments) {
push @new_experiments, $experiment
unless ( grep { /zettel\/$experiment/ } @existing_notes );
}
my @selected_experiments =
TUI::select_from_list( "Select Experiments to Import into Obsidian",
1, @new_experiments );
die "No experiment selected" unless @selected_experiments;
foreach my $experiment (@selected_experiments) {
# Create note
system(
'obsidian', 'create',
"name=$experiment", 'path=zettel',
'template=FailExperiment', 'open',
'newtab'
);
# Insert results
if ( -f "$local_archive_dir/$experiment/results.txt" ) {
open( my $fhandle, '<',
"$local_archive_dir/$experiment/results.txt" )
or return;
my $results = join "", <$fhandle>;
close($fhandle);
say "$local_archive_dir/$experiment/results.txt does not exist";
system( 'obsidian', 'append', "file=zettel/$experiment",
"content=## Results\n\n```\n$results```\n" );
}
# 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(
'obsidian', 'append',
"file=zettel/$experiment", "content=## Charts\n\n"
);
$attach_image->("single_result");
$attach_image->("scatter");
}
},
'10. Open Experiment In Explorer' =>
sub { do "$local_scripts_dir/explore.pl" },
'11. 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",
)
);
},
'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. Run Build in GDB' => sub {
my @builds = grep { /linux/ } Util::find_subdirs($local_builds_dir);
my @selected_builds =
TUI::select_from_list( "Select Build to Run in GDB", 0, @builds );
die "No experiment selected" unless @selected_builds;
my $selected_build = $selected_builds[0];
my $build_dir = "$local_builds_dir/$selected_build";
my $build_name = $selected_build =~ s/.*-.*-.*:.*:.*?_(.*)-.*-.*/$1/r;
my $module_source = "$local_root/build-$build_name";
say "$build_name";
system(
'gdb',
'--tui',
'-q',
"$build_dir/system.elf",
'-ex',
"set substitute-path '$module_source' '$build_dir'",
'-ex',
"set substitute-path '/build/source/core' '$local_wamr/core'",
'-ex',
'break main',
'-ex',
'break fail_start_trace',
'-ex',
'break fail_stop_trace',
'-ex',
'break fail_marker_positive',
'-ex',
'break fail_marker_detected',
'-ex',
'break fail_marker_negative',
);
},
'20. Plot Results' => sub {
# 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 );
}
},
'95. Delete Builds' => sub {
# Delete old build files
my @builds = Util::find_subdirs($local_builds_dir);
my @selected_builds =
TUI::select_from_list( "Select Builds to Delete", 1, @builds );
die "No builds selected" unless @selected_builds;
system( 'rm', '-rf', "$local_builds_dir/$_" ) for @selected_builds;
},
'96. Delete Builds (Mars)' => sub {
# Delete ran experiments from mars
my @builds = Mars::find_remote_subdirs($remote_builds_dir);
my @selected_builds =
TUI::select_from_list( "Select Builds to Delete from Mars",
1, @builds );
die "No experiment selected" unless @selected_builds;
Mars::ssh_system( 'rm', '-rf', "$remote_builds_dir/$_" )
for @selected_builds;
},
'97. Delete Ghidra Projects' => sub {
# Delete ghidra projects
my @projects =
map { s/\.gpr//r } Util::find_files($local_ghidra_projects);
my @selected_projects =
TUI::select_from_list( "Select Ghidra Projects to Delete",
1, @projects );
die "No project selected" unless @selected_projects;
system( 'rm', '-rf', "$local_ghidra_projects/$_.gpr" )
for @selected_projects;
system( 'rm', '-rf', "$local_ghidra_projects/$_.rep" )
for @selected_projects;
},
'98. Delete Archived Experiments' => sub {
# Delete archived experiments
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/$_" )
for @selected_experiments;
},
'99. Drop Databases (Mars)' => sub {
# Drop databases on mars
my @db_names = Mars::db_list();
my @selected_dbs =
TUI::select_from_list( "Select Databases to Drop from Mars",
1, @db_names );
die "No database selected" unless @selected_dbs;
Mars::db_drop($_) for @selected_dbs;
},
);
while (1) {
my @submenu =
TUI::select_from_list( "FailNix Menu", 0, sort keys %handlers );
die "No action selected" unless @submenu;
say @submenu;
eval { $handlers{ $submenu[0] }(); }
}
Mars::db_disconnect();