12 KiB
12 KiB
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.pyL1829-1850(import 类字段,如 Token.next)lib/core/Handles/HandlesClassDef.pyL841-863(本地类字段,如 Parser.cur)
- 验证:全量重建(普通 122.75s)后 IR 中
_parse_callName 分支三条件齐全(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.vpL455-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):
GSList[T].append泛型方法从未生成/特化(linkedlist 模块产物只有 LinkedNode.append;对照 list[T] 有特化方法);params: rowptr[GSList[Param]]局部变量 var_struct_class 未登记(初值 func.Params 为 i8*,未命中 HandlesAnnAssign L538-541)→ ClassName=None;- ObjVal 为 i8* → HandlesExprCall
_HandleMethodCallLlvmL3055 FakeDuck 分支遍历所有类,选中第一个有 append 的类 = LinkedNode。 - 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. 本段完成
- 清理全部残留
[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 打印)
- 全量重建验证:
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_lineREAD 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 污染。
- 方向建议:
- 静态核对
includes/llvmlite/__function.vp block_append_line/GSList[T].append 是否仍错分派到 LinkedNode.append(上段"阻塞 B"理论——本段已证容器/append 大多数场景正常,需确认 json 路径是否被 48B 写穿 24B GSList); - 查 json/init.vp new 翻译前是否有跨模块类型/结构体注册把 entry block 区域写坏;
- 若需再插桩:改 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-TMPcount)。
会话续接 2026-09-04(第三段):MEMDBG 插桩完成(等全量重建验证)
10. 本段完成
- 汇报复查: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)。
- 静态核对排除 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 野值)。
- 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。
- 验证方法: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 插桩的上一版,需全量重建后验证。