我自己也遇到了这个错误,在调查它的过程中,我发现了一个包含此信息的邮件列表帖子 http://www.redhat.com/archives/phil-list/2003-February/msg00077.html:
如果链接包含 IE 模型访问重定位的共享对象,则该对象
将设置 DF_STATIC_TLS 标志。根据规范,这意味着 dlopen
可能会拒绝加载它。
看着/usr/include/elf.h
, 我们有:
/* Values of `d_un.d_val' in the DT_FLAGS entry. */
...
#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */
所以你需要测试是否DF_STATIC_TLS
被设置在DT_FLAGS
共享库的入口。
为了测试,我使用线程本地存储创建了一段简单的代码:
static __thread int foo;
void set_foo(int new) {
foo = new;
}
然后我使用两个不同的线程本地存储模型对其进行了两次编译:
gcc -ftls-model=initial-exec -fPIC -c tls.c -o tls-initial-exec.o
gcc -shared tls-initial-exec.o -o tls-initial-exec.so
gcc -ftls-model=global-dynamic -fPIC -c tls.c -o tls-global-dynamic.o
gcc -shared tls-global-dynamic.o -o tls-global-dynamic.so
果然,我可以使用以下命令看到两个库之间的区别readelf
:
$ readelf --dynamic tls-initial-exec.so
Dynamic section at offset 0xe00 contains 25 entries:
Tag Type Name/Value
...
0x000000000000001e (FLAGS) STATIC_TLS
The tls-global-dynamic.so
版本没有DT_FLAGS
条目,大概是因为它没有设置任何标志。所以使用创建脚本应该相当容易readelf
and grep
查找受影响的库。