1 | #! /usr/bin/env perl
|
---|
2 | # -*- mode: Perl -*-
|
---|
3 | # Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
|
---|
4 | #
|
---|
5 | # Licensed under the Apache License 2.0 (the "License"). You may not use
|
---|
6 | # this file except in compliance with the License. You can obtain a copy
|
---|
7 | # in the file LICENSE in the source distribution or at
|
---|
8 | # https://www.openssl.org/source/license.html
|
---|
9 |
|
---|
10 | use strict;
|
---|
11 | use File::Spec::Functions qw(devnull);
|
---|
12 | use OpenSSL::Test qw(:DEFAULT srctop_file srctop_dir bldtop_dir bldtop_file);
|
---|
13 | use OpenSSL::Test::Utils;
|
---|
14 |
|
---|
15 | BEGIN {
|
---|
16 | setup("test_symbol_presence");
|
---|
17 | }
|
---|
18 |
|
---|
19 | use lib srctop_dir('Configurations');
|
---|
20 | use lib bldtop_dir('.');
|
---|
21 | use platform;
|
---|
22 |
|
---|
23 | plan skip_all => "Test is disabled on NonStop" if config('target') =~ m|^nonstop|;
|
---|
24 | # MacOS arranges symbol names differently
|
---|
25 | plan skip_all => "Test is disabled on MacOS" if config('target') =~ m|^darwin|;
|
---|
26 | plan skip_all => "This is unsupported on MSYS, MinGW or MSWin32"
|
---|
27 | if $^O eq 'msys' or $^O eq 'MSWin32' or config('target') =~ m|^mingw|;
|
---|
28 | plan skip_all => "Only useful when building shared libraries"
|
---|
29 | if disabled("shared");
|
---|
30 |
|
---|
31 | my @libnames = ("crypto", "ssl");
|
---|
32 | my $testcount = scalar @libnames;
|
---|
33 |
|
---|
34 | plan tests => $testcount * 2;
|
---|
35 |
|
---|
36 | note
|
---|
37 | "NOTE: developer test! It's possible that it won't run on your\n",
|
---|
38 | "platform, and that's perfectly fine. This is mainly for developers\n",
|
---|
39 | "on Unix to check that our shared libraries are consistent with the\n",
|
---|
40 | "ordinals (util/*.num in the source tree), something that should be\n",
|
---|
41 | "good enough a check for the other platforms as well.\n";
|
---|
42 |
|
---|
43 | foreach my $libname (@libnames) {
|
---|
44 | SKIP:
|
---|
45 | {
|
---|
46 | my $shlibname = platform->sharedlib("lib$libname");
|
---|
47 | my $shlibpath = bldtop_file($shlibname);
|
---|
48 | *OSTDERR = *STDERR;
|
---|
49 | *OSTDOUT = *STDOUT;
|
---|
50 | open STDERR, ">", devnull();
|
---|
51 | open STDOUT, ">", devnull();
|
---|
52 | my @nm_lines = map { s|\R$||; $_ } `nm -DPg $shlibpath 2> /dev/null`;
|
---|
53 | close STDERR;
|
---|
54 | close STDOUT;
|
---|
55 | *STDERR = *OSTDERR;
|
---|
56 | *STDOUT = *OSTDOUT;
|
---|
57 | skip "Can't run 'nm -DPg $shlibpath' => $?... ignoring", 2
|
---|
58 | unless $? == 0;
|
---|
59 |
|
---|
60 | my $bldtop = bldtop_dir();
|
---|
61 | my @def_lines;
|
---|
62 | indir $bldtop => sub {
|
---|
63 | my $mkdefpath = srctop_file("util", "mkdef.pl");
|
---|
64 | my $libnumpath = srctop_file("util", "lib$libname.num");
|
---|
65 | @def_lines = map { s|\R$||; $_ } `$^X $mkdefpath --ordinals $libnumpath --name $libname --OS linux 2> /dev/null`;
|
---|
66 | ok($? == 0, "running 'cd $bldtop; $^X $mkdefpath --ordinals $libnumpath --name $libname --OS linux' => $?");
|
---|
67 | }, create => 0, cleanup => 0;
|
---|
68 |
|
---|
69 | note "Number of lines in \@nm_lines before massaging: ", scalar @nm_lines;
|
---|
70 | note "Number of lines in \@def_lines before massaging: ", scalar @def_lines;
|
---|
71 |
|
---|
72 | # Massage the nm output to only contain defined symbols
|
---|
73 | @nm_lines =
|
---|
74 | sort
|
---|
75 | map {
|
---|
76 | # Drop the first space and everything following it
|
---|
77 | s| .*||;
|
---|
78 | # Drop OpenSSL dynamic version information if there is any
|
---|
79 | s|\@\@.+$||;
|
---|
80 | # Return the result
|
---|
81 | $_
|
---|
82 | }
|
---|
83 | grep(m|.* [BCDST] .*|, @nm_lines);
|
---|
84 |
|
---|
85 | # Massage the mkdef.pl output to only contain global symbols
|
---|
86 | # The output we got is in Unix .map format, which has a global
|
---|
87 | # and a local section. We're only interested in the global
|
---|
88 | # section.
|
---|
89 | my $in_global = 0;
|
---|
90 | @def_lines =
|
---|
91 | sort
|
---|
92 | map { s|;||; s|\s+||g; $_ }
|
---|
93 | grep { $in_global = 1 if m|global:|;
|
---|
94 | $in_global = 0 if m|local:|;
|
---|
95 | $in_global = 0 if m|\}|;
|
---|
96 | $in_global && m|;|; } @def_lines;
|
---|
97 |
|
---|
98 | note "Number of lines in \@nm_lines after massaging: ", scalar @nm_lines;
|
---|
99 | note "Number of lines in \@def_lines after massaging: ", scalar @def_lines;
|
---|
100 |
|
---|
101 | # Maintain lists of symbols that are missing in the shared library,
|
---|
102 | # or that are extra.
|
---|
103 | my @missing = ();
|
---|
104 | my @extra = ();
|
---|
105 |
|
---|
106 | while (scalar @nm_lines || scalar @def_lines) {
|
---|
107 | my $nm_first = $nm_lines[0];
|
---|
108 | my $def_first = $def_lines[0];
|
---|
109 |
|
---|
110 | if (!defined($nm_first)) {
|
---|
111 | push @missing, shift @def_lines;
|
---|
112 | } elsif (!defined($def_first)) {
|
---|
113 | push @extra, shift @nm_lines;
|
---|
114 | } elsif ($nm_first gt $def_first) {
|
---|
115 | push @missing, shift @def_lines;
|
---|
116 | } elsif ($nm_first lt $def_first) {
|
---|
117 | push @extra, shift @nm_lines;
|
---|
118 | } else {
|
---|
119 | shift @def_lines;
|
---|
120 | shift @nm_lines;
|
---|
121 | }
|
---|
122 | }
|
---|
123 |
|
---|
124 | if (scalar @missing) {
|
---|
125 | note "The following symbols are missing in ${shlibname}:";
|
---|
126 | foreach (@missing) {
|
---|
127 | note " $_";
|
---|
128 | }
|
---|
129 | }
|
---|
130 | if (scalar @extra) {
|
---|
131 | note "The following symbols are extra in ${shlibname}:";
|
---|
132 | foreach (@extra) {
|
---|
133 | note " $_";
|
---|
134 | }
|
---|
135 | }
|
---|
136 | ok(scalar @missing == 0,
|
---|
137 | "check that there are no missing symbols in ${shlibname}");
|
---|
138 | }
|
---|
139 | }
|
---|