为ARMv6/Thumb(arm1136j-s)构建Linux内核时出现异常汇编输出
嵌入式模拟器zImage解压失败:汇编代码异常篡改error函数
我使用Buildroot 2023.02.7为嵌入式模拟器生成Linux镜像,执行arm/boot/compressed/misc.c中的decompress_kernel函数时解压失败,核心问题是生成的汇编代码存在异常——错误地用r0中的output_data指针篡改了error函数的代码。
相关C代码
void decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, unsigned long free_mem_ptr_end_p, int arch_id) { int ret; output_data = (unsigned char *)output_start; free_mem_ptr = free_mem_ptr_p; free_mem_end_ptr = free_mem_ptr_end_p; __machine_arch_type = arch_id; #ifdef CONFIG_ARCH_EP93XX ep93xx_decomp_setup(); #endif arch_decomp_setup(); putstr("Uncompressing Linux..."); ret = do_decompress(input_data, input_data_end - input_data, output_data, error); if (ret) error("decompressor returned an error"); else putstr(" done, booting the kernel.\n"); }
异常汇编代码(zImage加载到0x2070'0000)
20700920: b5f0 push {r4, r5, r6, r7, r14} 20700922: 4e27 ldr r6, [pc, #156] @ (0x207009c0) 20700924: 4c27 ldr r4, [pc, #156] @ (0x207009c4) 20700926: 447e add r6, r15 20700928: 5937 ldr r7, [r6, r4] <--- 将'error'函数地址存入r7 2070092a: 2455 movs r4, #85 @ 0x55 <--- 将字符'U'存入r4 2070092c: 6038 str r0, [r7, #0] <--- 用r0中的output_data指针篡改'error'函数的代码 (...)
编译细节与已尝试操作
- 原本指定使用
-O0优化,但实际编译参数显示为-O2,Buildroot未遵守设置的优化级别 - 使用Buildroot构建的GCC 12.x、binutils 2.38、musl工具链,中间汇编阶段已出现相同问题
- 尝试过调整多种Thumb代码生成配置、强制关闭优化,问题仍未解决
排查建议
- Buildroot内核编译配置检查:
- 确认
BR2_TARGET_OPTIMIZATION是否正确设置为-O0,同时检查内核Makefile中是否存在强制覆盖优化级别的逻辑(比如KBUILD_CFLAGS中硬编码的-O2) - 核对
CONFIG_CPU_THUMBONLY等Thumb相关配置是否与目标模拟器架构匹配,部分ARM架构对Thumb代码的内存访问有严格对齐要求
- 确认
- error函数定义与调用验证:
- 检查
error函数是否被错误标记为__attribute__((section(".data")))或类似属性,导致代码段被放到数据段从而被误写 - 确认
do_decompress的第四个参数类型是否与error函数签名匹配,避免因函数指针类型不匹配导致的汇编生成错误
- 检查
- 工具链兼容性验证:
- 替换为官方预编译的ARM交叉工具链(如Linaro GCC 12.x)重新编译,排除Buildroot自制工具链的潜在bug
- 检查binutils的链接脚本,确认代码段(
.text)是否被错误设置为可写,正常情况下代码段应设为只读
- 内核压缩配置调整:
- 确认使用的压缩算法(gzip/lz4等)是否与模拟器架构兼容,尝试切换压缩算法验证问题是否消失
- 检查
CONFIG_KERNEL_COMPRESSION配置,确保未启用模拟器不支持的压缩特性
内容的提问来源于stack exchange,提问作者svc 1.380649
相关产品推荐
相关产品推荐

