跳转到主要内容

基于符号评估两个二进制文件的兼容性。

项目描述

Symbolator

Symbolator是一个小型库,允许您评估符号是否在感兴趣的库和二进制文件之间兼容。目标是创建一个用于build-abi-containers的测试器。

使用方法

安装

您可以在本地安装

$ git clone git@github.com:buildsi/symbolator.git
$ cd symbolator
$ pip install -e .

或从PyPI安装

$ pip install symbolator-python

生成符号

如果您只想为库生成ELF符号(pyelftools),您可以这样做

$ symbolator generate <library>

例如

$ symbolator generate libtcl8.6.so 
...
symbol("socket@@GLIBC_2.2.5").
symbol_type("/home/vanessa/Desktop/Code/symbolator/libtcl8.6.so","socket@@GLIBC_2.2.5","FUNC").
symbol_version("/home/vanessa/Desktop/Code/symbolator/libtcl8.6.so","socket@@GLIBC_2.2.5","").
symbol_binding("/home/vanessa/Desktop/Code/symbolator/libtcl8.6.so","socket@@GLIBC_2.2.5","GLOBAL").
symbol_visibility("/home/vanessa/Desktop/Code/symbolator/libtcl8.6.so","socket@@GLIBC_2.2.5","DEFAULT").
symbol_definition("/home/vanessa/Desktop/Code/symbolator/libtcl8.6.so","socket@@GLIBC_2.2.5","UND").
has_symbol("/home/vanessa/Desktop/Code/symbolator/libtcl8.6.so","socket@@GLIBC_2.2.5").
has_symbol("/home/vanessa/Desktop/Code/symbolator/libtcl8.6.so","socket@@GLIBC_2.2.5").

如果您想包含系统符号(链接到感兴趣库的库)

$ symbolator generate --system-libs libtcl8.6.so 

当前默认输出是ASP,用于clingo,因为这是我们需要的。如果您需要JSON输出

$ symbolator generate --json libtcl8.6.so

或仅包含全局符号的JSON

$ symbolator generate --json --globals libtcl8.6.so

比较库(compare)

如果您有两个不同版本的库,简单的比较将确定是否有任何符号或参数已更改。我们再次将使用pyelftools进行符号提取。为此,我们只需要两个不同版本的“相同”库。让我们先举些例子

$ cd examples/cpp
$ make

来生成

  • libmath-v1.so:原始库
  • libmath-v2.so:更改后的库

现在让我们运行比较

$ symbolator compare libmath-v1.so libmath-v2.so
...
{
    "is_libA": [
        "/home/vanessa/Desktop/Code/symbolator/examples/cpp/libmath-v1.so"
    ],
    "is_libB": [
        "/home/vanessa/Desktop/Code/symbolator/examples/cpp/libmath-v2.so"
    ],
    "symbol_is_missing": [
        "/home/vanessa/Desktop/Code/symbolator/examples/cpp/libmath-v1.so",
        "/home/vanessa/Desktop/Code/symbolator/examples/cpp/libmath-v2.so",
        "MathLibrary.cpp"
    ],
    "corpus_name_changed": [
        "/home/vanessa/Desktop/Code/symbolator/examples/cpp/libmath-v1.so",
        "/home/vanessa/Desktop/Code/symbolator/examples/cpp/libmath-v2.so",
        "libmath-v1.so",
        "libmath-v2.so"
    ]
}

或者再次只是JSON

$ symbolator compare libmath-v1.so libmath-v2.so --json

评估兼容性(compat)

为了评估兼容性,我们需要

  1. 一个主要感兴趣的二进制文件
  2. 一个已知与该二进制文件兼容的库
  3. 我们想要测试的竞争库

示例中有不同编译器的示例。例如,让我们构建cpp的示例文件。

$ cd examples/cpp
$ make

这将生成

  • math-client:我们感兴趣的主要二进制文件
  • libmath-v1.so:一个已知工作的库
  • libmath-v2.so:一个竞争库

