"本地符号'__bss_start'在符号表的全局部分",仅在Android NDK aarch64构建中出现。

4 人关注

我正在用NDK(r19b)为 arm aarch64 x86 x86_64 创建一个Android库。一切正常,只是当我为 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

当我用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__

我当然可以看到_edata_end__bss_start是在LOCAL而不是GLOBAL中,但我没有(或者至少我认为我没有)为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

那么,为什么aarch64不同?更好的是,我如何将这些移到GLOBAL?

[最新消息] 感谢温和的朋友们在https://github.com/android-ndk/ndk/issues/927,我发现这个解决方案效果最好;注意最后的"-fuse-ld=lld"。

APP_LDFLAGS := -Wl,--gc-sections,--strip-debug -fvisibility=hidden -fuse-ld=lld

这样一来,我仍然可以保留--gc-sections,而--no-fatal-warnings也没有必要。

[更多最新信息] 这个问题中显示的例子是用ndk-build,如果你使用的是带有Gradle的Android Studio,你很可能会有CMake。在这种情况下,添加你的编译器标志,如下所示。

[app/build.gradle]
android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                cppFlags '-fuse-ld=lld'
    
2 个评论
好的,我正在使用Android Studio和Gradle。我应该怎么编辑?
请注意,自NDK r22以来,LLD是默认的链接器。 github.com/android/ndk/wiki/Changelog-r22
android
android-ndk
arm64
solamour
solamour
发布于 2019-03-06
2 个回答
Dan Albert
Dan Albert
发布于 2021-12-02
已采纳
0 人赞同

APP_LDFLAGS := -Wl,-fvisibility=hidden

这有什么作用吗?这个选项没有出现在bfd的帮助页面上,但这些符号是由链接器发出的,所以我想知道是否是这个原因造成的。

如果不行,可以尝试在你的 -fuse-ld=gold (或者 -fuse-ld=lld ,如果你觉得很冒险,但是如果你需要支持的话,有很多Windows KIs都有这个功能)中加入 APP_LDFLAGS 。在NDK中,arm64和其他架构的最大区别是,我们仍然对arm64使用bfd。

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

一旦我删除了 --gc-sections ,在 LOCAL 中就没有什么显示了。库的大小略有增加,但我可以接受。
在我看来,这听起来像是一个错误。如果你改用gold(不过要提醒你,它对arch64的ldb会产生不好的调试信息)或ld(NDK的测试版),你可能可以保留这个标志。非常不幸的是,现在NDK中没有一个好的链接器选择,但我们正在努力解决这个问题。
替换代码0】和 -fuse-ld=lld 都没有任何区别; _edata _end __bss_start 都在 LOCAL 中。我可能需要把它归结为当前NDK的限制。
是的,我刚刚注意到,ld也是你最初使用的东西。这确实很奇怪,而且修复方法也很奇怪。我提交了 github.com/android-ndk/ndk/issues/927 为这个问题。如果你能提供一个测试案例,那将是非常棒的(还没有尝试过任何东西,所以也许在一个简单的hello world中也会发生这种情况?)
^这是一个将构建失败转化为运行时失败的绝佳方法。
zeitgeist
zeitgeist
发布于 2021-12-02
0 人赞同

我在使用外部 libExternal.so 文件时遇到了这个问题。

由于我没有源代码,我无法用LLD重建它。

我最终能够通过在我的项目中禁用链接器的警告来使用 libExternal.so 文件。 这个链接很有帮助 https://github.com/android/ndk/issues/927

我在AOSP(安卓10)中做了一个JNI安卓应用,使用了一个 sample.cpp 文件,该文件使用了 libExternal.so 。 我的应用程序能够用mm命令建立,并在设备上正常工作。

下面是我在AOSP构建(Android 10)中使用的 Android.mk 文件。

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := External
LOCAL_SRC_FILES := libExternal.so
LOCAL_MODULE_TAGS := samples
#LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
#LOCAL_LDFLAGS += -fuse-ld=gold
#LOCAL_EXPORT_LDFLAGS += -fuse-ld=gold
#LOCAL_DISABLE_FATAL_LINKER_WARNINGS := true
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := c++
LOCAL_SRC_FILES := libc++.so
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
#LOCAL_LDFLAGS += -fuse-ld=gold
#LOCAL_EXPORT_LDFLAGS += -fuse-ld=gold
#LOCAL_DISABLE_FATAL_LINKER_WARNINGS := true
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := libsample
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
#LOCAL_DISABLE_FATAL_LINKER_WARNINGS := true
#LOCAL_CFLAGS += -Iinclude
LOCAL_SRC_FILES := sample.cpp
LOCAL_REQUIRED_MODULES := External
#LOCAL_SHARED_LIBRARIES := External cdsprpc cutils c++ base log
LOCAL_SHARED_LIBRARIES := External
LOCAL_MODULE_TARGET_ARCH := arm64
#LOCAL_MODULE_TARGET_ARCH := arm64-v8a
#LOCAL_LDLIBS += $(LOCAL_PATH)/libExternal.so
#https://stackoverflow.com/questions/65597460/how-to-restrict-android-mk-to-compile-a-module-to-generate-only-64bit-library
LOCAL_CFLAGS += -Wall -std=c99 -g
LOCAL_CPPFLAGS += -Wall -std=c++03 -D_GLIBCXX_USE_CXX11_ABI=0 -g
# Does not build even after commenting below line
#LOCAL_LDLIBS := -lm -lstdc++ -ldl
#LOCAL_LDFLAGS += -fuse-ld=gold
#LOCAL_EXPORT_LDFLAGS += -fuse-ld=gold
#include $(BUILD_EXECUTABLE)
LOCAL_DISABLE_FATAL_LINKER_WARNINGS := true
LOCAL_LDFLAGS := -Wl,--no-fatal-warnings
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
res_dir := res $(LOCAL_PATH)/res
#LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := samples
LOCAL_SRC_FILES := $(call all-java-files-under, java)
LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dir))
LOCAL_USE_AAPT2 := true
LOCAL_JAVA_LIBRARIES := com.google.android.material_material
LOCAL_STATIC_ANDROID_LIBRARIES := \
        androidx.appcompat_appcompat \
        androidx-constraintlayout_constraintlayout \
        androidx.preference_preference \
        androidx.fragment_fragment \
        androidx.core_core
#LOCAL_REQUIRED_MODULES := sample External
LOCAL_REQUIRED_MODULES := External \
                           libsample \
                           libc++
LOCAL_SHARED_LIBRARIES := External \
                           libsample \
                           libc++
#LOCAL_LDLIBS += -lsample
LOCAL_JNI_SHARED_LIBRARIES := libsample libc++
#LOCAL_JNI_SHARED_LIBRARIES := libsample
#LOCAL_PREBUILT_JNI_LIBS := $(LOCAL_PATH)/libsample.so
LOCAL_PREBUILT_JNI_LIBS := libExternal.so
LOCAL_CERTIFICATE := platform