[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Bug ld/16937] New: aarch64: issue about executable exporting TLS class
From: |
jingyuuiuc at gmail dot com |
Subject: |
[Bug ld/16937] New: aarch64: issue about executable exporting TLS class static member variable |
Date: |
Mon, 12 May 2014 18:10:12 +0000 |
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 ld/16937] New: aarch64: issue about executable exporting TLS class static member variable,
jingyuuiuc at gmail dot com <=