#!/usr/bin/perl # detect unused functions and # functions which could be static use strict; my $verbose = 0; my %requested; my %requested_externally; my %exported; open(IN, ') { if (/global:/) { $in_global = 1; } elsif ($in_global) { if (/}/) { $in_global = 0; } else { s/;.*//s; s/^\s+//s; if (/^spice_/) { $requested{$_} = 1; $requested_externally{$_} = 1; } } } } close(IN); sub process_obj($) { my $fn = shift; open(IN, "objdump -t $fn |") or die; while () { # 0000000000006e87 g F .text 0000000000000114 .hidden spice_canvas_set_usr_data # 0000000000000000 *UND* 0000000000000000 rop3_init my @row = split(/\s+/); if ($row[1] eq '*UND*') { my $func = $row[-1]; print "requested $func\n" if $verbose; $requested{$func} = 1; $requested_externally{$func} = 1; } elsif ($row[1] eq 'g' && $row[3] eq '.text') { my $func = $row[-1]; print "exported $func\n" if $verbose; $exported{$func} = 1; } } close(IN); open(IN, "objdump -r $fn |") or die; while () { # 0000000000000043 R_X86_64_PLT32 __asan_report_load4-0x0000000000000004 if (/^[0-9a-f]+\s+R\S+\s+(.*?)[-+]0x/i) { $requested{$1} = 1; } } close(IN); } for my $fn (glob("server/.libs/*.o server/tests/*.o")) { print "Parsing $fn\n" if $verbose; process_obj($fn); } print "Unused functions:\n"; for my $func (sort keys %exported) { if (!exists($requested{$func})) { print "\t$func\n"; } } print "Can be static functions:\n"; for my $func (sort keys %exported) { if (exists($requested{$func}) && !exists($requested_externally{$func})) { print "\t$func\n"; } }