summaryrefslogtreecommitdiff
path: root/Porting/findrfuncs
blob: c9a7ff80a73d21e5df45506ca32ecb10044a497f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/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
#
# Hacked to automatically find the executable and shared objects.
# --jhi

use strict;
use File::Find;

my @EXES;
my $NMU = 'nm -u';
my @INCDIRS = qw(/usr/include);
my $SO = 'so';
my $EXE = '';

if (open(CONFIG, "config.sh")) {
    local $/;
    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$/}, '.' );

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;
	local *F;
	open F, "<$File::Find::name"
	    or die "Can't open $File::Find::name: $!";
	my $line;
	while (defined ($line = <F>)) {
	    if ($line =~ /\b(\w+_r)\b/) {
		#warn "$1 => $File::Find::name\n";
		$rfuncs{$1}->{$File::Find::name}++;
	    }
	}
	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) {
    # warn "#--- $exe\n";
    for my $sym (`$NMU $exe 2>/dev/null`) {
        chomp $sym;
        $sym =~ s/^\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"}++) {
    	    push @syms, $sym;
        }
    }
    
    if (@syms) {
        print "\nFollowing symbols in $exe have reentrant versions:\n";
        for my $sym (@syms) {
	    my @f = sort keys %{$rfuncs{$sym . '_r'}};
    	    print "$sym => $sym" . "_r (@f)\n";
        }
    }
    @syms = ();
}