2014-04-10 15 views
5

C'è un modo per interrogare il modello TLS di una libreria condivisa su Linux? (es. usando ldd o qualche altro strumento).C'è un modo per determinare il modello di archiviazione locale del thread usato da una libreria su Linux

Sto riscontrando un problema con il caricamento di troppe librerie con il modello "initial-exec" e vorrei determinare con certezza quale delle librerie di terze parti utilizza questo modello (quindi posso liberare alcune slot, ad es. Collegando staticamente).

Ciò si traduce in un errore:

dlopen: cannot load any more object with static TLS 

vedere this question.

risposta

7

mi sono imbattuto in questo errore io stesso, e mentre indaga, mi è venuto su un mailing list post with this info:

If you link a shared object containing IE-model access relocs, the object will have the DF_STATIC_TLS flag set. By the spec, this means that dlopen might refuse to load it.

Guardando /usr/include/elf.h, abbiamo:

/* Values of `d_un.d_val' in the DT_FLAGS entry. */ 
... 
#define DF_STATIC_TLS 0x00000010  /* Module uses the static TLS model */ 

Quindi è necessario verificare se DF_STATIC_TLS è impostato nella voce DT_FLAGS della libreria condivisa.

Per provare le cose, ho creato un semplice pezzo di codice utilizzando filo di archiviazione locale:

static __thread int foo; 
void set_foo(int new) { 
    foo = new; 
} 

ho poi compilato due volte con i due diversi modelli di archiviazione locale di thread:

gcc -ftls-model=initial-exec -fPIC -c tls.c -o tls-initial-exec.o 
gcc -shared tls-initial-exec.o -o tls-initial-exec.so 

gcc -ftls-model=global-dynamic -fPIC -c tls.c -o tls-global-dynamic.o 
gcc -shared tls-global-dynamic.o -o tls-global-dynamic.so 

E sicuro abbastanza, posso vedere una differenza tra le due librerie usando readelf:

$ readelf --dynamic tls-initial-exec.so 

Dynamic section at offset 0xe00 contains 25 entries: 
    Tag  Type       Name/Value 
... 
0x000000000000001e (FLAGS)    STATIC_TLS 

La versione tls-global-dynamic.so non disponeva di una voce DT_FLAGS, presumibilmente perché non disponeva di alcun flag impostato. Quindi dovrebbe essere abbastanza facile creare uno script usando readelf e grep per trovare le librerie interessate.

+1

Grazie mille! Bella risposta. Ho anche trovato 'readelf -l library | grep TLS' utile. Questo indica se c'è spazio per lo stoccaggio di qualsiasi thread. Si scopre che qualsiasi cosa con TLS utilizza anche uno slot DTV (e quindi può bloccare successivamente oggetti STATIC_TLS dal caricamento), ma se si caricano prima gli oggetti STATIC_TLS, quelli non-intial-exec usano un altro metodo e non prendono uno slot. – robince

Problemi correlati