diff --git a/Makefile.am b/Makefile.am index 67f6c0ed6e75f4ceacc93ddf1051709ec7cde20f..8107c736e0bc07d622caaf90dc54123490c342e7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -152,7 +152,8 @@ nobase_insttests_LTLIBRARIES = tests/red/libhelper.la \ tests/lib/libnotgles.la \ tests/shim/libnotgl.la \ tests/shim/libnotgles.la -nobase_dist_insttests_DATA = tests/CapsuleTest.pm +nobase_dist_insttests_DATA = tests/CapsuleTest.pm \ + tests/CapsuleTestDpkg.pm # Install the source code so we can rebuild it inside a container if we want to nobase_dist_insttests_DATA += examples/shim/libGL.so.1.excluded \ examples/shim/libGL.so.1.shared \ @@ -295,6 +296,7 @@ AM_TESTS_ENVIRONMENT = export CAPSULE_CFLAGS="-I$(abs_top_srcdir export G_TEST_BUILDDIR="$(abs_builddir)";\ export G_DEBUG=gc-friendly; \ export MALLOC_CHECK_=2; \ + export NM="$(NM)"; \ export PKG_CONFIG_PATH="$(abs_builddir)/data"; test_extra_programs = tests/notgl-user \ tests/notgl-helper-user \ diff --git a/debian/copyright b/debian/copyright index 9a8ec1d83411872d997e0f1a348ef8cd69a2ffb6..4c25d9d7e1b28d00218f0da31af121a426604e6c 100644 --- a/debian/copyright +++ b/debian/copyright @@ -10,6 +10,13 @@ Copyright: © 2017 Collabora Ltd. License: LGPL-2.1+ +Files: + tests/CapsuleTestDpkg.pm +Copyright: + © 2007 Raphaël Hertzog + © 2009-2010 Modestas Vainius +License: GPL-2+ + Files: build-aux/git-version-gen Copyright: @@ -40,6 +47,23 @@ Comment: On Debian systems, the full text of the GNU Lesser General Public License version 2.1 can be found in the file '/usr/share/common-licenses/LGPL-2.1'. +License: GPL-2+ + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +Comment: + On Debian systems, the full text of the GNU General Public License + version 2 can be found in the file '/usr/share/common-licenses/GPL-2'. + License: GPL-3+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/tests/CapsuleTest.pm b/tests/CapsuleTest.pm index 572fca880c202cb3caf99eb69acf8be3a442d3be..1097239fe5c685e125c7be0fb43e3f54b4d51f36 100644 --- a/tests/CapsuleTest.pm +++ b/tests/CapsuleTest.pm @@ -14,6 +14,8 @@ # # You should have received a copy of the GNU Lesser General Public # License along with libcapsule. If not, see <http://www.gnu.org/licenses/>. +# +# Note that get_symbols_with_nm() uses some GPL-2+ code taken from dpkg. package CapsuleTest; @@ -28,12 +30,14 @@ use Test::More; our @EXPORT = qw( diag_multiline + get_symbols_with_nm run_ok run_verbose skip_all_unless_bwrap $CAPSULE_INIT_PROJECT_TOOL $CAPSULE_SYMBOLS_TOOL $CAPSULE_VERSION_TOOL + $NM $PKG_CONFIG $builddir $srcdir @@ -99,6 +103,18 @@ unless (defined $CAPSULE_VERSION_TOOL) { chomp $CAPSULE_VERSION_TOOL; } +=item $NM + +The B<nm>(1) symbol-name-listing utility, configured for BSD output format. + +=cut + +our $NM = $ENV{NM}; + +if (! length $NM) { + $NM = 'nm -B'; +} + =item $srcdir An appropriate directory to find non-generated files: the top directory @@ -192,6 +208,43 @@ sub skip_all_unless_bwrap { } } +=item get_symbols_with_nm(I<LIBRARY>) + +Return a list of symbols found in I<LIBRARY>, in the same format +that capsule-symbols would use. + +=cut + +sub get_symbols_with_nm { + my $library = shift; + my $output; + + run_ok([split(' ', $NM), '--dynamic', '--extern-only', '--defined-only', + '--with-symbol-versions', $library], '>', \$output); + my @symbols_produced; + foreach my $line (split /\n/, $output) { + if ($line =~ m/^[[:xdigit:]]+\s+[ABCDGIRSTW]+\s+([^@]+)(\@\@?.*)?/) { + my $symbol = $1; + my $version = $2; + require CapsuleTestDpkg; + next if CapsuleTestDpkg::symbol_is_blacklisted($symbol); + next if "\@\@$symbol" eq $version; + + # Put them in the same format that capsule-symbols uses + if (length $version && $version ne '@@Base') { + push @symbols_produced, "$symbol $version"; + } + else { + push @symbols_produced, "$symbol "; + } + } + } + foreach my $sym (@symbols_produced) { + diag "- $sym"; + } + return sort @symbols_produced; +} + =back =head1 ENVIRONMENT @@ -221,6 +274,10 @@ if (length $ENV{CAPSULE_TESTS_KEEP_TEMP}) { B<capsule-version>(1) +=item NM + +The B<nm>(1) symbol-name-listing utility, if not C<nm -B>. + =item PKG_CONFIG B<pkg-config>(1) diff --git a/tests/CapsuleTestDpkg.pm b/tests/CapsuleTestDpkg.pm new file mode 100644 index 0000000000000000000000000000000000000000..dd23d788d0d44248466bb31bf85342fd6a8270f9 --- /dev/null +++ b/tests/CapsuleTestDpkg.pm @@ -0,0 +1,81 @@ +# Exerpts from Dpkg::Shlibs::SymbolFile +# +# Copyright © 2007 Raphaël Hertzog <hertzog@debian.org> +# Copyright © 2009-2010 Modestas Vainius <modax@debian.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +package CapsuleTestDpkg; + +use strict; +use warnings; + +my %blacklist = ( + __bss_end__ => 1, # arm + __bss_end => 1, # arm + _bss_end__ => 1, # arm + __bss_start => 1, # ALL + __bss_start__ => 1, # arm + __data_start => 1, # arm + __do_global_ctors_aux => 1, # ia64 + __do_global_dtors_aux => 1, # ia64 + __do_jv_register_classes => 1, # ia64 + _DYNAMIC => 1, # ALL + _edata => 1, # ALL + _end => 1, # ALL + __end__ => 1, # arm + __exidx_end => 1, # armel + __exidx_start => 1, # armel + _fbss => 1, # mips, mipsel + _fdata => 1, # mips, mipsel + _fini => 1, # ALL + _ftext => 1, # mips, mipsel + _GLOBAL_OFFSET_TABLE_ => 1, # hppa, mips, mipsel + __gmon_start__ => 1, # hppa + __gnu_local_gp => 1, # mips, mipsel + _gp => 1, # mips, mipsel + _init => 1, # ALL + _PROCEDURE_LINKAGE_TABLE_ => 1, # sparc, alpha + _SDA2_BASE_ => 1, # powerpc + _SDA_BASE_ => 1, # powerpc +); + +for my $i (14 .. 31) { + # Many powerpc specific symbols + $blacklist{"_restfpr_$i"} = 1; + $blacklist{"_restfpr_$i\_x"} = 1; + $blacklist{"_restgpr_$i"} = 1; + $blacklist{"_restgpr_$i\_x"} = 1; + $blacklist{"_savefpr_$i"} = 1; + $blacklist{"_savegpr_$i"} = 1; +} + +sub symbol_is_blacklisted { + my ($symbol, $include_groups) = @_; + + return 1 if exists $blacklist{$symbol}; + + # The ARM Embedded ABI spec states symbols under this namespace as + # possibly appearing in output objects. + return 1 if not ${$include_groups}{aeabi} and $symbol =~ /^__aeabi_/; + + # The GNU implementation of the OpenMP spec, specifies symbols under + # this namespace as possibly appearing in output objects. + return 1 if not ${$include_groups}{gomp} + and $symbol =~ /^\.gomp_critical_user_/; + + return 0; +} + +1; diff --git a/tests/gl-shim.pl b/tests/gl-shim.pl index 4c92d9c6ff4090a512cd040c577d5726dd5fe71c..8db5fc17f85599ab3e9024a37998b5ecf088478b 100755 --- a/tests/gl-shim.pl +++ b/tests/gl-shim.pl @@ -44,31 +44,41 @@ if (length $ENV{CAPSULE_TESTS_UNINSTALLED}) { my $examples = "$srcdir/examples"; +my @sonames = qw(libGL.so.1 libX11.so.6 libXext.so.6 libxcb-dri2.so.0 + libxcb-glx.so.0 libxcb-present.so.0 libxcb-sync.so.1 libxcb.so.1); + run_ok([$CAPSULE_INIT_PROJECT_TOOL, '--runtime-tree=/run/host', '--set-version=1.0.0', "--symbols-from=$examples/shim", - 'libGL.so.1', - 'libX11.so.6', - 'libXext.so.6', - 'libxcb-dri2.so.0', - 'libxcb-glx.so.0', - 'libxcb-present.so.0', - 'libxcb-sync.so.1', - 'libxcb.so.1', + @sonames, ]); run_ok([ 'sh', '-euc', 'cd "$1"; shift; ./configure "$@"', 'sh', "$test_tempdir/libGL-proxy", ], '>&2'); run_ok(['make', '-C', "$test_tempdir/libGL-proxy", 'V=1'], '>&2'); -ok(-e "$test_tempdir/libGL-proxy/libGL.la"); -ok(-e "$test_tempdir/libGL-proxy/.libs/libGL.so"); -ok(-e "$test_tempdir/libGL-proxy/.libs/libGL.so.1"); -ok(-e "$test_tempdir/libGL-proxy/.libs/libGL.so.1.0.0"); -# TODO: I can't run capsule-symbols on the generated proxy on Debian -# unstable, possibly caused by glvnd libGL? +foreach my $soname (@sonames) { + my $basename = $soname; + $basename =~ s/\.so\..*$//; + + ok(-e "$test_tempdir/libGL-proxy/$basename.la"); + ok(-e "$test_tempdir/libGL-proxy/.libs/$basename.so"); + ok(-e "$test_tempdir/libGL-proxy/.libs/$soname"); + ok(-e "$test_tempdir/libGL-proxy/.libs/$soname.0.0"); + + my @symbols_wanted; + open my $fh, "$examples/shim/$soname.symbols"; + while (defined(my $line = <$fh>)) { + chomp $line; + push @symbols_wanted, $line; + } + + my @symbols_produced = + get_symbols_with_nm("$test_tempdir/libGL-proxy/.libs/$soname"); + is_deeply \@symbols_wanted, [grep {! m/^capsule_meta $/} @symbols_produced]; +} chdir '/'; done_testing; diff --git a/tests/init-project.pl b/tests/init-project.pl index afa9d2934c1b897617f09b39fa10cc581eacb445..36b6a75a75cf830db94668ec36eecfc8ef9d8f60 100755 --- a/tests/init-project.pl +++ b/tests/init-project.pl @@ -104,13 +104,18 @@ sub uniq { return @unique; } +my @symbols_produced = + get_symbols_with_nm("$test_tempdir/libz-proxy/.libs/libz.so.1"); +is_deeply \@symbols_wanted, [grep {! m/^capsule_meta $/} @symbols_produced]; + +# Do the same thing with capsule-symbols. # We can't load the library unless we let it load its real # implementation, and it's hardwired to get that from /host, which # probably doesn't exist... so cheat by overriding it. run_ok(['env', "CAPSULE_PREFIX=/", @libcapsule_environment, $CAPSULE_SYMBOLS_TOOL, "$test_tempdir/libz-proxy/.libs/libz.so.1"], '>', \$output); -my @symbols_produced = grep { !/capsule_meta\b/ } sort(split /\n/, $output); +@symbols_produced = grep { !/capsule_meta\b/ } sort(split /\n/, $output); foreach my $sym (@symbols_produced) { diag "- $sym"; } @@ -190,6 +195,10 @@ run_ok(['make', '-C', "$test_tempdir/libz-proxy", 'V=1', } run_ok(['make', '-C', "$test_tempdir/libz-proxy", 'V=1'], '>&2'); +@symbols_produced = + get_symbols_with_nm("$test_tempdir/libz-proxy/.libs/libz.so.1"); +is_deeply \@symbols_wanted, [grep {! m/^capsule_meta $/} @symbols_produced]; + run_ok(['env', "CAPSULE_PREFIX=/", @libcapsule_environment, $CAPSULE_SYMBOLS_TOOL, "$test_tempdir/libz-proxy/.libs/libz.so.1"], '>', \$output);