Есть ли способ определить модель локального хранилища потока, используемую библиотекой в ​​Linux?

Есть ли способ запросить модель TLS общей библиотеки в Linux? (например, используя ldd или какой-либо другой инструмент).

У меня возникли проблемы с загрузкой слишком большого количества библиотек с моделью «initial-exec», и я хотел бы точно определить, какие из сторонних библиотек используют эту модель (чтобы я мог освободить некоторые слоты, например, путем статической компоновки).

Это приводит к ошибке:

 dlopen: cannot load any more object with static TLS

см. этот вопрос.


person robince    schedule 10.04.2014    source источник


Ответы (1)


Я сам столкнулся с этой ошибкой и, исследуя ее, наткнулся на сообщение в списке рассылки с этой информацией:

Если вы связываете общий объект, содержащий релоки доступа модели 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 для поиска затронутых библиотек.

person James Henstridge    schedule 11.04.2014
comment
Большое спасибо! Отличный ответ. Я также нашел readelf -l library | grep TLS полезным. Это указывает, есть ли вообще какое-либо хранилище местоположения потока. Оказывается, что-либо с TLS также использует слот DTV (и поэтому может блокировать загрузку более поздних объектов STATIC_TLS), но если вы сначала загружаете объекты STATIC_TLS, объекты, отличные от intial-exec, используют другой метод и не занимают слот. - person robince; 13.04.2014
comment
@robince Большое спасибо большое за этот комментарий (+1). Я не мог понять, почему порядок загрузки имеет значение - person Hammer; 02.09.2020