LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Hiding global symbols in a shared/static library (https://www.linuxquestions.org/questions/programming-9/hiding-global-symbols-in-a-shared-static-library-472643/)

jineshkj 08-10-2006 09:56 AM

Hiding global symbols in a shared/static library
 
hi friends,

i would like to know how to remove symbols from shared or static library. for example, i have two files f1.c and f2.c to be compiled to make a static library. both these files use a common global function called func(). But, this function must not be used by anyone who links the library with their application. ie, i want to remove func() from the global symbol table while compiling the library either as static or shared library.

will 'ld -x' help us while compiling shared libraries? what can I do for static libraries? i couldn't find anything specific in ar, nm or ranlib manpages.

can someone help me please?

thanks,

jinesh.

sundialsvcs 08-10-2006 12:22 PM

Have a look at info libtool.

Declare "func()" to be static so that the compiler will not generate an external symbol dictionary entry for it.

jineshkj 08-10-2006 11:47 PM

but if i declare func() to be static, it can be accessed only from the file it is written. remember that here i have two files f1.c and f2.c both of which should use this function.

sundialsvcs 08-11-2006 07:03 AM

The document How to Write Shared Libraries is the best I've ever found anywhere: http://people.redhat.com/drepper/dsohowto.pdf

45 (count 'em) pages covering way more than you ever thought you needed to know about how all this magic works in various Unix implementations. Symbol visibility and exporting is among the many topics covered.

Apple Computer also published a good piece although it's even longer:
http://developer.apple.com/documenta...cLibraries.pdf

Since "they" use basically the same techniques that "we" use, the document applies to "us, too."

xhi 08-11-2006 09:23 AM

what i would do in this case is to make two header files, one libsomelib.h and libsomelib_local.h.

all the files in somelib can include both files, done like this

#include <libsomelib.h>
#include "libsomelib_local.h"

keep all of the private library functions in _local.h.

now to make this work, you have to get a little creative with the makefile. you will need to copy the libsomelib.h to another directory, say director include/ somewhere in the build tree. this is also done for all your other libs. so now you have an include dir somewhere that has libsomelib.h, libsomeotherlib.h, libalib.h, etc etc.. and then when compiling just pass the path of that dir include/ to gcc like so

-I/path/to/include

now all of the libs only have access to the public api of each other, and each lib will have access to both the public and private api that it owns.

as for making functions private with the linker, i dont know if its possible i have never seen it done or attempted. but this works just as well, actuall better as it is far more flexible and easier to change.

jineshkj 08-25-2006 06:30 AM

Quote:

Originally Posted by xhi

#include <libsomelib.h>
#include "libsomelib_local.h"

keep all of the private library functions in _local.h.

Thanks for the reply. But, don't you think that instead of keeping two header files, we may have a #ifdef section to differentiate the local functions. For example, out header will be like:

--- somelib.h ------


#ifdef SOMELIB_LOCAL_INCLUDE

All the locally used functions.

#endif

All the public functions.


--- somelib.h ends here -----


And when compiling the library, we may use:

gcc -DSOMELIB_LOCAL_INCLUDE ...

In that way, it becomes easy to move functions between the sections, maybe in a far future we may wish to make a function public or private... right?

xhi 08-25-2006 08:29 AM

sure that sounds like it would work as well.

imo the way i mentioned is more clear cut, you have a public file and a private file. when you are looking for a function you dont have to see where in the file it is. looking for a #ifdef amongst hundered of lines over time would be error prone i would think. but as far as being functional, sure your way should work fine.

the project im currently working on is about 15,000 C source files large, and it is using a make system like i mentioned and it works flawlessly. the time spent is in the beginning writing your makefile.in template, then after that it is cake.

> In that way, it becomes easy to move functions between the sections,

i dont understand, you are just moving functions from one line in one file to another line in another file. i would not use that as a reason for using #ifdef, because either was is trivial.

>maybe in a far future we may wish to make a function public or private... right?

(i may not be understanding this statement correctly)
do you mean a function should be both private and public? in what i mentioned they are, a lib can include both the .h and the _local.h so both public and private functions are available to the lib.

-good luck

theNbomr 08-25-2006 09:59 AM

I don't see how the question makes sense. If you have something in a library, and that something needs to be referenced by another module, how will the linker resolve that reference, without there being a public name for it in the library? If the symbol is not to be referenced, why put it in a library? What am I missing?

--- rod

xhi 08-25-2006 10:09 AM

> If you have something in a library, and that something needs to be referenced by another module, how will the linker resolve that reference

i think you misread part of the original question

> this function must not be used by anyone who links the library with their application.

the function(s) is available to different modules in the lib itself, but not to any other lib

theNbomr 08-25-2006 11:29 AM

If you need the global symbol for your application only, and don't want it exported to other users of your library, just link the function as a separate object module, 'func.o', and don't put it in the library.
--- rod.

xhi 08-25-2006 12:24 PM

theNbomr, sure you could do that. it sounds to me like with your solution it seems like you are simply moving to having public and private .c files instead of (my solution) public and private .h files. right? which sounds to be less flexible. sure you save a few k on your libs, but i dont see it being worth it.

in my application the reason it is done the way i mentioned is because the public and private functions may be mixed amongst the source files. for example one source file may have 10 public and 3 private functions and another be similar, they are potentially all mixed. this is because they are possibly using some sort of statically declared function or variable in that file. if we want to change one of those to be public or private, instead of copying and pasting the function definition to another file (which is another error prone story in itself) we simply modify the declaration, remove from on .h and move to the other .h ..

imo its a simple solution for a large and quickly changing project.

ta0kira 08-26-2006 03:30 PM

Look at info:gcc and look up "Function Attributes". This will tell you the different classifications of visibility of functions (you might be looking for "__attribute__ ((visibility ("internal")))".) Also, you can link with the '--retain-symbols-file=file' option with 'ld' to restrict the symbols placed in the table (visible when using 'nm'.)
ta0kira

ta0kira 08-27-2006 09:42 PM

Quote:

Originally Posted by xhi
we simply modify the declaration, remove from on .h and move to the other .h ..

There are many ways to prevent the user from including a function in their own headers, but that doesn't prevent them from declaring an extern and then linking to it. Take this example:
Code:

//test.c

__attribute__ ((visibility ("internal")))
void DontUseMe()
{

}

Code:

//main.c

extern void DontUseMe();

int main()
{
DontUseMe();
}

Code:

> gcc test.c -c -fPIC
> gcc main.c -c
> ld test.o -shared -o libtest.so
> gcc main.o libtest.so
main.o(.text+0x11): In function `main':
: undefined reference to `DontUseMe'
collect2: ld returned 1 exit status

The linker error is a result of internal; if you remove it, you don't get the error. This only affects the final linked object; it can still be used across object files before the final link is made.
ta0kira

PS This is a "link time" vs. a "compile time" issue.

xhi 08-27-2006 09:53 PM

ta0kira,

i have never saw the attribute trick. i will definately be checking that out.. thanks.

and you are right, with my method if someone wanted to cheat they could cheat. it is used as more of a guide than a tight restriction i guess. the uses my method has found are only for control within a single app, controlling what one lib can know about another lib. and the libs that use this are never made available to other apps eithe, it seems like your method would be significantly more flexible, especially if one were to make libraries available to other projects.


good stuff..

jineshkj 08-28-2006 04:50 AM

Quote:

Originally Posted by ta0kira
Look at info:gcc and look up "Function Attributes". This will tell you the different classifications of visibility of functions (you might be looking for "__attribute__ ((visibility ("internal")))".) Also, you can link with the '--retain-symbols-file=file' option with 'ld' to restrict the symbols placed in the table (visible when using 'nm'.)
ta0kira

I liked the ld option that you've mentioned since it seem to be more straight forward. Combining this with the header file scheme mentioned by xhi, i think my problem is solved. I'm sure that just manipulating the header files won't prevent a tricky user from using those unintended-public functions declared in the xxx-local.h.

I personally don't like to use gcc attributes since no other compiler provides similar functionalities, whereas linker options would be easily portable across various linkers.


All times are GMT -5. The time now is 09:42 AM.