Подтвердить что ты не робот

"Неверная локальная ссылка на регулярный символ" в переменной TLS

У меня странная проблема, возникающая во время связывания.

У меня есть файл заголовка, который содержит следующее определение foo.hpp:

struct Foo { static __thread int x; }

И исходный файл, который ссылается на эту переменную plugin.cpp:

#include "foo.hpp"
void bar() { int y = Foo::x; }

Скомпилируется с помощью:

$CXX -stdlib=libc++ -std=c++11 -fvisibility=hidden -fPIC -o plugin.cpp.o -c plugin.cpp

Но когда я пытаюсь подключиться как динамическая библиотека:

$CXX -stdlib=libc++ -std=c++11 -fvisibility=hidden -dynamiclib -Wl,-undefined,dynamic_lookup -o libext.dylib ext.cpp.o

Я получаю:

ld: ссылка на локальную переменную нелегального потока на обычный символ __ZN3Foo1xE для архитектуры x86_64

Однако байт-код llvm подразумевает, что компилятор правильно видит Foo::x как переменную TLS.

$CXX -stdlib=libc++ -std=c++11 -fvisibility=hidden -fPIC -S -emit-llvm -o -
... omitted
@_ZN3Foo1xE = external thread_local global i32
... omitted
; Function Attrs: nounwind ssp uwtable
define hidden void @_Z3barv() #0 {
  %y = alloca i32, align 4
  %1 = load i32* @_ZN3Foo1xE, align 4
  store i32 %1, i32* %y, align 4
  ret void
}

Что может быть причиной этой проблемы с компоновщиком, и есть ли обходной путь? Кажется, я не могу найти никаких сообщений об ошибках, связанных с этим.

Примечания:

  • Это чистое использование Apple LLVM 7.0.0
  • У меня нет проблем с связыванием с помощью gcc 5 или gcc 4.9.3 на OS X

ИЗМЕНИТЬ Та же проблема существует при ссылке на глобальную переменную (вместо статического класса).

Когда я использую thread_local вместо __thread, это отлично работает, однако thread_local не работает с версией LLVM, которая поставляется с Xcode.

4b9b3361

Ответ 1

Яблочный исполняемый формат файла (MACH-O, я считаю) не позволяет локальное хранилище Thread. Это боль в заднице. Вы должны создать пространство в распределении памяти библиотеки потоков и скрыть локальные переменные потока. Это очень неясно.