You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于LLVM的自制编译器生成代码引发指针算术相关页故障求助

自制LLVM编译器生成代码引发页故障问题定位

问题概述

基于LLVM搭建的自制编译器在开发专属操作系统时触发页故障。页故障由memeq函数触发,但根源是tarLookup函数传递给memeq的ptr指针异常指向代码段(地址高于0xFFFFFFFFFF...)。第一次循环中memeq运行完全正常,但执行特定指针算术表达式后,下一次循环传递给memeq的指针地址完全错误。

关键代码细节

生成的LLVM IR代码

define i32 @tarLookup(ptr %archive, ptr %filename, ptr %out) {
entry:
  %fz = alloca i32, align 4
  %ptr = alloca ptr, align 8
  %archive1 = alloca ptr, align 8
  store ptr %archive, ptr %archive1, align 8
  %filename2 = alloca ptr, align 8
  store ptr %filename, ptr %filename2, align 8
  %out3 = alloca ptr, align 8
  store ptr %out, ptr %out3, align 8
  %archive4 = load ptr, ptr %archive1, align 8
  store ptr %archive4, ptr %ptr, align 8
  br label %cond

cond:
  %ptr5 = load ptr, ptr %ptr, align 8
  %tmpint = ptrtoint ptr %ptr5 to i64
  %tmpextendr = sext i32 257 to i64
  %tmp = add nsw i64 %tmpint, %tmpextendr
  %calltmp = call i1 @memeq(i64 %tmp, ptr @0, i32 5)
  br i1 %calltmp, label %loop, label %exit

loop:                                             ; preds = %cond
  %ptr6 = load ptr, ptr %ptr, align 8
  %tmpint7 = ptrtoint ptr %ptr6 to i64
  %tmpextendr8 = sext i32 124 to i64
  %tmp9 = add nsw i64 %tmpint7, %tmpextendr8
  %calltmp10 = call i32 @oct2bin(i64 %tmp9, i32 11)
  store i32 %calltmp10, ptr %fz, align 4
  %filename11 = load ptr, ptr %filename2, align 8
  %calltmp12 = call i32 @strlen(ptr %filename11)
  %tmp13 = add nsw i32 %calltmp12, 30
  br label %cond15

cond15:                                           ; preds = %loop
  %ptr16 = load ptr, ptr %ptr, align 8
  %filename17 = load ptr, ptr %filename2, align 8
  %filename18 = load ptr, ptr %filename2, align 8
  %calltmp19 = call i1 @strlen(ptr %filename18)
  %calltmp20 = call i1 @memeq(ptr %ptr16, ptr %filename17, i32 %calltmp19)
  br i1 %calltmp20, label %if, label %exit14

if:                                               ; preds = %cond15
  %ptr21 = load ptr, ptr %ptr, align 8
  %tmpint22 = ptrtoint ptr %ptr21 to i64
  %tmpextendr23 = sext i32 512 to i64
  %tmp24 = add nsw i64 %tmpint22, %tmpextendr23
  %out25 = load ptr, ptr %out3, align 8
  store i64 %tmp24, ptr %out25, align 4
  %fz26 = load i32, ptr %fz, align 4
  ret i32 %fz26

exit14:                                           ; preds = %cond15
  %ptr27 = load ptr, ptr %ptr, align 8 ;<--- 问题关联表达式
  %fz28 = load i32, ptr %fz, align 4
  %tmp29 = add nsw i32 %fz28, 511
  %tmp30 = sdiv i32 %tmp29, 512
  %tmp31 = add nsw i32 %tmp30, 1
  %tmp32 = mul nsw i32 %tmp31, 512
  %tmpint33 = ptrtoint ptr %ptr27 to i64
  %tmpextendr34 = sext i32 %tmp32 to i64
  %tmp35 = add nsw i64 %tmpint33, %tmpextendr34
  store i64 %tmp35, ptr %ptr, align 4
  br label %cond

exit:                                             ; preds = %cond
  ret i32 0
}

注:IR命名不够规范,后续了解到LLVM不强制要求默认命名规则。

触发问题的C语言表达式

ptr += (((filesize + 511) / 512) + 1) * 512;

可疑目标代码指令

编译器生成的目标代码中,以下指令被怀疑是问题根源:

and    $0xfffffe00,%eax

即使关闭所有优化,该指令仍会生成;而用clang编译相同C代码时,不会生成这条指令。

环境与验证细节

  • 目标平台:x86_64-elf
  • 链接器:x86_64-elf-ld(源码编译)
  • 引导加载程序:BOOTBOOT
  • 验证情况:传递给tarLookup的初始指针地址正确,第一次循环可正常运行(通过内核串口输出确认),问题明确出在上述指针算术表达式执行后。
  • 调试限制:尚未给编译器添加调试信息,无法在QEMU中使用GDB调试。

相关参考

  • USTAR格式规范(osdev相关文档)
  • 完整生成的汇编代码
  • 实现功能的C代码

内容的提问来源于stack exchange,提问作者Aryaman Jain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 22:57:33