|
@@ -190,11 +190,13 @@ class VtableDisambiguator(angr.Analysis):
|
|
|
|
|
|
table_index = 0
|
|
|
function_list: list[VTableFunction] = []
|
|
|
- vtable_range = enumerate(
|
|
|
- range(vtsym.rebased_addr + 0x4 * 2, vtsym.rebased_addr + vtsym.size, 4)
|
|
|
- )
|
|
|
+
|
|
|
+ # we include the initial upcast offset and class typeinfo here
|
|
|
+ vtable_range = enumerate(range(vtsym.rebased_addr, vtsym.rebased_addr + vtsym.size, 4))
|
|
|
+
|
|
|
for n, addr in vtable_range:
|
|
|
# get symbols that map to that address
|
|
|
+ # NOTE: classes that don't implement virtual destructors have nullptrs
|
|
|
deref = self.loader.fast_memory_load_pointer(addr)
|
|
|
fnsyms = set(self.syms_by_addr.get(deref) or set()) if deref else set()
|
|
|
if not fnsyms:
|
|
@@ -203,6 +205,15 @@ class VtableDisambiguator(angr.Analysis):
|
|
|
# functions are grouped correctly
|
|
|
table_index += 1
|
|
|
next(vtable_range)
|
|
|
+
|
|
|
+ for n1, addr1 in vtable_range:
|
|
|
+ # consume any leading nullptrs (destructors that were optimized out)
|
|
|
+ # this also consumes the next actual function pointer
|
|
|
+ # we could probably get away with looking for it in the parent class...
|
|
|
+ deref = self.loader.fast_memory_load_pointer(addr1)
|
|
|
+ function_list.append(VTableFunction(table_index, deref))
|
|
|
+ if deref != 0:
|
|
|
+ break
|
|
|
continue
|
|
|
function_list.append(VTableFunction(table_index, deref))
|
|
|
|