Linux 编译链接那些事儿(04)代码和编译环境一致,但文件MD5值不同问题

1 问题背景解读

编译环境一致,代码一致,环境变量一致,编译器版本一致,但是最终2个一致的环境编译出来的ELF文件,也就是XXX.so库正常应该一致。然而不一致。。。针对这2个ELF文件,通过readelf查看,仅build-id不同,但是其他的都是一样的,使用bcompare进行对比如下:

非常有趣的是 代码一致,编译时环境变量一致,编译器的版本,链接器的版本也一致,这么搞辖区都没有什么能查的了,但是问题要解决阿,毕竟交付合同要求MD5值必须一致。而且着急。

经过不断的探索和查资料,最后推断出应该是环境上有细微差别导致的,uname -a 查看下系统的版本如下:

#环境1
$uname -a
6.8.0-47-generic #47~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Oct  4 16:16:55 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

#环境2
$uname -a
6.8.0-48-generic #48~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Oct  4 17:24:13 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

这个问题直接解决似乎是不太可能了,毕竟重装系统,再重新安装各种软件和调试,代价过大。但是针对交付体系来说这个字段的变化会导致MD5值发生变化,进而影响商业的交付。

于是我们就想到,能否直接将这个build-id删除掉以保证MD5值一致呢?查了下资料发现是可行的,原理上很简单,就是在链接的时候添加"-Wl,--build-id=none" 这个链接选项禁止build-id的生成。

但是我们还是要对这个原理和是否满足交付需求。探讨之前我们先对build-id 标识进行解读:

ELF 文件中的 build-id 是一个在编译过程中生成的唯一标识符。build-id 是一个在 ELF 文件中存储的唯一的构建标识符,通常由编译器在编译过程中生成。它有点类似于文件的哈希值,用于标识特定的编译实例。build-id 的值被保存在 ELF 文件的 .note.gnu.build-id 段中,这是一个特殊的 ELF 段,用于存储构建相关的信息。

同时build-id 的设计目的主要有:

  • 版本控制:build-id 可以用来判断两个 ELF 文件是否是同一版本的源码编译得到的,有助于版本控制和二进制文件的一致性检查。
  • 调试和符号解析:在调试过程中,build-id 可以帮助调试器或符号服务器准确地识别出具体的二进制文件版本,尤其是在使用预编译的二进制或共享库时。
  • 安全性:build-id 可以用于安全目的,比如在动态链接库中,确保加载的库是预期的版本,防止恶意替换。

由于版本控制内部有其他的字段便于查找,调试版本本身不做约束,安全性上有MD5做保障,可以考虑将build-id去掉。作出决定后,接下来看具体的修改方案。

2 build-id禁止生成的修改方案解读

2.1 Linux系统上的修改

一般针对linux系统的编译,主要使用如下方式,如果cmake的版本在3.13以下在CMakeList.txt中添加:

add_library(X SHARED source_file.cpp)
set_target_properties(${module} PROPERTIES LINK_FLAGS "-Wl,--build-id=none")

如果cmake版本在3.13以上,则在CMakeList.txt中添加:

target_link_options(myTarget PRIVATE "-Wl,--build-id=none")

2.2 Android系统上的修改

针对android系统,将 -DCMAKE_SHARED_LINKER_FLAGS 用于设置共享库的链接器标志。需要修改build.gradle即可,修改方式如下:

android {
    ...
    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                cppFlags ""
                arguments "-DCMAKE_SHARED_LINKER_FLAGS=-Wl,--build-id=none"
            }
        }
    }
}

3 效果呈现

使用readelf工具再次查看下build-id是否还存在。对比如下:

未做处理,lib库编译调整前,如下所示:

$readelf -n lib/arm64-v8a/XXX.so

Displaying notes found in: .note.android.ident
  所有者            Data size 	Description
  Android              0x00000084	NT_VERSION (版本)
   description data: 1a 00 00 00 72 32 36 2d 63 61 6e 61 72 79 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

Displaying notes found in: .note.gnu.build-id
  所有者            Data size 	Description
  GNU                  0x00000014	NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: 907f0648f3759fd2970655c1d5cbff119c17f196

做处理,lib库编译调整后,如下所示:

$readelf -n lib/arm64-v8a/XXX.so

Displaying notes found in: .note.android.ident
  所有者            Data size 	Description
  Android              0x00000084	NT_VERSION (版本)
   description data: 1a 00 00 00 72 32 36 2d 63 61 6e 61 72 79 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

因为做了这样的处理,所以最终2个ELF的文件MD5值就变得一致了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值