2014-04-10 19 views
5

Gibt es eine Möglichkeit, das TLS-Modell einer gemeinsam genutzten Bibliothek unter Linux abzufragen? (zB mit ldd oder einem anderen Tool).Gibt es eine Möglichkeit, das lokale Thread-Speichermodell zu bestimmen, das von einer Bibliothek unter Linux verwendet wird

Ich habe Probleme mit dem Laden von zu vielen Bibliotheken mit dem "initial-exec" -Modell und möchte sicher feststellen, welche der Third-Party-Bibliotheken dieses Modell verwenden (damit ich einige Slots freigeben kann, zB durch statisches Binden)).

Dies führt zu einem Fehler:

dlopen: cannot load any more object with static TLS 

siehe this question.

Antwort

7

ich in diesen Fehler selbst lief, und während es zu untersuchen, kam ich auf einem 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.

bei /usr/include/elf.h suchen, haben wir:

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

Sie müssen also, wenn DF_STATIC_TLS testen wird im Eintrag DT_FLAGS der gemeinsam genutzten Bibliothek festgelegt.

Dinge zu testen, habe ich ein einfaches Stück Code Thread-Lokalspeicher mit:

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

ich es dann mit den beiden anderen Thread lokalen Speichermodellen zweimal zusammengestellt:

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 

Und sicher genug ist, kann ich einen Unterschied zwischen den beiden Bibliotheken sehen readelf mit:

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

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

Die tls-global-dynamic.so-Version hatte keinen DT_FLAGS-Eintrag, vermutlich weil keine Flags gesetzt waren. Es sollte also ziemlich einfach sein, ein Skript zu erstellen, das readelf und grep verwendet, um betroffene Bibliotheken zu finden.

+1

Vielen Dank! Gute Antwort. Ich fand auch 'readelf -l library | grep TLS' nützlich. Dies zeigt an, ob überhaupt ein Thread-Loca-Speicher vorhanden ist. Es stellt sich heraus, dass alles mit TLS auch einen DTV-Steckplatz verwendet (und somit spätere STATIC_TLS-Objekte vom Laden blockieren kann), aber wenn Sie zuerst die STATIC_TLS-Objekte laden, verwenden die Nicht-Anfangs-Exec-Methoden eine andere Methode und nehmen keinen Slot. – robince