将编译库链接到更新版本的glibc

时间:2022-01-23 06:30:10

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.

我正在开发一个使用ftdi D2XX驱动程序与ENTTEC DMX usb pro设备连接的项目。存储在/ usr / local / lib /中的ftdi驱动程序(libftdi2xx.so.1.1.12)是针对glibc v2.14或更高版本编译的。

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:

我正在开发debian 7,它只支持glibc v2.13。执行我编写的C代码(调用ftdi驱动程序)时会出错:

./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版本是不兼容的。我已经下载并安装了最新版本的glibc(v2.17)到我的计算机上的临时目录('〜/ glibc-testing / install / lib /')并使用该调用:

~/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.

通过此调用,我可以成功运行C代码。

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#.

我想将此C代码编译为共享库。它将用于与DMX设备连接,并将由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?

我不确定如何前进。我需要做的是告诉fdti驱动程序始终使用较新的glibc,同时让应用程序的其余部分使用普通库。 ftdi 2DXX驱动程序仅可预编译(无源代码可用)。有没有办法将这个预编译的程序链接到新库?

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

我已经查看了导出LD_LIBRARY_PATH = / home /.../ glibc / install / lib /的选项,但我没有成功。

Thank you!

3 个解决方案

#1


1  

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:

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.

现在最棘手的部分是让加载器相信它有正确的库(除非你想要实现自己的加载器),因为你需要修补库以删除对GLIBC_2.14的引用,因为它将会查看特别是libc。

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.

有几种方法可以继续;到目前为止,最简单的是用GLIBC_2.13替换GLIBC_2.14,请记住,您需要使用替换版本(即GLIBC_2.13)定义符号,因为版本是通过引用存储的。

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).

    解析ELF文件,在程序头中找到DYNAMIC类型条目,在那里搜索VERNEED条目,最后在那个条目之后你应该找到你可以修剪引用的需求表(也可以使用.gnu。如果可用的话,将获得version_r节标题。

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

    或者,您可以编写一个链接标准加载器但使用ptrace覆盖查找的加载器。

#2


0  

one of the variants it is update debian to sid.

其中一个变种是更新debian到sid。

another option is to change the file /etc/ld.so.conf.d/libc.conf and /etc/ld.so.conf.d/x86_64-linux-gnu.conf

另一种选择是更改文件/etc/ld.so.conf.d/libc.conf和/etc/ld.so.conf.d/x86_64-linux-gnu.conf

These files contain the path to search for libraries in the system.

这些文件包含在系统中搜索库的路径。

#3


0  

You can use PatchELF to modify the rpath of the provided shared library:

您可以使用PatchELF修改提供的共享库的rpath:

$ patchelf --set-rpath /home/user/glibc-testing/install/lib/ libftdi2xx.so.1.1.12

And then compile your shared library using:

然后使用以下命令编译您的共享库:

$ gcc -Wl,-rpath=/home/user/glibc-testing/install/lib/ <rest of flags>

Any executables you compile will have to be compiled with:

您编译的任何可执行文件都必须使用以下代码编译:

$ gcc -Wl,-rpath=/home/user/glibc-testing/install/lib/  -Wl,--dynamic-linker=/home/user/glibc-testing/install/lib/ld-linux-x86-64.so.2 <rest of flags>

#1


1  

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:

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.

现在最棘手的部分是让加载器相信它有正确的库(除非你想要实现自己的加载器),因为你需要修补库以删除对GLIBC_2.14的引用,因为它将会查看特别是libc。

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.

有几种方法可以继续;到目前为止,最简单的是用GLIBC_2.13替换GLIBC_2.14,请记住,您需要使用替换版本(即GLIBC_2.13)定义符号,因为版本是通过引用存储的。

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).

    解析ELF文件,在程序头中找到DYNAMIC类型条目,在那里搜索VERNEED条目,最后在那个条目之后你应该找到你可以修剪引用的需求表(也可以使用.gnu。如果可用的话,将获得version_r节标题。

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

    或者,您可以编写一个链接标准加载器但使用ptrace覆盖查找的加载器。

#2


0  

one of the variants it is update debian to sid.

其中一个变种是更新debian到sid。

another option is to change the file /etc/ld.so.conf.d/libc.conf and /etc/ld.so.conf.d/x86_64-linux-gnu.conf

另一种选择是更改文件/etc/ld.so.conf.d/libc.conf和/etc/ld.so.conf.d/x86_64-linux-gnu.conf

These files contain the path to search for libraries in the system.

这些文件包含在系统中搜索库的路径。

#3


0  

You can use PatchELF to modify the rpath of the provided shared library:

您可以使用PatchELF修改提供的共享库的rpath:

$ patchelf --set-rpath /home/user/glibc-testing/install/lib/ libftdi2xx.so.1.1.12

And then compile your shared library using:

然后使用以下命令编译您的共享库:

$ gcc -Wl,-rpath=/home/user/glibc-testing/install/lib/ <rest of flags>

Any executables you compile will have to be compiled with:

您编译的任何可执行文件都必须使用以下代码编译:

$ gcc -Wl,-rpath=/home/user/glibc-testing/install/lib/  -Wl,--dynamic-linker=/home/user/glibc-testing/install/lib/ld-linux-x86-64.so.2 <rest of flags>