]> git.sur5r.net Git - bacula/rescue/blob - rescue/linux/cdrom/yaird-0.0.5/perl/SharedLibraries.pm
4288895a0cff2460f701bebd921c74b1b19852b5
[bacula/rescue] / rescue / linux / cdrom / yaird-0.0.5 / perl / SharedLibraries.pm
1 #!perl -w
2 #
3 # SharedLibraries -- what shared libraries an object needs.
4 #   Copyright (C) 2005  Erik van Konijnenburg
5 #
6 #   This program is free software; you can redistribute it and/or modify
7 #   it under the terms of the GNU General Public License as published by
8 #   the Free Software Foundation; either version 2 of the License, or
9 #   (at your option) any later version.
10 #
11 #   This program is distributed in the hope that it will be useful,
12 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #   GNU General Public License for more details.
15 #
16 #   You should have received a copy of the GNU General Public License
17 #   along with this program; if not, write to the Free Software
18 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 #
20 use strict;
21 use warnings;
22 use Base;
23 use Conf;
24 package SharedLibraries;
25
26
27 #
28 # find -- find the shared libraries that are needed by an executable.
29 # Try to find libraries with ldd first.  That works only with executables
30 # linked with glibc, so if ldd finds nothing, we look for traces of klibc.
31 #
32 sub find ($) {
33         my ($executable) = @_;
34         my $in;
35         my $result = [];
36
37         if ($executable !~ m!^([.\w/-]+)$!) {
38                 # taint check.
39                 Base::fatal ("odd characters in executable name: $executable");
40         }
41         $executable = $1;
42
43         if (! open ($in, "-|", "/usr/bin/ldd $executable")) {
44                 Base::fatal ("can't read ldd for $executable");
45         }
46         while (defined (my $line = <$in>)) {
47                 chomp $line;
48                 last if ($line =~ /statically linked/);
49                 if ($line =~ /not a dynamic executable/) {
50                         #
51                         # Happens when doing ldd on a shell script
52                         # or kernel module (these have x-bit on in FC3,
53                         # no idea why they would do that).  Ldd exit status
54                         # will be non-zero.
55                         # Ldd only understands executables compiled with
56                         # glibc; try to find use of other libraries.
57                         #
58                         return findLibr ($executable);
59                 }
60                 elsif ($line =~ m!.* => (/.+) \(0x[0-9a-fA-F]+\)$!) {
61                         #
62                         # in ldd 2.3.2 (Debian) output looks like this:
63                         # /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0xb7fea000)
64                         #
65                         push @{$result}, $1;
66                 }
67                 elsif ($line =~ m!^\s*(/[^\s]+) \(0x[0-9a-fA-F]+\)$!) {
68                         #
69                         # But ldd 2.3.3 (FC3) has this:
70                         # /lib/ld-linux.so.2 (0x0056f000)
71                         #
72                         push @{$result}, $1;
73                 }
74                 elsif ($line =~ m!.* =>  \(0x[0-9a-fA-F]+\)$!) {
75                         #
76                         # And eg amd64 also has this:
77                         #       linux-gate.so.1 =>  (0x00000000)
78                         #
79                         # note the double space.  This is a section not
80                         # loaded from a file but mapped in by the kernel.
81                         # The kernel puts some code with proper syscall
82                         # linkage here.
83                         # See http://lkml.org/lkml/2003/6/18/156
84                         #
85                         next;
86                 }
87                 else {
88                         Base::fatal ("unexpected ldd output for $executable: $line");
89                 }
90         }
91         if (! close ($in)) {
92                 Base::fatal ("could not read ldd for $executable");
93         }
94         return $result;
95 }
96
97
98 #
99 # findLibr -- given a filename, return name of dynamic loader.
100 # non-ELF files or non-executable ELF files return empty list,
101 # corrupt ELF files are fatal error.
102 # If there are shared libraries without absolute path,
103 # fatal error, since we don't know how the path the library uses
104 # to look up the shared library.
105 #
106 sub findLibr ($) {
107         my ($executable) = @_;
108         my $in;
109         my $result = [];
110         my $auxDir = Conf::get ('auxDir');
111
112         if (! open ($in, "-|", "$auxDir/findlibs -q $executable")) {
113                 Base::fatal ("can't run findlibr for $executable");
114         }
115
116         while (defined (my $line = <$in>)) {
117                 chomp $line;
118                 if ($line =~ /^interpreter: ([\w.\/-]+)$/) {
119                         push @{$result}, $1;
120                 }
121                 elsif ($line =~ /^needed: ([\w.\/-]+)$/) {
122                         if (Base::isAbsolute ($1)) {
123                                 push @{$result}, $1;
124                         }
125                         else {
126                                 fatal ("shared library without glibc: $1 in $executable");
127                         }
128                 }
129                 else {
130                         bug ("odd output for findlibs");
131                 }
132         }
133
134         if (! close ($in)) {
135                 Base::fatal ("could not run findlibr for $executable");
136         }
137         return $result;
138 }
139
140 1;