From 5206236b014850518e2de5f47e4534bc1b10bd48 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 11 Oct 2012 15:10:19 +0400 Subject: [PATCH] Look through missing intermediate bases when interposing subclasses. --- library/VTableInterpose.cpp | 20 ++++++++++++++++++-- library/include/VTableInterpose.h | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/library/VTableInterpose.cpp b/library/VTableInterpose.cpp index 141450615..d8a07e830 100644 --- a/library/VTableInterpose.cpp +++ b/library/VTableInterpose.cpp @@ -281,9 +281,10 @@ VMethodInterposeLinkBase *VMethodInterposeLinkBase::get_first_interpose(virtual_ return item; } -void VMethodInterposeLinkBase::find_child_hosts(virtual_identity *cur, void *vmptr) +bool VMethodInterposeLinkBase::find_child_hosts(virtual_identity *cur, void *vmptr) { auto &children = cur->getChildren(); + bool found = false; for (size_t i = 0; i < children.size(); i++) { @@ -298,17 +299,32 @@ void VMethodInterposeLinkBase::find_child_hosts(virtual_identity *cur, void *vmp continue; child_next.insert(base); + found = true; } - else + else if (child->vtable_ptr) { void *cptr = child->get_vmethod_ptr(vmethod_idx); if (cptr != vmptr) continue; child_hosts.insert(child); + found = true; + find_child_hosts(child, vmptr); } + else + { + // If this vtable is not known, but any of the children + // have the same vmethod, this one definitely does too + if (find_child_hosts(child, vmptr)) + { + child_hosts.insert(child); + found = true; + } + } } + + return found; } void VMethodInterposeLinkBase::on_host_delete(virtual_identity *from) diff --git a/library/include/VTableInterpose.h b/library/include/VTableInterpose.h index b52b32270..bd3c23036 100644 --- a/library/include/VTableInterpose.h +++ b/library/include/VTableInterpose.h @@ -159,7 +159,7 @@ namespace DFHack void on_host_delete(virtual_identity *host); VMethodInterposeLinkBase *get_first_interpose(virtual_identity *id); - void find_child_hosts(virtual_identity *cur, void *vmptr); + bool find_child_hosts(virtual_identity *cur, void *vmptr); public: VMethodInterposeLinkBase(virtual_identity *host, int vmethod_idx, void *interpose_method, void *chain_mptr, int priority); ~VMethodInterposeLinkBase();