函数在运行时如何解析?

函数在运行时如何解析?

Linux 中的函数在运行时如何解析?它是纯粹基于名称和一些“符号表”,正如我想象的那样,还是某种硬编码的地址?我在网上读到,你必须为 Musl libc 和 glibc 重新编译,但它们不应该具有相同的符号导出吗?符号如何工作?

答案1

由于程序在运行时之前加载到内存中,因此函数映射到相对于基地址的某些内存地址。对函数的所有调用都被编译为相关的内存地址。符号表通常包含在二进制文件中,但为了调试目的将地址映射反转为人类可读的名称。尝试nm -D /usr/lib/libc.so.6典型的 Linux 安装来查看 glibc 的符号表。

在二进制兼容性方面,glibc 和 Musl 都实现了共享标准,但是有多种特性必须反映在它们自己的头文件中(因此为什么大多数 Linux 发行版中没有通用的标准库头文件包 - 它们而是与每个库捆绑在一起)。

来自 musl 的常见问题解答:

musl 与 glibc 兼容吗?

是和不是。在源代码和二进制级别上,musl 的目标是与 glibc 实现一定程度的功能兼容性,而不是 bug 兼容性。当使用 glibc 的应用程序无法针对 musl 进行编译时,原因通常是以下之一:

  • 假设包含一个标头将导致另一个不相关标头的符号被暴露。这是一个应用程序错误,修复它就像添加缺少的 #include 指令一样简单。
  • 使用 glibc 标头中的实现细节,这些细节不应该暴露给应用程序。这也是一个应用程序错误,通常可以通过搜索和替换来修复(例如,在源代码中将 __pid_t 替换为 pid_t)。
  • 使用未在 musl 中实现的接口。这只能通过使应用程序对接口的使用成为可选,或者通过扩展 musl 以支持缺失的接口来解决。

二进制兼容性受到更多限制,但随着 musl 的新版本,它会稳步提高。目前,一些 glibc 链接的共享库可以使用 musl 加载,但如果将 musl 放入 /lib/ld-linux.so.2 的位置,则除了最简单的 glibc 链接应用程序之外的所有应用程序都将失败。

相关内容