-#!/usr/bin/perl -w
+#!/usr/bin/perl -ws
#
# findrfuncs: find reentrant variants of functions used in an executable.
+#
# Requires a functional "nm -u". Searches headers in /usr/include
# to find available *_r functions and looks for non-reentrant
# variants used in the supplied executable.
#
+# Requires debug info in the shared libraries/executables.
+#
# Gurusamy Sarathy
# gsar@ActiveState.com
#
my $CONFIG = <CONFIG>;
$SO = $1 if $CONFIG =~ /^so='(\w+)'/m;
$EXE = $1 if $CONFIG =~ /^_exe='\.(\w+)'/m;
+ close(CONFIG);
}
push @EXES, "perl$EXE";
-find(sub {push @EXES, $File::Find::name if /.$SO$/}, '.' );
+find(sub {push @EXES, $File::Find::name if /\.$SO$/}, '.' );
push @EXES, @ARGV;
if ($^O eq 'dec_osf') {
$NMU = 'nm -Bu';
+} elsif ($^O eq 'irix') {
+ $NMU = 'nm -pu';
}
my %rfuncs;
my @syms;
find(sub {
return unless -f $File::Find::name;
- open my $F, "<$File::Find::name"
+ local *F;
+ open F, "<$File::Find::name"
or die "Can't open $File::Find::name: $!";
my $line;
- while (defined ($line = <$F>)) {
+ while (defined ($line = <F>)) {
if ($line =~ /\b(\w+_r)\b/) {
#warn "$1 => $File::Find::name\n";
- $rfuncs{$1} = $File::Find::name;
+ $rfuncs{$1}->{$File::Find::name}++;
}
}
- close $F;
+ close F;
}, @INCDIRS);
# delete bogus symbols grepped out of comments and such
delete $rfuncs{setlocale_r} if $^O eq 'linux';
+# delete obsolete (as promised by man pages) symbols
+my $netdb_r_obsolete;
+if ($^O eq 'hpux') {
+ delete $rfuncs{crypt_r};
+ delete $rfuncs{drand48_r};
+ delete $rfuncs{endgrent_r};
+ delete $rfuncs{endpwent_r};
+ delete $rfuncs{getgrent_r};
+ delete $rfuncs{getpwent_r};
+ delete $rfuncs{setlocale_r};
+ delete $rfuncs{srand48_r};
+ delete $rfuncs{strerror_r};
+ $netdb_r_obsolete = 1;
+} elsif ($^O eq 'dec_osf') {
+ delete $rfuncs{crypt_r};
+ delete $rfuncs{strerror_r};
+ $netdb_r_obsolete = 1;
+}
+if ($netdb_r_obsolete) {
+ delete @rfuncs{qw(endhostent_r
+ endnetent_r
+ endprotoent_r
+ endservent_r
+ gethostbyaddr_r
+ gethostbyname_r
+ gethostent_r
+ getnetbyaddr_r
+ getnetbyname_r
+ getnetent_r
+ getprotobyname_r
+ getprotobynumber_r
+ getprotoent_r
+ getservbyname_r
+ getservbyport_r
+ getservent_r
+ sethostent_r
+ setnetent_r
+ setprotoent_r
+ setservent_r)};
+}
+
my %syms;
for my $exe (@EXES) {
- for my $sym (`$NMU $exe`) {
+ # warn "#--- $exe\n";
+ for my $sym (`$NMU $exe 2>/dev/null`) {
chomp $sym;
- $sym =~ s/^\s+[Uu]\s+//;
$sym =~ s/^\s+//;
- next if /\s/;
+ $sym =~ s/^([0-9A-Fa-f]+\s+)?[Uu]\s+//;
+ $sym =~ s/\s+[Uu]\s+-$//;
+ next if $sym =~ /\s/;
$sym =~ s/\@.*\z//; # remove @@GLIBC_2.0 etc
# warn "#### $sym\n";
if (exists $rfuncs{"${sym}_r"} && ! $syms{"$sym:$exe"}++) {
if (@syms) {
print "\nFollowing symbols in $exe have reentrant versions:\n";
for my $sym (@syms) {
- print "$sym => $sym" . "_r (in file " . $rfuncs{"${sym}_r"} . ")\n";
+ my @f = sort keys %{$rfuncs{$sym . '_r'}};
+ print "$sym => $sym" . "_r (@f)\n";
}
}
@syms = ();
}
-