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