启用 LLVM 的 MemorySanitizer 是否会改变库的 ABI

Does enabling LLVM's MemorySanitizer change the ABI of libraries

LLVM 项目 MemorySanitizer 有一些难以满足的约束,即所有系统库也必须使用 MemorySanitizer 构建。

我一直在考虑一些方法来为我正在处理的项目(它已经使用 ASAN 和 UBSAN)启用 MSAN,特别是关于此约束。我一直在考虑的一种可能的解决方案会导致这样一种情况,即当使用 -fsanitize=memory 编译项目时,它将 link 针对动态系统库的非检测版本,如 libc,并且libstdc++,然后说 libcrypto(添加一个实际上不属于 'toolchain' 的部分)。但随后在 运行 时间,经过检测的二进制文件将 运行 在一个特殊环境(基本上是不同的用户空间)中,其中所有系统动态库都是使用 -fsanitize=memory.[=16= 构建的]

这样的方案可行吗?在我看来,这取决于使用 -fsanitize=memory 构建库是否会改变其 ABI,因为如果库 ABI 在检测版本和非检测版本之间不同,那么针对非检测系统动态库构建的图像是在具有检测系统库的环境中启动时,将在 运行 时发生灾难性故障。

if the library ABI differs between the instrumented and non-instrumented versions, then the image built against the non-instrumented system dynamic libraries is going to fail catastrophically at runtime

首先,使用 -fsanitize=memory 编译 会改变 ABI,例如通过向函数调用添加额外的(影子)操作数。这意味着在运行时 合并经过清理和未经过清理的代码 可能会崩溃。

另一方面,Msan 不会 更改 link-time 库 ABI,即它不会更改符号大小或名称,所以库的外部接口(即内容它的 ELF 符号 table) 用 -fsanitize=memory 编译不会改变。

这意味着 linking 针对未消毒版本和后来 运行 使用消毒版本好的