Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking compiled library to newer version of glibc

I am working on a project that uses the ftdi D2XX drivers to interface with the ENTTEC DMX usb pro device. The ftdi drivers (libftdi2xx.so.1.1.12 stored in /usr/local/lib/) are compiled against a version of glibc v2.14 or higher.

I am developing on debian 7 which only supports up to glibc v2.13. When executing the C code I have written (that makes calls to the ftdi drivers) it gives an error:

./a.out: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14' not found (required by /usr/local/lib/libftd2xx.so)

This makes sense, knowing that the glibc version is incompatible. I have downloaded and installed the newest version of glibc (v2.17) to a temporary directory ('~/glibc-testing/install/lib/') on my computer and by using the call:

~/glibc-testing/install/lib/ld-linux-x86-64.so.2 --library-path ~/glibc-testing/install/lib/ ./a.out 

With this call, I am able to run the C-code successfully.

I would like to compile this C-code to a shared library. It will be used to interface with the DMX device and will be called by a main application developed on C#.

I am not sure how to move forward. What it seems like I need to do is to tell the fdti driver to always use the newer glibc while letting the rest of the application use the normal libraries. The ftdi 2DXX drivers are only available precompiled (no source code available). Is there a way to link this pre-compiled program to the new library?

I have looked into options where I export LD_LIBRARY_PATH=/home/.../glibc/install/lib/ and I have had little success.

Thank you!

like image 457
Brotherhood Avatar asked Feb 18 '13 06:02

Brotherhood


1 Answers

You can provide the missing functions in your own code, but note those are versioned, you can either provide a map file or do everything along with the code. Example:

#define SYMVER(ver, sym) __asm__(".symver " #sym "," #sym "@" #ver "\n")

SYMVER(GLIBC_2.14, foo);
int foo(int a, char *b)
{
    return 4;
}

In order to figure out what to implement, you can use readelf:

readelf -s /usr/local/lib/libftd2xx.so | grep '@GLIBC_2\.14'

That's it, as far as functions go.

Now the tricky part is making the loader to believe it got the right library (unless you want to implement your own loader), for that you need to patch the library to remove the reference to GLIBC_2.14, because it is going to look on the libc specifically.

There's several ways to proceed; by far the simplest is to replace GLIBC_2.14 with GLIBC_2.13, just keep in mind that you need to define your symbols with the replacement version (i.e. GLIBC_2.13), because versions are stored by reference.

With that your program should run.

Now, theoretically you could instead:

  • Parse the ELF file, find the the DYNAMIC type entry in the program headers, there search for a VERNEED entry, and finally following that one you should find the table of requirements where you can trim the reference (also you can use the .gnu.version_r section header to get there if available).

  • Alternatively, you could write a loader that chains the standard loader but uses ptrace to override the lookup.

like image 128
Ismael Luceno Avatar answered Oct 06 '22 00:10

Ismael Luceno