4

我目前正在努力集成 ARM64 ftrace 补丁,以实现对“带寄存器的动态 ftrace”的全面支持。具体来说,我正在为 Pixel 3a (sargo) 开发 4.9.200 内核版本,我所指的补丁如下:

上述补丁需要支持'-fpatchable-function-entry=2' GCC 8.x 编译选项,我将支持集成到 GCC 9.1 以构建内核的原因。使用此选项编译内核会在每个可跟踪函数的序言中正确插入 2 条 ARM64 NOP 指令。

问题是使用移植的“带寄存器的动态 ftrace”补丁(4.8.x 和 4.20.x 非常相似)编译的内核在从内核态到用户态的转换过程中崩溃,特别是在调用 'do_execve ()' 产生'/init'。崩溃内核中的 ftrace 初始化和整个初始引导序列与正确引导的内核相同(例如,具有“在没有寄存器的情况下启用动态 ftrace”支持的内核)。

详细日志('debug'、'ignore_loglevel'、'initcall_debug' 和增加的日志缓冲区移位)已启用,并且崩溃实际上并未显示失败的原因(例如无效指令执行、无效内存访问)。

已尝试启用完整的 KASAN+KCOV 支持,但由于生成的 LZ4 图像太大而无法由 Pixel 3a 引导加载程序加载,导致“失败(远程:'错误验证收到的 boot.img: Buffer Too Small')" fastboot 错误。可以刷新引导映像,但在崩溃后设备进入引导循环阶段,在该阶段无法从“/sys/fs/pstore”获取日志,因为工作引导映像的新闪存导致崩溃日志刷新.

作为额外的尝试,4.8.x 补丁已移植到 4.9.x 内核,4.20.x 补丁已移植到 HiKey620 板(基于 ARM64)的 4.19.x 内核,从而在两者中都成功启动案例(使用从“master”分支编译的最新 AOSP)并且可以通过内核模块中的 API 使用“带寄存器的动态 ftrace”。在这一点上,我一直想知道 HiKey620 板和 Pixel 3a 的 4.9.x 内核之间可能有什么区别。

我也一直在使用内核选项“CONFIG_DEBUG_RODATA”来禁用只读内存强制(例如这个老问题https://github.com/raspberrypi/linux/issues/2166暗示 ARM 内核在 ftrace 时崩溃启用,结果是只读内存问题);在我的情况下,完整的启动顺序工作正常,所以我排除了它作为可能的原因。

为了确保'/init'(实际上是'/system/bin/init')二进制文件根本不被执行,我在入口点('int main(..) '的'init / main.cpp'文件)并且引导过程显然没有达到那个点,所以这导致我排除了'第一'和'第二'初始化用户级阶段的设置功能的问题。

以下链接指向崩溃内核(带有“带寄存器的动态 ftrace”的 4.9.200)和引导内核(带有“不带寄存器的动态 ftrace”的 4.9.200)的详细日志:

调试问题的最佳方法是什么?是否有任何明显的问题导致我失踪?

更新 1

在使用 Clang10 编译内核并启用使用 -Os 编译标志来缩小内核映像大小的“CONFIG_CC_OPTIMIZE_FOR_SIZE”选项后,我设法让 KASAN+KCOV 构建工作。启用“CONFIG_GZIP”会进一步减小大小,使 fastboot 能够正确引导内核而无需闪烁。Clang10 已从源代码编译,现在包含对“-fpatchable-function-entry”选项的完全支持。即使在这种情况下,所获得的崩溃日志也没有暗示任何特定的事情(例如,没有 KASAN 崩溃或警告)。

在寻找类似问题时,我遇到了看起来非常相似的问题,但没有解决方案:https ://unix.stackexchange.com/questions/243515/why-cant-the-kernel-run-init 。

更新 2

静态编译“/system/bin/init”二进制文件可以正确执行 FirstStageMain 函数(其日志与正确启动的内核相同)。现在,崩溃从前面提到的“do_execve()”调用转移到 FirstStageMain 函数真正末尾的“execv()”调用,该函数应该再次执行“/system/bin/init”二进制文件(使用2SI ramdisk SAR 引导逻辑),但使用不同的 argv[1] = "selinux_setup" 参数。

4

1 回答 1

0

该问题与在 Pixel 3a 4.9.200 内核上编译 vDSO 共享库时禁用“-fpatchable-function-entry=2”选项的必要性有关。

该更改已由主线内核中的提交28b1a824a4f44da46983cd2c3249f910bd4b797b引入,但在我试图向后移植的原始补丁中不存在,并且根据 HiKey620 板的实验,它甚至不是所有必需的设备。

内核的其他组件是在禁用选项的情况下构建的,当涉及到生成的程序集时,它们似乎都有特殊需求(例如,特定布局或使用不符合 ABI 的寄存器可能会在某些情况下损坏仪表)。

检查主线内核以删除“CC_FLAGS_FTRACE”变量似乎是绝对需要避免使用它的组件的一个很好的指标。

于 2020-05-18T17:53:07.557 回答