Files
TransPyC/work.md
T

12 KiB
Raw Blame History

TransPyC 会话交接:A 阻塞已修复 + 阻塞 B 根因定位(GSList 泛型方法分派)

交接日期:2026-09-04。供下一会话直接续接。

1. 已修复并验证(TPC/llvmlite 源码已改,未 commit)

1.1 阻塞 A:链式成员访问静默吞 if → element_class 补登记(已双重验证)

  • 现象:TPV 自举 SyntaxError 洪水;任何 name 实参 foo(b) 必失败。
  • 根因:跨模块 import 类布局中 rowptr[Token] 自引用字段被 stub 退化为 i8*(HEAD 以来既有稳态,非本次引入); HEAD 态 Token | t.CPtr 联合注解命中 import/class 字段收集的 BinOp 分支登记 element_class,char*→struct cast 可恢复; rowptr 重构后登记链断 → ps.cur.next.type == ... 求值静默 None → _HandleBoolOpLlvm 放 unreachable 后 return None → _HandleIfLlvm 吞掉 if 主体(keyword 分支从未生成)→ 控制流损坏。
  • 修复(TPC python 两处对称补丁):Subscript 字段收集分支增加 rowptr[裸结构](Name/Attribute slice 在 Gen.structs 或 class_sha1_map)登记 element_class:
    • lib/core/Handles/HandlesImports.py L1829-1850(import 类字段,如 Token.next)
    • lib/core/Handles/HandlesClassDef.py L841-863(本地类字段,如 Parser.cur)
  • 验证:全量重建(普通 122.75s)后 IR 中 _parse_call Name 分支三条件齐全(bitcast i8*→Token* + type==10 + op_subtype==11)、keyword 主体完整、无 unreachable; foo(b)/foo(b, k=5)/foo(b, 7) 解析通过(SyntaxError 洪水消失)。

1.2 DeepCopy bad-free(ASan 定位,已修复)

  • includes/llvmlite/__types.vp _DeepCopyDepth 的 case _: stdlib.free(new_ty) 对 MemBuddy(buddy) 分配的内存用 stdlib.free(只释放 malloc 块)→ 0xC0000374 / ASan bad-free。
  • 修复:改 pool.free(new_ty)(buddy 回收)。修复后崩溃点前移到阻塞 B(dump_ir param 链)。

2. 阻塞 B 根因已定位(未修复,下一会话主攻)

现象:翻译首个 include(stdint.vp)完成后 dump_ir → LLVMModule.PrintModule → param_get_ty 空指针崩(param 指针=垃圾)。

定位过程(DUMPDBG 插桩 + ASan):

  • printf(Translator 预注入 declare,Translator.vp L455-461)的 Params GSList 异常:Count=0 但 Head 非空、param 节点 Next=1、func.Next 也是非堆垃圾。
  • 铁证(output/625716485a97ad4e.ll L801-803,llvmlite/__function.vp function_add_param): params.append(param) 被编译为 bitcast GSList* → LinkedNode* + 调用 LinkedNode.append(linkedlist.vp 的兄弟类,双链树 48B)。 function_add_block 同样错误(L840-842)。
  • 根因链(TPC python 泛型方法分派 bug):
    1. GSList[T].append 泛型方法从未生成/特化(linkedlist 模块产物只有 LinkedNode.append;对照 list[T] 有特化方法);
    2. params: rowptr[GSList[Param]] 局部变量 var_struct_class 未登记(初值 func.Params 为 i8*,未命中 HandlesAnnAssign L538-541)→ ClassName=None;
    3. ObjVal 为 i8* → HandlesExprCall _HandleMethodCallLlvm L3055 FakeDuck 分支遍历所有类,选中第一个有 append 的类 = LinkedNode。
    4. LinkedNode.append(字段 parent/child/last_child/prev/next/child_count,48B)打在 24B GSList(Head/Tail/Count)上 → 写穿 24B(吻合 memhub DET 命中的 24B 块越界写,越界区为指针值)。
  • 下一步建议:对照 list[T](_list.vp)泛型方法特化注册机制,查 TPC 为何不给 GSList[T] 使用处生成 GSList[Param].append 特化; 候选入口:HandlesExprCall _try_complete_generic_specialization(L2523) / collect_class_methods(L2370) / 泛型类方法模板传播。

3. 环境状态

  • 源码改动(未提交):HandlesImports.py、HandlesClassDef.py(1.1);includes/llvmlite/__types.vp(1.2)。
  • includes/llvmlite/__module.vp 的 DUMPDBG 插桩已清理(内容与 HEAD 一致)。
  • TransPyV/output/TransPyV.exe 当前是带插桩残留的 ASan 版(3,140,096 B),下次验证前需全量重建还原(普通 122s / ASan ~190s)。
  • Test/Sha1Test/App/main.vp 已还原为原始 hashlib 用例;临时探针文件 _v*.vp/_a_probe.vp 已删;TransPyV/temp/_sha1*.log、_sha1main.bak.vp 可清理。

