Clang不会剥离本地静态库的符号

时间:2018-11-07 01:51:51

标签: android-ndk clang

使用Android NDK r18b(带有clang工具链)和Android Studio 3.2.1

我的mylib.gradle的相关部分:

task ndkBuild(type: Exec) {
    commandLine "${ndkDir}/ndk-build${ndkExt}"
}

我的Application.mk

APP_PLATFORM := android-17
APP_ABI := armeabi-v7a
# APP_OPTIM := release
APP_CFLAGS += -D_BSD_SOURCE

还有我的Android.mk的相关部分:

include $(CLEAR_VARS)

LOCAL_PATH := $(BASE_PATH)
LOCAL_MODULE := mylib_jni

LOCAL_STATIC_LIBRARIES := \
  lib1 \
  lib2

LOCAL_WHOLE_STATIC_LIBRARIES := \
  mylib_wrap \
  other_wrap

include $(BUILD_SHARED_LIBRARY)

静态库mylib_jni.so已成功构建。然后,我从NDK运行以下命令:

  

arm-linux-androideabi-readelf -a mylib_jni.so


未删除符号

在输出中,我可以在lib1lib2中看到所有非静态方法的名称(如上所示,不是整个库)。 这怎么可能?如何从ndk-build命令中获得一些输出,其中包含有关为何不删除符号的信息? (我找不到NDK构建步骤的options.txt。)

1 个答案:

答案 0 :(得分:4)

恐怕您在 strip visibility = hidden 之间感到困惑。

former是构建共享库的独立后链接步骤。其目的是通过删除链接器为调试目的而留下的一些额外信息,以减小文件(将打包为APK)的大小。请注意,当来自所有模块的本机库合并在一起时, gradle (在Android Studio 3.2+中)甚至会在以后执行此操作。

条带影响文件的大小,但不影响符号visibility

隐藏符号是另一种减小二进制文件大小的技术。强烈建议您使用这种方法,以减少您的库进行逆向工程的可能性。

默认情况下不会发生这种情况。您必须显式添加此编译器标志:

APP_CFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden

您可以将此与丢弃未使用的功能结合起来:

APP_CFLAGS += -ffunction-sections -fdata-sections
APP_LDFLAGS += -Wl,--gc-sections

您必须使用显式标记外部功能

__attribute__ ((visibility ("default")))

幸运的是,感谢 jni.h ,为所有JNIEXPORT功能集设置了此属性。

如果您使用预建的静态库,则may need also

APP_LDFLAGS += -Wl,--exclude-libs,ALL

考虑还提供version script

LOCAL_LDFLAGS += -Wl,-version-script -Wl,mylib_jni.vs