rpmbuild为何改写ELF头?如何阻止该行为?
问题描述
我有一个精简后的spec文件如下:
Name: some-binary Version: 6.1.0 Release: 1 License: proprietary Summary: a binary %description Whatever %install install -d %{buildroot}/fromrpm cp %{_sourcedir}/thebinary %{buildroot}//fromrpm/thebinary %files /fromrpm/thebinary
随后我执行了以下命令:
$ cd ~/rpmbuild/ $ rpmbuild -bb SPECS/some-binary.spec 2>/dev/null Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.gxRpSj Processing files: some-binary-6.1.0-1.x86_64 Provides: some-binary = 6.1.0-1 some-binary(x86-64) = 6.1.0-1 Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/dspeyer/rpmbuild/BUILDROOT/some-binary-6.1.0-1.x86_64 Wrote: /home/dspeyer/rpmbuild/RPMS/x86_64/some-binary-6.1.0-1.x86_64.rpm Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.WR3Utx $ rpm2cpio RPMS/x86_64/some-binary-6.1.0-1.x86_64.rpm | cpio -idmv ./fromrpm/thebinary 41456 blocks $ readelf -a SOURCES/thebinary | grep rela\. [ 5] .rela.plt RELA 0000000000400338 00000338 00 .note.gnu.property .note.gnu.build-id .note.ABI-tag .note.go.buildid .rela.plt Relocation section '.rela.plt' at offset 0x338 contains 29 entries: $ readelf -a fromrpm/thebinary | grep rela\. [ 6] .rela.got.plt RELA 0000000000000000 0143d048 Relocation section '.rela.got.plt' at offset 0x143d048 contains 29 entries:
该二进制为静态链接程序,经rpm打包后在RHEL 7.9上运行时立即崩溃,报错Unexpected reloc type in static binary,崩溃时在__libc_fatal内触发SIGSEGV。我怀疑是rpmbuild打包后二进制的rela段变化导致的问题,想知道:
- rpmbuild这种修改二进制rela段的行为目的是什么?
- 如何阻止这种行为?
解答
一、rpmbuild修改二进制的原因
你看到的rela段变化,是rpmbuild默认启用的brp-strip-static-archive脚本导致的。这个脚本原本的作用是对静态二进制执行strip操作,剥离调试符号、减小包体积,但它处理静态链接二进制时存在兼容性bug——错误地修改了重定位段(.rela相关段)的结构和位置,导致老版本系统(比如RHEL7.9)的动态加载器无法识别这些异常的重定位信息,进而触发崩溃。
简单来说,rpmbuild的初衷是优化包体积,但对静态二进制的处理逻辑有缺陷,反而破坏了二进制的兼容性。
二、阻止该行为的方法
有两种可靠的解决方式:
1. 全局禁用strip操作
在spec文件开头添加%global __strip /bin/true,让rpmbuild调用空命令代替strip,完全跳过符号剥离流程:
%global __strip /bin/true Name: some-binary Version: 6.1.0 Release: 1 License: proprietary Summary: a binary # 后续内容保持不变
2. 仅针对目标静态二进制跳过strip
如果不想全局禁用strip,只针对当前静态二进制处理,可以在%install段后添加标记,让rpm跳过对该文件的strip:
%install install -d %{buildroot}/fromrpm cp %{_sourcedir}/thebinary %{buildroot}/fromrpm/thebinary # 标记该文件无需执行strip %global __strip_file_fromrpm_thebinary /bin/true
或者用更通用的过滤方式,通过%filter_from_post剔除对该二进制的strip操作:
%filter_from_post /usr/lib/rpm/brp-strip-static-archive ^/usr/bin/strip.*fromrpm/thebinary$ %filter_from_post -f
两种方法都能避免rpm破坏静态二进制的重定位结构,解决RHEL7.9上的崩溃问题。
内容的提问来源于stack exchange,提问作者dspeyer
相关产品推荐
相关产品推荐

