Improved handling of virtual inheritance. (#7)

* new system for handling vtables

* commented out non-matching JKRDisposer::~JKDisposer()

* removed artificial vtables and matched simple virtual-call functions

* better text on nonmatching functions

* reverted asmdiff.sh

* attempt 2

* Spelling

* banner and .gitignore for vtable artifacts

* move virtual function to the correct class

* remove unnecessary casts
This commit is contained in:
Jonathan Wase
2020-12-01 15:18:01 -05:00
committed by GitHub
parent 937da3c59b
commit ac6b191dc1
16 changed files with 910 additions and 221 deletions
+18 -7
View File
@@ -3,20 +3,31 @@
#include "JSystem/JKernel/JKRHeap/JKRHeap.h"
// #include "JSystem/JKernel/asm/func_802D147C.s"
JKRDisposer::JKRDisposer() : __vt(&lbl_803CC0F0), ptr_link(this) {
this->heap = JKRHeap::findFromRoot(this);
JKRDisposer::JKRDisposer() : ptr_link(this) {
this->heap = JKRHeap::findFromRoot(this);
if (this->heap != 0) {
this->heap->disposable_list.append(&this->ptr_link);
}
}
// Almost. Missing three instructions, something
// to do with the destruction of JSUPtrLink
/*
Super close.
This is what we expected: (from Ghidra)
if (this != (JKRDisposer *)&DAT_fffffff8) {
JSUPtrLink::~JSUPtrLink(&this->ptr_link,0);
}
But the compiler generate code like this instead: (no if and -1 instead of 0)
JSUPtrLink::~JSUPtrLink(&this->ptr_link,-1);
Maybe we are using the wrong compiler?
*/
#ifdef NONMATCHING
JKRDisposer::~JKRDisposer() {
this->__vt = lbl_803CC0F0;
if (this->heap != NULL) {
this->heap->disposable_list.remove(&this->ptr_link);
JKRHeap* heap = this->heap;
if (heap != 0) {
heap->disposable_list.remove(&this->ptr_link);
}
}
#else
+56 -115
View File
@@ -1,11 +1,21 @@
#include "JSystem/JKernel/JKRHeap/JKRHeap.h"
#include "global.h"
// Initializing the members seems to be weird because of
// the way we're using vtables.
/*
Very close! When initialzing child_list(true) it will use less register then the asm code.
- 2cb0b0: 3b 5f 00 40 addi r26,r31,64
- 2cb0b4: 7f 43 d3 78 mr r3,r26
- 2cb0b8: 48 00 dd 9d bl 0x2d8e54
- 2cb0bc: 38 7a 00 0c addi r3,r26,12
+ 2cb0b0: 38 7f 00 40 addi r3,r31,64
+ 2cb0b4: 38 80 00 01 li r4,1
+ 2cb0b8: 48 00 dd 01 bl 0x2d8db8
+ 2cb0bc: 38 7f 00 4c addi r3,r31,76
*/
#ifdef NONMATCHING
JKRHeap::JKRHeap(void* data, u32 size, JKRHeap* parent, bool error_flag)
: __base(), __vt(lbl_803CBF70), child_list(true), heap_link(this), disposable_list(true) {
: JKRDisposer(), child_list(true), heap_link(this), disposable_list(true) {
OSInitMutex(this->mutex);
this->size = size;
this->begin = (u32)data;
@@ -89,19 +99,10 @@ JKRHeap* JKRHeap::becomeCurrentHeap() {
return prev;
}
// All virtual calls seems to only use r12
// but emulating the call with use another
// register (r4 in this case).
#ifdef NONMATCHING
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE448.s"
void JKRHeap::destroy() {
(*this->__vt->do_destroy)(this);
this->do_destroy();
}
#else
asm void JKRHeap::destroy() {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE448.s"
}
#endif
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE474.s"
void* JKRHeap::alloc(u32 size, int alignment, JKRHeap* heap) {
@@ -116,17 +117,10 @@ void* JKRHeap::alloc(u32 size, int alignment, JKRHeap* heap) {
return NULL;
}
// Same problem as with all other virtual calls.
#ifdef NONMATCHING
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE4D4.s"
void* JKRHeap::alloc(u32 size, int alignment) {
return (*this->__vt->do_alloc)(this, size, alignment);
return this->do_alloc(size, alignment);
}
#else
asm void* JKRHeap::alloc(u32 size, int alignment) {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE4D4.s"
}
#endif
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE500.s"
void JKRHeap::free(void* ptr, JKRHeap* heap) {
@@ -138,46 +132,25 @@ void JKRHeap::free(void* ptr, JKRHeap* heap) {
heap->free(ptr);
}
// Same problem as with all other virtual calls.
#ifdef NONMATCHING
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE548.s"
void JKRHeap::free(void* ptr) {
(*this->__vt->do_free)(this, ptr);
this->do_free(ptr);
}
#else
asm void JKRHeap::free(void* ptr) {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE548.s"
}
#endif
asm void JKRHeap::callAllDisposer() {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE574.s"
}
// Same problem as with all other virtual calls.
#ifdef NONMATCHING
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE5CC.s"
void JKRHeap::freeAll() {
(*this->__vt->do_freeAll)(this);
this->do_freeAll();
}
#else
asm void JKRHeap::freeAll() {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE5CC.s"
}
#endif
// Same problem as with all other virtual calls.
#ifdef NONMATCHING
void JKRHeap::freeAll() {
(*this->__vt->do_freeTail)(this);
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE5F8.s"
void JKRHeap::freeTail() {
this->do_freeTail();
}
#else
asm void JKRHeap::freeTail() {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE5F8.s"
}
#endif
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE624.s"
s32 JKRHeap::resize(void* ptr, u32 size, JKRHeap* heap) {
@@ -189,17 +162,10 @@ s32 JKRHeap::resize(void* ptr, u32 size, JKRHeap* heap) {
return heap->resize(ptr, size);
}
// Same problem as with all other virtual calls.
#ifdef NONMATCHING
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE684.s"
s32 JKRHeap::resize(void* ptr, u32 size) {
return (*this->__vt->do_resize)(this, ptr, size);
return this->do_resize(ptr, size);
}
#else
asm s32 JKRHeap::resize(void* ptr, u32 size) {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE684.s"
}
#endif
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE6B0.s"
s32 JKRHeap::getSize(void* ptr, JKRHeap* heap) {
@@ -211,68 +177,34 @@ s32 JKRHeap::getSize(void* ptr, JKRHeap* heap) {
return heap->getSize(ptr);
}
// Same problem as with all other virtual calls.
#ifdef NONMATCHING
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE700.s"
s32 JKRHeap::getSize(void* ptr) {
return (*this->__vt->do_getSize)(this, ptr);
return this->do_getSize(ptr);
}
#else
asm s32 JKRHeap::getSize(void* ptr) {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE700.s"
}
#endif
// Same problem as with all other virtual calls.
#ifdef NONMATCHING
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE72C.s"
s32 JKRHeap::getFreeSize() {
return (*this->__vt->do_getFreeSize)(this);
return this->do_getFreeSize();
}
#else
asm s32 JKRHeap::getFreeSize() {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE72C.s"
}
#endif
// Same problem as with all other virtual calls.
#ifdef NONMATCHING
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE758.s"
s32 JKRHeap::getMaxFreeBlock() {
return (*this->__vt->do_getMaxFreeBlock)(this);
return this->do_getMaxFreeBlock();
}
#else
asm s32 JKRHeap::getMaxFreeBlock() {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE758.s"
}
#endif
// Same problem as with all other virtual calls.
#ifdef NONMATCHING
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE784.s"
s32 JKRHeap::getTotalFreeSize() {
return (*this->__vt->do_getTotalFreeSize)(this);
return this->do_getTotalFreeSize();
}
#else
asm s32 JKRHeap::getTotalFreeSize() {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE784.s"
}
#endif
// Same problem as with all other virtual calls.
#ifdef NONMATCHING
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE7B0.s"
u8 JKRHeap::changeGroupID(u8 param_1) {
return (*this->__vt->go_changeGroupID)(this, param_1);
return this->do_changeGroupID(param_1);
}
#else
asm u8 JKRHeap::changeGroupID(u8 param_1) {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE7B0.s"
}
#endif
asm s32 JKRHeap::getMaxAllocatableSize(int alignment){nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE7DC.s"
asm s32 JKRHeap::getMaxAllocatableSize(int alignment) {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CE7DC.s"
}
// #include "JSystem/JKernel/JKRHeap/asm/func_802CE83C.s"
@@ -316,10 +248,21 @@ void JKRHeap::dispose(void* begin, void* end) {
this->dispose_subroutine((u32)begin, (u32)end);
}
#ifdef NONMATCHING
void JKRHeap::dispose() {
JSUPtrLink* node;
JKRDisposer* disposable;
while (node = this->disposable_list.head, node != NULL) {
disposable = (JKRDisposer*)node->owner;
disposable->~JKRDisposer();
}
}
#else
asm void JKRHeap::dispose() {
nofralloc
#include "JSystem/JKernel/JKRHeap/asm/func_802CEAC0.s"
}
#endif
// #include "JSystem/JKernel/JKRHeap/asm/func_802CEB18.s"
void JKRHeap::copyMemory(void* dst, void* src, u32 size) {
@@ -357,12 +300,12 @@ asm bool JKRHeap::isSubHeap(JKRHeap* heap) const {
// #include "JSystem/JKernel/JKRHeap/asm/func_802CEC4C.s"
void* operator new(u32 size) {
return JKRHeap::alloc(size, 4, (JKRHeap*)NULL);
return JKRHeap::alloc(size, 4, NULL);
}
// #include "JSystem/JKernel/JKRHeap/asm/func_802CEC74.s"
void* operator new(u32 size, int alignment) {
return JKRHeap::alloc(size, alignment, (JKRHeap*)NULL);
return JKRHeap::alloc(size, alignment, NULL);
}
// #include "JSystem/JKernel/JKRHeap/asm/func_802CEC98.s"
@@ -372,12 +315,12 @@ void* operator new(u32 size, JKRHeap* heap, int alignment) {
// #include "JSystem/JKernel/JKRHeap/asm/func_802CECC4.s"
void* operator new[](u32 size) {
return JKRHeap::alloc(size, 4, (JKRHeap*)NULL);
return JKRHeap::alloc(size, 4, NULL);
}
// #include "JSystem/JKernel/JKRHeap/asm/func_802CECEC.s"
void* operator new[](u32 size, int alignment) {
return JKRHeap::alloc(size, alignment, (JKRHeap*)NULL);
return JKRHeap::alloc(size, alignment, NULL);
}
// #include "JSystem/JKernel/JKRHeap/asm/func_802CED10.s"
@@ -387,12 +330,10 @@ void* operator new[](u32 size, JKRHeap* heap, int alignment) {
// #include "JSystem/JKernel/JKRHeap/asm/func_802CED3C.s"
void operator delete(void* ptr) {
JKRHeap::free(ptr, (JKRHeap*)NULL);
JKRHeap::free(ptr, NULL);
}
// #include "JSystem/JKernel/JKRHeap/asm/func_802CED60.s"
void operator delete[](void* ptr) {
JKRHeap::free(ptr, (JKRHeap*)NULL);
JKRHeap::free(ptr, NULL);
}
+21 -21
View File
@@ -2,11 +2,11 @@
#include "global.h"
// #include "JSupport/asm/func_802DBDFC.s"
JSUPtrLink::JSUPtrLink(void* param_1) {
this->list = (JSUPtrList*)NULL;
this->unk0 = param_1;
this->prev = (JSUPtrLink*)NULL;
this->next = (JSUPtrLink*)NULL;
JSUPtrLink::JSUPtrLink(void* owner) {
this->list = NULL;
this->owner = owner;
this->prev = NULL;
this->next = NULL;
}
// #include "JSupport/asm/func_802DBE14.s"
@@ -32,7 +32,7 @@ JSUPtrList::~JSUPtrList() {
JSUPtrLink* node = this->head;
s32 removed = 0;
while (this->length > removed) {
node->list = (JSUPtrList*)NULL;
node->list = NULL;
node = node->next;
removed += 1;
}
@@ -40,16 +40,16 @@ JSUPtrList::~JSUPtrList() {
// #include "JSupport/asm/func_802DBF14.s"
void JSUPtrList::initiate() {
this->head = (JSUPtrLink*)NULL;
this->tail = (JSUPtrLink*)NULL;
this->head = NULL;
this->tail = NULL;
this->length = 0;
}
// #include "JSupport/asm/func_802DBF28.s"
void JSUPtrList::setFirst(JSUPtrLink* first) {
first->list = this;
first->prev = (JSUPtrLink*)NULL;
first->next = (JSUPtrLink*)NULL;
first->prev = NULL;
first->next = NULL;
this->tail = first;
this->head = first;
this->length = 1;
@@ -58,7 +58,7 @@ void JSUPtrList::setFirst(JSUPtrLink* first) {
// #include "JSupport/asm/func_802DBF4C.s"
bool JSUPtrList::append(JSUPtrLink* ptr) {
JSUPtrList* list = ptr->list;
bool result = ((JSUPtrList*)NULL == list);
bool result = (NULL == list);
if (!result) {
result = list->remove(ptr);
}
@@ -69,7 +69,7 @@ bool JSUPtrList::append(JSUPtrLink* ptr) {
} else {
ptr->list = this;
ptr->prev = this->tail;
ptr->next = (JSUPtrLink*)NULL;
ptr->next = NULL;
this->tail->next = ptr;
this->tail = ptr;
this->length++;
@@ -82,7 +82,7 @@ bool JSUPtrList::append(JSUPtrLink* ptr) {
// #include "JSupport/asm/func_802DBFF0.s"
bool JSUPtrList::prepend(JSUPtrLink* ptr) {
JSUPtrList* list = ptr->list;
bool result = ((JSUPtrList*)NULL == list);
bool result = (NULL == list);
if (!result) {
result = list->remove(ptr);
}
@@ -107,7 +107,7 @@ bool JSUPtrList::prepend(JSUPtrLink* ptr) {
bool JSUPtrList::insert(JSUPtrLink* before, JSUPtrLink* ptr) {
if (before == this->head) {
return this->prepend(ptr);
} else if (before == (JSUPtrLink*)NULL) {
} else if (before == NULL) {
return this->append(ptr);
}
@@ -115,7 +115,7 @@ bool JSUPtrList::insert(JSUPtrLink* before, JSUPtrLink* ptr) {
return false;
}
bool result = ((JSUPtrList*)NULL == ptr->list);
bool result = (NULL == ptr->list);
if (!result) {
result = ptr->list->remove(ptr);
}
@@ -138,20 +138,20 @@ bool JSUPtrList::remove(JSUPtrLink* ptr) {
bool is_parent = (ptr->list == this);
if (is_parent) {
if (this->length == 1) {
this->head = (JSUPtrLink*)NULL;
this->tail = (JSUPtrLink*)NULL;
this->head = NULL;
this->tail = NULL;
} else if (ptr == this->head) {
ptr->next->prev = (JSUPtrLink*)NULL;
ptr->next->prev = NULL;
this->head = ptr->next;
} else if (ptr == this->tail) {
ptr->prev->next = (JSUPtrLink*)NULL;
ptr->prev->next = NULL;
this->tail = ptr->prev;
} else {
ptr->prev->next = ptr->next;
ptr->next->prev = ptr->prev;
}
ptr->list = (JSUPtrList*)NULL;
ptr->list = NULL;
this->length--;
}
@@ -161,7 +161,7 @@ bool JSUPtrList::remove(JSUPtrLink* ptr) {
// #include "JSupport/asm/func_802DC20C.s"
JSUPtrLink* JSUPtrList::getNthLink(u32 index) const {
if (index >= this->length) {
return (JSUPtrLink*)NULL;
return NULL;
}
JSUPtrLink* node = this->head;