llvm-ifs - 共享对象存根工具

摘要

llvm-ifs [选项] 输入文件

描述

llvm-ifs 是一个工具,它可以从 ELF 共享对象或基于文本的存根共同生成人类可读的基于文本的存根(.ifs 文件)和可链接的共享对象存根(.so 文件)。基于文本的存根可用于监控共享对象的 ABI 变化。可链接的共享对象存根可用于避免在共享库的 ABI 没有更改时进行不必要的重新链接。

IFS 格式

以下是 llvm-ifs 生成的共享对象的文本表示(IFS)示例。

--- !ifs-v1
IFSVersion: 3.0
SoName: libtest.so /* Optional */
Target: x86_64-unknown-linux-gnu   /* Optional, format 1, same format as llvm target triple */
Target: { Arch: x86_64, Endianness: little, Bitwidth: 64 } /* Optional, format 2 */
NeededLibs:
  - libc.so.6
Symbols:
  - { Name: sym0, Type: Notype }
  - { Name: sym1, Type: Object, Size: 0 }
  - { Name: sym2, Type: Func, Weak: false }
  - { Name: sym3, Type: TLS }
  - { Name: sym4, Type: Unknown, Warning: foo }
...
  • IFSVersion: IFS 文件的版本,用于读取器兼容性。

  • SoName (可选): 正在创建存根的共享对象文件的名称。

  • Target (可选): 此共享对象的体系结构、字节序和位信息。它可以是显式格式或隐式 LLVM 三元组格式。它可以是可选的,并且可以从命令行选项覆盖。

  • NeededLibs: 此库依赖的外部共享对象的列表。

  • Symbols: 所有用于链接每个符号的对象所需数据的集合,按名称升序排序。

    • Name: 符号名称。

    • Type: 符号是对象、函数、无类型、线程本地存储还是未知。未明确支持的符号类型被映射为未知,以提高信噪比。

    • Size: 有关符号的大小,不适用于函数,并且对于 NoType 符号是可选的。

    • Undefined: 符号是否在此共享对象文件中定义。

    • Weak: 符号是否应被视为弱符号。

    • Warning (可选): 当链接此符号时输出的警告文本。

这种基于 YAML 的文本格式包含生成可链接 ELF 共享对象以及 Apple TAPI 格式文件所需的一切。符号的顺序是排序的,因此可以使用 diff 工具轻松比较这些文件。如果文件内容发生变化,则表示可能存在 ABI 冲突更改。

ELF 存根格式

链接器可以使用的一个最小 ELF 文件应正确填充以下部分

  • ELF 头。

  • 节头。

  • 动态符号表(.dynsym 节)。

  • 动态字符串表(.dynstr 节)。

  • 动态表(.dynamic 节)。

    • DT_SYMTAB 条目。

    • DT_STRTAB 条目。

    • DT_STRSZ 条目。

    • DT_NEEDED 条目。(可选)

    • DT_SONAME 条目。(可选)

  • 节头字符串表(.shstrtab 节)

此 ELF 文件可能与依赖于程序头的 ELF 分析工具存在兼容性问题。像 LLD 这样的链接器可以很好地处理这样的最小 ELF 文件,而不会出现错误。

选项

--input-format=[IFS|ELF|OtherObjectFileFormats]

指定输入文件格式。目前,仅支持文本 IFS 文件和 ELF 共享对象文件。此标志是可选的,因为可以推断出输入格式。

--output-elf=<输出文件名>

指定 ELF 共享对象存根的输出文件。

--output-ifs=<输出文件名>

指定文本 IFS 的输出文件。

--output-tbd=<输出文件名>

指定 Apple TAPI tbd 的输出文件。

--arch=[x86_64|AArch64|...]

此标志是可选的,仅应在读取未定义 Arch(体系结构)的 IFS 文件时使用。此标志定义输出文件的体系结构,可以是 ELF 'e_machine' 字段支持的任何字符串。如果该值与 IFS 文件冲突,则会报告错误并程序将停止。

--endianness=[little|big]

此标志是可选的,仅应在读取未定义 Endianness 的 IFS 文件时使用。此标志定义输出文件的字节序。如果该值与 IFS 文件冲突,则会报告错误并程序将停止。

--bitwidth=[32|64]

此标志是可选的,仅应在读取未定义 BitWidth 的 IFS 文件时使用。此标志定义输出文件的位宽。如果该值与输入 IFS 文件冲突,则会报告错误并程序将停止。

--target=<目标三元组>

此标志是可选的,仅应在读取未定义任何目标信息的 IFS 文件时使用。此标志使用 llvm 目标三元组定义输出文件的体系结构、字节序和位宽。此标志不能与其他目标相关标志同时使用。

--hint-ifs-target=<目标三元组>

此标志是可选的,仅应在读取 ELF 共享对象并生成 IFS 文件时使用。默认情况下,llvm-ifs 将使用 ' ArchEndiannessBitWidth' 字段来反映输入对象文件中的目标信息。使用此标志将告诉 llvm-ifs 输出 IFS 文件中预期的目标三元组。如果该值与对象文件中的目标信息匹配,则此值将在生成的 IFS 中的 'Target:' 字段中使用。如果它与输入对象文件冲突,则会报告错误并程序将停止。

--hint-ifs-target

此标志是可选的,仅应在输出 IFS 文件时使用。此标志从 IFS 文件中剥离 Arch 字段,以便以后可以覆盖它。

--strip-ifs-endianness

此标志是可选的,仅应在输出 IFS 文件时使用。此标志从 IFS 文件中剥离 Endianness 字段,以便以后可以覆盖它。

--strip-ifs-bitwidth

此标志是可选的,仅应在输出 IFS 文件时使用。此标志从 IFS 文件中剥离 BitWidth 字段,以便以后可以覆盖它。

--strip-ifs-target

此标志是可选的,仅应在输出 IFS 文件时使用。此标志从 IFS 文件中剥离 Target 字段,以便以后可以覆盖它。

--write-if-changed

当设置此标志时,llvm-ifs 仅当输出文件尚不存在或内容与现有文件不同时才会写入输出文件。

--strip-size

当设置此标志时,llvm-ifs 将从输出 ifs 文件中删除大小字段。这对于仅打算链接到不依赖于复制重定位的位置无关代码的共享对象,或者对象的大小不是要跟踪的 abi 的有用部分时很有用。

退出状态

如果 llvm-ifs 成功,它将以 0 退出。否则,如果发生错误,它将以非零值退出。