Unix Programming - A foo() in seperate .so's resolves to the wrong library

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > August 2004 > A foo() in seperate .so's resolves to the wrong library





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author A foo() in seperate .so's resolves to the wrong library
Steven Reddie

2004-08-20, 2:51 am

Hi All,

I've got a problem where I have two .so's that contain a function with
the same name and the loader picks just one to be used for resolving
all references. I'm sure it's a common problem, but I'm having
trouble explaining it, so a diagram:

+-------------------+
| program |
+-------------------+
| |
V V
+-------+ +-------+
| a1.so | | b1.so |
+-------+ +-------+
| |
V V
+-------+ +-------+
| a2.so | | b2.so |
+-------+ +-------+

a1.so and a2.so are two libraries of a particular component. b1.so
and b2.so are two libraries of a seperate independent component.
a1.so and b1.so don't contain any clashing symbols. a2.so and b2.so
each have a function with the same name, let's say foo(). When a1.so
was linked, the linker saw that it could resolve foo() against a2.so
and flagged it as such. When b1.so was linked, the linker saw that it
could resolve foo() against b2.so and flagged it as such. However,
when linking a1.so and b1.so into program with a line such as (forget
about the missing lib prefix):
ld -o program program.o -la1 -lb1
the resulting executable when loaded resolves foo() against a2.so for
both a1.so and b1.so.

On Windows I get the behaviour that I need which is that since b1.so
was shown that it could resolve foo() against b2.so it will only
resolve it against that library at runtime. I need this behaviour
since a2.so and b2.so are actually different versions of the same
library and the program must be able to simultaneouly use components
which may use differerent versions of this library.

Any help is appreciated.

Regards,

Steven
Paul Pluzhnikov

2004-08-22, 6:08 pm

smr@essemer.com.au (Steven Reddie) writes:

> I've got a problem where I have two .so's that contain a function with
> the same name and the loader picks just one to be used for resolving
> all references. I'm sure it's a common problem [...]


This is *not* a "problem". This is how dynamic linker works (and how
it is supposed to work) on UNIXes (AIX being notable exception).

> On Windows I get the behaviour that I need ...


That is Windows-specific behaviour. You'll need to re-design yor
program if you must replicate this on UNIX.

One approach is for a1.so to have a table of function pointers,
and to initialize them with 'dlsym(a2_handle, "foo")' instead of
linking a1.so against a2.so directly.

However ...

> I need this behaviour
> since a2.so and b2.so are actually different versions of the same
> library and the program must be able to simultaneouly use components
> which may use differerent versions of this library.


.... if your target is Solaris or Linux, you might be able to "coerce"
dynamic loader into the behaviour you want by using versioned
symbols.

You can read more about versioned symbols here:
http://docs.sun.com/db/doc/806-0641/6j9vuqukc?a=view
http://www.linuxbase.org/spec/books...symversion.html

This:

> ld -o program program.o -la1 -lb1


is a very bad idea (TM). On UNIX, you should not use 'ld' directly,
except under very rare circumstances. Use compiler driver ('cc',
'gcc', etc.) instead.

Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
Chuck Dillon

2004-08-22, 6:08 pm

Steven Reddie wrote:
>
> On Windows I get the behaviour that I need which is that since b1.so
> was shown that it could resolve foo() against b2.so it will only
> resolve it against that library at runtime. I need this behaviour
> since a2.so and b2.so are actually different versions of the same
> library and the program must be able to simultaneouly use components
> which may use differerent versions of this library.
>


Your options will vary by platform but generally speaking you can't
pre-link a *NIX program to get the result you describe. The closest
you can get is to dynamically link to at least one of the versions at
runtime. See dlopen and the RTLD_LOCAL/GLOBAL discussion.

The idea would be to dlopen one (or both) of your .so with RTLD_LOCAL
asserted so that the symbols in that shared object doesn't polute your
program's namespace. But this requires that you explicitly find the
functions your program needs to call using dlsym and references them
via pointers.

More specifically, you could create a stub layer around the API in
b1.so (call it b1stubs.so). It would be a layer that mirrors the API
you need and lies between your program and b1.so. The stub layer would
have stubs for each function/object you need in b1.so plus an
initialization function. The initialization function of b1stubs.so
would dlopen the b1.so and use dlsym to get pointers to each
function/object. References to somefunc()@b1stub.so would call
somefunc()b1.so via a pointer returned by dlsym(b1handle,"somefunc").
Since you would dlopen b1.so as RTLD_LOCAL b1.so and b2.so would have a
namespace separate from your program and so have their own foo().

Again, YMMV on different systems (e.g. Solaris, AIX, IRIX, ...).

HTH,

-- ced



--
Chuck Dillon
Senior Software Engineer
NimbleGen Systems Inc.
Frank Cusack

2004-08-22, 6:08 pm

On 20 Aug 2004 01:39:55 -0700 smr@essemer.com.au (Steven Reddie) wrote:
> Hi All,
>
> I've got a problem where I have two .so's that contain a function with
> the same name and the loader picks just one to be used for resolving
> all references. I'm sure it's a common problem, but I'm having
> trouble explaining it, so a diagram:
>
> +-------------------+
> | program |
> +-------------------+
> | |
> V V
> +-------+ +-------+
> | a1.so | | b1.so |
> +-------+ +-------+
> | |
> V V
> +-------+ +-------+
> | a2.so | | b2.so |
> +-------+ +-------+
>
> a1.so and a2.so are two libraries of a particular component. b1.so
> and b2.so are two libraries of a seperate independent component.
> a1.so and b1.so don't contain any clashing symbols. a2.so and b2.so
> each have a function with the same name, let's say foo(). When a1.so
> was linked, the linker saw that it could resolve foo() against a2.so
> and flagged it as such. When b1.so was linked, the linker saw that it
> could resolve foo() against b2.so and flagged it as such. However,
> when linking a1.so and b1.so into program with a line such as (forget
> about the missing lib prefix):
> ld -o program program.o -la1 -lb1
> the resulting executable when loaded resolves foo() against a2.so for
> both a1.so and b1.so.


On Solaris, try 'ld -B direct' when linking b1.

/fc
Steven Reddie

2004-08-23, 8:01 am

The dlopen/dlsym approach is what I was hoping to avoid as the API has
about 2500 functions. I'm in the process of automating the creation
of the stubs which will be statically linked against (one function per
module to reduce aquired baggage).

The -Bgroup option on Solaris worked a treat, but the same option
which is documented as supported on Linux didn't work. Anyway, I need
to target also AIX, HP-UX, DEC Unix and others in the future, so
something more common such as dlsym is required.

Thanks for the help.

Regards,

Steven
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com