https://sourceware.org/bugzilla/show_bug.cgi?id=16937
Bug ID: 16937 Summary: aarch64: issue about executable exporting TLS class static member variable Product: binutils Version: 2.25 (HEAD) Status: NEW Severity: normal Priority: P2 Component: ld Assignee: unassigned at sourceware dot org Reporter: jingyuuiuc at gmail dot com I have a piece of code behaves wrong on aarch64. The scenario is that both executable and shared library define a TLS class static member variable. On aarch64, the executable exports the symbol to dynamic symbol stable with GLOBAL DEFAULT attribute. When shared library is dlopened, dynamic loader finds the symbol in executable's symbol table and binds to it. Thus both dynamic library and executable share the same copy of this variable, which is wrong. It's generally not expected that the linker will export a symbol in the executable's dynamic symbol table unless it sees a reference from a shared library. $ g++ var_exe.cc -ldl -o var $ g++ -shared -fPIC var_l.cc -o libvar1.so $ g++ -shared -fPIC var_l.cc -o libvar2.so On aarch64: $ ./var exe: live += 5 exe: live = 5 Calling libentry in ./libvar1.so... lib: live += 3 lib: live = 8 Calling libentry in ./libvar2.so... lib: live += 3 lib: live = 11 $ readelf --dyn-syms -W var | grep _ZN3var4liveE 11: 0000000000000000 4 TLS GLOBAL DEFAULT 18 _ZN3var4liveE $ readelf --dyn-syms -W libvar1.so | grep _ZN3var4liveE 16: 0000000000000000 4 TLS GLOBAL DEFAULT 16 _ZN3var4liveE $ readelf --dyn-syms -W libvar2.so | grep _ZN3var4liveE 16: 0000000000000000 4 TLS GLOBAL DEFAULT 16 _ZN3var4liveE On x86: $ ./var exe: live += 5 exe: live = 5 Calling libentry in ./libvar1.so... lib: live += 3 lib: live = 3 Calling libentry in ./libvar2.so... lib: live += 3 lib: live = 3 $ readelf --dyn-syms -W var | grep _ZN3var4liveE $ readelf --dyn-syms -W libvar1.so | grep _ZN3var4liveE 13: 0000000000000000 4 TLS GLOBAL DEFAULT 16 _ZN3var4liveE $ readelf --dyn-syms -W libvar2.so | grep _ZN3var4liveE 13: 0000000000000000 4 TLS GLOBAL DEFAULT 16 _ZN3var4liveE ============var.h:================ #include <pthread.h> class var{ public: var(){}; static void output(const char* prefix) { printf("%s: live = %d\n", prefix, live); }; static void inc(const char* prefix, int i) { printf("%s: live += %d\n", prefix, i); live += i; }; private: static __thread int live; }; ============var_l.cc:=============== #include <pthread.h> #include <stdio.h> #include "var.h" __thread int var::live=0; extern "C" void libentry() { var libvar; libvar.inc("lib", 3); libvar.output("lib"); } ============var_exe.cc:================= #include <dlfcn.h> #include <pthread.h> #include <stdio.h> #include "var.h" __thread int var::live=0; void* load_lib_and_call(const char* libname) { void* handle = dlopen(libname, RTLD_LOCAL | RTLD_NOW); if (handle == NULL) { printf("Can not open shared library %s\n", libname); return 0; } typedef void (*lib_fun_t)(); lib_fun_t lib_entry_ = (lib_fun_t)(dlsym(handle, "libentry")); const char *dlsym_error = dlerror(); if (dlsym_error) { printf("Can not load symbol libentry: %s\n", dlsym_error); dlclose(handle); return 0; } printf("Calling libentry in %s...\n", libname); lib_entry_(); return handle; } int main() { var mainvar; mainvar.inc("exe", 5); mainvar.output("exe"); void* handle1 = load_lib_and_call("./libvar1.so"); void* handle2 = load_lib_and_call("./libvar2.so"); if (handle1) dlclose(handle1); if (handle2) dlclose(handle2); return 0; } -- You are receiving this mail because: You are on the CC list for the bug. _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils