使用指北-012-ABITracker介绍

type
status
date
slug
summary
tags
category
icon
password

1. 文档说明

本文档中,整理自 ABI Tracker 的 Github 项目文档和 CSDN 的一篇博客,方便读者对 ABI Tracker 有一个初步的了解。

2. ABI Tracker 项目

ABI Tracker 是一个专门针对上游重要的包进行追踪的项目,它专门用于追踪上游软件包的变化与兼容性测试。 该工具适用于对确保向后兼容感兴趣的软件库开发人员和 Linux 维护人员,即允许旧的应用程序运行或使用较新版本重新编译。

2.1. API

应用程序编程接口(API)是计算机程序不同部分之间的接口或通信协议,旨在简化软件的实现和维护。
API 可以用于基于 Web 的系统、操作系统、数据库系统、计算机硬件或软件库。
API 规范可以采用多种形式,但通常包括例程、数据结构、对象类、变量或远程调用的规范。 POSIX、windows API 和 ASPI 是不同形式的 API 的示例。通常会提供 API 文档,以方便使用和实施。
最近,该术语通常用于指代客户端和服务器之间的特定类型的接口,该接口被描述为两者之间的 “合同”。因此,如果客户端以特定格式发出请求,将始终以特定的格式获得响应或启动已定义的操作。这是 API 的一种特殊形式,有时也定义为 WEB API。

2.2. ABI

在计算机软件中,应用程序二进制接口(ABI)是两个二进制程序模块之间的接口。通常,这些模块之一是库或操作系统工具,另一个是用户正在运行的程序。
ABI 定义了如何在机器代码中访问数据结构或计算例程,这是一种低级的,与硬件相关的格式。相比之下,API 在源代码中定义了这种访问,这是一种相对高级的、独立于硬件的、通常是人类可读的格式。 ABI 的一个常见方面是调用约定,它确定如何将数据作为计算例程的输入提供或从计算例程的输出读取。示例是 x86 调用约定。
坚持使用 ABI(可能会或可能不会正式标准化)通常是编译器、操作系统或库作者的工作;但是,当使用多种编程语言编写程序时,应用程序程序员可能必须直接处理 ABI,这可以通过使用外部函数调用接口(FFI)来实现。

2.3. 项目地址

主要仓库 https://github.com/lvc/
主要作者:Andrey Ponomarenko 。

3. 组件介绍

3.1. ABI Compliance Checker

3.1.1. 简介

