[PATCH 1/1] dpkg-gensymbols: Remove useless version script node symbols
Given a version script "test.sym":
LIBTEST_1
{
};
clang -shared /dev/null -o example.so -Wl,--version-script=test.sym -fuse-ld=ld
llvm-nm -D example.so:
0000000000000000 A LIBTEST_1@@LIBTEST_1
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w __cxa_finalize
w __gmon_start__
Other linkers such as LLVM lld and GNU gold don't generate the LIBTEST_1@@LIBTEST_1.
It's a nullptr SHN_ABS symbol meaning it's completely useless in practice.
Detecting these in symbol_is_internal() isn't sufficient as there're existing symbol
files with these symbols.
As such I've:
* Added Dpkg::Shlibs::Symbol::get_internal() to classify such symbols.
* Added with_internal option Dpkg::Shlibs::SymbolFile to allow omitting these symbols.
* Changed dpkg-gensymbols to keep such symbols for before, but not after. This allows
graceful removal of these from existing symbol files.
---
debian/changelog | 5 ++++
scripts/Dpkg/Shlibs/Symbol.pm | 12 ++++++++++
scripts/Dpkg/Shlibs/SymbolFile.pm | 2 ++
scripts/dpkg-gensymbols.pl | 2 +-
scripts/t/Dpkg_Shlibs.t | 24 +++++++++++++++++--
.../t/Dpkg_Shlibs/symbols.internal-existing | 5 ++++
6 files changed, 47 insertions(+), 3 deletions(-)
create mode 100644 scripts/t/Dpkg_Shlibs/symbols.internal-existing
diff --git a/debian/changelog b/debian/changelog
index ecf0e8a2a..9c0128fc0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,7 +1,12 @@
dpkg (1.21.0) UNRELEASED; urgency=medium
+ [ Guillem Jover ]
*
+ [ Raul Tambre ]
+ * dpkg-gensymbols: ignore invalid ld version script tag symbols.
+ Closes: #992796
+
-- Guillem Jover <guillem@debian.org> Wed, 14 Apr 2021 00:04:18 +0200
dpkg (1.20.8) unstable; urgency=medium
diff --git a/scripts/Dpkg/Shlibs/Symbol.pm b/scripts/Dpkg/Shlibs/Symbol.pm
index 142992b89..0ec691541 100644
--- a/scripts/Dpkg/Shlibs/Symbol.pm
+++ b/scripts/Dpkg/Shlibs/Symbol.pm
@@ -185,6 +185,18 @@ sub initialize {
}
}
+sub get_internal {
+ my $self = shift;
+
+ # GNU ld generates useless SHN_ABS symbols for each node in version scripts.
+ # See Debian bug #992796.
+ if ($self->{symbol} =~ /^(.*)[@]+\1$/) {
+ return 'tag-symbol';
+ }
+
+ return '';
+}
+
sub get_symbolname {
my $self = shift;
diff --git a/scripts/Dpkg/Shlibs/SymbolFile.pm b/scripts/Dpkg/Shlibs/SymbolFile.pm
index d492055b4..c1a5ebad0 100644
--- a/scripts/Dpkg/Shlibs/SymbolFile.pm
+++ b/scripts/Dpkg/Shlibs/SymbolFile.pm
@@ -289,6 +289,7 @@ sub output {
my ($self, $fh, %opts) = @_;
$opts{template_mode} //= 0;
$opts{with_deprecated} //= 1;
+ $opts{with_internal} //= 0;
$opts{with_pattern_matches} //= 0;
my $res = '';
foreach my $soname (sort $self->get_sonames()) {
@@ -328,6 +329,7 @@ sub output {
foreach my $sym (sort { $a->get_symboltempl() cmp
$b->get_symboltempl() } @symbols) {
next if $sym->{deprecated} and not $opts{with_deprecated};
+ next if not $opts{with_internal} and $sym->get_internal();
# Do not dump symbols from foreign arch unless dumping a template.
next if not $opts{template_mode} and
not $sym->arch_is_concerned($self->get_arch());
diff --git a/scripts/dpkg-gensymbols.pl b/scripts/dpkg-gensymbols.pl
index afc84015d..353df514c 100755
--- a/scripts/dpkg-gensymbols.pl
+++ b/scripts/dpkg-gensymbols.pl
@@ -301,7 +301,7 @@ unless ($quiet) {
} else {
$file_label = 'new_symbol_file';
}
- $ref_symfile->output($before, package => $oppackage, template_mode => 1);
+ $ref_symfile->output($before, package => $oppackage, template_mode => 1, with_internal => 1);
$symfile->output($after, package => $oppackage, template_mode => 1);
seek $before, 0, 0;
diff --git a/scripts/t/Dpkg_Shlibs.t b/scripts/t/Dpkg_Shlibs.t
index 32436741f..97d0ce486 100644
--- a/scripts/t/Dpkg_Shlibs.t
+++ b/scripts/t/Dpkg_Shlibs.t
@@ -22,7 +22,7 @@ use Test::Dpkg qw(:needs :paths);
use Cwd;
use IPC::Cmd qw(can_run);
-plan tests => 150;
+plan tests => 152;
$ENV{DEB_BUILD_ARCH} = 'amd64';
$ENV{DEB_HOST_ARCH} = 'amd64';
@@ -191,7 +191,7 @@ sub save_load_test {
my ($symfile, $comment, @opts) = @_;
my $save_file = File::Temp->new();
- $symfile->save($save_file->filename, @opts);
+ $symfile->save($save_file->filename, @opts, with_internal => 1);
my $dup = Dpkg::Shlibs::SymbolFile->new(file => $save_file->filename);
# Force sync of non-stored attributes
$dup->{file} = $symfile->{file};
@@ -603,6 +603,26 @@ $tmp->{testfield} = 3;
is ( $sym->{teststruct}{foo}, 1, 'original field "foo" not changed' );
is ( $sym->{testfield}, 1, 'original field "testfield" not changed' );
+# Test symbols previously considered non-internal
+$sym_file = Dpkg::Shlibs::SymbolFile->new(file => "$datadir/symbols.internal-existing");
+
+open $io, '>', \$io_data or die "cannot open io string\n";
+$sym_file->output($io);
+is($io_data,
+'libexample.so.1 libexample1 #MINVER#
+ example1@LIBEXAMPLE_1 0
+ example2@LIBEXAMPLE_30 30
+', 'internal symbols removed');
+
+open my $sym_file_data, '<', "$datadir/symbols.internal-existing"
+ or die "$datadir/symbols.internal-existing: $!";
+open $io, '>', \$io_data or die "cannot open io string\n";
+$sym_file->output($io, with_internal => 1);
+{
+ local $/ = undef;
+ is($io_data, <$sym_file_data>, 'with_internal same as input');
+}
+
############ Test symbol patterns ###########
SKIP: {
diff --git a/scripts/t/Dpkg_Shlibs/symbols.internal-existing b/scripts/t/Dpkg_Shlibs/symbols.internal-existing
new file mode 100644
index 000000000..e8922e8c3
--- /dev/null
+++ b/scripts/t/Dpkg_Shlibs/symbols.internal-existing
@@ -0,0 +1,5 @@
+libexample.so.1 libexample1 #MINVER#
+ LIBEXAMPLE_1@LIBEXAMPLE_1 1
+ LIBEXAMPLE_30@@LIBEXAMPLE_30 30
+ example1@LIBEXAMPLE_1 0
+ example2@LIBEXAMPLE_30 30
--
2.33.0
Reply to: