From ccc90e525df1fc8dcbfd64d7bf20be5f05a23929 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Mon, 22 Jun 2020 23:50:03 -0400 Subject: fix glibc version in debian package this should make the built binary work on debian stable --- bin/remove-glibc-2.29-use | 119 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100755 bin/remove-glibc-2.29-use (limited to 'bin') diff --git a/bin/remove-glibc-2.29-use b/bin/remove-glibc-2.29-use new file mode 100755 index 0000000..06e5cd1 --- /dev/null +++ b/bin/remove-glibc-2.29-use @@ -0,0 +1,119 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use 5.020; +use experimental 'signatures'; +no warnings 'experimental::signatures'; + +# see http://www.lightofdawn.org/wiki/wiki.cgi/NewAppsOnOldGlibc for details + +# as of currently, only `log2` is being used from GLIBC_2.29, and a +# corresponding version from GLIBC_2.2.5 does exist, so we can just swap it +# out. + +use constant VER_FLG_WEAK => 0x02; + +my $bin = $ARGV[0]; + +system("readelf -s $bin | grep -q GLIBC_2.29"); +if ($?) { + die "no symbols from GLIBC_2.29 found, skipping\n"; +} + +my %readelf_v = parse_readelf_v($bin); +my %readelf_s = parse_readelf_s($bin); + +if ($readelf_s{'log2@GLIBC_2.29'}{ver} != $readelf_v{'.gnu.version_r'}{'libm.so.6'}{'GLIBC_2.29'}{ver}) { + die "log2 doesn't appear to use the symbol version from GLIBC_2.29\n"; +} + +my $bin_contents = do { + local $/; + open my $bin_fh, '<', $bin or die "couldn't open $bin: $!"; + <$bin_fh> +}; + +my $gnu_version_r_offset = $readelf_v{'.gnu.version_r'}{offset}; +my $glibc_229_offset = $gnu_version_r_offset + $readelf_v{'.gnu.version_r'}{'libm.so.6'}{'GLIBC_2.29'}{offset}; +my $glibc_225_offset = $gnu_version_r_offset + $readelf_v{'.gnu.version_r'}{'libm.so.6'}{'GLIBC_2.2.5'}{offset}; + +# we could just make the GLIBC_2.29 symbol weak (as described in the above +# page), but that causes a warning to be printed every time you run the binary, +# which is obnoxious + +# my $prev_glibc_229_flags = substr $bin_contents, $glibc_229_offset + 0x04, 2, pack('s', VER_FLG_WEAK); +# if (unpack('s', $prev_glibc_229_flags) != 0) { +# die "GLIBC_2.39 did not have flags set to 0\n"; +# } + +# instead, we overwrite vna_hash, vna_flags, vna_other, vna_name with the 2.3.5 +# versions (but leave vna_next the same) - this causes there to be two entries +# describing GLIBC_2.2.5, but this appears to be harmless +substr($bin_contents, $glibc_229_offset + 0x00, 12, substr($bin_contents, $glibc_225_offset + 0x00, 12)); + +my $gnu_version_offset = $readelf_v{'.gnu.version'}{offset}; +my $log2_offset = $gnu_version_offset + 2 * $readelf_s{'log2@GLIBC_2.29'}{num}; + +my $prev_log2_version = substr $bin_contents, $log2_offset, 2, pack('s', $readelf_v{'.gnu.version_r'}{'libm.so.6'}{'GLIBC_2.2.5'}{ver}); +if (unpack('s', $prev_log2_version) != $readelf_v{'.gnu.version_r'}{'libm.so.6'}{'GLIBC_2.29'}{ver}) { + die "log2 doesn't appear to use the symbol version from GLIBC_2.29\n"; +} + +open my $fh, '>', "$bin.new" or die "couldn't open $bin.new: $!"; +print $fh $bin_contents; +chmod 0755, "$bin.new"; + +my $remaining = `readelf -s $bin.new | grep GLIBC_2.29`; +if (!$?) { + die "additional symbols from GLIBC_2.29 found:\n$remaining\n"; +} + +sub parse_readelf_s($bin) { + my $readelf = `readelf -s $bin`; + + my %ret; + for my $line (split "\n", $readelf) { + if ($line =~ /^ *[0-9]+:/) { + my ($num, $value, $size, $type, $bind, $vis, $ndx, $name, $ver) = split ' ', $line; + if (defined $ver) { + ($ver) = $ver =~ /\((.*)\)/; + } + if (defined $num) { + ($num) = $num =~ /(.*):/; + } + $ret{$name} = { + num => $num, + ver => $ver, + } + } + } + + %ret +} + +sub parse_readelf_v($bin) { + my $readelf = `readelf -V $bin`; + + my $section; + my $file; + my %ret; + for my $line (split "\n", $readelf) { + if ($line =~ /^Version (?:symbols|needs) section '([^']+)'/) { + $section = $1; + } + if ($line =~ /^ Addr: (?:[^ ]+) Offset: ([^ ]+)/) { + $ret{$section}{offset} = hex($1); + } + if ($line =~ /^ [^:]+: Version: [^ ]+ File: ([^ ]+)/) { + $file = $1; + } + if ($line =~ /^ ([^:]+): Name: ([^ ]+) Flags: (?:[^ ]+) Version: (.*)/) { + $ret{$section}{$file}{$2} = { + offset => hex($1), + ver => $3, + }; + } + } + + %ret +} -- cgit v1.2.3-54-g00ecf