Wenn Sie erklären test1()
versteckt (__attribute__((__visibility__("hidden")))
, wird der Sprung direkt.
Jetzt test1()
möglicherweise nicht in der Quelle-Übersetzungseinheit definiert wird als verstecktes, aber ich glaube, kein Schaden aus dieser Diskrepanz mit Ausnahme der C-Sprache kommen soll Stellen Sie sicher, dass &test1 == &test1
zur Laufzeit für Sie unterbrochen wird, wenn einer der Zeiger über einen verborgenen Verweis und einer über einen öffentlichen Verweis abgerufen wurde (der öffentliche Verweis wurde möglicherweise über Preloading oder ein DSO vor dem aktuellen im Lookup-Bereich eingefügt) , während die versteckte Referenz (die zu direkten Sprüngen führt) wirksam jede Art von Interposition verhindert)
Ein geeigneterer Weg, um damit umzugehen, wäre, zwei Namen für test1()
-einen öffentlichen Namen und einen privaten/versteckten Namen zu definieren.
In gcc und clang kann dies mit etwas Alias-Magie geschehen, was nur in der Übersetzungseinheit möglich ist, die das Symbol definiert.
Makros können es schönere machen:
#define PRIVATE __attribute__((__visibility__("hidden")))
#define PUBLIC __attribute__((__visibility__("default")))
#define PRIVATE_ALIAS(Alias,OfWhat) \
extern __typeof(OfWhat) Alias __attribute((__alias__(#OfWhat), \
__visibility__("hidden")))
#if HERE
PUBLIC void test1(void) { }
PRIVATE_ALIAS(test1__,test1);
#else
PUBLIC void test1(void);
PRIVATE void test1__(void);
#endif
void call_test1(void) { test1(); }
void call_test1__(void) { test1__(); }
void call_ext0(void) { void ext0(void); ext0(); }
void call_ext1(void) { PRIVATE void ext1(void); ext1(); }
Die oben compiliert (O3, x86-64) in:
call_test1:
jmp [email protected]
call_test1__:
jmp test1__
call_ext0:
jmp [email protected]
call_ext1:
jmp ext1
(Definition 1 HIER = inlines zusätzlich den test1 Aufruf da es klein ist und lokal und -O3 ist eingeschaltet).
Live-Beispiel unter https://godbolt.org/g/eZvmp7.
-fno-semantic-interposition
wird den Job auch tun, aber es bricht auch die C-Sprache Garantie, und es ist eine Art von einem großen Hammer, der nicht die Granularität von Aliasing hat.
Meinst du für Anrufe innerhalb Ihrer Bibliothek/ausführbare Datei? Das sollte irgendwie möglich sein, vielleicht durch die Definition eines privaten Alias oder etwas. Aber für Aufrufe von Funktionen in Bibliotheken, mit denen Sie nur dynamisch verknüpfen, bin ich nicht sicher, ob der Laufzeit-Linker * solche Referenzen auflösen kann. –
@PeterCordes Ohne '-fpic' schreibt der Linker Referenzen auf Symbole automatisch an PLT-Referenzen, wo dies erforderlich ist. Das ist das Verhalten, das ich möchte, d. H. Der Compiler erzeugt normale Aufrufe an alle Funktionen, und der Linker schreibt die Aufrufe neu, die zu einem anderen gemeinsamen Objekt gehen. – fuz
Führt ['-fno-semantic-interposition'] (http://stackoverflow.com/questions/35745543/new-option-in-gcc-5-3-fno-semantic-interposition) das aus, was Sie wollen? Siehe auch http://stackoverflow.com/questions/34102989/shared-object-in-linux-without-symbol-interposition-fno-semantic-interposition. Ist diese Frage ein Duplikat von beiden? –