Files
TransPyC/includes/_withcontent.vp
T
TermiNexus dc9a2848c1 debug(_withcontent): 临时 [wdbg] 诊断 provider 栈运行时状态
TLS 守卫/strcmp/IR 均正确但 Test 9 仍 find 返回 NULL,加运行时诊断:
get_stack 打印 tls 索引与栈指针(观察是否每次 NEW)、push 打印 field/ptr/top、
find 打印 field/top/HIT。重编 Test 跑一轮后删除。
2026-08-15 06:51:50 +08:00

82 lines
3.0 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import t, c
from stdint import *
from w32.win32process import TlsAlloc, TlsGetValue, TlsSetValue
import stdlib
import stdio
import string
# Maximum provider stack depth (compiler verifies sufficiency; increase if needed)
_MAX_PROVIDER_DEPTH: t.CDefine = 32
@t.Object
class _ProviderStack:
"""Provider stack, stores pairs of field names and pointers."""
names: t.CArray[VOIDPTR, 32]
ptrs: t.CArray[VOIDPTR, 32]
top: UINT64
# TLS index (global; all threads share the same index)
_tls_index: ULONG = 0
@t.TLS
def _init_tls():
"""Initialize TLS index (executes once; subsequent calls are skipped)."""
global _tls_index
# 双保险:TPV 已正式实现 @t.TLS(函数级一次性守卫,首次执行后置
# __tls_init_done 标志,后续调用直接返回),此判重守卫保留以兼容
# 尚未重建的旧 TPV.exe。_tls_index 初始为 0(TlsAlloc 成功不会返回 0)。
if _tls_index == 0:
_tls_index = TlsAlloc()
def _get_stack() -> _ProviderStack | t.CPtr:
"""Obtain current thread's provider stack. Allocate one if none exists."""
_init_tls()
stack: _ProviderStack | t.CPtr = TlsGetValue(_tls_index)
stdio.printf("[wdbg] get_stack tls=%llu stack=%p\n",
t.CUInt64T(_tls_index), stack)
if stack == None:
stack = stdlib.malloc(_ProviderStack.__sizeof__())
string.memset(stack, 0, _ProviderStack.__sizeof__())
TlsSetValue(_tls_index, stack)
stdio.printf("[wdbg] get_stack NEW stack=%p\n", stack)
return stack
def _push_provider(field_name: str, ptr: t.CPtr):
"""Push a provider (field_name, ptr) onto the stack."""
stack: _ProviderStack | t.CPtr = _get_stack()
stdio.printf("[wdbg] push field=%s ptr=%p top=%lu\n",
field_name, ptr, stack.top)
if stack.top >= _MAX_PROVIDER_DEPTH:
stdio.printf("[with] ERROR: provider stack overflow (depth=%lu, max=%d), field '%s' not injected\n", stack.top, _MAX_PROVIDER_DEPTH, field_name)
return
stack.names[stack.top] = field_name
stack.ptrs[stack.top] = ptr
stack.top = stack.top + 1
def _pop_provider():
"""Pop the top provider entry from the stack."""
stack: _ProviderStack | t.CPtr = _get_stack()
if stack.top > 0:
stack.top = stack.top - 1
def _find_provider(field_name: str) -> t.CPtr:
"""Search for matching field_name starting from stack top.
Return associated pointer, or NULL if no match found."""
stack: _ProviderStack | t.CPtr = _get_stack()
stdio.printf("[wdbg] find field=%s top=%lu\n", field_name, stack.top)
for i in range(stack.top - 1, -1, -1):
# 字段名用 strcmp 内容比较:编译器对每次 create_global_string 生成
# 独立的字符串常量(TPV 不去重),push/find 的指针地址不同,
# 指针 == 永假会导致 provider 匹配失败(__mbuddy__ 注入不上)。
if string.strcmp((str)(stack.names[i]), field_name) == 0:
stdio.printf("[wdbg] find HIT i=%d ptr=%p\n", i, stack.ptrs[i])
return stack.ptrs[i]
return None