fix(TPC): _get_member_offset 短名规范化+跨模块懒加载+fast-fail
class_members/class_vtable/class_parent 以短名注册而调用方可能传 sha1 全名,且 class_members 未随 struct 就绪,导致查表全 miss 静默返回 None → 变量 alloca 未初始化 → 运行期读 0xffffffffffffffff 崩溃(HandlesImports.HandleImport imp.names)。修复:统一短名解析、主动懒加载 class_members、找不到字段改为 fast-fail raise 暴露 class_members/struct 真实状态。
This commit is contained in:
1 parent
2129430446
commit
cb557c84ce
1 file changed
+35
-1
@@ -237,6 +237,13 @@ class FuncGenMixin:
|
||||
# 此处检测冲突,加载正确模块的 class_members 并以 sha1 前缀全名缓存。
|
||||
_ResolvedClass: str = ClassName if ClassName else ''
|
||||
if ClassName:
|
||||
# 统一短名解析(治本修复 2026-08-10):struct/class_members/class_vtable/
|
||||
# class_parent 均以短名注册(跨模块加载 HandlesImports L1604),而调用方
|
||||
# 可能传入带 sha1 前缀的全名(如 "f47f88ae6545965a.Import"),导致下方
|
||||
# 查表全部 miss 返回 None → _gep_and_Load_member 静默返回 None →
|
||||
# AnnAssign InitValue 为 None → 变量 alloca 未初始化 → 运行期读垃圾指针。
|
||||
ClassName = self._extract_short_name(ClassName)
|
||||
_ResolvedClass = ClassName
|
||||
_ClassSha1Map: dict[str, str] = getattr(self, 'class_sha1_map', {})
|
||||
_ExpectedSha1: str | None = _ClassSha1Map.get(ClassName)
|
||||
if _ExpectedSha1:
|
||||
@@ -289,6 +296,18 @@ class FuncGenMixin:
|
||||
isinstance(_first_elem.pointee, ir.IntType) and _first_elem.pointee.width == 8)
|
||||
if not _has_parent or _is_vtable_ptr:
|
||||
base = 1
|
||||
if ClassName and ClassName not in self.class_members and self._Trans and hasattr(self._Trans, 'ImportHandler'):
|
||||
# 跨模块 class_members 懒加载:struct 已从 stub 加载但 class_members
|
||||
# 可能尚未从 .vpi 填充(vpi/stub 就绪时序不一致),主动按类 sha1 加载。
|
||||
_Sha1sForLoad: dict[str, str] = getattr(self, 'class_sha1_map', {})
|
||||
for _mod_name_lz, _mod_sha1_lz in _Sha1sForLoad.items():
|
||||
try:
|
||||
self._Trans.ImportHandler._TryLoadClassMembersFromPyi(
|
||||
ClassName, f"{_mod_sha1_lz}.stub.ll", self)
|
||||
except Exception:
|
||||
continue
|
||||
if ClassName in self.class_members and len(self.class_members[ClassName]) > 0:
|
||||
break
|
||||
if _ResolvedClass and _ResolvedClass in self.class_members:
|
||||
for i, (name, _) in enumerate(self.class_members[_ResolvedClass]):
|
||||
if name == field_name:
|
||||
@@ -444,7 +463,22 @@ class FuncGenMixin:
|
||||
if _num_inherited_final == 1:
|
||||
# 单继承字段,偏移 = base(vtable 之后第一个位置)
|
||||
return base + 0
|
||||
return None
|
||||
# fast-fail(治本修复 2026-08-10):字段未找到不再静默返回 None。
|
||||
# 静默 None 会让调用方(_gep_and_Load_member L26-27)直接 return None,
|
||||
# AnnAssign InitValue 变 None → 变量 alloca 未初始化 → 运行期读垃圾指针
|
||||
# (如 HandlesImports.HandleImport 的 imp.names → 0xffffffffffffffff 崩溃)。
|
||||
# 抛出编译错误,暴露 class_members/struct 的真实状态便于定位根因。
|
||||
_members_diag: list = self.class_members.get(ClassName, []) if ClassName else []
|
||||
_struct_diag: str = 'not-registered'
|
||||
if ClassName and ClassName in self.structs:
|
||||
_st_diag = self.structs[ClassName]
|
||||
if isinstance(_st_diag, ir.IdentifiedStructType):
|
||||
_struct_diag = f"{len(_st_diag.elements)} elems" if _st_diag.elements is not None else 'opaque'
|
||||
_member_names_diag: list = [n for n, _ in _members_diag][:16]
|
||||
raise KeyError(
|
||||
f"[fast-fail] 属性 '{field_name}' 在类 '{ClassName}' 中找不到"
|
||||
f"(class_members={len(_members_diag)} 个: {_member_names_diag}, struct={_struct_diag})"
|
||||
)
|
||||
|
||||
def _resolve_class_for_var(self, var_name: str) -> str | None:
|
||||
for ClassName in self.class_methods:
|
||||
|
||||
Reference in new issue
Block a user