Skip to content
Snippets Groups Projects
Commit 00e16f2f authored by Simon McVittie's avatar Simon McVittie
Browse files

tests: use nm -B (like libtool does) to enumerate symbols


This protects us from potential bugs in capsule-symbols(1) by
having something else to cross-check our results against.
It also means we can inspect the generated shims for libraries that
we do not actually have and hence cannot load, such as libGL.so.1 on
autobuilders that do not have a graphics stack installed.

Signed-off-by: default avatarSimon McVittie <smcv@collabora.com>
parent 293b1feb
No related branches found
No related tags found
1 merge request!311Build capsule-capture-libs from a bundled copy of libcapsule
...@@ -152,7 +152,8 @@ nobase_insttests_LTLIBRARIES = tests/red/libhelper.la \ ...@@ -152,7 +152,8 @@ nobase_insttests_LTLIBRARIES = tests/red/libhelper.la \
tests/lib/libnotgles.la \ tests/lib/libnotgles.la \
tests/shim/libnotgl.la \ tests/shim/libnotgl.la \
tests/shim/libnotgles.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 # 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 \ nobase_dist_insttests_DATA += examples/shim/libGL.so.1.excluded \
examples/shim/libGL.so.1.shared \ examples/shim/libGL.so.1.shared \
...@@ -295,6 +296,7 @@ AM_TESTS_ENVIRONMENT = export CAPSULE_CFLAGS="-I$(abs_top_srcdir ...@@ -295,6 +296,7 @@ AM_TESTS_ENVIRONMENT = export CAPSULE_CFLAGS="-I$(abs_top_srcdir
export G_TEST_BUILDDIR="$(abs_builddir)";\ export G_TEST_BUILDDIR="$(abs_builddir)";\
export G_DEBUG=gc-friendly; \ export G_DEBUG=gc-friendly; \
export MALLOC_CHECK_=2; \ export MALLOC_CHECK_=2; \
export NM="$(NM)"; \
export PKG_CONFIG_PATH="$(abs_builddir)/data"; export PKG_CONFIG_PATH="$(abs_builddir)/data";
test_extra_programs = tests/notgl-user \ test_extra_programs = tests/notgl-user \
tests/notgl-helper-user \ tests/notgl-helper-user \
......
...@@ -10,6 +10,13 @@ Copyright: ...@@ -10,6 +10,13 @@ Copyright:
© 2017 Collabora Ltd. © 2017 Collabora Ltd.
License: LGPL-2.1+ License: LGPL-2.1+
Files:
tests/CapsuleTestDpkg.pm
Copyright:
© 2007 Raphaël Hertzog
© 2009-2010 Modestas Vainius
License: GPL-2+
Files: Files:
build-aux/git-version-gen build-aux/git-version-gen
Copyright: Copyright:
...@@ -40,6 +47,23 @@ Comment: ...@@ -40,6 +47,23 @@ Comment:
On Debian systems, the full text of the GNU Lesser General Public License 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'. 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+ License: GPL-3+
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
# #
# You should have received a copy of the GNU Lesser General Public # You should have received a copy of the GNU Lesser General Public
# License along with libcapsule. If not, see <http://www.gnu.org/licenses/>. # 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; package CapsuleTest;
...@@ -28,12 +30,14 @@ use Test::More; ...@@ -28,12 +30,14 @@ use Test::More;
our @EXPORT = qw( our @EXPORT = qw(
diag_multiline diag_multiline
get_symbols_with_nm
run_ok run_ok
run_verbose run_verbose
skip_all_unless_bwrap skip_all_unless_bwrap
$CAPSULE_INIT_PROJECT_TOOL $CAPSULE_INIT_PROJECT_TOOL
$CAPSULE_SYMBOLS_TOOL $CAPSULE_SYMBOLS_TOOL
$CAPSULE_VERSION_TOOL $CAPSULE_VERSION_TOOL
$NM
$PKG_CONFIG $PKG_CONFIG
$builddir $builddir
$srcdir $srcdir
...@@ -99,6 +103,18 @@ unless (defined $CAPSULE_VERSION_TOOL) { ...@@ -99,6 +103,18 @@ unless (defined $CAPSULE_VERSION_TOOL) {
chomp $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 =item $srcdir
An appropriate directory to find non-generated files: the top directory An appropriate directory to find non-generated files: the top directory
...@@ -192,6 +208,43 @@ sub skip_all_unless_bwrap { ...@@ -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 =back
=head1 ENVIRONMENT =head1 ENVIRONMENT
...@@ -221,6 +274,10 @@ if (length $ENV{CAPSULE_TESTS_KEEP_TEMP}) { ...@@ -221,6 +274,10 @@ if (length $ENV{CAPSULE_TESTS_KEEP_TEMP}) {
B<capsule-version>(1) B<capsule-version>(1)
=item NM
The B<nm>(1) symbol-name-listing utility, if not C<nm -B>.
=item PKG_CONFIG =item PKG_CONFIG
B<pkg-config>(1) B<pkg-config>(1)
......
# 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;
...@@ -44,31 +44,41 @@ if (length $ENV{CAPSULE_TESTS_UNINSTALLED}) { ...@@ -44,31 +44,41 @@ if (length $ENV{CAPSULE_TESTS_UNINSTALLED}) {
my $examples = "$srcdir/examples"; 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, run_ok([$CAPSULE_INIT_PROJECT_TOOL,
'--runtime-tree=/run/host', '--runtime-tree=/run/host',
'--set-version=1.0.0', '--set-version=1.0.0',
"--symbols-from=$examples/shim", "--symbols-from=$examples/shim",
'libGL.so.1', @sonames,
'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([ run_ok([
'sh', '-euc', 'cd "$1"; shift; ./configure "$@"', 'sh', '-euc', 'cd "$1"; shift; ./configure "$@"',
'sh', "$test_tempdir/libGL-proxy", 'sh', "$test_tempdir/libGL-proxy",
], '>&2'); ], '>&2');
run_ok(['make', '-C', "$test_tempdir/libGL-proxy", 'V=1'], '>&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 foreach my $soname (@sonames) {
# unstable, possibly caused by glvnd libGL? 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 '/'; chdir '/';
done_testing; done_testing;
......
...@@ -104,13 +104,18 @@ sub uniq { ...@@ -104,13 +104,18 @@ sub uniq {
return @unique; 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 # We can't load the library unless we let it load its real
# implementation, and it's hardwired to get that from /host, which # implementation, and it's hardwired to get that from /host, which
# probably doesn't exist... so cheat by overriding it. # probably doesn't exist... so cheat by overriding it.
run_ok(['env', "CAPSULE_PREFIX=/", @libcapsule_environment, run_ok(['env', "CAPSULE_PREFIX=/", @libcapsule_environment,
$CAPSULE_SYMBOLS_TOOL, "$test_tempdir/libz-proxy/.libs/libz.so.1"], $CAPSULE_SYMBOLS_TOOL, "$test_tempdir/libz-proxy/.libs/libz.so.1"],
'>', \$output); '>', \$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) { foreach my $sym (@symbols_produced) {
diag "- $sym"; diag "- $sym";
} }
...@@ -190,6 +195,10 @@ run_ok(['make', '-C', "$test_tempdir/libz-proxy", 'V=1', ...@@ -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'); 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, run_ok(['env', "CAPSULE_PREFIX=/", @libcapsule_environment,
$CAPSULE_SYMBOLS_TOOL, "$test_tempdir/libz-proxy/.libs/libz.so.1"], $CAPSULE_SYMBOLS_TOOL, "$test_tempdir/libz-proxy/.libs/libz.so.1"],
'>', \$output); '>', \$output);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment