Dear Matthew,
Thanks for your answer,
We able to reproduce and identify our problem. It was related to build environment. We build executable with -fPIC option.
Dear Mr Lee,
Below relocations are generated when thread local storage is used in application.
#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ #define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ #define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */
i.e when we want each thread to have its own copy of global data instead of sharing process globals.
Shown below are two global declaration for variable i;
int i; >>>>> Global defination, hence all thread for &i will return same address.
__thread int i; >>>>> Per Thread defination, hence each thread for &i will return different address.
We already know the difference between the executable and shared libraries.
=> executable are always loaded at fixed address, since the global lookup scope for any symbol starts with executable they do not require GOT.
=> shared libraries are position independent, hence all global symbols are accessed via GOT, also if symbols is defined in both executable and shared library, then executable global defination is used as it comes first in global lookup scope.
Similar is the case with symbol that are defined to be thread local.
=> ELF with GOT
#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ #define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */
=> ELF without GOT
#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */
I have made a simple test case (main.c & lib.c)
main.c
#include <pthread.h> #include <errno.h> #include <stdio.h> #include <stdlib.h>
#define MAX_THREAD 2
extern __thread int per_thread_var; extern void *thread(void *arg);
int main(void) { unsigned int i; pthread_t t_id; printf("%u\n", &per_thread_var);
for (i=0 ; i < MAX_THREAD ; ++i) { pthread_create(&t_id, NULL, &thread, (void *)i); } sleep(1); return 0; }
lib.c
#include <pthread.h> #include <errno.h> #include <stdio.h> #include <stdlib.h>
__thread int per_thread_var;
void *thread(void *arg) { printf("%u\n", &per_thread_var); }
$arm-linux-gnueabi-gcc -g -shared -fPIC -o lib1.so lib.c
$ arm-linux-gnueabi-gcc -g -o a-pic.out main.c -L. -l1 -lpthread -fPIC
$ arm-linux-gnueabi-readelf -h a-pic.out | grep Type Type: EXEC (Executable file)
$ arm-linux-gnueabi-readelf -r a-pic.out | grep per_thread_var 00010990 00000911 R_ARM_TLS_DTPMOD3 00000000 per_thread_var 00010994 00000912 R_ARM_TLS_DTPOFF3 00000000 per_thread_var
when compile executable without -fPIC option this disappear.
Thanks
On Wed, Jan 2, 2013 at 5:24 PM, Matthew Gretton-Dann matthew.gretton-dann@linaro.org wrote:
As I said above, I don't have enough information to answer this with confidence. But my guess is that yes - you are going to have to handle this (and the related relocations) in the prelink utilities.