Merge pull request #2681 from PeaceBeUponYou/master
Mono: Data Structure Dissect Fix and Debug Features
This commit is contained in:
commit
9a3ade0443
15
.gitignore
vendored
15
.gitignore
vendored
@ -48,3 +48,18 @@ Cheat Engine/MonoDataCollector/MonoDataCollector/x64/Release/stdafx.obj
|
||||
Cheat Engine/MonoDataCollector/MonoDataCollector/x64/Release/vc143.pdb
|
||||
Cheat Engine/MonoDataCollector/MonoDataCollector/MonoDataCollector.vcxproj
|
||||
Cheat Engine/MonoDataCollector/MonoDataCollector/MonoDataCollector.vcxproj
|
||||
Cheat Engine/MonoDataCollector/MonoDataCollector/MonoDataCollector.vcxproj
|
||||
*.vcxproj
|
||||
Cheat Engine/MonoDataCollector/.vs/MonoDataCollector/v17/ipch/AutoPCH/f68d19c2fab066ca/DLLMAIN.ipch
|
||||
Cheat Engine/MonoDataCollector/MonoDataCollector/MonoDataCollector.vcxproj
|
||||
Cheat Engine/MonoDataCollector/MonoDataCollector/x64/Release/MonoDataCollector.vcxproj.FileListAbsolute.txt
|
||||
Cheat Engine/MonoDataCollector/MonoDataCollector/x64/Release/MonoDataCollector64.Build.CppClean.log
|
||||
Cheat Engine/MonoDataCollector/MonoDataCollector/MonoDataCollector.vcxproj
|
||||
Cheat Engine/MonoDataCollector/.vs/MonoDataCollector/v17/ipch/AutoPCH/3d2a0f62d32e0fb5/CMEMSTREAM.ipch
|
||||
Cheat Engine/MonoDataCollector/.vs/MonoDataCollector/FileContentIndex/62bb0928-9760-4e2d-9c74-b56a96c8718a.vsidx
|
||||
Cheat Engine/MonoDataCollector/MonoDataCollector/x64/Release/MonoData.941726A9.tlog/Cl.items.tlog
|
||||
*.tlog
|
||||
*.vcxproj
|
||||
*.vsidx
|
||||
*.lpi
|
||||
Cheat Engine/MonoDataCollector/MonoDataCollector/MonoDataCollector.vcxproj
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "PipeServer.h"
|
||||
|
||||
|
||||
|
||||
HANDLE DataCollectorThread;
|
||||
HANDLE SuicideThread;
|
||||
HINSTANCE g_hInstance;
|
||||
@ -61,7 +60,17 @@ typedef int (NTAPI *ZWSETINFORMATIONTHREAD)(
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CUSTOM_DEBUG
|
||||
FILE* CreateAndTestDebugConsole()
|
||||
{
|
||||
FILE* f = nullptr;
|
||||
#if DEBUG_CONSOLE
|
||||
AllocConsole();
|
||||
freopen_s(&f, "CONOUT$", "w", stdout);
|
||||
#endif
|
||||
return f;
|
||||
}
|
||||
#endif
|
||||
|
||||
DWORD WINAPI DataCollectorEntry(LPVOID lpThreadParameter)
|
||||
{
|
||||
@ -85,20 +94,35 @@ DWORD WINAPI DataCollectorEntry(LPVOID lpThreadParameter)
|
||||
|
||||
OutputDebugString("creating new CPipeServer instance\n");
|
||||
pw=new CPipeServer();
|
||||
|
||||
|
||||
#ifdef CUSTOM_DEBUG
|
||||
FILE* console = CreateAndTestDebugConsole();
|
||||
if (console)
|
||||
printf("Console created!\n");
|
||||
#endif
|
||||
|
||||
OutputDebugString("starting CPipeServer instance\n");
|
||||
pw->Start();
|
||||
|
||||
OutputDebugString("Destroying PipeServer\n");
|
||||
DataCollectorThread=0;
|
||||
delete pw;
|
||||
|
||||
#ifdef CUSTOM_DEBUG
|
||||
if (console)
|
||||
fclose(console);
|
||||
#if DEBUG_CONSOLE
|
||||
FreeConsole();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (SuicideThread)
|
||||
TerminateThread(SuicideThread, 0);
|
||||
|
||||
Sleep(1000);
|
||||
|
||||
#ifdef _WINDOWS
|
||||
OutputDebugString("Freeing Memory\n");
|
||||
FreeLibraryAndExitThread(g_hInstance, 0);
|
||||
#endif
|
||||
return 0;
|
||||
|
@ -21,7 +21,6 @@
|
||||
#endif //linux
|
||||
|
||||
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -31,6 +30,15 @@
|
||||
//todo: Make this multithreaded. So: Make a list of threads that can AV
|
||||
|
||||
|
||||
void Log(_In_z_ _Printf_format_string_ char const* const _Format, ...)
|
||||
{
|
||||
#ifdef DEBUG_CONSOLE
|
||||
va_list args;
|
||||
va_start(args, _Format);
|
||||
vprintf(_Format, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL ExpectingAccessViolations = FALSE;
|
||||
|
||||
#ifdef _WINDOWS
|
||||
@ -448,6 +456,7 @@ void CPipeServer::InitMono()
|
||||
mono_free = (MONO_FREE)GetProcAddress(hMono, "il2cpp_free");
|
||||
|
||||
mono_get_root_domain = (MONO_GET_ROOT_DOMAIN)GetProcAddress(hMono, "il2cpp_get_root_domain");
|
||||
mono_get_root_domain = mono_get_root_domain ? mono_get_root_domain : (MONO_GET_ROOT_DOMAIN)GetProcAddress(hMono, "mono_get_root_domain"); //some modern games have the same name as mono
|
||||
mono_thread_attach = (MONO_THREAD_ATTACH)GetProcAddress(hMono, "il2cpp_thread_attach");
|
||||
mono_thread_detach = (MONO_THREAD_DETACH)GetProcAddress(hMono, "il2cpp_thread_detach");
|
||||
|
||||
@ -505,11 +514,14 @@ void CPipeServer::InitMono()
|
||||
|
||||
mono_type_get_name = (MONO_TYPE_GET_NAME)GetProcAddress(hMono, "il2cpp_type_get_name");
|
||||
mono_type_get_type = (MONO_TYPE_GET_TYPE)GetProcAddress(hMono, "il2cpp_type_get_type");
|
||||
mono_type_get_name_full = (MONO_TYPE_GET_NAME_FULL)GetProcAddress(hMono, "il2cpp_type_get_name_full");
|
||||
mono_type_is_byref = (MONO_TYPE_IS_BYREF)GetProcAddress(hMono, "il2cpp_type_is_byref");
|
||||
il2cpp_type_get_object = (IL2CPP_TYPE_GET_OBJECT)GetProcAddress(hMono, "il2cpp_type_get_object");
|
||||
il2cpp_method_get_object = (IL2CPP_METHOD_GET_OBJECT)GetProcAddress(hMono, "il2cpp_method_get_object");
|
||||
mono_type_get_name_full = (MONO_TYPE_GET_NAME_FULL)GetProcAddress(hMono, "il2cpp_type_get_name_full");
|
||||
|
||||
mono_method_get_name = (MONO_METHOD_GET_NAME)GetProcAddress(hMono, "il2cpp_method_get_name");
|
||||
mono_method_get_full_name = (MONO_METHOD_GET_FULL_NAME)GetProcAddress(hMono, "il2cpp_method_get_full_name");
|
||||
mono_method_get_full_name = mono_method_get_full_name ? mono_method_get_full_name : (MONO_METHOD_GET_FULL_NAME)GetProcAddress(hMono, "mono_method_get_full_name");
|
||||
mono_method_get_class = (MONO_METHOD_GET_CLASS)GetProcAddress(hMono, "il2cpp_method_get_class");
|
||||
mono_method_get_header = (MONO_METHOD_GET_HEADER)GetProcAddress(hMono, "il2cpp_method_get_header");
|
||||
mono_method_get_flags = (MONO_METHOD_GET_FLAGS)GetProcAddress(hMono, "il2cpp_method_get_flags");
|
||||
@ -542,13 +554,15 @@ void CPipeServer::InitMono()
|
||||
mono_method_desc_from_method = (MONO_METHOD_DESC_FROM_METHOD)GetProcAddress(hMono, "il2cpp_method_desc_from_method");;
|
||||
mono_method_desc_free = (MONO_METHOD_DESC_FREE)GetProcAddress(hMono, "il2cpp_method_desc_free");;
|
||||
|
||||
mono_string_new = (MONO_STRING_NEW)GetProcAddress(hMono, "il2cpp_string_new");
|
||||
mono_string_new = (MONO_STRING_NEW)GetProcAddress(hMono, "mono_string_new"); // il2cpp also has "mono_string_new". Th il2cpp_string_new is a different function
|
||||
mono_string_new = mono_string_new ? mono_string_new : (MONO_STRING_NEW)GetProcAddress(hMono, "il2cpp_string_new");
|
||||
mono_string_to_utf8 = (MONO_STRING_TO_UTF8)GetProcAddress(hMono, "il2cpp_string_to_utf8");
|
||||
il2cpp_array_new = (IL2CPP_ARRAY_NEW)GetProcAddress(hMono, "il2cpp_array_new");
|
||||
mono_array_element_size = (MONO_ARRAY_ELEMENT_SIZE)GetProcAddress(hMono, "il2cpp_array_element_size");
|
||||
mono_value_box = (MONO_VALUE_BOX)GetProcAddress(hMono, "il2cpp_value_box");
|
||||
mono_object_unbox = (MONO_OBJECT_UNBOX)GetProcAddress(hMono, "il2cpp_object_unbox");
|
||||
mono_object_new = (MONO_OBJECT_NEW)GetProcAddress(hMono, "il2cpp_object_new");
|
||||
mono_object_to_string = (MONO_OBJECT_TO_STRING)GetProcAddress(hMono, "il2cpp_object_to_string");
|
||||
|
||||
mono_class_get_type = (MONO_CLASS_GET_TYPE)GetProcAddress(hMono, "il2cpp_class_get_type");
|
||||
mono_type_get_class = (MONO_TYPE_GET_CLASS)GetProcAddress(hMono, "il2cpp_type_get_class");
|
||||
@ -558,6 +572,10 @@ void CPipeServer::InitMono()
|
||||
mono_runtime_invoke = (MONO_RUNTIME_INVOKE)GetProcAddress(hMono, "il2cpp_runtime_invoke");
|
||||
mono_runtime_object_init = (MONO_RUNTIME_OBJECT_INIT)GetProcAddress(hMono, "il2cpp_runtime_object_init");
|
||||
|
||||
mono_ptr_class_get = (MONO_PTR_GET_CLASS)GetProcAddress(hMono, "il2cpp_ptr_class_get");
|
||||
mono_ptr_class_get = mono_ptr_class_get ? mono_ptr_class_get : (MONO_PTR_GET_CLASS)GetProcAddress(hMono, "mono_ptr_class_get");
|
||||
mono_type_get_ptr_type = (MONO_PTR_GET_CLASS)GetProcAddress(hMono, "il2cpp_type_get_ptr_type");
|
||||
mono_type_get_ptr_type = mono_type_get_ptr_type ? mono_type_get_ptr_type : (MONO_PTR_GET_CLASS)GetProcAddress(hMono, "mono_type_get_ptr_type");
|
||||
|
||||
mono_assembly_name_new = (MONO_ASSEMBLY_NAME_NEW)GetProcAddress(hMono, "il2cpp_assembly_name_new");
|
||||
mono_assembly_loaded = (MONO_ASSEMBLY_LOADED)GetProcAddress(hMono, "il2cpp_assembly_loaded");
|
||||
@ -666,10 +684,12 @@ void CPipeServer::InitMono()
|
||||
mono_type_get_name = (MONO_TYPE_GET_NAME)GetProcAddress(hMono, "mono_type_get_name");
|
||||
mono_type_get_type = (MONO_TYPE_GET_TYPE)GetProcAddress(hMono, "mono_type_get_type");
|
||||
mono_type_get_object = (MONO_TYPE_GET_OBJECT)GetProcAddress(hMono, "mono_type_get_object");
|
||||
mono_method_get_object = (MONO_METHOD_GET_OBJECT)GetProcAddress(hMono, "mono_method_get_object");
|
||||
mono_type_get_name_full = (MONO_TYPE_GET_NAME_FULL)GetProcAddress(hMono, "mono_type_get_name_full");
|
||||
mono_type_is_byref = (MONO_TYPE_IS_BYREF)GetProcAddress(hMono, "mono_type_is_byref");
|
||||
mono_method_get_object = (MONO_METHOD_GET_OBJECT)GetProcAddress(hMono, "mono_method_get_object");
|
||||
|
||||
mono_method_get_name = (MONO_METHOD_GET_NAME)GetProcAddress(hMono, "mono_method_get_name");
|
||||
mono_method_get_full_name = (MONO_METHOD_GET_FULL_NAME)GetProcAddress(hMono, "mono_method_get_full_name");
|
||||
mono_method_get_class = (MONO_METHOD_GET_CLASS)GetProcAddress(hMono, "mono_method_get_class");
|
||||
mono_method_get_header = (MONO_METHOD_GET_HEADER)GetProcAddress(hMono, "mono_method_get_header");
|
||||
mono_method_get_flags = (MONO_METHOD_GET_FLAGS)GetProcAddress(hMono, "mono_method_get_flags");
|
||||
@ -709,6 +729,7 @@ void CPipeServer::InitMono()
|
||||
mono_value_box = (MONO_VALUE_BOX)GetProcAddress(hMono, "mono_value_box");
|
||||
mono_object_unbox = (MONO_OBJECT_UNBOX)GetProcAddress(hMono, "mono_object_unbox");
|
||||
mono_object_new = (MONO_OBJECT_NEW)GetProcAddress(hMono, "mono_object_new");
|
||||
mono_object_to_string = (MONO_OBJECT_TO_STRING)GetProcAddress(hMono, "mono_object_to_string");
|
||||
mono_object_isinst = (MONO_OBJECT_ISINST)GetProcAddress(hMono, "mono_object_isinst");
|
||||
mono_get_enum_class = (MONO_GET_ENUM_CLASS)GetProcAddress(hMono, "mono_get_enum_class");
|
||||
|
||||
@ -720,6 +741,8 @@ void CPipeServer::InitMono()
|
||||
mono_runtime_invoke = (MONO_RUNTIME_INVOKE)GetProcAddress(hMono, "mono_runtime_invoke");
|
||||
mono_runtime_object_init = (MONO_RUNTIME_OBJECT_INIT)GetProcAddress(hMono, "mono_runtime_object_init");
|
||||
|
||||
mono_ptr_class_get = (MONO_PTR_GET_CLASS)GetProcAddress(hMono, "mono_ptr_class_get");
|
||||
mono_type_get_ptr_type = (MONO_PTR_GET_CLASS)GetProcAddress(hMono, "mono_type_get_ptr_type");
|
||||
|
||||
mono_assembly_name_new = (MONO_ASSEMBLY_NAME_NEW)GetProcAddress(hMono, "mono_assembly_name_new");
|
||||
mono_assembly_loaded = (MONO_ASSEMBLY_LOADED)GetProcAddress(hMono, "mono_assembly_loaded");
|
||||
@ -772,7 +795,7 @@ void CPipeServer::Object_New()
|
||||
domain = (void*)mono_domain_get();
|
||||
|
||||
void* klass = (void*)ReadQword();
|
||||
void* object = mono_object_new(domain, klass);
|
||||
void* object = il2cpp ? mono_object_new(klass, klass) : mono_object_new(domain, klass); //No domain in il2cpp; And since it is __stdcall, the prms should be fine in x86 il2pp processes
|
||||
WriteQword((UINT64)object);
|
||||
}
|
||||
|
||||
@ -1522,6 +1545,20 @@ void CPipeServer::GetMethodName()
|
||||
Write(methodname, (WORD)strlen(methodname));
|
||||
}
|
||||
|
||||
void CPipeServer::GetMethodFullName()
|
||||
{
|
||||
void* method = (void*)ReadQword();
|
||||
if (method && mono_method_get_full_name)
|
||||
{
|
||||
char* methodname = mono_method_get_full_name(method);
|
||||
|
||||
WriteWord((WORD)strlen(methodname));
|
||||
Write(methodname, (WORD)strlen(methodname));
|
||||
}
|
||||
else
|
||||
WriteWord(0);
|
||||
}
|
||||
|
||||
void CPipeServer::GetMethodClass()
|
||||
{
|
||||
void* method = (void*)ReadQword();
|
||||
@ -1588,19 +1625,42 @@ void CPipeServer::GetMonoDataCollectorVersion()
|
||||
WriteDword(MONO_DATACOLLECTORVERSION);
|
||||
}
|
||||
|
||||
void CPipeServer::NewString()
|
||||
DECLSPEC_NOINLINE void CPipeServer::NewString()
|
||||
{
|
||||
//Log("Creating new string\n");
|
||||
void* domain = (void*)ReadQword();
|
||||
if (domain == NULL)
|
||||
if (domain == NULL && !il2cpp) //No domain required in il2cpp
|
||||
domain = (void*)mono_get_root_domain();
|
||||
|
||||
char* s = ReadString();
|
||||
void* string = mono_string_new ? mono_string_new(domain, s) : nullptr;
|
||||
free(s);
|
||||
|
||||
void* string = mono_string_new(domain, s);
|
||||
WriteQword((UINT_PTR)string);
|
||||
}
|
||||
|
||||
void CPipeServer::GetClassFromPointer()
|
||||
{
|
||||
void* ptr = (void*)ReadQword();
|
||||
if (ptr && mono_ptr_class_get)
|
||||
{
|
||||
WriteQword((UINT64)mono_ptr_class_get(ptr));
|
||||
}
|
||||
else
|
||||
WriteQword(0);
|
||||
}
|
||||
|
||||
void CPipeServer::GetTypeFromPointerType()
|
||||
{
|
||||
void* type = (void*)ReadQword();
|
||||
if (type && mono_type_get_ptr_type)
|
||||
{
|
||||
WriteQword((UINT64)mono_type_get_ptr_type(type));
|
||||
}
|
||||
else
|
||||
WriteQword(0);
|
||||
}
|
||||
|
||||
void CPipeServer::DisassembleMethod()
|
||||
{
|
||||
void* method = (void*)ReadQword();
|
||||
@ -1647,6 +1707,7 @@ void CPipeServer::GetMethodParameters()
|
||||
|
||||
{
|
||||
void* returntype = il2cpp_method_get_return_type(method);
|
||||
WriteQword((UINT64)returntype);
|
||||
if (returntype)
|
||||
WriteDword(mono_type_get_type(returntype));
|
||||
else
|
||||
@ -1677,35 +1738,24 @@ void CPipeServer::GetMethodParameters()
|
||||
WriteByte(0);
|
||||
}
|
||||
|
||||
if (paramcount)
|
||||
gpointer iter = NULL;
|
||||
MonoType* paramtype;
|
||||
|
||||
for (i = 0; i < paramcount; i++)
|
||||
{
|
||||
gpointer iter = NULL;
|
||||
MonoType* paramtype;
|
||||
|
||||
for (i = 0; i < paramcount; i++)
|
||||
{
|
||||
paramtype = mono_signature_get_params((MonoMethodSignature*)methodsignature, &iter);
|
||||
|
||||
if (paramtype)
|
||||
WriteDword(mono_type_get_type(paramtype));
|
||||
else
|
||||
WriteDword(0);
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
MonoType* returntype = mono_signature_get_return_type(methodsignature);
|
||||
if (returntype)
|
||||
WriteDword(mono_type_get_type(returntype));
|
||||
paramtype = mono_signature_get_params((MonoMethodSignature*)methodsignature, &iter);
|
||||
WriteQword((UINT64)paramtype);
|
||||
if (paramtype)
|
||||
WriteDword(mono_type_get_type(paramtype));
|
||||
else
|
||||
WriteDword(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
MonoType* returntype = mono_signature_get_return_type(methodsignature);
|
||||
WriteQword((UINT64)returntype);
|
||||
if (returntype)
|
||||
WriteDword(mono_type_get_type(returntype));
|
||||
else
|
||||
WriteDword(0);
|
||||
}
|
||||
else
|
||||
WriteByte(0);
|
||||
@ -1943,7 +1993,7 @@ void CPipeServer::GetStaticFieldAddressFromClass(void)
|
||||
}
|
||||
}
|
||||
|
||||
void CPipeServer::GetTypeClass(void)
|
||||
void CPipeServer::GetFieldClass(void)
|
||||
{
|
||||
void* field = (void*)ReadQword(); // TODO: this should be monotype but EnumFieldsInClass effectively returns fieldtype ptr
|
||||
void* type = field ? mono_field_get_type(field) : NULL;
|
||||
@ -1957,6 +2007,15 @@ void CPipeServer::GetTypeClass(void)
|
||||
WriteQword((UINT_PTR)klass);
|
||||
}
|
||||
|
||||
void CPipeServer::GetFieldType()
|
||||
{
|
||||
void* field = (void*)ReadQword();
|
||||
if (field && mono_field_get_type)
|
||||
WriteQword((UINT_PTR)mono_field_get_type(field));
|
||||
else
|
||||
WriteQword(0);
|
||||
}
|
||||
|
||||
void CPipeServer::GetArrayElementClass(void)
|
||||
{
|
||||
void* klass = (void*)ReadQword();
|
||||
@ -2385,102 +2444,120 @@ void CPipeServer::InvokeMethod(void)
|
||||
}
|
||||
try
|
||||
{
|
||||
MonoObject* exception = {};
|
||||
MonoObject* exception = nullptr;
|
||||
result = mono_runtime_invoke(method, pThis, arry, &exception);
|
||||
if (!result)
|
||||
{
|
||||
WriteByte(MONO_TYPE_VOID);
|
||||
WriteQword((UINT64)result);
|
||||
return;
|
||||
}
|
||||
void* klass = mono_object_get_class(result);
|
||||
void* type = klass ? mono_class_get_type(klass) : NULL;
|
||||
int returntype = type ? mono_type_get_type(type) : MONO_TYPE_VOID;
|
||||
WriteByte(returntype);
|
||||
switch (returntype)
|
||||
else
|
||||
{
|
||||
case MONO_TYPE_STRING:
|
||||
{
|
||||
if (il2cpp)
|
||||
void* klass = mono_object_get_class(result);
|
||||
void* type = klass ? mono_class_get_type(klass) : NULL;
|
||||
int returntype = type ? mono_type_get_type(type) : MONO_TYPE_VOID;
|
||||
WriteByte(returntype);
|
||||
switch (returntype)
|
||||
{
|
||||
wchar_t* ptr = il2cpp_string_chars(result);
|
||||
case MONO_TYPE_STRING:
|
||||
{
|
||||
if (il2cpp)
|
||||
{
|
||||
wchar_t* ptr = il2cpp_string_chars(result);
|
||||
#ifdef _WINDOWS
|
||||
int l = WideCharToMultiByte(CP_UTF8, 0, ptr, -1, NULL, 0, NULL, NULL);
|
||||
char* c = (char*)malloc(l + 1);
|
||||
l = WideCharToMultiByte(CP_UTF8, 0, ptr, -1, c, l, NULL, NULL);
|
||||
c[l] = 0;
|
||||
WriteString(c);
|
||||
free(c);
|
||||
int l = WideCharToMultiByte(CP_UTF8, 0, ptr, -1, NULL, 0, NULL, NULL);
|
||||
char* c = (char*)malloc(l + 1);
|
||||
l = WideCharToMultiByte(CP_UTF8, 0, ptr, -1, c, l, NULL, NULL);
|
||||
c[l] = 0;
|
||||
WriteString(c);
|
||||
free(c);
|
||||
#else
|
||||
//todo: unsure about this
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
|
||||
std::string dest = convert.to_bytes((char16_t*)ptr);
|
||||
WriteString(dest.c_str());
|
||||
//todo: unsure about this
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
|
||||
std::string dest = convert.to_bytes((char16_t*)ptr);
|
||||
WriteString(dest.c_str());
|
||||
#endif
|
||||
/*_bstr_t b((wchar_t*)il2cpp_string_chars(result));
|
||||
WriteString((char*)b);*/
|
||||
/*_bstr_t b((wchar_t*)il2cpp_string_chars(result));
|
||||
WriteString((char*)b);*/
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
char* ptr = mono_string_to_utf8(result);
|
||||
WriteString(ptr);
|
||||
g_free(ptr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MONO_TYPE_CHAR:
|
||||
WriteString((char*)mono_object_unbox(result));
|
||||
break;
|
||||
case MONO_TYPE_R4:
|
||||
{
|
||||
float f = *(float*)mono_object_unbox(result);
|
||||
Write(&f, 4);
|
||||
}break;
|
||||
case MONO_TYPE_R8:
|
||||
{
|
||||
double d = *(double*)mono_object_unbox(result);
|
||||
Write(&d, 8);
|
||||
}break;
|
||||
case MONO_TYPE_I1:
|
||||
case MONO_TYPE_U1:
|
||||
case MONO_TYPE_BOOLEAN:
|
||||
WriteByte(*(BYTE*)mono_object_unbox(result));
|
||||
break;
|
||||
case MONO_TYPE_I2:
|
||||
case MONO_TYPE_U2:
|
||||
WriteWord(*(WORD*)mono_object_unbox(result));
|
||||
break;
|
||||
case MONO_TYPE_I4:
|
||||
case MONO_TYPE_U4:
|
||||
WriteDword(*(DWORD*)mono_object_unbox(result));
|
||||
break;
|
||||
case MONO_TYPE_I:
|
||||
case MONO_TYPE_U:
|
||||
case MONO_TYPE_I8:
|
||||
case MONO_TYPE_U8:
|
||||
WriteQword(*(UINT64*)mono_object_unbox(result));
|
||||
break;
|
||||
case MONO_TYPE_VALUETYPE:
|
||||
WriteQword((UINT64)mono_object_unbox(result));
|
||||
break;
|
||||
/*case MONO_TYPE_PTR:
|
||||
case MONO_TYPE_BYREF:
|
||||
case MONO_TYPE_CLASS:
|
||||
case MONO_TYPE_FNPTR:
|
||||
case MONO_TYPE_GENERICINST:
|
||||
case MONO_TYPE_ARRAY:
|
||||
case MONO_TYPE_SZARRAY:
|
||||
case MONO_TYPE_VALUETYPE:
|
||||
{
|
||||
WriteQword((INT64)result);
|
||||
}
|
||||
break;*/
|
||||
|
||||
default:
|
||||
WriteQword((INT64)result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Push exception is caused
|
||||
if (exception && mono_object_to_string && mono_string_to_utf8)
|
||||
{
|
||||
WriteByte(1);
|
||||
void* MonoString = mono_object_to_string(exception, (void**) & exception);
|
||||
if (MonoString)
|
||||
{
|
||||
WriteByte(1);
|
||||
WriteString( mono_string_to_utf8(MonoString) );
|
||||
}
|
||||
else
|
||||
{
|
||||
char* ptr = mono_string_to_utf8(result);
|
||||
WriteString(ptr);
|
||||
g_free(ptr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MONO_TYPE_CHAR:
|
||||
WriteString((char*)mono_object_unbox(result));
|
||||
break;
|
||||
case MONO_TYPE_R4:
|
||||
{
|
||||
float f = *(float*)mono_object_unbox(result);
|
||||
Write(&f, 4);
|
||||
}break;
|
||||
case MONO_TYPE_R8:
|
||||
{
|
||||
double d = *(double*)mono_object_unbox(result);
|
||||
Write(&d, 8);
|
||||
}break;
|
||||
case MONO_TYPE_I1:
|
||||
case MONO_TYPE_U1:
|
||||
case MONO_TYPE_BOOLEAN:
|
||||
WriteByte(*(BYTE*)mono_object_unbox(result));
|
||||
break;
|
||||
case MONO_TYPE_I2:
|
||||
case MONO_TYPE_U2:
|
||||
WriteWord(*(WORD*)mono_object_unbox(result));
|
||||
break;
|
||||
case MONO_TYPE_I4:
|
||||
case MONO_TYPE_U4:
|
||||
WriteDword(*(DWORD*)mono_object_unbox(result));
|
||||
break;
|
||||
case MONO_TYPE_I:
|
||||
case MONO_TYPE_U:
|
||||
case MONO_TYPE_I8:
|
||||
case MONO_TYPE_U8:
|
||||
WriteQword(*(UINT64*)mono_object_unbox(result));
|
||||
break;
|
||||
case MONO_TYPE_VALUETYPE:
|
||||
WriteQword((UINT64)mono_object_unbox(result));
|
||||
break;
|
||||
/*case MONO_TYPE_PTR:
|
||||
case MONO_TYPE_BYREF:
|
||||
case MONO_TYPE_CLASS:
|
||||
case MONO_TYPE_FNPTR:
|
||||
case MONO_TYPE_GENERICINST:
|
||||
case MONO_TYPE_ARRAY:
|
||||
case MONO_TYPE_SZARRAY:
|
||||
case MONO_TYPE_VALUETYPE:
|
||||
{
|
||||
WriteQword((INT64)result);
|
||||
}
|
||||
break;*/
|
||||
|
||||
default:
|
||||
WriteQword((INT64)result);
|
||||
break;
|
||||
WriteByte(0);
|
||||
}
|
||||
else
|
||||
WriteByte(0);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -2664,6 +2741,18 @@ void CPipeServer::IsSubClassOf()
|
||||
WriteByte(0); //not supported
|
||||
}
|
||||
|
||||
void CPipeServer::IsTypeByReference()
|
||||
{
|
||||
void* monotype = (void*)ReadQword();
|
||||
if (monotype && mono_type_is_byref)
|
||||
{
|
||||
bool bIsByRef = mono_type_is_byref(monotype);
|
||||
WriteByte(bIsByRef);
|
||||
}
|
||||
else
|
||||
WriteByte(0);
|
||||
}
|
||||
|
||||
void CPipeServer::GetArrayElementSize()
|
||||
{
|
||||
void* klass = (void*)ReadQword();
|
||||
@ -2928,6 +3017,10 @@ void CPipeServer::Start(void)
|
||||
case MONOCMD_GETMETHODNAME:
|
||||
GetMethodName();
|
||||
break;
|
||||
|
||||
case MONOCMD_GETMETHODFULLNAME:
|
||||
GetMethodFullName();
|
||||
break;
|
||||
|
||||
case MONOCMD_GETMETHODCLASS:
|
||||
GetMethodClass();
|
||||
@ -2946,6 +3039,11 @@ void CPipeServer::Start(void)
|
||||
break;
|
||||
|
||||
case MONOCMD_TERMINATE:
|
||||
if (pipehandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DisconnectNamedPipe(pipehandle);
|
||||
CloseHandle(pipehandle);
|
||||
}
|
||||
return;
|
||||
|
||||
case MONOCMD_DISASSEMBLE:
|
||||
@ -2972,8 +3070,12 @@ void CPipeServer::Start(void)
|
||||
GetStaticFieldAddressFromClass();
|
||||
break;
|
||||
|
||||
case MONOCMD_GETTYPECLASS:
|
||||
GetTypeClass();
|
||||
case MONOCMD_GETFIELDCLASS:
|
||||
GetFieldClass();
|
||||
break;
|
||||
|
||||
case MONOCMD_GETFIELDTYPE:
|
||||
GetFieldType();
|
||||
break;
|
||||
|
||||
case MONOCMD_GETARRAYELEMENTCLASS:
|
||||
@ -3012,6 +3114,10 @@ void CPipeServer::Start(void)
|
||||
IsSubClassOf();
|
||||
break;
|
||||
|
||||
case MONOCMD_TYPEISBYREF:
|
||||
IsTypeByReference();
|
||||
break;
|
||||
|
||||
case MONOCMD_ISIL2CPP:
|
||||
IsIL2CPP();
|
||||
break;
|
||||
@ -3084,6 +3190,14 @@ void CPipeServer::Start(void)
|
||||
NewCSArray();
|
||||
break;
|
||||
|
||||
case MONOCMD_GETPTRTYPECLASS:
|
||||
GetClassFromPointer();
|
||||
break;
|
||||
|
||||
case MONOCMD_GETTYPEPTRTYPE:
|
||||
GetTypeFromPointerType();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
ExpectingAccessViolations = FALSE;
|
||||
|
@ -6,8 +6,13 @@
|
||||
#endif
|
||||
|
||||
|
||||
//#define CUSTOM_DEBUG
|
||||
#ifdef CUSTOM_DEBUG
|
||||
#define DEBUG_CONSOLE 1
|
||||
#endif // CUSTOM_DEBUG
|
||||
|
||||
//yyyymmdd
|
||||
#define MONO_DATACOLLECTORVERSION 20230512
|
||||
#define MONO_DATACOLLECTORVERSION 20230830
|
||||
|
||||
#define MONO_TYPE_NAME_FORMAT_IL 0
|
||||
#define MONO_TYPE_NAME_FORMAT_REFLECTION 1
|
||||
@ -42,7 +47,7 @@
|
||||
#define MONOCMD_GETMETHODSIGNATURE 24
|
||||
#define MONOCMD_GETPARENTCLASS 25
|
||||
#define MONOCMD_GETSTATICFIELDADDRESSFROMCLASS 26
|
||||
#define MONOCMD_GETTYPECLASS 27
|
||||
#define MONOCMD_GETFIELDCLASS 27
|
||||
#define MONOCMD_GETARRAYELEMENTCLASS 28
|
||||
#define MONOCMD_FINDMETHODBYDESC 29
|
||||
#define MONOCMD_INVOKEMETHOD 30
|
||||
@ -78,6 +83,11 @@
|
||||
#define MONOCMD_MONOOBJECTUNBOX 60
|
||||
#define MONOCMD_MONOARRAYNEW 61
|
||||
#define MONOCMD_ENUMINTERFACESOFCLASS 62
|
||||
#define MONOCMD_GETMETHODFULLNAME 63
|
||||
#define MONOCMD_TYPEISBYREF 64
|
||||
#define MONOCMD_GETPTRTYPECLASS 65
|
||||
#define MONOCMD_GETFIELDTYPE 66
|
||||
#define MONOCMD_GETTYPEPTRTYPE 67
|
||||
|
||||
|
||||
typedef struct {} MonoType;
|
||||
@ -149,10 +159,13 @@ typedef int (__cdecl *MONO_FIELD_GET_OFFSET)(void *field);
|
||||
typedef char* (__cdecl *MONO_TYPE_GET_NAME)(void *type);
|
||||
typedef void* (__cdecl* MONO_TYPE_GET_CLASS)(void* type);
|
||||
typedef int (__cdecl *MONO_TYPE_GET_TYPE)(void *type);
|
||||
typedef int (__cdecl *MONO_TYPE_IS_BYREF)(void *monotype);
|
||||
typedef void* (__cdecl *MONO_TYPE_GET_OBJECT)(void *domain, void *type);
|
||||
typedef void* (__cdecl *IL2CPP_TYPE_GET_OBJECT)(void *type);
|
||||
typedef void* (__cdecl *MONO_METHOD_GET_OBJECT)(void *domain, void *method, void* klass);
|
||||
typedef void* (__cdecl *IL2CPP_METHOD_GET_OBJECT)(void* method, void* klass);
|
||||
typedef void* (__cdecl* MONO_PTR_GET_CLASS)(void* monotype);
|
||||
typedef void* (__cdecl* MONO_TYPE_GET_PTR_TYPE)(void* ptrmonotype);
|
||||
|
||||
|
||||
typedef char* (__cdecl *MONO_TYPE_GET_NAME_FULL)(void *type, int format);
|
||||
@ -166,6 +179,7 @@ typedef void* (__cdecl * MONO_FIELD_GET_VALUE_OBJECT)(void *domain, void* field,
|
||||
|
||||
|
||||
typedef char* (__cdecl *MONO_METHOD_GET_NAME)(void *method);
|
||||
typedef char* (__cdecl *MONO_METHOD_GET_FULL_NAME)(void *method);
|
||||
typedef void* (__cdecl *MONO_COMPILE_METHOD)(void *method);
|
||||
typedef void (__cdecl *MONO_FREE_METHOD)(void *method);
|
||||
|
||||
@ -328,6 +342,7 @@ private:
|
||||
|
||||
MONO_TYPE_GET_NAME mono_type_get_name;
|
||||
MONO_TYPE_GET_TYPE mono_type_get_type;
|
||||
MONO_TYPE_IS_BYREF mono_type_is_byref;
|
||||
MONO_TYPE_GET_OBJECT mono_type_get_object; //return a ReflectionType* object
|
||||
IL2CPP_TYPE_GET_OBJECT il2cpp_type_get_object;
|
||||
MONO_METHOD_GET_OBJECT mono_method_get_object;
|
||||
@ -337,9 +352,12 @@ private:
|
||||
MONO_TYPE_GET_NAME_FULL mono_type_get_name_full;
|
||||
MONO_FIELD_GET_FLAGS mono_field_get_flags;
|
||||
MONO_FIELD_GET_VALUE_OBJECT mono_field_get_value_object;
|
||||
MONO_PTR_GET_CLASS mono_ptr_class_get;
|
||||
MONO_TYPE_GET_PTR_TYPE mono_type_get_ptr_type;
|
||||
|
||||
MONO_METHOD_GET_FLAGS mono_method_get_flags;
|
||||
MONO_METHOD_GET_NAME mono_method_get_name;
|
||||
MONO_METHOD_GET_FULL_NAME mono_method_get_full_name;
|
||||
MONO_METHOD_GET_HEADER mono_method_get_header;
|
||||
MONO_METHOD_GET_CLASS mono_method_get_class;
|
||||
MONO_METHOD_SIG mono_method_signature;
|
||||
@ -451,6 +469,7 @@ private:
|
||||
void FindClass();
|
||||
void FindMethod();
|
||||
void GetMethodName();
|
||||
void GetMethodFullName();
|
||||
void GetMethodClass();
|
||||
void GetKlassName();
|
||||
void GetClassNamespace();
|
||||
@ -470,7 +489,8 @@ private:
|
||||
void UnBoxMonoObject();
|
||||
void GetVTableFromClass();
|
||||
void GetStaticFieldAddressFromClass();
|
||||
void GetTypeClass();
|
||||
void GetFieldClass();
|
||||
void GetFieldType();
|
||||
void GetArrayElementClass();
|
||||
void FindMethodByDesc();
|
||||
void InvokeMethod();
|
||||
@ -483,6 +503,7 @@ private:
|
||||
void IsEnumClass();
|
||||
void IsValueTypeClass();
|
||||
void IsSubClassOf();
|
||||
void IsTypeByReference();
|
||||
void GetArrayElementSize();
|
||||
void NewCSArray();
|
||||
void IsIL2CPP();
|
||||
@ -492,6 +513,9 @@ private:
|
||||
void GetMonoDataCollectorVersion();
|
||||
void NewString();
|
||||
|
||||
void GetClassFromPointer();
|
||||
void GetTypeFromPointerType();
|
||||
|
||||
public:
|
||||
CPipeServer(void);
|
||||
~CPipeServer(void);
|
||||
|
@ -21,7 +21,7 @@ local dpiscale=getScreenDPI()/96
|
||||
|
||||
mono_timeout=3000 --change to 0 to never timeout (meaning: 0 will freeze your face off if it breaks on a breakpoint, just saying ...)
|
||||
|
||||
MONO_DATACOLLECTORVERSION=20230512
|
||||
MONO_DATACOLLECTORVERSION=20230830
|
||||
|
||||
MONOCMD_INITMONO=0
|
||||
MONOCMD_OBJECT_GETCLASS=1
|
||||
@ -89,6 +89,11 @@ MONOCMD_GETREFLECTIONMETHODOFMONOMETHOD = 59
|
||||
MONOCMD_MONOOBJECTUNBOX = 60
|
||||
MONOCMD_MONOARRAYNEW = 61
|
||||
MONOCMD_ENUMINTERFACESOFCLASS = 62
|
||||
MONOCMD_GETMETHODFULLNAME = 63
|
||||
MONOCMD_TYPEISBYREF = 64
|
||||
MONOCMD_GETPTRTYPECLASS = 65
|
||||
MONOCMD_GETFIELDTYPE = 66
|
||||
MONOCMD_GETTYPEPTRTYPE = 67
|
||||
|
||||
MONO_TYPE_END = 0x00 -- End of List
|
||||
MONO_TYPE_VOID = 0x01
|
||||
@ -144,6 +149,9 @@ monoTypeToVartypeLookup[MONO_TYPE_R4]=vtSingle
|
||||
monoTypeToVartypeLookup[MONO_TYPE_R8]=vtDouble
|
||||
monoTypeToVartypeLookup[MONO_TYPE_STRING]=vtPointer --pointer to a string object
|
||||
monoTypeToVartypeLookup[MONO_TYPE_PTR]=vtPointer
|
||||
monoTypeToVartypeLookup[MONO_TYPE_I]=vtPointer --IntPtr
|
||||
monoTypeToVartypeLookup[MONO_TYPE_U]=vtPointer
|
||||
monoTypeToVartypeLookup[MONO_TYPE_OBJECT]=vtPointer --object
|
||||
monoTypeToVartypeLookup[MONO_TYPE_BYREF]=vtPointer
|
||||
monoTypeToVartypeLookup[MONO_TYPE_CLASS]=vtPointer
|
||||
monoTypeToVartypeLookup[MONO_TYPE_FNPTR]=vtPointer
|
||||
@ -166,7 +174,7 @@ monoTypeToCStringLookup[MONO_TYPE_I8]='int64'
|
||||
monoTypeToCStringLookup[MONO_TYPE_U8]='unsigned int 64'
|
||||
monoTypeToCStringLookup[MONO_TYPE_R4]='single'
|
||||
monoTypeToCStringLookup[MONO_TYPE_R8]='double'
|
||||
monoTypeToCStringLookup[MONO_TYPE_STRING]='String' --pointer to a string object
|
||||
monoTypeToCStringLookup[MONO_TYPE_STRING]='String'
|
||||
monoTypeToCStringLookup[MONO_TYPE_PTR]='Pointer'
|
||||
monoTypeToCStringLookup[MONO_TYPE_BYREF]='Object'
|
||||
monoTypeToCStringLookup[MONO_TYPE_CLASS]='Object'
|
||||
@ -1415,6 +1423,10 @@ function mono_class_isValueType(klass)
|
||||
return retv==1
|
||||
end
|
||||
|
||||
function mono_class_isStruct(klass)
|
||||
return mono_class_isValueType(klass) and not(mono_class_isEnum(klass)) and not(mono_class_IsPrimitive(klass))
|
||||
end
|
||||
|
||||
function mono_class_isSubClassOf(klass,parentklass,checkInterfaces)
|
||||
checkInterfaces = checkInterfaces and 1 or 0
|
||||
if not klass or klass==0 then return false end
|
||||
@ -1548,6 +1560,33 @@ function mono_class_getImage(class)
|
||||
return result;
|
||||
end
|
||||
|
||||
function mono_ptr_class_get(fieldtype_or_ptrtype)
|
||||
--returns the MonoType* object which is a pointer to the given type. Use "mono_class_getFullName" on the returned value to see the difference.
|
||||
monopipe.lock()
|
||||
monopipe.writeByte(MONOCMD_GETPTRTYPECLASS)
|
||||
monopipe.writeQword(fieldtype_or_ptrtype)
|
||||
local val = monopipe.readQword()
|
||||
monopipe.unlock()
|
||||
return val
|
||||
end
|
||||
|
||||
function mono_field_get_type(monofield)
|
||||
monopipe.lock()
|
||||
monopipe.writeByte(MONOCMD_GETFIELDTYPE)
|
||||
monopipe.writeQword(monofield)
|
||||
local val = monopipe.readQword()
|
||||
monopipe.unlock()
|
||||
return val
|
||||
end
|
||||
|
||||
function mono_type_get_ptr_type(ptrtype)
|
||||
monopipe.lock()
|
||||
monopipe.writeByte(MONOCMD_GETTYPEPTRTYPE)
|
||||
monopipe.writeQword(ptrtype)
|
||||
local val = monopipe.readQword()
|
||||
monopipe.unlock()
|
||||
return val
|
||||
end
|
||||
|
||||
function mono_field_getClass(field)
|
||||
--if debug_canBreak() then return nil end
|
||||
@ -1593,6 +1632,15 @@ function mono_type_get_type(monotype)
|
||||
return retv
|
||||
end
|
||||
|
||||
function mono_type_is_byref(monotype)
|
||||
monopipe.lock()
|
||||
monopipe.writeByte(MONOCMD_TYPEISBYREF)
|
||||
monopipe.writeQword(monotype)
|
||||
local val = monopipe.readByte()
|
||||
monopipe.unlock()
|
||||
return val == 1
|
||||
end
|
||||
|
||||
function mono_classtype_get_reflectiontype(monotype)
|
||||
if not monotype or monotype==0 then return end
|
||||
monopipe.lock()
|
||||
@ -2112,7 +2160,7 @@ function mono_class_enumFields(class, includeParents, expandedStructs)
|
||||
if expandedStructs then
|
||||
for k,v in pairs(mainFields) do
|
||||
local lockls = mono_field_getClass(v.field)
|
||||
if ((v.monotype==MONO_TYPE_VALUETYPE) and not(mono_class_isEnum(lockls)) and not(mono_class_isSubClassOf(mono_field_getClass(v.field),class))) and not(v.isStatic or v.isConst) then --does not want to infinitely loop if the struct has some static member of the same class
|
||||
if not(v.isStatic or v.isConst) and mono_class_isStruct(lockls) and not(mono_class_isSubClassOf(lockls,class)) then --does not want to infinitely loop if the struct has some static member of the same class
|
||||
local subFields = GetFields(lockls, includeParents, expandedStructs, true)
|
||||
--print(v.name, v.typename, fu(v.monotype))
|
||||
if #subFields >0 then
|
||||
@ -2573,6 +2621,17 @@ function mono_method_getName(method)
|
||||
return result;
|
||||
end
|
||||
|
||||
function mono_method_getFullName(monomethod)
|
||||
monopipe.lock()
|
||||
monopipe.writeByte(MONOCMD_GETMETHODFULLNAME)
|
||||
monopipe.writeQword(monomethod)
|
||||
local namelength=monopipe.readWord()
|
||||
local result=monopipe.readString(namelength)
|
||||
monopipe.unlock()
|
||||
return result or ''
|
||||
end
|
||||
|
||||
|
||||
function mono_method_getHeader(method)
|
||||
--if debug_canBreak() then return nil end
|
||||
if method==nil then return nil end
|
||||
@ -2622,10 +2681,12 @@ function mono_method_get_parameters(method)
|
||||
|
||||
--types
|
||||
for i=1, paramcount do
|
||||
result.parameters[i].monotype=monopipe.readQword();
|
||||
result.parameters[i].type=monopipe.readDword();
|
||||
end
|
||||
|
||||
--result
|
||||
result.returnmonotype = monopipe.readQword()
|
||||
result.returntype=monopipe.readDword()
|
||||
|
||||
monopipe.unlock()
|
||||
@ -3097,11 +3158,18 @@ function mono_invoke_method(domain, method, object, args)
|
||||
mono_writeObject(args[i].type, args[i].value)
|
||||
end
|
||||
|
||||
local result=mono_readObject()
|
||||
local result =mono_readObject()
|
||||
--print(type(result),result)
|
||||
if monopipe then
|
||||
local exception = nil
|
||||
if monopipe.readByte() == 1 then
|
||||
if monopipe.readByte() == 1 then
|
||||
local excplen = monopipe.readWord()
|
||||
exception = monopipe.readString(excplen)
|
||||
end
|
||||
end
|
||||
monopipe.unlock()
|
||||
return result
|
||||
return result, exception
|
||||
else
|
||||
--something bad happened
|
||||
LaunchMonoDataCollector()
|
||||
@ -3387,9 +3455,6 @@ function monoform_createInstanceOfClass(sender)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--[[
|
||||
function monoform_miCreateObject(sender)
|
||||
if (monoForm.TV.Selected~=nil) then
|
||||
@ -3995,7 +4060,15 @@ end
|
||||
|
||||
function miMonoActivateClick(sender)
|
||||
if monopipe then
|
||||
monopipe.OnTimeout()
|
||||
if isKeyPressed(VK_CONTROL) then
|
||||
monopipe.lock()
|
||||
monopipe.writeByte(MONOCMD_TERMINATE)
|
||||
monopipe.unlock()
|
||||
monopipe.OnTimeout()
|
||||
print('dll ejected')
|
||||
else
|
||||
monopipe.OnTimeout()
|
||||
end
|
||||
else
|
||||
if LaunchMonoDataCollector()==0 then
|
||||
showMessage(translate("Failure to launch "))
|
||||
@ -4493,23 +4566,56 @@ end
|
||||
|
||||
mono_StringStruct=nil
|
||||
|
||||
function monoform_exportStructInternal(s, caddr, recursive, static, structmap, makeglobal)
|
||||
function monofrom_addPointerStructure(parentstructure, thiselement, field, recursive, static, structmap, loopnumber)
|
||||
--This function will add sub-strutures to the fields that are c Pointers
|
||||
--to disable, set " monoSettings.Value["MaxPointerChildStructs"] = "" "
|
||||
assert(field.monotype==MONO_TYPE_PTR, 'Error: WAIT! How did I end up here!?')
|
||||
local kls = mono_field_getClass(field.field)
|
||||
if not kls or not readPointer(kls) then return end
|
||||
kls = mono_class_get_type(kls)
|
||||
kls = mono_type_get_ptr_type(kls)
|
||||
if not kls or not readPointer(kls) then return end
|
||||
local pat = mono_type_get_type(kls)
|
||||
kls = mono_type_get_class(kls)
|
||||
kls = pat==MONO_TYPE_GENERICINST and mono_class_getParent(kls) or kls
|
||||
if not kls or not readPointer(kls) then return end
|
||||
local subflds = mono_class_enumFields(kls,1)
|
||||
if #subflds==0 then return end
|
||||
local subofst; -- the offset of very first non-static, non-const field needs to be subtracted from similar fields
|
||||
for k,v in ipairs(subflds) do
|
||||
if not v.isStatic and not v.isConst then
|
||||
subofst = subofst or v.offset
|
||||
break
|
||||
end
|
||||
end
|
||||
local structure = createStructure("")
|
||||
monoform_exportStructInternal(structure, kls, recursive, static, structmap, nil, subofst, loopnumber-1)
|
||||
print(structure.Count, field.name)
|
||||
if structure.Count > 0 then
|
||||
thiselement.ChildStruct = structure
|
||||
thiselement.ChildStructStart = 0
|
||||
else
|
||||
structure.destroy()
|
||||
end
|
||||
--print(#subflds, subflds[1].offset,mono_class_getFullName(kls), mono_class_getFullName(mono_field_getClass(field.field)))
|
||||
end
|
||||
|
||||
function monoform_exportStructInternal(s, caddr, recursive, static, structmap, makeglobal, minusoffset, loopnumber)
|
||||
--print("monoform_exportStructInternal")
|
||||
if not(tonumber(monoSettings.Value["MaxPointerChildStructs"])) then
|
||||
monoSettings.Value["MaxPointerChildStructs"] = "2"
|
||||
end
|
||||
|
||||
if (monopipe==nil) or (caddr==0) or (caddr==nil) then return nil end
|
||||
|
||||
-- print("b")
|
||||
|
||||
local className = mono_class_getFullName(caddr)
|
||||
--print('Populating '..className)
|
||||
|
||||
-- handle Array as separate case
|
||||
|
||||
if string.sub(className,-2)=='[]' then
|
||||
local elemtype = mono_class_getArrayElementClass(caddr)
|
||||
return monoform_exportArrayStructInternal(s, caddr, elemtype, recursive, structmap, makeglobal, true)
|
||||
end
|
||||
|
||||
minusoffset = minusoffset or 0
|
||||
|
||||
local hasStatic = false
|
||||
structure_beginUpdate(s)
|
||||
@ -4529,14 +4635,16 @@ function monoform_exportStructInternal(s, caddr, recursive, static, structmap, m
|
||||
if fieldname~=nil then
|
||||
e.Name=fieldname
|
||||
end
|
||||
e.Offset=fields[i].offset
|
||||
e.Offset=fields[i].offset - minusoffset
|
||||
e.Vartype=mono_class_isEnum(mono_field_getClass( fields[i].field )) and vtDword or monoTypeToVarType(ft)
|
||||
--print(string.format(" Field: %d: %d: %d: %s", e.Offset, e.Vartype, ft, fieldname))
|
||||
|
||||
loopnumber = loopnumber or tonumber(monoSettings.Value["MaxPointerChildStructs"])
|
||||
if ft==MONO_TYPE_STRING or ft==MONO_TYPE_CHAR then
|
||||
--e.Vartype=vtUnicodeString
|
||||
e.Bytesize = 999
|
||||
|
||||
elseif ft == MONO_TYPE_PTR and loopnumber > 0 then
|
||||
monofrom_addPointerStructure(s, e, fields[i], recursive, static, structmap, loopnumber)
|
||||
--[[ e.Vartype=vtPointer
|
||||
--print(string.format(" Field: %d: %d: %d: %s", e.Offset, e.Vartype, ft, fieldname))
|
||||
|
||||
@ -4609,6 +4717,50 @@ function monoform_exportArrayStruct(arraytype, elemtype, typename, recursive, st
|
||||
return monoform_exportArrayStructInternal(acs, arraytype, elemtype, recursive, structmap, makeglobal, reload)
|
||||
end
|
||||
|
||||
function mono_structfields_getStartOffset(fields)
|
||||
--this function get the first non-static, non-const field and gets its offset to subtract from all the offsets of fields
|
||||
--this is done since structs as a memeber element in a class are not pointers, rather simple values!
|
||||
for k,v in pairs(fields) do
|
||||
if not(v.isConst) and not(v.isStatic) then
|
||||
return v.offset
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function monoform_addCSStructElements(structure, klass, parentstructname, offsetInStructure, prename, postname, preklassName, postClassName)
|
||||
parentstructname = type(parentstructname)=='string' and #parentstructname>0 and parentstructname..'.' or ''
|
||||
offsetInStructure = tonumber(offsetInStructure) or 0 --for arrays of the same struct
|
||||
prename = prename or "" --the text to add before the name of the element
|
||||
postname = postname or "" --text to add after the name of the element
|
||||
preklassName = preklassName or "" --the text to add before the klassname (in paranthesis) of the element
|
||||
postklassName = postklassName or "" --text to add after the klassname (in paranthesis) of the element
|
||||
|
||||
local subfield = mono_class_enumFields(klass)
|
||||
local suboffset = mono_structfields_getStartOffset(subfield)
|
||||
if not suboffset then
|
||||
suboffset = targetIs64Bit() and 0x10 or 0x8
|
||||
end
|
||||
for k,v in pairs(subfield) do
|
||||
if not(v.isConst) and not(v.isStatic) then
|
||||
local fieldClass = mono_field_getClass( v.field )
|
||||
local klsname = mono_class_getName(fieldClass)
|
||||
local eloffset = offsetInStructure+v.offset-suboffset
|
||||
if mono_class_isStruct(fieldClass) then
|
||||
monoform_addCSStructElements(structure, fieldClass, v.name, eloffset, prename, postname, klsname..'.')
|
||||
else
|
||||
local nm = v.name..'('..preklassName..klsname..postklassName..')'
|
||||
local ce=structure.addElement()
|
||||
ce.Name=string.format("%s%s%s",prename,parentstructname..nm,postname)
|
||||
ce.Offset=eloffset
|
||||
ce.Vartype= mono_class_isEnum(fieldClass) and vtDword or monoTypeToVarType( v.monotype ) --vtPointer
|
||||
if ce.Vartype == vtDword then
|
||||
ce.DisplayMethod = 'dtSignedInteger'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function monoform_exportArrayStructInternal(acs, arraytype, elemtype, recursive, structmap, makeglobal, reload)
|
||||
--print("monoform_exportArrayStructInternal")
|
||||
--print(fu(arraytype),mono_class_getFullName(arraytype))
|
||||
@ -4628,35 +4780,22 @@ function monoform_exportArrayStructInternal(acs, arraytype, elemtype, recursive,
|
||||
|
||||
local j
|
||||
local psize = arraytype and mono_array_element_size(arraytype) or nil
|
||||
psize = psize and psize or (targetIs64Bit() and 8 or 4)
|
||||
psize = psize and psize or (targetIs64Bit() and 8 or 4)
|
||||
|
||||
local start
|
||||
if targetIs64Bit() then
|
||||
start=0x20
|
||||
else
|
||||
start=0x10
|
||||
end
|
||||
local start
|
||||
if targetIs64Bit() then
|
||||
start=0x20
|
||||
else
|
||||
start=0x10
|
||||
end
|
||||
local elementkls = mono_class_getArrayElementClass(arraytype)
|
||||
local elementmonotype = mono_type_get_type(mono_class_get_type(elementkls))
|
||||
local isStruct = mono_class_isValueType(elementkls) and not(mono_class_IsPrimitive(elementkls)) and not(mono_class_isEnum(elementkls))
|
||||
local isStruct = mono_class_isStruct(elementkls)--mono_class_isValueType(elementkls) and not(mono_class_IsPrimitive(elementkls)) and not(mono_class_isEnum(elementkls))
|
||||
--print(fu(elementkls),mono_class_getFullName(elementkls),fu(elementmonotype))
|
||||
if isStruct then
|
||||
--print("yep, a struct")
|
||||
local subfield = mono_class_enumFields(elementkls)
|
||||
local suboffset = subfield[1].offset == 0x10 and 0x10 or 0
|
||||
for k,v in pairs(subfield) do
|
||||
if not(v.isConst) and not(v.isStatic) then
|
||||
local nm = v.name..'('..mono_class_getName(mono_field_getClass(v.field))..')'
|
||||
for j=0, 9 do -- Arbitrarily add 10 elements
|
||||
ce=acs.addElement()
|
||||
ce.Name=string.format("[%d]%s",j,nm)
|
||||
ce.Offset=j*psize+start+v.offset-suboffset
|
||||
ce.Vartype= monoTypeToVarType( v.monotype ) --vtPointer
|
||||
if ce.Vartype == vtDword then
|
||||
ce.DisplayMethod = 'dtSignedInteger'
|
||||
end
|
||||
end
|
||||
end
|
||||
for j=0, 9 do -- Arbitrarily add 10 elements
|
||||
monoform_addCSStructElements(acs, elementkls, "", j*psize+start, '['..j..']', "")
|
||||
end
|
||||
else
|
||||
for j=0, 9 do -- Arbitrarily add 10 elements
|
||||
|
Loading…
Reference in New Issue
Block a user