a serious dlopen problem

A serious dlopen() problem found in qrtp. At least, it is serious for me
because it is a show stopper for my product.

dlopen() can’t distinguish 2 shared libraries with the same file name
by located in different directory.

dll1.c is the source for the first shared library.
dll2.c is the source for the 2nd shared library.
main.c is the calling program that demostrates the shared libraries
created from dll1.c and dll2.c does work if they have different file
name.
main2.c is the calling program that demostrates the problem.

$ cat dll1.c
char *s = “this is dll1”;
$ cat dll2.c
char *s = “this is dll2”;
char *t = “this is dll2”;
$ cat main.c
#include <stdio.h>
#include <dlfcn.h>

int main ()
{
void* p;
void* pp;
char** str;

p = dlopen ("./dll1.so", RTLD_NOW | RTLD_LOCAL);
if (p == 0) { printf (“failed to open dll1\n”); return (1); }
str = dlsym (p, “s”);
printf (“s=’%s’\n”, *str);

/* I mean not to dlclose it because my product requires both

  • to be opened
    dlclose (p);
    */

pp = dlopen ("./dll2.so", RTLD_NOW | RTLD_LOCAL);
if (pp == 0) { printf (“failed to open dll2\n”); return (1); }
str = dlsym (pp, “s”);
printf (“s=’%s’\n”, *str);
str = dlsym (pp, “t”);
printf (“t=’%s’\n”, *str);
dlclose (pp);
return (0);
}
$ cat main2.c
#include <stdio.h>
#include <dlfcn.h>

int main ()
{
void* p;
void* pp;
char** str;

p = dlopen ("./dll1/dll.so", RTLD_NOW | RTLD_LOCAL);
if (p == 0) { printf (“failed to open dll1\n”); return (1); }
str = dlsym (p, “s”);
printf (“s=’%s’\n”, *str);

/* I mean not to dlclose it because my product requires both

  • to be opened
    dlclose (p);
    */

pp = dlopen ("./dll2/dll.so", RTLD_NOW | RTLD_LOCAL);
if (pp == 0) { printf (“failed to open dll2\n”); return (1); }
str = dlsym (pp, “s”);
printf (“s=’%s’\n”, *str);
str = dlsym (pp, “t”);
printf (“t=’%s’\n”, *str);
dlclose (pp);
return (0);
}
$ cc -shared -o dll1.so dll1.c
$ cc -shared -o dll2.so dll2.c
$ cc -o main main.c
$ cc -o main2 main2.c
$ rm -fr dll1 dll2
$ mkdir dll1
$ mkdir dll2
$ cp dll1.so dll1/dll.so
$ cp dll2.so dll2/dll.so
$ ./main
s=‘this is dll1’
s=‘this is dll2’
t=‘this is dll2’
$ ./main2
s=‘this is dll1’
s=‘this is dll1’ <----- wrong
Memory fault (core dumped) <----- can’t find t

Any suggustion?

\

Gordon Man
Empress Software Inc.

When you dlopen a shared object, the runtime linker detects
that you already have a file of that name loaded. It doesn’t
remember where it came from.

What you could do is give each version a different SONAME record,
eg

qcc -shared -Vgcc_ntox86 -o dll1/dll.so -Wl,-soname=dll1/dll.so dll1.c
qcc -shared -Vgcc_ntox86 -o dll2/dll.so -Wl,-soname=dll2/dll.so dll2.c

That way the dlln part would be considered part of the object’s
name as well.

gmman@qnx.com wrote:

A serious dlopen() problem found in qrtp. At least, it is serious for me
because it is a show stopper for my product.

dlopen() can’t distinguish 2 shared libraries with the same file name
by located in different directory.

dll1.c is the source for the first shared library.
dll2.c is the source for the 2nd shared library.
main.c is the calling program that demostrates the shared libraries
created from dll1.c and dll2.c does work if they have different file
name.
main2.c is the calling program that demostrates the problem.

$ cat dll1.c
char *s = “this is dll1”;
$ cat dll2.c
char *s = “this is dll2”;
char *t = “this is dll2”;
$ cat main.c
#include <stdio.h
#include <dlfcn.h

int main ()
{
void* p;
void* pp;
char** str;

p = dlopen ("./dll1.so", RTLD_NOW | RTLD_LOCAL);
if (p == 0) { printf (“failed to open dll1\n”); return (1); }
str = dlsym (p, “s”);
printf (“s=’%s’\n”, *str);

/* I mean not to dlclose it because my product requires both

  • to be opened
    dlclose (p);
    */

pp = dlopen ("./dll2.so", RTLD_NOW | RTLD_LOCAL);
if (pp == 0) { printf (“failed to open dll2\n”); return (1); }
str = dlsym (pp, “s”);
printf (“s=’%s’\n”, *str);
str = dlsym (pp, “t”);
printf (“t=’%s’\n”, *str);
dlclose (pp);
return (0);
}
$ cat main2.c
#include <stdio.h
#include <dlfcn.h

