aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-06-22 23:50:03 -0400
committerJesse Luehrs <doy@tozt.net>2020-06-22 23:54:26 -0400
commitccc90e525df1fc8dcbfd64d7bf20be5f05a23929 (patch)
tree394b770ad1c57de115258f2b7cbf3da2e6ce2a65
parent14d7cd8ffa4e95f866175545534fd5af901e8402 (diff)
downloadrbw-ccc90e525df1fc8dcbfd64d7bf20be5f05a23929.tar.gz
rbw-ccc90e525df1fc8dcbfd64d7bf20be5f05a23929.zip
fix glibc version in debian package
this should make the built binary work on debian stable
-rw-r--r--CHANGELOG.md5
-rw-r--r--Makefile6
-rwxr-xr-xbin/remove-glibc-2.29-use119
3 files changed, 128 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9b47183..ba84ae7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,11 @@
* `rbw get --full` now also includes the username. (Jarkko Oranen)
+### Fixed
+
+* `rbw` should now be usable on systems with glibc-2.28 (such as Debian
+ stable). (incredible-machine)
+
## [0.4.2] - 2020-05-30
### Fixed
diff --git a/Makefile b/Makefile
index a95bf3b..937b1ab 100644
--- a/Makefile
+++ b/Makefile
@@ -12,6 +12,8 @@ build:
release:
@cargo build --release --all-targets
+ @./bin/remove-glibc-2.29-use ./target/release/rbw
+ @mv ./target/release/rbw.new ./target/release/rbw
.PHONY: release
test:
@@ -40,8 +42,8 @@ package: pkg/$(DEB_PACKAGE)
pkg:
@mkdir pkg
-pkg/$(DEB_PACKAGE): | pkg
- @cargo deb && mv target/debian/$(DEB_PACKAGE) pkg
+pkg/$(DEB_PACKAGE): release | pkg
+ @cargo deb --no-build && mv target/debian/$(DEB_PACKAGE) pkg
pkg/$(DEB_PACKAGE).minisig: pkg/$(DEB_PACKAGE)
@minisign -Sm pkg/$(DEB_PACKAGE)
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
+}