简体   繁体   English

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

[英]"local symbol '__bss_start' in global part of symbol table" only in Android NDK aarch64 build

I'm creating an Android library with NDK (r19b) for arm , aarch64 , x86 , and x86_64 .我正在为armaarch64x86x86_64创建一个带有 NDK (r19b) 的 Android 库。 All is OK, except that when I build an app for aarch64 architecture, I get the following error message.一切正常,除了当我为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

When I checked each build variant with readelf -s libmystuff.so , I noticed that only aarch64 is different.当我使用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__

I can surely see _edata , _end , and __bss_start are in LOCAL instead of GLOBAL, but I don't (or at least I think I don't) do anything special for aarch64 ;我当然可以看到_edata_end__bss_start在 LOCAL 而不是 GLOBAL 中,但我没有(或者至少我认为我没有)为aarch64做任何特别的aarch64 they all use the same build configuration.它们都使用相同的构建配置。

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

So, why is aarch64 different?那么,为什么aarch64不同呢? Better yet, how do I move those to GLOBAL?更好的是,我如何将这些移动到 GLOBAL?

[UPDATE] Thanks to the gentle folks at https://github.com/android-ndk/ndk/issues/927 , I found the solution works best; [更新] 感谢https://github.com/android-ndk/ndk/issues/927 上的好心人,我发现这个解决方案效果最好; notice "-fuse-ld=lld" at the end.注意末尾的“-fuse-ld=lld”。

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

This way, I still get to keep --gc-sections , and --no-fatal-warnings is not necessary either.这样,我仍然可以保留--gc-sections ,并且--no-fatal-warnings也不是必需的。

[MORE UPDATE] The example shown in this question is using ndk-build , and if you are using Android Studio with Gradle, you'll most likely have CMake . [更多更新] 此问题中显示的示例使用ndk-build ,如果您将 Android Studio 与 Gradle 一起使用,则很可能会使用CMake In that case, add your compiler flags as the following.在这种情况下,添加您的编译器标志如下。

[app/build.gradle]
android {
    ...
    defaultConfig {
        externalNativeBuild {
            cmake {
                cppFlags '-fuse-ld=lld'
            }

APP_LDFLAGS := -Wl,-fvisibility=hidden

Does this do anything?这有什么作用吗? This option doesn't appear in the help page for bfd, but those symbols are emitted by the linker so I'm wondering if that's what's causing this.这个选项没有出现在 bfd 的帮助页面中,但是这些符号是由链接器发出的,所以我想知道这是否是导致这种情况的原因。

Failing that, try adding -fuse-ld=gold (or -fuse-ld=lld if you're feeling adventurous, but there are a number of Windows KIs with that if that's something you need to support) to your APP_LDFLAGS .如果失败,请尝试将-fuse-ld=gold (或-fuse-ld=lld如果您喜欢冒险,但如果您需要支持,则有许多 Windows KI)到您的APP_LDFLAGS The biggest difference between arm64 and the other architectures in the NDK is that we still use bfd for arm64. arm64 和 NDK 中其他架构最大的区别是我们仍然使用 bfd 来处理 arm64。

Since these are symbols that are emitted by the linker, this seems like the most likely culprit.由于这些是由链接器发出的符号,因此这似乎是最有可能的罪魁祸首。

I faced this problem when using an external libExternal.so file.我在使用外部libExternal.so文件时遇到了这个问题。

Since I did not have the source code, I couldn't rebuild it with LLD.由于我没有源代码,因此无法使用 LLD 重建它。

I eventually was able to use the libExternal.so file by disabling the linker warnings in my project.我最终能够通过在我的项目中禁用链接器警告来使用libExternal.so文件。 This link was very helpful https://github.com/android/ndk/issues/927此链接非常有用https://github.com/android/ndk/issues/927

I have made a JNI android app in AOSP (Android 10) that uses a sample.cpp file that uses libExternal.so .我在 AOSP(Android 10)中制作了一个 JNI android 应用程序,它使用了一个使用libExternal.sosample.cpp文件。 My app was able to be built with mm command and worked properly on device.我的应用程序能够使用 mm 命令构建并在设备上正常运行。

Here is the Android.mk file that I used in my AOSP build (Android 10).这是我在 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
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PACKAGE_NAME := NativeCPP
LOCAL_PRIVATE_PLATFORM_APIS := true
include $(BUILD_PACKAGE)

By the way I have also tried putting LOCAL_LDLIBS += -lstdc++ in the last block instead of using libc++.so and it works.顺便说一句,我还尝试将LOCAL_LDLIBS += -lstdc++放在最后一个块中,而不是使用libc++.so并且它有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM