Anzeige:
Ergebnis 1 bis 7 von 7

Thema: Preloading ohne dlfcn.h/dlopen()

  1. #1
    Registrierter Benutzer
    Registriert seit
    29.02.2004
    Beiträge
    113

    Preloading ohne dlfcn.h/dlopen()

    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
    Code:
    extern int foo(void);
    int foo(void);
    um zwei verschiedene Funktionen.

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

  2. #2
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Äh, wie meinen?
    Code:
    $ 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

  3. #3
    Registrierter Benutzer
    Registriert seit
    29.02.2004
    Beiträge
    113
    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

  4. #4
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    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?

  5. #5
    Registrierter Benutzer
    Registriert seit
    29.02.2004
    Beiträge
    113
    Zitat Zitat von locus vivendi
    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

  6. #6
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    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.

  7. #7
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    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)

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •