Suchpfade von dlopen()



  • Hi,

    ich habe das problem, dass eine shared object datei, die ich mittels dlopen() lade, von anderen libraries abhängt, die dann von dlopen nicht gefunden werden. Laut man page von dlopen sucht dlopen in den Verzeichnissen die in LD_LIBRARY_PATH stehen, aber so wie ich das hier sehen kann, scheint das nicht zu stimmen:

    mexPrintf("Opening %s, LD_LIBRARY_PATH is now \"%s\"...\n", filename, getenv("LD_LIBRARY_PATH"));
    	if ( (handle = dlopen(filename, RTLD_LAZY)) == NULL)
    	{
    		/* return [-1, -1] in case of error */
    		mexPrintf("Could not open shared object file: %s\n", dlerror());
    		packResults(-1, -1, plhs);
    		return;
    	}
    

    Das ganze ist eine C-Datei die über MEX als Erweiterung in Matlab eingebunden wird, daher das mexPrintf. Jedenfalls erhalte ich folgende Fehlermeldung:

    Opening /pfad/zu/so/file/soFile.so, LD_LIBRARY_PATH is now "/lalala/ein/paar/pfade"...
    Could not open shared object file: libremote.so: cannot open shared object file: No such file or directory

    Die Datei libremote.so befindet sich aber definitiv in einem der Verzeichnisse im LD_LIBRARY_PATH.

    Hat jemand eine Idee was hier das Problem sein könnte?



  • man dlopen schrieb:

    void *dlopen(const char *filename, int flag);
    [...]
    If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname. Otherwise, the dynamic linker searches for the ibrary as follows (see ld.so(8) for further details):

    o (ELF only) If the executable file for the calling program contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag, then the
    directories listed in the DT_RPATH tag are searched.

    o If, at the time that the program was started, the environment variable LD_LIBRARY_PATH was defined to contain a colon-separated
    list of directories, then these are searched. (As a security measure this variable is ignored for set-user-ID and set-group-ID
    programs.)

    o (ELF only) If the executable file for the calling program contains a DT_RUNPATH tag, then the directories listed in that tag are
    searched.

    o The cache file /etc/ld.so.cache (maintained by ldconfig(8)) is checked to see whether it contains an entry for filename.

    o The directories /lib and /usr/lib are searched (in that order).

    Poste doch die echte Ausgabe von deinem Code. "Opening /pfad/zu/so/file/soFile.so," scheint mir nicht echt.



  • Du kannst mit dem Programm strace gucken, welche Dateien versucht werden zu öffnen. Ansonsten überprüfe mal auf Tippfehler.



  • Hi,

    erstmal danke für die Antworten. Ich habe bereits mit export LD_DEBUG=files geschaut, aber da steht auch nur dass henon.so (die datei die ich laden will) die library libremote.so braucht, die dann nicht gefunden wird. die anderen optionen, wie LD_DEBUG=libs usw. funktionieren nicht, weil der code von matlab aus ausgeführt wird und matlab mit diesen optionen gar nicht erst startet.

    Ich habe die tatsächlichen Pfade aus Platzgründen weggelassen, aber wenn ihr sie sehen wollt:

    Opening /ag/agstuddellnitz/bderenor/pareto/svn/OptGaio/gaio/models/henon.so, LD_LIBRARY_PATH is now "/opt/matlab/matlab7.8/sys/os/glnx86:
    /opt/matlab/matlab7.8/bin/glnx86:/opt/matlab/matlab7.8/extern/lib/glnx86:
    /opt/matlab/matlab7.8/sys/java/jre/glnx86/jre/lib/i386/native_threads:
    /opt/matlab/matlab7.8/sys/java/jre/glnx86/jre/lib/i386/client:
    /opt/matlab/matlab7.8/sys/java/jre/glnx86/jre/lib/i386:
    /opt/matlab/matlab7.0sp2/bin/glnx86/:
    /ag/agstuddellnitz/bderenor/pareto/svn/OptGaio/gaio/lib:
    /ag/agstuddellnitz/bderenor/pareto/svn/OptGaio/gaio/models:
    /ag/agstuddellnitz/bderenor/pareto/svn/OptGaio/gaio/../schuetze/models:
    /ag/agstuddellnitz/bderenor/pareto/svn/OptGaio/gaio/externalLib/protobuf/lib:
    /ag/agstuddellnitz/bderenor/pareto/svn/OptGaio/gaio/externalLib/protobuf-c/lib"...
    Could not open shared object file: libremote.so: cannot open shared object file: No such file or directory

    Und hier das ls von dem im LD_LIBRARY_PATH oben offensichtlich enthaltenen Pfad:

    $ ls /ag/agstuddellnitz/bderenor/pareto/svn/OptGaio/gaio/lib
    libParetoMatrix.so libarpack.a libblas.a libgaio.a liblapack.a liblpk.a libremote.a libremote.so stNRg6Cl stazBJqc stgFitdy

    strace liefert an dieser Stelle gar keine Ausgabe (also matlab mit "strace matlab" gestartet und dann innerhalb matlab das prog ausgeführt).



  • Hi,

    ich habe jetzt mal alles was mit matlab zu tun hat aus dem code entfernt und ein testprogramm erzeugt das nichts anderes tut als zu versuchen henon.so zu laden. strace liefert hier diese (auf libremote.so bezogenen) Ausgaben:

    open("/lib/tls/i686/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/tls/i686/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/tls/i686/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/tls/i686/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/tls/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/tls/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/tls/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/tls/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i686/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i686/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i686/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i686/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/tls/i686/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/tls/i686/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/tls/i686/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/tls/i686/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/tls/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/tls/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/tls/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/tls/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i686/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i686/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i686/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i686/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/tls/i686/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/tls/i686/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/tls/i686/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/tls/i686/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/tls/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/tls/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/tls/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/tls/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/i686/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/i686/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/i686/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/i686/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/lib/i486-linux-gnu/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/tls/i686/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/tls/i686/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/tls/i686/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/tls/i686/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/tls/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/tls/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/tls/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/tls/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/i686/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/i686/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/i686/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/i686/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/sse2/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/sse2/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/cmov/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    open("/usr/lib/i486-linux-gnu/libremote.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    Could not open shared object file: libremote.so: cannot open shared object file: No such file or directory

    Soweit ich das sehen kann wird also tatsächlich nicht im Inhalt von LD_LIBRARY_PATH gesucht.



  • Also entweder du fügst alle Verzeichnisse für die libs zu der LD_LIBRARY_PATH hinzu (hast du das beim letzten mal auch gemacht?) oder du gibst einfach den vollständigen Pfad bei dlopen an. (bruahct die libremote noch andere "eigene" libs?) Veränderst du LD_LIBRARY_PATH im Program?



  • Hi,

    alle Verzeichnisse für die libs sind im LD_LIBRARY_PATH und wie man bei strace sehen kann wird keins der verzeichnisse die im LD_LIBRARY_PATH stehen tatsächlich untersucht. dlopen wird bereits mit dem vollständigen Pfad aufgerufen "/ag/agstuddellnitz/bderenor/pareto/svn/OptGaio/gaio/models/henon.so", die libremote ist bereits eine dependency.



  • Irgendwie kann ich das nicht recht nachvollziehen.
    Ich hab mal einen kleinen test erstellt. Was passiert da bei dir?

    #!/bin/sh
    
    touch lib.c
    
    gcc -shared -Wl,-soname,liba.so -o liba.so lib.c
    gcc -shared -Wl,-soname,libb.so -o libb.so lib.c -L. -la
    
    cat << EOF > testdlopen.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <dlfcn.h>
    
    int main(int argc, char *argv[])
    {
            void *handle;
    
            printf("LD_LIBRARY_PATH=%s\n", getenv("LD_LIBRARY_PATH"));
    
            if (!(handle = dlopen("./libb.so", RTLD_LAZY))) {
                    printf("dlopen: %s\n", dlerror());
                    return 2;
            }
    
            printf("lib loaded\n");
    
            dlclose(handle);
    
            return 0;
    }
    EOF
    
    gcc -o testdlopen -Wall -ldl testdlopen.c
    
    ./testdlopen
    LD_LIBRARY_PATH="." ./testdlopen
    

    Es wird eine leere liba erstellt und eine libb, die liba braucht. Dann ein Programm das versucht libb zu laden, einmal mit und einmal ohne "." in LD_LIBRARY_PATH.



  • Hi,

    danke lagalopex, das hat schonmal geholfen. Also, wenn ich die richtigen Pfade in der Shell setze bevor ich das prog starte, dann klappt alles wie es soll. wenn ich die pfade allerdings mittels setenv innerhalb des Programms setze, dann nicht. Mache ich hier etwas falsch? Ich setze die Pfade mittels

    char* env = constructEnvironment();
    setenv("LD_LIBRARY_PATH", env, 1);
    

    wobei innerhalb von constructEnvironment der string zusammengeklebt wird. der ist auch so erstmal richtig und bleibt auch noch bestehen wenn das Program beendet wurde. Kann es sein dass innerhalb des Progs gesetzte Umgebungsvariablen das Programm selbst nicht beeinflussen weil es noch mit den alten Umgebungsvariablen gestartet wurde?



  • man: dlopen(3):
    If, at the time that the program was started, the environment variable LD_LIBRARY_PATH was defined to contain a colon-separated list of directories, then these are searched. (As a security measure this variable is ignored for set-user-ID and set-group-ID programs.)

    Also muss LD_LIBRARY_PATH bereits beim Programmstart gesetzt sein.

    Denn die Umgebung wird am Anfang ausgewertet und kann über einen dritten Parameter von main oder der globalen Variablen man: environ(7) ausgewertet werden, welche von setenv nichtmehr verändert werden.
    Ich weiß allerdings nicht, wie dlopen das macht.



  • Hm,

    okay, was würde man also tun wenn man mit dlopen verzeichnisse durchsuchen will, die zum Programmstart noch nicht feststehen? Gibt es eine Möglichkeit dlopen direkt Pfadangaben für die sekundär geladenen Libraries mitzugeben? Kann man z.B. diese DT_RPATH und DT_RUNPATH attribute zur Laufzeit setzen?



  • Du könntest LD_LIBRARY_PATH in deiner Umgebung speichern (entweder vom Benutzer oder gar ganz global). Du könntest auch die Verzeichnisse offiziell eintragen in der /etc/ld.so.conf.

    Oder du startest dein Programm halt immer mit dem passenden LD_LIBRARY_PATH davor.


Anmelden zum Antworten