4. 调试方法备忘(重要,避免重复踩坑)

  • TPC ASan 构建:PATH 前置 D:\msys64\clang64\bin 后 python Projectrans.py --project ./TransPyV/project.json --clean --rebuild-includes --clear-cache --asan(~190s)。
  • TPV exe 的 stdout 重定向到文件会丢输出(WriteConsole/句柄缓存),必须控制台直跑观测;但控制台模式下 abort 会吞未 flush 的 printf——诊断 printf 后必须 stdio.fflush(None)。
  • 单文件 --src 模式翻译阶段缺类型上下文(int 等注解解析失败)是伪影,真实验证须跑工程(--project TransPyV/Test/*/project.vpj --phase 1)。
  • 复现崩溃:Sha1Test(import hashlib 链)与 TransPyV/Test/project.vpj(全量)phase1 均可在 ~10s 内复现 0xC0000374/AV。
  • 模块 sha1 → 源文件:TransPyV/temp/_sha1_map.txt(TPC 全量重建后刷新);运行期(TPV)模块 hash 由其自己内存表维护。

5. Commit 建议(conventional commits,中文,TransPyC 根仓库)

fix(core): rowptr[裸结构] 字段补登 class_member_element_class,修复链式成员访问静默吞 if(TPV 自举 SyntaxError 洪水根因)

fix(llvmlite): _DeepCopyDepth 兜底分支改用 pool.free 释放 buddy 内存(原 stdlib.free 致堆损坏)

阻塞 B 修复落定后再提交(含 GSList 分派修复)。


会话续接 2026-09-04(后半段):插桩清理 + 崩溃点前移复现(json/init.vp prescan alloca)

承接上文"阻塞 B"。本段未改 TPC/llvmlite 语义代码,完成取证与状态刷新。

6. 本段完成

  1. 清理全部残留 [DBG-TMP] 插桩(4 个文件)
    • TransPyV/App/lib/core/Gen/AssignGenMixin.vp(prescan var_ty/alloca.Ty 打印)
    • TransPyV/App/lib/core/Gen/Expr/ExprGenName.vp(nm alloca/Ty hex dump)
    • TransPyV/App/lib/core/Gen/Func/FuncGenDef.vp(translate_function_def 打印)
    • TransPyV/App/lib/core/Gen/Type/TypeGenResolve.vp(attr CUInt64T builtin/ctyp/found 打印)
  2. 全量重建验证:python Projectrans.py --project ./TransPyV/project.json --clean --rebuild-includes --clear-cache --asan 成功(~142s), 产物 TransPyV/output/TransPyV.exe(ASan),二进制扫描 DBG-TMP count=0。

7. 干净复现结果(重要,供续接)

命令:.\TransPyV\output\TransPyV.exe --project ./TransPyV/project.vpj --clear-cache --rebuild-includes --asan --run --detection → exit 1。

  • Phase1 翻译到 ./includes/json/__init__.vp([22/53])时崩溃,日志被 \r 进度覆盖/printf 中断截断,必须控制台直跑看 ASan。
  • ASan 栈(确定性):AssignGenMixin.translate_annassign_prescan → StmtGenDeclMixin.pre_scan_allocas → FuncGenDef.translate_function_def → Translator.translate_children → VarGenMixin._alloca_at_entry → build_alloca_at_entry(IRBuilder) → block_append_text → block_append_line READ access-violation @ 0x0308735d0002。
  • 模块 sha1(→源):625716485a97ad4e=includes/llvmlite/__function.vp、fba457abe40d6872=includes/llvmlite/__builder.vp、 b9ef07833ceba511=VarGenMixin、b024541f0bd472bc=AssignGenMixin、ddb2be6edcee9cb9=FuncGenDef(App)。
  • 与历史崩溃点同族:build_alloca_at_entry 读 0xFFFFFFFFFFFF(旧)→ dump_ir ensure_opaque_for_type 读 -1(中)→ 现 block_append_line 读 0x0308735d0002(新)。均为"block/Lines 链表对象被写坏或读取越界指针"。

8. 结论与下一步方向

  • 疑点收敛:json/init.vp 首个触发 AnnAssign 预扫描的函数(很可能是 JsonValue.__new__ 的 ptr: rowptr[JsonValue] = pool.alloc(...)) 的 entry block/Lines(GSList) 已损坏(或跨模块 BasicBlock/Function stub 字段偏移读歪)。memhub/stdint 等前序 include 同路径成功 → 数据相关损坏而非全局性。
  • 未决 todo(见前文):m2=定位 free list 重复 put 同一块写入者;m5=确认 LLVMType 对象创建即坏 vs allocator 污染。
  • 方向建议:
    1. 静态核对 includes/llvmlite/__function.vp block_append_line/GSList[T].append 是否仍错分派到 LinkedNode.append(上段"阻塞 B"理论——本段已证容器/append 大多数场景正常,需确认 json 路径是否被 48B 写穿 24B GSList);
    2. 查 json/init.vp new 翻译前是否有跨模块类型/结构体注册把 entry block 区域写坏;
    3. 若需再插桩:改 includes 须 TPC 全量重建(~142s)生效(include 代码编译进 exe);插桩须 stdio.fflush(None),且 stdout 重定向会丢进度(用 \r),ASan 报告须控制台直跑。

9. 教训备忘

  • Grep/ripgrep 工具会漏扫被 ignore 规则覆盖的目录(本次 Gen/Type/TypeGenResolve.vp 残留 DBG 即因此漏检); 排查残留/全树关键字时用 python 全文件扫描(os.walk + 字节查找)兜底。
  • exe 是否含插桩可用 python -c 二进制 find 快速验证(DBG-TMP count)。

会话续接 2026-09-04(第三段):MEMDBG 插桩完成(等全量重建验证)

10. 本段完成

  1. 汇报复查:TPC ASan 重建成功(exe 3,101,696B,插桩标记 count=0);TPV 干净复现仍崩 (1.log:READ AV @ 0x02ab4c870002,栈 = block_append_line → block_append_text → IRBuilder.build_alloca_at_entry → VarGenMixin._alloca_at_entry → translate_annassign_prescan → pre_scan_allocas → translate_function_def,与 §7 完全同族)。崩溃模块无法从重定向日志确认 (stdout 丢 flush,"memhub.vp" 只是最后一条 INFO)。
  2. 静态核对排除 LinkedNode 误分派(重要):本次全新产物 output/*.ll 中
    • block_append_line→GSList[Line].append(625716485a97ad4e.ll L1008)、 function_add_param→GSList[Param].append(L805)、function_add_block→GSList[BasicBlock].append(L843);
    • 全 output 目录 零实际 call LinkedNode.append(仅 declare)。 → 阻塞 B 旧理论(GSList.append 误分派 LinkedNode / 48B 写穿 24B)已排除; 崩溃是 block/Lines 对象进入前已被上游损坏(寄存器 rdx=0x4bec0f0002≈(block<<1)|2 野值)。
  3. MEMDBG 插桩(includes/memhub.vp,未提交,待 TPC 全量重建生效):
    • MEMBUDDY_DBG=1 开关(L56-62)+ 4 处改动(注释里有清单): ① alloc 采样分支:新出块仍残留同 order free list → 报错退出(重复 put 实锤); ② free:归还前同 order free list 已含本块 → 报错退出(double-put); ③ free:无效/悬空 ptr(池内且 header 偶数=已释放)→ 报错退出(原静默吞); ④ 既有 [DET] 分配重叠 / _det_probe 下溢、越界写 exit 前全部补 stdio.fflush(None) ——此前这些 printf 因 stdout 重定向/abort 被吞,可能早已命中而 1.log 看不见。
    • 均 [MEMDBG]/[DET] 前缀 + fflush,重定向到文件也能保留,可直接 .\TransPyV\output\TransPyV.exe ... > 2.log 后 grep。
  4. 验证方法:TPC 全量重建(--clean --rebuild-includes --clear-cache --asan,~142s)后跑 .\TransPyV\output\TransPyV.exe --project ./TransPyV/project.vpj --clear-cache --rebuild-includes --asan --run --detection, 观察是否出现 [MEMDBG] 重复归还 / alloc 重复出块 / 悬空 free / [DET] 重叠或越界写。
    • 若三类 [MEMDBG] 都不触发而仍 AV:指向"stale 指针持活块"场景(free 合法但过早/ 双 owner 复用)或跨模块字段偏移写歪——下一步看是否在 free 后立即对同块 alloc 做 "上一 owner 仍在用"追踪(检测模式已做 free 后 0xCD 填充,可观察崩溃值是否 0xCD 系)。

11. 环境状态

  • 源码改动(未提交):HandlesImports.py、HandlesClassDef.py(§1.1);includes/llvmlite/__types.vp(§1.2); includes/memhub.vp(§10 MEMDBG 插桩)。
  • TransPyV/output/TransPyV.exe(ASan 3,101,696B)为无 MEMDBG 插桩的上一版,需全量重建后验证。