如果你看示例,竞争库应该不兼容,因为参数类型有变化。我们可能看不到C的情况,但我们应该看到C++的不同的符号(名称字符串)。要运行测试

$ symbolator compat math-client libmath-v1.so libmath-v2.so
% binary           : math-client
% working library  : libmath-v1.so
% contender library: libmath-v2.so
Missing Symbol Count: 1
Missing Symbols:
['math-client', 'libmath-v2.so', '_ZN11MathLibrary10Arithmetic3AddEdd']

注意,这是示例的正确答案——我们缺少那个符号!默认情况下,这使用is_compatible.lp。如果你只想将符号输出到其他逻辑程序中使用,你可以这样做

$ symbolator compat --dump math-client libmath-v1.so libmath-v2.so

或者获取答案的json

$ symbolator compat --json math-client libmath-v1.so libmath-v2.so 
{
    "binary": "/home/vanessa/Desktop/Code/symbolator/examples/cpp/math-client",
    "library_working": "/home/vanessa/Desktop/Code/symbolator/examples/cpp/libmath-v1.so",
    "library_contender": "/home/vanessa/Desktop/Code/symbolator/examples/cpp/libmath-v2.so",
    "missing_symbols": [
        "/home/vanessa/Desktop/Code/symbolator/examples/cpp/math-client",
        "/home/vanessa/Desktop/Code/symbolator/examples/cpp/libmath-v2.so",
        "_ZN11MathLibrary10Arithmetic3AddEdd"
    ],
    "count_missing_symbols": "1"
}

再次,这只是在直接从elf获取符号的pyelftools。

Smeagle稳定性模型

截至版本0.0.15,我们支持读取来自Smeaglegosmeagle的json输出,然后进行更详细的不稳定性模型。假设我们有来自smeagle的两个输出文件,例如在examples/smeagle中,使用gosmeagle生成以下内容

$ cd examples/cpp
$ make
$ cd ../smeagle
$ gosmeagle parse ../cpp/libmath-v1.so --pretty > libmath-v1.so.json
$ gosmeagle parse ../cpp/libmath-v2.so --pretty > libmath-v2.so.json

然后我们可以运行symbolator来使用json进行稳定性测试。

$ symbolator stability-test examples/smeagle/libmath-v1.so.json examples/smeagle/libmath-v2.so.json --detail
Libraries are not stable: 0 missing exports, 2 missing_imports

Missing Imports
---------------
 _ZN11MathLibrary10Arithmetic3AddEdd Basic %rdi 0
 _ZN11MathLibrary10Arithmetic3AddEdd Basic %rsi 0

这也可以通过编程方式获取json输出。

与库拼接

假设我们还有一个感兴趣的二进制文件,但我们只对检查符号(以及查找任何未定义的)或请求“拼接”一个感兴趣的库的已知依赖感兴趣——我们可以使用“splice”来完成。当只提供一个二进制文件时,它会读取二进制文件,查找所有依赖库,然后输出任何未定义的符号(不应该有任何)。

$ symbolator splice math-client

% binary : math-client
% splice : libmath-v1.so->libmath-v2.so

Missing Symbols:

=> math-client
   __gmon_start__
   _ITM_deregisterTMCloneTable
   _ITM_registerTMCloneTable

...

现在假设我们想要拼接其他版本的libmath。

$ symbolator splice math-client -s libmath-v1.so=libmath-v2.so

如果库的主名称相同(例如,libmath.1.so与libmath.2.so),我们只需这样做

$ symbolator splice math-client -s libmath.2.so
% binary : math-client
% splice : libmath-v1.so->libmath-v2.so

Missing Symbols:

=> math-client
   _ZN11MathLibrary10Arithmetic3AddEdd
   __gmon_start__
   _ITM_deregisterTMCloneTable
   _ITM_registerTMCloneTable

