1#!/usr/bin/perl -w
2# Copyright (C) 1997-2022 Free Software Foundation, Inc.
3# This file is part of the GNU C Library.
4
5# The GNU C Library is free software; you can redistribute it and/or
6# modify it under the terms of the GNU Lesser General Public
7# License as published by the Free Software Foundation; either
8# version 2.1 of the License, or (at your option) any later version.
9
10# The GNU C Library is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13# Lesser General Public License for more details.
14
15# You should have received a copy of the GNU Lesser General Public
16# License along with the GNU C Library; if not, see
17# <https://www.gnu.org/licenses/>.
18
19
20$PACKAGE = "libc";
21$progname = $0;
22if ($ENV{CC}) {
23  $CC = $ENV{CC};
24} else {
25  $CC= "gcc";
26}
27if ($ENV{LD_SO}) {
28  $LD_SO = $ENV{LD_SO};
29} else {
30  $LD_SO = "";
31}
32
33sub usage {
34  print "Usage: test-installation [soversions.mk]\n";
35  print "  --help       print this help, then exit\n";
36  print "  --version    print version number, then exit\n";
37  exit 0;
38}
39
40sub installation_problem {
41  print "The script has found some problems with your installation!\n";
42  print "Please read the FAQ and the README file and check the following:\n";
43  print "- Did you change the gcc specs file (necessary after upgrading from\n";
44  print "  Linux libc5)?\n";
45  print "- Are there any symbolic links of the form libXXX.so to old libraries?\n";
46  print "  Links like libm.so -> libm.so.5 (where libm.so.5 is an old library) are wrong,\n";
47  print "  libm.so should point to the newly installed glibc file - and there should be\n";
48  print "  only one such link (check e.g. /lib and /usr/lib)\n";
49  print "You should restart this script from your build directory after you've\n";
50  print "fixed all problems!\n";
51  print "Btw. the script doesn't work if you're installing GNU libc not as your\n";
52  print "primary library!\n";
53  exit 1;
54}
55
56arglist: while (@ARGV) {
57  if ($ARGV[0] eq "--v" || $ARGV[0] eq "--ve" || $ARGV[0] eq "--ver" ||
58      $ARGV[0] eq "--vers" || $ARGV[0] eq "--versi" ||
59      $ARGV[0] eq "--versio" || $ARGV[0] eq "--version") {
60    print "test-installation (GNU $PACKAGE)\n";
61    print "Copyright (C) 2022 Free Software Foundation, Inc.\n";
62    print "This is free software; see the source for copying conditions.  There is NO\n";
63    print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
64    print "Written by Andreas Jaeger <aj\@arthur.rhein-neckar.de>\n";
65
66    exit 0;
67  } elsif ($ARGV[0] eq "--h" || $ARGV[0] eq "--he" || $ARGV[0] eq "--hel" ||
68	   $ARGV[0] eq "--help") {
69    &usage;
70  } elsif ($ARGV[0] =~ /^-/) {
71    print "$progname: unrecognized option `$ARGV[0]'\n";
72    print "Try `$progname --help' for more information.\n";
73    exit 1;
74  } else {
75    last arglist;
76  }
77}
78
79# We expect none or one argument.
80if ($#ARGV == -1) {
81    $dir = ".";
82    $soversions="soversions.mk";
83    $config="config.make";
84} elsif ($#ARGV == 0) {
85    if (-d $ARGV[0]) {
86      $dir = $ARGV[0];
87      $soversions = "$ARGV[0]/soversions.mk";
88      $config = "$ARGV[0]/config.make";
89    } else {
90      $soversions = $dir = $ARGV[0];
91      $dir =~ s!/?[^/]*/*$!!;
92      $config = $dir . "/config.make";
93    }
94} else {
95    die "Wrong number of arguments.";
96}
97
98if (system ("grep -q \"build-mathvec = yes\" $config") == 0) {
99    $build_mathvec = 1;
100} else {
101    $build_mathvec = 0;
102}
103
104# Read names and versions of all shared libraries that are part of
105# glibc
106open SOVERSIONS, $soversions
107  or die ("Couldn't open $soversions in build directory!");
108
109$link_libs = "";
110%versions = ();
111
112while (<SOVERSIONS>) {
113  next if (/^all-sonames/);
114  chop;
115  if (/^lib/) {
116    ($name, $version)= /^lib(.*)\.so-version=\.(.*)$/;
117    # Filter out some libraries we don't want to link:
118    # - nss_ldap since it's not yet available
119    # - libdb1 since it conflicts with libdb
120    # - libthread_db since it contains unresolved references
121    # - it's just a test NSS module
122    # - We don't provide the libgcc so we don't test it
123    # - libmvec if it wasn't built
124    next if ($build_mathvec == 0 && $name eq "mvec");
125    if ($name ne "nss_ldap" && $name ne "db1"
126	&& $name ne "thread_db"
127	&& $name ne "nss_test1" && $name ne "libgcc_s") {
128      $link_libs .= " -l$name";
129      $versions{$name} = $version;
130    }
131  } elsif ($LD_SO ne "") {
132    ($ld_so_name, $ld_so_version) = split ('\.so\.', $LD_SO);
133  } else {
134    if (/^ld\.so/) {
135      ($ld_so_name, $ld_so_version)= /=(.*)\.so\.(.*)$/;
136    }
137  }
138}
139
140close SOVERSIONS;
141
142# Create test program and link it against all
143# shared libraries
144
145open PRG, ">$dir/test-prg$$.c"
146  or die ("Couldn't write test file $dir/test-prg$$.c");
147
148print PRG '
149#include <stdio.h>
150#include <stdlib.h>
151int main(void) {
152  printf ("Your new glibc installation seems to be ok.\n");
153  exit (0);
154}
155';
156close PRG;
157
158open GCC, "$CC $dir/test-prg$$.c $link_libs -o $dir/test-prg$$ 2>&1 |"
159  or die ("Couldn't execute $CC!");
160
161while (<GCC>) {
162  print $_ if (! /warning/);
163}
164close GCC;
165if ($?) {
166  print "Execution of $CC failed!\n";
167  &installation_problem;
168}
169
170# Test if test program is linked against the right versions of
171# shared libraries
172
173$ok = 1;
174%found = ();
175
176open LDD, "ldd $dir/test-prg$$ |"
177  or die ("Couldn't execute ldd");
178while (<LDD>) {
179  if (/^\s*lib/) {
180    ($name, $version1, $version2) =
181      /^\s*lib(\w*)\.so\.([0-9\.]*)\s*=>.*\.so\.([0-9\.]*)/;
182    $found{$name} = 1;
183    if ($versions{$name} ne $version1 || $version1 ne $version2) {
184      print "Library lib$name is not correctly installed.\n";
185      print "Please check your installation!\n";
186      print "Offending line of ldd output: $_\n";
187      $ok = 0;
188    }
189  }
190  if (/$ld_so_name/) {
191    ($version1) = /$ld_so_name\.so\.([0-9\.]*)/;
192    if ($version1 ne $ld_so_version) {
193      print "The dynamic linker $ld_so_name.so is not correctly installed.\n";
194      print "Please check your installation!\n";
195      print "Offending line of ldd output: $_\n";
196      $ok = 0;
197    }
198  }
199}
200
201close LDD;
202die "ldd execution failed" if $?;
203
204foreach (keys %versions) {
205  unless ($found{$_}) {
206    print "Library lib$_ is not correctly installed since the test program\n";
207    print "was not linked dynamically against it.\n";
208    print "Do you have a file/link lib$_.so?\n";
209    $ok = 0;
210  }
211}
212
213&installation_problem unless $ok;
214
215# Finally execute the test program
216system ("$dir/test-prg$$") == 0
217  or die ("Execution of test program failed");
218
219# Clean up after ourselves
220unlink ("$dir/test-prg$$", "$dir/test-prg$$.c");
221