1 #!/usr/bin/perl -w 2 3 use strict; 4 use DBI; 5 use Scalar::Util qw(looks_like_number); 6 7 sub usage() 8 { 9 print "usage: $0 <project> <smatch_warns.txt> <db_file>\n"; 10 exit(1); 11 } 12 13 my %too_common_funcs; 14 sub get_too_common_functions($$$) 15 { 16 my $path = shift; 17 my $project = shift; 18 my $warns = shift; 19 20 open(FUNCS, "grep 'SQL_caller_info: ' $warns | grep '%call_marker%' | cut -d \"'\" -f 6 | sort | uniq -c | "); 21 22 while (<FUNCS>) { 23 if ($_ =~ /(\d+) (.*)/) { 24 if (int($1) > 200) { 25 $too_common_funcs{$2} = 1; 26 } 27 } 28 } 29 30 close(FUNCS); 31 32 open(FILE, ">", "$path/../$project.common_functions"); 33 foreach my $func (keys %too_common_funcs) { 34 if ($func =~ / /) { 35 next; 36 } 37 print FILE "$func\n"; 38 } 39 close(FILE); 40 } 41 42 my $exec_name = $0; 43 my $path = $exec_name; 44 $path =~ s/(.*)\/.*/$1/; 45 my $project = shift; 46 my $warns = shift; 47 my $db_file = shift; 48 49 if (!defined($db_file)) { 50 usage(); 51 } 52 53 get_too_common_functions($path, $project, $warns); 54 55 my $db = DBI->connect("dbi:SQLite:$db_file", "", "", {AutoCommit => 0}); 56 $db->do("PRAGMA cache_size = 800000"); 57 $db->do("PRAGMA journal_mode = OFF"); 58 $db->do("PRAGMA count_changes = OFF"); 59 $db->do("PRAGMA temp_store = MEMORY"); 60 $db->do("PRAGMA locking = EXCLUSIVE"); 61 62 foreach my $func (keys %too_common_funcs) { 63 $db->do("insert into common_caller_info values ('unknown', 'too common', '$func', 0, 0, 0, -1, '', '');"); 64 } 65 66 my $call_id = 0; 67 my ($fn, $dummy, $sql); 68 69 open(WARNS, "<$warns"); 70 while (<WARNS>) { 71 # test.c:11 frob() SQL_caller_info: insert into caller_info values ('test.c', 'frob', '__smatch_buf_size', %CALL_ID%, 1, 0, -1, '', '); 72 73 if (!($_ =~ /^.*? \w+\(\) SQL_caller_info: /)) { 74 next; 75 } 76 ($dummy, $dummy, $dummy, $dummy, $dummy, $fn, $dummy) = split(/'/); 77 78 if ($fn =~ /__builtin_/) { 79 next; 80 } 81 if ($fn =~ /^(printk|memset|memcpy|kfree|printf|dev_err|writel)$/) { 82 next; 83 } 84 85 ($dummy, $dummy, $sql) = split(/:/, $_, 3); 86 87 if ($sql =~ /%call_marker%/) { 88 $sql =~ s/%call_marker%//; # don't need this taking space in the db. 89 $call_id++; 90 } 91 $sql =~ s/%CALL_ID%/$call_id/; 92 93 $db->do($sql); 94 } 95 $db->commit(); 96 $db->disconnect();