8

我在 Ubuntu 12.04 上构建了一个应用程序,并尝试在嵌入式系统上运行它。我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

嵌入式设备上存在的 libc6 版本是 2.8.90。在\lib设备上的目录中,我有 2 个库

libc-2.8.90.so
libc.so.6

当我将应用程序复制到嵌入式设备上时,出现以下错误

/usr/lib/libc.so.6: version `GLIBC_2.15` not found (required by ./ServerSocketApp)

我知道如果可能的话,当我在我的开发机器上构建应用程序时,我需要强制它链接到与嵌入式设备上存在的相同版本的 libc6。我遇到的问题是我根本不知道该怎么做。我现在找到的任何答案对我来说都毫无意义。我需要将某些选项传递给 g++ 以使其链接到版本 2.8.90 吗?

绝望中,我在想是否可以将我的开发机器上的 libc 复制到嵌入式设备上,而不是已经存在的并希望最好???我似乎无法在网上找到任何简单的文档来解释你是如何做到这一点的,所以任何建议都会非常受欢迎,因为我在这里扯头发。

4

3 回答 3

9

好的,这里有一个更长的解释,但要小心。我仍然强烈建议您设置一个 chrooted 环境以匹配嵌入式设备上可用的环境,并在构建过程的最后阶段使用它。

您应该了解动态链接的 ELF 可执行文件是如何加载和执行的。有一种称为运行时链接编辑器(RTLD) 的东西,也称为动态链接器,它负责加载所有必要的动态链接库、修复重定位等。动态链接器的名称/lib/ld-linux.so.2在 32 位 Linux 系统上 glibc2与. 动态链接器与库的耦合非常紧密,通常只能处理该库的匹配版本。它的路径也被链接器硬编码到可执行文件中(通常/lib64/ld-linux-x86-64.so.2glibc2glibc2ld,由编译器隐式调用以进行链接)。您只需执行以下操作即可轻松检查最后一条语句的有效性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与系统上安装的版本不同的版本,可执行文件将在其中运行,您应该使用以下一组选项将您的代码链接到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通常是通过-WlGCC 的选项。

-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.6libm.so.6实际上是指向真实库的符号链接,其名称类似于libc-2.<version>.so. 您应该复制这些库文件并创建适当的符号链接以使每个人都满意。

于 2012-07-09T16:57:27.310 回答
1

使用 LSB SDK ( http://www.linuxfoundation.org/collaborate/workgroups/lsb/download )编译时可能会有一些运气,它限制了可执行文件可用的符号。

于 2012-07-09T15:16:52.557 回答
1

这从根本上是不正确的。虽然您可能能够拼凑出一种链接旧 libc 的方法,但问题在于您的环境设置。

当您为嵌入式系统开发应用程序时。你在主机上这样做。通常,主机和嵌入式设备不在同一架构上。例如,您的主机通常是在 x86 上运行的台式机/笔记本电脑,而嵌入式系统可能在 ARM 上。如果您碰巧与您的嵌入式设备使用相同的架构,那纯属巧合。标准实践环境设置仍应遵循:

  • 主机应该有一个工具链设置来交叉构建应用程序到嵌入式架构
  • 主机应该有您的嵌入式设备存在的完整 rootfs 的副本。这将包含您的交叉工具将用于为嵌入式系统编译应用程序的所有库

如果您以这种方式设置它。开发将很容易。您将能够设置简单、干净的 make 文件来构建您的应用程序,然后只需scp将二进制文件转移到嵌入式系统并运行即可。

于 2012-07-09T18:25:16.057 回答