【问题标题】:Is there a way to determine thread local storage model used by a library on Linux有没有办法确定 Linux 上的库使用的线程本地存储模型
【发布时间】:2014-05-23 22:05:36
【问题描述】:

有没有办法在 Linux 上查询共享库的 TLS 模型? (例如使用 ldd 或其他工具)。

我在使用“initial-exec”模型加载太多库时遇到问题,我想确定哪些第三方库使用此模型(因此我可以释放一些插槽,例如通过静态链接) .

这会导致错误:

 dlopen: cannot load any more object with static TLS

this question

【问题讨论】:

    标签: linux shared-libraries glibc thread-local-storage ldd


    【解决方案1】:

    我自己遇到了这个错误,在调查它时,我遇到了mailing list post with this info

    如果您链接包含 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 条目,大概是因为它没有设置任何标志。因此,使用readelfgrep 创建脚本来查找受影响的库应该相当容易。

    【讨论】:

    • 非常感谢!很好的答案。我还发现readelf -l library | grep TLS 很有用。这表明是否有任何线程位置存储。事实证明,任何带有 TLS 的东西也使用 DTV 插槽(因此可以阻止以后加载 STATIC_TLS 对象),但如果您首先加载 STATIC_TLS 对象,非初始执行对象使用另一种方法并且不占用插槽。
    • @robince 非常感谢您所以的评论 (+1)。我不明白为什么加载顺序很重要
    • 我最近发现,即使使用静态 TLS,aarch64 二进制文件在 FLAGS 中也没有 STATIC_TLS。我发现最好的方法是在readelf -a -W library | grep R_AARCH64_TLS_TPREL64 输出中查找重定位条目。如果有,则表示静态 TLS 二进制文件。 x86_64 的等价物是R_X86_64_TPOFF64
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-24
    • 2019-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多