|
From: | Jef Driesen |
Subject: | Re: Questions on exporting functions from a shared library |
Date: | Tue, 23 Sep 2008 20:44:47 +0200 |
User-agent: | Thunderbird 2.0.0.16 (X11/20080724) |
Brian Dessent wrote:
Jef Driesen wrote:And how about gcc < 4.0 that do not support the visibility attributes? Is there a way to hide non-public symbols? Is the version script still available in this case? Is it possible to use both the attributes and the -export-symbols together?There are two aspects to the symbol visibility stuff: A) When the compiler knows at compile time that a function or variable has hidden visibility it can create more efficient code for calling/accessing it because it doesn't have to use the usual PIC indirection through the PLT/GOT. This is similar to how marking a function static allows the compiler more latitude to optimize it, except this also works for functions that must remain accessible from other objects in the library but not accessible from outside the library. B) When linking the shared library, it's helpful to reduce the number of entries in the dynamic symbol table to only those that are part of the defined public API. This is what improves the symbol lookup time during startup, as well as ensuring that no client of your library accidently uses some undocumented or internal interface. When you use __attribute__((visibility)) you get both (A) and (B), but when you use a version map you get (B) only. However, since (B) only happens at link-time it doesn't require any compiler support and it only depends on whether the linker supports symbol versioning. I believe that libtool is smart enough to check the linker for symbol versioning support to implement -export-symbols, so as long as you are using a non-ancient version of binutils it should work fine with gcc < 4 and still provide the (B) benefits.
Thanks for the clear explanation! I'm mostly interested in the ability to prevent applications from using non-public functions. Performance improvements would be nice bonus, but not really a must.
This ELF visibility is quite different from the win32 dllimport/export attributes. If I understand everything correctly, the ELF visibility only has an impact on the internal code (when compiling the library). While the win32 dllimport attribute changes how the applications links to the library. When linking against a DLL, the application is linked against a stub function that calls the DLL function, and with dllimport the linker can generate code that calls the DLL function directly. So this is results in a change on the application side, not the library.
I already discovered one technical difference when not using dllimport. If you try (in an application linked against your dll) to obtain the address of a function that resides in the dll, you get the address of the stub function. But with dllimport, you get the address of the real function. That could make a difference if want to compare with a function pointer that is returned from a function in the dll (which always returns the real address).
Now that I start to understand all the differences, I only need to find a way how to incorporate everything nicely in my automake build system. Suggestions? I guess I'm not the first one struggling with this, so I'm surprised there is not more information available. Most projects (at least the ones I checked) seems to be using -export-symbols.
[Prev in Thread] | Current Thread | [Next in Thread] |