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!
warum es nicht durch einen Debugger ausführen und sich durch den Code Schritt? –
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
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'. –