fix(phase1): 加 translate 后存活块检查 + printf Params 链创建即校验 + dump 函数清单诊断

builtins.vp dump 卡死已定位:printf.fmt Param 的 Next 被越界写破坏成环
(Params.Count=1 但遍历超限)。本次加运行时证据收集:
1. printf declare 创建后立即打印 fmt Param 地址/Next(区分创建即坏 vs
   后续被破坏)
2. dump_ir(OUTPUT_STUB) 打印模块函数清单+param0/next(确认创建上下文)
3. translate 返回后、dump 前 mb.check_alive_blocks(mark1)(抓 translate
   期间写穿破坏的块 header/canary,rc=6 定位越界写穿文件)
This commit is contained in:
TermiNexus committed 2026-08-18 08:17:54 +08:00
1 parent 43470b6e4a
commit 0cb0a12810
2 files changed
+41

No files matched your search

+28
View File
@@ -352,6 +352,14 @@ class Translator:
return 1
llvmlite.add_param(pool, printf_func, i8_ptr_ty, "fmt")
printf_func.IsVarArg = 1
# 诊断(builtins.vp dump 卡死根因排查):printf.fmt Param 创建后立即
# 校验其 Next——区分"创建即损坏"(create_declare/add_param 环节问题)
# 与"后续被越界写破坏"(dump 时遍历成环)。next=0 为正常。
dbg_p0: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(printf_func)
if dbg_p0 is not None:
dbg_p0n: llvmlite.Param | t.CPtr = llvmlite.param_get_next(dbg_p0)
stdio.printf("[DIAG] printf.fmt 创建后: param=%llu next=%llu\n",
t.CUInt64T(dbg_p0), t.CUInt64T(dbg_p0n))
# 声明 LLVM va_start/va_end intrinsic(供 *args 函数体内使用)
# declare void @llvm.va_start(i8*)
@@ -590,6 +598,26 @@ class Translator:
return
if _mbuddy is None:
return
# 诊断(builtins.vp dump 卡死根因排查,仅 stub 模式打印一次):
# 模块函数清单 + 每个函数首个参数地址/Next 值(步数上限防成环死循环)。
# 确认 printf declare 的创建上下文与 Params 链损坏状态。
if mode == llvmlite.OUTPUT_STUB:
dbg_f: llvmlite.Function | t.CPtr = llvmlite.module_get_func_head(self.Module)
dbg_steps: int = 0
while dbg_f is not None:
dbg_steps += 1
if dbg_steps > 100000:
stdio.printf("[DIAG] 模块函数链遍历超限(dump_ir 诊断)\n")
stdlib.exit(1)
dbg_name: str = llvmlite.function_get_name(dbg_f)
dbg_p: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(dbg_f)
if dbg_p is not None:
dbg_pn: llvmlite.Param | t.CPtr = llvmlite.param_get_next(dbg_p)
stdio.printf("[DIAG] 模块函数: %s param0=%llu next=%llu\n",
dbg_name, t.CUInt64T(dbg_p), t.CUInt64T(dbg_pn))
else:
stdio.printf("[DIAG] 模块函数: %s (无参数)\n", dbg_name)
dbg_f = llvmlite.function_get_next(dbg_f)
buf[0] = '\0'
llvmlite.LLVMModulePrint(buf, size, self.Module, _mbuddy, mode)
+13
View File
@@ -827,6 +827,19 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
failed += 1
continue
# 诊断(builtins.vp dump 卡死根因排查):pre_rc 哨兵在 translate 前,
# 覆盖不到 translate 期间的 AST/IR 写穿。dump 前立即检查存活块
# header/canary(rc=6 块尾 canary 损坏=越界写穿数据区),把"dump
# 时链表成环卡死"变成"定位到 translate 期间写穿发生的文件"。
post_rc: t.CInt = mb.check_alive_blocks(mark1)
if post_rc != 0:
fb: str = VLogger.fmt_buf()
if fb is not None:
viperlib.snprintf(fb, 1024,
"内存损坏(translate后存活块, rc=%d): %s", post_rc, file_path)
VLogger.error(fb, "Phase1")
stdlib.exit(1)
# dump stub IR(declarations only)
PHASE1_IR_SIZE: t.CSizeT = 1048576
stub_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE)