PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Preloading ohne dlfcn.h/dlopen()



Deever
25-04-2005, 20:03
Hey Amigos, wie geht's?

Ich hörte schon vor längerem über die Umgebungsvariable LD_PRELOAD und kann auch nachvollziehen, was dabei passiert. In konkreten Umsetzungen davon, die mir begegnet sind, werden die originalen, gewrappten Funktionen aber immer über dlopen() einem Funktionszeiger zugeordnet. Deshalb meine Frage: ließe sich das nicht auch gänzlich ohne dlopen() realisieren, und wenn ja, wie? Mindestens unter ELF nämlich handelt es sich bei
extern int foo(void);
int foo(void);um zwei verschiedene Funktionen.

Vielen Dank für eure Antworten!
Gruß,
/dev

Joghurt
28-04-2005, 10:47
Äh, wie meinen?

$ cat sqrt.c
double sqrt(double t)
{
return 42.;
}
$ cat a.c
#include <math.h>
#include <stdio.h>

main()
{
printf("Die Wurzel aus 2 ist %f\n", sqrt(2));
return;
}
$ gcc -shared -o libsqrt.so sqrt.c
$ gcc -lm a.c -o a
$ LD_PRELOAD=./libsqrt.so a
Die Wurzel aus 2 ist 42.000000

Deever
28-04-2005, 20:00
Nicht ganz! ;)
Ich meine den Fall, bei dem du eine vorhandene Funktion wrappst, also eine Funktion gleichen Namens in einer Preload-Library, die die echte aber aufruft. Ist man hier zu dlopen() gezwungen?

Gruß,
/dev

locus vivendi
29-04-2005, 08:20
Mindestens unter ELF nämlich handelt es sich bei
Code:
extern int foo(void);
int foo(void);
um zwei verschiedene Funktionen.
Das verstehe ich nicht / sehe ich anders. Sowohl C und C++ sagen doch, dass beide Deklarationen die gleiche Funktion benennen. Und ein kurzer Test bei mir zeigt, dass in beiden Fällen auch das gleiche Symbol in einer ELF-Objektdatei erzeugt wird. Wie zeigt es sich denn bei dir, dass es sich nicht um die gleichen Funktionen handelt?

Ist man hier zu dlopen() gezwungen?
Ich kann leider nur vermuten: Ja (Mal davon abgesehen das man sich prinzipiell auch einen eigenen Loader schreiben könnte...). Welches Problem verursacht dlopen() denn?

Deever
29-04-2005, 09:15
Das verstehe ich nicht / sehe ich anders. Sowohl C und C++ sagen doch, dass beide Deklarationen die gleiche Funktion benennen.Ja, das hängt aber damit zusammen, daß sie als "höhere Sprachen" Funktionen über Namen und nicht über Adressen identifiziern.


Und ein kurzer Test bei mir zeigt, dass in beiden Fällen auch das gleiche Symbol in einer ELF-Objektdatei erzeugt wird.Wenn du die extern-Funktion in deiner Testdatei auch gleich implementierst, dann ja. Sonst, und das ist ja genau der Sinn von extern, ist das Symbol einfach 'U' wie unresolved.


Welches Problem verursacht dlopen() denn?Ich brauche die libdl, die ich für sowas Grundlegendes wie Preloading eigentlich nicht extra einbinden will. Aber ich seh schon, ich werd nicht drumrumkommen. :(

Gruß,
/dev

locus vivendi
29-04-2005, 13:41
Und ein kurzer Test bei mir zeigt, dass in beiden Fällen auch das gleiche Symbol in einer ELF-Objektdatei erzeugt wird.
Wenn du die extern-Funktion in deiner Testdatei auch gleich implementierst, dann ja. Sonst, und das ist ja genau der Sinn von extern, ist das Symbol einfach 'U' wie unresolved.
Also bei mir sieht es so aus, das immer das gleiche ELF-Symbol dabei herauskommt. So wie ich es aufgrund der Sprache auch erwarten würde. Also, alles innherhalb von Anführungszeichen soll eine komplette Übersetzungseinheit sein:
"extern int foo(); [newline]" - "int foo(); [newline]"
..
"extern int foo(); void g() { foo(); } [newline] " -
"int foo(); void g() { foo(); } [newline]
..
"extern int foo() { } [newline]" - "int foo() { } [newline]"
..
"extern int foo() { } void g() { foo(); } [newline] -
"int foo() { } void g() { foo(); } [newline]

(Damit müssten eigentlich alle relevanten Fälle abgedeckt sein.)

Dann erzeugt jeweils ein "..."-"..." Paar die gleichen ELF-Symbole. Genaugenommen ist dann jeweils die gesamte Objektdatei gleich. Ob das extern dasteht, oder nicht, ist also egal, man kann weder programmatisch, noch durch Analyse des Objektcodes herausfinden ob es angegeben wurde oder nicht. Deshalb wundere ich mich stark, wie du zu deiner Aussage kommst.

Joghurt
29-04-2005, 14:25
Also malloc kannst du wrappen, in dem du in deiner malloc-Funktion __libc_malloc aufrufst. Ob das jetzt global für alle libc funktionen geht, wage ich zu bezweifeln.

Was genau willst du denn machen? Ich nehme mal an, ld's --wrap option hilft dir nicht weiter (da du dafür das Programm neu linken musst)