2015-05-21 1 views
7

Я просто изучаю, как TLS (потоковое локальное хранилище) реализовано в системах Linux. В документе ELF Handling for Thread-Local Storage объясняется, как требования программы к локальным переменным потока могут быть закодированы в двоичном формате ELF и как «среда выполнения» должна обрабатывать такие двоичные файлы.В Linux, TLS настроен ядром или libc (или другим языком исполнения)?

Однако мне не ясно, будет ли на практике «среда выполнения», которая устанавливает область (области) TLS, будет ядром Linux (и его кодом для загрузки двоичных файлов ELF) или некоторым кодом инициализации в libc. Может кто-нибудь объяснить кратко?

(Фон: Я пытаюсь статически связать и запустить приложение, но он segfaults при запуске. В gdb я вижу, что код segfaulting - это некоторый код init из libc. Он пытается прочитать статическую переменную используя адрес, относящийся к GS, но GS равен нулю.)

+2

glibc и musl - с открытым исходным кодом; вы можете проверить исходный код для них. –

+3

Обсуждаете ли вы TLS (потоковое локальное хранилище) или TLS (безопасность транспортного уровня)? Содержимое предлагает локальное хранилище; tag [tag: ssl] предлагает последний. Вы были синонимичны? Я удалил [tag: ssl] и добавил [tag: thread-local-storage], хотя [tag: tls], по-видимому, не был сопоставлен с [tag: ssl]. –

+0

@JonathanLeffler, я добавил tls, что означает поток-локальное хранилище. Спасибо за исправление ошибки. –

ответ

4

Инициация локального хранения нити является частью кода запуска, предоставленного libc. При статической привязке ваш компоновщик должен добавить инициализацию TLS к коду запуска, связанному с вашей программой.

Например, Glibc имеет __libc_setup_tls и _dl_tls_setup (среди других, связанных с вещами) в libc.a, которые будут добавлены к инициализации кода вашей программы, если вы связываете с помощью, скажем, gcc -static. (Для динамически связанных программ _dl_ ... функции являются частью динамического компоновщика погрузчика ELF, ld-linux.so, которая не используется для запуска статический связанной программы.)

Правильного TLS инициализация в статический связанно Таким образом, исполняемый файл является результатом совместной работы вашей библиотеки C (которая предоставляет код) и вашей инструментальной цепочки (которая должна понимать, как правильно соединить все необходимые коды запуска).

Участие ядра в инициализации TLS незначительно. (В принципе, он просто должен убедиться, что раздел .tdata доступен для libc для инициализации.) См. ELF file TLS and LOAD program sections.

+0

Это не отвечает на решающий вопрос о том, как сегмент GS настраивается, чтобы указать раздел TLS. Это то, что может сделать только ядро. –

+0

Я еще не смотрел на 'glibc', но я только что проверил' musl'. Он инициализирует TLS при запуске (как вы сказали), но затем также использует системный вызов 'set_thread_area', чтобы сделать запись в процессе 'LDT, которая указывает на пространство, выделенное для TLS. Затем libc устанавливает регистр '% gs' так, чтобы он ссылался на запись LDT для TLS. (Это на x86-32 - x86-64 использует другой регистр сегментов.) –

Смежные вопросы