#!/usr/bin/perl -w use strict; use File::Basename; my $dbglvl = 0; if (scalar(@ARGV) ne 2) { my $pgm = basename($0); print STDERR "Usage: $pgm dso-name apache-prefix\n"; print STDERR "Example: $pgm /usr/local/apache2/modules/mod_silly2.so /usr/local/apache2\n"; exit(1); } my $dso = $ARGV[0]; my $prefix = $ARGV[1]; my @needed_from_httpd = (); my @needed_from_other = (); my %available_from_httpd = (); my %available_from_apr = (); my %available_from_special_dsos = (); my $rc = 0; get_dso_requirements(); get_httpd_exports(); get_apr_exports(); get_special_dso_exports(); find_unresolved(); exit($rc); sub find_unresolved { my $needed; my $problem_found = 0; my @non_apr; foreach $needed (@needed_from_httpd) { if (!exists($available_from_httpd{$needed}) && !exists($available_from_special_dsos{$needed})) { print STDERR "Error: Your DSO wants $needed, but it isn't exported by httpd or special DSOs.\n"; $problem_found = 1; $rc = 1; } } if (!$problem_found) { print STDERR "Your DSO should be able to resolve all symbols from httpd.\n"; foreach my $onesym (@needed_from_other) { if (!exists($available_from_apr{$onesym})) { print STDERR "Unresolved symbol: $onesym\n"; } } @non_apr = grep !/apr_/, @needed_from_other; if (scalar(@non_apr) > 0) { print STDERR "If it won't load, perhaps it is due to one of these symbols:\n"; print STDERR " @non_apr\n"; } } } sub get_dso_requirements { open(DSO, "dump -Tv $dso |") or die "can't run \"dump -Tv $dso\": $?"; while () { my $line = $_; chomp($line); if ($dbglvl > 0) { print "parsing `$line'...\n"; } if ($line =~ /\s+undef\s+IMP\s+..\s+EXTref\s+\.\.\s+([A-Za-z_\d]+)/) { my $sym = $1; if ($sym =~ /^ap_/ or $sym =~ /^unixd_/ or $sym eq "core_module") { if ($dbglvl > 0) { print "needed from httpd by DSO: $sym\n"; } @needed_from_httpd = (@needed_from_httpd, $sym); } else { if ($dbglvl > 0) { print "needed from elsewhere by DSO: $sym\n"; } @needed_from_other = (@needed_from_other, $sym); } } elsif ($dbglvl > 0) { print " (ignored)\n"; } } close(DSO); } sub get_httpd_exports { open(HTTPD, "dump -Tv $prefix/bin/httpd |") or die "can't run \"dump -Tv $prefix/bin/httpd\": $?"; while () { if (/\s+([A-Za-z_\d]+)\s*$/) { # print "from httpd: $1\n"; $available_from_httpd{$1} = 1; } } close(HTTPD); } sub get_apr_exports { my $tmpname; my $aprname; my $apuname; my $found; $found = 0; for $tmpname ("libapr.so", "libapr-0.so") { $aprname = "$prefix/lib/$tmpname"; if (-f $aprname) { $found = 1; last; } } if (!$found) { print STDERR "libapr[-0].so wasn't found; is prefix $prefix correct?\n"; exit(1); } $found = 0; for $tmpname ("libaprutil.so", "libaprutil-0.so") { $apuname = "$prefix/lib/$tmpname"; if (-f $apuname) { $found = 1; last; } } if (!$found) { print STDERR "libaprutil[-0].so wasn't found; is prefix $prefix correct?\n"; exit(1); } open(APR, "dump -Tv $aprname |") or die "can't dump apr: $?"; while () { if (/\s+([A-Za-z_\d]+)\s*$/) { $available_from_apr{$1} = 1; } } close(APR); open(APR, "dump -Tv $apuname |") or die "can't dump apr-util: $?"; while () { if (/\s+([A-Za-z_\d]+)\s*$/) { $available_from_apr{$1} = 1; } } close(APR); } sub get_special_dso_exports { foreach my $dso (("mod_proxy.so", "mod_dav.so")) { if (! -e "$prefix/modules/$dso") { print "no $dso in your configuration (not an error, just looking)...\n"; next; } open(DSO, "dump -Tv $prefix/modules/$dso |") or die "can't run \"dump -Tv $prefix/modules/$dso\": $?"; while () { if (/\s+([A-Za-z_\d]+)\s*$/) { # print "$1\n"; $available_from_special_dsos{$1} = 1; } } close(DSO); } }