1 #!/usr/bin/perl
   2 
   3 # This script is supposed to help use the param_mapper output.
   4 # Give it a function and parameter and it lists the functions
   5 # and parameters which are basically equivalent.
   6 
   7 use strict;
   8 
   9 sub usage()
  10 {
  11     print("call_tree.pl <smatch output file>\n");
  12     print("call_tree.pl finds paths between two functions\n"); 
  13     exit(1);
  14 }
  15 
  16 my %param_map;
  17 
  18 my $UNKNOWN  = 1;
  19 my $NOTFOUND = 2;
  20 my $FOUND    = 3;
  21 
  22 my $path;
  23 
  24 sub print_path()
  25 {
  26     my $i = 0;
  27 
  28     foreach my $func (@{$path}) {
  29         if ($i++) {
  30             print(", ");
  31         }
  32         print("$func");
  33     }
  34     print("\n");
  35     print("\n");
  36 }
  37 
  38 sub recurse($$)
  39 {
  40     my $link = shift;
  41     my $target = shift;
  42     my $found = 0;
  43 
  44     if ($link =~ /$target/) {
  45         print_path();
  46         return 1;
  47     }
  48     if (%{$param_map{$link}}->{found} == $NOTFOUND) {
  49         return 0;
  50     }
  51 
  52     %{$param_map{$link}}->{found} = $NOTFOUND;
  53 
  54     foreach my $l (@{%{$param_map{$link}}->{links}}){
  55         push(@{$path}, $l);
  56         $found = recurse($l, $target);
  57         if (!$found) {
  58             pop(@{$path});
  59         } else {
  60             last;
  61         }
  62     }
  63 
  64     return $found;
  65 }
  66 
  67 sub search($$)
  68 {
  69     my $start_func = shift;
  70     my $end_func = shift;
  71 
  72     foreach my $link (@{%{$param_map{$start_func}}->{links}}){
  73         %{$param_map{$start_func}}->{found} = $NOTFOUND;
  74         foreach my $l (@{%{$param_map{$start_func}}->{links}}){
  75             %{$param_map{$l}}->{found} = $NOTFOUND;
  76         }
  77         $path = [$start_func, $link];
  78         %{$param_map{$link}}->{found} = $UNKNOWN;
  79         recurse($link, $end_func);
  80     }
  81 }
  82 
  83 sub add_link($$)
  84 {
  85     my $one = shift;
  86     my $two = shift;
  87 
  88     if (!defined($param_map{$one})) {
  89         $param_map{$one} = {found => $UNKNOWN, links => []};
  90     }
  91     push @{$param_map{$one}->{links}}, $two;
  92 }
  93 
  94 sub load_all($)
  95 {
  96     my $file = shift;
  97 
  98     open(FILE, "<$file");
  99     while (<FILE>) {
 100         if (/.*?:\d+ (.*?)\(\) info: func_call (.*)/) {
 101             add_link("$1", "$2");
 102         }
 103     }
 104 }
 105 
 106 sub set_all_unknown()
 107 {
 108     my $i = 0;
 109 
 110     foreach my $func (keys %param_map){
 111         %{$param_map{$func}}->{found} = $UNKNOWN;
 112     }
 113 }
 114 
 115 my $file = shift();
 116 if (!$file) {
 117     usage();
 118 }
 119 
 120 if (! -e $file) {
 121     printf("Error:  $file does not exist.\n");
 122     exit(1);
 123 }
 124 
 125 print("Loading functions...\n");
 126 load_all($file);
 127 
 128 while (1) {
 129     my $start_func;
 130     my $end_func;
 131 
 132     print("Enter the start function:  ");
 133     $start_func = <STDIN>;
 134     $start_func =~ s/^\s+|\s+$//g;
 135     print("Enter the target function:  ");
 136     $end_func = <STDIN>;
 137     $end_func =~ s/^\s+|\s+$//g;
 138 
 139 
 140     print("$start_func to $end_func\n");
 141     if ($start_func =~ /./ && $end_func =~ /./) {
 142         search($start_func, $end_func);
 143     }
 144 
 145     set_all_unknown();
 146 }