1 #!/usr/bin/perl 2 3 use strict; 4 5 sub usage() 6 { 7 print "$0 <smatch output file> <function> <parameter>\n"; 8 print "Give this program a function and parameter and it follows to find\n"; 9 print "how the parameter gets passed down to lower levels.\n'"; 10 exit(1); 11 } 12 13 my %param_map; 14 15 my $UNUSED = 0; 16 my $USED = 1; 17 18 sub print_link($) 19 { 20 my $link = shift; 21 22 $link =~ s/%/ /; 23 print "$link\n"; 24 } 25 26 sub recurse($) 27 { 28 my $link = shift; 29 30 if ($param_map{$link}{used} == $USED) { 31 return; 32 } 33 ${param_map}{$link}->{used} = $USED; 34 35 print_link($link); 36 37 foreach my $l (@{$param_map{$link}{links}}){ 38 recurse($l); 39 } 40 41 } 42 43 sub follow($$) 44 { 45 my $f = shift; 46 my $p = shift; 47 48 recurse("$f%$p"); 49 } 50 51 sub add_link($$) 52 { 53 my $one = shift; 54 my $two = shift; 55 56 if (!defined($param_map{$one})) { 57 $param_map{$one} = {used => $UNUSED, links => []}; 58 } 59 push @{$param_map{$one}{links}}, $two; 60 } 61 62 sub load_all($) 63 { 64 my $file = shift; 65 66 open(FILE, "<$file"); 67 while (<FILE>) { 68 if (/.*?:\d+ (.*?)\(\) info: param_mapper (\d+) => (.*?) (\d+)/) { 69 add_link("$1%$2", "$3%$4"); 70 } 71 } 72 } 73 74 sub set_all_unused() 75 { 76 foreach my $func (keys %param_map){ 77 ($param_map{$func}{used} = $UNUSED); 78 } 79 80 } 81 82 my $file = shift(); 83 my $func = shift(); 84 my $param = shift(); 85 86 if (!defined($file) or !defined($func) or !defined($param)) { 87 usage(); 88 } 89 90 if (! -e $file) { 91 printf("Error: $file does not exist.\n"); 92 exit(1); 93 } 94 95 load_all($file); 96 97 while (1) { 98 follow($func, $param); 99 100 $func = shift(); 101 $param = shift(); 102 if (!defined($func) || !defined($param)) { 103 last; 104 } 105 set_all_unused(); 106 }