How to create Shared Library in Linux ?

Below program demos how to create a shared library and link it with the main program to create a executable. For demo, we will write two files / c program each of which has one function defined inside it.

 vim first.c 
#include <stdio.h>
#include "header.h"
void function1(void) { printf("This is function1\n");
}
 vim second.c 
#include <stdio.h>
#include "header.h"
void function2(void) { printf("This is Function2\n");
}
 vim header.h 
#ifndef __HEADER_H
#define __HEADER_H
void function1(void);
void function2(void);
#endif
 $ gcc -c first.c
-rw-rw-r-- 1 myuser myuser 1.1K Sep 1 20:49 first.o
 $ gcc -c second.c
-rw-rw-r-- 1 myuser myuser 1.1K Sep 1 20:49 second.o
 $ gcc -o testlib.so -shared first.o second.o
-rwxrwxr-x 1 myuser myuser 6.9K Sep 1 22:18 testlib.so
 $ file testlib.so testlib.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=00cebe431ba7f5a5df7d019d265db58916552303, not stripped
 $ nm -s testlib.so
00002010 B __bss_start
00002010 b completed.7200 w __cxa_finalize@@GLIBC_2.1.3
00000420 t deregister_tm_clones
000004b0 t __do_global_dtors_aux
00001f14 t __do_global_dtors_aux_fini_array_entry
0000200c d __dso_handle
00001f1c d _DYNAMIC
00002010 D _edata
00002014 B _end
00000574 T _fini
00000500 t frame_dummy
00001f10 t __frame_dummy_init_array_entry
0000064c r __FRAME_END__
00000540 T function1
00000559 T function2
00002000 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__
000005ac r __GNU_EH_FRAME_HDR
000003cc T _init w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable
00001f18 d __JCR_END__
00001f18 d __JCR_LIST__ w _Jv_RegisterClasses U puts@@GLIBC_2.0
00000460 t register_tm_clones
00002010 d __TMC_END__
00000410 t __x86.get_pc_thunk.bx
0000053c t __x86.get_pc_thunk.dx

From “nm” command, we can see that now our created library has the symbols from both the object files first.o and second.o. so, now our shared library is ready. Now lets write a main program or application which will use this library and write its own application using library functions as,

 $ vim main.c 
#include <stdio.h>
#include "header.h"
int main(int argc, char *argv[]) { function1(); //call function1 from first.c function2(); //call function2 from second.c return 0;
}
 $ gcc -o main main.c testlib.so 
 $ file main
main: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=a7f9aee8eb8dbed81d4894af0a25be7d36476f02, not stripped

Now, lets try to execute our newly created executable “main” as,

 $ ./main
./main: error while loading shared libraries: testlib.so: cannot open shared object file: No such file or directory 

Despite having our library created and linked, Why this happened ? Lets try to diagnose,

 $ ldd main	linux-gate.so.1 => (0xb772e000)	testlib.so => not found	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb754a000)	/lib/ld-linux.so.2 (0x800e4000) 

As per ldd, its showing that main is unable to find the “testlib.so” since this is dynamically linked library, we have to mention the path where this library is stored to the executable during the start. Ideally, the path searched are what has been seen in “LD_LIBRARY_PATH” so, we have to add our present path to this environment variable as,

 $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD 

Now, check with “ldd”, it shows library found.

$ ldd main	linux-gate.so.1 => (0xb776d000)	testlib.so (0xb7766000)	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7586000)	/lib/ld-linux.so.2 (0x80092000)
$ ./main
This is function1
This is Function2

OR You can use the Makefile as below to compile everything and just type “make” in same directory by copying this Makefile.

 vim Makefile 
all: gcc -c first.c gcc -c second.c gcc -o testlib.so -shared first.o second.o gcc -o main main.c testlib.so
clean: rm -rf main testlib.so first.o second.o
READ  How to fix : ERROR: do_package_qa: QA Issue: No GNU_HASH in the elf binary

Leave a Reply

Your email address will not be published. Required fields are marked *