使用前缀。但由于前缀有一个不同的名称,我们需要明确地命名它。为了以json格式输出

$ symbolator splice math-client -s libmath.2.so --json

如果我们为拼接和未拼接生成了符号(给定已更改的库),然后我们可以快速地进行比较(跨越所有符号)并发现唯一的区别是更改的库中缺少的符号

[x for x in values if x not in compares]
['_ZN11MathLibrary10Arithmetic3AddEdd']

延迟拼接

如果我们想稍后导出json以进行拼接,我们可以这样做

$ mkdir -p examples/splice
$ cd examples/splice
$ symbolator generate ../cpp/math-client --system-libs --json > math-client.json
$ symbolator generate ../cpp/libmath-v2.so --system-libs --json > libmath-v2.so.json

然后进行类似的拼接,但使用输入json。

$ symbolator jsonsplice math-client.json -s libmath-v1.so=libmath-v2.so.json

或者不进行拼接

$ symbolator jsonsplice math-client.json

输出相同(我们看到缺少的符号),但使用这种方法,我们可以分别运行提取,保存数据,然后在json中稍后进行拼接!

与Smeagle拼接

开发中

请注意,这不会工作,直到smeagle能够处理加载这些库而不发生段错误。练习将类似于以下内容。

如果我们想使用Smeagle事实运行类似的分析,那么我们实际上需要预先生成所有事实,并将它们“扔进汤里”。我们可以通过ldd的发现和生成方式来做到这一点,然后将json交给splice。

$ ldd examples/cpp/math-client
	linux-vdso.so.1 (0x00007ffc05b96000)
	libmath-v1.so => not found
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f6854aff000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f685490d000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f68547be000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f6854d03000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f68547a3000)

从上面的内容我们运行

$ mkdir -p examples/smeagle/global
$ cd examples/smeagle/global
$ gosmeagle parse ../../cpp/libmath-v1.so --pretty > libmath-v1.so.json
$ gosmeagle parse ../../cpp/math-client --pretty > math-client.json
$ gosmeagle parse /lib/modules/5.4.0-89-generic/vdso/vdso64.so --pretty > vdso64.so.json

这些没有dwarf

/usr/lib/x86_64-linux-gnu/libstdc++.so.6
/lib/x86_64-linux-gnu/libc.so.6
/lib64/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/libgcc_s.so.1

Smeagle c++也无法解析它们。

# ./build/standalone/Smeagle -l /lib/x86_64-linux-gnu/libgcc_s.so.1 
Segmentation fault (core dumped)

测试

安装symbolator后

$ cd tests/
$ ./test_client.sh

容器安装

您还可以将symbolator构建到容器中!

$ docker build -t symbolator .

然后可以通过entrypoint或shell与symbolator交互。

# shell
$ docker run --entrypoint bash -it symbolator

# entrypoint
$ docker run -it symbolator

示例已构建到容器中以方便测试。

$ cd examples/cpp
$ symbolator compat math-client libmath-v1.so libmath-v2.so 
% binary           : math-client
% working library  : libmath-v1.so
% contender library: libmath-v2.so
Compatible

示例

示例文件夹包含了多个编译器的代码,您可以在其中进行测试。

  • g++
  • gcc
  • gcc-10
  • icc
  • icpc
  • clang
  • clang-10
  • clang++

许可证

此项目是Spack的一部分。Spack采用MIT许可协议和Apache许可协议(版本2.0)进行分发。用户可以选择任一许可协议。

所有新的贡献都必须在MIT和Apache-2.0许可协议下进行。

有关详细信息,请参阅LICENSE-MIT、LICENSE-APACHE、COPYRIGHT和NOTICE。

SPDX-License-Identifier: (Apache-2.0 OR MIT)

LLNL-CODE-811652

项目详情


下载文件

下载适用于您的平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分发

symbolator-python-0.0.18.tar.gz (33.0 kB 查看哈希值)

上传时间 源代码

由以下提供支持