该工具分析 API / ABI(ABI = API + 编译器 ABI)中可能破坏二进制兼容性和 / 或源兼容性的更改:调用堆栈中的更改,v 表更改,删除的符号,重命名的字段等。
该工具可以为库的头文件和共享对象创建和比较 ABI 转储。如果共享对象包含调试信息,则还可以由 ABI Dumper 工具 (https://github.com/lvc/abi-dumper) 创建库的 ABI 转储。
该工具是ABI跟踪器和上游跟踪器项目的核心组件:https://abi-laboratory.pro/tracker/ ,主要由 Andrey Ponomarenko 开发。
该工具主要用于 C / C++ 项目分析,是整个项目的核心组件。

3.1.2. 项目地址

3.1.3. 安装与使用

依赖:
  • Perl5
  • GCC C++ >= 3.0
  • GNU Binutils
  • ctags
  • ABI-DUMPER >= 1.1
安装:

3.1.4. 二进制兼容性检测

  • 数据类型的问题
  • 结构体和类
  • 添加 / 删除字段(更改内部布局)
  • 大小变化
  • 字段顺序变化
  • 字段类型变化
  • 字段的变化(递归分析)
  • 添加 / 删除虚函数(更改 v-table 布局)
  • 虚函数位置变化
  • 虚函数重写
  • 添加 / 删除基类
  • 基类的变化(递归分析)
  • 联合体
  • 添加 / 删除字段
  • 大小变化
  • 字段类型的变化
  • 字段的变化(递归分析)
  • 枚举
  • 成员值变化
  • 删除 / 重命名成员
  • 符号问题
  • 删除的符号(函数或全局数据)
  • 添加 / 删除参数
  • 参数 / 返回值类型变化
  • 默认参数值变化
  • 重命名参数
  • 不正确的版本变化
  • 属性变化(const、volatile、static 等)
  • 常量问题
  • 值变化

3.1.5. 源码兼容性检测

  • 数据类型问题
  • 结构、类和联合
  • 已删除/重命名的字段
  • 更改字段类型
  • 字段变化(递归分析)
  • 添加/删除的基类
  • 更改字段或方法的访问级别
  • 添加了纯虚拟方法
  • 枚举
  • 已删除/重命名的成员
  • 符号问题
  • 删除的符号(函数或全局数据)
  • 添加/删除的参数
  • 更改参数类型
  • 删除了参数的默认值
  • 返回值类型的更改
  • 已更改的属性(const、static等)

3.1.6. 测试

其中包含100个 C 用例及 200 个 C++ 用例用于 API/ABI 测试。

3.2. ABI Dumper

3.2.1. 简介

ABI Dumper 是一个拷贝ABI的工具,该工具会把ABI格式为包含 DWARF 调试信息的 ELF结构体。
使用 abi-dumper 命令可以对 so/ko(库中需要包含 debug info)生成 dump 文件,再通过 abicc 基于 dump 文件生成 abi 变更报表。
该工具主要由 Andrey Ponomarenko 开发。

3.2.2. 项目地址

3.2.3. 安装与使用

依赖:
  • Perl 5
  • Elfutils (eu-readelf)
  • GNU Binutils
  • Ctags
  • Vtable Dumper >= 1.1
  • ABI Compliance Checker >= 2.2
  • GCC C++
安装:

3.3. Vtable Dumper

3.3.1. 简介

Vtable Dumper 可以列出 C++ 共享库的虚函数表。
该工具适用于对确保向后兼容感兴趣的软件库开发人员和 Linux 维护人员,即允许旧的应用程序运行或使用较新版本重新编译。

3.3.2. 项目地址

3.3.3. 安装与使用

依赖:
  • libelf
  • libdl
  • libstdc++
安装:
用法:
确保目标库的依赖库可以被 ldd 找到,否则 dlopen 会执行失败。对于特殊情况,可以添加路径到 LD_LIBRARY_PATH 中。其他参数可以查看 -help 。

3.4. ABI Monitor

3.4.1. 简介

新版本 ABI 追踪工具,通过自动化的构建、编译,为 ABI Tracker 创建配置。

3.4.2. 项目地址

依赖:
  • Perl5 >= 5.8
  • Perl-Data-Dumper
  • curl
  • wget
推荐:
  • cmake
  • autotools
  • meson
  • gcc
  • g++

3.4.3. 安装与使用

3.5. Pkg Diff

3.5.1. 简介

对比两个包或者两个目录直接差异的工具,如果要对比目录需要加入 -d 参数。

3.5.2. 项目地址

3.5.3. 安装与使用

依赖:
  • Perl 5
  • GNU Diff
  • GNU Wdiff
  • GNU Awk
  • GNU Binutils
  • Perl-File-LibMagic
推荐:
  • ABI Compliance Checker >= 1.99.1
  • ABI Dumper >= 0.97

3.6. ABI Tracker

3.6.1. 简介

与 abi-monitor 配合使用,以连续最追踪多个版本,并以图表的形式展现出来。

3.6.2. 安装与使用

依赖:
  • Perl 5 >= 5.8
  • Elfutils
  • ABI Dumper >= 1.1
  • Vtable-Dumper >= 1.1
  • ABI Compliance Checker >= 2.2
  • ABI Monitor >= 1.12
  • PkgDiff >= 1.6.4
  • RfcDiff >= 1.41
安装:
使用:
图表:
计划任务:cron job

4. ABICC用法介绍

4.1. 方法一:借用 abi-dumper 命令

在编译的时候,需要添加 -g -Og 的gcc 选项来包含 DWARF 调试信息。
创建新旧两个版本的 ABI Dump:
公有头文件 ABI 过滤器,PATH 是库路径。
创建对比报告。
小结:该方法原理是借助 abi-dumper 命令对包含debug info 的 so/ko 生成 dump 文件,再通过 abicc 基于 dump 文件生成 abi 变更报表。
缺点:需要依赖 abi-dumper 工具,同时还要求 so/ko 携带 debug info 信息。

4.2. 方法二:原始

为两个版本,分别创建 XML 描述文件,例如 OLD.xml,NEW.xml。
通过描述文件创建报告。
小结:先配置 xml 描述文件,在通过 abicc 基于 xml 生成 ABI 报表。
缺点:需要同时可以访问新旧两个版本库,对换系统的情况不合适。

4.3. 方法三:创建 ABI DUMPS

创建 XML 描述文件。
创建 ABI Dump 文件。
创建变更报表。
小结:类似方法二,可以在两个系统方分别执行,再对比。
缺点:多了一步创建报表。

5. 示例

5.1. 示例一:GLibc 追踪

以下是对 GLIBC 手动编译的演示。

5.1.1. 安装

安装abicc。
测试abicc。
安装glib。

5.1.2. 追踪

创建 xml 描述文件glibc-2.16.xml。
生成 abi dump 文件,这里提供两种方法。
通用方法:
对于 glibc 这种包,它必定包含很多非必要文件,以及非公有头文件,因此可以更加个性化的生成 abi dump 信息。难点:除非项目提供或者常年进行 GLIBC 开发的人员,才会知道这些。
生成报表。

5.2. 示例二:openssl 追踪

本例提供使用 abi-monitor 对 openssl 版本进行连续追踪的方法。

5.2.1. 安装

略,参考上面文档,不再赘述。

5.2.2. 追踪

创建 profile 文件,注意这里的profile 文件与上面所有 XML 文件都无关系,它是 json 格式的。它包含源代码地址,构建方式,作者以及控制哪些对比变量。
构建。
效果。
notion image

6. 原理

6.1. abicc 项目

6.1.1. 项目结构

一级目录
二级目录
三级目录
说明
doc/
文档目录
Makefile.pl
安装脚本
Makefile
安装脚本
abi-compliance-checker.pl
abi-compliance-checker 命令
modules/
模块目录
RulesBin.xml
二进制 abi 报表规则配置文件
RulesSrc.xml
源码 abi 报表规则配置文件
internals/
Scripts
js 相关脚本
Styles
css 相关脚本
*.pm
内部 perl 模块

6.1.2. 模块说明

模块名
作用
该模块从抽象语法树创建 ABI 转储,依赖 ElfTools、TUDump、GccAst 三个模块,包括 createABIDump、readSymbols 等函数,与 abi-dump 命令不是一回事。
该模块提供基础命令
该模块用于创建调用的约定模型
该模块用于处理 XML 描述符
该模块用于读取 ELF 二进制文件信息
该模块用于过滤符号信息
该模块用于解析 GCC 抽象语法树
该模块用于处理输入数据
该模块用于记录日志
该模块用于处理 C++ 符号
该模块带有处理路径的函数
该模块带有回归测试套件
该模块用于比较操作系统
该模块用于检查文件并生成路径
该模块用于创建抽象语法树的转储
该模块用于处理一些类型属性
该模块包含一些基础通用的函数
该模块用于处理以 XML 格式创建的转储,并读取它们

6.2. 编译头文件

方法二,需要用到 gcc 编译器。gcc 通过编译头文件生成 tu 文件。不同版本的 gcc 使用的参数也不一样,通常是以 gcc8 作为分水岭。因为在 gcc8 之后,原本的 -fdump-lang-raw 替换了之前的 -fdump-translation-util,相应的原来的 tu 文件也会被替换为 raw 文件。具体可以在 TUDump.pm 文件中查看。
方法二对编译器的版本有一定的限制,使用方法三可以规避这些限制。

6.2.1. gcc 参数说明

说明:
  • fdump-lang-raw:转储原始的内部树数据,仅适用于 C++。
  • fdump-translation-unit:gcc8之前的选项,作用同上,只适用于 C++。
  • fkeep-inline-functions:处理 C 或 C++ 的内联函数。
  • c:编译或汇编源文件,带不链接。
  • x language:显示选择要编译的语言。
  • fpermissive:运行一些不合格的代码。
  • w:禁止所有警告消息。
更多的 gcc 选项可以查看:https://gcc.gnu.org/onlinedocs/

6.2.2. tu 或 raw 文件

tu 或者 raw 使用抽象语法树生成,原理比较复杂,通常简单的文件也会产生千百行输出,因此想读懂这些,可以先学习抽象语法树(AST)的相关内容。

6.3. 工作流程

完整的工作流程:
notion image
创建转储流程:
notion image

7. 总结与延伸

7.1. 总结

ABI Tracker 是用来追踪上游软件包 ABI 变化的项目,ABICC,ABI Dumper,Vtable Dumper,ABI Monitor,PkgDiff… 这些都是为了实现这个手段的中间产物。
对于出现的错误类型,可能随着语言的复杂程度提高而变得更加困难,这背后涉及的语法树,动态符号表等知识过于复杂,短期内也无法掌握。编译原理是一门复杂的知识,需要长期投入研究,不是短时间就能出成果的工作,想了解更多背后的原理,可以参考链接1中的文章进行学习。
该项目的意义是让人能清晰了解版本变化对ABI的影响,并不是要求要去修复这些,所以还是以展示性的数据为主。该项目的未来,会更加减少人工参与,朝着更加自动化的目标前进的。

7.2. 延伸

7.2.1. 实践优化

实践中,建议不要跳过生成 dump 文件这一步骤。因为虽然不采用 abi dump 文件,也可以进行比对,但是还是建议使用 dump 文件进行比对。这样对比更加自由,不用受限于编译环境,或者不同的系统版本,但最好使用同样版本的abicc。

7.2.2. 软件包对比

pkg-abidiff 项目,可以直接对比 rpm 包,项目地址为 https://github.com/lvc/pkg-abidiff 。但如果想依赖软件包自动的完成所有包的对比,实际执行中是不可能的。一些软件包对比的时候,需要个性化的定制过滤参数(比如上面的 GLibc),这是不可能通过完全自动化完成的。

7.2.3. 其他语言

此外,ABI Tracker 还有个兄弟项目,叫 JAPI Tracker,适用于 Java 项目追踪,示例网站是 https://abi-laboratory.pro/java/tracker/

7.2.4. 其他工具

icheck:C 语言 ABI/API 接口检测器。
用法:
shlib-compat:使用 DWARF 调试信息的 ABI 兼容性检测工具。
用法:

8. 参考链接

  1. https://blog.csdn.net/canpool/article/details/118380060
  1. https://sourceware.org/glibc/wiki/Testing/ABI_checker
  1. https://abi-laboratory.pro/java/tracker
  1. https://github.com/lvc/pkg-abidiff
  1. https://stackoverflow.com/questions/1970296/how-to-test-binary-compatibility-automatically
  1. https://wiki.openssl.org/index.php/ABI_Tracker
  1. https://gcc.gnu.org/onlinedocs/
中年码农的困境log-001-我与计算机