“符号表全局部分中的本地符号‘__bss_start’”仅在 Android NDK aarch64 构建中

sol*_*our 5 android android-ndk arm64

我正在使用 NDK (r19b) 创建一个 Android 库arm,用于aarch64x86、 和x86_64。一切都很好,除了当我构建aarch64架构应用程序时,我收到以下错误消息。

ld.lld: error: found local symbol '_edata' in global part of symbol table in file libmystuff.so
ld.lld: error: found local symbol '_end' in global part of symbol table in file libmystuff.so
ld.lld: error: found local symbol '__bss_start' in global part of symbol table in file libmystuff.so
Run Code Online (Sandbox Code Playgroud)

当我使用 检查每个构建变体时readelf -s libmystuff.so,我注意到只有一个aarch64是不同的。

[arm]
    4021: 007a30f0     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    4022: 007c6b10     0 NOTYPE  GLOBAL DEFAULT  ABS _end
    4023: 007a30f0     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start

[x86]
    3848: 00c82c88     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    3849: 00ca4b28     0 NOTYPE  GLOBAL DEFAULT  ABS _end
    3850: 00c82c88     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start

[x86_64]
    3874: 0000000000c9b890     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    3875: 0000000000ce5f68     0 NOTYPE  GLOBAL DEFAULT  ABS _end
    3876: 0000000000c9b890     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start

[aarch64]
       3: 0000000000b4f168     0 NOTYPE  LOCAL  DEFAULT  ABS _edata
       4: 0000000000b990e8     0 NOTYPE  LOCAL  DEFAULT  ABS _end
       5: 0000000000b4f168     0 NOTYPE  LOCAL  DEFAULT  ABS __bss_start

     865: 0000000000b9e3e8     0 NOTYPE  GLOBAL DEFAULT  ABS __end__
    2468: 0000000000b54168     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start__
Run Code Online (Sandbox Code Playgroud)

我当然可以看到_edata_end、 和__bss_start是本地的而不是全局的,但我没有(或者至少我认为我没有)为 ; 做任何特别的事情aarch64;它们都使用相同的构建配置。

jni/Application.mk
    NDK_TOOLCHAIN_VERSION := clang
    APP_STL := c++_static
    APP_CFLAGS := -fstack-protector-all -fvisibility=hidden -ffunction-sections -fdata-sections
    APP_CPPFLAGS := -fstack-protector-all -std=c++11 -fvisibility=hidden -ffunction-sections -fdata-sections -frtti
    APP_LDFLAGS := -Wl,--gc-sections,-fvisibility=hidden,--strip-debug
Run Code Online (Sandbox Code Playgroud)

那么,为什么aarch64不同呢?更好的是,我如何将它们移至全球?

[更新] 感谢https://github.com/android-ndk/ndk/issues/927上的好心人,我发现该解决方案效果最好;请注意末尾的“-fuse-ld=lld”。

APP_LDFLAGS := -Wl,--gc-sections,--strip-debug -fvisibility=hidden -fuse-ld=lld
Run Code Online (Sandbox Code Playgroud)

这样我还是可以保留的--gc-sections--no-fatal-warnings也没有必要。

[更多更新] 这个问题中显示的示例是使用ndk-build,如果您将 Android Studio 与 Gradle 一起使用,那么您很可能会使用CMake. 在这种情况下,请添加编译器标志,如下所示。

[app/build.gradle]
android {
    ...
    defaultConfig {
        externalNativeBuild {
            cmake {
                cppFlags '-fuse-ld=lld'
            }
Run Code Online (Sandbox Code Playgroud)

Dan*_*ert 3

APP_LDFLAGS := -Wl,-fvisibility=hidden

这有什么作用吗?此选项不会出现在 bfd 的帮助页面中,但这些符号是由链接器发出的,所以我想知道这是否是导致此问题的原因。

如果做不到这一点,请尝试将-fuse-ld=gold(或者-fuse-ld=lld如果您喜欢冒险,但如果您需要支持的话,有许多 Windows KI 可以实现)添加到您的APP_LDFLAGS. arm64 与 NDK 中其他架构最大的区别是我们仍然使用 bfd for arm64。

由于这些是由链接器发出的符号,因此这似乎是最有可能的罪魁祸首。