无法使用静态TLS加载更多对象

我有一个应用程序使用dlopen()来加载额外的模块。 应用程序和模块是在Ubuntu 12.04 x86_64上使用gcc 4.6而构build的,但是为了i386 arch。 然后将二进制文件复制到具有完全相同的操作系统的另一台机器,并正常工作

但是,如果它们被复制到Ubuntu 12.04 i386,则一些(但不是全部)模块将无法加载以下消息:

 dlopen: cannot load any more object with static TLS 

我怀疑这是由__threadvariables的使用引起的。 但是,这些variables不会在加载的模块中使用 – 只能在加载器模块本身中使用。

有人可以提供任何额外的信息,可以是什么原因?

我正在减less__threadvariables的数量并优化它们(使用-ftls-model等),我只是好奇它为什么不能在几乎相同的系统上工作。

Solutions Collecting From Web of "无法使用静态TLS加载更多对象"

我怀疑这是由__thread变量的使用引起的。

正确。

但是,这些变量不会在加载的模块中使用 – 只能在加载器模块本身中使用。

不正确。 你可能不会自己使用__thread ,但是你静态链接到你的模块中的一些库正在使用它们。 您可以通过以下方式确认:

 readelf -l /path/to/foo.so | grep TLS 

可能是什么原因?

该模块使用-ftls-model=initial-exec ,但应该使用-ftls-model=global-dynamic 。 这通常发生在链接到foo.so (某些)代码不带-fPIC

x86_64上将非-fPIC代码链接到共享库是不可能的,但在ix86上是允许的(并导致许多微妙的问题,比如这个)。

更新:

我有1个模块编译没有-fPIC,但我根本不设置tls-model,据我所知,默认值不是initial-exec

  • 每个ELF图像(可执行文件或共享库)只能有一个tls模型。
  • 对于非-fPIC代码,TLS模型默认为initial-exec

因此,如果甚至将一个使用__thread-fPIC对象链接到foo.so ,那么foo.so将为其所有 TLS获取initial-exec

那么为什么它会导致问题 – 因为如果使用initial-exec,则tls变量的数量是有限的(因为它们不是动态分配的)?

正确。