为什么 LTO 在 armv8a NDK 构建中引入新的 DT 标志 TLSDESC_PLT 和 TLSDESC_GOT
Why does LTO introduce new DT flags TLSDESC_PLT and TLSDESC_GOT in armv8a NDK build
我正在使用 NDK 为 Android 构建一个 armv8a SDK,我想在启用 LTO 的情况下进行构建。我在 C++ 工具链的编译和 link 标志中添加了 -flto
,一切顺利,直到我尝试在模拟器中添加 运行,此时发出如下错误:
WARNING: linker: /data/lib/libservice.so: unused DT entry: type 0x6ffffef6 arg 0x8e30
和
WARNING: linker: /data/lib/libservice.so: unused DT entry: type 0x6ffffef7 arg 0x2fb50
一些研究让我找到了 this answer,这让我能够挖掘出 0x6ffffef6
和 0x6ffffef6
的符号名称,它们恰好是 TLSDESC_PLT
和 TLSDESC_GOT
显然与动态 linker 和 PLT/GOT 以及 TLS 有关。很好
比较非 LTO 构建与 LTO 构建,这些标志肯定只用于 LTO 构建:
$ readelf -a /lto/lib/libservice.so | grep TLS
L (link order), O (extra OS processing required), G (group), T (TLS),
TLS 0x000000000001ed70 0x000000000002ed70 0x000000000002ed70
0x000000006ffffef6 (TLSDESC_PLT) 0x8e30
0x000000006ffffef7 (TLSDESC_GOT) 0x2fb50
00000002ffd8 000000000407 R_AARCH64_TLSDESC 0
00000002ffe8 000000000407 R_AARCH64_TLSDESC 8
579: 0000000000000008 8 TLS LOCAL DEFAULT 17 _ZN5xxxxx12_GLOBAL__N_113
788: 0000000000000000 1 TLS LOCAL DEFAULT 17 __tls_guard
$
$ readelf -a /nolto/lib/libservice.so | grep TLS
L (link order), O (extra OS processing required), G (group), T (TLS),
$
那么,一些问题:
- 为什么 android armv8a 运行time 拒绝这些 DT 标志?
- 为什么启用 LTO 似乎会改变 TLS 实施或需求?为什么会发出这些标签(连同其他符号)?
- 如何防止或避免此问题?我可以申请其他 TLS 模型吗?
- 我至少发现了一个类似的问题,其中 Android 环境拒绝
$ORIGIN
处理通常需要的标志 DT_ORIGIN
,但仍然尊重 $ORIGIN
即使没有设置 DT_ORIGIN
。 TLDESC_
标志的拒绝是否可能是一个类似的过分热心的检查,代码实际上是好的,这将表明 NDK 错误?
任何见解表示赞赏。请注意,这似乎适用于其他 Android 目标,特别是 Android x86_64 构建与 -flto
一起工作得很好,并且生成的二进制文件没有任何 TLSDESC
readelf -a
输出中的任何内容。
我升级到NDK r18 beta2,我不再有这个问题。看来潜在的错误与不通过 gold 链接器插件传播模拟 TLS 的使用有关(参见 https://github.com/android-ndk/ndk/issues/498),该插件已在 r18 中修复。
我正在使用 NDK 为 Android 构建一个 armv8a SDK,我想在启用 LTO 的情况下进行构建。我在 C++ 工具链的编译和 link 标志中添加了 -flto
,一切顺利,直到我尝试在模拟器中添加 运行,此时发出如下错误:
WARNING: linker: /data/lib/libservice.so: unused DT entry: type 0x6ffffef6 arg 0x8e30
和
WARNING: linker: /data/lib/libservice.so: unused DT entry: type 0x6ffffef7 arg 0x2fb50
一些研究让我找到了 this answer,这让我能够挖掘出 0x6ffffef6
和 0x6ffffef6
的符号名称,它们恰好是 TLSDESC_PLT
和 TLSDESC_GOT
显然与动态 linker 和 PLT/GOT 以及 TLS 有关。很好
比较非 LTO 构建与 LTO 构建,这些标志肯定只用于 LTO 构建:
$ readelf -a /lto/lib/libservice.so | grep TLS
L (link order), O (extra OS processing required), G (group), T (TLS),
TLS 0x000000000001ed70 0x000000000002ed70 0x000000000002ed70
0x000000006ffffef6 (TLSDESC_PLT) 0x8e30
0x000000006ffffef7 (TLSDESC_GOT) 0x2fb50
00000002ffd8 000000000407 R_AARCH64_TLSDESC 0
00000002ffe8 000000000407 R_AARCH64_TLSDESC 8
579: 0000000000000008 8 TLS LOCAL DEFAULT 17 _ZN5xxxxx12_GLOBAL__N_113
788: 0000000000000000 1 TLS LOCAL DEFAULT 17 __tls_guard
$
$ readelf -a /nolto/lib/libservice.so | grep TLS
L (link order), O (extra OS processing required), G (group), T (TLS),
$
那么,一些问题:
- 为什么 android armv8a 运行time 拒绝这些 DT 标志?
- 为什么启用 LTO 似乎会改变 TLS 实施或需求?为什么会发出这些标签(连同其他符号)?
- 如何防止或避免此问题?我可以申请其他 TLS 模型吗?
- 我至少发现了一个类似的问题,其中 Android 环境拒绝
$ORIGIN
处理通常需要的标志DT_ORIGIN
,但仍然尊重$ORIGIN
即使没有设置DT_ORIGIN
。TLDESC_
标志的拒绝是否可能是一个类似的过分热心的检查,代码实际上是好的,这将表明 NDK 错误?
任何见解表示赞赏。请注意,这似乎适用于其他 Android 目标,特别是 Android x86_64 构建与 -flto
一起工作得很好,并且生成的二进制文件没有任何 TLSDESC
readelf -a
输出中的任何内容。
我升级到NDK r18 beta2,我不再有这个问题。看来潜在的错误与不通过 gold 链接器插件传播模拟 TLS 的使用有关(参见 https://github.com/android-ndk/ndk/issues/498),该插件已在 r18 中修复。