I am trying to compile the following components:
appl - an application which links to a dynamic shared library (libwrapper.so)
libwrapper.so - A library used by appl. This library invokes functions from a libbackend archive.
libbackend.a - A static archive that uses libc functions.
I want to ensure that the libc functions invoked by libbackend always uses a fixed libc implementation. So I am also archiving the needed libc.a in libbackend, in my compilation environment.
I want to achieve that when libbackend invokes any libc function, the archived libc function from the compilation environment should be invoked, not the function from libc.so version in the target environment.
Can this be achieved? Also, can this be achieved without changing the way appl is being compiled; i.e., can be this achieved by changing makefile of only libwrapper and libbackend?
This is what I have tried so far, and does not work:
[dev-env]# ls
appl.c backend.c backend.h Makefile wrapper.c wrapper.h
[dev-env]# cat appl.c
#include <stdio.h>
#include "wrapper.h"
void main()
{
printf("in appl\n");
wrapper();
}
[dev-env]# cat wrapper.h
void wrapper();
[dev-env]# cat wrapper.c
#include <stdio.h>
#include "wrapper.h"
#include "backend.h"
void wrapper()
{
printf("In wrapper\n");
backend();
}
[dev-env]# cat backend.h
void backend();
[dev-env]# cat backend.c
#include <stdio.h>
#include <gnu/libc-version.h>
#include "backend.h"
void backend()
{
printf("in backend\n");
printf("GNU libc version: %s\n", gnu_get_libc_version());
}
[dev-env]# cat Makefile
LIBC=$(shell gcc --print-file-name=libc.a)
all: libbackend.a libwrapper.so appl
libbackend.a: backend.c backend.h
gcc -static -fPIC -c backend.c -o backend.o
ar rcs libbackend.a $(LIBC) backend.o
libwrapper.so: wrapper.c wrapper.h libbackend.a
gcc -c wrapper.c
gcc -shared -o libwrapper.so wrapper.o libbackend.a
appl: appl.c
gcc -o appl appl.c -L . -lwrapper
clean:
rm *.o *.a *.so appl
[dev-env]#
From compilation environment:
[dev-env]# make
gcc -static -fPIC -c backend.c -o backend.o
ar rcs libbackend.a /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libc.a backend.o
gcc -c wrapper.c
gcc -shared -o libwrapper.so wrapper.o libbackend.a
gcc -o appl appl.c -L . -lwrapper
[dev-env]# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
[dev-env]# ./appl
in appl
In wrapper
in backend
GNU libc version: 2.28
In target environment:
[target]# ./appl
in appl
In wrapper
in backend
GNU libc version: 2.30
If what I am intending works, on target I should have seen the version output as "2.28".