有没有办法在 Linux 上查询共享库的 TLS 模型?(例如使用 ldd 或其他工具)。
我在使用“initial-exec”模型加载太多库时遇到问题,并且想确定哪些第三方库使用此模型(因此我可以释放一些插槽,例如通过静态链接)。
这会导致错误:
dlopen: cannot load any more object with static TLS
看到这个问题。
有没有办法在 Linux 上查询共享库的 TLS 模型?(例如使用 ldd 或其他工具)。
我在使用“initial-exec”模型加载太多库时遇到问题,并且想确定哪些第三方库使用此模型(因此我可以释放一些插槽,例如通过静态链接)。
这会导致错误:
dlopen: cannot load any more object with static TLS
看到这个问题。
我自己遇到了这个错误,在调查它时,我来到了一个包含以下信息的邮件列表帖子:
如果您链接包含 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
该tls-global-dynamic.so
版本没有DT_FLAGS
条目,大概是因为它没有设置任何标志。readelf
因此,使用和grep
查找受影响的库创建脚本应该相当容易。