diff --git a/scripts/Modules/Filters.pm b/scripts/Modules/Filters.pm index 9fd3193..bb75f2f 100644 --- a/scripts/Modules/Filters.pm +++ b/scripts/Modules/Filters.pm @@ -127,6 +127,20 @@ $CONFIGS{no_native_call_data} = { ], }; +# 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 = (); @@ -151,33 +165,55 @@ sub build_filter_clause { my $elf = "$experiment_dir/system.elf"; - my @filters; + # 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 $regions = $CONFIGS{$config_name}{regions}; + 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 ); + my ( $start, $end, $col ) = $resolve->($region); + next unless defined $start; - if ( ref($region) eq 'HASH' ) { - - # resolve [start, end) via symbol + size - $col = $region->{col}; - ( $start, $end ) = Util::elf_sym_range( $elf, $region->{func} ); + if ($invert) { + push @keep_terms, "$col BETWEEN $start AND @{[$end - 1]}"; } else { - # [start_sym, end_sym, col] - 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 ); + push @excl_filters, "$col NOT BETWEEN $start AND @{[$end - 1]}"; } - - next unless defined $start && defined $end && $end > $start; - push @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 ); }