我已经在Ubuntu 12.04上构build了一个应用程序,并尝试在embedded式系统上运行它。 我在我的开发机器上运行apt-cache show libc6
,显示(其中包括)
Package: libc6 Priority: required Section: libs Architecture: i386 Source: eglibc Version: 2.15-0ubuntu10 Replaces: belocs-locales-bin, libc6-i386 Provides: glibc-2.13-1, libc6-i686
embedded式设备上存在的libc6版本是2.8.90。 在设备的\lib
目录中,我有2个库
libc-2.8.90.so libc.so.6
当我将应用程序复制到embedded式设备上时,出现以下错误
/usr/lib/libc.so.6: version `GLIBC_2.15` not found (required by ./ServerSocketApp)
我知道如果可能的话,当我在开发环境中构build应用程序时,我需要强制它链接到embedded式设备上存在的相同版本的libc6。 我的问题是,我根本不知道如何做到这一点。 我发现的答案现在对我来说毫无意义。 有没有一些选项,我需要传递给g ++得到这个链接到2.8.90版本?
在绝望中,我想是否有可能将我的开发机器上的libc复制到embedded式设备上,而不是已经存在的地方,希望最好? 我只是似乎无法find任何在线文档,用简单的语言解释了你甚至可以如何解决这个问题,所以任何build议都会真正受到欢迎,因为我正在把我的头发拉出来。
这从根本上是不正确的。 虽然您可能能够一起破解旧版libc的链接,但问题在于您的环境设置。
当您为嵌入式系统开发应用程序时。 你在主机上这样做。 通常,主机和嵌入式设备不在相同的架构上。 例如,您的主机通常是在x86上运行的台式机/笔记本电脑,嵌入式系统可能在ARM上。 如果您碰巧与嵌入式设备处于相同的架构,那纯属巧合。 标准的练习环境设置应该仍然如下:
如果你有这样的设置。 发展会很容易。 您将能够设置简单,干净的make文件来构建应用程序,然后将二进制文件scp
到嵌入式系统并运行。
好的,这里有一个比较长的解释,但要小心。 我仍然强烈建议你设置一个chroot环境来匹配嵌入式设备上可用的环境,并在构建过程的最后阶段使用它。
您应该了解如何加载和执行动态链接的ELF可执行文件。 有一种称为运行时链接编辑器 (RTLD),也称为动态链接器,负责加载所有必要的动态链接库,修复重定位等。 在具有glibc2
64位Linux系统上,使用glibc2
和/lib64/ld-linux-x86-64.so.2
32位Linux系统上的动态链接程序的名称是glibc2
。 动态链接器与glibc2
库紧密耦合,通常只能处理该库的匹配版本。 而且它的路径被链接器硬编码成可执行文件(通常是ld
,编译器隐式调用来做链接)。 您可以通过简单地执行ldd some_elf_executable
轻松检查最后一条语句的ldd some_elf_executable
– 运行时链接编辑器显示完整路径:
$ ldd some_elf_executable linux-vdso.so.1 => (0x00007fffab59e000) libm.so.6 => /lib64/libm.so.6 (0x0000003648400000) libc.so.6 => /lib64/libc.so.6 (0x0000003648800000) /lib64/ld-linux-x86-64.so.2 (0x0000003648000000) <--- the RTLD
为了生成一个动态链接的可执行文件,该可执行文件使用的glibc2
版本与系统上安装的glibc2
版本不同,要运行可执行文件,应该将代码与以下一组选项链接到ld
:
-rpath=/path/to/newer/libs
– 这个指示动态连接器在尝试解决库依赖关系时首先搜索/path/to/newer/libs
。 /path/to/newer/libs
应该与您在嵌入式设备上复制了更新的glibc2
版本的路径匹配 -rpath-link=/path/to/newer/libs
– 此选项指示链接器(而不是动态链接器)在链接时解决共享库之间的依赖关系时使用/path/to/newer/libs
– 这不应该是正常的在你的情况下必要的 --dynamic-linker=/path/to/newer/libs/ld-linux.so.2
– 这个覆盖了被嵌入到可执行文件中的RTLD的路径 将这些选项提供给ld
方法通常是通过GCC的-Wl
选项。
-rpath=/path/to/newer/libs
变为:
-Wl,-rpath,/path/to/newer/libs
(注意=
被替换为)
--dynamic-linker=/path/to/newer/libs/ld-linux.so.2
变为:
-Wl,--dynamic-linker,/path/to/newer/libs/ld-linux.so.2
您应该从开发系统将/lib/ld-linux.so.2
复制到嵌入式设备上的/path/to/newer/libs/
。 您还应该复制libc.so.6
,数学库libm.so.6
以及可执行文件使用的或可能间接加载的所有其他库。 请注意, libc.so.6
和libm.so.6
实际上是名称类似于libc-2.<version>.so
的实际库的符号链接。 你应该复制这些库文件,并创建适当的符号链接,让每个人都高兴。
您可能有一些运气与LSB SDK( http://www.linuxfoundation.org/collaborate/workgroups/lsb/download )编译,这限制了可用于可执行文件的符号。