Example of shared library
Making an executable shared library
References
About the author
You may know that it is possible to run the C shared library. For example, on my Linux system, if I run it, it displays its version:
GNU C Library (Ubuntu EGLIBC 2.11.1-0ubuntu7.8) stable release version 2.11.1, by Roland McGrath et al.
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.4.3.
Compiled on a Linux >>2.6.24-27-server<< system on 2011-01-21.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
This paper focuses on the recipe to make executable shared libraries.
Here is the source file of a shared library:
service.c |
#include <stdio.h> void lib_service(void) { printf("This is a service of the shared library\n"); } // lib_service |
Here is a main program which uses the preceding shared library:
main.c |
#include <stdio.h> extern void lib_service(void); int main(int ac, char *av[]) { lib_service(); return 0; } // main |
To build this program along with its shared library, we do:
$ gcc main.c -o main -lservice -L.
To run the program we do:
$ ./main
This is a service of the shared library
If we run the library we get a segmentation fault:
$ ./libservice.so
Erreur de segmentation
We must first specify an entry point for the library:
service.c |
#include <stdio.h> void lib_service(void) { printf("This is a service of the shared library\n"); } // lib_service void lib_entry(void) { printf("Entry point of the service library\n"); } |
This entry point is set into the object thanks to the "-e" option of the linker:
But the execution still fails:
Illegal instruction
We must make the entry point be a "no return" function thanks to the "_exit()" service:
service.c |
#include <stdio.h> #include <unistd.h> void lib_service(void) { printf("This is a service of the shared library\n"); } // lib_service void lib_entry(void) { printf("Entry point of the service library\n"); _exit(0); } |
But the execution still fails:
$ ./libservice.so
Illegal instruction
We specify the interpreter file to be the dynamic linker. On our Linux system, it is /lib/ld-linux.so.2. Make sure to use the right linker. If the system is 64 bits, this may be something like: /lib64/ld-linux-x86-64.so.2.
service.c |
#include <stdio.h> #include <unistd.h> const char service_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2"; void lib_service(void) { printf("This is a service of the shared library\n"); } // lib_service void lib_entry(void) { printf("Entry point of the service library\n"); _exit(0); } |
Now it works !
$ ./libservice.so
Entry point of the service library
Although, it is executable, the file is still usable as a library since the "main" executable can still dynamically link with it:
This is a service of the shared library
If the linker pathname is not correct, an error like the following may be displayed:
bash: ./libservice.so: Accessing a corrupted shared library
NB: If you are using the G++ compiler, make sure that the entry point is defined as a C language symbol with the extern "C" directive. For example:
service.c |
#include <stdio.h> #include <unistd.h> const char service_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2"; void lib_service(void) { printf("This is a service of the shared library\n"); } // lib_service extern "C" { void lib_entry(void) { printf("Entry point of the service library\n"); _exit(0); } } |
The author is an engineer in computer sciences located in France. He can be contacted here.