You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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段变化导致的问题,想知道:

  1. rpmbuild这种修改二进制rela段的行为目的是什么?
  2. 如何阻止这种行为?
解答

一、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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 10:30:51