Browse Source

Hoist parent vtable entry lookup

nosoop 10 months ago
parent
commit
54d4f06a8a
1 changed files with 17 additions and 13 deletions
  1. 17 13
      src/smgdc/angr/vtable_disamb.py

+ 17 - 13
src/smgdc/angr/vtable_disamb.py

@@ -332,6 +332,18 @@ class VtableDisambiguator(angr.Analysis):
                     return fnsym
         return None
 
+    def get_vfn_from_parent(self, vt: Symbol, vtidx: int) -> int:
+        # HACK: some virtual destructors got optimized out and are represented by nullptrs
+        #       in that case we try to match functions from the parent
+        for parent_vt in self.superclass_map[vt]:
+            pvptr_first, *_ = self.get_vfptrs_from_table(parent_vt)
+            if vtidx > len(pvptr_first):
+                break
+            vptr = pvptr_first[vtidx]
+            if vptr:
+                return vptr
+        return 0
+
     @functools.cache
     def get_vtables_from_address(self, vt: Symbol) -> list[VTable]:
         # returns a list of vtables for each vtable present on the class
@@ -346,20 +358,12 @@ class VtableDisambiguator(angr.Analysis):
         for table_index, vptrs in enumerate(vptr_lists):
             for n, vptr in enumerate(vptrs):
                 # get symbols that map to that address
+                vptr = vptr or self.get_vfn_from_parent(vt, n)
                 if vptr == 0:
-                    # HACK: some virtual destructors got optimized out and are represented by nullptrs
-                    for parent_vt in self.superclass_map[vt]:
-                        # HACK: in that case we try to match functions from the parent
-                        pvptr_first, *_ = self.get_vfptrs_from_table(parent_vt)
-                        vptr = pvptr_first[n]
-                        if vptr:
-                            break
-
-                    if vptr == 0:
-                        call_unexpected = self.loader.find_symbol("__cxa_call_unexpected")
-                        assert call_unexpected
-                        function_list.append(VTableFunction(table_index, {call_unexpected}))
-                        continue
+                    call_unexpected = self.loader.find_symbol("__cxa_call_unexpected")
+                    assert call_unexpected
+                    function_list.append(VTableFunction(table_index, {call_unexpected}))
+                    continue
 
                 fnsyms = set(self.syms_by_addr.get(vptr) or set()) if vptr else set()