我想做的是在 glibc 中修复 Y2038 问题。 我在我的 Ubuntu 18.04 VM 中使用 buildroot 2022.02.2 来交叉编译 32 位 ARM CPU。 我读到添加额外的标志 _FILE_OFFSET_BITS=64 和 _TIME_BITS=64 应该可以做到这一点,但我得到这样的构建错误
/tmp/cclzLgs6.s: 汇编程序消息:/tmp/cclzLgs6.s:138:错误:符号"__sigtimedwait64"为 已定义
2.34 中是否支持 Y2038 问题,或者它是否正在进行中? 或者也许我做错了什么,比如错过了一些标志?
谢谢 卡塔林
您可以执行以下操作来获取 Y2038 安全构建根 32 位 ARM 系统:
- 在 https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/downloads 使用预编译的 ARM 工具链。版本 11.2-2022.02 由 GCC 11.2 和 glibc 2.34 组成。(_TIME_BITS=64 选项是在 glibc 2.34 中引入的。
- 使用版本为>= 5.1 的 Linux 内核。 https://sourceware.org/pipermail/libc-alpha/2021-August/129718.html 说需要 5.1 才能完全支持 64 位时间。
- 在 https://github.com/buildroot/buildroot/commit/6e33e5908086a511294296f317f6e6f86fa84b1d 年曾尝试在 buildroot 中启用系统范围的 _TIME_BITS=64,但后来由于未能构建某些软件包而在 https://github.com/buildroot/buildroot/commit/dd170f0cbad729dba4193b2b20e3de0a7010d485 年恢复。您仍然应该做的是根据第一个补丁添加 _TIME_BITS=64。
- 对于某些未定义_FILE_OFFSET_BITS的包,特别是 zlib 包和在其代码中嵌入 zlib 的包,您可能会遇到构建错误。此处的简单解决方法是修改这些包中的代码,以便在未定义_FILE_OFFSET_BITS时也进行 undef _TIME_BITS。这似乎在我看过的所有情况下都有效,因为受影响的编译单元无论如何都不会使用任何时间函数。
例如,将此补丁作为 0002-time-bits.patch 放入 buildroot/package/libzlib/中:
--- a/gzguts.h
+++ b/gzguts.h
@@ -9,6 +9,7 @@
# endif
# ifdef _FILE_OFFSET_BITS
# undef _FILE_OFFSET_BITS
+# undef _TIME_BITS
# endif
#endif
这是必需的,因为 glibc 标头中有一个断言,当 _TIME_BITS 为 64 但_FILE_OFFSET_BITS不是 64 时出错。
更新:
新发布的 zlib 1.3 版本包含上述补丁 (https://github.com/madler/zlib/commit/a566e156b3fa07b566ddbf6801b517a9dba04fa3)。
我注意到的一件事是,可以从他们的网站下载的预编译的ARM工具链与内核v4.20.13中的Linux内核头捆绑在一起。在某些情况下,这些旧标头与 _TIME_BITS=64 不兼容,例如 SO_TIMESTAMP/SCM_TIMESTAMP 的使用,因为这些旧标头定义了不正确的(旧)整数。我在运行 btmon 记录器时通过查看损坏的时间戳注意到了这一点。我决定使用更新的 Linux 内核标头构建自己的工具链,这些标头针对我实际使用的 Linux 内核版本。
幸运的是,由于自动构建脚本和 ARM 工具链的每个版本提供的说明,从头开始构建工具链相对简单,可以通过单击相关下载部分底部的"发行说明"链接找到这些说明。这些说明可以在"使用 Linaro 的 ABE 从源代码构建 Linux 托管工具链"下找到。该示例适用于arm-gnu-toolchain-aarch64-none-elf
但相应的说明也适用于arm-gnu-toolchain-arm-none-linux-gnueabihf
。
在下载的清单文件中,我将linux_revision=v4.20.13
更改为linux_revision=v6.3
(这是我的目标内核版本)并删除了linux_md5sum
行(我懒得找出校验和)。出于某种非常奇怪的原因,与预编译的已发布二进制文件中使用的清单相比,示例清单中的gcc_stage2_flags
显然不同。值得注意的是,由于示例清单文件中--disable-libatomic
,libatomic 不包括在内。但是许多 buildroot 包都需要 libatomic,例如需要对大于 8 字节的对象执行原子操作的包,或者恰好链接到 libatomic.so 的包。为了更好地与二进制版本保持一致,我从gcc_stage2_flags
中删除了--disable-libatomic --without-cloog --without-isl --disable-libgomp --disable-libquadmath
(但没有触及gcc_stage1_flags
)。
用这个新工具链替换预编译的工具链后,btmon 现在会显示正确的时间戳。