function_hooks: function comparisons can imply a parameter value
[smatch.git] / smatch_scripts / unlocked_paths.pl
blobf235b87e3cffab7941effa29ed30ec7d2ad95f8b
1 #!/usr/bin/perl
3 use strict;
5 sub usage()
7 print "Usage: unlocked_paths.pl <call tree file> <lock> <function>\n";
8 print "Prints a list of paths to <function> which don't take the <lock>.\n";
9 print "Generate the call tree file by running smatch with --call-tree.\n";
10 exit(1);
13 my %f_map;
15 sub add_to_map($)
17 my $callee = shift;
19 if (!defined($f_map{$callee})) {
20 $f_map{$callee} = {visited => 0, called_by => {}};
24 sub add_called_by($$)
26 my $caller = shift;
27 my $callee = shift;
28 my $tmp;
30 %{$f_map{$callee}->{called_by}}->{$caller} = 1;
33 sub load_all($$)
35 my $file = shift;
36 my $lock = shift;
38 open(FILE, "<$file");
39 while (<FILE>) {
40 if (/.*?:\d+ (.*?)\(\) info: func_call \((.*)\) (.*)/) {
41 my $caller = quotemeta $1;
42 my $locks = quotemeta $2;
43 my $callee = quotemeta $3;
45 add_to_map($callee);
46 if (!($locks =~ /$lock/)) {
47 add_called_by($caller, $callee);
53 my @fstack;
54 sub print_fstack()
56 foreach my $f (reverse @fstack) {
57 printf "$f ";
59 printf "\n";
62 sub print_unlocked_paths($)
64 my $function = shift;
66 if (! defined %{$f_map{$function}}->{called_by}) {
67 push @fstack, $function;
68 print_fstack();
69 pop @fstack;
70 return;
73 push @fstack, $function;
75 if (!%{$f_map{$function}}->{visited}) {
76 %{$f_map{$function}}->{visited} = 1;
77 foreach my $caller (keys %{%{$f_map{$function}}->{called_by}}){
78 print_unlocked_paths($caller);
80 %{$f_map{$function}}->{visited} = 0;
84 pop @fstack;
87 my $file = shift;
88 my $lock = shift;
89 my $target = shift;
91 if (!$file || !$lock || !$target) {
92 usage();
94 if (! -e $file) {
95 printf("Error: $file does not exist.\n");
96 exit(1);
99 load_all($file, $lock);
100 print_unlocked_paths($target);