Files
failnix/scripts/Modules/Filters.pm
T

233 lines
6.6 KiB
Perl

package Filters;
use strict;
use warnings;
use diagnostics;
use FindBin;
use lib $FindBin::Bin;
use Util;
my %CONFIGS = (
no_aot_instr => {
label => "Exclude WAMR AOT array (instr)",
regions => [
[
'_wamr_aot_start', '_wamr_aot_end',
'p.injection_instr_absolute'
]
],
},
no_aot_data => {
label => "Exclude WAMR AOT array (data)",
regions =>
[ [ '_wamr_aot_start', '_wamr_aot_end', 'g.data_physical_address' ] ],
},
no_mmap_instr => {
label => "Exclude WAMR mmap (instr)",
regions => [
[
'_wamr_mmap_start', '_wamr_mmap_end',
'p.injection_instr_absolute'
]
],
},
no_mmap_data => {
label => "Exclude WAMR mmap (data)",
regions => [
[ '_wamr_mmap_start', '_wamr_mmap_end', 'g.data_physical_address' ]
],
},
no_runtime_pool_instr => {
label => "Exclude WAMR runtime pool (instr)",
regions => [
[
'_wamr_runtime_pool_start', '_wamr_runtime_pool_end',
'p.injection_instr_absolute'
]
],
},
no_runtime_pool_data => {
label => "Exclude WAMR runtime pool (data)",
regions => [
[
'_wamr_runtime_pool_start', '_wamr_runtime_pool_end',
'g.data_physical_address'
]
],
},
no_linear_pool_instr => {
label => "Exclude WAMR linear pool (instr)",
regions => [
[
'_wamr_linear_pool_start', '_wamr_linear_pool_end',
'p.injection_instr_absolute'
]
],
},
no_linear_pool_data => {
label => "Exclude WAMR linear pool (data)",
regions => [
[
'_wamr_linear_pool_start', '_wamr_linear_pool_end',
'g.data_physical_address'
]
],
},
no_global_heap_instr => {
label => "Exclude WAMR global heap (instr)",
regions => [
[
'_wamr_global_heap_start', '_wamr_global_heap_end',
'p.injection_instr_absolute'
]
],
},
no_global_heap_data => {
label => "Exclude WAMR global heap (data)",
regions => [
[
'_wamr_global_heap_start', '_wamr_global_heap_end',
'g.data_physical_address'
]
],
},
);
# All entries are functions part of the native call chain
my @NATIVE_CALL_FUNCS = (
'aot_invoke_native', # imported-function dispatch (AOT)
'aot_call_indirect', # call_indirect dispatch (AOT)
'wasm_interp_call_func_native', # native dispatch (Interp)
'wasm_runtime_invoke_native', # common
'invokeNative', # common
# Imported functions:
'host_fail_start_trace',
'host_fail_stop_trace',
'host_fail_marker_positive',
'host_fail_marker_negative',
'host_fail_marker_detected',
'host_print',
);
$CONFIGS{no_native_call_instr} = {
label => "Exclude WAMR native call chain (instr)",
regions => [
map { { func => $_, col => 'p.injection_instr_absolute' } }
@NATIVE_CALL_FUNCS
],
};
$CONFIGS{no_native_call_data} = {
label => "Exclude WAMR native call chain (data)",
regions => [
map { { func => $_, col => 'g.data_physical_address' } }
@NATIVE_CALL_FUNCS
],
};
# Generate the inverse filters to the regions defined above
for my $name ( keys %CONFIGS ) {
next unless $name =~ /^no_/;
( my $only_name = $name ) =~ s/^no_/only_/;
my $src = $CONFIGS{$name};
my $label = $src->{label} // $name;
$label =~ s/^Exclude/Keep only/;
$CONFIGS{$only_name} = {
label => $label,
invert => 1,
regions => $src->{regions},
};
}
# Those will be executed automatically by runner.pl (+ no filter at all)
# my @DEFAULT_CONFIGS = ('no_aot_data');
my @DEFAULT_CONFIGS = ();
sub get_configs {
return \%CONFIGS;
}
sub get_default_configs {
return @DEFAULT_CONFIGS;
}
# Builds the filters for regions whose column matches $col_filter.
# Queries that aggreate separately have to apply the data and instruction
# filters separately as well.
sub build_filter_clause_restricted {
my ( $experiment_dir, $col_filter, @config_names ) = @_;
# Drop empty ones, rest is combined
@config_names = grep { defined && length } @config_names;
return "" unless @config_names;
return ""
unless defined $experiment_dir && -f "$experiment_dir/system.elf";
my $elf = "$experiment_dir/system.elf";
# Produce ($start, $end, $col)-tuple from a defined region
my $resolve = sub {
my ($region) = @_;
my ( $start, $end, $col );
if ( ref($region) eq 'HASH' ) {
# Symbol + size definition (e.g., native call function list)
$col = $region->{col};
( $start, $end ) = Util::elf_sym_range( $elf, $region->{func} );
}
else {
# Linker script definition (e.g., AOT region)
my ( $start_sym, $end_sym );
( $start_sym, $end_sym, $col ) = @$region;
$start = Util::elf_sym_addr( $elf, $start_sym );
$end = Util::elf_sym_addr( $elf, $end_sym );
}
return unless defined $start && defined $end && $end > $start;
return ( $start, $end, $col );
};
my @excl_filters;
my @keep_terms;
for my $config_name (@config_names) {
my $config = $CONFIGS{$config_name};
next unless defined $config;
my $regions = $config->{regions};
next unless defined $regions;
my $invert = $config->{invert};
for my $region (@$regions) {
my ( $start, $end, $col ) = $resolve->($region);
next unless defined $start;
next unless $col =~ $col_filter;
if ($invert) {
push @keep_terms, "$col BETWEEN $start AND @{[$end - 1]}";
}
else {
push @excl_filters, "$col NOT BETWEEN $start AND @{[$end - 1]}";
}
}
}
# Including filters are combined with OR...
my @filters = @excl_filters;
push @filters, "(" . join( " OR ", @keep_terms ) . ")" if @keep_terms;
# ...excluding filters are combined with AND
return "" unless @filters;
return "\nAND " . join( "\nAND ", @filters );
}
sub build_filter_clause {
my ( $experiment_dir, @config_names ) = @_;
return build_filter_clause_restricted( $experiment_dir, qr//,
@config_names );
}
1;