#include #include #include #include #include #include extern int TLS_SIZE; extern unsigned long tls_position(void); extern int __real_pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); extern int arch_prctl(int code, unsigned long addr); // This data structure is used to pass the function+args that the user // called during the thread creation. typedef struct _target { void *(*the_start_routine)(void*); void * the_arg; } target; void* tls_setup(void*); // wrapper for pthread_create() int __wrap_pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg){ target *trg; int ret; trg = (target*)malloc(sizeof(target)); trg->the_start_routine = start_routine; trg->the_arg = arg; // real pthread_create call ret = __real_pthread_create(thread, attr, tls_setup, (void*)trg); return ret; } void * tls_setup(void * args){ unsigned long addr; void *(*the_start_routine)(void*); void * the_arg; // Creation of TLS zone addr = (unsigned long)mmap(NULL, TLS_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, 0,0); // set addr of TLS inside the TLS zone *(unsigned long*)addr = addr; // Set base of segment GS to newly created TLS zone arch_prctl(ARCH_SET_GS,addr); // execute init function for thread the_start_routine = ((target*)args)->the_start_routine; the_arg = ((target*)args)->the_arg; return the_start_routine(the_arg); }