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.