From d30a1ad04431c245ee606d7825e8a1f3d8e691c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Fri, 30 Aug 2019 13:22:54 +0100 Subject: [PATCH] src: rewrite symfile library checker in Python MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As part of a goal to eliminate Perl from libvirt build tools, rewrite the check-symfile.pl tool in Python. This was a straight conversion, manually going line-by-line to change the syntax from Perl to Python. Thus the overall structure of the file and approach is the same. Tested-by: Cole Robinson Reviewed-by: Ján Tomko Signed-off-by: Daniel P. Berrangé --- Makefile.am | 1 + scripts/check-symfile.py | 80 +++++++++++++++++++++++++++++++++++++++ src/Makefile.am | 5 +-- src/admin/Makefile.inc.am | 4 +- src/check-symfile.pl | 70 ---------------------------------- 5 files changed, 85 insertions(+), 75 deletions(-) create mode 100755 scripts/check-symfile.py delete mode 100755 src/check-symfile.pl diff --git a/Makefile.am b/Makefile.am index df3b948213..fc8dcadaf3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -48,6 +48,7 @@ EXTRA_DIST = \ scripts/augeas-gentest.py \ build-aux/check-spacing.pl \ scripts/check-aclperms.py \ + scripts/check-symfile.py \ scripts/check-symsorting.py \ scripts/header-ifdef.py \ scripts/minimize-po.py \ diff --git a/scripts/check-symfile.py b/scripts/check-symfile.py new file mode 100755 index 0000000000..a543a0fbcd --- /dev/null +++ b/scripts/check-symfile.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# +# Copyright (C) 2012-2019 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library. If not, see +# . + +from __future__ import print_function + +import re +import subprocess +import sys + +if len(sys.argv) < 3: + print("syntax: %s SYMFILE ELFLIB(S)" % sys.argv[0], file=sys.stderr) + +symfile = sys.argv[1] +elflibs = sys.argv[2:] + +wantsyms = {} +gotsyms = {} + +ret = 0 + +with open(symfile, "r") as fh: + for line in fh: + line = line.strip() + if line.find("{") != -1: + continue + if line.find("}") != -1: + continue + if line in ["global:", "local:"]: + continue + if line == "": + continue + if line[0] == '#': + continue + if line.find("*") != -1: + continue + + line = line.strip(";") + + if line in wantsyms: + print("Symbol $1 is listed twice", file=sys.stderr) + ret = 1 + else: + wantsyms[line] = True + +for elflib in elflibs: + nm = subprocess.Popen(["nm", elflib], shell=False, + stdout=subprocess.PIPE).stdout + + for line in nm: + line = line.decode("utf-8") + symmatch = re.search(r'''^\S+\s(?:[TBD])\s(\S+)\s*$''', line) + if symmatch is None: + continue + + gotsyms[symmatch.group(1)] = True + + +for sym in wantsyms.keys(): + if sym in gotsyms: + continue + + print("Expected symbol '%s' is not in ELF library" % sym, file=sys.stderr) + ret = 1 + +sys.exit(ret) diff --git a/src/Makefile.am b/src/Makefile.am index 2aa74dc84c..438ed744c5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -277,15 +277,14 @@ PDWTAGS = \ # rule for libvirt.la. However, checking symbols relies on Linux ELF layout if WITH_LINUX check-symfile: libvirt.syms libvirt.la - $(AM_V_GEN)$(PERL) $(srcdir)/check-symfile.pl libvirt.syms \ - .libs/libvirt.so + $(AM_V_GEN)$(RUNUTF8) $(PYTHON) $(top_srcdir)/scripts/check-symfile.py \ + libvirt.syms .libs/libvirt.so else ! WITH_LINUX check-symfile: endif ! WITH_LINUX check-symsorting: $(AM_V_GEN)$(RUNUTF8) $(PYTHON) $(top_srcdir)/scripts/check-symsorting.py \ $(srcdir) $(SYM_FILES) -EXTRA_DIST += check-symfile.pl # Keep this list synced with RPC_PROBE_FILES PROTOCOL_STRUCTS = \ diff --git a/src/admin/Makefile.inc.am b/src/admin/Makefile.inc.am index 97048df6f3..a02991df68 100644 --- a/src/admin/Makefile.inc.am +++ b/src/admin/Makefile.inc.am @@ -105,8 +105,8 @@ libvirt_admin_la_CFLAGS = \ if WITH_LINUX check-admin-symfile: admin/libvirt_admin.syms libvirt-admin.la - $(AM_V_GEN)$(PERL) $(srcdir)/check-symfile.pl admin/libvirt_admin.syms \ - .libs/libvirt-admin.so + $(AM_V_GEN)$(RUNUTF8) $(PYTHON) $(top_srcdir)/scripts/check-symfile.py \ + admin/libvirt_admin.syms .libs/libvirt-admin.so else ! WITH_LINUX check-admin-symfile: endif ! WITH_LINUX diff --git a/src/check-symfile.pl b/src/check-symfile.pl deleted file mode 100755 index 4f88300864..0000000000 --- a/src/check-symfile.pl +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env perl - -# Copyright (C) 2012-2013 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see -# . - -die "syntax: $0 SYMFILE ELFLIB(S)" unless int(@ARGV) >= 2; - -my $symfile = shift @ARGV; -my @elflibs = @ARGV; - -my %wantsyms; -my %gotsyms; - -my $ret = 0; - -open SYMFILE, $symfile or die "cannot read $symfile: $!"; - -while () { - next if /{/; - next if /}/; - next if /global:/; - next if /local:/; - next if /^\s*$/; - next if /^\s*#/; - next if /\*/; - - die "malformed line $_" unless /^\s*(\S+);$/; - - if (exists $wantsyms{$1}) { - print STDERR "Symbol $1 is listed twice\n"; - $ret = 1; - } else { - $wantsyms{$1} = 1; - } -} -close SYMFILE; - -foreach my $elflib (@elflibs) { - open NM, "-|", "nm", $elflib or die "cannot run 'nm $elflib': $!"; - - while () { - next unless /^\S+\s(?:[TBD])\s(\S+)\s*$/; - - $gotsyms{$1} = 1; - } - - close NM; -} - -foreach my $sym (keys(%wantsyms)) { - next if exists $gotsyms{$sym}; - - print STDERR "Expected symbol $sym is not in ELF library\n"; - $ret = 1; -} - -exit($ret);