Android 是否支持弱符号?
Does Android support weak symbols?
我一直在看这样的问题:
- Cannot load library: reloc_library[1285]: cannot locate 'rand'
- Android app crashes in the start because java.lang.UnsatisfiedLinkError
在我看来这可以用 weak symbols 来解决。也就是说,原生组件可以提供像 rand
这样的符号,但用 __attribute__((weak))
来装饰它们。如果符号在另一个库中找到,比如标准运行时,那么弱链接符号将 not 被使用。另一方面,如果缺少该符号,则将使用本机组件的版本。
我无法找到有关 Android 的信息(搜索时有太多不相关的噪音)。
我打开了我的 Crypto++/JNI 示例项目之一,并将以下内容添加到 CPP 文件中。 AutoSeededRandomPool
只是一个 Crypto++ 随机数生成器对象(下面没有什么特别或棘手的)。
// CPP file
#ifdef __cplusplus
extern "C" {
#endif
int __attribute__((weak)) rand(void)
{
int r;
AutoSeededRandomPool& prng = GetPRNG();
prng.GenerateBlock(&r, sizeof(r));
return r;
}
#ifdef __cplusplus
}
#endif
尝试编译它会导致 redefinition of int rand()
。我还尝试了以下方法:
// CPP file
#ifdef __cplusplus
extern "C" {
#endif
int rand(void) __attribute__((weak));
int random(void)
{
...
}
#ifdef __cplusplus
}
#endif
并将 int rand(void) __attribute__((weak));
移动到 H 文件会产生相同的 redefinition of int rand()
。
而且我没有收到任何关于未知属性的错误或警告。
我还看到 __GXX_WEAK__
在预处理器中被定义为 1
,但是 SUPPORTS_WEAK
没有 定义,所以它的混合信号(可能是一个错误,类似于 Define GXX_WEAK to 0 when using -fno-weak)。
我不确定是我做错了什么,还是遇到了 const and weak attribute with c++ code 之类的事情,或者其他事情。
Android是否支持弱符号?如果是,如何使用它们。
这里有一个没有答案的类似 Stack Overflow 问题:
- Different behavior of override weak function in shared library between OS X and Android
一些系统细节:
- 基本系统是 Mac OS X 10.8.5,已完全修补
- Eclipse 4.4.1 (Luna),完全修补
- Android NDK 修订版 10d
- GCC 4.9 交叉编译器
Android 不支持弱符号覆盖。
在最近的版本 android-5.0.2_r1 中,
请参阅 linker.cpp source code
中第 539 行的注释
/*
*
* Notes on weak symbols:
* The ELF specs are ambigious about treatment of weak definitions in
* dynamic linking. Some systems return the first definition found
* and some the first non-weak definition. This is system dependent.
* Here we return the first definition found for simplicity.
*/
此评论存在于版本 2.2_r1(在 linker.c 中)到最新版本 5.0.2_r1
tl;博士; Android 支持弱符号
请注意,这不是 android 特定的,它同样适用于 ld-linux。so/ld:
这需要澄清一下,因为有 2 种情况使用了弱符号:
- 静态libraries/object 个文件
- 动态libraries/executables
(1) 对于静态库和目标文件,可以定义多个弱符号,并在最终对象(.so 或可执行文件)的编译时链接期间选择正确的符号(最强或第一)。
(2) 对于动态库,弱符号的行为方式与默认符号相同,但有一个例外。这意味着共享库没有弱符号覆盖之类的东西。换句话说,在 relocation/dlsym() 期间,将返回第一个找到的 (GLOBAL) 符号:weak 或 default。
例如(这里我们假设none个对象是-Bsymbolic,这是另一个例外):
| main.executable <- foo()
的弱(弱)定义
| -> lib1.so <- foo()
的强(默认)定义
| -> lib2.so <- 使用 foo()
lib2.so 将使用 main.executalbe 的 foo() 实现,尽管 lib1.so 导出 DEFAULT foo() 的速度很快。
例外情况是 WEAK 符号在运行时链接过程中被允许保持未解析状态,并在大多数有用的情况下导致空引用...当未解析的 DEFAULT 符号运行时链接器失败时。
我一直在看这样的问题:
- Cannot load library: reloc_library[1285]: cannot locate 'rand'
- Android app crashes in the start because java.lang.UnsatisfiedLinkError
在我看来这可以用 weak symbols 来解决。也就是说,原生组件可以提供像 rand
这样的符号,但用 __attribute__((weak))
来装饰它们。如果符号在另一个库中找到,比如标准运行时,那么弱链接符号将 not 被使用。另一方面,如果缺少该符号,则将使用本机组件的版本。
我无法找到有关 Android 的信息(搜索时有太多不相关的噪音)。
我打开了我的 Crypto++/JNI 示例项目之一,并将以下内容添加到 CPP 文件中。 AutoSeededRandomPool
只是一个 Crypto++ 随机数生成器对象(下面没有什么特别或棘手的)。
// CPP file
#ifdef __cplusplus
extern "C" {
#endif
int __attribute__((weak)) rand(void)
{
int r;
AutoSeededRandomPool& prng = GetPRNG();
prng.GenerateBlock(&r, sizeof(r));
return r;
}
#ifdef __cplusplus
}
#endif
尝试编译它会导致 redefinition of int rand()
。我还尝试了以下方法:
// CPP file
#ifdef __cplusplus
extern "C" {
#endif
int rand(void) __attribute__((weak));
int random(void)
{
...
}
#ifdef __cplusplus
}
#endif
并将 int rand(void) __attribute__((weak));
移动到 H 文件会产生相同的 redefinition of int rand()
。
而且我没有收到任何关于未知属性的错误或警告。
我还看到 __GXX_WEAK__
在预处理器中被定义为 1
,但是 SUPPORTS_WEAK
没有 定义,所以它的混合信号(可能是一个错误,类似于 Define GXX_WEAK to 0 when using -fno-weak)。
我不确定是我做错了什么,还是遇到了 const and weak attribute with c++ code 之类的事情,或者其他事情。
Android是否支持弱符号?如果是,如何使用它们。
这里有一个没有答案的类似 Stack Overflow 问题:
- Different behavior of override weak function in shared library between OS X and Android
一些系统细节:
- 基本系统是 Mac OS X 10.8.5,已完全修补
- Eclipse 4.4.1 (Luna),完全修补
- Android NDK 修订版 10d
- GCC 4.9 交叉编译器
Android 不支持弱符号覆盖。
在最近的版本 android-5.0.2_r1 中, 请参阅 linker.cpp source code
中第 539 行的注释/*
*
* Notes on weak symbols:
* The ELF specs are ambigious about treatment of weak definitions in
* dynamic linking. Some systems return the first definition found
* and some the first non-weak definition. This is system dependent.
* Here we return the first definition found for simplicity.
*/
此评论存在于版本 2.2_r1(在 linker.c 中)到最新版本 5.0.2_r1
tl;博士; Android 支持弱符号
请注意,这不是 android 特定的,它同样适用于 ld-linux。so/ld:
这需要澄清一下,因为有 2 种情况使用了弱符号:
- 静态libraries/object 个文件
- 动态libraries/executables
(1) 对于静态库和目标文件,可以定义多个弱符号,并在最终对象(.so 或可执行文件)的编译时链接期间选择正确的符号(最强或第一)。
(2) 对于动态库,弱符号的行为方式与默认符号相同,但有一个例外。这意味着共享库没有弱符号覆盖之类的东西。换句话说,在 relocation/dlsym() 期间,将返回第一个找到的 (GLOBAL) 符号:weak 或 default。
例如(这里我们假设none个对象是-Bsymbolic,这是另一个例外):
| main.executable <- foo()
的弱(弱)定义
| -> lib1.so <- foo()
的强(默认)定义
| -> lib2.so <- 使用 foo()
lib2.so 将使用 main.executalbe 的 foo() 实现,尽管 lib1.so 导出 DEFAULT foo() 的速度很快。
例外情况是 WEAK 符号在运行时链接过程中被允许保持未解析状态,并在大多数有用的情况下导致空引用...当未解析的 DEFAULT 符号运行时链接器失败时。