int main ()
{
void* p;
void* pp;
char** str;

p = dlopen ("./dll1/dll.so", RTLD_NOW | RTLD_LOCAL);
if (p == 0) { printf (“failed to open dll1\n”); return (1); }
str = dlsym (p, “s”);
printf (“s=’%s’\n”, *str);

/* I mean not to dlclose it because my product requires both

  • to be opened
    dlclose (p);
    */

pp = dlopen ("./dll2/dll.so", RTLD_NOW | RTLD_LOCAL);
if (pp == 0) { printf (“failed to open dll2\n”); return (1); }
str = dlsym (pp, “s”);
printf (“s=’%s’\n”, *str);
str = dlsym (pp, “t”);
printf (“t=’%s’\n”, *str);
dlclose (pp);
return (0);
}
$ cc -shared -o dll1.so dll1.c
$ cc -shared -o dll2.so dll2.c
$ cc -o main main.c
$ cc -o main2 main2.c
$ rm -fr dll1 dll2
$ mkdir dll1
$ mkdir dll2
$ cp dll1.so dll1/dll.so
$ cp dll2.so dll2/dll.so
$ ./main
s=‘this is dll1’
s=‘this is dll2’
t=‘this is dll2’
$ ./main2
s=‘this is dll1’
s=‘this is dll1’ <----- wrong
Memory fault (core dumped) <----- can’t find t

Any suggustion?


Gordon Man
Empress Software Inc.


cburgess@qnx.com

No, this does not help because I have no control how the shared library
is made and where it is going to be stored.

Our product is a database product which built on top of the file system.
A database is represented by a directory. The shared library is used to
store psm and user defined function. A database application can access
multiple database at the same time. The user defines the shared library
name and they define where the database is. They can define the same
shared library name for different database.

They can copy (or rename) the database after everything is set up.
What I know is the name of the shared library (which is not created by
me) and where it is stored (the database directory name). Our product
will just dlopen it.

The runtime linker has to remember where it came from. I can understand
(but disagree) that the runtime linker may not want to remember where
it came from the program starts. However, it has to remember when dlopen()
is used. So far, I have not seen one dlopen() for over 15 different kinds of
platforms that behaves the way like QRTP.

Colin Burgess <cburgess@qnx.com> wrote:
: When you dlopen a shared object, the runtime linker detects
: that you already have a file of that name loaded. It doesn’t
: remember where it came from.

: What you could do is give each version a different SONAME record,
: eg

: qcc -shared -Vgcc_ntox86 -o dll1/dll.so -Wl,-soname=dll1/dll.so dll1.c
: qcc -shared -Vgcc_ntox86 -o dll2/dll.so -Wl,-soname=dll2/dll.so dll2.c

: That way the dlln part would be considered part of the object’s
: name as well.

: gmman@qnx.com wrote:

:> A serious dlopen() problem found in qrtp. At least, it is serious for me
:> because it is a show stopper for my product.

:> dlopen() can’t distinguish 2 shared libraries with the same file name
:> by located in different directory.

:> dll1.c is the source for the first shared library.
:> dll2.c is the source for the 2nd shared library.
:> main.c is the calling program that demostrates the shared libraries
:> created from dll1.c and dll2.c does work if they have different file
:> name.
:> main2.c is the calling program that demostrates the problem.

:> $ cat dll1.c
:> char *s = “this is dll1”;
:> $ cat dll2.c
:> char *s = “this is dll2”;
:> char *t = “this is dll2”;
:> $ cat main.c
:> #include <stdio.h>
:> #include <dlfcn.h>

:> int main ()
:> {
:> void* p;
:> void* pp;
:> char** str;

:> p = dlopen ("./dll1.so", RTLD_NOW | RTLD_LOCAL);
:> if (p == 0) { printf (“failed to open dll1\n”); return (1); }
:> str = dlsym (p, “s”);
:> printf (“s=’%s’\n”, *str);

:> /* I mean not to dlclose it because my product requires both
:> * to be opened
:> dlclose (p);
:> */

:> pp = dlopen ("./dll2.so", RTLD_NOW | RTLD_LOCAL);
:> if (pp == 0) { printf (“failed to open dll2\n”); return (1); }
:> str = dlsym (pp, “s”);
:> printf (“s=’%s’\n”, *str);
:> str = dlsym (pp, “t”);
:> printf (“t=’%s’\n”, *str);
:> dlclose (pp);
:> return (0);
:> }
:> $ cat main2.c
:> #include <stdio.h>
:> #include <dlfcn.h>

:> int main ()
:> {
:> void* p;
:> void* pp;
:> char** str;

:> p = dlopen ("./dll1/dll.so", RTLD_NOW | RTLD_LOCAL);
:> if (p == 0) { printf (“failed to open dll1\n”); return (1); }
:> str = dlsym (p, “s”);
:> printf (“s=’%s’\n”, *str);

:> /* I mean not to dlclose it because my product requires both
:> * to be opened
:> dlclose (p);
:> */

:> pp = dlopen ("./dll2/dll.so", RTLD_NOW | RTLD_LOCAL);
:> if (pp == 0) { printf (“failed to open dll2\n”); return (1); }
:> str = dlsym (pp, “s”);
:> printf (“s=’%s’\n”, *str);
:> str = dlsym (pp, “t”);
:> printf (“t=’%s’\n”, *str);
:> dlclose (pp);
:> return (0);
:> }
:> $ cc -shared -o dll1.so dll1.c
:> $ cc -shared -o dll2.so dll2.c
:> $ cc -o main main.c
:> $ cc -o main2 main2.c
:> $ rm -fr dll1 dll2
:> $ mkdir dll1
:> $ mkdir dll2
:> $ cp dll1.so dll1/dll.so
:> $ cp dll2.so dll2/dll.so
:> $ ./main
:> s=‘this is dll1’
:> s=‘this is dll2’
:> t=‘this is dll2’
:> $ ./main2
:> s=‘this is dll1’
:> s=‘this is dll1’ <----- wrong
:> Memory fault (core dumped) <----- can’t find t

:> Any suggustion?


:> –
:> Gordon Man
:> Empress Software Inc.

: –
: cburgess@qnx.com


Gordon Man