On 26 May 2015 at 21:07, Michael Hudson-Doyle <michael.hud...@canonical.com> wrote: >> It would be nice if the unit test would cover versions longer than >> the normal space padding, and the visibility attributes. > > I'll try to do that tomorrow.
So it took a week longer than I hoped, but I'm attaching a patch with, I think, pretty comprehensive tests. The implementation is the same as my previous patch (and the tests fail without the new implementation). I'm not much of a perl programmer, so my perl is probably as unidiomatic as it gets, but if you can make my test cases pass I don't really care if you change everything else completely :-) Cheers, mwh
From e5a3fcb914a03ea0e448371ea3a271e33dc41c34 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle <michael.hud...@canonical.com> Date: Thu, 4 Jun 2015 13:13:23 +1200 Subject: [PATCH] Support for spaces in symbols in Dpkg::Shlibs::Objdump. --- scripts/Dpkg/Shlibs/Objdump.pm | 63 ++++++++++------ scripts/Makefile.am | 18 ++++- scripts/t/Dpkg_Shlibs.t | 35 ++++++++- scripts/t/Dpkg_Shlibs/makespacesymc.pl | 32 ++++++++ scripts/t/Dpkg_Shlibs/objdump.spacesyms | 127 ++++++++++++++++++++++++++++++++ scripts/t/Dpkg_Shlibs/spacesym.pl | 19 +++++ scripts/t/Dpkg_Shlibs/spacesyms.map | 7 ++ 7 files changed, 276 insertions(+), 25 deletions(-) create mode 100755 scripts/t/Dpkg_Shlibs/makespacesymc.pl create mode 100644 scripts/t/Dpkg_Shlibs/objdump.spacesyms create mode 100755 scripts/t/Dpkg_Shlibs/spacesym.pl create mode 100644 scripts/t/Dpkg_Shlibs/spacesyms.map diff --git a/scripts/Dpkg/Shlibs/Objdump.pm b/scripts/Dpkg/Shlibs/Objdump.pm index c19c3fb..dd53a24 100644 --- a/scripts/Dpkg/Shlibs/Objdump.pm +++ b/scripts/Dpkg/Shlibs/Objdump.pm @@ -221,7 +221,7 @@ sub parse_objdump_output { if ($section eq 'dynsym') { $self->parse_dynamic_symbol($_); } elsif ($section eq 'dynreloc') { - if (/^\S+\s+(\S+)\s+(\S+)\s*$/) { + if (/^\S+\s+(\S+)\s+(.+)$/) { $self->{dynrelocs}{$2} = $1; } else { warning(g_("couldn't parse dynamic relocation record: %s"), $_); @@ -299,21 +299,36 @@ sub parse_objdump_output { sub parse_dynamic_symbol { my ($self, $line) = @_; my $vis_re = '(\.protected|\.hidden|\.internal|0x\S+)'; - if ($line =~ /^[0-9a-f]+ (.{7})\s+(\S+)\s+[0-9a-f]+(?:\s+(\S+))?(?:\s+$vis_re)?\s+(\S+)/) { - - my ($flags, $sect, $ver, $vis, $name) = ($1, $2, $3, $4, $5); - - # Special case if version is missing but extra visibility - # attribute replaces it in the match - if (defined($ver) and $ver =~ /^$vis_re$/) { - $vis = $ver; - $ver = ''; - } + if ($line =~ /^[0-9a-f]+ (.{7})\s+(\S+)\s+[0-9a-f]+(.+)$/) { + + my ($flags, $sect, $rest) = ($1, $2, $3); + my ($ver, $vis, $name); + + if ($rest =~ /^ {11}/) { + # No version + $rest =~ s/^\s+|\s+$//g; + if ($rest =~ /^$vis_re\s+(\S.+)/) { + $vis = $1; + $name = $2; + } else { + $name = $rest; + } + } elsif ($rest =~ /(?:\s+(\S+))?(?:\s+$vis_re)?\s+(.+)/) { + ($ver, $vis, $name) = ($1, $2, $3); + # Special case if version is missing but extra visibility + # attribute replaces it in the match + if (defined($ver) and $ver =~ /^$vis_re$/) { + $vis = $ver; + $ver = ''; + } + } - # Cleanup visibility field - $vis =~ s/^\.// if defined($vis); + if (defined($name)) { + # Cleanup visibility field + $vis =~ s/^\.// if defined($vis); - my $symbol = { + # Register symbol + my $symbol = { name => $name, version => $ver // '', section => $sect, @@ -328,16 +343,18 @@ sub parse_dynamic_symbol { defined => $sect ne '*UND*' }; - # Handle hidden symbols - if (defined($ver) and $ver =~ /^\((.*)\)$/) { - $ver = $1; - $symbol->{version} = $1; - $symbol->{hidden} = 1; - } + # Handle hidden symbols + if (defined($ver) and $ver =~ /^\((.*)\)$/) { + $ver = $1; + $symbol->{version} = $1; + $symbol->{hidden} = 1; + } + $self->add_dynamic_symbol($symbol); + return; + } + } - # Register symbol - $self->add_dynamic_symbol($symbol); - } elsif ($line =~ /^[0-9a-f]+ (.{7})\s+(\S+)\s+[0-9a-f]+/) { + if ($line =~ /^[0-9a-f]+ (.{7})\s+(\S+)\s+[0-9a-f]+/) { # Same start but no version and no symbol ... just ignore } elsif ($line =~ /^REG_G\d+\s+/) { # Ignore some s390-specific output like diff --git a/scripts/Makefile.am b/scripts/Makefile.am index be164b7..ad3e0b9 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -313,7 +313,8 @@ test_data_objects = \ t/Dpkg_Shlibs/libobjdump.basictags-amd64.so \ t/Dpkg_Shlibs/libobjdump.basictags-i386.so \ t/Dpkg_Shlibs/libobjdump.basictags-mips.so \ - t/Dpkg_Shlibs/libobjdump.patterns.so + t/Dpkg_Shlibs/libobjdump.patterns.so \ + t/Dpkg_Shlibs/libobjdump.spacesyms.so $(srcdir)/t/Dpkg_Shlibs/libobjdump.basictags-amd64.so: $(srcdir)/t/Dpkg_Shlibs/basictags.c $(CC) $(CFLAGS) -shared -fPIC -Wl,-soname -Wl,libbasictags.so.1 $< \ @@ -332,6 +333,19 @@ $(srcdir)/t/Dpkg_Shlibs/libobjdump.patterns.so: $(srcdir)/t/Dpkg_Shlibs/patterns -Wl,--version-script=$(srcdir)/t/Dpkg_Shlibs/patterns.map $< \ -o $@ +spacesyms.c: $(srcdir)/t/Dpkg_Shlibs/makespacesymc.pl + $(srcdir)/t/Dpkg_Shlibs/makespacesymc.pl > spacesyms.c + +spacesyms.o: spacesyms.c + $(CC) $(CFLAGS) -c -fPIC -o $@.tmp $< + $(srcdir)/t/Dpkg_Shlibs/spacesym.pl $@.tmp $@ + rm $@.tmp + +$(srcdir)/t/Dpkg_Shlibs/libobjdump.spacesyms.so: spacesyms.o $(srcdir)/t/Dpkg_Shlibs/spacesyms.map + $(CC) -shared -Wl,-soname -Wl,libspacesyms.so.1 \ + -Wl,--version-script=$(srcdir)/t/Dpkg_Shlibs/spacesyms.map $< \ + -o $@ + .PHONY: refresh-test-data OBJDUMP = objdump -w -f -p -T -R @@ -345,6 +359,8 @@ refresh-test-data: $(test_data_objects) >$(srcdir)/t/Dpkg_Shlibs/objdump.basictags-mips $(OBJDUMP) $(srcdir)/t/Dpkg_Shlibs/libobjdump.patterns.so \ >$(srcdir)/t/Dpkg_Shlibs/objdump.patterns + $(OBJDUMP) $(srcdir)/t/Dpkg_Shlibs/libobjdump.spacesyms.so \ + >$(srcdir)/t/Dpkg_Shlibs/objdump.spacesyms $(OBJDUMP) `which ls` >$(srcdir)/t/Dpkg_Shlibs/objdump.ls include $(top_srcdir)/check.am diff --git a/scripts/t/Dpkg_Shlibs.t b/scripts/t/Dpkg_Shlibs.t index 4bcd848..813b49a 100644 --- a/scripts/t/Dpkg_Shlibs.t +++ b/scripts/t/Dpkg_Shlibs.t @@ -16,7 +16,7 @@ use strict; use warnings; -use Test::More tests => 124; +use Test::More tests => 148; use Cwd; use IO::String; @@ -351,6 +351,39 @@ is_deeply( $sym, { name => 'IA__g_free', version => '', hidden => '', defined => 1 }, 'symbol with visibility without version' ); +# Check parsing of objdump output when symbol names contain spaces +$obj = Dpkg::Shlibs::Objdump::Object->new; + +open $objdump, '<', "$datadir/objdump.spacesyms" + or die "$datadir/objdump.spacesyms: $!"; +$obj->parse_objdump_output($objdump); +close $objdump; + +sub check_spacesym { + my ($name, $visibility, $version) = @_; + $sym = $obj->get_symbol("$name@" . "$version"); + is_deeply( $sym, { name => $name, version => $version, + soname => 'libspacesyms.so.1', objid => 'libspacesyms.so.1', + section => '.text', dynamic => 1, + debug => '', type => 'F', weak => '', + local => '', global => 1, visibility => $visibility, + hidden => '', defined => 1 }, $name ); + ok(defined($obj->{dynrelocs}{$name}), "dynreloc found for $name"); +} + +check_spacesym('symdefaultvernospacedefault', '', 'Base'); +check_spacesym('symdefaultvernospaceprotected', 'protected', 'Base'); +check_spacesym('symlongvernospacedefault', '', 'VERY_LONG_VERSION_1'); +check_spacesym('symlongvernospaceprotected', 'protected', 'VERY_LONG_VERSION_1'); +check_spacesym('symshortvernospacedefault', '', 'V1'); +check_spacesym('symshortvernospaceprotected', 'protected', 'V1'); +check_spacesym('symdefaultverSPA CEdefault', '', 'Base'); +check_spacesym('symdefaultverSPA CEprotected', 'protected', 'Base'); +check_spacesym('symlongverSPA CEdefault', '', 'VERY_LONG_VERSION_1'); +check_spacesym('symlongverSPA CEprotected', 'protected', 'VERY_LONG_VERSION_1'); +check_spacesym('symshortverSPA CEdefault', '', 'V1'); +check_spacesym('symshortverSPA CEprotected', 'protected', 'V1'); + ####### Test symbol tagging support ###### # Parsing/dumping diff --git a/scripts/t/Dpkg_Shlibs/makespacesymc.pl b/scripts/t/Dpkg_Shlibs/makespacesymc.pl new file mode 100755 index 0000000..cea94d2 --- /dev/null +++ b/scripts/t/Dpkg_Shlibs/makespacesymc.pl @@ -0,0 +1,32 @@ +#!/usr/bin/perl -w +# +# makespacesymc.pl outputs a C file that contains symbols matching +# sym{defaultver,longver,shortver}{nospace,SPACE}{default,hidden,protected,internal} +# with symbol visibility matching the final element and at least one +# relocation against each symbol. When used together with spacesym.pl +# and spacesyms.map, makes a shared object that contains symbols that +# covers all cases of: +# 1) has a short, long or Base version +# 2) has or does not have a space in the symbol name +# 3) default, hidden, protected or internal visibility. + +use strict; + +my @symbols; + +foreach my $version ("defaultver", "longver", "shortver") { + foreach my $space ("nospace", "SPACE") { + foreach my $visibility ("default", "hidden", "protected", "internal") { + my $symbol = "sym$version$space$visibility"; + push @symbols, $symbol; + print "void $symbol(void) __attribute__((visibility(\"$visibility\")));\n"; + print "void $symbol(void) {}\n"; + } + } +} + +print "void (*funcs[])(void) = {\n"; +foreach my $symbol (@symbols) { + print "$symbol,\n"; +} +print "};\n"; diff --git a/scripts/t/Dpkg_Shlibs/objdump.spacesyms b/scripts/t/Dpkg_Shlibs/objdump.spacesyms new file mode 100644 index 0000000..a32600d --- /dev/null +++ b/scripts/t/Dpkg_Shlibs/objdump.spacesyms @@ -0,0 +1,127 @@ + +../../scripts/t/Dpkg_Shlibs/libobjdump.spacesyms.so: file format elf64-x86-64 +architecture: i386:x86-64, flags 0x00000150: +HAS_SYMS, DYNAMIC, D_PAGED +start address 0x0000000000000b80 + +Program Header: + LOAD off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21 + filesz 0x000000000000115c memsz 0x000000000000115c flags r-x + LOAD off 0x0000000000001dd0 vaddr 0x0000000000201dd0 paddr 0x0000000000201dd0 align 2**21 + filesz 0x0000000000000370 memsz 0x0000000000000378 flags rw- + DYNAMIC off 0x0000000000001de8 vaddr 0x0000000000201de8 paddr 0x0000000000201de8 align 2**3 + filesz 0x00000000000001f0 memsz 0x00000000000001f0 flags rw- + NOTE off 0x00000000000001c8 vaddr 0x00000000000001c8 paddr 0x00000000000001c8 align 2**2 + filesz 0x0000000000000024 memsz 0x0000000000000024 flags r-- +EH_FRAME off 0x0000000000000e00 vaddr 0x0000000000000e00 paddr 0x0000000000000e00 align 2**2 + filesz 0x00000000000000d4 memsz 0x00000000000000d4 flags r-- + STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4 + filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw- + RELRO off 0x0000000000001dd0 vaddr 0x0000000000201dd0 paddr 0x0000000000201dd0 align 2**0 + filesz 0x0000000000000230 memsz 0x0000000000000230 flags r-- + +Dynamic Section: + NEEDED libc.so.6 + SONAME libspacesyms.so.1 + INIT 0x0000000000000b30 + FINI 0x0000000000000df4 + INIT_ARRAY 0x0000000000201dd0 + INIT_ARRAYSZ 0x0000000000000008 + FINI_ARRAY 0x0000000000201dd8 + FINI_ARRAYSZ 0x0000000000000008 + GNU_HASH 0x00000000000001f0 + STRTAB 0x0000000000000530 + SYMTAB 0x00000000000002a8 + STRSZ 0x0000000000000214 + SYMENT 0x0000000000000018 + PLTGOT 0x0000000000202000 + PLTRELSZ 0x0000000000000030 + PLTREL 0x0000000000000007 + JMPREL 0x0000000000000b00 + RELA 0x0000000000000800 + RELASZ 0x0000000000000300 + RELAENT 0x0000000000000018 + VERDEF 0x0000000000000780 + VERDEFNUM 0x0000000000000003 + VERNEED 0x00000000000007e0 + VERNEEDNUM 0x0000000000000001 + VERSYM 0x0000000000000744 + RELACOUNT 0x000000000000000f + +Version definitions: +1 0x01 0x026eb371 libspacesyms.so.1 +2 0x00 0x00000591 V1 +3 0x00 0x0df29ee1 VERY_LONG_VERSION_1 + V1 + +Version References: + required from libc.so.6: + 0x09691a75 0x00 04 GLIBC_2.2.5 + +DYNAMIC SYMBOL TABLE: +0000000000000b30 l d .init 0000000000000000 .init +0000000000000000 w D *UND* 0000000000000000 _ITM_deregisterTMCloneTable +0000000000000000 w D *UND* 0000000000000000 __gmon_start__ +0000000000000000 w D *UND* 0000000000000000 _Jv_RegisterClasses +0000000000000000 w D *UND* 0000000000000000 _ITM_registerTMCloneTable +0000000000000000 w DF *UND* 0000000000000000 GLIBC_2.2.5 __cxa_finalize +0000000000000cc0 g DF .text 0000000000000002 Base symdefaultverSPA CEdefault +0000000000000df4 g DF .fini 0000000000000000 Base _fini +0000000000202080 g DO .data 00000000000000c0 Base funcs +0000000000000b30 g DF .init 0000000000000000 Base _init +0000000000000d80 g DF .text 0000000000000002 V1 symshortvernospacedefault +0000000000202140 g D .bss 0000000000000000 Base __bss_start +0000000000000ca0 g DF .text 0000000000000002 Base .protected symdefaultvernospaceprotected +0000000000202148 g D .bss 0000000000000000 Base _end +0000000000000dc0 g DF .text 0000000000000002 V1 symshortverSPA CEdefault +0000000000000000 g DO *ABS* 0000000000000000 V1 V1 +0000000000000da0 g DF .text 0000000000000002 V1 .protected symshortvernospaceprotected +0000000000000d00 g DF .text 0000000000000002 VERY_LONG_VERSION_1 symlongvernospacedefault +0000000000000000 g DO *ABS* 0000000000000000 VERY_LONG_VERSION_1 VERY_LONG_VERSION_1 +0000000000202140 g D .data 0000000000000000 Base _edata +0000000000000c80 g DF .text 0000000000000002 Base symdefaultvernospacedefault +0000000000000d60 g DF .text 0000000000000002 VERY_LONG_VERSION_1 .protected symlongverSPA CEprotected +0000000000000ce0 g DF .text 0000000000000002 Base .protected symdefaultverSPA CEprotected +0000000000000d40 g DF .text 0000000000000002 VERY_LONG_VERSION_1 symlongverSPA CEdefault +0000000000000de0 g DF .text 0000000000000002 V1 .protected symshortverSPA CEprotected +0000000000000d20 g DF .text 0000000000000002 VERY_LONG_VERSION_1 .protected symlongvernospaceprotected + + +DYNAMIC RELOCATION RECORDS +OFFSET TYPE VALUE +0000000000201dd0 R_X86_64_RELATIVE *ABS*+0x0000000000000c50 +0000000000201dd8 R_X86_64_RELATIVE *ABS*+0x0000000000000c10 +0000000000202040 R_X86_64_RELATIVE *ABS*+0x0000000000202040 +0000000000202088 R_X86_64_RELATIVE *ABS*+0x0000000000000c90 +0000000000202098 R_X86_64_RELATIVE *ABS*+0x0000000000000cb0 +00000000002020a8 R_X86_64_RELATIVE *ABS*+0x0000000000000cd0 +00000000002020b8 R_X86_64_RELATIVE *ABS*+0x0000000000000cf0 +00000000002020c8 R_X86_64_RELATIVE *ABS*+0x0000000000000d10 +00000000002020d8 R_X86_64_RELATIVE *ABS*+0x0000000000000d30 +00000000002020e8 R_X86_64_RELATIVE *ABS*+0x0000000000000d50 +00000000002020f8 R_X86_64_RELATIVE *ABS*+0x0000000000000d70 +0000000000202108 R_X86_64_RELATIVE *ABS*+0x0000000000000d90 +0000000000202118 R_X86_64_RELATIVE *ABS*+0x0000000000000db0 +0000000000202128 R_X86_64_RELATIVE *ABS*+0x0000000000000dd0 +0000000000202138 R_X86_64_RELATIVE *ABS*+0x0000000000000df0 +0000000000201fd8 R_X86_64_GLOB_DAT _ITM_deregisterTMCloneTable +0000000000201fe0 R_X86_64_GLOB_DAT __gmon_start__ +0000000000201fe8 R_X86_64_GLOB_DAT _Jv_RegisterClasses +0000000000201ff0 R_X86_64_GLOB_DAT _ITM_registerTMCloneTable +0000000000201ff8 R_X86_64_GLOB_DAT __cxa_finalize +0000000000202080 R_X86_64_64 symdefaultvernospacedefault +0000000000202090 R_X86_64_64 symdefaultvernospaceprotected +00000000002020a0 R_X86_64_64 symdefaultverSPA CEdefault +00000000002020b0 R_X86_64_64 symdefaultverSPA CEprotected +00000000002020c0 R_X86_64_64 symlongvernospacedefault +00000000002020d0 R_X86_64_64 symlongvernospaceprotected +00000000002020e0 R_X86_64_64 symlongverSPA CEdefault +00000000002020f0 R_X86_64_64 symlongverSPA CEprotected +0000000000202100 R_X86_64_64 symshortvernospacedefault +0000000000202110 R_X86_64_64 symshortvernospaceprotected +0000000000202120 R_X86_64_64 symshortverSPA CEdefault +0000000000202130 R_X86_64_64 symshortverSPA CEprotected +0000000000202018 R_X86_64_JUMP_SLOT __gmon_start__ +0000000000202020 R_X86_64_JUMP_SLOT __cxa_finalize + + diff --git a/scripts/t/Dpkg_Shlibs/spacesym.pl b/scripts/t/Dpkg_Shlibs/spacesym.pl new file mode 100755 index 0000000..69986ea --- /dev/null +++ b/scripts/t/Dpkg_Shlibs/spacesym.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl -w +# +# spacesym.pl INPUT OUTPUT copies the object file INPUT to OUTPUT, +# redefining any symbol in INPUT that contains "SPACE" in its name to +# contain "SPA CE" instead. + +use strict; + +my ($input, $output) = @ARGV; +my @cmds = ("objcopy"); +open(NM, "nm $input | grep SPACE |"); +while (<NM>) { + chomp; + my $x = (split " ",$_,3)[2]; + my $y = $x =~ s/SPACE/SPA CE/r; + push @cmds, "--redefine-sym=$x=$y"; +} +push @cmds, $input, $output; +exec @cmds; diff --git a/scripts/t/Dpkg_Shlibs/spacesyms.map b/scripts/t/Dpkg_Shlibs/spacesyms.map new file mode 100644 index 0000000..b40f71d --- /dev/null +++ b/scripts/t/Dpkg_Shlibs/spacesyms.map @@ -0,0 +1,7 @@ +V1 { +global: symshortver*; +}; + +VERY_LONG_VERSION_1 { +global: symlongver*; +} V1; \ No newline at end of file -- 2.1.4