2016-03-20 8 views
0

verwende Es ist ein einfaches Beispiel, mein Problem zu beschreiben:ich eine Standard-C-Bibliothek-Funktion in einer dynamischen Bibliothek neu zu definieren, aber ich kann es nicht

Ich habe 3 Dateien, Haupt, level1.so und level2.so. (Mein OS ist solaris11.3, gcc Version 3.4.3)

In Haupt, ruft execute() von level1.so. Und die execute() ruft run() von level2.so. Und die run() ruft fcloseall() auf, die in level2.so neu definiert wird.

fcloseall() ist neu definiert, um nichts zu tun (es schließt alle geöffneten fds gehören ursprünglich stdout, stdin und stderr ursprünglich).

Jetzt möchte ich etwas um execute() in Haupt drucken, aber nur die Nachricht vor execute() wird gedruckt.

Die Codes sind unten dargestellt:

Die level2.so von level2.c und level2depend.c kompiliert wird.

level2.c:

#include <stdio.h> 
int run() 
{ 
    fcloseall(); 
    return 0; 
} 

level2depend.c:

#include <stdio.h> 
int fcloseall() //redefine the std c function fcloseall 
{ 
    printf("in redefined fcloseall\n"); 
    return 0; 
} 

Die level1.so zusammengestellt von level1.c.

level1.c

#include <dlfcn.h> 
int execute() 
{ 

     int (*sofunc)(void); 
     void * lib_handle = NULL; 
     char *errorInfo;  
     lib_handle = dlopen("./liblevel2.so",RTLD_LAZY); 
     if(!lib_handle) 
     { 
      return 0; 
     } 
     sofunc = (int(*)(void))dlsym(lib_handle,"run"); 
     errorInfo = dlerror(); 
     if (errorInfo != NULL){ 
      dlclose(lib_handle); 
      return 0; 
     } 
     int ret = sofunc(); 
     dlclose(lib_handle); 
     return 0; 
} 

The Haupt aus main.c zusammengestellt.

main.c

#include <dlfcn.h> 
#include <stdio.h> 
int main() 
{ 

     int (*sofunc)(void); 
     void * lib_handle = NULL; 
     char *errorInfo;  
     lib_handle = dlopen("./liblevel1.so",RTLD_LAZY); 
     if(!lib_handle) 
     { 
      return 0; 
     } 
     sofunc = (int(*)(void))dlsym(lib_handle,"execute"); 
     errorInfo = dlerror(); 
     if (errorInfo != NULL){ 
      dlclose(lib_handle); 
      return 0; 
     } 
     printf("before\n"); 
     int ret = sofunc(); 
     printf("after\n"); 
     dlclose(lib_handle); 
     return 0; 
} 

Die Make-Datei ist:

all: 
    gcc level2depend.c -o level2depend.o -c -g -fPIC 
    gcc level2.c -o level2.o -c -g -fPIC 
    gcc -shared -g level2.o level2depend.o -o liblevel2.so -fPIC 
    gcc level1.c -o level1.o -c -g -fPIC 
    gcc level1.o -o liblevel1.so -shared -fPIC 
    gcc main.c -o main -g -ldl 
clean: 
    rm level2depend.o level1.o liblevel1.so level2.o liblevel2.so main 

ich ausführen Haupt und das Ergebnis ist:

[email protected]#./main 
before 

Wenn ich das Make-Datei als gcc main.c -o main -g -ldl -llevel2 ändern, das Ergebnis ist:

[email protected]#./main 
before 
in redefined fcloseall 
after 

Und das ist was ich will.

Ich möchte wissen, warum dies geschieht. Vielen Dank!

+0

warum es nicht durch einen Debugger ausführen und sich durch den Code Schritt? –

+0

Der Level2-Code enthält: '#include ' wo 'fcloseall()' prototyped ist. Jede Ihrer Unterdateien benötigt eine Header-Datei. Wenn Sie main.c verknüpfen, müssen die von Ihnen definierten Bibliotheken referenziert werden, damit sie zuerst betrachtet werden. Hinweis: Es ist immer eine schlechte Idee, Funktionen mit dem gleichen Namen wie die Systemfunktionen zu schreiben. – user3629249

+0

Dank @Mike, ich habe bereits debugged, extrahierte ich dieses Beispiel aus einem recht komplexen Projekt. Und danke @ user3629249, Ihre Antwort gibt mir eine Inspiration. Dieses Problem ist wie ein "Global Symbol Interpose": Wenn ein Symbol in der globalen Symboltabelle hinzugefügt werden muss, wird es ignoriert, wenn ein Symbol vorhanden ist. Ich benutze 'ldd', um ** main ** reference' libc.so.1' zu finden. Außerdem ist 'fcloseall' in' libc.so.1' definiert. Wenn ich also '-level2' nicht verwende, findet ** main ** den' fcloseall' von 'lib.so.1'. –

Antwort

0

Sie können die von ld bereitgestellte Wrap-Funktion verwenden.

gcc -Wl,-wrap,fcloseall .... 

und im Quellcode,

int __wrap_fcloseall(void) 
{...} 
+0

Dank @lyyyuna, kann Ihre Methode mein Problem lösen. Ich füge '-Wl, -wrap, fcloseall' hinzu, um ** liblevel2.so ** zu erstellen und nicht' -level2' hinzuzufügen, um ** main ** zu erstellen, es funktioniert so wie ich es will! Aber in meiner Build-Maschine (sol10) kann 'ld'' 'wrap' 'nicht erkennen ... –

Verwandte Themen