views:

96

answers:

1

Hello,

I'm working on refactoring a suite of old utilities and creating a new server that's going to use common code from all of them to unify their functionality and allow external access by remote clients. For each utility, I'm taking the code I need for the server and refactoring it out into a shared library so that the utility and the server will now both link against the shared library. Because of the way the former implementor of these utilites did things, they pretty much just copied and pasted everything whenever they needed to create a new utility, so there's a ton of functions that have the same signature (ie callbacks for an XML parser) but do different things inside.

When I run the standalone utilities which have been refactored to link against the shared code, they work perfectly. When I try to use the server with the same functionality as a given utility, the server is using code from the first library linked in, instead of the library it should be taking functionality from.

For example, I have xml for devices A, B, C that get parsed by a common xml library, but each device has its own shared library libA, libB, libC that's used by the server. When I make a call to the server to send xml for device C, it's using the function 'HandleStartElement' from libA, instead of the function of same name and signature in libC, even though the shared libraries only declare these functions internally and don't share any headers that mention these internal callbacks for parsing xml.

Can somebody please explain to me why it's not reading the proper function, and how to avoid this in the future ?

My makefile for the server has the following flags for the compilation of the main program :

-I../include -L../lib -lA -lB -lC

Each shared library is using next to no flags for the shared library, and is not using -fPIC.

+6  A: 

When used with -l flags, shared libraries are supposed to work like non-shared libraries, and, in particular, will not support the presence of several functions with the same name. You are already somewhat lucky that the server runs at all.

If I understand your problem correctly, then the functions which have the same name are not intended to be "seen" outside of the shared library. A shared library has a "dynamic symbol table" which lists what symbols are exported and imported by the shared library. With GNU tools, you can see its contents with nm -D libfoo.so. Traditional Unix linkers populate that symbol table by using all the public entities in the object files (namely, non-static functions and global variables). What you want here is a more controlled construction of that symbol table. If your code uses GNU tools (e.g. you are running on Linux), then you want to read this article, in particular section 2.2. Short story: the ELF format supports what you are after, and there are several tools/ways to achieve it.

However, in your place, I would flourish some sed-based scripts to rename the offending functions with unique names. Some retaliatory actions on the original over-copy-pasters may also be in order.

You should use -fPIC. Not using -fPIC for shared libraries on some architectures is a fatal mistake. Since your code does not crash, I suppose that you run on x86 hardware.

Thomas Pornin
You do understand the problem correctly, and I do want a more controlled construction of the symbol table. I'm actually cross compiling from an x86 machine running Gentoo with a 2.6 kernal to a PPC 405 embedded machine running a 2.4 kernel. I'll give the article a read, and see if I can manipulate the construction of the symbol table, otherwise I'll just have to rename a bunch of crap. Thank you so much.
Alex Marshall
Ran through the article. Just redeclaring my internal module functionts as static (which I should have known to do in the first place) was sufficient to prevent them from being publicly accessible in the symbol table. Thank you once again.
Alex Marshall