Comment 0 for bug 1818726

Revision history for this message
Adrian (adrian-jhhgrd) wrote : Segfault when using TLS __thread variable in a shared object in global-dynamic mode

When working on an aarch64 a53 soc, I had trouble compiling libssh, which worked fine on 32-bit arm. The library would segfault as soon as it tired to set a __thread variable. I created a sample application to reproduce the issue below.
Sample program:

threadtest.c:

#include <stdlib.h>
#include <pthread.h>

__thread int TLS_data;

void *theThread(void *parm)
{
 printf("About to set TLS_data...\n");
 TLS_data = 1; # segfault
 printf("TLS_data = %d\n", TLS_data);
 return NULL;
}

void threadtest(void)
{
 pthread_t thread;
 pthread_create(&thread, NULL, theThread, NULL);
 pthread_join(thread, NULL);
}

threadtest.h:

#ifndef threadtest_h__
#define threadtest_h__

extern void threadtest(void);

#endif // threadtest_h__

main.c:

#include <stdio.h>
#include "threadtest.h"

int main(void)
{
    puts("This is a test...");
    threadtest();
    return 0;
}

Makefile:

CPGCC:=path to your aarch64 gcc
MODEL=global-dynamic
#MODEL=initial-exec # this works

all:
 $(CPGCC) -c -Wall -Werror -lpthread -fPIC -ftls-model=$(MODEL) threadtest.c
 $(CPGCC) -shared -o libthreadtest-$(MODEL).so threadtest.o
 $(CPGCC) -L/var/mnt/m2/threadtest -Wall -o test-$(MODEL) main.c -lthreadtest-$(MODEL)

clean:
 rm -f *.o *.so test*

.PHONY: all clean

When setting tls-model to global-dynamic or local-dynamic, program segfaults. When setting it to initial-exec or local-exec, program completes.

This problem does *not* occur when there is not shared library and everything is contained in the same program.

Also attaching resulting assembly for the global-dynamic (left) output vs initial-exec (right) output.

I built my toolchain using crosstool-ng, using uClibc 1.0.22 and linaro gcc linaro-6.4-2018.05.