diff --git a/O&Z_IL2CPP_Security/JsonManager.cs b/O&Z_IL2CPP_Security/JsonManager.cs index 1ffbfde..e1e8466 100644 --- a/O&Z_IL2CPP_Security/JsonManager.cs +++ b/O&Z_IL2CPP_Security/JsonManager.cs @@ -19,11 +19,13 @@ public class ObfusConfig public int NumObfus { get; set; } public int LocalVariables2Field { get; set; } public int StrCrypter { get; set; } + public int Obfusfunc { get; set; } } public class JsonManager { public JsonIndex index; public string path; + public static string origin = "ewogICAgImtleSI6MTE0NTE0LAogICAgIlZlcnNpb24iOiIyNC40IiwKICAgICIvLyI6IuaUr+aMgTI4IDI0LjQiLAogICAgIk9iZnVzIjoKICAgIHsKICAgICAgICAiQ29udHJvbEZsb3ciOjEsCiAgICAgICAgIk51bU9iZnVzIjoxLAogICAgICAgICJMb2NhbFZhcmlhYmxlczJGaWVsZCI6MSwKICAgICAgICAiU3RyQ3J5cHRlciI6MSwKICAgICAgICAiT2JmdXNmdW5jIjoxLAogICAgICAgICIvLyI6IjA95YWz6ZetIDE95byA5ZCvIiwKICAgICAgICAiLy8iOiJDb250cm9sRmxvd++8muaOp+WItua1geeoi+a3t+a3hiIsCiAgICAgICAgIi8vIjoiTnVtT2JmdXPvvJrmlbDlrZfmt7fmt4YiLAogICAgICAgICIvLyI6IkxvY2FsVmFyaWFibGVzMkZpZWxk77ya5bGA6YOo5Y+Y6YeP6L2s5o2i5Li65a2X5q61IiwKICAgICAgICAiLy8iOiJTdHJDcnlwdGVy77ya5a2X56ym5Liy5Yqg5a+GIiwKICAgICAgICAiLy8iOiJPYmZ1c2Z1bmPvvJroh6rlrprkuYnmt7fmt4bnsbvlkozmlrnms5XlkI3np7As5Y+v5Lul5Zyoa2V5ZnVuY+S4reiHquWumuS5iea3t+a3huaooeW8jyjlpoLnlKjliLDkuoblj43lsITnrYnnsbvlnospIgoKICAgIH0KfQ=="; public JsonManager(string _path) { path = _path; diff --git a/O&Z_IL2CPP_Security/Progarm.cs b/O&Z_IL2CPP_Security/Progarm.cs index 860fac9..ed5271a 100644 --- a/O&Z_IL2CPP_Security/Progarm.cs +++ b/O&Z_IL2CPP_Security/Progarm.cs @@ -16,22 +16,13 @@ Console.WriteLine("O&Z_IL2CPP_Security"); if (!File.Exists("Config.json")) { + Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Config.json not found!"); - Console.WriteLine("正在生成默认配置文件..."); - JsonIndex index = new JsonIndex() - { - key = 114514, - Version = "24.4", - Obfus = new ObfusConfig() - { - ControlFlow = 1, - NumObfus = 1, - LocalVariables2Field = 1, - StrCrypter = 1 - } - }; - File.WriteAllText("Config.json", JsonMapper.ToJson(index)); + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine("正在生成默认配置文件..."); + File.WriteAllBytes("Config.json", Convert.FromBase64String(JsonManager.origin)); if (File.Exists("Config.json")) Console.WriteLine("已重新生成默认配置文件...\nDone!"); + Console.ForegroundColor = ConsoleColor.White; } if (args.Length == 0) { @@ -193,7 +184,10 @@ bool CheckMetadataFile() } void _Test() { - Console.WriteLine(XXTEA.EncryptToBase64String("HelloWorld", "123456")); + AssemblyLoader loader = new AssemblyLoader(OpenFilePath); + ObfusFunc obfusFunc = new ObfusFunc(loader.Module); + obfusFunc.Excute(); + loader.Save(); } void CheckVersion() { @@ -220,6 +214,11 @@ void MonoObfus() ControlFlow controlFlow = new ControlFlow(loader.Module); controlFlow.Execute(); } + if (jsonManager.index.Obfus.Obfusfunc == 1) + { + ObfusFunc obfusFunc = new ObfusFunc(loader.Module); + obfusFunc.Excute(); + } if (jsonManager.index.Obfus.NumObfus == 1) { NumObfus numObfus = new NumObfus(loader.Module); diff --git a/O&Z_IL2CPP_Security/Properties/launchSettings.json b/O&Z_IL2CPP_Security/Properties/launchSettings.json index 4b7c6ef..747e55d 100644 --- a/O&Z_IL2CPP_Security/Properties/launchSettings.json +++ b/O&Z_IL2CPP_Security/Properties/launchSettings.json @@ -10,7 +10,7 @@ }, "Test": { "commandName": "Project", - "commandLineArgs": "\"global-metadata.dat\" Test" + "commandLineArgs": "\"C:\\Users\\22864\\Desktop\\2019Testbuild\\O&Z_2019_4_32_f1_Data\\Managed\\Assembly-CSharp - 副本.dll\" Test" }, "Generate": { "commandName": "Project", @@ -18,7 +18,7 @@ }, "Obfus": { "commandName": "Project", - "commandLineArgs": "\"C:\\Users\\22864\\Desktop\\END_AUTO V2\\END_Data\\Managed\\Assembly-CSharp.dll.bak\" MonoObfus" + "commandLineArgs": "\"C:\\Users\\22864\\Desktop\\2019Testbuild\\O&Z_2019_4_32_f1_Data\\Managed\\Assembly-CSharp - 副本.dll\" MonoObfus" } } } \ No newline at end of file diff --git a/O&Z_IL2CPP_Security/resource/Config.json b/O&Z_IL2CPP_Security/resource/Config.json new file mode 100644 index 0000000..62c7848 --- /dev/null +++ b/O&Z_IL2CPP_Security/resource/Config.json @@ -0,0 +1,19 @@ +{ + "key":114514, + "Version":"24.4", + "//":"支持28 24.4", + "Obfus": + { + "ControlFlow":1, + "NumObfus":1, + "LocalVariables2Field":1, + "StrCrypter":1, + "StrObfus":1, + "//":"0=关闭 1=开启", + "//":"ControlFlow:控制流程混淆", + "//":"NumObfus:数字混淆", + "//":"LocalVariables2Field:局部变量转换为字段", + "//":"StrCrypter:字符串加密", + "//":"StrObfus:方法加密混淆,可以在keyfunc中添加自定义需要排除的方法(如用到了反射等类型)" + } +} \ No newline at end of file diff --git a/O&Z_IL2CPP_Security/resource/keyfunc.json b/O&Z_IL2CPP_Security/resource/keyfunc.json new file mode 100644 index 0000000..7494ca9 --- /dev/null +++ b/O&Z_IL2CPP_Security/resource/keyfunc.json @@ -0,0 +1,126 @@ +{ + "ignoreMethod": [ + "Awake", + "OnEnable", + "Start", + "FixedUpdate", + "Update", + "OnDisable", + "LateUpdate", + "Reset", + "OnValidate", + "FixedUpdate", + "OnTriggerEnter", + "OnTriggerEnter2D", + "OnTriggerExit", + "OnTriggerExit2D", + "OnTriggerStay2D", + "OnCollisionEnter", + "OnCollisionEnter2D", + "OnCollisionExit", + "OnCollisionExit2D", + "OnCollisionStay", + "OnCollisionStay2D", + "OnMouseDown", + "OnMouseDrag", + "OnMouseEnter", + "OnMouseExit", + "OnMouseOver", + "OnMouseUp", + "OnMouseUpAsButton", + "OnPreCull", + "OnBecameVisible", + "OnBecameInvisible", + "OnWillRenderObject", + "OnPreRender", + "OnRenderObject", + "OnPostRender", + "OnRenderImage", + "OnGUI", + "OnDrawGizmos", + "OnDrawGizmosSelected", + "OnApplicationFocus", + "OnApplicationPause", + "OnApplicationQuit", + "OnDisable", + "OnDestory", + "OnLevelWasLoaded", + "OnAnimatorIK", + "OnAnimatorMove", + "OnApplicationFocus", + "OnApplicationPause", + "OnApplicationQuit", + "OnAudioFilterRead", + "OnBecameInvisible", + "OnBecameVisible", + "OnConnectedToServer", + "OnControllerColliderHit", + "OnEnable", + "OnFailedToConnect", + "OnDisconnectedFromServer", + "OnDrawGizmos", + "OnDrawGizmosSelected", + "OnEnable", + "OnFailedToConnect", + "OnFailedToConnectToMasterServer", + "OnJointBreak", + "OnJointBreak2D", + "OnMasterServerEvent", + "OnNetworkInstantiate", + "OnParticleCollision", + "OnParticleSystemStopped", + "OnParticleTrigger", + "OnParticleUpdateJobScheduled", + "OnPlayerConnected", + "OnPlayerDisconnected", + "OnPostRender", + "OnPreCull", + "OnPreRender", + "OnRenderImage", + "OnRenderObject", + "OnSerializeNetworkView", + "OnServerInitialized", + "OnTransformChildrenChanged", + "OnTransformParentChanged", + "OnValidate", + "OnWillRenderObject", + "Reset", + "__", + "incontrol", + "stop", + "option", + "pausemanager", + "fallingrock", + "postfix", + "prefix", + "transpiler" + ], + "ignoreField":[ + "incontrol", + "enum", + "optional", + "__" + ], + "//":"以上为默认忽略列表,默认包含全部的Unity关键方法,建议不要修改,以下为自定义忽略列表,可以根据需要自行添加(如果需要用到反射或者动态调用的方法,建议添加到这里))", + + "//":"关于如何是使用自定义忽略列表,这里有几点建议", + "//":"1.在Unity中,GameObject或者prefabs初始绑定了脚本,则该脚本的类名不可混淆,方法名和字段名可以混淆", + "//":"2.在Unity中,GameObject或者prefabs初始没有绑定脚本,但是在代码中动态添加了脚本,则该脚本的类名、方法名和字段名都可以混淆", + "//":"3.如果该脚本中涉及到了UI的事件响应(如Button.OnClick),则该脚本的类名和该方法名都不可混淆,字段名可以混淆", + "//":"4.Unity的生命周期方法和回调方法不能混淆,上方的忽略列表包含了大多数常用的生命周期和回调方法,如果有遗漏,可以自行添加", + "//":"5.Unity中的Invoke等特殊方法所调用的函数方法不可混淆,同理协程类的方法也不可混淆,请自行添加到自定义忽略列表", + "//":"6.部分涉及反射类的代码不能混淆,如System.Reflection(GetField,GetMethod,Invoke等),请自行添加到自定义忽略列表", + "//":"7.Native层里直接调用C#或通过Unity内置API发送事件到C#的类和方法不可混淆(大多数在移动平台中)", + "//":"8.一些特殊插件对应的脚本不可混淆,例如xLua和与之绑定的C#脚本", + + + "//":"对于方法名的混淆采用的是白名单模式,即默认混淆,如果不需要混淆,可以添加到这里", + "customignoreMethod":[ + ], + "//":"对于字段名的混淆采用的是白名单模式,即默认混淆,如果不需要混淆,可以添加到这里", + "customignoreField":[ + ], + "//":"对于类名的混淆采用的是黑名单模式,即默认不混淆,如果需要混淆,可以添加到这里", + "customignoreClass":[ + ] +} \ No newline at end of file diff --git a/O&Z_IL2CPP_Security/resource/src-res/24.4/MetadataCache.cpp b/O&Z_IL2CPP_Security/resource/src-res/24.4/MetadataCache.cpp new file mode 100644 index 0000000..933dca0 --- /dev/null +++ b/O&Z_IL2CPP_Security/resource/src-res/24.4/MetadataCache.cpp @@ -0,0 +1,1725 @@ +#include "il2cpp-config.h" +#include "MetadataCache.h" + +#include <map> +#include <limits> +#include "il2cpp-class-internals.h" +#include "il2cpp-tabledefs.h" +#include "il2cpp-runtime-stats.h" +#include "gc/GarbageCollector.h" +#include "metadata/ArrayMetadata.h" +#include "metadata/GenericMetadata.h" +#include "metadata/GenericMethod.h" +#include "metadata/Il2CppTypeCompare.h" +#include "metadata/Il2CppTypeHash.h" +#include "metadata/Il2CppTypeVector.h" +#include "metadata/Il2CppGenericContextCompare.h" +#include "metadata/Il2CppGenericContextHash.h" +#include "metadata/Il2CppGenericInstCompare.h" +#include "metadata/Il2CppGenericInstHash.h" +#include "metadata/Il2CppGenericMethodCompare.h" +#include "metadata/Il2CppGenericMethodHash.h" +#include "metadata/Il2CppSignatureCompare.h" +#include "metadata/Il2CppSignatureHash.h" +#include "os/Atomic.h" +#include "os/Mutex.h" +#include "utils/CallOnce.h" +#include "utils/Collections.h" +#include "utils/HashUtils.h" +#include "utils/Il2CppHashMap.h" +#include "utils/Il2CppHashSet.h" +#include "utils/Memory.h" +#include "utils/StringUtils.h" +#include "utils/PathUtils.h" +#include "vm/Assembly.h" +#include "vm/Class.h" +#include "vm/ClassInlines.h" +#include "vm/GenericClass.h" +#include "vm/MetadataAlloc.h" +#include "vm/MetadataLoader.h" +#include "vm/MetadataLock.h" +#include "vm/Method.h" +#include "vm/Object.h" +#include "vm/String.h" +#include "vm/Type.h" +#include "mono-runtime/il2cpp-mapping.h" +#include "vm-utils/NativeSymbol.h" +#include "vm-utils/VmStringUtils.h" +#include "vm/xxtea.h" +typedef std::map<Il2CppClass*, Il2CppClass*> PointerTypeMap; +typedef Il2CppHashMap<const char*, Il2CppClass*, il2cpp::utils::StringUtils::StringHasher<const char*>, il2cpp::utils::VmStringUtils::CaseSensitiveComparer> WindowsRuntimeTypeNameToClassMap; +typedef Il2CppHashMap<const Il2CppClass*, const char*, il2cpp::utils::PointerHash<Il2CppClass> > ClassToWindowsRuntimeTypeNameMap; + +typedef Il2CppHashSet<const Il2CppGenericMethod*, il2cpp::metadata::Il2CppGenericMethodHash, il2cpp::metadata::Il2CppGenericMethodCompare> Il2CppGenericMethodSet; +typedef Il2CppGenericMethodSet::const_iterator Il2CppGenericMethodSetIter; +static Il2CppGenericMethodSet s_GenericMethodSet; + +struct Il2CppMetadataCache +{ + il2cpp::os::FastMutex m_CacheMutex; + PointerTypeMap m_PointerTypes; +}; + +static Il2CppMetadataCache s_MetadataCache; +static Il2CppClass** s_TypeInfoTable = NULL; +static Il2CppClass** s_TypeInfoDefinitionTable = NULL; +static const MethodInfo** s_MethodInfoDefinitionTable = NULL; +static Il2CppString** s_StringLiteralTable = NULL; +static const Il2CppGenericMethod** s_GenericMethodTable = NULL; +static int32_t s_ImagesCount = 0; +static Il2CppImage* s_ImagesTable = NULL; +static int32_t s_AssembliesCount = 0; +static Il2CppAssembly* s_AssembliesTable = NULL; + + +typedef Il2CppHashSet<const Il2CppGenericInst*, il2cpp::metadata::Il2CppGenericInstHash, il2cpp::metadata::Il2CppGenericInstCompare> Il2CppGenericInstSet; +static Il2CppGenericInstSet s_GenericInstSet; + +typedef Il2CppHashMap<const Il2CppGenericMethod*, const Il2CppGenericMethodIndices*, il2cpp::metadata::Il2CppGenericMethodHash, il2cpp::metadata::Il2CppGenericMethodCompare> Il2CppMethodTableMap; +typedef Il2CppMethodTableMap::const_iterator Il2CppMethodTableMapIter; +static Il2CppMethodTableMap s_MethodTableMap; + +typedef Il2CppHashMap<il2cpp::utils::dynamic_array<const Il2CppType*>, Il2CppMethodPointer, il2cpp::metadata::Il2CppSignatureHash, il2cpp::metadata::Il2CppSignatureCompare> Il2CppUnresolvedSignatureMap; +typedef Il2CppUnresolvedSignatureMap::const_iterator Il2CppUnresolvedSignatureMapIter; +static Il2CppUnresolvedSignatureMap *s_pUnresolvedSignatureMap; + +typedef Il2CppHashMap<FieldInfo*, int32_t, il2cpp::utils::PointerHash<FieldInfo> > Il2CppThreadLocalStaticOffsetHashMap; +typedef Il2CppThreadLocalStaticOffsetHashMap::iterator Il2CppThreadLocalStaticOffsetHashMapIter; +static Il2CppThreadLocalStaticOffsetHashMap s_ThreadLocalStaticOffsetMap; + +static const Il2CppCodeRegistration * s_Il2CppCodeRegistration; +static const Il2CppMetadataRegistration * s_Il2CppMetadataRegistration; +static const Il2CppCodeGenOptions* s_Il2CppCodeGenOptions; +static CustomAttributesCache** s_CustomAttributesCaches; + +static WindowsRuntimeTypeNameToClassMap s_WindowsRuntimeTypeNameToClassMap; +static ClassToWindowsRuntimeTypeNameMap s_ClassToWindowsRuntimeTypeNameMap; + +struct InteropDataToTypeConverter +{ + inline const Il2CppType* operator()(const Il2CppInteropData& interopData) const + { + return interopData.type; + } +}; + +typedef il2cpp::utils::collections::ArrayValueMap<const Il2CppType*, Il2CppInteropData, InteropDataToTypeConverter, il2cpp::metadata::Il2CppTypeLess, il2cpp::metadata::Il2CppTypeEqualityComparer> InteropDataMap; +static InteropDataMap s_InteropData; + +struct WindowsRuntimeFactoryTableEntryToTypeConverter +{ + inline const Il2CppType* operator()(const Il2CppWindowsRuntimeFactoryTableEntry& entry) const + { + return entry.type; + } +}; + +typedef il2cpp::utils::collections::ArrayValueMap<const Il2CppType*, Il2CppWindowsRuntimeFactoryTableEntry, WindowsRuntimeFactoryTableEntryToTypeConverter, il2cpp::metadata::Il2CppTypeLess, il2cpp::metadata::Il2CppTypeEqualityComparer> WindowsRuntimeFactoryTable; +static WindowsRuntimeFactoryTable s_WindowsRuntimeFactories; + +template<typename K, typename V> +struct PairToKeyConverter +{ + inline const K& operator()(const std::pair<K, V>& pair) const + { + return pair.first; + } +}; + +typedef il2cpp::utils::collections::ArrayValueMap<const Il2CppGuid*, std::pair<const Il2CppGuid*, Il2CppClass*>, PairToKeyConverter<const Il2CppGuid*, Il2CppClass*> > GuidToClassMap; +static GuidToClassMap s_GuidToNonImportClassMap; + +template<typename T> +static T MetadataOffset(void* metadata, size_t sectionOffset, size_t itemIndex) +{ + return reinterpret_cast<T>(reinterpret_cast<uint8_t*>(metadata) + sectionOffset) + itemIndex; +} + +void il2cpp::vm::MetadataCache::Register(const Il2CppCodeRegistration* const codeRegistration, const Il2CppMetadataRegistration* const metadataRegistration, const Il2CppCodeGenOptions* const codeGenOptions) +{ + s_Il2CppCodeRegistration = codeRegistration; + s_Il2CppMetadataRegistration = metadataRegistration; + s_Il2CppCodeGenOptions = codeGenOptions; + + for (int32_t j = 0; j < metadataRegistration->genericClassesCount; j++) + if (metadataRegistration->genericClasses[j]->typeDefinitionIndex != kTypeIndexInvalid) + il2cpp::metadata::GenericMetadata::RegisterGenericClass(metadataRegistration->genericClasses[j]); + + for (int32_t i = 0; i < metadataRegistration->genericInstsCount; i++) + s_GenericInstSet.insert(metadataRegistration->genericInsts[i]); + + s_InteropData.assign_external(codeRegistration->interopData, codeRegistration->interopDataCount); + s_WindowsRuntimeFactories.assign_external(codeRegistration->windowsRuntimeFactoryTable, codeRegistration->windowsRuntimeFactoryCount); +} + +static void* s_GlobalMetadata; +static const Il2CppGlobalMetadataHeader* s_GlobalMetadataHeader; +static const FrontHeader* frontHeader; +bool il2cpp::vm::MetadataCache::Initialize() +{ + char _metadataName[19] = {53,62,61,48,51,62,127,63,55,38,51,54,51,38,51,124,54,51,38}; //global-metadata.dat + for(int i=0;i<strlen(_metadataName);i++) + { + _metadataName[i] ^= 114514; + } + s_GlobalMetadata = vm::MetadataLoader::LoadMetadataFile(_metadataName); + if (!s_GlobalMetadata) + return false; + + il2cpp::metadata::GenericMetadata::SetMaximumRuntimeGenericDepth(s_Il2CppCodeGenOptions->maximumRuntimeGenericDepth); + //还原头部 + frontHeader = (FrontHeader *)s_GlobalMetadata; + char *Headerdata = (char *)malloc(frontHeader->legnth); + size_t Headerlen; + memcpy(Headerdata, (char*)s_GlobalMetadata + frontHeader->offset, frontHeader->legnth); + char *Header = (char *)xxtea_decrypt(Headerdata, frontHeader->legnth, frontHeader->key, &Headerlen); + s_GlobalMetadataHeader = (const Il2CppGlobalMetadataHeader*)Header; + + //s_GlobalMetadataHeader = (const Il2CppGlobalMetadataHeader*)s_GlobalMetadata; + + IL2CPP_ASSERT(s_GlobalMetadataHeader->sanity == 0xFAB11BAF); + IL2CPP_ASSERT(s_GlobalMetadataHeader->version == 24); + + // Pre-allocate these arrays so we don't need to lock when reading later. + // These arrays hold the runtime metadata representation for metadata explicitly + // referenced during conversion. There is a corresponding table of same size + // in the converted metadata, giving a description of runtime metadata to construct. + s_TypeInfoTable = (Il2CppClass**)IL2CPP_CALLOC(s_Il2CppMetadataRegistration->typesCount, sizeof(Il2CppClass*)); + s_TypeInfoDefinitionTable = (Il2CppClass**)IL2CPP_CALLOC(s_GlobalMetadataHeader->typeDefinitionsCount / sizeof(Il2CppTypeDefinition), sizeof(Il2CppClass*)); + s_MethodInfoDefinitionTable = (const MethodInfo**)IL2CPP_CALLOC(s_GlobalMetadataHeader->methodsCount / sizeof(Il2CppMethodDefinition), sizeof(MethodInfo*)); + s_GenericMethodTable = (const Il2CppGenericMethod**)IL2CPP_CALLOC(s_Il2CppMetadataRegistration->methodSpecsCount, sizeof(Il2CppGenericMethod*)); + s_ImagesCount = s_GlobalMetadataHeader->imagesCount / sizeof(Il2CppImageDefinition); + s_ImagesTable = (Il2CppImage*)IL2CPP_CALLOC(s_ImagesCount, sizeof(Il2CppImage)); + s_AssembliesCount = s_GlobalMetadataHeader->assembliesCount / sizeof(Il2CppAssemblyDefinition); + s_AssembliesTable = (Il2CppAssembly*)IL2CPP_CALLOC(s_AssembliesCount, sizeof(Il2CppAssembly)); + // setup all the Il2CppImages. There are not many and it avoid locks later on + const Il2CppImageDefinition* imagesDefinitions = (const Il2CppImageDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->imagesOffset); + for (int32_t imageIndex = 0; imageIndex < s_ImagesCount; imageIndex++) + { + const Il2CppImageDefinition* imageDefinition = imagesDefinitions + imageIndex; + Il2CppImage* image = s_ImagesTable + imageIndex; + image->name = GetStringFromIndex(imageDefinition->nameIndex); + + std::string nameNoExt = il2cpp::utils::PathUtils::PathNoExtension(image->name); + image->nameNoExt = (char*)IL2CPP_CALLOC(nameNoExt.size() + 1, sizeof(char)); + strcpy(const_cast<char*>(image->nameNoExt), nameNoExt.c_str()); + + image->assembly = const_cast<Il2CppAssembly*>(GetAssemblyFromIndex(imageDefinition->assemblyIndex)); + image->typeStart = imageDefinition->typeStart; + image->typeCount = imageDefinition->typeCount; + image->exportedTypeStart = imageDefinition->exportedTypeStart; + image->exportedTypeCount = imageDefinition->exportedTypeCount; + image->entryPointIndex = imageDefinition->entryPointIndex; + image->token = imageDefinition->token; + image->customAttributeStart = imageDefinition->customAttributeStart; + image->customAttributeCount = imageDefinition->customAttributeCount; + for (uint32_t codeGenModuleIndex = 0; codeGenModuleIndex < s_Il2CppCodeRegistration->codeGenModulesCount; ++codeGenModuleIndex) + { + if (strcmp(image->name, s_Il2CppCodeRegistration->codeGenModules[codeGenModuleIndex]->moduleName) == 0) + image->codeGenModule = s_Il2CppCodeRegistration->codeGenModules[codeGenModuleIndex]; + } + IL2CPP_ASSERT(image->codeGenModule); + image->dynamic = false; + } + + // setup all the Il2CppAssemblies. + const Il2CppAssemblyDefinition* assemblyDefinitions = (const Il2CppAssemblyDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->assembliesOffset); + for (int32_t assemblyIndex = 0; assemblyIndex < s_ImagesCount; assemblyIndex++) + { + const Il2CppAssemblyDefinition* assemblyDefinition = assemblyDefinitions + assemblyIndex; + Il2CppAssembly* assembly = s_AssembliesTable + assemblyIndex; + + assembly->image = il2cpp::vm::MetadataCache::GetImageFromIndex(assemblyDefinition->imageIndex); + assembly->token = assemblyDefinition->token; + assembly->referencedAssemblyStart = assemblyDefinition->referencedAssemblyStart; + assembly->referencedAssemblyCount = assemblyDefinition->referencedAssemblyCount; + + Il2CppAssemblyName* assemblyName = &assembly->aname; + const Il2CppAssemblyNameDefinition* assemblyNameDefinition = &assemblyDefinition->aname; + + assemblyName->name = GetStringFromIndex(assemblyNameDefinition->nameIndex); + assemblyName->culture = GetStringFromIndex(assemblyNameDefinition->cultureIndex); + assemblyName->public_key = (const uint8_t*)GetStringFromIndex(assemblyNameDefinition->publicKeyIndex); + assemblyName->hash_alg = assemblyNameDefinition->hash_alg; + assemblyName->hash_len = assemblyNameDefinition->hash_len; + assemblyName->flags = assemblyNameDefinition->flags; + assemblyName->major = assemblyNameDefinition->major; + assemblyName->minor = assemblyNameDefinition->minor; + assemblyName->build = assemblyNameDefinition->build; + assemblyName->revision = assemblyNameDefinition->revision; + memcpy(assemblyName->public_key_token, assemblyNameDefinition->public_key_token, sizeof(assemblyNameDefinition->public_key_token)); + + il2cpp::vm::Assembly::Register(assembly); + } + + InitializeUnresolvedSignatureTable(); + +#if IL2CPP_ENABLE_NATIVE_STACKTRACES + std::vector<MethodDefinitionKey> managedMethods; + + + const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); + for (int32_t i = 0; i < s_AssembliesCount; i++) + { + const Il2CppImage* image = s_AssembliesTable[i].image; + + for (size_t j = 0; j < image->typeCount; j++) + { + const Il2CppTypeDefinition* type = typeDefinitions + image->typeStart + j; + + for (uint16_t u = 0; u < type->method_count; u++) + { + const Il2CppMethodDefinition* methodDefinition = GetMethodDefinitionFromIndex(type->methodStart + u); + MethodDefinitionKey currentMethodList; + currentMethodList.methodIndex = type->methodStart + u; + currentMethodList.method = GetMethodPointer(image, methodDefinition->token); + if (currentMethodList.method) + managedMethods.push_back(currentMethodList); + } + } + } + + for (int32_t i = 0; i < s_Il2CppMetadataRegistration->genericMethodTableCount; i++) + { + const Il2CppGenericMethodFunctionsDefinitions* genericMethodIndices = s_Il2CppMetadataRegistration->genericMethodTable + i; + + MethodDefinitionKey currentMethodList; + + GenericMethodIndex genericMethodIndex = genericMethodIndices->genericMethodIndex; + + IL2CPP_ASSERT(genericMethodIndex < s_Il2CppMetadataRegistration->methodSpecsCount); + const Il2CppMethodSpec* methodSpec = s_Il2CppMetadataRegistration->methodSpecs + genericMethodIndex; + + currentMethodList.methodIndex = methodSpec->methodDefinitionIndex; + + IL2CPP_ASSERT(genericMethodIndices->indices.methodIndex < static_cast<int32_t>(s_Il2CppCodeRegistration->genericMethodPointersCount)); + currentMethodList.method = s_Il2CppCodeRegistration->genericMethodPointers[genericMethodIndices->indices.methodIndex]; + + managedMethods.push_back(currentMethodList); + } + + il2cpp::utils::NativeSymbol::RegisterMethods(managedMethods); +#endif + return true; +} +void il2cpp::vm::MetadataCache::InitializeStringLiteralTable() +{ + s_StringLiteralTable = (Il2CppString**)il2cpp::gc::GarbageCollector::AllocateFixed(s_GlobalMetadataHeader->stringLiteralCount / sizeof(Il2CppStringLiteral) * sizeof(Il2CppString*), NULL); +} + +void il2cpp::vm::MetadataCache::InitializeGenericMethodTable() +{ + for (int32_t i = 0; i < s_Il2CppMetadataRegistration->genericMethodTableCount; i++) + { + const Il2CppGenericMethodFunctionsDefinitions* genericMethodIndices = s_Il2CppMetadataRegistration->genericMethodTable + i; + const Il2CppGenericMethod* genericMethod = GetGenericMethodFromIndex(genericMethodIndices->genericMethodIndex); + s_MethodTableMap.insert(std::make_pair(genericMethod, &genericMethodIndices->indices)); + } +} + +void il2cpp::vm::MetadataCache::InitializeWindowsRuntimeTypeNamesTables() +{ + int32_t typeCount = s_GlobalMetadataHeader->windowsRuntimeTypeNamesSize / sizeof(Il2CppWindowsRuntimeTypeNamePair); + const Il2CppWindowsRuntimeTypeNamePair* windowsRuntimeTypeNames = MetadataOffset<Il2CppWindowsRuntimeTypeNamePair*>(s_GlobalMetadata, s_GlobalMetadataHeader->windowsRuntimeTypeNamesOffset, 0); + + for (int32_t i = 0; i < typeCount; i++) + { + Il2CppWindowsRuntimeTypeNamePair typeNamePair = windowsRuntimeTypeNames[i]; + const char* name = GetStringFromIndex(typeNamePair.nameIndex); + const Il2CppType* type = GetIl2CppTypeFromIndex(typeNamePair.typeIndex); + Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type); + + if (!Class::IsNullable(klass)) + { + // Don't add nullable types to name -> klass map because IReference`1<T> and Nullable`1<T> + // share windows runtime type names, and that would cause a collision. + s_WindowsRuntimeTypeNameToClassMap.insert(std::make_pair(name, klass)); + } + + s_ClassToWindowsRuntimeTypeNameMap.insert(std::make_pair(klass, name)); + } +} + +void il2cpp::vm::MetadataCache::InitializeGuidToClassTable() +{ + Il2CppInteropData* interopData = s_Il2CppCodeRegistration->interopData; + uint32_t interopDataCount = s_Il2CppCodeRegistration->interopDataCount; + std::vector<std::pair<const Il2CppGuid*, Il2CppClass*> > guidToNonImportClassMap; + guidToNonImportClassMap.reserve(interopDataCount); + + for (uint32_t i = 0; i < interopDataCount; i++) + { + // It's important to check for non-import types because type projections will have identical GUIDs (e.g. IEnumerable<T> and IIterable<T>) + if (interopData[i].guid != NULL) + { + Il2CppClass* klass = Class::FromIl2CppType(interopData[i].type); + if (!klass->is_import_or_windows_runtime) + guidToNonImportClassMap.push_back(std::make_pair(interopData[i].guid, klass)); + } + } + + s_GuidToNonImportClassMap.assign(guidToNonImportClassMap); +} + +// this is called later in the intialization cycle with more systems setup like GC +void il2cpp::vm::MetadataCache::InitializeGCSafe() +{ + InitializeStringLiteralTable(); + InitializeGenericMethodTable(); + InitializeWindowsRuntimeTypeNamesTables(); + InitializeGuidToClassTable(); +} + +void il2cpp::vm::MetadataCache::InitializeUnresolvedSignatureTable() +{ + s_pUnresolvedSignatureMap = new Il2CppUnresolvedSignatureMap(); + + for (uint32_t i = 0; i < s_Il2CppCodeRegistration->unresolvedVirtualCallCount; ++i) + { + const Il2CppRange* range = MetadataOffset<Il2CppRange*>(s_GlobalMetadata, s_GlobalMetadataHeader->unresolvedVirtualCallParameterRangesOffset, i); + il2cpp::utils::dynamic_array<const Il2CppType*> signature; + + for (int j = 0; j < range->length; ++j) + { + TypeIndex typeIndex = *MetadataOffset<TypeIndex*>(s_GlobalMetadata, s_GlobalMetadataHeader->unresolvedVirtualCallParameterTypesOffset, range->start + j); + const Il2CppType* type = il2cpp::vm::MetadataCache::GetIl2CppTypeFromIndex(typeIndex); + signature.push_back(type); + } + + (*s_pUnresolvedSignatureMap)[signature] = s_Il2CppCodeRegistration->unresolvedVirtualCallPointers[i]; + } +} + +Il2CppClass* il2cpp::vm::MetadataCache::GetGenericInstanceType(Il2CppClass* genericTypeDefinition, const il2cpp::metadata::Il2CppTypeVector& genericArgumentTypes) +{ + const Il2CppGenericInst* inst = il2cpp::vm::MetadataCache::GetGenericInst(genericArgumentTypes); + Il2CppGenericClass* genericClass = il2cpp::metadata::GenericMetadata::GetGenericClass(genericTypeDefinition, inst); + return il2cpp::vm::GenericClass::GetClass(genericClass); +} + +const MethodInfo* il2cpp::vm::MetadataCache::GetGenericInstanceMethod(const MethodInfo* genericMethodDefinition, const Il2CppGenericContext* context) +{ + const MethodInfo* method = genericMethodDefinition; + const Il2CppGenericInst* classInst = context->class_inst; + const Il2CppGenericInst* methodInst = context->method_inst; + if (genericMethodDefinition->is_inflated) + { + IL2CPP_ASSERT(genericMethodDefinition->klass->generic_class); + classInst = genericMethodDefinition->klass->generic_class->context.class_inst; + method = genericMethodDefinition->genericMethod->methodDefinition; + } + + const Il2CppGenericMethod* gmethod = GetGenericMethod(method, classInst, methodInst); + return il2cpp::metadata::GenericMethod::GetMethod(gmethod); +} + +const MethodInfo* il2cpp::vm::MetadataCache::GetGenericInstanceMethod(const MethodInfo* genericMethodDefinition, const il2cpp::metadata::Il2CppTypeVector& genericArgumentTypes) +{ + Il2CppGenericContext context = { NULL, GetGenericInst(genericArgumentTypes) }; + + return GetGenericInstanceMethod(genericMethodDefinition, &context); +} + +const Il2CppGenericContext* il2cpp::vm::MetadataCache::GetMethodGenericContext(const MethodInfo* method) +{ + if (!method->is_inflated) + { + IL2CPP_NOT_IMPLEMENTED(Image::GetMethodGenericContext); + return NULL; + } + + return &method->genericMethod->context; +} + +const MethodInfo* il2cpp::vm::MetadataCache::GetGenericMethodDefinition(const MethodInfo* method) +{ + if (!method->is_inflated) + { + IL2CPP_NOT_IMPLEMENTED(Image::GetGenericMethodDefinition); + return NULL; + } + + return method->genericMethod->methodDefinition; +} + +const Il2CppGenericContainer* il2cpp::vm::MetadataCache::GetMethodGenericContainer(const MethodInfo* method) +{ + return method->genericContainer; +} + +Il2CppClass* il2cpp::vm::MetadataCache::GetPointerType(Il2CppClass* type) +{ + il2cpp::os::FastAutoLock lock(&s_MetadataCache.m_CacheMutex); + + PointerTypeMap::const_iterator i = s_MetadataCache.m_PointerTypes.find(type); + if (i == s_MetadataCache.m_PointerTypes.end()) + return NULL; + + return i->second; +} + +Il2CppClass* il2cpp::vm::MetadataCache::GetWindowsRuntimeClass(const char* fullName) +{ + WindowsRuntimeTypeNameToClassMap::iterator it = s_WindowsRuntimeTypeNameToClassMap.find(fullName); + if (it != s_WindowsRuntimeTypeNameToClassMap.end()) + return it->second; + + return NULL; +} + +const char* il2cpp::vm::MetadataCache::GetWindowsRuntimeClassName(const Il2CppClass* klass) +{ + ClassToWindowsRuntimeTypeNameMap::iterator it = s_ClassToWindowsRuntimeTypeNameMap.find(klass); + if (it != s_ClassToWindowsRuntimeTypeNameMap.end()) + return it->second; + + return NULL; +} + +Il2CppMethodPointer il2cpp::vm::MetadataCache::GetWindowsRuntimeFactoryCreationFunction(const char* fullName) +{ + Il2CppClass* klass = GetWindowsRuntimeClass(fullName); + if (klass == NULL) + return NULL; + + WindowsRuntimeFactoryTable::iterator factoryEntry = s_WindowsRuntimeFactories.find_first(&klass->byval_arg); + if (factoryEntry == s_WindowsRuntimeFactories.end()) + return NULL; + + return factoryEntry->createFactoryFunction; +} + +Il2CppClass* il2cpp::vm::MetadataCache::GetClassForGuid(const Il2CppGuid* guid) +{ + IL2CPP_ASSERT(guid != NULL); + + GuidToClassMap::iterator it = s_GuidToNonImportClassMap.find_first(guid); + if (it != s_GuidToNonImportClassMap.end()) + return it->second; + + return NULL; +} + +void il2cpp::vm::MetadataCache::AddPointerType(Il2CppClass* type, Il2CppClass* pointerType) +{ + il2cpp::os::FastAutoLock lock(&s_MetadataCache.m_CacheMutex); + s_MetadataCache.m_PointerTypes.insert(std::make_pair(type, pointerType)); +} + +const Il2CppGenericInst* il2cpp::vm::MetadataCache::GetGenericInst(const Il2CppType* const* types, uint32_t typeCount) +{ + // temporary inst to lookup a permanent one that may already exist + Il2CppGenericInst inst; + inst.type_argc = typeCount; + inst.type_argv = (const Il2CppType**)alloca(inst.type_argc * sizeof(Il2CppType*)); + + size_t index = 0; + const Il2CppType* const* typesEnd = types + typeCount; + for (const Il2CppType* const* iter = types; iter != typesEnd; ++iter, ++index) + inst.type_argv[index] = *iter; + + { + // Acquire lock to check if inst has already been cached. + il2cpp::os::FastAutoLock lock(&s_MetadataCache.m_CacheMutex); + Il2CppGenericInstSet::const_iterator iter = s_GenericInstSet.find(&inst); + if (iter != s_GenericInstSet.end()) + return *iter; + } + + Il2CppGenericInst* newInst = NULL; + { + il2cpp::os::FastAutoLock lock(&g_MetadataLock); + newInst = (Il2CppGenericInst*)MetadataMalloc(sizeof(Il2CppGenericInst)); + newInst->type_argc = typeCount; + newInst->type_argv = (const Il2CppType**)MetadataMalloc(newInst->type_argc * sizeof(Il2CppType*)); + } + + index = 0; + for (const Il2CppType* const* iter = types; iter != typesEnd; ++iter, ++index) + newInst->type_argv[index] = *iter; + + { + // Acquire lock agains to attempt to cache inst. + il2cpp::os::FastAutoLock lock(&s_MetadataCache.m_CacheMutex); + // Another thread may have already added this inst or we may be the first. + // In either case, the iterator returned from 'insert' points to the item + // cached within the set. We can always return this. In the case of another + // thread beating us, the only downside is an extra allocation in the + // metadata memory pool that lives for life of process anyway. + auto result = s_GenericInstSet.insert(newInst); + if (result.second) + ++il2cpp_runtime_stats.generic_instance_count; + + return *(result.first); + } +} + +const Il2CppGenericInst* il2cpp::vm::MetadataCache::GetGenericInst(const il2cpp::metadata::Il2CppTypeVector& types) +{ + return GetGenericInst(&types[0], static_cast<uint32_t>(types.size())); +} + +static il2cpp::os::FastMutex s_GenericMethodMutex; +const Il2CppGenericMethod* il2cpp::vm::MetadataCache::GetGenericMethod(const MethodInfo* methodDefinition, const Il2CppGenericInst* classInst, const Il2CppGenericInst* methodInst) +{ + Il2CppGenericMethod method = { 0 }; + method.methodDefinition = methodDefinition; + method.context.class_inst = classInst; + method.context.method_inst = methodInst; + + il2cpp::os::FastAutoLock lock(&s_GenericMethodMutex); + Il2CppGenericMethodSet::const_iterator iter = s_GenericMethodSet.find(&method); + if (iter != s_GenericMethodSet.end()) + return *iter; + + Il2CppGenericMethod* newMethod = MetadataAllocGenericMethod(); + newMethod->methodDefinition = methodDefinition; + newMethod->context.class_inst = classInst; + newMethod->context.method_inst = methodInst; + + s_GenericMethodSet.insert(newMethod); + + return newMethod; +} + +static bool IsShareableEnum(const Il2CppType* type) +{ + // Base case for recursion - we've found an enum. + if (il2cpp::vm::Type::IsEnum(type)) + return true; + + if (il2cpp::vm::Type::IsGenericInstance(type)) + { + // Recursive case - look "inside" the generic instance type to see if this is a nested enum. + Il2CppClass* definition = il2cpp::vm::GenericClass::GetTypeDefinition(type->data.generic_class); + return IsShareableEnum(il2cpp::vm::Class::GetType(definition)); + } + + // Base case for recurion - this is not an enum or a generic instance type. + return false; +} + +// this logic must match the C# logic in GenericSharingAnalysis.GetSharedTypeForGenericParameter +static const Il2CppGenericInst* GetSharedInst(const Il2CppGenericInst* inst) +{ + if (inst == NULL) + return NULL; + + il2cpp::metadata::Il2CppTypeVector types; + for (uint32_t i = 0; i < inst->type_argc; ++i) + { + if (il2cpp::vm::Type::IsReference(inst->type_argv[i])) + types.push_back(&il2cpp_defaults.object_class->byval_arg); + else + { + const Il2CppType* type = inst->type_argv[i]; + if (s_Il2CppCodeGenOptions->enablePrimitiveValueTypeGenericSharing) + { + if (IsShareableEnum(type)) + { + const Il2CppType* underlyingType = il2cpp::vm::Type::GetUnderlyingType(type); + switch (underlyingType->type) + { + case IL2CPP_TYPE_I1: + type = &il2cpp_defaults.sbyte_shared_enum->byval_arg; + break; + case IL2CPP_TYPE_I2: + type = &il2cpp_defaults.int16_shared_enum->byval_arg; + break; + case IL2CPP_TYPE_I4: + type = &il2cpp_defaults.int32_shared_enum->byval_arg; + break; + case IL2CPP_TYPE_I8: + type = &il2cpp_defaults.int64_shared_enum->byval_arg; + break; + case IL2CPP_TYPE_U1: + type = &il2cpp_defaults.byte_shared_enum->byval_arg; + break; + case IL2CPP_TYPE_U2: + type = &il2cpp_defaults.uint16_shared_enum->byval_arg; + break; + case IL2CPP_TYPE_U4: + type = &il2cpp_defaults.uint32_shared_enum->byval_arg; + break; + case IL2CPP_TYPE_U8: + type = &il2cpp_defaults.uint64_shared_enum->byval_arg; + break; + default: + IL2CPP_ASSERT(0 && "Invalid enum underlying type"); + break; + } + } + } + + if (il2cpp::vm::Type::IsGenericInstance(type)) + { + const Il2CppGenericInst* sharedInst = GetSharedInst(type->data.generic_class->context.class_inst); + Il2CppGenericClass* gklass = il2cpp::metadata::GenericMetadata::GetGenericClass(type->data.generic_class->typeDefinitionIndex, sharedInst); + Il2CppClass* klass = il2cpp::vm::GenericClass::GetClass(gklass); + type = &klass->byval_arg; + } + types.push_back(type); + } + } + + const Il2CppGenericInst* sharedInst = il2cpp::vm::MetadataCache::GetGenericInst(types); + + return sharedInst; +} + +InvokerMethod il2cpp::vm::MetadataCache::GetInvokerMethodPointer(const MethodInfo* methodDefinition, const Il2CppGenericContext* context) +{ + Il2CppGenericMethod method = { 0 }; + method.methodDefinition = const_cast<MethodInfo*>(methodDefinition); + method.context.class_inst = context->class_inst; + method.context.method_inst = context->method_inst; + + Il2CppMethodTableMapIter iter = s_MethodTableMap.find(&method); + if (iter != s_MethodTableMap.end()) + { + IL2CPP_ASSERT(iter->second->invokerIndex >= 0); + if (static_cast<uint32_t>(iter->second->invokerIndex) < s_Il2CppCodeRegistration->invokerPointersCount) + return s_Il2CppCodeRegistration->invokerPointers[iter->second->invokerIndex]; + return NULL; + } + // get the shared version if it exists + method.context.class_inst = GetSharedInst(context->class_inst); + method.context.method_inst = GetSharedInst(context->method_inst); + + iter = s_MethodTableMap.find(&method); + if (iter != s_MethodTableMap.end()) + { + IL2CPP_ASSERT(iter->second->invokerIndex >= 0); + if (static_cast<uint32_t>(iter->second->invokerIndex) < s_Il2CppCodeRegistration->invokerPointersCount) + return s_Il2CppCodeRegistration->invokerPointers[iter->second->invokerIndex]; + return NULL; + } + + return NULL; +} + +Il2CppMethodPointer il2cpp::vm::MetadataCache::GetMethodPointer(const MethodInfo* methodDefinition, const Il2CppGenericContext* context) +{ + Il2CppGenericMethod method = { 0 }; + method.methodDefinition = const_cast<MethodInfo*>(methodDefinition); + method.context.class_inst = context->class_inst; + method.context.method_inst = context->method_inst; + + Il2CppMethodTableMapIter iter = s_MethodTableMap.find(&method); + if (iter != s_MethodTableMap.end()) + { + IL2CPP_ASSERT(iter->second->invokerIndex >= 0); + if (iter->second->adjustorThunkIndex != -1) + return s_Il2CppCodeRegistration->genericAdjustorThunks[iter->second->adjustorThunkIndex]; + + if (static_cast<uint32_t>(iter->second->methodIndex) < s_Il2CppCodeRegistration->genericMethodPointersCount) + return s_Il2CppCodeRegistration->genericMethodPointers[iter->second->methodIndex]; + return NULL; + } + + method.context.class_inst = GetSharedInst(context->class_inst); + method.context.method_inst = GetSharedInst(context->method_inst); + + iter = s_MethodTableMap.find(&method); + if (iter != s_MethodTableMap.end()) + { + IL2CPP_ASSERT(iter->second->invokerIndex >= 0); + if (iter->second->adjustorThunkIndex != -1) + return s_Il2CppCodeRegistration->genericAdjustorThunks[iter->second->adjustorThunkIndex]; + + if (static_cast<uint32_t>(iter->second->methodIndex) < s_Il2CppCodeRegistration->genericMethodPointersCount) + return s_Il2CppCodeRegistration->genericMethodPointers[iter->second->methodIndex]; + return NULL; + } + + return NULL; +} + +Il2CppClass* il2cpp::vm::MetadataCache::GetTypeInfoFromTypeIndex(TypeIndex index, bool throwOnError) +{ + if (index == kTypeIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index < s_Il2CppMetadataRegistration->typesCount && "Invalid type index "); + + if (s_TypeInfoTable[index]) + return s_TypeInfoTable[index]; + + const Il2CppType* type = s_Il2CppMetadataRegistration->types[index]; + Il2CppClass *klass = il2cpp::vm::Class::FromIl2CppType(type, throwOnError); + if (klass) + { + il2cpp::vm::ClassInlines::InitFromCodegen(klass); + s_TypeInfoTable[index] = klass; + } + + return s_TypeInfoTable[index]; +} + +const Il2CppType* il2cpp::vm::MetadataCache::GetIl2CppTypeFromIndex(TypeIndex index) +{ + if (index == kTypeIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index < s_Il2CppMetadataRegistration->typesCount && "Invalid type index "); + + return s_Il2CppMetadataRegistration->types[index]; +} + +const MethodInfo* il2cpp::vm::MetadataCache::GetMethodInfoFromIndex(EncodedMethodIndex methodIndex) +{ + uint32_t index = GetDecodedMethodIndex(methodIndex); + + if (index == 0) + return NULL; + + if (GetEncodedIndexType(methodIndex) == kIl2CppMetadataUsageMethodRef) + return il2cpp::metadata::GenericMethod::GetMethod(GetGenericMethodFromIndex(index)); + else + return il2cpp::vm::MetadataCache::GetMethodInfoFromMethodDefinitionIndex(index); +} + +const Il2CppGenericMethod* il2cpp::vm::MetadataCache::GetGenericMethodFromIndex(GenericMethodIndex index) +{ + IL2CPP_ASSERT(index < s_Il2CppMetadataRegistration->methodSpecsCount); + if (s_GenericMethodTable[index]) + return s_GenericMethodTable[index]; + + const Il2CppMethodSpec* methodSpec = s_Il2CppMetadataRegistration->methodSpecs + index; + const MethodInfo* methodDefinition = GetMethodInfoFromMethodDefinitionIndex(methodSpec->methodDefinitionIndex); + const Il2CppGenericInst* classInst = NULL; + const Il2CppGenericInst* methodInst = NULL; + if (methodSpec->classIndexIndex != -1) + { + IL2CPP_ASSERT(methodSpec->classIndexIndex < s_Il2CppMetadataRegistration->genericInstsCount); + classInst = s_Il2CppMetadataRegistration->genericInsts[methodSpec->classIndexIndex]; + } + if (methodSpec->methodIndexIndex != -1) + { + IL2CPP_ASSERT(methodSpec->methodIndexIndex < s_Il2CppMetadataRegistration->genericInstsCount); + methodInst = s_Il2CppMetadataRegistration->genericInsts[methodSpec->methodIndexIndex]; + } + s_GenericMethodTable[index] = GetGenericMethod(methodDefinition, classInst, methodInst); + + return s_GenericMethodTable[index]; +} + +static int CompareIl2CppTokenAdjustorThunkPair(const void* pkey, const void* pelem) +{ + return (int)(((Il2CppTokenAdjustorThunkPair*)pkey)->token - ((Il2CppTokenAdjustorThunkPair*)pelem)->token); +} + +Il2CppMethodPointer il2cpp::vm::MetadataCache::GetAdjustorThunk(const Il2CppImage* image, uint32_t token) +{ + if (image->codeGenModule->adjustorThunkCount == 0) + return NULL; + + Il2CppTokenAdjustorThunkPair key; + memset(&key, 0, sizeof(Il2CppTokenAdjustorThunkPair)); + key.token = token; + + const Il2CppTokenAdjustorThunkPair* result = (const Il2CppTokenAdjustorThunkPair*)bsearch(&key, image->codeGenModule->adjustorThunks, + image->codeGenModule->adjustorThunkCount, sizeof(Il2CppTokenAdjustorThunkPair), CompareIl2CppTokenAdjustorThunkPair); + + if (result == NULL) + return NULL; + + return result->adjustorThunk; +} + +Il2CppMethodPointer il2cpp::vm::MetadataCache::GetMethodPointer(const Il2CppImage* image, uint32_t token) +{ + uint32_t rid = GetTokenRowId(token); + uint32_t table = GetTokenType(token); + if (rid == 0) + return NULL; + + IL2CPP_ASSERT(rid <= image->codeGenModule->methodPointerCount); + + return image->codeGenModule->methodPointers[rid - 1]; +} + +InvokerMethod il2cpp::vm::MetadataCache::GetMethodInvoker(const Il2CppImage* image, uint32_t token) +{ + uint32_t rid = GetTokenRowId(token); + uint32_t table = GetTokenType(token); + if (rid == 0) + return NULL; + + int32_t index = image->codeGenModule->invokerIndices[rid - 1]; + + if (index == kMethodIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_Il2CppCodeRegistration->invokerPointersCount); + return s_Il2CppCodeRegistration->invokerPointers[index]; +} + +const Il2CppInteropData* il2cpp::vm::MetadataCache::GetInteropDataForType(const Il2CppType* type) +{ + IL2CPP_ASSERT(type != NULL); + InteropDataMap::iterator interopData = s_InteropData.find_first(type); + if (interopData == s_InteropData.end()) + return NULL; + + return interopData; +} + +static bool MatchTokens(Il2CppTokenIndexMethodTuple key, Il2CppTokenIndexMethodTuple element) +{ + return key.token < element.token; +} + +Il2CppMethodPointer il2cpp::vm::MetadataCache::GetReversePInvokeWrapper(const Il2CppImage* image, const MethodInfo* method) +{ + if (image->codeGenModule->reversePInvokeWrapperCount == 0) + return NULL; + + // For each image (i.e. assembly), the reverse pinvoke wrapper indices are in an array sorted by + // metadata token. Each entry also might have the method metadata pointer, which is used to further + // find methods that have a matching metadata token. + + Il2CppTokenIndexMethodTuple key; + memset(&key, 0, sizeof(Il2CppTokenIndexMethodTuple)); + key.token = method->token; + + // Binary search for a range which matches the metadata token. + auto begin = image->codeGenModule->reversePInvokeWrapperIndices; + auto end = image->codeGenModule->reversePInvokeWrapperIndices + image->codeGenModule->reversePInvokeWrapperCount; + auto matchingRange = std::equal_range(begin, end, key, &MatchTokens); + + int32_t index = -1; + auto numberOfMatches = std::distance(matchingRange.first, matchingRange.second); + if (numberOfMatches == 1) + { + // Normal case - we found one non-generic method. + index = matchingRange.first->index; + } + else if (numberOfMatches > 1) + { + // Multiple generic instance methods share the same token, since it is from the generic method definition. + // To find the proper method, look for the one with a matching method metadata pointer. + const Il2CppTokenIndexMethodTuple* currentMatch = matchingRange.first; + const Il2CppTokenIndexMethodTuple* lastMatch = matchingRange.second; + while (currentMatch != lastMatch) + { + // First, check the method metadata, and use it if it has been initialized. + // If not, let's fall back to the generic method. + const MethodInfo* possibleMatch = (const MethodInfo*)*currentMatch->method; + if (possibleMatch == NULL) + possibleMatch = il2cpp::metadata::GenericMethod::GetMethod(GetGenericMethodFromIndex(currentMatch->genericMethodIndex)); + if (possibleMatch == method) + { + index = currentMatch->index; + break; + } + currentMatch++; + } + } + + if (index == -1) + return NULL; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_Il2CppCodeRegistration->reversePInvokeWrapperCount); + return s_Il2CppCodeRegistration->reversePInvokeWrappers[index]; +} + +static const Il2CppType* GetReducedType(const Il2CppType* type) +{ + if (type->byref) + return &il2cpp_defaults.object_class->byval_arg; + + if (il2cpp::vm::Type::IsEnum(type)) + type = il2cpp::vm::Type::GetUnderlyingType(type); + + switch (type->type) + { + case IL2CPP_TYPE_BOOLEAN: + return &il2cpp_defaults.sbyte_class->byval_arg; + case IL2CPP_TYPE_CHAR: + return &il2cpp_defaults.int16_class->byval_arg; + case IL2CPP_TYPE_BYREF: + case IL2CPP_TYPE_CLASS: + case IL2CPP_TYPE_OBJECT: + case IL2CPP_TYPE_STRING: + case IL2CPP_TYPE_ARRAY: + case IL2CPP_TYPE_SZARRAY: + return &il2cpp_defaults.object_class->byval_arg; + case IL2CPP_TYPE_GENERICINST: + if (il2cpp::vm::Type::GenericInstIsValuetype(type)) + return type; + else + return &il2cpp_defaults.object_class->byval_arg; + default: + return type; + } +} + +Il2CppMethodPointer il2cpp::vm::MetadataCache::GetUnresolvedVirtualCallStub(const MethodInfo* method) +{ + il2cpp::utils::dynamic_array<const Il2CppType*> signature; + + signature.push_back(GetReducedType(method->return_type)); + for (int i = 0; i < method->parameters_count; ++i) + signature.push_back(GetReducedType(method->parameters[i].parameter_type)); + + Il2CppUnresolvedSignatureMapIter it = s_pUnresolvedSignatureMap->find(signature); + if (it != s_pUnresolvedSignatureMap->end()) + return it->second; + + return NULL; +} + +static const Il2CppImage* GetImageForTypeDefinitionIndex(TypeDefinitionIndex index) +{ + for (int32_t imageIndex = 0; imageIndex < s_ImagesCount; imageIndex++) + { + const Il2CppImage* image = s_ImagesTable + imageIndex; + IL2CPP_ASSERT(index >= 0); + if (index >= image->typeStart && static_cast<uint32_t>(index) < (image->typeStart + image->typeCount)) + return image; + } + + IL2CPP_ASSERT(0 && "Failed to find owning image for type"); + return NULL; +} + +enum PackingSize +{ + Zero, + One, + Two, + Four, + Eight, + Sixteen, + ThirtyTwo, + SixtyFour, + OneHundredTwentyEight +}; + +static uint8_t ConvertPackingSizeEnumToValue(PackingSize packingSize) +{ + switch (packingSize) + { + case Zero: + return 0; + case One: + return 1; + case Two: + return 2; + case Four: + return 4; + case Eight: + return 8; + case Sixteen: + return 16; + case ThirtyTwo: + return 32; + case SixtyFour: + return 64; + case OneHundredTwentyEight: + return 128; + default: + Assert(0 && "Invalid packing size!"); + return 0; + } +} + +static const int kBitIsValueType = 1; +static const int kBitIsEnum = 2; +static const int kBitHasFinalizer = 3; +static const int kBitHasStaticConstructor = 4; +static const int kBitIsBlittable = 5; +static const int kBitIsImportOrWindowsRuntime = 6; +static const int kPackingSize = 7; // This uses 4 bits from bit 7 to bit 10 +static const int kPackingSizeIsDefault = 11; +static const int kClassSizeIsDefault = 12; +static const int kSpecifiedPackingSize = 13; // This uses 4 bits from bit 13 to bit 16 + +int32_t il2cpp::vm::MetadataCache::StructLayoutPack(TypeDefinitionIndex index) +{ + const Il2CppTypeDefinition* typeDefinition = GetTypeDefinitionFromIndex(index); + return ConvertPackingSizeEnumToValue(static_cast<PackingSize>((typeDefinition->bitfield >> (kSpecifiedPackingSize - 1)) & 0xF)); +} + +bool il2cpp::vm::MetadataCache::StructLayoutPackIsDefault(TypeDefinitionIndex index) +{ + const Il2CppTypeDefinition* typeDefinition = GetTypeDefinitionFromIndex(index); + return (typeDefinition->bitfield >> (kPackingSizeIsDefault - 1)) & 0x1; +} + +bool il2cpp::vm::MetadataCache::StructLayoutSizeIsDefault(TypeDefinitionIndex index) +{ + const Il2CppTypeDefinition* typeDefinition = GetTypeDefinitionFromIndex(index); + return (typeDefinition->bitfield >> (kClassSizeIsDefault - 1)) & 0x1; +} + +static Il2CppClass* FromTypeDefinition(TypeDefinitionIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_GlobalMetadataHeader->typeDefinitionsCount / sizeof(Il2CppTypeDefinition)); + const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); + const Il2CppTypeDefinition* typeDefinition = typeDefinitions + index; + const Il2CppTypeDefinitionSizes* typeDefinitionSizes = s_Il2CppMetadataRegistration->typeDefinitionsSizes[index]; + Il2CppClass* typeInfo = (Il2CppClass*)IL2CPP_CALLOC(1, sizeof(Il2CppClass) + (sizeof(VirtualInvokeData) * typeDefinition->vtable_count)); + typeInfo->klass = typeInfo; + typeInfo->image = GetImageForTypeDefinitionIndex(index); + typeInfo->name = il2cpp::vm::MetadataCache::GetStringFromIndex(typeDefinition->nameIndex); + typeInfo->namespaze = il2cpp::vm::MetadataCache::GetStringFromIndex(typeDefinition->namespaceIndex); + typeInfo->byval_arg = *il2cpp::vm::MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->byvalTypeIndex); + typeInfo->this_arg = *il2cpp::vm::MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->byrefTypeIndex); + typeInfo->typeDefinition = typeDefinition; + typeInfo->genericContainerIndex = typeDefinition->genericContainerIndex; + typeInfo->instance_size = typeDefinitionSizes->instance_size; + typeInfo->actualSize = typeDefinitionSizes->instance_size; // actualySize is instance_size for compiler generated values + typeInfo->native_size = typeDefinitionSizes->native_size; + typeInfo->static_fields_size = typeDefinitionSizes->static_fields_size; + typeInfo->thread_static_fields_size = typeDefinitionSizes->thread_static_fields_size; + typeInfo->thread_static_fields_offset = -1; + typeInfo->flags = typeDefinition->flags; + typeInfo->valuetype = (typeDefinition->bitfield >> (kBitIsValueType - 1)) & 0x1; + typeInfo->enumtype = (typeDefinition->bitfield >> (kBitIsEnum - 1)) & 0x1; + typeInfo->is_generic = typeDefinition->genericContainerIndex != kGenericContainerIndexInvalid; // generic if we have a generic container + typeInfo->has_finalize = (typeDefinition->bitfield >> (kBitHasFinalizer - 1)) & 0x1; + typeInfo->has_cctor = (typeDefinition->bitfield >> (kBitHasStaticConstructor - 1)) & 0x1; + typeInfo->is_blittable = (typeDefinition->bitfield >> (kBitIsBlittable - 1)) & 0x1; + typeInfo->is_import_or_windows_runtime = (typeDefinition->bitfield >> (kBitIsImportOrWindowsRuntime - 1)) & 0x1; + typeInfo->packingSize = ConvertPackingSizeEnumToValue(static_cast<PackingSize>((typeDefinition->bitfield >> (kPackingSize - 1)) & 0xF)); + typeInfo->method_count = typeDefinition->method_count; + typeInfo->property_count = typeDefinition->property_count; + typeInfo->field_count = typeDefinition->field_count; + typeInfo->event_count = typeDefinition->event_count; + typeInfo->nested_type_count = typeDefinition->nested_type_count; + typeInfo->vtable_count = typeDefinition->vtable_count; + typeInfo->interfaces_count = typeDefinition->interfaces_count; + typeInfo->interface_offsets_count = typeDefinition->interface_offsets_count; + typeInfo->token = typeDefinition->token; + typeInfo->interopData = il2cpp::vm::MetadataCache::GetInteropDataForType(&typeInfo->byval_arg); + + if (typeDefinition->parentIndex != kTypeIndexInvalid) + typeInfo->parent = il2cpp::vm::Class::FromIl2CppType(il2cpp::vm::MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->parentIndex)); + + if (typeDefinition->declaringTypeIndex != kTypeIndexInvalid) + typeInfo->declaringType = il2cpp::vm::Class::FromIl2CppType(il2cpp::vm::MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->declaringTypeIndex)); + + typeInfo->castClass = typeInfo->element_class = typeInfo; + if (typeInfo->enumtype) + typeInfo->castClass = typeInfo->element_class = il2cpp::vm::Class::FromIl2CppType(il2cpp::vm::MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->elementTypeIndex)); + + return typeInfo; +} + +const Il2CppAssembly* il2cpp::vm::MetadataCache::GetAssemblyFromIndex(AssemblyIndex index) +{ + if (index == kGenericContainerIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index <= s_AssembliesCount); + return s_AssembliesTable + index; +} + +const Il2CppAssembly* il2cpp::vm::MetadataCache::GetAssemblyByName(const char* nameToFind) +{ + for (int i = 0; i < s_AssembliesCount; i++) + { + const Il2CppAssembly* assembly = s_AssembliesTable + i; + + const char* assemblyName = assembly->aname.name; + + if (strcmp(assemblyName, nameToFind) == 0) + return assembly; + } + + return NULL; +} + +Il2CppImage* il2cpp::vm::MetadataCache::GetImageFromIndex(ImageIndex index) +{ + if (index == kGenericContainerIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index <= s_ImagesCount); + return s_ImagesTable + index; +} + +Il2CppClass* il2cpp::vm::MetadataCache::GetTypeInfoFromTypeDefinitionIndex(TypeDefinitionIndex index) +{ + if (index == kTypeIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_GlobalMetadataHeader->typeDefinitionsCount / sizeof(Il2CppTypeDefinition)); + + if (!s_TypeInfoDefinitionTable[index]) + { + // we need to use the metadata lock, since we may need to retrieve other Il2CppClass's when setting. Our parent may be a generic instance for example + il2cpp::os::FastAutoLock lock(&g_MetadataLock); + // double checked locking + if (!s_TypeInfoDefinitionTable[index]) + s_TypeInfoDefinitionTable[index] = FromTypeDefinition(index); + } + + return s_TypeInfoDefinitionTable[index]; +} + +const Il2CppTypeDefinition* il2cpp::vm::MetadataCache::GetTypeDefinitionFromIndex(TypeDefinitionIndex index) +{ + if (index == kTypeDefinitionIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_GlobalMetadataHeader->typeDefinitionsCount / sizeof(Il2CppTypeDefinition)); + const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); + return typeDefinitions + index; +} + +TypeDefinitionIndex il2cpp::vm::MetadataCache::GetExportedTypeFromIndex(TypeDefinitionIndex index) +{ + if (index == kTypeDefinitionIndexInvalid) + return kTypeDefinitionIndexInvalid; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_GlobalMetadataHeader->exportedTypeDefinitionsCount / sizeof(TypeDefinitionIndex)); + TypeDefinitionIndex* exportedTypes = (TypeDefinitionIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->exportedTypeDefinitionsOffset); + return *(exportedTypes + index); +} + +const Il2CppGenericContainer* il2cpp::vm::MetadataCache::GetGenericContainerFromIndex(GenericContainerIndex index) +{ + if (index == kGenericContainerIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->genericContainersCount / sizeof(Il2CppGenericContainer)); + const Il2CppGenericContainer* genericContainers = (const Il2CppGenericContainer*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->genericContainersOffset); + return genericContainers + index; +} + +const Il2CppGenericParameter* il2cpp::vm::MetadataCache::GetGenericParameterFromIndex(GenericParameterIndex index) +{ + if (index == kGenericParameterIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->genericParametersCount / sizeof(Il2CppGenericParameter)); + const Il2CppGenericParameter* genericParameters = (const Il2CppGenericParameter*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->genericParametersOffset); + return genericParameters + index; +} + +const Il2CppType* il2cpp::vm::MetadataCache::GetGenericParameterConstraintFromIndex(GenericParameterConstraintIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->genericParameterConstraintsCount / sizeof(TypeIndex)); + const TypeIndex* constraintIndices = (const TypeIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->genericParameterConstraintsOffset); + + return GetIl2CppTypeFromIndex(constraintIndices[index]); +} + +Il2CppClass* il2cpp::vm::MetadataCache::GetNestedTypeFromIndex(NestedTypeIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->nestedTypesCount / sizeof(TypeDefinitionIndex)); + const TypeDefinitionIndex* nestedTypeIndices = (const TypeDefinitionIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->nestedTypesOffset); + + return GetTypeInfoFromTypeDefinitionIndex(nestedTypeIndices[index]); +} + +const Il2CppType* il2cpp::vm::MetadataCache::GetInterfaceFromIndex(InterfacesIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->interfacesCount / sizeof(TypeIndex)); + const TypeIndex* interfaceIndices = (const TypeIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->interfacesOffset); + + return GetIl2CppTypeFromIndex(interfaceIndices[index]); +} + +EncodedMethodIndex il2cpp::vm::MetadataCache::GetVTableMethodFromIndex(VTableIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->vtableMethodsCount / sizeof(EncodedMethodIndex)); + const EncodedMethodIndex* methodReferences = (const EncodedMethodIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->vtableMethodsOffset); + + return methodReferences[index]; +} + +Il2CppInterfaceOffsetPair il2cpp::vm::MetadataCache::GetInterfaceOffsetIndex(InterfaceOffsetIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->interfaceOffsetsCount / sizeof(Il2CppInterfaceOffsetPair)); + const Il2CppInterfaceOffsetPair* interfaceOffsets = (const Il2CppInterfaceOffsetPair*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->interfaceOffsetsOffset); + + return interfaceOffsets[index]; +} + +static int CompareIl2CppTokenRangePair(const void* pkey, const void* pelem) +{ + return (int)(((Il2CppTokenRangePair*)pkey)->token - ((Il2CppTokenRangePair*)pelem)->token); +} + +il2cpp::vm::RGCTXCollection il2cpp::vm::MetadataCache::GetRGCTXs(const Il2CppImage* image, uint32_t token) +{ + il2cpp::vm::RGCTXCollection collection = { 0, NULL }; + if (image->codeGenModule->rgctxRangesCount == 0) + return collection; + + Il2CppTokenRangePair key; + memset(&key, 0, sizeof(Il2CppTokenRangePair)); + key.token = token; + + const Il2CppTokenRangePair* res = (const Il2CppTokenRangePair*)bsearch(&key, image->codeGenModule->rgctxRanges, image->codeGenModule->rgctxRangesCount, sizeof(Il2CppTokenRangePair), CompareIl2CppTokenRangePair); + + if (res == NULL) + return collection; + + collection.count = res->range.length; + collection.items = image->codeGenModule->rgctxs + res->range.start; + + return collection; +} + +const Il2CppEventDefinition* il2cpp::vm::MetadataCache::GetEventDefinitionFromIndex(EventIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->eventsCount / sizeof(Il2CppEventDefinition)); + const Il2CppEventDefinition* events = (const Il2CppEventDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->eventsOffset); + return events + index; +} + +const Il2CppFieldDefinition* il2cpp::vm::MetadataCache::GetFieldDefinitionFromIndex(FieldIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->fieldsCount / sizeof(Il2CppFieldDefinition)); + const Il2CppFieldDefinition* fields = (const Il2CppFieldDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldsOffset); + return fields + index; +} + +const Il2CppFieldDefaultValue* il2cpp::vm::MetadataCache::GetFieldDefaultValueFromIndex(FieldIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->fieldDefaultValuesCount / sizeof(Il2CppFieldDefaultValue)); + const Il2CppFieldDefaultValue* defaultValues = (const Il2CppFieldDefaultValue*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldDefaultValuesOffset); + return defaultValues + index; +} + +const uint8_t* il2cpp::vm::MetadataCache::GetFieldDefaultValueDataFromIndex(FieldIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->fieldAndParameterDefaultValueDataCount / sizeof(uint8_t)); + const uint8_t* defaultValuesData = (const uint8_t*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldAndParameterDefaultValueDataOffset); + return defaultValuesData + index; +} + +const Il2CppFieldDefaultValue* il2cpp::vm::MetadataCache::GetFieldDefaultValueForField(const FieldInfo* field) +{ + Il2CppClass* parent = field->parent; + size_t fieldIndex = (field - parent->fields); + if (il2cpp::vm::Type::IsGenericInstance(&parent->byval_arg)) + fieldIndex += il2cpp::vm::GenericClass::GetTypeDefinition(parent->generic_class)->typeDefinition->fieldStart; + else + fieldIndex += parent->typeDefinition->fieldStart; + const Il2CppFieldDefaultValue *start = (const Il2CppFieldDefaultValue*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldDefaultValuesOffset); + const Il2CppFieldDefaultValue *entry = start; + while (entry < start + s_GlobalMetadataHeader->fieldDefaultValuesCount) + { + if (fieldIndex == entry->fieldIndex) + { + return entry; + } + entry++; + } + IL2CPP_ASSERT(0); + return NULL; +} + +const Il2CppParameterDefaultValue * il2cpp::vm::MetadataCache::GetParameterDefaultValueForParameter(const MethodInfo* method, const ParameterInfo* parameter) +{ + if (Method::IsGenericInstance(method)) + method = GetGenericMethodDefinition(method); + + IL2CPP_ASSERT(!Method::IsGenericInstance(method)); + + if (method->methodDefinition == NULL) + return NULL; + + size_t parameterIndex = method->methodDefinition->parameterStart + parameter->position; + const Il2CppParameterDefaultValue *start = (const Il2CppParameterDefaultValue*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->parameterDefaultValuesOffset); + const Il2CppParameterDefaultValue *entry = start; + while (entry < start + s_GlobalMetadataHeader->parameterDefaultValuesCount) + { + if (parameterIndex == entry->parameterIndex) + return entry; + entry++; + } + + return NULL; +} + +const uint8_t* il2cpp::vm::MetadataCache::GetParameterDefaultValueDataFromIndex(ParameterIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->fieldAndParameterDefaultValueDataCount / sizeof(uint8_t)); + const uint8_t* defaultValuesData = (const uint8_t*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldAndParameterDefaultValueDataOffset); + return defaultValuesData + index; +} + +int il2cpp::vm::MetadataCache::GetFieldMarshaledSizeForField(const FieldInfo* field) +{ + Il2CppClass* parent = field->parent; + size_t fieldIndex = (field - parent->fields); + fieldIndex += parent->typeDefinition->fieldStart; + const Il2CppFieldMarshaledSize *start = (const Il2CppFieldMarshaledSize*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldMarshaledSizesOffset); + const Il2CppFieldMarshaledSize *entry = start; + while ((intptr_t)entry < (intptr_t)start + s_GlobalMetadataHeader->fieldMarshaledSizesCount) + { + if (fieldIndex == entry->fieldIndex) + return entry->size; + entry++; + } + + return -1; +} + +const Il2CppMethodDefinition* il2cpp::vm::MetadataCache::GetMethodDefinitionFromIndex(MethodIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->methodsCount / sizeof(Il2CppMethodDefinition)); + const Il2CppMethodDefinition* methods = (const Il2CppMethodDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->methodsOffset); + return methods + index; +} + +const MethodInfo* il2cpp::vm::MetadataCache::GetMethodInfoFromMethodDefinitionIndex(MethodIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->methodsCount / sizeof(Il2CppMethodDefinition)); + + if (!s_MethodInfoDefinitionTable[index]) + { + const Il2CppMethodDefinition* methodDefinition = GetMethodDefinitionFromIndex(index); + Il2CppClass* typeInfo = GetTypeInfoFromTypeDefinitionIndex(methodDefinition->declaringType); + il2cpp::vm::Class::SetupMethods(typeInfo); + s_MethodInfoDefinitionTable[index] = typeInfo->methods[index - typeInfo->typeDefinition->methodStart]; + } + + return s_MethodInfoDefinitionTable[index]; +} + +const Il2CppPropertyDefinition* il2cpp::vm::MetadataCache::GetPropertyDefinitionFromIndex(PropertyIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->propertiesCount / sizeof(Il2CppPropertyDefinition)); + const Il2CppPropertyDefinition* properties = (const Il2CppPropertyDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->propertiesOffset); + return properties + index; +} + +const Il2CppParameterDefinition* il2cpp::vm::MetadataCache::GetParameterDefinitionFromIndex(ParameterIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->parametersCount / sizeof(Il2CppParameterDefinition)); + const Il2CppParameterDefinition* parameters = (const Il2CppParameterDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->parametersOffset); + return parameters + index; +} + +int32_t il2cpp::vm::MetadataCache::GetFieldOffsetFromIndexLocked(TypeIndex typeIndex, int32_t fieldIndexInType, FieldInfo* field, const il2cpp::os::FastAutoLock& lock) +{ + IL2CPP_ASSERT(typeIndex <= s_Il2CppMetadataRegistration->typeDefinitionsSizesCount); + int32_t offset = s_Il2CppMetadataRegistration->fieldOffsets[typeIndex][fieldIndexInType]; + if (offset < 0) + { + AddThreadLocalStaticOffsetForFieldLocked(field, offset & ~THREAD_LOCAL_STATIC_MASK, lock); + return THREAD_STATIC_FIELD_OFFSET; + } + return offset; +} + +void il2cpp::vm::MetadataCache::AddThreadLocalStaticOffsetForFieldLocked(FieldInfo* field, int32_t offset, const il2cpp::os::FastAutoLock& lock) +{ + s_ThreadLocalStaticOffsetMap.add(field, offset); +} + +int32_t il2cpp::vm::MetadataCache::GetThreadLocalStaticOffsetForField(FieldInfo* field) +{ + IL2CPP_ASSERT(field->offset == THREAD_STATIC_FIELD_OFFSET); + + il2cpp::os::FastAutoLock lock(&g_MetadataLock); + Il2CppThreadLocalStaticOffsetHashMapIter iter = s_ThreadLocalStaticOffsetMap.find(field); + IL2CPP_ASSERT(iter != s_ThreadLocalStaticOffsetMap.end()); + return iter->second; +} + +int32_t il2cpp::vm::MetadataCache::GetReferenceAssemblyIndexIntoAssemblyTable(int32_t referencedAssemblyTableIndex) +{ + IL2CPP_ASSERT(referencedAssemblyTableIndex >= 0 && static_cast<uint32_t>(referencedAssemblyTableIndex) <= s_GlobalMetadataHeader->referencedAssembliesCount / sizeof(int32_t)); + const int32_t* referenceAssemblyIndicies = (const int32_t*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->referencedAssembliesOffset); + return referenceAssemblyIndicies[referencedAssemblyTableIndex]; +} + +const TypeDefinitionIndex il2cpp::vm::MetadataCache::GetIndexForTypeDefinition(const Il2CppClass* typeDefinition) +{ + IL2CPP_ASSERT(typeDefinition->typeDefinition); + const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); + + IL2CPP_ASSERT(typeDefinition->typeDefinition >= typeDefinitions && typeDefinition->typeDefinition < typeDefinitions + s_GlobalMetadataHeader->typeDefinitionsCount); + + ptrdiff_t index = typeDefinition->typeDefinition - typeDefinitions; + IL2CPP_ASSERT(index <= std::numeric_limits<TypeDefinitionIndex>::max()); + return static_cast<TypeDefinitionIndex>(index); +} + +const GenericParameterIndex il2cpp::vm::MetadataCache::GetIndexForGenericParameter(const Il2CppGenericParameter* genericParameter) +{ + const Il2CppGenericParameter* genericParameters = (const Il2CppGenericParameter*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->genericParametersOffset); + + IL2CPP_ASSERT(genericParameter >= genericParameters && genericParameter < genericParameters + s_GlobalMetadataHeader->genericParametersCount); + + ptrdiff_t index = genericParameter - genericParameters; + IL2CPP_ASSERT(index <= std::numeric_limits<GenericParameterIndex>::max()); + return static_cast<GenericParameterIndex>(index); +} + +const MethodIndex il2cpp::vm::MetadataCache::GetIndexForMethodDefinition(const MethodInfo* method) +{ + IL2CPP_ASSERT(!method->is_inflated); + const Il2CppMethodDefinition* methodDefinitions = (const Il2CppMethodDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->methodsOffset); + + IL2CPP_ASSERT(method->methodDefinition >= methodDefinitions && method->methodDefinition < methodDefinitions + s_GlobalMetadataHeader->methodsCount); + + ptrdiff_t index = method->methodDefinition - methodDefinitions; + IL2CPP_ASSERT(index <= std::numeric_limits<MethodIndex>::max()); + return static_cast<MethodIndex>(index); +} + +static il2cpp::utils::OnceFlag s_CustomAttributesOnceFlag; + +static void InitializeCustomAttributesCaches(void* arg) +{ + s_CustomAttributesCaches = (CustomAttributesCache**)IL2CPP_CALLOC(s_Il2CppCodeRegistration->customAttributeCount, sizeof(CustomAttributesCache*)); +} + +CustomAttributesCache* il2cpp::vm::MetadataCache::GenerateCustomAttributesCache(CustomAttributeIndex index) +{ + if (index == kCustomAttributeIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && index < s_Il2CppCodeRegistration->customAttributeCount); + IL2CPP_ASSERT(index >= 0 && index < static_cast<int32_t>(s_GlobalMetadataHeader->attributesInfoCount / sizeof(Il2CppCustomAttributeTypeRange))); + + il2cpp::utils::CallOnce(s_CustomAttributesOnceFlag, &InitializeCustomAttributesCaches, NULL); + + // use atomics rather than a Mutex here to avoid deadlock. The attribute generators call arbitrary managed code + CustomAttributesCache* cache = il2cpp::os::Atomic::ReadPointer(&s_CustomAttributesCaches[index]); + if (cache == NULL) + { + const Il2CppCustomAttributeTypeRange* attributeTypeRange = MetadataOffset<const Il2CppCustomAttributeTypeRange*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributesInfoOffset, index); + + cache = (CustomAttributesCache*)IL2CPP_CALLOC(1, sizeof(CustomAttributesCache)); + cache->count = attributeTypeRange->count; + cache->attributes = (Il2CppObject**)il2cpp::gc::GarbageCollector::AllocateFixed(sizeof(Il2CppObject *) * cache->count, 0); + + for (int32_t i = 0; i < attributeTypeRange->count; i++) + { + IL2CPP_ASSERT(attributeTypeRange->start + i < s_GlobalMetadataHeader->attributeTypesCount); + TypeIndex typeIndex = *MetadataOffset<TypeIndex*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeTypesOffset, attributeTypeRange->start + i); + cache->attributes[i] = il2cpp::vm::Object::New(GetTypeInfoFromTypeIndex(typeIndex)); + il2cpp::gc::GarbageCollector::SetWriteBarrier((void**)cache->attributes + i); + } + + // generated code calls the attribute constructor and sets any fields/properties + s_Il2CppCodeRegistration->customAttributeGenerators[index](cache); + + CustomAttributesCache* original = il2cpp::os::Atomic::CompareExchangePointer(&s_CustomAttributesCaches[index], cache, (CustomAttributesCache*)NULL); + if (original) + { + // A non-NULL return value indicates some other thread already generated this cache. + // We need to cleanup the resources we allocated + il2cpp::gc::GarbageCollector::FreeFixed(cache->attributes); + IL2CPP_FREE(cache); + + cache = original; + } + } + + return cache; +} + +static int CompareTokens(const void* pkey, const void* pelem) +{ + return (int)(((Il2CppCustomAttributeTypeRange*)pkey)->token - ((Il2CppCustomAttributeTypeRange*)pelem)->token); +} + +CustomAttributeIndex il2cpp::vm::MetadataCache::GetCustomAttributeIndex(const Il2CppImage* image, uint32_t token) +{ + const Il2CppCustomAttributeTypeRange* attributeTypeRange = MetadataOffset<const Il2CppCustomAttributeTypeRange*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributesInfoOffset, 0); + + Il2CppCustomAttributeTypeRange key; + memset(&key, 0, sizeof(Il2CppCustomAttributeTypeRange)); + key.token = token; + + const Il2CppCustomAttributeTypeRange* res = (const Il2CppCustomAttributeTypeRange*)bsearch(&key, attributeTypeRange + image->customAttributeStart, image->customAttributeCount, sizeof(Il2CppCustomAttributeTypeRange), CompareTokens); + + if (res == NULL) + return kCustomAttributeIndexInvalid; + + CustomAttributeIndex index = (CustomAttributeIndex)(res - attributeTypeRange); + + IL2CPP_ASSERT(index >= 0 && index < static_cast<int32_t>(s_GlobalMetadataHeader->attributesInfoCount / sizeof(Il2CppCustomAttributeTypeRange))); + + return index; +} + +CustomAttributesCache* il2cpp::vm::MetadataCache::GenerateCustomAttributesCache(const Il2CppImage* image, uint32_t token) +{ + return GenerateCustomAttributesCache(GetCustomAttributeIndex(image, token)); +} + +bool il2cpp::vm::MetadataCache::HasAttribute(CustomAttributeIndex index, Il2CppClass* attribute) +{ + if (index == kCustomAttributeIndexInvalid) + return false; + + IL2CPP_ASSERT(attribute); + + const Il2CppCustomAttributeTypeRange* attributeTypeRange = MetadataOffset<const Il2CppCustomAttributeTypeRange*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributesInfoOffset, index); + + for (int32_t i = 0; i < attributeTypeRange->count; i++) + { + IL2CPP_ASSERT(attributeTypeRange->start + i < s_GlobalMetadataHeader->attributeTypesCount); + TypeIndex typeIndex = *MetadataOffset<TypeIndex*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeTypesOffset, attributeTypeRange->start + i); + Il2CppClass* klass = GetTypeInfoFromTypeIndex(typeIndex); + + if (il2cpp::vm::Class::HasParent(klass, attribute) || (il2cpp::vm::Class::IsInterface(attribute) && il2cpp::vm::Class::IsAssignableFrom(attribute, klass))) + return true; + } + + return false; +} + +bool il2cpp::vm::MetadataCache::HasAttribute(const Il2CppImage* image, uint32_t token, Il2CppClass* attribute) +{ + return HasAttribute(GetCustomAttributeIndex(image, token), attribute); +} + +int skip = *|*|*#skip#*|*|*; +int key = *|*|*#key#*|*|*; + +Il2CppString* il2cpp::vm::MetadataCache::GetStringLiteralFromIndex(StringLiteralIndex index) +{ + if (index == kStringLiteralIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_GlobalMetadataHeader->stringLiteralCount / sizeof(Il2CppStringLiteral) && "Invalid string literal index "); + + if (s_StringLiteralTable[index]) + return s_StringLiteralTable[index]; + + const Il2CppStringLiteral* stringLiteral = (const Il2CppStringLiteral*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->stringLiteralOffset) + index; + + //解密流程 + char* str = (char*)malloc(stringLiteral->length);//申请内存 + memcpy(str,(const char*)s_GlobalMetadata + s_GlobalMetadataHeader->stringLiteralDataOffset + stringLiteral->dataIndex,stringLiteral->length); + for (size_t i = 0; i < stringLiteral->length; i++)//解密字符串 + { + str[i] ^= key; + } + s_StringLiteralTable[index] = String::NewLen((const char*)str, stringLiteral->length); + il2cpp::gc::GarbageCollector::SetWriteBarrier((void**)s_StringLiteralTable + index); + + + return s_StringLiteralTable[index]; +} + +const char* il2cpp::vm::MetadataCache::GetStringFromIndex(StringIndex index) +{ + IL2CPP_ASSERT(index <= s_GlobalMetadataHeader->stringCount); + const char* strings = ((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->stringOffset) + index; + + auto length = strlen(strings); + auto buffer = (char*)IL2CPP_CALLOC(length + 1, sizeof(char)); + memset(buffer, 0, length + 1); + //uint8_t* uintBuffer = (uint8_t*)(buffer); + for (size_t i = 0; i < length; i++) + { + if(strings[i] != skip && strings[i] != 0) + buffer[i] = strings[i] ^ key; + else + buffer[i] = strings[i]; + } + return buffer; +} + +FieldInfo* il2cpp::vm::MetadataCache::GetFieldInfoFromIndex(EncodedMethodIndex index) +{ + IL2CPP_ASSERT(s_GlobalMetadataHeader->fieldRefsCount >= 0 && index <= static_cast<uint32_t>(s_GlobalMetadataHeader->fieldRefsCount)); + + const Il2CppFieldRef* fieldRef = MetadataOffset<const Il2CppFieldRef*>(s_GlobalMetadata, s_GlobalMetadataHeader->fieldRefsOffset, index); + Il2CppClass* typeInfo = GetTypeInfoFromTypeIndex(fieldRef->typeIndex); + return typeInfo->fields + fieldRef->fieldIndex; +} + +static bool IsMatchingUsage(Il2CppMetadataUsage usage, const il2cpp::utils::dynamic_array<Il2CppMetadataUsage>& expectedUsages) +{ + if (expectedUsages.empty()) + return true; + + size_t numberOfExpectedUsages = expectedUsages.size(); + for (size_t i = 0; i < numberOfExpectedUsages; ++i) + { + if (expectedUsages[i] == usage) + return true; + } + + return false; +} + +// This method can be called from multiple threads, so it does have a data race. However, each +// thread is reading from the same read-only metadata, so each thread will set the same values. +// Therefore, we can safely ignore thread sanitizer issues in this method. +void il2cpp::vm::MetadataCache::IntializeMethodMetadataRange(uint32_t start, uint32_t count, const il2cpp::utils::dynamic_array<Il2CppMetadataUsage>& expectedUsages, bool throwOnError) IL2CPP_DISABLE_TSAN +{ + for (uint32_t i = 0; i < count; i++) + { + uint32_t offset = start + i; + IL2CPP_ASSERT(s_GlobalMetadataHeader->metadataUsagePairsCount >= 0 && offset <= static_cast<uint32_t>(s_GlobalMetadataHeader->metadataUsagePairsCount)); + const Il2CppMetadataUsagePair* metadataUsagePairs = MetadataOffset<const Il2CppMetadataUsagePair*>(s_GlobalMetadata, s_GlobalMetadataHeader->metadataUsagePairsOffset, offset); + uint32_t destinationIndex = metadataUsagePairs->destinationIndex; + uint32_t encodedSourceIndex = metadataUsagePairs->encodedSourceIndex; + + Il2CppMetadataUsage usage = GetEncodedIndexType(encodedSourceIndex); + if (IsMatchingUsage(usage, expectedUsages)) + { + uint32_t decodedIndex = GetDecodedMethodIndex(encodedSourceIndex); + switch (usage) + { + case kIl2CppMetadataUsageTypeInfo: + *s_Il2CppMetadataRegistration->metadataUsages[destinationIndex] = GetTypeInfoFromTypeIndex(decodedIndex, throwOnError); + break; + case kIl2CppMetadataUsageIl2CppType: + *s_Il2CppMetadataRegistration->metadataUsages[destinationIndex] = const_cast<Il2CppType*>(GetIl2CppTypeFromIndex(decodedIndex)); + break; + case kIl2CppMetadataUsageMethodDef: + case kIl2CppMetadataUsageMethodRef: + *s_Il2CppMetadataRegistration->metadataUsages[destinationIndex] = const_cast<MethodInfo*>(GetMethodInfoFromIndex(encodedSourceIndex)); + break; + case kIl2CppMetadataUsageFieldInfo: + *s_Il2CppMetadataRegistration->metadataUsages[destinationIndex] = GetFieldInfoFromIndex(decodedIndex); + break; + case kIl2CppMetadataUsageStringLiteral: + *s_Il2CppMetadataRegistration->metadataUsages[destinationIndex] = GetStringLiteralFromIndex(decodedIndex); + break; + default: + IL2CPP_NOT_IMPLEMENTED(il2cpp::vm::MetadataCache::InitializeMethodMetadata); + break; + } + } + } +} + +void il2cpp::vm::MetadataCache::InitializeAllMethodMetadata() +{ + il2cpp::utils::dynamic_array<Il2CppMetadataUsage> onlyAcceptMethodUsages; + onlyAcceptMethodUsages.push_back(kIl2CppMetadataUsageMethodDef); + onlyAcceptMethodUsages.push_back(kIl2CppMetadataUsageMethodRef); + onlyAcceptMethodUsages.push_back(kIl2CppMetadataUsageTypeInfo); + IntializeMethodMetadataRange(0, s_GlobalMetadataHeader->metadataUsagePairsCount / sizeof(Il2CppMetadataUsagePair), onlyAcceptMethodUsages, false); +} + +void il2cpp::vm::MetadataCache::InitializeMethodMetadata(uint32_t index) +{ + IL2CPP_ASSERT(s_GlobalMetadataHeader->metadataUsageListsCount >= 0 && index <= static_cast<uint32_t>(s_GlobalMetadataHeader->metadataUsageListsCount)); + + const Il2CppMetadataUsageList* metadataUsageLists = MetadataOffset<const Il2CppMetadataUsageList*>(s_GlobalMetadata, s_GlobalMetadataHeader->metadataUsageListsOffset, index); + + uint32_t start = metadataUsageLists->start; + uint32_t count = metadataUsageLists->count; + + il2cpp::utils::dynamic_array<Il2CppMetadataUsage> acceptAllUsages; + IntializeMethodMetadataRange(start, count, acceptAllUsages, true); +} + +void il2cpp::vm::MetadataCache::WalkPointerTypes(WalkTypesCallback callback, void* context) +{ + il2cpp::os::FastAutoLock lock(&s_MetadataCache.m_CacheMutex); + for (PointerTypeMap::iterator it = s_MetadataCache.m_PointerTypes.begin(); it != s_MetadataCache.m_PointerTypes.end(); it++) + { + callback(it->second, context); + } +} diff --git a/O&Z_IL2CPP_Security/resource/src-res/24.4/il2cpp-metadata.h b/O&Z_IL2CPP_Security/resource/src-res/24.4/il2cpp-metadata.h new file mode 100644 index 0000000..364bf3b --- /dev/null +++ b/O&Z_IL2CPP_Security/resource/src-res/24.4/il2cpp-metadata.h @@ -0,0 +1,490 @@ +#pragma once + +#include "il2cpp-config.h" +#include <stdint.h> +#include "il2cpp-tokentype.h" + +// This file contains the structures specifying how we store converted metadata. +// These structures have 3 constraints: +// 1. These structures will be stored in an external file, and as such must not contain any pointers. +// All references to other metadata should occur via an index into a corresponding table. +// 2. These structures are assumed to be const. Either const structures in the binary or mapped as +// readonly memory from an external file. Do not add any 'calculated' fields which will be written to at runtime. +// 3. These structures should be optimized for size. Other structures are used at runtime which can +// be larger to store cached information + +typedef int32_t TypeIndex; +typedef int32_t TypeDefinitionIndex; +typedef int32_t FieldIndex; +typedef int32_t DefaultValueIndex; +typedef int32_t DefaultValueDataIndex; +typedef int32_t CustomAttributeIndex; +typedef int32_t ParameterIndex; +typedef int32_t MethodIndex; +typedef int32_t GenericMethodIndex; +typedef int32_t PropertyIndex; +typedef int32_t EventIndex; +typedef int32_t GenericContainerIndex; +typedef int32_t GenericParameterIndex; +typedef int16_t GenericParameterConstraintIndex; +typedef int32_t NestedTypeIndex; +typedef int32_t InterfacesIndex; +typedef int32_t VTableIndex; +typedef int32_t InterfaceOffsetIndex; +typedef int32_t RGCTXIndex; +typedef int32_t StringIndex; +typedef int32_t StringLiteralIndex; +typedef int32_t GenericInstIndex; +typedef int32_t ImageIndex; +typedef int32_t AssemblyIndex; +typedef int32_t InteropDataIndex; + +static const TypeIndex kTypeIndexInvalid = -1; +static const TypeDefinitionIndex kTypeDefinitionIndexInvalid = -1; +static const DefaultValueDataIndex kDefaultValueIndexNull = -1; +static const CustomAttributeIndex kCustomAttributeIndexInvalid = -1; +static const EventIndex kEventIndexInvalid = -1; +static const FieldIndex kFieldIndexInvalid = -1; +static const MethodIndex kMethodIndexInvalid = -1; +static const PropertyIndex kPropertyIndexInvalid = -1; +static const GenericContainerIndex kGenericContainerIndexInvalid = -1; +static const GenericParameterIndex kGenericParameterIndexInvalid = -1; +static const RGCTXIndex kRGCTXIndexInvalid = -1; +static const StringLiteralIndex kStringLiteralIndexInvalid = -1; +static const InteropDataIndex kInteropDataIndexInvalid = -1; + +// Encoded index (1 bit) +// MethodDef - 0 +// MethodSpec - 1 +// We use the top 3 bits to indicate what table to index into +// Type Binary Hex +// Il2CppClass 001 0x20000000 +// Il2CppType 010 0x40000000 +// MethodInfo 011 0x60000000 +// FieldInfo 100 0x80000000 +// StringLiteral 101 0xA0000000 +// MethodRef 110 0xC0000000 + +typedef uint32_t EncodedMethodIndex; + +enum Il2CppMetadataUsage +{ + kIl2CppMetadataUsageInvalid, + kIl2CppMetadataUsageTypeInfo, + kIl2CppMetadataUsageIl2CppType, + kIl2CppMetadataUsageMethodDef, + kIl2CppMetadataUsageFieldInfo, + kIl2CppMetadataUsageStringLiteral, + kIl2CppMetadataUsageMethodRef, +}; + +#ifdef __cplusplus +static inline Il2CppMetadataUsage GetEncodedIndexType(EncodedMethodIndex index) +{ + return (Il2CppMetadataUsage)((index & 0xE0000000) >> 29); +} + +static inline uint32_t GetDecodedMethodIndex(EncodedMethodIndex index) +{ + return index & 0x1FFFFFFFU; +} + +static inline uint32_t GetTokenType(uint32_t token) +{ + return token & 0xFF000000; +} + +static inline uint32_t GetTokenRowId(uint32_t token) +{ + return token & 0x00FFFFFF; +} + +#endif + +struct Il2CppImage; +struct Il2CppType; +struct Il2CppTypeDefinitionMetadata; + +typedef union Il2CppRGCTXDefinitionData +{ + int32_t rgctxDataDummy; + MethodIndex methodIndex; + TypeIndex typeIndex; +} Il2CppRGCTXDefinitionData; + +typedef enum Il2CppRGCTXDataType +{ + IL2CPP_RGCTX_DATA_INVALID, + IL2CPP_RGCTX_DATA_TYPE, + IL2CPP_RGCTX_DATA_CLASS, + IL2CPP_RGCTX_DATA_METHOD, + IL2CPP_RGCTX_DATA_ARRAY, +} Il2CppRGCTXDataType; + +#if RUNTIME_MONO + +typedef struct MonoRGCTXDefinition +{ + Il2CppRGCTXDataType type; + AssemblyIndex assemblyIndex; + int32_t token; + int32_t generic_parameter_index; +} MonoRGCTXDefinition; + +#else + +typedef struct Il2CppRGCTXDefinition +{ + Il2CppRGCTXDataType type; + Il2CppRGCTXDefinitionData data; +} Il2CppRGCTXDefinition; + +#endif + +typedef struct Il2CppInterfaceOffsetPair +{ + TypeIndex interfaceTypeIndex; + int32_t offset; +} Il2CppInterfaceOffsetPair; + +typedef struct Il2CppTypeDefinition +{ + StringIndex nameIndex; + StringIndex namespaceIndex; + TypeIndex byvalTypeIndex; + TypeIndex byrefTypeIndex; + + TypeIndex declaringTypeIndex; + TypeIndex parentIndex; + TypeIndex elementTypeIndex; // we can probably remove this one. Only used for enums + + GenericContainerIndex genericContainerIndex; + + uint32_t flags; + + FieldIndex fieldStart; + MethodIndex methodStart; + EventIndex eventStart; + PropertyIndex propertyStart; + NestedTypeIndex nestedTypesStart; + InterfacesIndex interfacesStart; + VTableIndex vtableStart; + InterfacesIndex interfaceOffsetsStart; + + uint16_t method_count; + uint16_t property_count; + uint16_t field_count; + uint16_t event_count; + uint16_t nested_type_count; + uint16_t vtable_count; + uint16_t interfaces_count; + uint16_t interface_offsets_count; + + // bitfield to portably encode boolean values as single bits + // 01 - valuetype; + // 02 - enumtype; + // 03 - has_finalize; + // 04 - has_cctor; + // 05 - is_blittable; + // 06 - is_import_or_windows_runtime; + // 07-10 - One of nine possible PackingSize values (0, 1, 2, 4, 8, 16, 32, 64, or 128) + // 11 - PackingSize is default + // 12 - ClassSize is default + // 13-16 - One of nine possible PackingSize values (0, 1, 2, 4, 8, 16, 32, 64, or 128) - the specified packing size (even for explicit layouts) + uint32_t bitfield; + uint32_t token; +} Il2CppTypeDefinition; + +typedef struct Il2CppFieldDefinition +{ + StringIndex nameIndex; + TypeIndex typeIndex; + uint32_t token; +} Il2CppFieldDefinition; + +typedef struct Il2CppFieldDefaultValue +{ + FieldIndex fieldIndex; + TypeIndex typeIndex; + DefaultValueDataIndex dataIndex; +} Il2CppFieldDefaultValue; + +typedef struct Il2CppFieldMarshaledSize +{ + FieldIndex fieldIndex; + TypeIndex typeIndex; + int32_t size; +} Il2CppFieldMarshaledSize; + +typedef struct Il2CppFieldRef +{ + TypeIndex typeIndex; + FieldIndex fieldIndex; // local offset into type fields +} Il2CppFieldRef; + +typedef struct Il2CppParameterDefinition +{ + StringIndex nameIndex; + uint32_t token; + TypeIndex typeIndex; +} Il2CppParameterDefinition; + +typedef struct Il2CppParameterDefaultValue +{ + ParameterIndex parameterIndex; + TypeIndex typeIndex; + DefaultValueDataIndex dataIndex; +} Il2CppParameterDefaultValue; + +typedef struct Il2CppMethodDefinition +{ + StringIndex nameIndex; + TypeDefinitionIndex declaringType; + TypeIndex returnType; + ParameterIndex parameterStart; + GenericContainerIndex genericContainerIndex; + uint32_t token; + uint16_t flags; + uint16_t iflags; + uint16_t slot; + uint16_t parameterCount; +} Il2CppMethodDefinition; + +typedef struct Il2CppEventDefinition +{ + StringIndex nameIndex; + TypeIndex typeIndex; + MethodIndex add; + MethodIndex remove; + MethodIndex raise; + uint32_t token; +} Il2CppEventDefinition; + +typedef struct Il2CppPropertyDefinition +{ + StringIndex nameIndex; + MethodIndex get; + MethodIndex set; + uint32_t attrs; + uint32_t token; +} Il2CppPropertyDefinition; + +typedef struct Il2CppMethodSpec +{ + MethodIndex methodDefinitionIndex; + GenericInstIndex classIndexIndex; + GenericInstIndex methodIndexIndex; +} Il2CppMethodSpec; + +typedef struct Il2CppStringLiteral +{ + StringLiteralIndex dataIndex; + uint32_t length; + //StringLiteralIndex dataIndex; +} Il2CppStringLiteral; + +typedef struct +{ + MethodIndex methodIndex; + MethodIndex invokerIndex; + MethodIndex adjustorThunkIndex; +} Il2CppGenericMethodIndices; + +typedef struct Il2CppGenericMethodFunctionsDefinitions +{ + GenericMethodIndex genericMethodIndex; + Il2CppGenericMethodIndices indices; +} Il2CppGenericMethodFunctionsDefinitions; + +#define PUBLIC_KEY_BYTE_LENGTH 8 +static const int kPublicKeyByteLength = PUBLIC_KEY_BYTE_LENGTH; + +typedef struct Il2CppAssemblyNameDefinition +{ + StringIndex nameIndex; + StringIndex cultureIndex; + StringIndex publicKeyIndex; + uint32_t hash_alg; + int32_t hash_len; + uint32_t flags; + int32_t major; + int32_t minor; + int32_t build; + int32_t revision; + uint8_t public_key_token[PUBLIC_KEY_BYTE_LENGTH]; +} Il2CppAssemblyNameDefinition; + +typedef struct Il2CppImageDefinition +{ + StringIndex nameIndex; + AssemblyIndex assemblyIndex; + + TypeDefinitionIndex typeStart; + uint32_t typeCount; + + TypeDefinitionIndex exportedTypeStart; + uint32_t exportedTypeCount; + + MethodIndex entryPointIndex; + uint32_t token; + + CustomAttributeIndex customAttributeStart; + uint32_t customAttributeCount; +} Il2CppImageDefinition; + +typedef struct Il2CppAssemblyDefinition +{ + ImageIndex imageIndex; + uint32_t token; + int32_t referencedAssemblyStart; + int32_t referencedAssemblyCount; + Il2CppAssemblyNameDefinition aname; +} Il2CppAssemblyDefinition; + +typedef struct Il2CppMetadataUsageList +{ + uint32_t start; + uint32_t count; +} Il2CppMetadataUsageList; + +typedef struct Il2CppMetadataUsagePair +{ + uint32_t destinationIndex; + uint32_t encodedSourceIndex; +} Il2CppMetadataUsagePair; + +typedef struct Il2CppCustomAttributeTypeRange +{ + uint32_t token; + int32_t start; + int32_t count; +} Il2CppCustomAttributeTypeRange; + +typedef struct Il2CppRange +{ + int32_t start; + int32_t length; +} Il2CppRange; + +typedef struct Il2CppWindowsRuntimeTypeNamePair +{ + StringIndex nameIndex; + TypeIndex typeIndex; +} Il2CppWindowsRuntimeTypeNamePair; + +#pragma pack(push, p1,4) +typedef struct Il2CppGlobalMetadataHeader +{ + int32_t sanity; + int32_t stringLiteralCount; + int32_t stringLiteralDataCount; + int32_t stringCount; + int32_t eventsCount; + int32_t propertiesCount; + int32_t methodsCount; + int32_t parameterDefaultValuesCount; + int32_t fieldDefaultValuesCount; + int32_t fieldAndParameterDefaultValueDataCount; + int32_t fieldMarshaledSizesCount; + int32_t parametersCount; + int32_t fieldsCount; + int32_t genericParametersCount; + int32_t genericParameterConstraintsCount; + int32_t genericContainersCount; + int32_t nestedTypesCount; + int32_t interfacesCount; + int32_t vtableMethodsCount; + int32_t interfaceOffsetsCount; + int32_t typeDefinitionsCount; + int32_t imagesCount; + int32_t assembliesCount; + int32_t metadataUsageListsCount; + int32_t metadataUsagePairsCount; + int32_t fieldRefsCount; + int32_t referencedAssembliesCount; + int32_t attributesInfoCount; + int32_t attributeTypesCount; + int32_t unresolvedVirtualCallParameterTypesCount; + int32_t unresolvedVirtualCallParameterRangesCount; + int32_t windowsRuntimeTypeNamesSize; + int32_t exportedTypeDefinitionsCount; + + int32_t version; + + int32_t stringLiteralOffset; // string data for managed code + int32_t stringLiteralDataOffset; + int32_t stringOffset; // string data for metadata + int32_t eventsOffset; // Il2CppEventDefinition + int32_t propertiesOffset; // Il2CppPropertyDefinition + int32_t methodsOffset; // Il2CppMethodDefinition + int32_t parameterDefaultValuesOffset; // Il2CppParameterDefaultValue + int32_t fieldDefaultValuesOffset; // Il2CppFieldDefaultValue + int32_t fieldAndParameterDefaultValueDataOffset; // uint8_t + int32_t fieldMarshaledSizesOffset; // Il2CppFieldMarshaledSize + int32_t parametersOffset; // Il2CppParameterDefinition + int32_t fieldsOffset; // Il2CppFieldDefinition + int32_t genericParametersOffset; // Il2CppGenericParameter + int32_t genericParameterConstraintsOffset; // TypeIndex + int32_t genericContainersOffset; // Il2CppGenericContainer + int32_t nestedTypesOffset; // TypeDefinitionIndex + int32_t interfacesOffset; // TypeIndex + int32_t vtableMethodsOffset; // EncodedMethodIndex + int32_t interfaceOffsetsOffset; // Il2CppInterfaceOffsetPair + int32_t typeDefinitionsOffset; // Il2CppTypeDefinition + int32_t imagesOffset; // Il2CppImageDefinition + int32_t assembliesOffset; // Il2CppAssemblyDefinition + int32_t metadataUsageListsOffset; // Il2CppMetadataUsageList + int32_t metadataUsagePairsOffset; // Il2CppMetadataUsagePair + int32_t fieldRefsOffset; // Il2CppFieldRef + int32_t referencedAssembliesOffset; // public UInt32 + int32_t attributesInfoOffset; // Il2CppCustomAttributeTypeRange + int32_t attributeTypesOffset; // TypeIndex + int32_t unresolvedVirtualCallParameterTypesOffset; // TypeIndex + int32_t unresolvedVirtualCallParameterRangesOffset; // Il2CppRange + int32_t windowsRuntimeTypeNamesOffset; // Il2CppWindowsRuntimeTypeNamePair + int32_t exportedTypeDefinitionsOffset; // TypeDefinitionIndex +} Il2CppGlobalMetadataHeader; +#pragma pack(pop, p1) + +#pragma pack(push, p1, 4) +typedef struct FrontHeader +{ + char sign[24]; + int64_t offset; + int32_t legnth; + unsigned char key[32]; +} FrontHeader; +#pragma pack(pop, p1) +#if RUNTIME_MONO + +#pragma pack(push, p1,4) +typedef struct Il2CppGlobalMonoMetadataHeader +{ + int32_t sanity; + int32_t version; + int32_t stringOffset; // string data for metadata + int32_t stringCount; + int32_t genericMethodInfoMappingOffset; // hash -> generic MonoMethodInfo mapping + int32_t genericMethodInfoMappingCount; + + int32_t monoStringOffset; // mono strings + int32_t monoStringCount; + int32_t methodMetadataOffset; // method metadata + int32_t methodMetadataCount; + int32_t genericArgumentIndicesOffset; // generic argument indices + int32_t genericArgumentIndicesCount; + int32_t typeTableOffset; // type table + int32_t typeTableCount; + int32_t fieldTableOffset; // field table + int32_t fieldTableCount; + int32_t genericMethodIndexTableOffset; // generic method index table + int32_t genericMethodIndexTableCount; + int32_t metaDataUsageListsTableOffset; // meta data usage lists table + int32_t metaDataUsageListsTableCount; + int32_t metaDataUsagePairsTableOffset; // meta data usage pairs table + int32_t metaDataUsagePairsTableCount; + int32_t assemblyNameTableOffset; // assembly names + int32_t assemblyNameTableCount; +} Il2CppGlobalMonoMetadataHeader; +#pragma pack(pop, p1) +#endif diff --git a/O&Z_IL2CPP_Security/resource/src-res/28/GlobalMetadata.cpp b/O&Z_IL2CPP_Security/resource/src-res/28/GlobalMetadata.cpp new file mode 100644 index 0000000..5f87016 --- /dev/null +++ b/O&Z_IL2CPP_Security/resource/src-res/28/GlobalMetadata.cpp @@ -0,0 +1,1687 @@ +#include "GlobalMetadata.h" + +#include "il2cpp-config.h" + + +#include <map> +#include <limits> +#include <il2cpp-runtime-metadata.h> +#include "il2cpp-class-internals.h" +#include "il2cpp-tabledefs.h" +#include "il2cpp-runtime-stats.h" +#include "gc/GarbageCollector.h" +#include "metadata/ArrayMetadata.h" +#include "metadata/CustomAttributeDataReader.h" +#include "metadata/CustomAttributeCreator.h" +#include "metadata/GenericMetadata.h" +#include "metadata/GenericMethod.h" +#include "metadata/Il2CppTypeCompare.h" +#include "metadata/Il2CppTypeHash.h" +#include "metadata/Il2CppGenericContextCompare.h" +#include "metadata/Il2CppGenericContextHash.h" +#include "metadata/Il2CppGenericInstCompare.h" +#include "metadata/Il2CppGenericInstHash.h" +#include "metadata/Il2CppGenericMethodCompare.h" +#include "metadata/Il2CppGenericMethodHash.h" +#include "metadata/Il2CppSignature.h" +#include "os/Atomic.h" +#include "os/Mutex.h" +#include "utils/CallOnce.h" +#include "utils/Collections.h" +#include "utils/HashUtils.h" +#include "utils/Il2CppHashMap.h" +#include "utils/Il2CppHashSet.h" +#include "utils/Memory.h" +#include "utils/StringUtils.h" +#include "utils/PathUtils.h" +#include "vm/Assembly.h" +#include "vm/Class.h" +#include "vm/ClassInlines.h" +#include "vm/GenericClass.h" +#include "vm/MetadataAlloc.h" +#include "vm/MetadataLoader.h" +#include "vm/MetadataLock.h" +#include "vm/Exception.h" +#include "vm/Method.h" +#include "vm/Object.h" +#include "vm/String.h" +#include "vm/Type.h" +#include "vm-utils/MethodDefinitionKey.h" +#include "vm-utils/NativeSymbol.h" +#include "vm-utils/VmStringUtils.h" + +#include "Baselib.h" +#include "Cpp/ReentrantLock.h" + +#include "GlobalMetadataFileInternals.h" + +#include "vm/xxtea.h" + +typedef struct Il2CppImageGlobalMetadata +{ + TypeDefinitionIndex typeStart; + TypeDefinitionIndex exportedTypeStart; + CustomAttributeIndex customAttributeStart; + MethodIndex entryPointIndex; + const Il2CppImage* image; +} Il2CppImageGlobalMetadata; + +static int32_t s_MetadataImagesCount = 0; +static Il2CppImageGlobalMetadata* s_MetadataImagesTable = NULL; + +static CustomAttributesCache* GenerateCustomAttributesCacheInternal(const Il2CppCustomAttributeDataRange* attrDataRange); +static CustomAttributesCache* GenerateCustomAttributesCacheInternal(const Il2CppImageGlobalMetadata* image, CustomAttributeIndex index); +static TypeDefinitionIndex GetIndexForTypeDefinitionInternal(const Il2CppTypeDefinition* typeDefinition); +static Il2CppClass* GetTypeInfoFromTypeDefinitionIndex(TypeDefinitionIndex index); +static Il2CppClass* FromTypeDefinition(TypeDefinitionIndex index); +static GenericParameterIndex GetIndexForGenericParameter(Il2CppMetadataGenericParameterHandle handle); +static Il2CppMetadataGenericParameterHandle GetGenericParameterFromIndexInternal(GenericParameterIndex index); + +static void* s_GlobalMetadata; +static const Il2CppGlobalMetadataHeader* s_GlobalMetadataHeader; +static const Il2CppGenericMethod** s_GenericMethodTable = NULL; + +static const MethodInfo** s_MethodInfoDefinitionTable = NULL; + +static Il2CppString** s_StringLiteralTable = NULL; + +static il2cpp::utils::OnceFlag s_CustomAttributesOnceFlag; +static int s_CustomAttributesCount; +static CustomAttributesCache** s_CustomAttributesCaches; + +static const Il2CppCodeRegistration * s_GlobalMetadata_CodeRegistration; +static const Il2CppMetadataRegistration * s_Il2CppMetadataRegistration; + +static Il2CppClass** s_TypeInfoTable = NULL; +static Il2CppClass** s_TypeInfoDefinitionTable = NULL; + +static const int kBitIsValueType = 1; +static const int kBitIsEnum = 2; +static const int kBitHasFinalizer = 3; +static const int kBitHasStaticConstructor = 4; +static const int kBitIsBlittable = 5; +static const int kBitIsImportOrWindowsRuntime = 6; +static const int kPackingSize = 7; // This uses 4 bits from bit 7 to bit 10 +static const int kPackingSizeIsDefault = 11; +static const int kClassSizeIsDefault = 12; +static const int kSpecifiedPackingSize = 13; // This uses 4 bits from bit 13 to bit 16 +static const int kBitIsByRefLike = 17; + +template<typename T> +static T MetadataOffset(const void* metadata, size_t sectionOffset, size_t itemIndex) +{ + return reinterpret_cast<T>(reinterpret_cast<uint8_t*>(const_cast<void*>(metadata)) + sectionOffset) + itemIndex; +} + +int skip = *|*|*#skip#*|*|*; +int key = *|*|*#key#*|*|*; + +static const char* GetStringFromIndex(StringIndex index) +{ + IL2CPP_ASSERT(index <= s_GlobalMetadataHeader->stringSize); + const char* strings = MetadataOffset<const char*>(s_GlobalMetadata, s_GlobalMetadataHeader->stringOffset, index); + auto length = strlen(strings); + auto buffer = (char*)IL2CPP_CALLOC(length + 1, sizeof(char)); + memset(buffer, 0, length + 1); + //uint8_t* uintBuffer = (uint8_t*)(buffer); + for (size_t i = 0; i < length; i++) + { + if(strings[i] != skip && strings[i] != 0) + buffer[i] = strings[i] ^ key; + else + buffer[i] = strings[i]; + } + return buffer; +} + + +static const char* GetWindowsRuntimeStringFromIndex(StringIndex index) +{ + IL2CPP_ASSERT(index <= s_GlobalMetadataHeader->windowsRuntimeStringsSize); + return MetadataOffset<const char*>(s_GlobalMetadata, s_GlobalMetadataHeader->windowsRuntimeStringsOffset, index); +} + +static const Il2CppMethodDefinition* GetMethodDefinitionFromIndex(MethodIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->methodsSize / sizeof(Il2CppMethodDefinition)); + return MetadataOffset<const Il2CppMethodDefinition*>(s_GlobalMetadata, s_GlobalMetadataHeader->methodsOffset, index); +} + +const MethodInfo* il2cpp::vm::GlobalMetadata::GetMethodInfoFromMethodDefinitionIndex(MethodIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->methodsSize / sizeof(Il2CppMethodDefinition)); + + if (!s_MethodInfoDefinitionTable[index]) + { + const Il2CppMethodDefinition* methodDefinition = GetMethodDefinitionFromIndex(index); + Il2CppClass* typeInfo = GetTypeInfoFromTypeDefinitionIndex(methodDefinition->declaringType); + il2cpp::vm::Class::SetupMethods(typeInfo); + const Il2CppTypeDefinition* typeDefinition = reinterpret_cast<const Il2CppTypeDefinition*>(typeInfo->typeMetadataHandle); + s_MethodInfoDefinitionTable[index] = typeInfo->methods[index - typeDefinition->methodStart]; + } + + return s_MethodInfoDefinitionTable[index]; +} + +static const Il2CppEventDefinition* GetEventDefinitionFromIndex(const Il2CppImage* image, EventIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->eventsSize / sizeof(Il2CppEventDefinition)); + const Il2CppEventDefinition* events = (const Il2CppEventDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->eventsOffset); + return events + index; +} + +static const Il2CppPropertyDefinition* GetPropertyDefinitionFromIndex(const Il2CppImage* image, PropertyIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->propertiesSize / sizeof(Il2CppPropertyDefinition)); + const Il2CppPropertyDefinition* properties = (const Il2CppPropertyDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->propertiesOffset); + return properties + index; +} + +static const Il2CppParameterDefinition* GetParameterDefinitionFromIndex(const Il2CppImage* image, ParameterIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->parametersSize / sizeof(Il2CppParameterDefinition)); + const Il2CppParameterDefinition* parameters = (const Il2CppParameterDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->parametersOffset); + return parameters + index; +} + +static const Il2CppGenericMethod* GetGenericMethodFromIndex(GenericMethodIndex index) +{ + IL2CPP_ASSERT(index < s_Il2CppMetadataRegistration->methodSpecsCount); + if (s_GenericMethodTable[index]) + return s_GenericMethodTable[index]; + + const Il2CppMethodSpec* methodSpec = s_Il2CppMetadataRegistration->methodSpecs + index; + const MethodInfo* methodDefinition = il2cpp::vm::GlobalMetadata::GetMethodInfoFromMethodDefinitionIndex(methodSpec->methodDefinitionIndex); + const Il2CppGenericInst* classInst = NULL; + const Il2CppGenericInst* methodInst = NULL; + if (methodSpec->classIndexIndex != -1) + { + IL2CPP_ASSERT(methodSpec->classIndexIndex < s_Il2CppMetadataRegistration->genericInstsCount); + classInst = s_Il2CppMetadataRegistration->genericInsts[methodSpec->classIndexIndex]; + } + if (methodSpec->methodIndexIndex != -1) + { + IL2CPP_ASSERT(methodSpec->methodIndexIndex < s_Il2CppMetadataRegistration->genericInstsCount); + methodInst = s_Il2CppMetadataRegistration->genericInsts[methodSpec->methodIndexIndex]; + } + s_GenericMethodTable[index] = il2cpp::vm::MetadataCache::GetGenericMethod(methodDefinition, classInst, methodInst); + + return s_GenericMethodTable[index]; +} + +static const MethodInfo* GetMethodInfoFromEncodedIndex(EncodedMethodIndex methodIndex) +{ + Il2CppMetadataUsage usage = GetEncodedIndexType(methodIndex); + + uint32_t index = GetDecodedMethodIndex(methodIndex); + + switch (GetEncodedIndexType(methodIndex)) + { + case kIl2CppMetadataUsageMethodRef: + return il2cpp::metadata::GenericMethod::GetMethod(GetGenericMethodFromIndex(index)); + case kIl2CppMetadataUsageMethodDef: + return il2cpp::vm::GlobalMetadata::GetMethodInfoFromMethodDefinitionIndex(index); + case kIl2CppMetadataUsageInvalid: + { + switch (index) + { + case kIl2CppInvalidMetadataUsageNoData: + return NULL; + case kIl2CppInvalidMetadataUsageAmbiguousMethod: + return il2cpp::vm::Method::GetAmbiguousMethodInfo(); + default: + IL2CPP_ASSERT(0); + break; + } + } + default: + IL2CPP_ASSERT(0); + break; + } + + return NULL; +} + +static Il2CppString* GetStringLiteralFromIndex(StringLiteralIndex index) +{ + if (index == kStringLiteralIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_GlobalMetadataHeader->stringLiteralSize / sizeof(Il2CppStringLiteral) && "Invalid string literal index "); + + if (s_StringLiteralTable[index]) + return s_StringLiteralTable[index]; + + const Il2CppStringLiteral* stringLiteral = (const Il2CppStringLiteral*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->stringLiteralOffset) + index; + char* str = (char*)malloc(stringLiteral->length); + memcpy(str,(const char*)s_GlobalMetadata + s_GlobalMetadataHeader->stringLiteralDataOffset + stringLiteral->dataIndex, stringLiteral->length); + for (size_t i = 0; i < stringLiteral->length; i++)//解密字符串 + { + str[i] ^= key; + } + Il2CppString* newString = il2cpp::vm::String::NewLen((const char*)str, stringLiteral->length); + Il2CppString* prevString = il2cpp::os::Atomic::CompareExchangePointer<Il2CppString>(s_StringLiteralTable + index, newString, NULL); + if (prevString == NULL) + { + il2cpp::gc::GarbageCollector::SetWriteBarrier((void**)s_StringLiteralTable + index); + return newString; + } + return prevString; +} + +static FieldInfo* GetFieldInfoFromIndex(EncodedMethodIndex index) +{ + IL2CPP_ASSERT(s_GlobalMetadataHeader->fieldRefsSize >= 0 && index <= static_cast<uint32_t>(s_GlobalMetadataHeader->fieldRefsSize / sizeof(Il2CppFieldRef))); + + const Il2CppFieldRef* fieldRef = MetadataOffset<const Il2CppFieldRef*>(s_GlobalMetadata, s_GlobalMetadataHeader->fieldRefsOffset, index); + const Il2CppClass* typeInfo = il2cpp::vm::GlobalMetadata::GetTypeInfoFromTypeIndex(fieldRef->typeIndex); + return typeInfo->fields + fieldRef->fieldIndex; +} + +void il2cpp::vm::GlobalMetadata::Register(const Il2CppCodeRegistration* const codeRegistration, const Il2CppMetadataRegistration* const metadataRegistration, const Il2CppCodeGenOptions* const codeGenOptions) +{ + s_GlobalMetadata_CodeRegistration = codeRegistration; + s_Il2CppMetadataRegistration = metadataRegistration; +} + +typedef void (*Il2CppTypeUpdater)(Il2CppType*); + +static void InitializeTypeHandle(Il2CppType* type) +{ + type->data.typeHandle = il2cpp::vm::GlobalMetadata::GetTypeHandleFromIndex(type->data.__klassIndex); +} + +static void ClearTypeHandle(Il2CppType* type) +{ + type->data.__klassIndex = GetIndexForTypeDefinitionInternal(reinterpret_cast<const Il2CppTypeDefinition*>(type->data.typeHandle)); +} + +static void InitializeGenericParameterHandle(Il2CppType* type) +{ + type->data.genericParameterHandle = GetGenericParameterFromIndexInternal(type->data.__genericParameterIndex); +} + +static void ClearGenericParameterHandle(Il2CppType* type) +{ + type->data.__genericParameterIndex = GetIndexForGenericParameter(reinterpret_cast<Il2CppMetadataGenericParameterHandle>(type->data.genericParameterHandle)); +} + +static void ProcessIl2CppTypeDefinitions(Il2CppTypeUpdater updateTypeDef, Il2CppTypeUpdater updateGenericParam) +{ + for (int32_t i = 0; i < s_Il2CppMetadataRegistration->typesCount; i++) + { + const Il2CppType* type = s_Il2CppMetadataRegistration->types[i]; + switch (type->type) + { + case IL2CPP_TYPE_VOID: + case IL2CPP_TYPE_BOOLEAN: + case IL2CPP_TYPE_CHAR: + case IL2CPP_TYPE_I1: + case IL2CPP_TYPE_U1: + case IL2CPP_TYPE_I2: + case IL2CPP_TYPE_U2: + case IL2CPP_TYPE_I4: + case IL2CPP_TYPE_U4: + case IL2CPP_TYPE_I8: + case IL2CPP_TYPE_U8: + case IL2CPP_TYPE_R4: + case IL2CPP_TYPE_R8: + case IL2CPP_TYPE_STRING: + case IL2CPP_TYPE_VALUETYPE: + case IL2CPP_TYPE_CLASS: + case IL2CPP_TYPE_I: + case IL2CPP_TYPE_U: + case IL2CPP_TYPE_OBJECT: + case IL2CPP_TYPE_TYPEDBYREF: + // The Il2Cpp conversion process writes these types in a writeable section + // So we can const_cast them here safely + updateTypeDef(const_cast<Il2CppType*>(type)); + break; + case IL2CPP_TYPE_VAR: + case IL2CPP_TYPE_MVAR: + updateGenericParam(const_cast<Il2CppType*>(type)); + break; + default: + // Nothing do to + break; + } + } +} +static const FrontHeader* frontHeader; +bool il2cpp::vm::GlobalMetadata::Initialize(int32_t* imagesCount, int32_t* assembliesCount) +{ + char _metadataName[19] = {53,62,61,48,51,62,127,63,55,38,51,54,51,38,51,124,54,51,38}; //global-metadata.dat + for(int i=0;i<strlen(_metadataName);i++) + { + _metadataName[i] ^= 114514; + } + s_GlobalMetadata = vm::MetadataLoader::LoadMetadataFile(_metadataName); + if (!s_GlobalMetadata) + return false; + + frontHeader = (FrontHeader *)s_GlobalMetadata; + char *Headerdata = (char *)malloc(frontHeader->legnth); + size_t Headerlen; + memcpy(Headerdata, (char*)s_GlobalMetadata + frontHeader->offset, frontHeader->legnth); + char *Header = (char *)xxtea_decrypt(Headerdata, frontHeader->legnth, frontHeader->key, &Headerlen); + s_GlobalMetadataHeader = (const Il2CppGlobalMetadataHeader*)Header; + + //s_GlobalMetadataHeader = (const Il2CppGlobalMetadataHeader*)s_GlobalMetadata; + IL2CPP_ASSERT(s_GlobalMetadataHeader->sanity == 0xFAB11BAF); + IL2CPP_ASSERT(s_GlobalMetadataHeader->version == 29); + IL2CPP_ASSERT(s_GlobalMetadataHeader->stringLiteralOffset == sizeof(Il2CppGlobalMetadataHeader)); + + s_MetadataImagesCount = *imagesCount = s_GlobalMetadataHeader->imagesSize / sizeof(Il2CppImageDefinition); + *assembliesCount = s_GlobalMetadataHeader->assembliesSize / sizeof(Il2CppAssemblyDefinition); + + // Pre-allocate these arrays so we don't need to lock when reading later. + // These arrays hold the runtime metadata representation for metadata explicitly + // referenced during conversion. There is a corresponding table of same size + // in the converted metadata, giving a description of runtime metadata to construct. + s_MetadataImagesTable = (Il2CppImageGlobalMetadata*)IL2CPP_CALLOC(s_MetadataImagesCount, sizeof(Il2CppImageGlobalMetadata)); + s_TypeInfoTable = (Il2CppClass**)IL2CPP_CALLOC(s_Il2CppMetadataRegistration->typesCount, sizeof(Il2CppClass*)); + s_TypeInfoDefinitionTable = (Il2CppClass**)IL2CPP_CALLOC(s_GlobalMetadataHeader->typeDefinitionsSize / sizeof(Il2CppTypeDefinition), sizeof(Il2CppClass*)); + s_MethodInfoDefinitionTable = (const MethodInfo**)IL2CPP_CALLOC(s_GlobalMetadataHeader->methodsSize / sizeof(Il2CppMethodDefinition), sizeof(MethodInfo*)); + s_GenericMethodTable = (const Il2CppGenericMethod**)IL2CPP_CALLOC(s_Il2CppMetadataRegistration->methodSpecsCount, sizeof(Il2CppGenericMethod*)); + + ProcessIl2CppTypeDefinitions(InitializeTypeHandle, InitializeGenericParameterHandle); + + return true; +} + +void il2cpp::vm::GlobalMetadata::InitializeAllMethodMetadata() +{ + for (size_t i = 0; i < s_Il2CppMetadataRegistration->metadataUsagesCount; i++) + { + uintptr_t* metadataPointer = reinterpret_cast<uintptr_t*>(s_Il2CppMetadataRegistration->metadataUsages[i]); + Il2CppMetadataUsage usage = GetEncodedIndexType(static_cast<uint32_t>(*metadataPointer)); + switch (usage) + { + case kIl2CppMetadataUsageTypeInfo: + case kIl2CppMetadataUsageMethodDef: + case kIl2CppMetadataUsageMethodRef: + InitializeRuntimeMetadata(metadataPointer, false); + break; + default: + break; + } + } +} + +// This method can be called from multiple threads, so it does have a data race. However, each +// thread is reading from the same read-only metadata, so each thread will set the same values. +// Therefore, we can safely ignore thread sanitizer issues in this method. +void* il2cpp::vm::GlobalMetadata::InitializeRuntimeMetadata(uintptr_t* metadataPointer, bool throwOnError) IL2CPP_DISABLE_TSAN +{ + // This must be the only read of *metadataPointer + // This code has no locks and we need to ensure that we only read metadataPointer once + // so we don't read it once as an encoded token and once as an initialized pointer + uintptr_t metadataValue = (uintptr_t)UnityPalReadPtrVal((intptr_t*)metadataPointer); + + if (IsRuntimeMetadataInitialized(metadataValue)) + return (void*)metadataValue; + + uint32_t encodedToken = static_cast<uint32_t>(metadataValue); + Il2CppMetadataUsage usage = GetEncodedIndexType(encodedToken); + uint32_t decodedIndex = GetDecodedMethodIndex(encodedToken); + + void* initialized = NULL; + + switch (usage) + { + case kIl2CppMetadataUsageTypeInfo: + initialized = (void*)il2cpp::vm::GlobalMetadata::GetTypeInfoFromTypeIndex(decodedIndex, throwOnError); + break; + case kIl2CppMetadataUsageIl2CppType: + initialized = (void*)il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(decodedIndex); + break; + case kIl2CppMetadataUsageMethodDef: + case kIl2CppMetadataUsageMethodRef: + initialized = (void*)GetMethodInfoFromEncodedIndex(encodedToken); + break; + case kIl2CppMetadataUsageFieldInfo: + initialized = (void*)GetFieldInfoFromIndex(decodedIndex); + break; + case kIl2CppMetadataUsageStringLiteral: + initialized = (void*)GetStringLiteralFromIndex(decodedIndex); + break; + case kIl2CppMetadataUsageInvalid: + break; + default: + IL2CPP_NOT_IMPLEMENTED(il2cpp::vm::GlobalMetadata::InitializeMethodMetadata); + break; + } + + if (initialized != NULL) + *metadataPointer = (uintptr_t)initialized; + + return initialized; +} + +void il2cpp::vm::GlobalMetadata::InitializeStringLiteralTable() +{ + s_StringLiteralTable = (Il2CppString**)il2cpp::gc::GarbageCollector::AllocateFixed(s_GlobalMetadataHeader->stringLiteralSize / sizeof(Il2CppStringLiteral) * sizeof(Il2CppString*), NULL); +} + +void il2cpp::vm::GlobalMetadata::InitializeWindowsRuntimeTypeNamesTables(WindowsRuntimeTypeNameToClassMap& windowsRuntimeTypeNameToClassMap, ClassToWindowsRuntimeTypeNameMap& classToWindowsRuntimeTypeNameMap) +{ + int32_t typeCount = s_GlobalMetadataHeader->windowsRuntimeTypeNamesSize / sizeof(Il2CppWindowsRuntimeTypeNamePair); + const Il2CppWindowsRuntimeTypeNamePair* windowsRuntimeTypeNames = MetadataOffset<Il2CppWindowsRuntimeTypeNamePair*>(s_GlobalMetadata, s_GlobalMetadataHeader->windowsRuntimeTypeNamesOffset, 0); + + windowsRuntimeTypeNameToClassMap.resize(typeCount / 2 + 1); + classToWindowsRuntimeTypeNameMap.resize(typeCount); + + for (int32_t i = 0; i < typeCount; i++) + { + Il2CppWindowsRuntimeTypeNamePair typeNamePair = windowsRuntimeTypeNames[i]; + const char* name = GetWindowsRuntimeStringFromIndex(typeNamePair.nameIndex); + const Il2CppType* type = GetIl2CppTypeFromIndex(typeNamePair.typeIndex); + Il2CppClass* klass = Class::FromIl2CppType(type); + + if (!Class::IsNullable(klass)) + { + // Don't add nullable types to name -> klass map because IReference`1<T> and Nullable`1<T> + // share windows runtime type names, and that would cause a collision. + windowsRuntimeTypeNameToClassMap.insert(std::make_pair(name, klass)); + } + + classToWindowsRuntimeTypeNameMap.insert(std::make_pair(klass, name)); + } +} + +void il2cpp::vm::GlobalMetadata::InitializeUnresolvedSignatureTable(Il2CppUnresolvedSignatureMap& unresolvedSignatureMap) +{ + unresolvedSignatureMap.resize(s_GlobalMetadata_CodeRegistration->unresolvedVirtualCallCount); + + for (uint32_t i = 0; i < s_GlobalMetadata_CodeRegistration->unresolvedVirtualCallCount; ++i) + { + const Il2CppMetadataRange* range = MetadataOffset<Il2CppMetadataRange*>(s_GlobalMetadata, s_GlobalMetadataHeader->unresolvedVirtualCallParameterRangesOffset, i); + il2cpp::metadata::Il2CppSignature signature; + signature.Count = range->length; + signature.Types = (const Il2CppType**)MetadataMalloc(range->length * sizeof(Il2CppType*)); + + for (int j = 0; j < range->length; ++j) + { + TypeIndex typeIndex = *MetadataOffset<TypeIndex*>(s_GlobalMetadata, s_GlobalMetadataHeader->unresolvedVirtualCallParameterTypesOffset, range->start + j); + const Il2CppType* type = GetIl2CppTypeFromIndex(typeIndex); + signature.Types[j] = type; + } + + unresolvedSignatureMap.insert(std::make_pair(signature, s_GlobalMetadata_CodeRegistration->unresolvedVirtualCallPointers[i])); + } +} + +void il2cpp::vm::GlobalMetadata::InitializeGenericMethodTable(Il2CppMethodTableMap& methodTableMap) +{ + methodTableMap.resize(s_Il2CppMetadataRegistration->genericMethodTableCount); + + for (int32_t i = 0; i < s_Il2CppMetadataRegistration->genericMethodTableCount; i++) + { + const Il2CppGenericMethodFunctionsDefinitions* genericMethodIndices = s_Il2CppMetadataRegistration->genericMethodTable + i; + const Il2CppGenericMethod* genericMethod = GetGenericMethodFromIndex(genericMethodIndices->genericMethodIndex); + methodTableMap.insert(std::make_pair(genericMethod, &genericMethodIndices->indices)); + } +} + +static void ClearStringLiteralTable() +{ + il2cpp::gc::GarbageCollector::FreeFixed(s_StringLiteralTable); + s_StringLiteralTable = NULL; +} + +static void FreeAndNull(void** pointer) +{ + IL2CPP_FREE(*pointer); + *pointer = NULL; +} + +void il2cpp::vm::GlobalMetadata::Clear() +{ + ClearStringLiteralTable(); + + FreeAndNull((void**)&s_MethodInfoDefinitionTable); + FreeAndNull((void**)&s_GenericMethodTable); + FreeAndNull((void**)&s_TypeInfoTable); + FreeAndNull((void**)&s_TypeInfoDefinitionTable); + + ProcessIl2CppTypeDefinitions(ClearTypeHandle, ClearGenericParameterHandle); + + vm::MetadataLoader::UnloadMetadataFile(s_GlobalMetadata); + s_GlobalMetadataHeader = NULL; + s_GlobalMetadata = NULL; + + s_GlobalMetadata_CodeRegistration = NULL; + s_Il2CppMetadataRegistration = NULL; +} + +void il2cpp::vm::GlobalMetadata::BuildIl2CppImage(Il2CppImage* image, ImageIndex imageIndex, AssemblyIndex* imageAssemblyIndex) +{ + const Il2CppImageDefinition* imagesDefinitions = (const Il2CppImageDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->imagesOffset); + + const Il2CppImageDefinition* imageDefinition = imagesDefinitions + imageIndex; + + image->name = GetStringFromIndex(imageDefinition->nameIndex); + + *imageAssemblyIndex = imageDefinition->assemblyIndex; + image->typeCount = imageDefinition->typeCount; + image->exportedTypeCount = imageDefinition->exportedTypeCount; + image->token = imageDefinition->token; + image->customAttributeCount = imageDefinition->customAttributeCount; + + Il2CppImageGlobalMetadata* metadataImage = s_MetadataImagesTable + imageIndex; + metadataImage->typeStart = imageDefinition->typeStart; + metadataImage->customAttributeStart = imageDefinition->customAttributeStart; + metadataImage->entryPointIndex = imageDefinition->entryPointIndex; + metadataImage->exportedTypeStart = imageDefinition->exportedTypeStart; + metadataImage->image = image; + + image->metadataHandle = reinterpret_cast<Il2CppMetadataImageHandle>(metadataImage); +} + +void il2cpp::vm::GlobalMetadata::BuildIl2CppAssembly(Il2CppAssembly* assembly, AssemblyIndex assemblyIndex, ImageIndex* assemblyImageIndex) +{ + const Il2CppAssemblyDefinition* assemblyDefinitions = (const Il2CppAssemblyDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->assembliesOffset); + const Il2CppAssemblyDefinition* assemblyDefinition = assemblyDefinitions + assemblyIndex; + + assembly->token = assemblyDefinition->token; + assembly->referencedAssemblyStart = assemblyDefinition->referencedAssemblyStart; + assembly->referencedAssemblyCount = assemblyDefinition->referencedAssemblyCount; + + Il2CppAssemblyName* assemblyName = &assembly->aname; + const Il2CppAssemblyNameDefinition* assemblyNameDefinition = &assemblyDefinition->aname; + + assemblyName->name = GetStringFromIndex(assemblyNameDefinition->nameIndex); + assemblyName->culture = GetStringFromIndex(assemblyNameDefinition->cultureIndex); + assemblyName->public_key = (const uint8_t*)GetStringFromIndex(assemblyNameDefinition->publicKeyIndex); + assemblyName->hash_alg = assemblyNameDefinition->hash_alg; + assemblyName->hash_len = assemblyNameDefinition->hash_len; + assemblyName->flags = assemblyNameDefinition->flags; + assemblyName->major = assemblyNameDefinition->major; + assemblyName->minor = assemblyNameDefinition->minor; + assemblyName->build = assemblyNameDefinition->build; + assemblyName->revision = assemblyNameDefinition->revision; + memcpy(assemblyName->public_key_token, assemblyNameDefinition->public_key_token, sizeof(assemblyNameDefinition->public_key_token)); + + *assemblyImageIndex = assemblyDefinition->imageIndex; +} + +static const Il2CppImageGlobalMetadata* GetImageMetadata(const Il2CppImage* image) +{ + return reinterpret_cast<const Il2CppImageGlobalMetadata*>(image->metadataHandle); +} + +const MethodInfo* il2cpp::vm::GlobalMetadata::GetAssemblyEntryPoint(const Il2CppImage* image) +{ + const Il2CppImageGlobalMetadata* imageMetadata = GetImageMetadata(image); + + if (imageMetadata == NULL || imageMetadata->entryPointIndex == -1) + return NULL; + + return GetMethodInfoFromMethodDefinitionIndex(imageMetadata->entryPointIndex); +} + +Il2CppMetadataTypeHandle il2cpp::vm::GlobalMetadata::GetAssemblyTypeHandle(const Il2CppImage* image, AssemblyTypeIndex index) +{ + const Il2CppImageGlobalMetadata* imageMetadata = GetImageMetadata(image); + + IL2CPP_ASSERT(index >= 0 && index < static_cast<AssemblyTypeIndex>(image->typeCount)); + TypeDefinitionIndex typeDefintionIndex = imageMetadata->typeStart + index; + return GetTypeHandleFromIndex(typeDefintionIndex); +} + +const Il2CppAssembly* il2cpp::vm::GlobalMetadata::GetReferencedAssembly(const Il2CppAssembly* assembly, int32_t referencedAssemblyTableIndex, const Il2CppAssembly assembliesTable[], int assembliesCount) +{ + IL2CPP_ASSERT(referencedAssemblyTableIndex < assembly->referencedAssemblyCount); + + referencedAssemblyTableIndex = assembly->referencedAssemblyStart + referencedAssemblyTableIndex; + + IL2CPP_ASSERT(referencedAssemblyTableIndex >= 0 && static_cast<uint32_t>(referencedAssemblyTableIndex) <= s_GlobalMetadataHeader->referencedAssembliesSize / sizeof(int32_t)); + const int32_t* referenceAssemblyIndicies = (const int32_t*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->referencedAssembliesOffset); + return assembliesTable + referenceAssemblyIndicies[referencedAssemblyTableIndex]; +} + +Il2CppMetadataTypeHandle il2cpp::vm::GlobalMetadata::GetAssemblyExportedTypeHandle(const Il2CppImage* image, AssemblyExportedTypeIndex index) +{ + if (index == kTypeDefinitionIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && index < static_cast<AssemblyExportedTypeIndex>(image->exportedTypeCount)); + + const Il2CppImageGlobalMetadata* imageMetadata = GetImageMetadata(image); + + int32_t exportedTypeIndex = imageMetadata->exportedTypeStart + index; + + IL2CPP_ASSERT(exportedTypeIndex >= 0 && static_cast<uint32_t>(exportedTypeIndex) < s_GlobalMetadataHeader->exportedTypeDefinitionsSize / sizeof(TypeDefinitionIndex)); + TypeDefinitionIndex* exportedTypes = (TypeDefinitionIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->exportedTypeDefinitionsOffset); + TypeDefinitionIndex typeDefintionIndex = *(exportedTypes + exportedTypeIndex); + + return GetTypeHandleFromIndex(typeDefintionIndex); +} + +static const Il2CppTypeDefinition* GetTypeDefinitionForIndex(TypeDefinitionIndex index) +{ + if (index == kTypeDefinitionIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_GlobalMetadataHeader->typeDefinitionsSize / sizeof(Il2CppTypeDefinition)); + const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); + return typeDefinitions + index; +} + +static TypeDefinitionIndex GetIndexForTypeDefinitionInternal(const Il2CppTypeDefinition* typeDefinition) +{ + IL2CPP_ASSERT(typeDefinition); + const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); + + IL2CPP_ASSERT(typeDefinition >= typeDefinitions && typeDefinition < typeDefinitions + s_GlobalMetadataHeader->typeDefinitionsSize / sizeof(Il2CppTypeDefinition)); + + ptrdiff_t index = typeDefinition - typeDefinitions; + IL2CPP_ASSERT(index <= std::numeric_limits<TypeDefinitionIndex>::max()); + return static_cast<TypeDefinitionIndex>(index); +} + +Il2CppClass* il2cpp::vm::GlobalMetadata::GetTypeInfoFromTypeDefinitionIndex(TypeDefinitionIndex index) +{ + if (index == kTypeIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_GlobalMetadataHeader->typeDefinitionsSize / sizeof(Il2CppTypeDefinition)); + + if (!s_TypeInfoDefinitionTable[index]) + { + // we need to use the metadata lock, since we may need to retrieve other Il2CppClass's when setting. Our parent may be a generic instance for example + il2cpp::os::FastAutoLock lock(&il2cpp::vm::g_MetadataLock); + // double checked locking + if (!s_TypeInfoDefinitionTable[index]) + s_TypeInfoDefinitionTable[index] = FromTypeDefinition(index); + } + + return s_TypeInfoDefinitionTable[index]; +} + +Il2CppClass* il2cpp::vm::GlobalMetadata::GetTypeInfoFromHandle(Il2CppMetadataTypeHandle handle) +{ + const Il2CppTypeDefinition* typeDefinition = reinterpret_cast<const Il2CppTypeDefinition*>(handle); + return GetTypeInfoFromTypeDefinitionIndex(GetIndexForTypeDefinitionInternal(typeDefinition)); +} + +Il2CppClass* il2cpp::vm::GlobalMetadata::GetTypeInfoFromType(const Il2CppType* type) +{ + return GetTypeInfoFromHandle(type->data.typeHandle); +} + +const Il2CppType* il2cpp::vm::GlobalMetadata::GetInterfaceFromOffset(const Il2CppClass* klass, TypeInterfaceIndex offset) +{ + const Il2CppTypeDefinition* typeDefinition = reinterpret_cast<const Il2CppTypeDefinition*>(klass->typeMetadataHandle); + + IL2CPP_ASSERT(offset >= 0 && offset < typeDefinition->interfaces_count); + + InterfacesIndex index = typeDefinition->interfacesStart + offset; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->interfacesSize / sizeof(TypeIndex)); + const TypeIndex* interfaceIndices = (const TypeIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->interfacesOffset); + + return GetIl2CppTypeFromIndex(interfaceIndices[index]); +} + +Il2CppInterfaceOffsetInfo il2cpp::vm::GlobalMetadata::GetInterfaceOffsetInfo(const Il2CppClass* klass, TypeInterfaceOffsetIndex index) +{ + const Il2CppTypeDefinition* typeDefinition = reinterpret_cast<const Il2CppTypeDefinition*>(klass->typeMetadataHandle); + + IL2CPP_ASSERT(index >= 0 && index < typeDefinition->interface_offsets_count); + + index = index + typeDefinition->interfaceOffsetsStart; + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->interfaceOffsetsSize / sizeof(Il2CppInterfaceOffsetPair)); + const Il2CppInterfaceOffsetPair* interfaceOffsets = (const Il2CppInterfaceOffsetPair*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->interfaceOffsetsOffset); + + return + { + GetIl2CppTypeFromIndex(interfaceOffsets[index].interfaceTypeIndex), + interfaceOffsets[index].offset + }; +} + +Il2CppMetadataTypeHandle il2cpp::vm::GlobalMetadata::GetTypeHandleFromIndex(TypeDefinitionIndex typeIndex) +{ + return reinterpret_cast<Il2CppMetadataTypeHandle>(GetTypeDefinitionForIndex(typeIndex)); +} + +Il2CppMetadataTypeHandle il2cpp::vm::GlobalMetadata::GetTypeHandleFromType(const Il2CppType* type) +{ + IL2CPP_ASSERT(type->type == IL2CPP_TYPE_CLASS || type->type == IL2CPP_TYPE_VALUETYPE); + return type->data.typeHandle; +} + +bool il2cpp::vm::GlobalMetadata::TypeIsNested(Il2CppMetadataTypeHandle handle) +{ + return reinterpret_cast<const Il2CppTypeDefinition*>(handle)->declaringTypeIndex != kTypeIndexInvalid; +} + +bool il2cpp::vm::GlobalMetadata::TypeIsValueType(Il2CppMetadataTypeHandle handle) +{ + return (reinterpret_cast<const Il2CppTypeDefinition*>(handle)->bitfield >> (kBitIsValueType - 1)) & 0x1; +} + +bool il2cpp::vm::GlobalMetadata::StructLayoutPackIsDefault(Il2CppMetadataTypeHandle handle) +{ + return (reinterpret_cast<const Il2CppTypeDefinition*>(handle)->bitfield >> (kPackingSizeIsDefault - 1)) & 0x1; +} + +bool il2cpp::vm::GlobalMetadata::StructLayoutSizeIsDefault(Il2CppMetadataTypeHandle handle) +{ + return (reinterpret_cast<const Il2CppTypeDefinition*>(handle)->bitfield >> (kClassSizeIsDefault - 1)) & 0x1; +} + +std::pair<const char*, const char*> il2cpp::vm::GlobalMetadata::GetTypeNamespaceAndName(Il2CppMetadataTypeHandle handle) +{ + const Il2CppTypeDefinition* typeDefinition = reinterpret_cast<const Il2CppTypeDefinition*>(handle); + return std::make_pair + ( + GetStringFromIndex(typeDefinition->namespaceIndex), + GetStringFromIndex(typeDefinition->nameIndex) + ); +} + +Il2CppClass* il2cpp::vm::GlobalMetadata::GetNestedTypeFromOffset(const Il2CppClass* klass, TypeNestedTypeIndex offset) +{ + const Il2CppTypeDefinition* typeDefinition = reinterpret_cast<const Il2CppTypeDefinition*>(klass->typeMetadataHandle); + + IL2CPP_ASSERT(offset >= 0 && offset < typeDefinition->nested_type_count); + + NestedTypeIndex index = typeDefinition->nestedTypesStart + offset; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->nestedTypesSize / sizeof(TypeDefinitionIndex)); + + const TypeDefinitionIndex* nestedTypeIndices = (const TypeDefinitionIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->nestedTypesOffset); + + return GetTypeInfoFromTypeDefinitionIndex(nestedTypeIndices[index]); +} + +Il2CppMetadataTypeHandle il2cpp::vm::GlobalMetadata::GetNestedTypes(Il2CppMetadataTypeHandle handle, void** iter) +{ + if (!iter) + return NULL; + + const Il2CppTypeDefinition* typeDefinition = reinterpret_cast<const Il2CppTypeDefinition*>(handle); + + const TypeDefinitionIndex* nestedTypeIndices = (const TypeDefinitionIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->nestedTypesOffset); + + if (!*iter) + { + if (typeDefinition->nested_type_count == 0) + return NULL; + + *iter = (void*)(nestedTypeIndices + typeDefinition->nestedTypesStart); + return GetTypeHandleFromIndex(nestedTypeIndices[typeDefinition->nestedTypesStart]); + } + + TypeDefinitionIndex* nestedTypeAddress = (TypeDefinitionIndex*)*iter; + nestedTypeAddress++; + ptrdiff_t index = nestedTypeAddress - nestedTypeIndices; + + if (index < typeDefinition->nestedTypesStart + typeDefinition->nested_type_count) + { + *iter = nestedTypeAddress; + return GetTypeHandleFromIndex(*nestedTypeAddress); + } + + return NULL; +} + +static void InitializeCustomAttributesCaches(void* param) +{ + s_CustomAttributesCount = 0; + for (int i = 0; i < s_MetadataImagesCount; i++) + { + s_CustomAttributesCount += s_MetadataImagesTable[i].image->customAttributeCount; + } + + s_CustomAttributesCaches = (CustomAttributesCache**)IL2CPP_CALLOC(s_CustomAttributesCount, sizeof(CustomAttributesCache*)); +} + +static int CompareTokens(const void* pkey, const void* pelem) +{ + return (int)(((Il2CppCustomAttributeDataRange*)pkey)->token - ((Il2CppCustomAttributeDataRange*)pelem)->token); +} + +static CustomAttributesCache* GenerateCustomAttributesCacheInternal(const Il2CppImageGlobalMetadata* imageMetadata, CustomAttributeIndex index) +{ + if (index == kCustomAttributeIndexInvalid || imageMetadata == NULL) + return NULL; + + il2cpp::utils::CallOnce(s_CustomAttributesOnceFlag, &InitializeCustomAttributesCaches, NULL); + + IL2CPP_ASSERT(index >= 0 && index < s_CustomAttributesCount); + IL2CPP_ASSERT(index >= 0 && index < static_cast<int32_t>(s_GlobalMetadataHeader->attributeDataRangeOffset / sizeof(Il2CppCustomAttributeDataRange))); + + // use atomics rather than a Mutex here to avoid deadlock. The attribute generators call arbitrary managed code + CustomAttributesCache* cache = il2cpp::os::Atomic::ReadPointer(&s_CustomAttributesCaches[index]); + + if (cache == NULL) + { + const Il2CppCustomAttributeDataRange* startRange = MetadataOffset<const Il2CppCustomAttributeDataRange*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeDataRangeOffset, index); + const Il2CppCustomAttributeDataRange* endRange = MetadataOffset<const Il2CppCustomAttributeDataRange*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeDataRangeOffset, index + 1); + + void* start = MetadataOffset<uint8_t*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeDataOffset, startRange->startOffset); + void* end = MetadataOffset<uint8_t*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeDataOffset, endRange->startOffset); + IL2CPP_ASSERT(start && end); + + il2cpp::metadata::CustomAttributeDataReader reader(start, end); + + cache = (CustomAttributesCache*)IL2CPP_CALLOC(1, sizeof(CustomAttributesCache)); + cache->count = (int)reader.GetCount(); + cache->attributes = (Il2CppObject**)il2cpp::gc::GarbageCollector::AllocateFixed(sizeof(Il2CppObject*) * cache->count, 0); + + il2cpp::metadata::CustomAttributeDataIterator iter = reader.GetDataIterator(); + for (int i = 0; i < cache->count; i++) + { + Il2CppException* exc = NULL; + il2cpp::metadata::CustomAttributeCreator creator; + if (reader.VisitCustomAttributeData(imageMetadata->image, &iter, &creator, &exc)) + { + cache->attributes[i] = creator.GetAttribute(&exc); + il2cpp::gc::GarbageCollector::SetWriteBarrier((void**)&cache->attributes[i]); + } + + if (exc != NULL) + { + il2cpp::gc::GarbageCollector::FreeFixed(cache->attributes); + IL2CPP_FREE(cache); + il2cpp::vm::Exception::Raise(exc); + } + } + + CustomAttributesCache* original = il2cpp::os::Atomic::CompareExchangePointer(&s_CustomAttributesCaches[index], cache, (CustomAttributesCache*)NULL); + if (original) + { + // A non-NULL return value indicates some other thread already generated this cache. + // We need to cleanup the resources we allocated + il2cpp::gc::GarbageCollector::FreeFixed(cache->attributes); + IL2CPP_FREE(cache); + + cache = original; + } + } + + return cache; +} + +static const Il2CppImageGlobalMetadata* GetImageForCustomAttributeIndex(CustomAttributeIndex index) +{ + for (int32_t imageIndex = 0; imageIndex < s_MetadataImagesCount; imageIndex++) + { + const Il2CppImageGlobalMetadata* imageMetadta = s_MetadataImagesTable + imageIndex; + IL2CPP_ASSERT(index >= 0); + if (index >= imageMetadta->customAttributeStart && static_cast<uint32_t>(index) < (imageMetadta->customAttributeStart + imageMetadta->image->customAttributeCount)) + return imageMetadta; + } + + IL2CPP_ASSERT(0 && "Failed to find owning image for custom attribute index"); + return NULL; +} + +static CustomAttributeIndex GetCustomAttributeIndex(const Il2CppCustomAttributeDataRange* attrDataRange) +{ + if (attrDataRange == NULL) + return kCustomAttributeIndexInvalid; + + const Il2CppCustomAttributeDataRange* attributeTypeRangeStart = MetadataOffset<const Il2CppCustomAttributeDataRange*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeDataRangeOffset, 0); + + CustomAttributeIndex index = (CustomAttributeIndex)(attrDataRange - attributeTypeRangeStart); + + IL2CPP_ASSERT(index >= 0 && index < (CustomAttributeIndex)(s_GlobalMetadataHeader->attributeDataRangeSize / sizeof(Il2CppCustomAttributeDataRange))); + + return index; +} + +static CustomAttributeIndex GetCustomAttributeIndex(const Il2CppImage* image, uint32_t token) +{ + const Il2CppCustomAttributeDataRange* attrDataRange = reinterpret_cast<const Il2CppCustomAttributeDataRange*>(il2cpp::vm::GlobalMetadata::GetCustomAttributeTypeToken(image, token)); + return GetCustomAttributeIndex(attrDataRange); +} + +static CustomAttributesCache* GenerateCustomAttributesCacheInternal(const Il2CppCustomAttributeDataRange* attrDataRange) +{ + if (attrDataRange == NULL) + return NULL; + + CustomAttributeIndex index = GetCustomAttributeIndex(attrDataRange); + return GenerateCustomAttributesCacheInternal(GetImageForCustomAttributeIndex(index), index); +} + +CustomAttributesCache* il2cpp::vm::GlobalMetadata::GenerateCustomAttributesCache(Il2CppMetadataCustomAttributeHandle handle) +{ + return GenerateCustomAttributesCacheInternal(reinterpret_cast<const Il2CppCustomAttributeDataRange*>(handle)); +} + +Il2CppMetadataCustomAttributeHandle il2cpp::vm::GlobalMetadata::GetCustomAttributeTypeToken(const Il2CppImage* image, uint32_t token) +{ + const Il2CppCustomAttributeDataRange* attributeTypeRange = MetadataOffset<const Il2CppCustomAttributeDataRange*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeDataRangeOffset, 0); + + Il2CppCustomAttributeDataRange key = {0}; + key.token = token; + + const Il2CppImageGlobalMetadata* imageMetadata = GetImageMetadata(image); + const Il2CppCustomAttributeDataRange* res = (const Il2CppCustomAttributeDataRange*)bsearch(&key, attributeTypeRange + imageMetadata->customAttributeStart, image->customAttributeCount, sizeof(Il2CppCustomAttributeDataRange), CompareTokens); + + return reinterpret_cast<Il2CppMetadataCustomAttributeHandle>(res); +} + +std::tuple<void*, void*> il2cpp::vm::GlobalMetadata::GetCustomAttributeDataRange(const Il2CppImage* image, uint32_t token) +{ + const Il2CppCustomAttributeDataRange* attributeTypeRange = MetadataOffset<const Il2CppCustomAttributeDataRange*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeDataRangeOffset, 0); + + Il2CppCustomAttributeDataRange key = {0}; + key.token = token; + + const Il2CppImageGlobalMetadata* imageMetadata = GetImageMetadata(image); + const Il2CppCustomAttributeDataRange* res = (const Il2CppCustomAttributeDataRange*)bsearch(&key, attributeTypeRange + imageMetadata->customAttributeStart, image->customAttributeCount, sizeof(Il2CppCustomAttributeDataRange), CompareTokens); + if (res == NULL) + return std::make_tuple<void*, void*>(NULL, NULL); + + const Il2CppCustomAttributeDataRange* next = res + 1; + + return std::make_tuple<void*, void*>( + MetadataOffset<uint8_t*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeDataOffset, res->startOffset), + MetadataOffset<uint8_t*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeDataOffset, next->startOffset) + ); +} + +CustomAttributesCache* il2cpp::vm::GlobalMetadata::GenerateCustomAttributesCache(const Il2CppImage* image, uint32_t token) +{ + return GenerateCustomAttributesCacheInternal(GetImageMetadata(image), GetCustomAttributeIndex(image, token)); +} + +static bool HasAttributeFromTypeRange(const Il2CppImage* image, const Il2CppCustomAttributeDataRange* dataRange, Il2CppClass* attribute) +{ + void* start = MetadataOffset<uint8_t*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeDataOffset, dataRange->startOffset); + void* end = MetadataOffset<uint8_t*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeDataOffset, (dataRange + 1)->startOffset); + + il2cpp::metadata::CustomAttributeDataReader reader(start, end); + + const MethodInfo* ctor; + il2cpp::metadata::CustomAttributeCtorIterator iter = reader.GetCtorIterator(); + while (reader.IterateAttributeCtors(image, &ctor, &iter)) + { + Il2CppClass* klass = ctor->klass; + if (il2cpp::vm::Class::HasParent(klass, attribute) || (il2cpp::vm::Class::IsInterface(attribute) && il2cpp::vm::Class::IsAssignableFrom(attribute, klass))) + return true; + } + + return false; +} + +bool il2cpp::vm::GlobalMetadata::HasAttribute(Il2CppMetadataCustomAttributeHandle token, Il2CppClass* attribute) +{ + if (token == NULL) + return false; + + const Il2CppCustomAttributeDataRange* dataRange = reinterpret_cast<const Il2CppCustomAttributeDataRange*>(token); + + CustomAttributeIndex index = GetCustomAttributeIndex(dataRange); + const Il2CppImageGlobalMetadata* imageMetadata = GetImageForCustomAttributeIndex(index); + if (imageMetadata == NULL) + return false; + + return HasAttributeFromTypeRange(imageMetadata->image, dataRange, attribute); +} + +bool il2cpp::vm::GlobalMetadata::HasAttribute(const Il2CppImage* image, uint32_t token, Il2CppClass* attribute) +{ + CustomAttributeIndex index = GetCustomAttributeIndex(image, token); + if (index == kCustomAttributeIndexInvalid) + return false; + + IL2CPP_ASSERT(attribute); + + const Il2CppCustomAttributeDataRange* attributeTypeRange = MetadataOffset<const Il2CppCustomAttributeDataRange*>(s_GlobalMetadata, s_GlobalMetadataHeader->attributeDataRangeOffset, index); + return HasAttributeFromTypeRange(image, attributeTypeRange, attribute); +} + +const MethodInfo* il2cpp::vm::GlobalMetadata::GetMethodInfoFromVTableSlot(const Il2CppClass* klass, int32_t vTableSlot) +{ + const Il2CppTypeDefinition* typeDefinition = reinterpret_cast<const Il2CppTypeDefinition*>(klass->typeMetadataHandle); + + uint32_t index = typeDefinition->vtableStart + vTableSlot; + IL2CPP_ASSERT(index >= 0 && index <= s_GlobalMetadataHeader->vtableMethodsSize / sizeof(EncodedMethodIndex)); + const EncodedMethodIndex* vTableMethodReferences = (const EncodedMethodIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->vtableMethodsOffset); + EncodedMethodIndex vTableMethodReference = vTableMethodReferences[index]; + return GetMethodInfoFromEncodedIndex(vTableMethodReference); +} + +static const Il2CppFieldDefaultValue* GetFieldDefaultValueEntry(const FieldInfo* field) +{ + Il2CppClass* parent = field->parent; + size_t fieldIndex = (field - parent->fields); + + if (il2cpp::vm::Type::IsGenericInstance(&parent->byval_arg)) + parent = il2cpp::vm::GenericClass::GetTypeDefinition(parent->generic_class); + + fieldIndex += reinterpret_cast<const Il2CppTypeDefinition*>(parent->typeMetadataHandle)->fieldStart; + + const Il2CppFieldDefaultValue *start = (const Il2CppFieldDefaultValue*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldDefaultValuesOffset); + const Il2CppFieldDefaultValue *entry = start; + while (entry < start + s_GlobalMetadataHeader->fieldDefaultValuesSize / sizeof(Il2CppFieldDefaultValue)) + { + if (fieldIndex == entry->fieldIndex) + { + return entry; + } + entry++; + } + IL2CPP_ASSERT(0); + return NULL; +} + +static const uint8_t* GetFieldOrParameterDefalutValue(uint32_t index) +{ + if (index == kDefaultValueIndexNull) + return NULL; + + IL2CPP_ASSERT(index >= 0 && index <= s_GlobalMetadataHeader->fieldAndParameterDefaultValueDataSize / sizeof(uint8_t)); + const uint8_t* defaultValuesData = (const uint8_t*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldAndParameterDefaultValueDataOffset); + return defaultValuesData + index; +} + +const uint8_t* il2cpp::vm::GlobalMetadata::GetFieldDefaultValue(const FieldInfo* field, const Il2CppType** type) +{ + const Il2CppFieldDefaultValue* entry = GetFieldDefaultValueEntry(field); + + if (entry != NULL) + { + *type = GetIl2CppTypeFromIndex(entry->typeIndex); + return GetFieldOrParameterDefalutValue(entry->dataIndex); + } + + return NULL; +} + +static const Il2CppParameterDefaultValue * GetParameterDefaultValueEntry(const MethodInfo* method, int32_t parameterPosition) +{ + if (il2cpp::vm::Method::IsGenericInstance(method)) + method = il2cpp::vm::MetadataCache::GetGenericMethodDefinition(method); + + IL2CPP_ASSERT(!il2cpp::vm::Method::IsGenericInstance(method)); + + const Il2CppMethodDefinition* methodDefinition = reinterpret_cast<const Il2CppMethodDefinition*>(method->methodMetadataHandle); + + if (methodDefinition == NULL) + return NULL; + + size_t parameterIndex = methodDefinition->parameterStart + parameterPosition; + const Il2CppParameterDefaultValue *start = (const Il2CppParameterDefaultValue*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->parameterDefaultValuesOffset); + const Il2CppParameterDefaultValue *entry = start; + while (entry < start + s_GlobalMetadataHeader->parameterDefaultValuesSize / sizeof(Il2CppParameterDefaultValue)) + { + if (parameterIndex == entry->parameterIndex) + return entry; + entry++; + } + + return NULL; +} + +const uint8_t* il2cpp::vm::GlobalMetadata::GetParameterDefaultValue(const MethodInfo* method, int32_t parameterPosition, const Il2CppType** type, bool* isExplicitySetNullDefaultValue) +{ + *isExplicitySetNullDefaultValue = false; + const Il2CppParameterDefaultValue* parameterDefaultValue = GetParameterDefaultValueEntry(method, parameterPosition); + + if (parameterDefaultValue != NULL) + { + *type = GetIl2CppTypeFromIndex(parameterDefaultValue->typeIndex); + *isExplicitySetNullDefaultValue = parameterDefaultValue->dataIndex == kDefaultValueIndexNull; + return GetFieldOrParameterDefalutValue(parameterDefaultValue->dataIndex); + } + + return NULL; +} + +static TypeDefinitionIndex GetIndexForTypeDefinition(const Il2CppClass* klass) +{ + const Il2CppTypeDefinition* typeDefinition = reinterpret_cast<const Il2CppTypeDefinition*>(klass->typeMetadataHandle); + return GetIndexForTypeDefinitionInternal(typeDefinition); +} + +uint32_t il2cpp::vm::GlobalMetadata::GetFieldOffset(const Il2CppClass* klass, int32_t fieldIndexInType, FieldInfo* field) +{ + uint32_t typeIndex = GetIndexForTypeDefinition(klass); + IL2CPP_ASSERT(typeIndex <= static_cast<uint32_t>(s_Il2CppMetadataRegistration->typeDefinitionsSizesCount)); + int32_t offset = s_Il2CppMetadataRegistration->fieldOffsets[typeIndex][fieldIndexInType]; + return offset; +} + +int il2cpp::vm::GlobalMetadata::GetFieldMarshaledSizeForField(const FieldInfo* field) +{ + Il2CppClass* parent = field->parent; + size_t fieldIndex = (field - parent->fields); + fieldIndex += reinterpret_cast<const Il2CppTypeDefinition*>(parent->typeMetadataHandle)->fieldStart; + + const Il2CppFieldMarshaledSize *start = (const Il2CppFieldMarshaledSize*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldMarshaledSizesOffset); + const Il2CppFieldMarshaledSize *entry = start; + while (entry < start + s_GlobalMetadataHeader->fieldMarshaledSizesSize / sizeof(Il2CppFieldMarshaledSize)) + { + if (fieldIndex == entry->fieldIndex) + return entry->size; + entry++; + } + + return -1; +} + +static const Il2CppFieldDefinition* GetFieldDefinitionFromIndex(const Il2CppImage* image, FieldIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->fieldsSize / sizeof(Il2CppFieldDefinition)); + const Il2CppFieldDefinition* fields = (const Il2CppFieldDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldsOffset); + return fields + index; +} + +Il2CppMetadataFieldInfo il2cpp::vm::GlobalMetadata::GetFieldInfo(const Il2CppClass* klass, TypeFieldIndex fieldIndex) +{ + const Il2CppTypeDefinition* typeDefinition = reinterpret_cast<const Il2CppTypeDefinition*>(klass->typeMetadataHandle); + + IL2CPP_ASSERT(typeDefinition != NULL); + IL2CPP_ASSERT(fieldIndex >= 0 && fieldIndex < typeDefinition->field_count); + IL2CPP_ASSERT(typeDefinition->fieldStart != kFieldIndexInvalid); + + const Il2CppFieldDefinition* fieldDefinition = GetFieldDefinitionFromIndex(klass->image, typeDefinition->fieldStart + fieldIndex); + + return { + GetIl2CppTypeFromIndex(fieldDefinition->typeIndex), + GetStringFromIndex(fieldDefinition->nameIndex), + fieldDefinition->token + }; +} + +Il2CppMetadataMethodInfo il2cpp::vm::GlobalMetadata::GetMethodInfo(const Il2CppClass* klass, TypeMethodIndex index) +{ + const Il2CppTypeDefinition* typeDefinition = reinterpret_cast<const Il2CppTypeDefinition*>(klass->typeMetadataHandle); + + IL2CPP_ASSERT(typeDefinition != NULL); + IL2CPP_ASSERT(index >= 0 && index < typeDefinition->method_count); + IL2CPP_ASSERT(typeDefinition->methodStart != kMethodIndexInvalid); + + const Il2CppMethodDefinition* methodDefinition = GetMethodDefinitionFromIndex(typeDefinition->methodStart + index); + + return { + reinterpret_cast<Il2CppMetadataMethodDefinitionHandle>(methodDefinition), + GetStringFromIndex(methodDefinition->nameIndex), + GetIl2CppTypeFromIndex(methodDefinition->returnType), + methodDefinition->token, + methodDefinition->flags, + methodDefinition->iflags, + methodDefinition->slot, + methodDefinition->parameterCount, + }; +} + +Il2CppMetadataParameterInfo il2cpp::vm::GlobalMetadata::GetParameterInfo(const Il2CppClass* klass, Il2CppMetadataMethodDefinitionHandle handle, MethodParameterIndex paramIndex) +{ + const Il2CppMethodDefinition* methodDefinition = reinterpret_cast<const Il2CppMethodDefinition*>(handle); + + IL2CPP_ASSERT(methodDefinition != NULL); + IL2CPP_ASSERT(paramIndex >= 0 && paramIndex < methodDefinition->parameterCount); + + const Il2CppParameterDefinition* parameterDefinition = GetParameterDefinitionFromIndex(klass->image, methodDefinition->parameterStart + paramIndex); + + return { + GetStringFromIndex(parameterDefinition->nameIndex), + parameterDefinition->token, + GetIl2CppTypeFromIndex(parameterDefinition->typeIndex), + }; +} + +Il2CppMetadataPropertyInfo il2cpp::vm::GlobalMetadata::GetPropertyInfo(const Il2CppClass* klass, TypePropertyIndex index) +{ + const Il2CppTypeDefinition* typeDefintion = reinterpret_cast<const Il2CppTypeDefinition*>(klass->typeMetadataHandle); + + IL2CPP_ASSERT(typeDefintion != NULL); + IL2CPP_ASSERT(index >= 0 && index < typeDefintion->property_count); + IL2CPP_ASSERT(typeDefintion->propertyStart != kPropertyIndexInvalid); + + const Il2CppPropertyDefinition* propertyDefintion = GetPropertyDefinitionFromIndex(klass->image, typeDefintion->propertyStart + index); + + return { + GetStringFromIndex(propertyDefintion->nameIndex), + propertyDefintion->get != kMethodIndexInvalid ? klass->methods[propertyDefintion->get] : NULL, + propertyDefintion->set != kMethodIndexInvalid ? klass->methods[propertyDefintion->set] : NULL, + propertyDefintion->attrs, + propertyDefintion->token, + }; +} + +Il2CppMetadataEventInfo il2cpp::vm::GlobalMetadata::GetEventInfo(const Il2CppClass* klass, TypeEventIndex index) +{ + const Il2CppTypeDefinition* typeDefintion = reinterpret_cast<const Il2CppTypeDefinition*>(klass->typeMetadataHandle); + + IL2CPP_ASSERT(typeDefintion != NULL); + IL2CPP_ASSERT(index >= 0 && index < typeDefintion->event_count); + + const Il2CppEventDefinition* eventDefintion = GetEventDefinitionFromIndex(klass->image, typeDefintion->eventStart + index); + + return { + GetStringFromIndex(eventDefintion->nameIndex), + GetIl2CppTypeFromIndex(eventDefintion->typeIndex), + eventDefintion->add != kMethodIndexInvalid ? klass->methods[eventDefintion->add] : NULL, + eventDefintion->remove != kMethodIndexInvalid ? klass->methods[eventDefintion->remove] : NULL, + eventDefintion->raise != kMethodIndexInvalid ? klass->methods[eventDefintion->raise] : NULL, + eventDefintion->token, + }; +} + +static const Il2CppGenericContainer* GetGenericContainerFromIndexInternal(GenericContainerIndex index) +{ + if (index == kGenericContainerIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->genericContainersSize / sizeof(Il2CppGenericContainer)); + const Il2CppGenericContainer* genericContainers = (const Il2CppGenericContainer*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->genericContainersOffset); + return genericContainers + index; +} + +static Il2CppMetadataGenericContainerHandle GetGenericContainerFromIndex(GenericContainerIndex index) +{ + const Il2CppGenericContainer* container = GetGenericContainerFromIndexInternal(index); + return reinterpret_cast<Il2CppMetadataGenericContainerHandle>(container); +} + +Il2CppMetadataGenericContainerHandle il2cpp::vm::GlobalMetadata::GetGenericContainerFromGenericClass(const Il2CppGenericClass* genericClass) +{ + const Il2CppTypeDefinition* genericType = reinterpret_cast<const Il2CppTypeDefinition*>(GetTypeHandleFromType(genericClass->type)); + return GetGenericContainerFromIndex(genericType->genericContainerIndex); +} + +Il2CppMetadataGenericContainerHandle il2cpp::vm::GlobalMetadata::GetGenericContainerFromMethod(Il2CppMetadataMethodDefinitionHandle handle) +{ + const Il2CppMethodDefinition* methodDefinition = reinterpret_cast<const Il2CppMethodDefinition*>(handle); + return GetGenericContainerFromIndex(methodDefinition->genericContainerIndex); +} + +const Il2CppGenericMethod* il2cpp::vm::GlobalMetadata::GetGenericMethodFromTokenMethodTuple(const Il2CppTokenIndexMethodTuple* tuple) +{ + return GetGenericMethodFromIndex(tuple->__genericMethodIndex); +} + +static Il2CppMetadataGenericParameterHandle GetGenericParameterFromIndexInternal(GenericParameterIndex index) +{ + if (index == kGenericParameterIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->genericParametersSize / sizeof(Il2CppGenericParameter)); + const Il2CppGenericParameter* genericParameters = (const Il2CppGenericParameter*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->genericParametersOffset); + return reinterpret_cast<Il2CppMetadataGenericParameterHandle>(genericParameters + index); +} + +Il2CppMetadataGenericParameterHandle il2cpp::vm::GlobalMetadata::GetGenericParameterFromType(const Il2CppType* type) +{ + IL2CPP_ASSERT(type->type == IL2CPP_TYPE_VAR || type->type == IL2CPP_TYPE_MVAR); + return type->data.genericParameterHandle; +} + +Il2CppClass* il2cpp::vm::GlobalMetadata::GetContainerDeclaringType(Il2CppMetadataGenericContainerHandle handle) +{ + const Il2CppGenericContainer* genericContainer = reinterpret_cast<const Il2CppGenericContainer*>(handle); + + if (genericContainer->is_method) + return GetMethodInfoFromMethodDefinitionIndex(genericContainer->ownerIndex)->klass; + + return GetTypeInfoFromTypeDefinitionIndex(genericContainer->ownerIndex); +} + +Il2CppClass* il2cpp::vm::GlobalMetadata::GetParameterDeclaringType(Il2CppMetadataGenericParameterHandle handle) +{ + const Il2CppGenericParameter* genericParameter = reinterpret_cast<const Il2CppGenericParameter*>(handle); + + const Il2CppGenericContainer* genericContainer = GetGenericContainerFromIndexInternal(genericParameter->ownerIndex); + + if (genericContainer->is_method) + return GetMethodInfoFromMethodDefinitionIndex(genericContainer->ownerIndex)->klass; + + return GetTypeInfoFromTypeDefinitionIndex(genericContainer->ownerIndex); +} + +Il2CppMetadataGenericParameterHandle il2cpp::vm::GlobalMetadata::GetGenericParameterFromIndex(Il2CppMetadataGenericContainerHandle handle, GenericContainerParameterIndex index) +{ + const Il2CppGenericContainer* genericContainer = reinterpret_cast<const Il2CppGenericContainer*>(handle); + + IL2CPP_ASSERT(index >= 0 && index < genericContainer->type_argc); + + return GetGenericParameterFromIndexInternal(genericContainer->genericParameterStart + index); +} + +const Il2CppType* il2cpp::vm::GlobalMetadata::GetGenericParameterConstraintFromIndex(Il2CppMetadataGenericParameterHandle handle, GenericParameterConstraintIndex index) +{ + const Il2CppGenericParameter* genericParameter = reinterpret_cast<const Il2CppGenericParameter*>(handle); + + IL2CPP_ASSERT(index >= 0 && index < genericParameter->constraintsCount); + + index = genericParameter->constraintsStart + index; + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->genericParameterConstraintsSize / sizeof(TypeIndex)); + const TypeIndex* constraintIndices = (const TypeIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->genericParameterConstraintsOffset); + + return GetIl2CppTypeFromIndex(constraintIndices[index]); +} + +static GenericParameterIndex GetIndexForGenericParameter(Il2CppMetadataGenericParameterHandle handle) +{ + const Il2CppGenericParameter* genericParameter = reinterpret_cast<const Il2CppGenericParameter*>(handle); + const Il2CppGenericParameter* genericParameters = (const Il2CppGenericParameter*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->genericParametersOffset); + + IL2CPP_ASSERT(genericParameter >= genericParameters && genericParameter < genericParameters + s_GlobalMetadataHeader->genericParametersSize / sizeof(Il2CppGenericParameter)); + + ptrdiff_t index = genericParameter - genericParameters; + IL2CPP_ASSERT(index <= std::numeric_limits<GenericParameterIndex>::max()); + return static_cast<GenericParameterIndex>(index); +} + +const MethodInfo* il2cpp::vm::GlobalMetadata::GetGenericInstanceMethod(const MethodInfo* genericMethodDefinition, const Il2CppGenericContext* context) +{ + const MethodInfo* method = genericMethodDefinition; + const Il2CppGenericInst* classInst = context->class_inst; + const Il2CppGenericInst* methodInst = context->method_inst; + if (genericMethodDefinition->is_inflated) + { + IL2CPP_ASSERT(genericMethodDefinition->klass->generic_class); + classInst = genericMethodDefinition->klass->generic_class->context.class_inst; + method = genericMethodDefinition->genericMethod->methodDefinition; + } + + return il2cpp::metadata::GenericMethod::GetMethod(method, classInst, methodInst); +} + +const Il2CppType* il2cpp::vm::GlobalMetadata::GetTypeFromRgctxDefinition(const Il2CppRGCTXDefinition* rgctxDef) +{ + IL2CPP_ASSERT(rgctxDef->type == IL2CPP_RGCTX_DATA_TYPE || rgctxDef->type == IL2CPP_RGCTX_DATA_CLASS); + return GetIl2CppTypeFromIndex(((const Il2CppRGCTXDefinitionData*)rgctxDef->data)->__typeIndex); +} + +const Il2CppGenericMethod* il2cpp::vm::GlobalMetadata::GetGenericMethodFromRgctxDefinition(const Il2CppRGCTXDefinition* rgctxDef) +{ + IL2CPP_ASSERT(rgctxDef->type == IL2CPP_RGCTX_DATA_METHOD); + return GetGenericMethodFromIndex(((const Il2CppRGCTXDefinitionData*)rgctxDef->data)->__methodIndex); +} + +std::pair<const Il2CppType*, const MethodInfo*> il2cpp::vm::GlobalMetadata::GetConstrainedCallFromRgctxDefinition(const Il2CppRGCTXDefinition* rgctxDef) +{ + IL2CPP_ASSERT(rgctxDef->type == IL2CPP_RGCTX_DATA_CONSTRAINED); + + const Il2CppRGCTXConstrainedData* constrainedData = (const Il2CppRGCTXConstrainedData*)rgctxDef->data; + + const Il2CppType* type = GetIl2CppTypeFromIndex(constrainedData->__typeIndex); + const MethodInfo* method = GetMethodInfoFromEncodedIndex(constrainedData->__encodedMethodIndex); + return std::make_pair(type, method); +} + +enum PackingSize +{ + Zero, + One, + Two, + Four, + Eight, + Sixteen, + ThirtyTwo, + SixtyFour, + OneHundredTwentyEight +}; + +static uint8_t ConvertPackingSizeEnumToValue(PackingSize packingSize) +{ + switch (packingSize) + { + case Zero: + return 0; + case One: + return 1; + case Two: + return 2; + case Four: + return 4; + case Eight: + return 8; + case Sixteen: + return 16; + case ThirtyTwo: + return 32; + case SixtyFour: + return 64; + case OneHundredTwentyEight: + return 128; + default: + Assert(0 && "Invalid packing size!"); + return 0; + } +} + +int32_t il2cpp::vm::GlobalMetadata::StructLayoutPack(Il2CppMetadataTypeHandle handle) +{ + return ConvertPackingSizeEnumToValue(static_cast<PackingSize>((reinterpret_cast<const Il2CppTypeDefinition*>(handle)->bitfield >> (kSpecifiedPackingSize - 1)) & 0xF)); +} + +static const Il2CppImage* GetImageForTypeDefinitionIndex(TypeDefinitionIndex index) +{ + for (int32_t imageIndex = 0; imageIndex < s_MetadataImagesCount; imageIndex++) + { + const Il2CppImageGlobalMetadata* imageMetadata = s_MetadataImagesTable + imageIndex; + IL2CPP_ASSERT(index >= 0); + if (index >= imageMetadata->typeStart && static_cast<uint32_t>(index) < (imageMetadata->typeStart + imageMetadata->image->typeCount)) + return imageMetadata->image; + } + + IL2CPP_ASSERT(0 && "Failed to find owning image for type defintion index"); + return NULL; +} + +static Il2CppClass* FromTypeDefinition(TypeDefinitionIndex index) +{ + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_GlobalMetadataHeader->typeDefinitionsSize / sizeof(Il2CppTypeDefinition)); + const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); + const Il2CppTypeDefinition* typeDefinition = typeDefinitions + index; + const Il2CppTypeDefinitionSizes* typeDefinitionSizes = s_Il2CppMetadataRegistration->typeDefinitionsSizes[index]; + Il2CppClass* typeInfo = (Il2CppClass*)IL2CPP_CALLOC(1, sizeof(Il2CppClass) + (sizeof(VirtualInvokeData) * typeDefinition->vtable_count)); + typeInfo->klass = typeInfo; + typeInfo->image = GetImageForTypeDefinitionIndex(index); + typeInfo->name = GetStringFromIndex(typeDefinition->nameIndex); + typeInfo->namespaze = GetStringFromIndex(typeDefinition->namespaceIndex); + typeInfo->byval_arg = *il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(typeDefinition->byvalTypeIndex); + typeInfo->this_arg = typeInfo->byval_arg; + typeInfo->this_arg.byref = true; + typeInfo->this_arg.valuetype = 0; + typeInfo->typeMetadataHandle = reinterpret_cast<const Il2CppMetadataTypeHandle>(typeDefinition); + typeInfo->genericContainerHandle = GetGenericContainerFromIndex(typeDefinition->genericContainerIndex); + typeInfo->instance_size = typeDefinitionSizes->instance_size; + typeInfo->actualSize = typeDefinitionSizes->instance_size; // actualySize is instance_size for compiler generated values + typeInfo->native_size = typeDefinitionSizes->native_size; + typeInfo->static_fields_size = typeDefinitionSizes->static_fields_size; + typeInfo->thread_static_fields_size = typeDefinitionSizes->thread_static_fields_size; + typeInfo->thread_static_fields_offset = -1; + typeInfo->flags = typeDefinition->flags; + typeInfo->enumtype = (typeDefinition->bitfield >> (kBitIsEnum - 1)) & 0x1; + typeInfo->is_generic = typeDefinition->genericContainerIndex != kGenericContainerIndexInvalid; // generic if we have a generic container + typeInfo->has_finalize = (typeDefinition->bitfield >> (kBitHasFinalizer - 1)) & 0x1; + typeInfo->has_cctor = (typeDefinition->bitfield >> (kBitHasStaticConstructor - 1)) & 0x1; + typeInfo->cctor_finished_or_no_cctor = !typeInfo->has_cctor; + typeInfo->is_blittable = (typeDefinition->bitfield >> (kBitIsBlittable - 1)) & 0x1; + typeInfo->is_import_or_windows_runtime = (typeDefinition->bitfield >> (kBitIsImportOrWindowsRuntime - 1)) & 0x1; + typeInfo->packingSize = ConvertPackingSizeEnumToValue(static_cast<PackingSize>((typeDefinition->bitfield >> (kPackingSize - 1)) & 0xF)); + typeInfo->is_byref_like = (typeDefinition->bitfield >> (kBitIsByRefLike - 1)) & 0x1; + typeInfo->method_count = typeDefinition->method_count; + typeInfo->property_count = typeDefinition->property_count; + typeInfo->field_count = typeDefinition->field_count; + typeInfo->event_count = typeDefinition->event_count; + typeInfo->nested_type_count = typeDefinition->nested_type_count; + typeInfo->vtable_count = typeDefinition->vtable_count; + typeInfo->interfaces_count = typeDefinition->interfaces_count; + typeInfo->interface_offsets_count = typeDefinition->interface_offsets_count; + typeInfo->token = typeDefinition->token; + typeInfo->interopData = il2cpp::vm::MetadataCache::GetInteropDataForType(&typeInfo->byval_arg); + + if (typeDefinition->parentIndex != kTypeIndexInvalid) + typeInfo->parent = il2cpp::vm::Class::FromIl2CppType(il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(typeDefinition->parentIndex)); + + if (typeDefinition->declaringTypeIndex != kTypeIndexInvalid) + typeInfo->declaringType = il2cpp::vm::Class::FromIl2CppType(il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(typeDefinition->declaringTypeIndex)); + + typeInfo->castClass = typeInfo->element_class = typeInfo; + if (typeInfo->enumtype) + typeInfo->castClass = typeInfo->element_class = il2cpp::vm::Class::FromIl2CppType(il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(typeDefinition->elementTypeIndex)); + + return typeInfo; +} + +const Il2CppType* il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(TypeIndex index) +{ + if (index == kTypeIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index < s_Il2CppMetadataRegistration->typesCount && "Invalid type index "); + + return s_Il2CppMetadataRegistration->types[index]; +} + +uint32_t il2cpp::vm::GlobalMetadata::GetGenericContainerCount(Il2CppMetadataGenericContainerHandle handle) +{ + const Il2CppGenericContainer* container = reinterpret_cast<const Il2CppGenericContainer*>(handle); + return container != NULL ? container->type_argc : 0; +} + +void il2cpp::vm::GlobalMetadata::MakeGenericArgType(Il2CppMetadataGenericContainerHandle containerHandle, Il2CppMetadataGenericParameterHandle paramHandle, Il2CppType* arg) +{ + const Il2CppGenericContainer* container = reinterpret_cast<const Il2CppGenericContainer*>(containerHandle); + + arg->type = container->is_method ? IL2CPP_TYPE_MVAR : IL2CPP_TYPE_VAR; + arg->data.genericParameterHandle = paramHandle; +} + +bool il2cpp::vm::GlobalMetadata::GetGenericContainerIsMethod(Il2CppMetadataGenericContainerHandle handle) +{ + const Il2CppGenericContainer* container = reinterpret_cast<const Il2CppGenericContainer*>(handle); + IL2CPP_ASSERT(container != NULL); + return container != NULL ? container->is_method : false; +} + +int16_t il2cpp::vm::GlobalMetadata::GetGenericConstraintCount(Il2CppMetadataGenericParameterHandle handle) +{ + const Il2CppGenericParameter* genericParameter = reinterpret_cast<const Il2CppGenericParameter*>(handle); + return genericParameter->constraintsCount; +} + +const char* il2cpp::vm::GlobalMetadata::GetGenericParameterName(Il2CppMetadataGenericParameterHandle handle) +{ + const Il2CppGenericParameter* genericParameter = reinterpret_cast<const Il2CppGenericParameter*>(handle); + return GetStringFromIndex(genericParameter->nameIndex); +} + +Il2CppGenericParameterInfo il2cpp::vm::GlobalMetadata::GetGenericParameterInfo(Il2CppMetadataGenericParameterHandle handle) +{ + const Il2CppGenericParameter* genericParameter = reinterpret_cast<const Il2CppGenericParameter*>(handle); + + return { + reinterpret_cast<Il2CppMetadataGenericContainerHandle>(GetGenericContainerFromIndexInternal(genericParameter->ownerIndex)), + GetStringFromIndex(genericParameter->nameIndex), + genericParameter->num, + genericParameter->flags + }; +} + +uint16_t il2cpp::vm::GlobalMetadata::GetGenericParameterFlags(Il2CppMetadataGenericParameterHandle handle) +{ + const Il2CppGenericParameter* genericParameter = reinterpret_cast<const Il2CppGenericParameter*>(handle); + return genericParameter->flags; +} + +const MethodInfo* il2cpp::vm::GlobalMetadata::GetMethodInfoFromCatchPoint(const Il2CppCatchPoint* cp) +{ + return GetMethodInfoFromMethodDefinitionIndex(cp->__methodDefinitionIndex); +} + +const MethodInfo* il2cpp::vm::GlobalMetadata::GetMethodInfoFromSequencePoint(const Il2CppSequencePoint* seqPoint) +{ + return GetMethodInfoFromMethodDefinitionIndex(seqPoint->__methodDefinitionIndex); +} + +Il2CppClass* il2cpp::vm::GlobalMetadata::GetTypeInfoFromTypeSourcePair(const Il2CppTypeSourceFilePair* pair) +{ + return GetTypeInfoFromTypeDefinitionIndex(pair->__klassIndex); +} + +Il2CppClass* il2cpp::vm::GlobalMetadata::GetTypeInfoFromTypeIndex(TypeIndex index, bool throwOnError) +{ + if (index == kTypeIndexInvalid) + return NULL; + + IL2CPP_ASSERT(index < s_Il2CppMetadataRegistration->typesCount && "Invalid type index "); + + if (s_TypeInfoTable[index]) + return s_TypeInfoTable[index]; + + const Il2CppType* type = s_Il2CppMetadataRegistration->types[index]; + + Il2CppClass *klass = Class::FromIl2CppType(type, throwOnError); + if (klass != NULL) + { + s_TypeInfoTable[index] = ClassInlines::InitFromCodegenSlow(klass, throwOnError); + } + return s_TypeInfoTable[index]; +} + +const MethodInfo* il2cpp::vm::GlobalMetadata::GetMethodInfoFromMethodHandle(Il2CppMetadataMethodDefinitionHandle handle) +{ + const Il2CppMethodDefinition* methodDefinition = reinterpret_cast<const Il2CppMethodDefinition*>(handle); + const Il2CppMethodDefinition* methods = (const Il2CppMethodDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->methodsOffset); + + const MethodIndex index = static_cast<MethodIndex>(methodDefinition - methods); + + IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) <= s_GlobalMetadataHeader->methodsSize / sizeof(Il2CppMethodDefinition)); + + return GetMethodInfoFromMethodDefinitionIndex(index); +} + +#if IL2CPP_ENABLE_NATIVE_STACKTRACES +void il2cpp::vm::GlobalMetadata::GetAllManagedMethods(std::vector<MethodDefinitionKey>& managedMethods) +{ + size_t methodDefinitionsCount = s_GlobalMetadataHeader->methodsSize / sizeof(Il2CppMethodDefinition); + managedMethods.reserve(methodDefinitionsCount + s_Il2CppMetadataRegistration->genericMethodTableCount); + + const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); + for (int32_t i = 0; i < s_MetadataImagesCount; i++) + { + const Il2CppImageGlobalMetadata* image = s_MetadataImagesTable + i; + + for (size_t j = 0; j < image->image->typeCount; j++) + { + const Il2CppTypeDefinition* type = typeDefinitions + image->typeStart + j; + + for (uint16_t u = 0; u < type->method_count; u++) + { + const Il2CppMethodDefinition* methodDefinition = GetMethodDefinitionFromIndex(type->methodStart + u); + MethodDefinitionKey currentMethodList; + currentMethodList.methodHandle = reinterpret_cast<Il2CppMetadataMethodDefinitionHandle>(methodDefinition); + currentMethodList.method = il2cpp::vm::MetadataCache::GetMethodPointer(image->image, methodDefinition->token); + if (currentMethodList.method) + managedMethods.push_back(currentMethodList); + } + } + } + + for (int32_t i = 0; i < s_Il2CppMetadataRegistration->genericMethodTableCount; i++) + { + const Il2CppGenericMethodFunctionsDefinitions* genericMethodIndices = s_Il2CppMetadataRegistration->genericMethodTable + i; + + MethodDefinitionKey currentMethodList; + + GenericMethodIndex genericMethodIndex = genericMethodIndices->genericMethodIndex; + + IL2CPP_ASSERT(genericMethodIndex < s_Il2CppMetadataRegistration->methodSpecsCount); + const Il2CppMethodSpec* methodSpec = s_Il2CppMetadataRegistration->methodSpecs + genericMethodIndex; + const Il2CppMethodDefinition* methodDefinition = GetMethodDefinitionFromIndex(methodSpec->methodDefinitionIndex); + currentMethodList.methodHandle = reinterpret_cast<Il2CppMetadataMethodDefinitionHandle>(methodDefinition); + + IL2CPP_ASSERT(genericMethodIndices->indices.methodIndex < static_cast<int32_t>(s_GlobalMetadata_CodeRegistration->genericMethodPointersCount)); + currentMethodList.method = s_GlobalMetadata_CodeRegistration->genericMethodPointers[genericMethodIndices->indices.methodIndex]; + + managedMethods.push_back(currentMethodList); + } +} + +#endif diff --git a/O&Z_IL2CPP_Security/resource/src-res/28/GlobalMetadataFileInternals.h b/O&Z_IL2CPP_Security/resource/src-res/28/GlobalMetadataFileInternals.h new file mode 100644 index 0000000..b11ef55 --- /dev/null +++ b/O&Z_IL2CPP_Security/resource/src-res/28/GlobalMetadataFileInternals.h @@ -0,0 +1,353 @@ +#pragma once + +#include "il2cpp-metadata.h" + +// This file contains the structures specifying how we store converted metadata. +// These structures have 3 constraints: +// 1. These structures will be stored in an external file, and as such must not contain any pointers. +// All references to other metadata should occur via an index into a corresponding table. +// 2. These structures are assumed to be const. Either const structures in the binary or mapped as +// readonly memory from an external file. Do not add any 'calculated' fields which will be written to at runtime. +// 3. These structures should be optimized for size. Other structures are used at runtime which can +// be larger to store cached information + +// Encoded index (1 bit) +// MethodDef - 0 +// MethodSpec - 1 +// We use the top 3 bits to indicate what table to index into +// Type Binary Hex +// Il2CppClass 001 0x20000000 +// Il2CppType 010 0x40000000 +// MethodInfo 011 0x60000000 +// FieldInfo 100 0x80000000 +// StringLiteral 101 0xA0000000 +// MethodRef 110 0xC0000000 + +typedef uint32_t EncodedMethodIndex; + +enum Il2CppMetadataUsage +{ + kIl2CppMetadataUsageInvalid, + kIl2CppMetadataUsageTypeInfo, + kIl2CppMetadataUsageIl2CppType, + kIl2CppMetadataUsageMethodDef, + kIl2CppMetadataUsageFieldInfo, + kIl2CppMetadataUsageStringLiteral, + kIl2CppMetadataUsageMethodRef, +}; + +enum Il2CppInvalidMetadataUsageToken +{ + kIl2CppInvalidMetadataUsageNoData = 0, + kIl2CppInvalidMetadataUsageAmbiguousMethod = 1, +}; + +#ifdef __cplusplus +static inline Il2CppMetadataUsage GetEncodedIndexType(EncodedMethodIndex index) +{ + return (Il2CppMetadataUsage)((index & 0xE0000000) >> 29); +} + +static inline uint32_t GetDecodedMethodIndex(EncodedMethodIndex index) +{ + return (index & 0x1FFFFFFEU) >> 1; +} + +#endif + +typedef struct Il2CppInterfaceOffsetPair +{ + TypeIndex interfaceTypeIndex; + int32_t offset; +} Il2CppInterfaceOffsetPair; + +typedef struct Il2CppTypeDefinition +{ + StringIndex nameIndex; + StringIndex namespaceIndex; + TypeIndex byvalTypeIndex; + + TypeIndex declaringTypeIndex; + TypeIndex parentIndex; + TypeIndex elementTypeIndex; // we can probably remove this one. Only used for enums + + GenericContainerIndex genericContainerIndex; + + uint32_t flags; + + FieldIndex fieldStart; + MethodIndex methodStart; + EventIndex eventStart; + PropertyIndex propertyStart; + NestedTypeIndex nestedTypesStart; + InterfacesIndex interfacesStart; + VTableIndex vtableStart; + InterfacesIndex interfaceOffsetsStart; + + uint16_t method_count; + uint16_t property_count; + uint16_t field_count; + uint16_t event_count; + uint16_t nested_type_count; + uint16_t vtable_count; + uint16_t interfaces_count; + uint16_t interface_offsets_count; + + // bitfield to portably encode boolean values as single bits + // 01 - valuetype; + // 02 - enumtype; + // 03 - has_finalize; + // 04 - has_cctor; + // 05 - is_blittable; + // 06 - is_import_or_windows_runtime; + // 07-10 - One of nine possible PackingSize values (0, 1, 2, 4, 8, 16, 32, 64, or 128) + // 11 - PackingSize is default + // 12 - ClassSize is default + // 13-16 - One of nine possible PackingSize values (0, 1, 2, 4, 8, 16, 32, 64, or 128) - the specified packing size (even for explicit layouts) + uint32_t bitfield; + uint32_t token; +} Il2CppTypeDefinition; + +typedef struct Il2CppFieldDefinition +{ + StringIndex nameIndex; + TypeIndex typeIndex; + uint32_t token; +} Il2CppFieldDefinition; + +typedef struct Il2CppFieldDefaultValue +{ + FieldIndex fieldIndex; + TypeIndex typeIndex; + DefaultValueDataIndex dataIndex; +} Il2CppFieldDefaultValue; + +typedef struct Il2CppFieldMarshaledSize +{ + FieldIndex fieldIndex; + TypeIndex typeIndex; + int32_t size; +} Il2CppFieldMarshaledSize; + +typedef struct Il2CppFieldRef +{ + TypeIndex typeIndex; + FieldIndex fieldIndex; // local offset into type fields +} Il2CppFieldRef; + +typedef struct Il2CppParameterDefinition +{ + StringIndex nameIndex; + uint32_t token; + TypeIndex typeIndex; +} Il2CppParameterDefinition; + +typedef struct Il2CppParameterDefaultValue +{ + ParameterIndex parameterIndex; + TypeIndex typeIndex; + DefaultValueDataIndex dataIndex; +} Il2CppParameterDefaultValue; + +typedef struct Il2CppMethodDefinition +{ + StringIndex nameIndex; + TypeDefinitionIndex declaringType; + TypeIndex returnType; + ParameterIndex parameterStart; + GenericContainerIndex genericContainerIndex; + uint32_t token; + uint16_t flags; + uint16_t iflags; + uint16_t slot; + uint16_t parameterCount; +} Il2CppMethodDefinition; + +typedef struct Il2CppEventDefinition +{ + StringIndex nameIndex; + TypeIndex typeIndex; + MethodIndex add; + MethodIndex remove; + MethodIndex raise; + uint32_t token; +} Il2CppEventDefinition; + +typedef struct Il2CppPropertyDefinition +{ + StringIndex nameIndex; + MethodIndex get; + MethodIndex set; + uint32_t attrs; + uint32_t token; +} Il2CppPropertyDefinition; + +typedef struct Il2CppStringLiteral +{ + StringLiteralIndex dataIndex; + uint32_t length; +} Il2CppStringLiteral; + +typedef struct Il2CppAssemblyNameDefinition +{ + StringIndex nameIndex; + StringIndex cultureIndex; + StringIndex publicKeyIndex; + uint32_t hash_alg; + int32_t hash_len; + uint32_t flags; + int32_t major; + int32_t minor; + int32_t build; + int32_t revision; + uint8_t public_key_token[PUBLIC_KEY_BYTE_LENGTH]; +} Il2CppAssemblyNameDefinition; + +typedef struct Il2CppImageDefinition +{ + StringIndex nameIndex; + AssemblyIndex assemblyIndex; + + TypeDefinitionIndex typeStart; + uint32_t typeCount; + + TypeDefinitionIndex exportedTypeStart; + uint32_t exportedTypeCount; + + MethodIndex entryPointIndex; + uint32_t token; + + CustomAttributeIndex customAttributeStart; + uint32_t customAttributeCount; +} Il2CppImageDefinition; + +typedef struct Il2CppAssemblyDefinition +{ + ImageIndex imageIndex; + uint32_t token; + int32_t referencedAssemblyStart; + int32_t referencedAssemblyCount; + Il2CppAssemblyNameDefinition aname; +} Il2CppAssemblyDefinition; + +typedef struct Il2CppCustomAttributeDataRange +{ + uint32_t token; + uint32_t startOffset; +} Il2CppCustomAttributeDataRange; + +typedef struct Il2CppMetadataRange +{ + int32_t start; + int32_t length; +} Il2CppMetadataRange; + +typedef struct Il2CppGenericContainer +{ + /* index of the generic type definition or the generic method definition corresponding to this container */ + int32_t ownerIndex; // either index into Il2CppClass metadata array or Il2CppMethodDefinition array + int32_t type_argc; + /* If true, we're a generic method, otherwise a generic type definition. */ + int32_t is_method; + /* Our type parameters. */ + GenericParameterIndex genericParameterStart; +} Il2CppGenericContainer; + +typedef struct Il2CppGenericParameter +{ + GenericContainerIndex ownerIndex; /* Type or method this parameter was defined in. */ + StringIndex nameIndex; + GenericParameterConstraintIndex constraintsStart; + int16_t constraintsCount; + uint16_t num; + uint16_t flags; +} Il2CppGenericParameter; + +typedef struct Il2CppWindowsRuntimeTypeNamePair +{ + StringIndex nameIndex; + TypeIndex typeIndex; +} Il2CppWindowsRuntimeTypeNamePair; + +#pragma pack(push, p1, 4) +typedef struct Il2CppGlobalMetadataHeader +{ + int32_t sanity; + + int32_t stringLiteralOffset; // string data for managed code + int32_t interfacesOffset; // TypeIndex + int32_t stringLiteralDataOffset; + int32_t stringOffset; // string data for metadata + int32_t vtableMethodsOffset; // EncodedMethodIndex + int32_t eventsOffset; // Il2CppEventDefinition + int32_t interfaceOffsetsOffset; // Il2CppInterfaceOffsetPair + int32_t propertiesOffset; // Il2CppPropertyDefinition + int32_t assembliesOffset; // Il2CppAssemblyDefinition + int32_t methodsOffset; // Il2CppMethodDefinition + int32_t fieldRefsOffset; // Il2CppFieldRef + int32_t parameterDefaultValuesOffset; // Il2CppParameterDefaultValue + int32_t typeDefinitionsOffset; // Il2CppTypeDefinition + int32_t fieldDefaultValuesOffset; // Il2CppFieldDefaultValue + int32_t imagesOffset; // Il2CppImageDefinition + int32_t fieldAndParameterDefaultValueDataOffset; // uint8_t + int32_t referencedAssembliesOffset; // int32_t + int32_t fieldMarshaledSizesOffset; // Il2CppFieldMarshaledSize + int32_t unresolvedVirtualCallParameterTypesOffset; // TypeIndex + int32_t parametersOffset; // Il2CppParameterDefinition + int32_t unresolvedVirtualCallParameterRangesOffset; // Il2CppMetadataRange + int32_t fieldsOffset; // Il2CppFieldDefinition + int32_t windowsRuntimeTypeNamesOffset; // Il2CppWindowsRuntimeTypeNamePair + int32_t genericParametersOffset; // Il2CppGenericParameter + int32_t windowsRuntimeStringsOffset; // const char* + int32_t genericParameterConstraintsOffset; // TypeIndex + int32_t exportedTypeDefinitionsOffset; // TypeDefinitionIndex + int32_t genericContainersOffset; // Il2CppGenericContainer + int32_t nestedTypesOffset; // TypeDefinitionIndex + + int32_t version; + int32_t genericContainersSize; + int32_t stringLiteralSize; + int32_t nestedTypesSize; + int32_t interfacesSize; + int32_t stringLiteralDataSize; + int32_t vtableMethodsSize; + int32_t stringSize; + int32_t interfaceOffsetsSize; + int32_t eventsSize; + int32_t typeDefinitionsSize; + int32_t parameterDefaultValuesSize; + int32_t imagesSize; + int32_t fieldDefaultValuesSize; + int32_t assembliesSize; + int32_t propertiesSize; + int32_t fieldRefsSize; + int32_t methodsSize; + int32_t referencedAssembliesSize; + int32_t attributeDataOffset; + int32_t attributeDataSize; + int32_t attributeDataRangeOffset; + int32_t attributeDataRangeSize; + int32_t fieldAndParameterDefaultValueDataSize; + int32_t unresolvedVirtualCallParameterTypesSize; + int32_t fieldMarshaledSizesSize; + int32_t unresolvedVirtualCallParameterRangesSize; + int32_t parametersSize; + int32_t windowsRuntimeTypeNamesSize; + int32_t fieldsSize; + int32_t windowsRuntimeStringsSize; + int32_t genericParametersSize; + int32_t exportedTypeDefinitionsSize; + int32_t genericParameterConstraintsSize; +} Il2CppGlobalMetadataHeader; +#pragma pack(pop, p1) + +//FrontHeader +#pragma pack(push, p1, 4) +typedef struct FrontHeader +{ + char sign[24]; + int64_t offset; + int32_t legnth; + unsigned char key[32]; +} FrontHeader; +#pragma pack(pop, p1) \ No newline at end of file diff --git a/O&Z_IL2CPP_Security/resource/src-res/xxtea.cpp b/O&Z_IL2CPP_Security/resource/src-res/xxtea.cpp new file mode 100644 index 0000000..0e6ab68 --- /dev/null +++ b/O&Z_IL2CPP_Security/resource/src-res/xxtea.cpp @@ -0,0 +1,260 @@ +/**********************************************************\ +| | +| xxtea.c | +| | +| XXTEA encryption algorithm library for C. | +| | +| Encryption Algorithm Authors: | +| David J. Wheeler | +| Roger M. Needham | +| | +| Code Authors: Chen fei <cf850118@163.com> | +| Ma Bingyao <mabingyao@gmail.com> | +| LastModified: Feb 7, 2016 | +| | +\**********************************************************/ + + +#include "xxtea.h" + +#include <string.h> +#if defined(_MSC_VER) && _MSC_VER < 1600 +typedef unsigned __int8 uint8_t; +typedef unsigned __int32 uint32_t; +#else +#if defined(__FreeBSD__) && __FreeBSD__ < 5 +/* FreeBSD 4 doesn't have stdint.h file */ +#include <inttypes.h> +#else +#include <stdint.h> +#endif +#endif + +#include <sys/types.h> /* This will likely define BYTE_ORDER */ + +#ifndef BYTE_ORDER +#if (BSD >= 199103) +# include <machine/endian.h> +#else +#if defined(linux) || defined(__linux__) +# include <endian.h> +#else +#define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ +#define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ +#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp)*/ + +#if defined(__i386__) || defined(__x86_64__) || defined(__amd64__) || \ + defined(vax) || defined(ns32000) || defined(sun386) || \ + defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ + defined(__alpha__) || defined(__alpha) +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ + defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ + defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ + defined(apollo) || defined(__convex__) || defined(_CRAY) || \ + defined(__hppa) || defined(__hp9000) || \ + defined(__hp9000s300) || defined(__hp9000s700) || \ + defined (BIT_ZERO_ON_LEFT) || defined(m68k) || defined(__sparc) +#define BYTE_ORDER BIG_ENDIAN +#endif +#endif /* linux */ +#endif /* BSD */ +#endif /* BYTE_ORDER */ + +#ifndef BYTE_ORDER +#ifdef __BYTE_ORDER +#if defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN) +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN __LITTLE_ENDIAN +#endif +#ifndef BIG_ENDIAN +#define BIG_ENDIAN __BIG_ENDIAN +#endif +#if (__BYTE_ORDER == __LITTLE_ENDIAN) +#define BYTE_ORDER LITTLE_ENDIAN +#else +#define BYTE_ORDER BIG_ENDIAN +#endif +#endif +#endif +#endif + +#define MX (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z)) +#define DELTA 0x9e3779b9 + +#define FIXED_KEY \ + size_t i;\ + uint8_t fixed_key[16];\ + memcpy(fixed_key, key, 16);\ + for (i = 0; (i < 16) && (fixed_key[i] != 0); ++i);\ + for (++i; i < 16; ++i) fixed_key[i] = 0;\ + + +static uint32_t * xxtea_to_uint_array(const uint8_t * data, size_t len, int inc_len, size_t * out_len) { + uint32_t *out; +#if !(defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)) + size_t i; +#endif + size_t n; + + n = (((len & 3) == 0) ? (len >> 2) : ((len >> 2) + 1)); + + if (inc_len) { + out = (uint32_t *)calloc(n + 1, sizeof(uint32_t)); + if (!out) return NULL; + out[n] = (uint32_t)len; + *out_len = n + 1; + } + else { + out = (uint32_t *)calloc(n, sizeof(uint32_t)); + if (!out) return NULL; + *out_len = n; + } +#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN) + memcpy(out, data, len); +#else + for (i = 0; i < len; ++i) { + out[i >> 2] |= (uint32_t)data[i] << ((i & 3) << 3); + } +#endif + + return out; +} + +static uint8_t * xxtea_to_ubyte_array(const uint32_t * data, size_t len, int inc_len, size_t * out_len) { + uint8_t *out; +#if !(defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)) + size_t i; +#endif + size_t m, n; + + n = len << 2; + + if (inc_len) { + m = data[len - 1]; + n -= 4; + if ((m < n - 3) || (m > n)) return NULL; + n = m; + } + + out = (uint8_t *)malloc(n + 1); + +#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN) + memcpy(out, data, n); +#else + for (i = 0; i < n; ++i) { + out[i] = (uint8_t)(data[i >> 2] >> ((i & 3) << 3)); + } +#endif + + out[n] = '\0'; + *out_len = n; + + return out; +} + +static uint32_t * xxtea_uint_encrypt(uint32_t * data, size_t len, uint32_t * key) { + uint32_t n = (uint32_t)len - 1; + uint32_t z = data[n], y, p, q = 6 + 52 / (n + 1), sum = 0, e; + + if (n < 1) return data; + + while (0 < q--) { + sum += DELTA; + e = sum >> 2 & 3; + + for (p = 0; p < n; p++) { + y = data[p + 1]; + z = data[p] += MX; + } + + y = data[0]; + z = data[n] += MX; + } + + return data; +} + +static uint32_t * xxtea_uint_decrypt(uint32_t * data, size_t len, uint32_t * key) { + uint32_t n = (uint32_t)len - 1; + uint32_t z, y = data[0], p, q = 6 + 52 / (n + 1), sum = q * DELTA, e; + + if (n < 1) return data; + + while (sum != 0) { + e = sum >> 2 & 3; + + for (p = n; p > 0; p--) { + z = data[p - 1]; + y = data[p] -= MX; + } + + z = data[n]; + y = data[0] -= MX; + sum -= DELTA; + } + + return data; +} + +static uint8_t * xxtea_ubyte_encrypt(const uint8_t * data, size_t len, const uint8_t * key, size_t * out_len) { + uint8_t *out; + uint32_t *data_array, *key_array; + size_t data_len, key_len; + + if (!len) return NULL; + + data_array = xxtea_to_uint_array(data, len, 1, &data_len); + if (!data_array) return NULL; + + key_array = xxtea_to_uint_array(key, 16, 0, &key_len); + if (!key_array) { + free(data_array); + return NULL; + } + + out = xxtea_to_ubyte_array(xxtea_uint_encrypt(data_array, data_len, key_array), data_len, 0, out_len); + + free(data_array); + free(key_array); + + return out; +} + +static uint8_t * xxtea_ubyte_decrypt(const uint8_t * data, size_t len, const uint8_t * key, size_t * out_len) { + uint8_t *out; + uint32_t *data_array, *key_array; + size_t data_len, key_len; + + if (!len) return NULL; + + data_array = xxtea_to_uint_array(data, len, 0, &data_len); + if (!data_array) return NULL; + + key_array = xxtea_to_uint_array(key, 16, 0, &key_len); + if (!key_array) { + free(data_array); + return NULL; + } + + out = xxtea_to_ubyte_array(xxtea_uint_decrypt(data_array, data_len, key_array), data_len, 1, out_len); + + free(data_array); + free(key_array); + + return out; +} + +// public functions + +void * xxtea_encrypt(const void * data, size_t len, const void * key, size_t * out_len) { + FIXED_KEY + return xxtea_ubyte_encrypt((const uint8_t *)data, len, fixed_key, out_len); +} + +void * xxtea_decrypt(const void * data, size_t len, const void * key, size_t * out_len) { + FIXED_KEY + return xxtea_ubyte_decrypt((const uint8_t *)data, len, fixed_key, out_len); +} diff --git a/O&Z_IL2CPP_Security/resource/src-res/xxtea.h b/O&Z_IL2CPP_Security/resource/src-res/xxtea.h new file mode 100644 index 0000000..a54a700 --- /dev/null +++ b/O&Z_IL2CPP_Security/resource/src-res/xxtea.h @@ -0,0 +1,54 @@ +/**********************************************************\ +| | +| xxtea.h | +| | +| XXTEA encryption algorithm library for C. | +| | +| Encryption Algorithm Authors: | +| David J. Wheeler | +| Roger M. Needham | +| | +| Code Authors: Chen fei <cf850118@163.com> | +| Ma Bingyao <mabingyao@gmail.com> | +| LastModified: Mar 3, 2015 | +| | +\**********************************************************/ + +#ifndef XXTEA_INCLUDED +#define XXTEA_INCLUDED + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Function: xxtea_encrypt + * @data: Data to be encrypted + * @len: Length of the data to be encrypted + * @key: Symmetric key + * @out_len: Pointer to output length variable + * Returns: Encrypted data or %NULL on failure + * + * Caller is responsible for freeing the returned buffer. + */ +void * xxtea_encrypt(const void * data, size_t len, const void * key, size_t * out_len); + +/** + * Function: xxtea_decrypt + * @data: Data to be decrypted + * @len: Length of the data to be decrypted + * @key: Symmetric key + * @out_len: Pointer to output length variable + * Returns: Decrypted data or %NULL on failure + * + * Caller is responsible for freeing the returned buffer. + */ +void * xxtea_decrypt(const void * data, size_t len, const void * key, size_t * out_len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/O&Z_Obfuscator/LitJson/AssemblyInfo.cs.in b/O&Z_Obfuscator/LitJson/AssemblyInfo.cs.in new file mode 100644 index 0000000..2cd1f90 --- /dev/null +++ b/O&Z_Obfuscator/LitJson/AssemblyInfo.cs.in @@ -0,0 +1,18 @@ +using System; +using System.Reflection; +using System.Runtime.CompilerServices; + + +[assembly: CLSCompliant (true)] + +[assembly: AssemblyTitle ("LitJson")] +[assembly: AssemblyDescription ("LitJSON library")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("LitJSON")] +[assembly: AssemblyCopyright ( + "The authors disclaim copyright to this source code")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] + +[assembly: AssemblyVersion ("@ASSEMBLY_VERSION@")] diff --git a/O&Z_Obfuscator/LitJson/IJsonWrapper.cs b/O&Z_Obfuscator/LitJson/IJsonWrapper.cs new file mode 100644 index 0000000..afa7a1f --- /dev/null +++ b/O&Z_Obfuscator/LitJson/IJsonWrapper.cs @@ -0,0 +1,60 @@ +#region Header +/** + * IJsonWrapper.cs + * Interface that represents a type capable of handling all kinds of JSON + * data. This is mainly used when mapping objects through JsonMapper, and + * it's implemented by JsonData. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System.Collections; +using System.Collections.Specialized; + + +namespace O_Z_IL2CPP_Security.LitJson +{ + public enum JsonType + { + None, + + Object, + Array, + String, + Int, + Long, + Double, + Boolean + } + + public interface IJsonWrapper : IList, IOrderedDictionary + { + bool IsArray { get; } + bool IsBoolean { get; } + bool IsDouble { get; } + bool IsInt { get; } + bool IsLong { get; } + bool IsObject { get; } + bool IsString { get; } + + bool GetBoolean(); + double GetDouble(); + int GetInt(); + JsonType GetJsonType(); + long GetLong(); + string GetString(); + + void SetBoolean(bool val); + void SetDouble(double val); + void SetInt(int val); + void SetJsonType(JsonType type); + void SetLong(long val); + void SetString(string val); + + string ToJson(); + void ToJson(JsonWriter writer); + } +} diff --git a/O&Z_Obfuscator/LitJson/JsonData.cs b/O&Z_Obfuscator/LitJson/JsonData.cs new file mode 100644 index 0000000..926ce0c --- /dev/null +++ b/O&Z_Obfuscator/LitJson/JsonData.cs @@ -0,0 +1,1142 @@ +#region Header +/** + * JsonData.cs + * Generic type to hold JSON data (objects, arrays, and so on). This is + * the default type returned by JsonMapper.ToObject(). + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; + + +namespace O_Z_IL2CPP_Security.LitJson +{ + public class JsonData : IJsonWrapper, IEquatable<JsonData> + { + #region Fields + private IList<JsonData> inst_array; + private bool inst_boolean; + private double inst_double; + private int inst_int; + private long inst_long; + private IDictionary<string, JsonData> inst_object; + private string inst_string; + private string json; + private JsonType type; + + // Used to implement the IOrderedDictionary interface + private IList<KeyValuePair<string, JsonData>> object_list; + #endregion + + + #region Properties + public int Count + { + get { return EnsureCollection().Count; } + } + + public bool IsArray + { + get { return type == JsonType.Array; } + } + + public bool IsBoolean + { + get { return type == JsonType.Boolean; } + } + + public bool IsDouble + { + get { return type == JsonType.Double; } + } + + public bool IsInt + { + get { return type == JsonType.Int; } + } + + public bool IsLong + { + get { return type == JsonType.Long; } + } + + public bool IsObject + { + get { return type == JsonType.Object; } + } + + public bool IsString + { + get { return type == JsonType.String; } + } + + public ICollection<string> Keys + { + get { EnsureDictionary(); return inst_object.Keys; } + } + + /// <summary> + /// Determines whether the json contains an element that has the specified key. + /// </summary> + /// <param name="key">The key to locate in the json.</param> + /// <returns>true if the json contains an element that has the specified key; otherwise, false.</returns> + public bool ContainsKey(string key) + { + EnsureDictionary(); + return inst_object.Keys.Contains(key); + } + #endregion + + + #region ICollection Properties + int ICollection.Count + { + get + { + return Count; + } + } + + bool ICollection.IsSynchronized + { + get + { + return EnsureCollection().IsSynchronized; + } + } + + object ICollection.SyncRoot + { + get + { + return EnsureCollection().SyncRoot; + } + } + #endregion + + + #region IDictionary Properties + bool IDictionary.IsFixedSize + { + get + { + return EnsureDictionary().IsFixedSize; + } + } + + bool IDictionary.IsReadOnly + { + get + { + return EnsureDictionary().IsReadOnly; + } + } + + ICollection IDictionary.Keys + { + get + { + EnsureDictionary(); + IList<string> keys = new List<string>(); + + foreach (KeyValuePair<string, JsonData> entry in + object_list) + { + keys.Add(entry.Key); + } + + return (ICollection)keys; + } + } + + ICollection IDictionary.Values + { + get + { + EnsureDictionary(); + IList<JsonData> values = new List<JsonData>(); + + foreach (KeyValuePair<string, JsonData> entry in + object_list) + { + values.Add(entry.Value); + } + + return (ICollection)values; + } + } + #endregion + + + + #region IJsonWrapper Properties + bool IJsonWrapper.IsArray + { + get { return IsArray; } + } + + bool IJsonWrapper.IsBoolean + { + get { return IsBoolean; } + } + + bool IJsonWrapper.IsDouble + { + get { return IsDouble; } + } + + bool IJsonWrapper.IsInt + { + get { return IsInt; } + } + + bool IJsonWrapper.IsLong + { + get { return IsLong; } + } + + bool IJsonWrapper.IsObject + { + get { return IsObject; } + } + + bool IJsonWrapper.IsString + { + get { return IsString; } + } + #endregion + + + #region IList Properties + bool IList.IsFixedSize + { + get + { + return EnsureList().IsFixedSize; + } + } + + bool IList.IsReadOnly + { + get + { + return EnsureList().IsReadOnly; + } + } + #endregion + + + #region IDictionary Indexer + object IDictionary.this[object key] + { + get + { + return EnsureDictionary()[key]; + } + + set + { + if (!(key is string)) + throw new ArgumentException( + "The key has to be a string"); + + JsonData data = ToJsonData(value); + + this[(string)key] = data; + } + } + #endregion + + + #region IOrderedDictionary Indexer + object IOrderedDictionary.this[int idx] + { + get + { + EnsureDictionary(); + return object_list[idx].Value; + } + + set + { + EnsureDictionary(); + JsonData data = ToJsonData(value); + + KeyValuePair<string, JsonData> old_entry = object_list[idx]; + + inst_object[old_entry.Key] = data; + + KeyValuePair<string, JsonData> entry = + new KeyValuePair<string, JsonData>(old_entry.Key, data); + + object_list[idx] = entry; + } + } + #endregion + + + #region IList Indexer + object IList.this[int index] + { + get + { + return EnsureList()[index]; + } + + set + { + EnsureList(); + JsonData data = ToJsonData(value); + + this[index] = data; + } + } + #endregion + + + #region Public Indexers + public JsonData this[string prop_name] + { + get + { + EnsureDictionary(); + return inst_object[prop_name]; + } + + set + { + EnsureDictionary(); + + KeyValuePair<string, JsonData> entry = + new KeyValuePair<string, JsonData>(prop_name, value); + + if (inst_object.ContainsKey(prop_name)) + { + for (int i = 0; i < object_list.Count; i++) + { + if (object_list[i].Key == prop_name) + { + object_list[i] = entry; + break; + } + } + } + else + object_list.Add(entry); + + inst_object[prop_name] = value; + + json = null; + } + } + + public JsonData this[int index] + { + get + { + EnsureCollection(); + + if (type == JsonType.Array) + return inst_array[index]; + + return object_list[index].Value; + } + + set + { + EnsureCollection(); + + if (type == JsonType.Array) + inst_array[index] = value; + else + { + KeyValuePair<string, JsonData> entry = object_list[index]; + KeyValuePair<string, JsonData> new_entry = + new KeyValuePair<string, JsonData>(entry.Key, value); + + object_list[index] = new_entry; + inst_object[entry.Key] = value; + } + + json = null; + } + } + #endregion + + + #region Constructors + public JsonData() + { + } + + public JsonData(bool boolean) + { + type = JsonType.Boolean; + inst_boolean = boolean; + } + + public JsonData(double number) + { + type = JsonType.Double; + inst_double = number; + } + + public JsonData(int number) + { + type = JsonType.Int; + inst_int = number; + } + + public JsonData(long number) + { + type = JsonType.Long; + inst_long = number; + } + + public JsonData(object obj) + { + if (obj is bool) + { + type = JsonType.Boolean; + inst_boolean = (bool)obj; + return; + } + + if (obj is double) + { + type = JsonType.Double; + inst_double = (double)obj; + return; + } + + if (obj is int) + { + type = JsonType.Int; + inst_int = (int)obj; + return; + } + + if (obj is long) + { + type = JsonType.Long; + inst_long = (long)obj; + return; + } + + if (obj is string) + { + type = JsonType.String; + inst_string = (string)obj; + return; + } + + throw new ArgumentException( + "Unable to wrap the given object with JsonData"); + } + + public JsonData(string str) + { + type = JsonType.String; + inst_string = str; + } + #endregion + + + #region Implicit Conversions + public static implicit operator JsonData(bool data) + { + return new JsonData(data); + } + + public static implicit operator JsonData(double data) + { + return new JsonData(data); + } + + public static implicit operator JsonData(int data) + { + return new JsonData(data); + } + + public static implicit operator JsonData(long data) + { + return new JsonData(data); + } + + public static implicit operator JsonData(string data) + { + return new JsonData(data); + } + #endregion + + + #region Explicit Conversions + public static explicit operator bool(JsonData data) + { + if (data.type != JsonType.Boolean) + throw new InvalidCastException( + "Instance of JsonData doesn't hold a double"); + + return data.inst_boolean; + } + + public static explicit operator double(JsonData data) + { + if (data.type != JsonType.Double) + throw new InvalidCastException( + "Instance of JsonData doesn't hold a double"); + + return data.inst_double; + } + + public static explicit operator int(JsonData data) + { + if (data.type != JsonType.Int && data.type != JsonType.Long) + { + throw new InvalidCastException( + "Instance of JsonData doesn't hold an int"); + } + + // cast may truncate data... but that's up to the user to consider + return data.type == JsonType.Int ? data.inst_int : (int)data.inst_long; + } + + public static explicit operator long(JsonData data) + { + if (data.type != JsonType.Long && data.type != JsonType.Int) + { + throw new InvalidCastException( + "Instance of JsonData doesn't hold a long"); + } + + return data.type == JsonType.Long ? data.inst_long : data.inst_int; + } + + public static explicit operator string(JsonData data) + { + if (data.type != JsonType.String) + throw new InvalidCastException( + "Instance of JsonData doesn't hold a string"); + + return data.inst_string; + } + #endregion + + + #region ICollection Methods + void ICollection.CopyTo(Array array, int index) + { + EnsureCollection().CopyTo(array, index); + } + #endregion + + + #region IDictionary Methods + void IDictionary.Add(object key, object value) + { + JsonData data = ToJsonData(value); + + EnsureDictionary().Add(key, data); + + KeyValuePair<string, JsonData> entry = + new KeyValuePair<string, JsonData>((string)key, data); + object_list.Add(entry); + + json = null; + } + + void IDictionary.Clear() + { + EnsureDictionary().Clear(); + object_list.Clear(); + json = null; + } + + bool IDictionary.Contains(object key) + { + return EnsureDictionary().Contains(key); + } + + IDictionaryEnumerator IDictionary.GetEnumerator() + { + return ((IOrderedDictionary)this).GetEnumerator(); + } + + void IDictionary.Remove(object key) + { + EnsureDictionary().Remove(key); + + for (int i = 0; i < object_list.Count; i++) + { + if (object_list[i].Key == (string)key) + { + object_list.RemoveAt(i); + break; + } + } + + json = null; + } + #endregion + + + #region IEnumerable Methods + IEnumerator IEnumerable.GetEnumerator() + { + return EnsureCollection().GetEnumerator(); + } + #endregion + + + #region IJsonWrapper Methods + bool IJsonWrapper.GetBoolean() + { + if (type != JsonType.Boolean) + throw new InvalidOperationException( + "JsonData instance doesn't hold a boolean"); + + return inst_boolean; + } + + double IJsonWrapper.GetDouble() + { + if (type != JsonType.Double) + throw new InvalidOperationException( + "JsonData instance doesn't hold a double"); + + return inst_double; + } + + int IJsonWrapper.GetInt() + { + if (type != JsonType.Int) + throw new InvalidOperationException( + "JsonData instance doesn't hold an int"); + + return inst_int; + } + + long IJsonWrapper.GetLong() + { + if (type != JsonType.Long) + throw new InvalidOperationException( + "JsonData instance doesn't hold a long"); + + return inst_long; + } + + string IJsonWrapper.GetString() + { + if (type != JsonType.String) + throw new InvalidOperationException( + "JsonData instance doesn't hold a string"); + + return inst_string; + } + + void IJsonWrapper.SetBoolean(bool val) + { + type = JsonType.Boolean; + inst_boolean = val; + json = null; + } + + void IJsonWrapper.SetDouble(double val) + { + type = JsonType.Double; + inst_double = val; + json = null; + } + + void IJsonWrapper.SetInt(int val) + { + type = JsonType.Int; + inst_int = val; + json = null; + } + + void IJsonWrapper.SetLong(long val) + { + type = JsonType.Long; + inst_long = val; + json = null; + } + + void IJsonWrapper.SetString(string val) + { + type = JsonType.String; + inst_string = val; + json = null; + } + + string IJsonWrapper.ToJson() + { + return ToJson(); + } + + void IJsonWrapper.ToJson(JsonWriter writer) + { + ToJson(writer); + } + #endregion + + + #region IList Methods + int IList.Add(object value) + { + return Add(value); + } + + void IList.Clear() + { + EnsureList().Clear(); + json = null; + } + + bool IList.Contains(object value) + { + return EnsureList().Contains(value); + } + + int IList.IndexOf(object value) + { + return EnsureList().IndexOf(value); + } + + void IList.Insert(int index, object value) + { + EnsureList().Insert(index, value); + json = null; + } + + void IList.Remove(object value) + { + EnsureList().Remove(value); + json = null; + } + + void IList.RemoveAt(int index) + { + EnsureList().RemoveAt(index); + json = null; + } + #endregion + + + #region IOrderedDictionary Methods + IDictionaryEnumerator IOrderedDictionary.GetEnumerator() + { + EnsureDictionary(); + + return new OrderedDictionaryEnumerator( + object_list.GetEnumerator()); + } + + void IOrderedDictionary.Insert(int idx, object key, object value) + { + string property = (string)key; + JsonData data = ToJsonData(value); + + this[property] = data; + + KeyValuePair<string, JsonData> entry = + new KeyValuePair<string, JsonData>(property, data); + + object_list.Insert(idx, entry); + } + + void IOrderedDictionary.RemoveAt(int idx) + { + EnsureDictionary(); + + inst_object.Remove(object_list[idx].Key); + object_list.RemoveAt(idx); + } + #endregion + + + #region Private Methods + private ICollection EnsureCollection() + { + if (type == JsonType.Array) + return (ICollection)inst_array; + + if (type == JsonType.Object) + return (ICollection)inst_object; + + throw new InvalidOperationException( + "The JsonData instance has to be initialized first"); + } + + private IDictionary EnsureDictionary() + { + if (type == JsonType.Object) + return (IDictionary)inst_object; + + if (type != JsonType.None) + throw new InvalidOperationException( + "Instance of JsonData is not a dictionary"); + + type = JsonType.Object; + inst_object = new Dictionary<string, JsonData>(); + object_list = new List<KeyValuePair<string, JsonData>>(); + + return (IDictionary)inst_object; + } + + private IList EnsureList() + { + if (type == JsonType.Array) + return (IList)inst_array; + + if (type != JsonType.None) + throw new InvalidOperationException( + "Instance of JsonData is not a list"); + + type = JsonType.Array; + inst_array = new List<JsonData>(); + + return (IList)inst_array; + } + + private JsonData ToJsonData(object obj) + { + if (obj == null) + return null; + + if (obj is JsonData) + return (JsonData)obj; + + return new JsonData(obj); + } + + private static void WriteJson(IJsonWrapper obj, JsonWriter writer) + { + if (obj == null) + { + writer.Write(null); + return; + } + + if (obj.IsString) + { + writer.Write(obj.GetString()); + return; + } + + if (obj.IsBoolean) + { + writer.Write(obj.GetBoolean()); + return; + } + + if (obj.IsDouble) + { + writer.Write(obj.GetDouble()); + return; + } + + if (obj.IsInt) + { + writer.Write(obj.GetInt()); + return; + } + + if (obj.IsLong) + { + writer.Write(obj.GetLong()); + return; + } + + if (obj.IsArray) + { + writer.WriteArrayStart(); + foreach (object elem in (IList)obj) + WriteJson((JsonData)elem, writer); + writer.WriteArrayEnd(); + + return; + } + + if (obj.IsObject) + { + writer.WriteObjectStart(); + + foreach (DictionaryEntry entry in (IDictionary)obj) + { + writer.WritePropertyName((string)entry.Key); + WriteJson((JsonData)entry.Value, writer); + } + writer.WriteObjectEnd(); + + return; + } + } + #endregion + + + public int Add(object value) + { + JsonData data = ToJsonData(value); + + json = null; + + return EnsureList().Add(data); + } + + public bool Remove(object obj) + { + json = null; + if (IsObject) + { + JsonData value = null; + if (inst_object.TryGetValue((string)obj, out value)) + return inst_object.Remove((string)obj) && object_list.Remove(new KeyValuePair<string, JsonData>((string)obj, value)); + else + throw new KeyNotFoundException("The specified key was not found in the JsonData object."); + } + if (IsArray) + { + return inst_array.Remove(ToJsonData(obj)); + } + throw new InvalidOperationException( + "Instance of JsonData is not an object or a list."); + } + + public void Clear() + { + if (IsObject) + { + ((IDictionary)this).Clear(); + return; + } + + if (IsArray) + { + ((IList)this).Clear(); + return; + } + } + + public bool Equals(JsonData x) + { + if (x == null) + return false; + + if (x.type != type) + { + // further check to see if this is a long to int comparison + if (x.type != JsonType.Int && x.type != JsonType.Long + || type != JsonType.Int && type != JsonType.Long) + { + return false; + } + } + + switch (type) + { + case JsonType.None: + return true; + + case JsonType.Object: + return inst_object.Equals(x.inst_object); + + case JsonType.Array: + return inst_array.Equals(x.inst_array); + + case JsonType.String: + return inst_string.Equals(x.inst_string); + + case JsonType.Int: + { + if (x.IsLong) + { + if (x.inst_long < int.MinValue || x.inst_long > int.MaxValue) + return false; + return inst_int.Equals((int)x.inst_long); + } + return inst_int.Equals(x.inst_int); + } + + case JsonType.Long: + { + if (x.IsInt) + { + if (inst_long < int.MinValue || inst_long > int.MaxValue) + return false; + return x.inst_int.Equals((int)inst_long); + } + return inst_long.Equals(x.inst_long); + } + + case JsonType.Double: + return inst_double.Equals(x.inst_double); + + case JsonType.Boolean: + return inst_boolean.Equals(x.inst_boolean); + } + + return false; + } + + public JsonType GetJsonType() + { + return type; + } + + public void SetJsonType(JsonType type) + { + if (this.type == type) + return; + + switch (type) + { + case JsonType.None: + break; + + case JsonType.Object: + inst_object = new Dictionary<string, JsonData>(); + object_list = new List<KeyValuePair<string, JsonData>>(); + break; + + case JsonType.Array: + inst_array = new List<JsonData>(); + break; + + case JsonType.String: + inst_string = default; + break; + + case JsonType.Int: + inst_int = default; + break; + + case JsonType.Long: + inst_long = default; + break; + + case JsonType.Double: + inst_double = default; + break; + + case JsonType.Boolean: + inst_boolean = default; + break; + } + + this.type = type; + } + + public string ToJson() + { + if (json != null) + return json; + + StringWriter sw = new StringWriter(); + JsonWriter writer = new JsonWriter(sw); + writer.Validate = false; + + WriteJson(this, writer); + json = sw.ToString(); + + return json; + } + + public void ToJson(JsonWriter writer) + { + bool old_validate = writer.Validate; + + writer.Validate = false; + + WriteJson(this, writer); + + writer.Validate = old_validate; + } + + public override string ToString() + { + switch (type) + { + case JsonType.Array: + return "JsonData array"; + + case JsonType.Boolean: + return inst_boolean.ToString(); + + case JsonType.Double: + return inst_double.ToString(); + + case JsonType.Int: + return inst_int.ToString(); + + case JsonType.Long: + return inst_long.ToString(); + + case JsonType.Object: + return "JsonData object"; + + case JsonType.String: + return inst_string; + } + + return "Uninitialized JsonData"; + } + } + + + internal class OrderedDictionaryEnumerator : IDictionaryEnumerator + { + IEnumerator<KeyValuePair<string, JsonData>> list_enumerator; + + + public object Current + { + get { return Entry; } + } + + public DictionaryEntry Entry + { + get + { + KeyValuePair<string, JsonData> curr = list_enumerator.Current; + return new DictionaryEntry(curr.Key, curr.Value); + } + } + + public object Key + { + get { return list_enumerator.Current.Key; } + } + + public object Value + { + get { return list_enumerator.Current.Value; } + } + + + public OrderedDictionaryEnumerator( + IEnumerator<KeyValuePair<string, JsonData>> enumerator) + { + list_enumerator = enumerator; + } + + + public bool MoveNext() + { + return list_enumerator.MoveNext(); + } + + public void Reset() + { + list_enumerator.Reset(); + } + } +} diff --git a/O&Z_Obfuscator/LitJson/JsonException.cs b/O&Z_Obfuscator/LitJson/JsonException.cs new file mode 100644 index 0000000..c8d728a --- /dev/null +++ b/O&Z_Obfuscator/LitJson/JsonException.cs @@ -0,0 +1,65 @@ +#region Header +/** + * JsonException.cs + * Base class throwed by LitJSON when a parsing error occurs. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; + + +namespace O_Z_IL2CPP_Security.LitJson +{ + public class JsonException : +#if NETSTANDARD1_5 + Exception +#else + ApplicationException +#endif + { + public JsonException() : base() + { + } + + internal JsonException(ParserToken token) : + base(string.Format( + "Invalid token '{0}' in input string", token)) + { + } + + internal JsonException(ParserToken token, + Exception inner_exception) : + base(string.Format( + "Invalid token '{0}' in input string", token), + inner_exception) + { + } + + internal JsonException(int c) : + base(string.Format( + "Invalid character '{0}' in input string", (char)c)) + { + } + + internal JsonException(int c, Exception inner_exception) : + base(string.Format( + "Invalid character '{0}' in input string", (char)c), + inner_exception) + { + } + + + public JsonException(string message) : base(message) + { + } + + public JsonException(string message, Exception inner_exception) : + base(message, inner_exception) + { + } + } +} diff --git a/O&Z_Obfuscator/LitJson/JsonMapper.cs b/O&Z_Obfuscator/LitJson/JsonMapper.cs new file mode 100644 index 0000000..f9622e6 --- /dev/null +++ b/O&Z_Obfuscator/LitJson/JsonMapper.cs @@ -0,0 +1,1098 @@ +#region Header +/** + * JsonMapper.cs + * JSON to .Net object and object to JSON conversions. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Reflection; + + +namespace O_Z_IL2CPP_Security.LitJson +{ + internal struct PropertyMetadata + { + public MemberInfo Info; + public bool IsField; + public Type Type; + } + + + internal struct ArrayMetadata + { + private Type element_type; + private bool is_array; + private bool is_list; + + + public Type ElementType + { + get + { + if (element_type == null) + return typeof(JsonData); + + return element_type; + } + + set { element_type = value; } + } + + public bool IsArray + { + get { return is_array; } + set { is_array = value; } + } + + public bool IsList + { + get { return is_list; } + set { is_list = value; } + } + } + + + internal struct ObjectMetadata + { + private Type element_type; + private bool is_dictionary; + + private IDictionary<string, PropertyMetadata> properties; + + + public Type ElementType + { + get + { + if (element_type == null) + return typeof(JsonData); + + return element_type; + } + + set { element_type = value; } + } + + public bool IsDictionary + { + get { return is_dictionary; } + set { is_dictionary = value; } + } + + public IDictionary<string, PropertyMetadata> Properties + { + get { return properties; } + set { properties = value; } + } + } + + + internal delegate void ExporterFunc(object obj, JsonWriter writer); + public delegate void ExporterFunc<T>(T obj, JsonWriter writer); + + internal delegate object ImporterFunc(object input); + public delegate TValue ImporterFunc<TJson, TValue>(TJson input); + + public delegate IJsonWrapper WrapperFactory(); + + + public class JsonMapper + { + #region Fields + private static readonly int max_nesting_depth; + + private static readonly IFormatProvider datetime_format; + + private static readonly IDictionary<Type, ExporterFunc> base_exporters_table; + private static readonly IDictionary<Type, ExporterFunc> custom_exporters_table; + + private static readonly IDictionary<Type, + IDictionary<Type, ImporterFunc>> base_importers_table; + private static readonly IDictionary<Type, + IDictionary<Type, ImporterFunc>> custom_importers_table; + + private static readonly IDictionary<Type, ArrayMetadata> array_metadata; + private static readonly object array_metadata_lock = new object(); + + private static readonly IDictionary<Type, + IDictionary<Type, MethodInfo>> conv_ops; + private static readonly object conv_ops_lock = new object(); + + private static readonly IDictionary<Type, ObjectMetadata> object_metadata; + private static readonly object object_metadata_lock = new object(); + + private static readonly IDictionary<Type, + IList<PropertyMetadata>> type_properties; + private static readonly object type_properties_lock = new object(); + + private static readonly JsonWriter static_writer; + private static readonly object static_writer_lock = new object(); + #endregion + + + #region Constructors + static JsonMapper() + { + max_nesting_depth = 100; + + array_metadata = new Dictionary<Type, ArrayMetadata>(); + conv_ops = new Dictionary<Type, IDictionary<Type, MethodInfo>>(); + object_metadata = new Dictionary<Type, ObjectMetadata>(); + type_properties = new Dictionary<Type, + IList<PropertyMetadata>>(); + + static_writer = new JsonWriter(); + + datetime_format = DateTimeFormatInfo.InvariantInfo; + + base_exporters_table = new Dictionary<Type, ExporterFunc>(); + custom_exporters_table = new Dictionary<Type, ExporterFunc>(); + + base_importers_table = new Dictionary<Type, + IDictionary<Type, ImporterFunc>>(); + custom_importers_table = new Dictionary<Type, + IDictionary<Type, ImporterFunc>>(); + + RegisterBaseExporters(); + RegisterBaseImporters(); + } + #endregion + + + #region Private Methods + private static void AddArrayMetadata(Type type) + { + if (array_metadata.ContainsKey(type)) + return; + + ArrayMetadata data = new ArrayMetadata(); + + data.IsArray = type.IsArray; + + if (type.GetInterface("System.Collections.IList") != null) + data.IsList = true; + + foreach (PropertyInfo p_info in type.GetProperties()) + { + if (p_info.Name != "Item") + continue; + + ParameterInfo[] parameters = p_info.GetIndexParameters(); + + if (parameters.Length != 1) + continue; + + if (parameters[0].ParameterType == typeof(int)) + data.ElementType = p_info.PropertyType; + } + + lock (array_metadata_lock) + { + try + { + array_metadata.Add(type, data); + } + catch (ArgumentException) + { + return; + } + } + } + + private static void AddObjectMetadata(Type type) + { + if (object_metadata.ContainsKey(type)) + return; + + ObjectMetadata data = new ObjectMetadata(); + + if (type.GetInterface("System.Collections.IDictionary") != null) + data.IsDictionary = true; + + data.Properties = new Dictionary<string, PropertyMetadata>(); + + foreach (PropertyInfo p_info in type.GetProperties()) + { + if (p_info.Name == "Item") + { + ParameterInfo[] parameters = p_info.GetIndexParameters(); + + if (parameters.Length != 1) + continue; + + if (parameters[0].ParameterType == typeof(string)) + data.ElementType = p_info.PropertyType; + + continue; + } + + PropertyMetadata p_data = new PropertyMetadata(); + p_data.Info = p_info; + p_data.Type = p_info.PropertyType; + + data.Properties.Add(p_info.Name, p_data); + } + + foreach (FieldInfo f_info in type.GetFields()) + { + PropertyMetadata p_data = new PropertyMetadata(); + p_data.Info = f_info; + p_data.IsField = true; + p_data.Type = f_info.FieldType; + + data.Properties.Add(f_info.Name, p_data); + } + + lock (object_metadata_lock) + { + try + { + object_metadata.Add(type, data); + } + catch (ArgumentException) + { + return; + } + } + } + + private static void AddTypeProperties(Type type) + { + if (type_properties.ContainsKey(type)) + return; + + IList<PropertyMetadata> props = new List<PropertyMetadata>(); + + foreach (PropertyInfo p_info in type.GetProperties()) + { + if (p_info.Name == "Item") + continue; + + PropertyMetadata p_data = new PropertyMetadata(); + p_data.Info = p_info; + p_data.IsField = false; + props.Add(p_data); + } + + foreach (FieldInfo f_info in type.GetFields()) + { + PropertyMetadata p_data = new PropertyMetadata(); + p_data.Info = f_info; + p_data.IsField = true; + + props.Add(p_data); + } + + lock (type_properties_lock) + { + try + { + type_properties.Add(type, props); + } + catch (ArgumentException) + { + return; + } + } + } + + private static MethodInfo GetConvOp(Type t1, Type t2) + { + lock (conv_ops_lock) + { + if (!conv_ops.ContainsKey(t1)) + conv_ops.Add(t1, new Dictionary<Type, MethodInfo>()); + } + + if (conv_ops[t1].ContainsKey(t2)) + return conv_ops[t1][t2]; + + MethodInfo op = t1.GetMethod( + "op_Implicit", new Type[] { t2 }); + + lock (conv_ops_lock) + { + try + { + conv_ops[t1].Add(t2, op); + } + catch (ArgumentException) + { + return conv_ops[t1][t2]; + } + } + + return op; + } + + private static object ReadValue(Type inst_type, JsonReader reader) + { + reader.Read(); + + if (reader.Token == JsonToken.ArrayEnd) + return null; + + Type underlying_type = Nullable.GetUnderlyingType(inst_type); + Type value_type = underlying_type ?? inst_type; + + if (reader.Token == JsonToken.Null) + { +#if NETSTANDARD1_5 + if (inst_type.IsClass() || underlying_type != null) { + return null; + } +#else + if (inst_type.IsClass || underlying_type != null) + { + return null; + } +#endif + + throw new JsonException(string.Format( + "Can't assign null to an instance of type {0}", + inst_type)); + } + + if (reader.Token == JsonToken.Double || + reader.Token == JsonToken.Int || + reader.Token == JsonToken.Long || + reader.Token == JsonToken.String || + reader.Token == JsonToken.Boolean) + { + + Type json_type = reader.Value.GetType(); + + if (value_type.IsAssignableFrom(json_type)) + return reader.Value; + + // If there's a custom importer that fits, use it + if (custom_importers_table.ContainsKey(json_type) && + custom_importers_table[json_type].ContainsKey( + value_type)) + { + + ImporterFunc importer = + custom_importers_table[json_type][value_type]; + + return importer(reader.Value); + } + + // Maybe there's a base importer that works + if (base_importers_table.ContainsKey(json_type) && + base_importers_table[json_type].ContainsKey( + value_type)) + { + + ImporterFunc importer = + base_importers_table[json_type][value_type]; + + return importer(reader.Value); + } + + // Maybe it's an enum +#if NETSTANDARD1_5 + if (value_type.IsEnum()) + return Enum.ToObject (value_type, reader.Value); +#else + if (value_type.IsEnum) + return Enum.ToObject(value_type, reader.Value); +#endif + // Try using an implicit conversion operator + MethodInfo conv_op = GetConvOp(value_type, json_type); + + if (conv_op != null) + return conv_op.Invoke(null, + new object[] { reader.Value }); + + // No luck + throw new JsonException(string.Format( + "Can't assign value '{0}' (type {1}) to type {2}", + reader.Value, json_type, inst_type)); + } + + object instance = null; + + if (reader.Token == JsonToken.ArrayStart) + { + + AddArrayMetadata(inst_type); + ArrayMetadata t_data = array_metadata[inst_type]; + + if (!t_data.IsArray && !t_data.IsList) + throw new JsonException(string.Format( + "Type {0} can't act as an array", + inst_type)); + + IList list; + Type elem_type; + + if (!t_data.IsArray) + { + list = (IList)Activator.CreateInstance(inst_type); + elem_type = t_data.ElementType; + } + else + { + list = new ArrayList(); + elem_type = inst_type.GetElementType(); + } + + list.Clear(); + + while (true) + { + object item = ReadValue(elem_type, reader); + if (item == null && reader.Token == JsonToken.ArrayEnd) + break; + + list.Add(item); + } + + if (t_data.IsArray) + { + int n = list.Count; + instance = Array.CreateInstance(elem_type, n); + + for (int i = 0; i < n; i++) + ((Array)instance).SetValue(list[i], i); + } + else + instance = list; + + } + else if (reader.Token == JsonToken.ObjectStart) + { + AddObjectMetadata(value_type); + ObjectMetadata t_data = object_metadata[value_type]; + + instance = Activator.CreateInstance(value_type); + + while (true) + { + reader.Read(); + + if (reader.Token == JsonToken.ObjectEnd) + break; + + string property = (string)reader.Value; + + if (t_data.Properties.ContainsKey(property)) + { + PropertyMetadata prop_data = + t_data.Properties[property]; + + if (prop_data.IsField) + { + ((FieldInfo)prop_data.Info).SetValue( + instance, ReadValue(prop_data.Type, reader)); + } + else + { + PropertyInfo p_info = + (PropertyInfo)prop_data.Info; + + if (p_info.CanWrite) + p_info.SetValue( + instance, + ReadValue(prop_data.Type, reader), + null); + else + ReadValue(prop_data.Type, reader); + } + + } + else + { + if (!t_data.IsDictionary) + { + + if (!reader.SkipNonMembers) + { + throw new JsonException(string.Format( + "The type {0} doesn't have the " + + "property '{1}'", + inst_type, property)); + } + else + { + ReadSkip(reader); + continue; + } + } + + ((IDictionary)instance).Add( + property, ReadValue( + t_data.ElementType, reader)); + } + + } + + } + + return instance; + } + + private static IJsonWrapper ReadValue(WrapperFactory factory, + JsonReader reader) + { + reader.Read(); + + if (reader.Token == JsonToken.ArrayEnd || + reader.Token == JsonToken.Null) + return null; + + IJsonWrapper instance = factory(); + + if (reader.Token == JsonToken.String) + { + instance.SetString((string)reader.Value); + return instance; + } + + if (reader.Token == JsonToken.Double) + { + instance.SetDouble((double)reader.Value); + return instance; + } + + if (reader.Token == JsonToken.Int) + { + instance.SetInt((int)reader.Value); + return instance; + } + + if (reader.Token == JsonToken.Long) + { + instance.SetLong((long)reader.Value); + return instance; + } + + if (reader.Token == JsonToken.Boolean) + { + instance.SetBoolean((bool)reader.Value); + return instance; + } + + if (reader.Token == JsonToken.ArrayStart) + { + instance.SetJsonType(JsonType.Array); + + while (true) + { + IJsonWrapper item = ReadValue(factory, reader); + if (item == null && reader.Token == JsonToken.ArrayEnd) + break; + + instance.Add(item); + } + } + else if (reader.Token == JsonToken.ObjectStart) + { + instance.SetJsonType(JsonType.Object); + + while (true) + { + reader.Read(); + + if (reader.Token == JsonToken.ObjectEnd) + break; + + string property = (string)reader.Value; + + ((IDictionary)instance)[property] = ReadValue( + factory, reader); + } + + } + + return instance; + } + + private static void ReadSkip(JsonReader reader) + { + ToWrapper( + delegate { return new JsonMockWrapper(); }, reader); + } + + private static void RegisterBaseExporters() + { + base_exporters_table[typeof(byte)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToInt32((byte)obj)); + }; + + base_exporters_table[typeof(char)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToString((char)obj)); + }; + + base_exporters_table[typeof(DateTime)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToString((DateTime)obj, + datetime_format)); + }; + + base_exporters_table[typeof(decimal)] = + delegate (object obj, JsonWriter writer) + { + writer.Write((decimal)obj); + }; + + base_exporters_table[typeof(sbyte)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToInt32((sbyte)obj)); + }; + + base_exporters_table[typeof(short)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToInt32((short)obj)); + }; + + base_exporters_table[typeof(ushort)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToInt32((ushort)obj)); + }; + + base_exporters_table[typeof(uint)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToUInt64((uint)obj)); + }; + + base_exporters_table[typeof(ulong)] = + delegate (object obj, JsonWriter writer) + { + writer.Write((ulong)obj); + }; + + base_exporters_table[typeof(DateTimeOffset)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(((DateTimeOffset)obj).ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz", datetime_format)); + }; + } + + private static void RegisterBaseImporters() + { + ImporterFunc importer; + + importer = delegate (object input) + { + return Convert.ToByte((int)input); + }; + RegisterImporter(base_importers_table, typeof(int), + typeof(byte), importer); + + importer = delegate (object input) + { + return Convert.ToUInt64((int)input); + }; + RegisterImporter(base_importers_table, typeof(int), + typeof(ulong), importer); + + importer = delegate (object input) + { + return Convert.ToInt64((int)input); + }; + RegisterImporter(base_importers_table, typeof(int), + typeof(long), importer); + + importer = delegate (object input) + { + return Convert.ToSByte((int)input); + }; + RegisterImporter(base_importers_table, typeof(int), + typeof(sbyte), importer); + + importer = delegate (object input) + { + return Convert.ToInt16((int)input); + }; + RegisterImporter(base_importers_table, typeof(int), + typeof(short), importer); + + importer = delegate (object input) + { + return Convert.ToUInt16((int)input); + }; + RegisterImporter(base_importers_table, typeof(int), + typeof(ushort), importer); + + importer = delegate (object input) + { + return Convert.ToUInt32((int)input); + }; + RegisterImporter(base_importers_table, typeof(int), + typeof(uint), importer); + + importer = delegate (object input) + { + return Convert.ToSingle((int)input); + }; + RegisterImporter(base_importers_table, typeof(int), + typeof(float), importer); + + importer = delegate (object input) + { + return Convert.ToDouble((int)input); + }; + RegisterImporter(base_importers_table, typeof(int), + typeof(double), importer); + + importer = delegate (object input) + { + return Convert.ToDecimal((double)input); + }; + RegisterImporter(base_importers_table, typeof(double), + typeof(decimal), importer); + + importer = delegate (object input) + { + return Convert.ToSingle((double)input); + }; + RegisterImporter(base_importers_table, typeof(double), + typeof(float), importer); + + importer = delegate (object input) + { + return Convert.ToUInt32((long)input); + }; + RegisterImporter(base_importers_table, typeof(long), + typeof(uint), importer); + + importer = delegate (object input) + { + return Convert.ToChar((string)input); + }; + RegisterImporter(base_importers_table, typeof(string), + typeof(char), importer); + + importer = delegate (object input) + { + return Convert.ToDateTime((string)input, datetime_format); + }; + RegisterImporter(base_importers_table, typeof(string), + typeof(DateTime), importer); + + importer = delegate (object input) + { + return DateTimeOffset.Parse((string)input, datetime_format); + }; + RegisterImporter(base_importers_table, typeof(string), + typeof(DateTimeOffset), importer); + } + + private static void RegisterImporter( + IDictionary<Type, IDictionary<Type, ImporterFunc>> table, + Type json_type, Type value_type, ImporterFunc importer) + { + if (!table.ContainsKey(json_type)) + table.Add(json_type, new Dictionary<Type, ImporterFunc>()); + + table[json_type][value_type] = importer; + } + + private static void WriteValue(object obj, JsonWriter writer, + bool writer_is_private, + int depth) + { + if (depth > max_nesting_depth) + throw new JsonException( + string.Format("Max allowed object depth reached while " + + "trying to export from type {0}", + obj.GetType())); + + if (obj == null) + { + writer.Write(null); + return; + } + + if (obj is IJsonWrapper) + { + if (writer_is_private) + writer.TextWriter.Write(((IJsonWrapper)obj).ToJson()); + else + ((IJsonWrapper)obj).ToJson(writer); + + return; + } + + if (obj is string) + { + writer.Write((string)obj); + return; + } + + if (obj is double) + { + writer.Write((double)obj); + return; + } + + if (obj is float) + { + writer.Write((float)obj); + return; + } + + if (obj is int) + { + writer.Write((int)obj); + return; + } + + if (obj is bool) + { + writer.Write((bool)obj); + return; + } + + if (obj is long) + { + writer.Write((long)obj); + return; + } + + if (obj is Array) + { + writer.WriteArrayStart(); + + foreach (object elem in (Array)obj) + WriteValue(elem, writer, writer_is_private, depth + 1); + + writer.WriteArrayEnd(); + + return; + } + + if (obj is IList) + { + writer.WriteArrayStart(); + foreach (object elem in (IList)obj) + WriteValue(elem, writer, writer_is_private, depth + 1); + writer.WriteArrayEnd(); + + return; + } + + if (obj is IDictionary dictionary) + { + writer.WriteObjectStart(); + foreach (DictionaryEntry entry in dictionary) + { + var propertyName = entry.Key is string key ? + key + : Convert.ToString(entry.Key, CultureInfo.InvariantCulture); + writer.WritePropertyName(propertyName); + WriteValue(entry.Value, writer, writer_is_private, + depth + 1); + } + writer.WriteObjectEnd(); + + return; + } + + Type obj_type = obj.GetType(); + + // See if there's a custom exporter for the object + if (custom_exporters_table.ContainsKey(obj_type)) + { + ExporterFunc exporter = custom_exporters_table[obj_type]; + exporter(obj, writer); + + return; + } + + // If not, maybe there's a base exporter + if (base_exporters_table.ContainsKey(obj_type)) + { + ExporterFunc exporter = base_exporters_table[obj_type]; + exporter(obj, writer); + + return; + } + + // Last option, let's see if it's an enum + if (obj is Enum) + { + Type e_type = Enum.GetUnderlyingType(obj_type); + + if (e_type == typeof(long)) + writer.Write((long)obj); + else if (e_type == typeof(uint)) + writer.Write((uint)obj); + else if (e_type == typeof(ulong)) + writer.Write((ulong)obj); + else if (e_type == typeof(ushort)) + writer.Write((ushort)obj); + else if (e_type == typeof(short)) + writer.Write((short)obj); + else if (e_type == typeof(byte)) + writer.Write((byte)obj); + else if (e_type == typeof(sbyte)) + writer.Write((sbyte)obj); + else + writer.Write((int)obj); + + return; + } + + // Okay, so it looks like the input should be exported as an + // object + AddTypeProperties(obj_type); + IList<PropertyMetadata> props = type_properties[obj_type]; + + writer.WriteObjectStart(); + foreach (PropertyMetadata p_data in props) + { + if (p_data.IsField) + { + writer.WritePropertyName(p_data.Info.Name); + WriteValue(((FieldInfo)p_data.Info).GetValue(obj), + writer, writer_is_private, depth + 1); + } + else + { + PropertyInfo p_info = (PropertyInfo)p_data.Info; + + if (p_info.CanRead) + { + writer.WritePropertyName(p_data.Info.Name); + WriteValue(p_info.GetValue(obj, null), + writer, writer_is_private, depth + 1); + } + } + } + writer.WriteObjectEnd(); + } + #endregion + + + public static string ToJson(object obj) + { + lock (static_writer_lock) + { + static_writer.Reset(); + + WriteValue(obj, static_writer, true, 0); + + return static_writer.ToString(); + } + } + + public static void ToJson(object obj, JsonWriter writer) + { + WriteValue(obj, writer, false, 0); + } + + public static JsonData ToObject(JsonReader reader) + { + return (JsonData)ToWrapper( + delegate { return new JsonData(); }, reader); + } + + public static JsonData ToObject(TextReader reader) + { + JsonReader json_reader = new JsonReader(reader); + + return (JsonData)ToWrapper( + delegate { return new JsonData(); }, json_reader); + } + + public static JsonData ToObject(string json) + { + return (JsonData)ToWrapper( + delegate { return new JsonData(); }, json); + } + + public static T ToObject<T>(JsonReader reader) + { + return (T)ReadValue(typeof(T), reader); + } + + public static T ToObject<T>(TextReader reader) + { + JsonReader json_reader = new JsonReader(reader); + + return (T)ReadValue(typeof(T), json_reader); + } + + public static T ToObject<T>(string json) + { + JsonReader reader = new JsonReader(json); + + return (T)ReadValue(typeof(T), reader); + } + + public static object ToObject(string json, Type ConvertType) + { + JsonReader reader = new JsonReader(json); + + return ReadValue(ConvertType, reader); + } + + public static IJsonWrapper ToWrapper(WrapperFactory factory, + JsonReader reader) + { + return ReadValue(factory, reader); + } + + public static IJsonWrapper ToWrapper(WrapperFactory factory, + string json) + { + JsonReader reader = new JsonReader(json); + + return ReadValue(factory, reader); + } + + public static void RegisterExporter<T>(ExporterFunc<T> exporter) + { + ExporterFunc exporter_wrapper = + delegate (object obj, JsonWriter writer) + { + exporter((T)obj, writer); + }; + + custom_exporters_table[typeof(T)] = exporter_wrapper; + } + + public static void RegisterImporter<TJson, TValue>( + ImporterFunc<TJson, TValue> importer) + { + ImporterFunc importer_wrapper = + delegate (object input) + { + return importer((TJson)input); + }; + + RegisterImporter(custom_importers_table, typeof(TJson), + typeof(TValue), importer_wrapper); + } + + public static void UnregisterExporters() + { + custom_exporters_table.Clear(); + } + + public static void UnregisterImporters() + { + custom_importers_table.Clear(); + } + } +} diff --git a/O&Z_Obfuscator/LitJson/JsonMockWrapper.cs b/O&Z_Obfuscator/LitJson/JsonMockWrapper.cs new file mode 100644 index 0000000..1be9fd6 --- /dev/null +++ b/O&Z_Obfuscator/LitJson/JsonMockWrapper.cs @@ -0,0 +1,109 @@ +#region Header +/** + * JsonMockWrapper.cs + * Mock object implementing IJsonWrapper, to facilitate actions like + * skipping data more efficiently. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections; +using System.Collections.Specialized; + + +namespace O_Z_IL2CPP_Security.LitJson +{ + public class JsonMockWrapper : IJsonWrapper + { + public bool IsArray { get { return false; } } + public bool IsBoolean { get { return false; } } + public bool IsDouble { get { return false; } } + public bool IsInt { get { return false; } } + public bool IsLong { get { return false; } } + public bool IsObject { get { return false; } } + public bool IsString { get { return false; } } + + public bool GetBoolean() { return false; } + public double GetDouble() { return 0.0; } + public int GetInt() { return 0; } + public JsonType GetJsonType() { return JsonType.None; } + public long GetLong() { return 0L; } + public string GetString() { return ""; } + + public void SetBoolean(bool val) { } + public void SetDouble(double val) { } + public void SetInt(int val) { } + public void SetJsonType(JsonType type) { } + public void SetLong(long val) { } + public void SetString(string val) { } + + public string ToJson() { return ""; } + public void ToJson(JsonWriter writer) { } + + + bool IList.IsFixedSize { get { return true; } } + bool IList.IsReadOnly { get { return true; } } + + object IList.this[int index] + { + get { return null; } + set { } + } + + int IList.Add(object value) { return 0; } + void IList.Clear() { } + bool IList.Contains(object value) { return false; } + int IList.IndexOf(object value) { return -1; } + void IList.Insert(int i, object v) { } + void IList.Remove(object value) { } + void IList.RemoveAt(int index) { } + + + int ICollection.Count { get { return 0; } } + bool ICollection.IsSynchronized { get { return false; } } + object ICollection.SyncRoot { get { return null; } } + + void ICollection.CopyTo(Array array, int index) { } + + + IEnumerator IEnumerable.GetEnumerator() { return null; } + + + bool IDictionary.IsFixedSize { get { return true; } } + bool IDictionary.IsReadOnly { get { return true; } } + + ICollection IDictionary.Keys { get { return null; } } + ICollection IDictionary.Values { get { return null; } } + + object IDictionary.this[object key] + { + get { return null; } + set { } + } + + void IDictionary.Add(object k, object v) { } + void IDictionary.Clear() { } + bool IDictionary.Contains(object key) { return false; } + void IDictionary.Remove(object key) { } + + IDictionaryEnumerator IDictionary.GetEnumerator() { return null; } + + + object IOrderedDictionary.this[int idx] + { + get { return null; } + set { } + } + + IDictionaryEnumerator IOrderedDictionary.GetEnumerator() + { + return null; + } + void IOrderedDictionary.Insert(int i, object k, object v) { } + void IOrderedDictionary.RemoveAt(int i) { } + } +} diff --git a/O&Z_Obfuscator/LitJson/JsonReader.cs b/O&Z_Obfuscator/LitJson/JsonReader.cs new file mode 100644 index 0000000..7f210bf --- /dev/null +++ b/O&Z_Obfuscator/LitJson/JsonReader.cs @@ -0,0 +1,523 @@ +#region Header +/** + * JsonReader.cs + * Stream-like access to JSON text. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text; + + +namespace O_Z_IL2CPP_Security.LitJson +{ + public enum JsonToken + { + None, + + ObjectStart, + PropertyName, + ObjectEnd, + + ArrayStart, + ArrayEnd, + + Int, + Long, + Double, + + String, + + Boolean, + Null + } + + + public class JsonReader + { + #region Fields + private static readonly IDictionary<int, IDictionary<int, int[]>> parse_table; + + private Stack<int> automaton_stack; + private int current_input; + private int current_symbol; + private bool end_of_json; + private bool end_of_input; + private Lexer lexer; + private bool parser_in_string; + private bool parser_return; + private bool read_started; + private TextReader reader; + private bool reader_is_owned; + private bool skip_non_members; + private object token_value; + private JsonToken token; + #endregion + + + #region Public Properties + public bool AllowComments + { + get { return lexer.AllowComments; } + set { lexer.AllowComments = value; } + } + + public bool AllowSingleQuotedStrings + { + get { return lexer.AllowSingleQuotedStrings; } + set { lexer.AllowSingleQuotedStrings = value; } + } + + public bool SkipNonMembers + { + get { return skip_non_members; } + set { skip_non_members = value; } + } + + public bool EndOfInput + { + get { return end_of_input; } + } + + public bool EndOfJson + { + get { return end_of_json; } + } + + public JsonToken Token + { + get { return token; } + } + + public object Value + { + get { return token_value; } + } + #endregion + + + #region Constructors + static JsonReader() + { + parse_table = PopulateParseTable(); + } + + public JsonReader(string json_text) : + this(new StringReader(json_text), true) + { + } + + public JsonReader(TextReader reader) : + this(reader, false) + { + } + + private JsonReader(TextReader reader, bool owned) + { + if (reader == null) + throw new ArgumentNullException("reader"); + + parser_in_string = false; + parser_return = false; + + read_started = false; + automaton_stack = new Stack<int>(); + automaton_stack.Push((int)ParserToken.End); + automaton_stack.Push((int)ParserToken.Text); + + lexer = new Lexer(reader); + + end_of_input = false; + end_of_json = false; + + skip_non_members = true; + + this.reader = reader; + reader_is_owned = owned; + } + #endregion + + + #region Static Methods + private static IDictionary<int, IDictionary<int, int[]>> PopulateParseTable() + { + // See section A.2. of the manual for details + IDictionary<int, IDictionary<int, int[]>> parse_table = new Dictionary<int, IDictionary<int, int[]>>(); + + TableAddRow(parse_table, ParserToken.Array); + TableAddCol(parse_table, ParserToken.Array, '[', + '[', + (int)ParserToken.ArrayPrime); + + TableAddRow(parse_table, ParserToken.ArrayPrime); + TableAddCol(parse_table, ParserToken.ArrayPrime, '"', + (int)ParserToken.Value, + + (int)ParserToken.ValueRest, + ']'); + TableAddCol(parse_table, ParserToken.ArrayPrime, '[', + (int)ParserToken.Value, + (int)ParserToken.ValueRest, + ']'); + TableAddCol(parse_table, ParserToken.ArrayPrime, ']', + ']'); + TableAddCol(parse_table, ParserToken.ArrayPrime, '{', + (int)ParserToken.Value, + (int)ParserToken.ValueRest, + ']'); + TableAddCol(parse_table, ParserToken.ArrayPrime, (int)ParserToken.Number, + (int)ParserToken.Value, + (int)ParserToken.ValueRest, + ']'); + TableAddCol(parse_table, ParserToken.ArrayPrime, (int)ParserToken.True, + (int)ParserToken.Value, + (int)ParserToken.ValueRest, + ']'); + TableAddCol(parse_table, ParserToken.ArrayPrime, (int)ParserToken.False, + (int)ParserToken.Value, + (int)ParserToken.ValueRest, + ']'); + TableAddCol(parse_table, ParserToken.ArrayPrime, (int)ParserToken.Null, + (int)ParserToken.Value, + (int)ParserToken.ValueRest, + ']'); + + TableAddRow(parse_table, ParserToken.Object); + TableAddCol(parse_table, ParserToken.Object, '{', + '{', + (int)ParserToken.ObjectPrime); + + TableAddRow(parse_table, ParserToken.ObjectPrime); + TableAddCol(parse_table, ParserToken.ObjectPrime, '"', + (int)ParserToken.Pair, + (int)ParserToken.PairRest, + '}'); + TableAddCol(parse_table, ParserToken.ObjectPrime, '}', + '}'); + + TableAddRow(parse_table, ParserToken.Pair); + TableAddCol(parse_table, ParserToken.Pair, '"', + (int)ParserToken.String, + ':', + (int)ParserToken.Value); + + TableAddRow(parse_table, ParserToken.PairRest); + TableAddCol(parse_table, ParserToken.PairRest, ',', + ',', + (int)ParserToken.Pair, + (int)ParserToken.PairRest); + TableAddCol(parse_table, ParserToken.PairRest, '}', + (int)ParserToken.Epsilon); + + TableAddRow(parse_table, ParserToken.String); + TableAddCol(parse_table, ParserToken.String, '"', + '"', + (int)ParserToken.CharSeq, + '"'); + + TableAddRow(parse_table, ParserToken.Text); + TableAddCol(parse_table, ParserToken.Text, '[', + (int)ParserToken.Array); + TableAddCol(parse_table, ParserToken.Text, '{', + (int)ParserToken.Object); + + TableAddRow(parse_table, ParserToken.Value); + TableAddCol(parse_table, ParserToken.Value, '"', + (int)ParserToken.String); + TableAddCol(parse_table, ParserToken.Value, '[', + (int)ParserToken.Array); + TableAddCol(parse_table, ParserToken.Value, '{', + (int)ParserToken.Object); + TableAddCol(parse_table, ParserToken.Value, (int)ParserToken.Number, + (int)ParserToken.Number); + TableAddCol(parse_table, ParserToken.Value, (int)ParserToken.True, + (int)ParserToken.True); + TableAddCol(parse_table, ParserToken.Value, (int)ParserToken.False, + (int)ParserToken.False); + TableAddCol(parse_table, ParserToken.Value, (int)ParserToken.Null, + (int)ParserToken.Null); + + TableAddRow(parse_table, ParserToken.ValueRest); + TableAddCol(parse_table, ParserToken.ValueRest, ',', + ',', + (int)ParserToken.Value, + (int)ParserToken.ValueRest); + TableAddCol(parse_table, ParserToken.ValueRest, ']', + (int)ParserToken.Epsilon); + + return parse_table; + } + + private static void TableAddCol(IDictionary<int, IDictionary<int, int[]>> parse_table, ParserToken row, int col, + params int[] symbols) + { + parse_table[(int)row].Add(col, symbols); + } + + private static void TableAddRow(IDictionary<int, IDictionary<int, int[]>> parse_table, ParserToken rule) + { + parse_table.Add((int)rule, new Dictionary<int, int[]>()); + } + #endregion + + + #region Private Methods + private void ProcessNumber(string number) + { + if (number.IndexOf('.') != -1 || + number.IndexOf('e') != -1 || + number.IndexOf('E') != -1) + { + + double n_double; + if (double.TryParse(number, NumberStyles.Any, CultureInfo.InvariantCulture, out n_double)) + { + token = JsonToken.Double; + token_value = n_double; + + return; + } + } + + int n_int32; + if (int.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int32)) + { + token = JsonToken.Int; + token_value = n_int32; + + return; + } + + long n_int64; + if (long.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int64)) + { + token = JsonToken.Long; + token_value = n_int64; + + return; + } + + ulong n_uint64; + if (ulong.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_uint64)) + { + token = JsonToken.Long; + token_value = n_uint64; + + return; + } + + // Shouldn't happen, but just in case, return something + token = JsonToken.Int; + token_value = 0; + } + + private void ProcessSymbol() + { + if (current_symbol == '[') + { + token = JsonToken.ArrayStart; + parser_return = true; + + } + else if (current_symbol == ']') + { + token = JsonToken.ArrayEnd; + parser_return = true; + + } + else if (current_symbol == '{') + { + token = JsonToken.ObjectStart; + parser_return = true; + + } + else if (current_symbol == '}') + { + token = JsonToken.ObjectEnd; + parser_return = true; + + } + else if (current_symbol == '"') + { + if (parser_in_string) + { + parser_in_string = false; + + parser_return = true; + + } + else + { + if (token == JsonToken.None) + token = JsonToken.String; + + parser_in_string = true; + } + + } + else if (current_symbol == (int)ParserToken.CharSeq) + { + token_value = lexer.StringValue; + + } + else if (current_symbol == (int)ParserToken.False) + { + token = JsonToken.Boolean; + token_value = false; + parser_return = true; + + } + else if (current_symbol == (int)ParserToken.Null) + { + token = JsonToken.Null; + parser_return = true; + + } + else if (current_symbol == (int)ParserToken.Number) + { + ProcessNumber(lexer.StringValue); + + parser_return = true; + + } + else if (current_symbol == (int)ParserToken.Pair) + { + token = JsonToken.PropertyName; + + } + else if (current_symbol == (int)ParserToken.True) + { + token = JsonToken.Boolean; + token_value = true; + parser_return = true; + + } + } + + private bool ReadToken() + { + if (end_of_input) + return false; + + lexer.NextToken(); + + if (lexer.EndOfInput) + { + Close(); + + return false; + } + + current_input = lexer.Token; + + return true; + } + #endregion + + + public void Close() + { + if (end_of_input) + return; + + end_of_input = true; + end_of_json = true; + + if (reader_is_owned) + { + using (reader) { } + } + + reader = null; + } + + public bool Read() + { + if (end_of_input) + return false; + + if (end_of_json) + { + end_of_json = false; + automaton_stack.Clear(); + automaton_stack.Push((int)ParserToken.End); + automaton_stack.Push((int)ParserToken.Text); + } + + parser_in_string = false; + parser_return = false; + + token = JsonToken.None; + token_value = null; + + if (!read_started) + { + read_started = true; + + if (!ReadToken()) + return false; + } + + + int[] entry_symbols; + + while (true) + { + if (parser_return) + { + if (automaton_stack.Peek() == (int)ParserToken.End) + end_of_json = true; + + return true; + } + + current_symbol = automaton_stack.Pop(); + + ProcessSymbol(); + + if (current_symbol == current_input) + { + if (!ReadToken()) + { + if (automaton_stack.Peek() != (int)ParserToken.End) + throw new JsonException( + "Input doesn't evaluate to proper JSON text"); + + if (parser_return) + return true; + + return false; + } + + continue; + } + + try + { + + entry_symbols = + parse_table[current_symbol][current_input]; + + } + catch (KeyNotFoundException e) + { + throw new JsonException((ParserToken)current_input, e); + } + + if (entry_symbols[0] == (int)ParserToken.Epsilon) + continue; + + for (int i = entry_symbols.Length - 1; i >= 0; i--) + automaton_stack.Push(entry_symbols[i]); + } + } + + } +} diff --git a/O&Z_Obfuscator/LitJson/JsonWriter.cs b/O&Z_Obfuscator/LitJson/JsonWriter.cs new file mode 100644 index 0000000..8e27db0 --- /dev/null +++ b/O&Z_Obfuscator/LitJson/JsonWriter.cs @@ -0,0 +1,499 @@ +#region Header +/** + * JsonWriter.cs + * Stream-like facility to output JSON text. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text; + + +namespace O_Z_IL2CPP_Security.LitJson +{ + internal enum Condition + { + InArray, + InObject, + NotAProperty, + Property, + Value + } + + internal class WriterContext + { + public int Count; + public bool InArray; + public bool InObject; + public bool ExpectingValue; + public int Padding; + } + + public class JsonWriter + { + #region Fields + private static readonly NumberFormatInfo number_format; + + private WriterContext context; + private Stack<WriterContext> ctx_stack; + private bool has_reached_end; + private char[] hex_seq; + private int indentation; + private int indent_value; + private StringBuilder inst_string_builder; + private bool pretty_print; + private bool validate; + private bool lower_case_properties; + private TextWriter writer; + #endregion + + + #region Properties + public int IndentValue + { + get { return indent_value; } + set + { + indentation = indentation / indent_value * value; + indent_value = value; + } + } + + public bool PrettyPrint + { + get { return pretty_print; } + set { pretty_print = value; } + } + + public TextWriter TextWriter + { + get { return writer; } + } + + public bool Validate + { + get { return validate; } + set { validate = value; } + } + + public bool LowerCaseProperties + { + get { return lower_case_properties; } + set { lower_case_properties = value; } + } + #endregion + + + #region Constructors + static JsonWriter() + { + number_format = NumberFormatInfo.InvariantInfo; + } + + public JsonWriter() + { + inst_string_builder = new StringBuilder(); + writer = new StringWriter(inst_string_builder); + + Init(); + } + + public JsonWriter(StringBuilder sb) : + this(new StringWriter(sb)) + { + } + + public JsonWriter(TextWriter writer) + { + if (writer == null) + throw new ArgumentNullException("writer"); + + this.writer = writer; + + Init(); + } + #endregion + + + #region Private Methods + private void DoValidation(Condition cond) + { + if (!context.ExpectingValue) + context.Count++; + + if (!validate) + return; + + if (has_reached_end) + throw new JsonException( + "A complete JSON symbol has already been written"); + + switch (cond) + { + case Condition.InArray: + if (!context.InArray) + throw new JsonException( + "Can't close an array here"); + break; + + case Condition.InObject: + if (!context.InObject || context.ExpectingValue) + throw new JsonException( + "Can't close an object here"); + break; + + case Condition.NotAProperty: + if (context.InObject && !context.ExpectingValue) + throw new JsonException( + "Expected a property"); + break; + + case Condition.Property: + if (!context.InObject || context.ExpectingValue) + throw new JsonException( + "Can't add a property here"); + break; + + case Condition.Value: + if (!context.InArray && + (!context.InObject || !context.ExpectingValue)) + throw new JsonException( + "Can't add a value here"); + + break; + } + } + + private void Init() + { + has_reached_end = false; + hex_seq = new char[4]; + indentation = 0; + indent_value = 4; + pretty_print = false; + validate = true; + lower_case_properties = false; + + ctx_stack = new Stack<WriterContext>(); + context = new WriterContext(); + ctx_stack.Push(context); + } + + private static void IntToHex(int n, char[] hex) + { + int num; + + for (int i = 0; i < 4; i++) + { + num = n % 16; + + if (num < 10) + hex[3 - i] = (char)('0' + num); + else + hex[3 - i] = (char)('A' + (num - 10)); + + n >>= 4; + } + } + + private void Indent() + { + if (pretty_print) + indentation += indent_value; + } + + + private void Put(string str) + { + if (pretty_print && !context.ExpectingValue) + for (int i = 0; i < indentation; i++) + writer.Write(' '); + + writer.Write(str); + } + + private void PutNewline() + { + PutNewline(true); + } + + private void PutNewline(bool add_comma) + { + if (add_comma && !context.ExpectingValue && + context.Count > 1) + writer.Write(','); + + if (pretty_print && !context.ExpectingValue) + writer.Write(Environment.NewLine); + } + + private void PutString(string str) + { + Put(string.Empty); + + writer.Write('"'); + + int n = str.Length; + for (int i = 0; i < n; i++) + { + switch (str[i]) + { + case '\n': + writer.Write("\\n"); + continue; + + case '\r': + writer.Write("\\r"); + continue; + + case '\t': + writer.Write("\\t"); + continue; + + case '"': + case '\\': + writer.Write('\\'); + writer.Write(str[i]); + continue; + + case '\f': + writer.Write("\\f"); + continue; + + case '\b': + writer.Write("\\b"); + continue; + } + + if (str[i] >= 32 && str[i] <= 126) + { + writer.Write(str[i]); + continue; + } + + // Default, turn into a \uXXXX sequence + IntToHex(str[i], hex_seq); + writer.Write("\\u"); + writer.Write(hex_seq); + } + + writer.Write('"'); + } + + private void Unindent() + { + if (pretty_print) + indentation -= indent_value; + } + #endregion + + + public override string ToString() + { + if (inst_string_builder == null) + return string.Empty; + + return inst_string_builder.ToString(); + } + + public void Reset() + { + has_reached_end = false; + + ctx_stack.Clear(); + context = new WriterContext(); + ctx_stack.Push(context); + + if (inst_string_builder != null) + inst_string_builder.Remove(0, inst_string_builder.Length); + } + + public void Write(bool boolean) + { + DoValidation(Condition.Value); + PutNewline(); + + Put(boolean ? "true" : "false"); + + context.ExpectingValue = false; + } + + public void Write(decimal number) + { + DoValidation(Condition.Value); + PutNewline(); + + Put(Convert.ToString(number, number_format)); + + context.ExpectingValue = false; + } + + public void Write(double number) + { + DoValidation(Condition.Value); + PutNewline(); + + string str = Convert.ToString(number, number_format); + Put(str); + + if (str.IndexOf('.') == -1 && + str.IndexOf('E') == -1) + writer.Write(".0"); + + context.ExpectingValue = false; + } + + public void Write(float number) + { + DoValidation(Condition.Value); + PutNewline(); + + string str = Convert.ToString(number, number_format); + Put(str); + + context.ExpectingValue = false; + } + + public void Write(int number) + { + DoValidation(Condition.Value); + PutNewline(); + + Put(Convert.ToString(number, number_format)); + + context.ExpectingValue = false; + } + + public void Write(long number) + { + DoValidation(Condition.Value); + PutNewline(); + + Put(Convert.ToString(number, number_format)); + + context.ExpectingValue = false; + } + + public void Write(string str) + { + DoValidation(Condition.Value); + PutNewline(); + + if (str == null) + Put("null"); + else + PutString(str); + + context.ExpectingValue = false; + } + + [CLSCompliant(false)] + public void Write(ulong number) + { + DoValidation(Condition.Value); + PutNewline(); + + Put(Convert.ToString(number, number_format)); + + context.ExpectingValue = false; + } + + public void WriteArrayEnd() + { + DoValidation(Condition.InArray); + PutNewline(false); + + ctx_stack.Pop(); + if (ctx_stack.Count == 1) + has_reached_end = true; + else + { + context = ctx_stack.Peek(); + context.ExpectingValue = false; + } + + Unindent(); + Put("]"); + } + + public void WriteArrayStart() + { + DoValidation(Condition.NotAProperty); + PutNewline(); + + Put("["); + + context = new WriterContext(); + context.InArray = true; + ctx_stack.Push(context); + + Indent(); + } + + public void WriteObjectEnd() + { + DoValidation(Condition.InObject); + PutNewline(false); + + ctx_stack.Pop(); + if (ctx_stack.Count == 1) + has_reached_end = true; + else + { + context = ctx_stack.Peek(); + context.ExpectingValue = false; + } + + Unindent(); + Put("}"); + } + + public void WriteObjectStart() + { + DoValidation(Condition.NotAProperty); + PutNewline(); + + Put("{"); + + context = new WriterContext(); + context.InObject = true; + ctx_stack.Push(context); + + Indent(); + } + + public void WritePropertyName(string property_name) + { + DoValidation(Condition.Property); + PutNewline(); + string propertyName = property_name == null || !lower_case_properties + ? property_name + : property_name.ToLowerInvariant(); + + PutString(propertyName); + + if (pretty_print) + { + if (propertyName.Length > context.Padding) + context.Padding = propertyName.Length; + + for (int i = context.Padding - propertyName.Length; + i >= 0; i--) + writer.Write(' '); + + writer.Write(": "); + } + else + writer.Write(':'); + + context.ExpectingValue = true; + } + } +} diff --git a/O&Z_Obfuscator/LitJson/Lexer.cs b/O&Z_Obfuscator/LitJson/Lexer.cs new file mode 100644 index 0000000..f476ede --- /dev/null +++ b/O&Z_Obfuscator/LitJson/Lexer.cs @@ -0,0 +1,971 @@ +#region Header +/** + * Lexer.cs + * JSON lexer implementation based on a finite state machine. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + + +namespace O_Z_IL2CPP_Security.LitJson +{ + internal class FsmContext + { + public bool Return; + public int NextState; + public Lexer L; + public int StateStack; + } + + + internal class Lexer + { + #region Fields + private delegate bool StateHandler(FsmContext ctx); + + private static readonly int[] fsm_return_table; + private static readonly StateHandler[] fsm_handler_table; + + private bool allow_comments; + private bool allow_single_quoted_strings; + private bool end_of_input; + private FsmContext fsm_context; + private int input_buffer; + private int input_char; + private TextReader reader; + private int state; + private StringBuilder string_buffer; + private string string_value; + private int token; + private int unichar; + #endregion + + + #region Properties + public bool AllowComments + { + get { return allow_comments; } + set { allow_comments = value; } + } + + public bool AllowSingleQuotedStrings + { + get { return allow_single_quoted_strings; } + set { allow_single_quoted_strings = value; } + } + + public bool EndOfInput + { + get { return end_of_input; } + } + + public int Token + { + get { return token; } + } + + public string StringValue + { + get { return string_value; } + } + #endregion + + + #region Constructors + static Lexer() + { + PopulateFsmTables(out fsm_handler_table, out fsm_return_table); + } + + public Lexer(TextReader reader) + { + allow_comments = true; + allow_single_quoted_strings = true; + + input_buffer = 0; + string_buffer = new StringBuilder(128); + state = 1; + end_of_input = false; + this.reader = reader; + + fsm_context = new FsmContext(); + fsm_context.L = this; + } + #endregion + + + #region Static Methods + private static int HexValue(int digit) + { + switch (digit) + { + case 'a': + case 'A': + return 10; + + case 'b': + case 'B': + return 11; + + case 'c': + case 'C': + return 12; + + case 'd': + case 'D': + return 13; + + case 'e': + case 'E': + return 14; + + case 'f': + case 'F': + return 15; + + default: + return digit - '0'; + } + } + + private static void PopulateFsmTables(out StateHandler[] fsm_handler_table, out int[] fsm_return_table) + { + // See section A.1. of the manual for details of the finite + // state machine. + fsm_handler_table = new StateHandler[28] { + State1, + State2, + State3, + State4, + State5, + State6, + State7, + State8, + State9, + State10, + State11, + State12, + State13, + State14, + State15, + State16, + State17, + State18, + State19, + State20, + State21, + State22, + State23, + State24, + State25, + State26, + State27, + State28 + }; + + fsm_return_table = new int[28] { + (int) ParserToken.Char, + 0, + (int) ParserToken.Number, + (int) ParserToken.Number, + 0, + (int) ParserToken.Number, + 0, + (int) ParserToken.Number, + 0, + 0, + (int) ParserToken.True, + 0, + 0, + 0, + (int) ParserToken.False, + 0, + 0, + (int) ParserToken.Null, + (int) ParserToken.CharSeq, + (int) ParserToken.Char, + 0, + 0, + (int) ParserToken.CharSeq, + (int) ParserToken.Char, + 0, + 0, + 0, + 0 + }; + } + + private static char ProcessEscChar(int esc_char) + { + switch (esc_char) + { + case '"': + case '\'': + case '\\': + case '/': + return Convert.ToChar(esc_char); + + case 'n': + return '\n'; + + case 't': + return '\t'; + + case 'r': + return '\r'; + + case 'b': + return '\b'; + + case 'f': + return '\f'; + + default: + // Unreachable + return '?'; + } + } + + private static bool State1(FsmContext ctx) + { + while (ctx.L.GetChar()) + { + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') + continue; + + if (ctx.L.input_char >= '1' && ctx.L.input_char <= '9') + { + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 3; + return true; + } + + switch (ctx.L.input_char) + { + case '"': + ctx.NextState = 19; + ctx.Return = true; + return true; + + case ',': + case ':': + case '[': + case ']': + case '{': + case '}': + ctx.NextState = 1; + ctx.Return = true; + return true; + + case '-': + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 2; + return true; + + case '0': + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 4; + return true; + + case 'f': + ctx.NextState = 12; + return true; + + case 'n': + ctx.NextState = 16; + return true; + + case 't': + ctx.NextState = 9; + return true; + + case '\'': + if (!ctx.L.allow_single_quoted_strings) + return false; + + ctx.L.input_char = '"'; + ctx.NextState = 23; + ctx.Return = true; + return true; + + case '/': + if (!ctx.L.allow_comments) + return false; + + ctx.NextState = 25; + return true; + + default: + return false; + } + } + + return true; + } + + private static bool State2(FsmContext ctx) + { + ctx.L.GetChar(); + + if (ctx.L.input_char >= '1' && ctx.L.input_char <= '9') + { + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 3; + return true; + } + + switch (ctx.L.input_char) + { + case '0': + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 4; + return true; + + default: + return false; + } + } + + private static bool State3(FsmContext ctx) + { + while (ctx.L.GetChar()) + { + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') + { + ctx.L.string_buffer.Append((char)ctx.L.input_char); + continue; + } + + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') + { + ctx.Return = true; + ctx.NextState = 1; + return true; + } + + switch (ctx.L.input_char) + { + case ',': + case ']': + case '}': + ctx.L.UngetChar(); + ctx.Return = true; + ctx.NextState = 1; + return true; + + case '.': + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 5; + return true; + + case 'e': + case 'E': + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 7; + return true; + + default: + return false; + } + } + return true; + } + + private static bool State4(FsmContext ctx) + { + ctx.L.GetChar(); + + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') + { + ctx.Return = true; + ctx.NextState = 1; + return true; + } + + switch (ctx.L.input_char) + { + case ',': + case ']': + case '}': + ctx.L.UngetChar(); + ctx.Return = true; + ctx.NextState = 1; + return true; + + case '.': + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 5; + return true; + + case 'e': + case 'E': + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 7; + return true; + + default: + return false; + } + } + + private static bool State5(FsmContext ctx) + { + ctx.L.GetChar(); + + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') + { + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 6; + return true; + } + + return false; + } + + private static bool State6(FsmContext ctx) + { + while (ctx.L.GetChar()) + { + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') + { + ctx.L.string_buffer.Append((char)ctx.L.input_char); + continue; + } + + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') + { + ctx.Return = true; + ctx.NextState = 1; + return true; + } + + switch (ctx.L.input_char) + { + case ',': + case ']': + case '}': + ctx.L.UngetChar(); + ctx.Return = true; + ctx.NextState = 1; + return true; + + case 'e': + case 'E': + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 7; + return true; + + default: + return false; + } + } + + return true; + } + + private static bool State7(FsmContext ctx) + { + ctx.L.GetChar(); + + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') + { + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 8; + return true; + } + + switch (ctx.L.input_char) + { + case '+': + case '-': + ctx.L.string_buffer.Append((char)ctx.L.input_char); + ctx.NextState = 8; + return true; + + default: + return false; + } + } + + private static bool State8(FsmContext ctx) + { + while (ctx.L.GetChar()) + { + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') + { + ctx.L.string_buffer.Append((char)ctx.L.input_char); + continue; + } + + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') + { + ctx.Return = true; + ctx.NextState = 1; + return true; + } + + switch (ctx.L.input_char) + { + case ',': + case ']': + case '}': + ctx.L.UngetChar(); + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + return true; + } + + private static bool State9(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case 'r': + ctx.NextState = 10; + return true; + + default: + return false; + } + } + + private static bool State10(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case 'u': + ctx.NextState = 11; + return true; + + default: + return false; + } + } + + private static bool State11(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case 'e': + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State12(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case 'a': + ctx.NextState = 13; + return true; + + default: + return false; + } + } + + private static bool State13(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case 'l': + ctx.NextState = 14; + return true; + + default: + return false; + } + } + + private static bool State14(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case 's': + ctx.NextState = 15; + return true; + + default: + return false; + } + } + + private static bool State15(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case 'e': + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State16(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case 'u': + ctx.NextState = 17; + return true; + + default: + return false; + } + } + + private static bool State17(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case 'l': + ctx.NextState = 18; + return true; + + default: + return false; + } + } + + private static bool State18(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case 'l': + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State19(FsmContext ctx) + { + while (ctx.L.GetChar()) + { + switch (ctx.L.input_char) + { + case '"': + ctx.L.UngetChar(); + ctx.Return = true; + ctx.NextState = 20; + return true; + + case '\\': + ctx.StateStack = 19; + ctx.NextState = 21; + return true; + + default: + ctx.L.string_buffer.Append((char)ctx.L.input_char); + continue; + } + } + + return true; + } + + private static bool State20(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case '"': + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State21(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case 'u': + ctx.NextState = 22; + return true; + + case '"': + case '\'': + case '/': + case '\\': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + ctx.L.string_buffer.Append( + ProcessEscChar(ctx.L.input_char)); + ctx.NextState = ctx.StateStack; + return true; + + default: + return false; + } + } + + private static bool State22(FsmContext ctx) + { + int counter = 0; + int mult = 4096; + + ctx.L.unichar = 0; + + while (ctx.L.GetChar()) + { + + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9' || + ctx.L.input_char >= 'A' && ctx.L.input_char <= 'F' || + ctx.L.input_char >= 'a' && ctx.L.input_char <= 'f') + { + + ctx.L.unichar += HexValue(ctx.L.input_char) * mult; + + counter++; + mult /= 16; + + if (counter == 4) + { + ctx.L.string_buffer.Append( + Convert.ToChar(ctx.L.unichar)); + ctx.NextState = ctx.StateStack; + return true; + } + + continue; + } + + return false; + } + + return true; + } + + private static bool State23(FsmContext ctx) + { + while (ctx.L.GetChar()) + { + switch (ctx.L.input_char) + { + case '\'': + ctx.L.UngetChar(); + ctx.Return = true; + ctx.NextState = 24; + return true; + + case '\\': + ctx.StateStack = 23; + ctx.NextState = 21; + return true; + + default: + ctx.L.string_buffer.Append((char)ctx.L.input_char); + continue; + } + } + + return true; + } + + private static bool State24(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case '\'': + ctx.L.input_char = '"'; + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State25(FsmContext ctx) + { + ctx.L.GetChar(); + + switch (ctx.L.input_char) + { + case '*': + ctx.NextState = 27; + return true; + + case '/': + ctx.NextState = 26; + return true; + + default: + return false; + } + } + + private static bool State26(FsmContext ctx) + { + while (ctx.L.GetChar()) + { + if (ctx.L.input_char == '\n') + { + ctx.NextState = 1; + return true; + } + } + + return true; + } + + private static bool State27(FsmContext ctx) + { + while (ctx.L.GetChar()) + { + if (ctx.L.input_char == '*') + { + ctx.NextState = 28; + return true; + } + } + + return true; + } + + private static bool State28(FsmContext ctx) + { + while (ctx.L.GetChar()) + { + if (ctx.L.input_char == '*') + continue; + + if (ctx.L.input_char == '/') + { + ctx.NextState = 1; + return true; + } + + ctx.NextState = 27; + return true; + } + + return true; + } + #endregion + + + private bool GetChar() + { + if ((input_char = NextChar()) != -1) + return true; + + end_of_input = true; + return false; + } + + private int NextChar() + { + if (input_buffer != 0) + { + int tmp = input_buffer; + input_buffer = 0; + + return tmp; + } + + return reader.Read(); + } + + public bool NextToken() + { + StateHandler handler; + fsm_context.Return = false; + + while (true) + { + handler = fsm_handler_table[state - 1]; + + if (!handler(fsm_context)) + throw new JsonException(input_char); + + if (end_of_input) + return false; + + if (fsm_context.Return) + { + string_value = string_buffer.ToString(); + string_buffer.Remove(0, string_buffer.Length); + token = fsm_return_table[state - 1]; + + if (token == (int)ParserToken.Char) + token = input_char; + + state = fsm_context.NextState; + + return true; + } + + state = fsm_context.NextState; + } + } + + private void UngetChar() + { + input_buffer = input_char; + } + } +} diff --git a/O&Z_Obfuscator/LitJson/LitJSON.csproj b/O&Z_Obfuscator/LitJson/LitJSON.csproj new file mode 100644 index 0000000..73a77ff --- /dev/null +++ b/O&Z_Obfuscator/LitJson/LitJSON.csproj @@ -0,0 +1,61 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFrameworks>netstandard2.1;netstandard2.0;net45;netstandard1.5;net40;net35;net20;net6.0</TargetFrameworks> + </PropertyGroup> + + <PropertyGroup> + <GenerateAssemblyInfo>false</GenerateAssemblyInfo> + <DebugType>embedded</DebugType> + <EmbedUntrackedSources>true</EmbedUntrackedSources> + <PublishRepositoryUrl>true</PublishRepositoryUrl> + <SourceLinkCreate Condition="'$(OS)' == 'Windows_NT'">true</SourceLinkCreate> + </PropertyGroup> + + <ItemGroup Condition="'$(OS)' == 'Windows_NT'"> + <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" /> + <DotNetCliToolReference Include="dotnet-sourcelink-git" Version="2.8.3" /> + <DotNetCliToolReference Include="dotnet-sourcelink" Version="2.8.3" /> + </ItemGroup> + + <PropertyGroup> + <PackageId>LitJson</PackageId> + <Description>A .Net library to handle conversions from and to JSON (JavaScript Object Notation) strings. Written in C#, and it’s intended to be small, fast and easy to use. +It's quick and lean, without external dependencies.</Description> + <Copyright>The authors disclaim copyright to this source code.</Copyright> + <Authors>Leonardo Boshell, Mattias Karlsson and contributors</Authors> + <Company>Leonardo Boshell, Mattias Karlsson and contributors</Company> + <PackageLicenseExpression>Unlicense</PackageLicenseExpression> + <PackageIcon>litjson.png</PackageIcon> + <RepositoryUrl>https://github.com/LitJSON/litjson</RepositoryUrl> + <RepositoryType>git</RepositoryType> + <PackageTags>JSON;Serializer</PackageTags> + <IncludeSource>true</IncludeSource> + </PropertyGroup> + + <ItemGroup> + <None Include="litjson.png" Pack="true" PackagePath="" /> + </ItemGroup> + + <PropertyGroup Condition="'$(TargetFramework)' == 'net20' "> + <DefineConstants>$(DefineConstants);LEGACY</DefineConstants> + <FrameworkPathOverride Condition="'$(TargetFramework)' == 'net20' and '$(OS)' == 'Windows_NT'">C:\Windows\Microsoft.NET\Framework\v2.0.50727</FrameworkPathOverride> + </PropertyGroup> + + <PropertyGroup Condition="'$(TargetFramework)' == 'net35' "> + <DefineConstants>$(DefineConstants);LEGACY</DefineConstants> + <FrameworkPathOverride Condition="'$(TargetFramework)' == 'net35' and '$(OS)' == 'Windows_NT'">C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client</FrameworkPathOverride> + </PropertyGroup> + + <PropertyGroup Condition="'$(TargetFramework)' == 'net40' "> + <DefineConstants>$(DefineConstants);LEGACY</DefineConstants> + </PropertyGroup> + + <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.5' "> + <PackageReference Include="System.Collections.NonGeneric" Version="4.0.1" /> + <PackageReference Include="System.Collections.Specialized" Version="4.0.1" /> + <PackageReference Include="System.Reflection" Version="4.3.0" /> + <PackageReference Include="System.Reflection.TypeExtensions" Version="4.1.0" /> + </ItemGroup> + +</Project> diff --git a/O&Z_Obfuscator/LitJson/Netstandard15Polyfill.cs b/O&Z_Obfuscator/LitJson/Netstandard15Polyfill.cs new file mode 100644 index 0000000..55b02a2 --- /dev/null +++ b/O&Z_Obfuscator/LitJson/Netstandard15Polyfill.cs @@ -0,0 +1,24 @@ +#if NETSTANDARD1_5 +using System; +using System.Reflection; +namespace LitJson +{ + internal static class Netstandard15Polyfill + { + internal static Type GetInterface(this Type type, string name) + { + return type.GetTypeInfo().GetInterface(name); + } + + internal static bool IsClass(this Type type) + { + return type.GetTypeInfo().IsClass; + } + + internal static bool IsEnum(this Type type) + { + return type.GetTypeInfo().IsEnum; + } + } +} +#endif \ No newline at end of file diff --git a/O&Z_Obfuscator/LitJson/ParserToken.cs b/O&Z_Obfuscator/LitJson/ParserToken.cs new file mode 100644 index 0000000..0dabea2 --- /dev/null +++ b/O&Z_Obfuscator/LitJson/ParserToken.cs @@ -0,0 +1,45 @@ +#region Header + +#endregion + + +/** +* ParserToken.cs +* Internal representation of the tokens used by the lexer and the parser. +* +* The authors disclaim copyright to this source code. For more details, see +* the COPYING file included with this distribution. +**/ +namespace O_Z_IL2CPP_Security.LitJson +{ + internal enum ParserToken + { + // Lexer tokens (see section A.1.1. of the manual) + None = char.MaxValue + 1, + Number, + True, + False, + Null, + CharSeq, + // Single char + Char, + + // Parser Rules (see section A.2.1 of the manual) + Text, + Object, + ObjectPrime, + Pair, + PairRest, + Array, + ArrayPrime, + Value, + ValueRest, + String, + + // End of input + End, + + // The empty rule + Epsilon + } +} diff --git a/O&Z_Obfuscator/LitJson/litjson.png b/O&Z_Obfuscator/LitJson/litjson.png new file mode 100644 index 0000000..a4c15e5 Binary files /dev/null and b/O&Z_Obfuscator/LitJson/litjson.png differ diff --git a/O&Z_Obfuscator/OZ_Obfuscator.csproj b/O&Z_Obfuscator/OZ_Obfuscator.csproj index 8e73c3b..ecc4aa6 100644 --- a/O&Z_Obfuscator/OZ_Obfuscator.csproj +++ b/O&Z_Obfuscator/OZ_Obfuscator.csproj @@ -71,9 +71,20 @@ </ItemGroup> <ItemGroup> <Compile Include="AssemblyLoader.cs" /> + <Compile Include="LitJson\IJsonWrapper.cs" /> + <Compile Include="LitJson\JsonData.cs" /> + <Compile Include="LitJson\JsonException.cs" /> + <Compile Include="LitJson\JsonMapper.cs" /> + <Compile Include="LitJson\JsonMockWrapper.cs" /> + <Compile Include="LitJson\JsonReader.cs" /> + <Compile Include="LitJson\JsonWriter.cs" /> + <Compile Include="LitJson\Lexer.cs" /> + <Compile Include="LitJson\Netstandard15Polyfill.cs" /> + <Compile Include="LitJson\ParserToken.cs" /> <Compile Include="Ofbuscators\ControlFlow.cs" /> <Compile Include="Ofbuscators\Antide4dot.cs" /> <Compile Include="Ofbuscators\LocalVariables2Field.cs" /> + <Compile Include="Ofbuscators\ObfusFunc.cs" /> <Compile Include="Runtime\Num2Modle.cs" /> <Compile Include="Ofbuscators\NumObfus.cs" /> <Compile Include="Program.cs" /> @@ -89,5 +100,12 @@ <Install>false</Install> </BootstrapperPackage> </ItemGroup> + <ItemGroup> + <None Include="LitJson\AssemblyInfo.cs.in" /> + <None Include="LitJson\LitJSON.csproj" /> + </ItemGroup> + <ItemGroup> + <Content Include="LitJson\litjson.png" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </Project> \ No newline at end of file diff --git a/O&Z_Obfuscator/Ofbuscators/ObfusFunc.cs b/O&Z_Obfuscator/Ofbuscators/ObfusFunc.cs new file mode 100644 index 0000000..0442df3 --- /dev/null +++ b/O&Z_Obfuscator/Ofbuscators/ObfusFunc.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using dnlib.DotNet; +using dnlib.DotNet.Emit; +using O_Z_IL2CPP_Security.LitJson; +using OZ_Obfus; + +namespace OZ_Obfuscator.Ofbuscators +{ + public class ObfusFunc + { + ModuleDefMD module; + List<string> ignoreMethod = new List<string>(); + List<string> ignoreField = new List<string>(); + List<string> obfusClass = new List<string>(); + public ObfusFunc(ModuleDefMD module) + { + this.module = module; + if(!File.Exists("keyfunc.json")) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("keyfunc.json not found!"); + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine("正在重新生成默认keyfunc.json..."); + Console.WriteLine("如果您不想使用默认keyfunc.json,请重新配置keyfunc.json"); + Console.ForegroundColor = ConsoleColor.White; + File.WriteAllBytes("keyfunc.json", Convert.FromBase64String(ignore.origin)); + } + ignore ig = JsonMapper.ToObject<ignore>(File.ReadAllText("keyfunc.json")); + foreach (var item in ig.ignoreMethod) + ignoreMethod.Add(item.ToLower()); + foreach (var item in ig.ignoreField) + ignoreField.Add(item.ToLower()); + foreach(var item in ig.customignoreMethod) + ignoreMethod.Add(item.ToLower()); + foreach (var item in ig.customignoreField) + ignoreField.Add(item.ToLower()); + foreach (var item in ig.customignoreClass) + obfusClass.Add(item.ToLower()); + } + public void Excute() + { + foreach (var type in module.Types.Where(x => !(x.Name.StartsWith("<")))) + { + foreach (var field in type.Fields.Where(x => !x.IsRuntimeSpecialName && !x.IsSpecialName + && !(x.Name.StartsWith("<")))) + { + if (ignoreField.FirstOrDefault(x => field.FullName.ToLower().Contains(x)) == null) + NameGenerator.SetObfusName(field, NameGenerator.Mode.FuncName, 3); + } + foreach (var method in type.Methods.Where(x => !x.IsConstructor && !x.IsVirtual + && !x.IsRuntime && !x.IsRuntimeSpecialName && !x.IsAbstract + && !((x.GenericParameters != null) && x.GenericParameters.Count > 0) && !(x.Overrides.Count > 0) + && !(x.Name.StartsWith("<") || x.Name.ToLower().StartsWith("do")))) + { + if (ignoreMethod.FirstOrDefault(x => method.FullName.ToLower().Contains(x)) == null) + NameGenerator.SetObfusName(method, NameGenerator.Mode.FuncName, 5); + if (method.HasParams()) + { + foreach (var p in method.Parameters) + { + p.Name = NameGenerator.GetName(NameGenerator.Mode.FuncName, 4); + } + } + } + foreach (var p in type.Properties.Where(x => !x.IsRuntimeSpecialName && !x.IsSpecialName)) + NameGenerator.SetObfusName(p, NameGenerator.Mode.Base64, 5); + //NameGenerator.SetObfusName(type, NameGenerator.Mode.FuncName, 6); + + if (obfusClass.FirstOrDefault(x => type.FullName.ToLower().Contains(x)) != null) + { + NameGenerator.SetObfusName(type, NameGenerator.Mode.FuncName, 6); + } + } + } + } + public class ignore + { + public string[] ignoreMethod; + public string[] ignoreField; + public string[] customignoreMethod; + public string[] customignoreField; + public string[] customignoreClass; + public static string origin = "ewogICAgImlnbm9yZU1ldGhvZCI6IFsKICAgICAgICAiQXdha2UiLAogICAgICAgICJPbkVuYWJsZSIsCiAgICAgICAgIlN0YXJ0IiwKICAgICAgICAiRml4ZWRVcGRhdGUiLAogICAgICAgICJVcGRhdGUiLAogICAgICAgICJPbkRpc2FibGUiLAogICAgICAgICJMYXRlVXBkYXRlIiwKICAgICAgICAiUmVzZXQiLAogICAgICAgICJPblZhbGlkYXRlIiwKICAgICAgICAiRml4ZWRVcGRhdGUiLAogICAgICAgICJPblRyaWdnZXJFbnRlciIsCiAgICAgICAgIk9uVHJpZ2dlckVudGVyMkQiLAogICAgICAgICJPblRyaWdnZXJFeGl0IiwKICAgICAgICAiT25UcmlnZ2VyRXhpdDJEIiwKICAgICAgICAiT25UcmlnZ2VyU3RheTJEIiwKICAgICAgICAiT25Db2xsaXNpb25FbnRlciIsCiAgICAgICAgIk9uQ29sbGlzaW9uRW50ZXIyRCIsCiAgICAgICAgIk9uQ29sbGlzaW9uRXhpdCIsCiAgICAgICAgIk9uQ29sbGlzaW9uRXhpdDJEIiwKICAgICAgICAiT25Db2xsaXNpb25TdGF5IiwKICAgICAgICAiT25Db2xsaXNpb25TdGF5MkQiLAogICAgICAgICJPbk1vdXNlRG93biIsCiAgICAgICAgIk9uTW91c2VEcmFnIiwKICAgICAgICAiT25Nb3VzZUVudGVyIiwKICAgICAgICAiT25Nb3VzZUV4aXQiLAogICAgICAgICJPbk1vdXNlT3ZlciIsCiAgICAgICAgIk9uTW91c2VVcCIsCiAgICAgICAgIk9uTW91c2VVcEFzQnV0dG9uIiwKICAgICAgICAiT25QcmVDdWxsIiwKICAgICAgICAiT25CZWNhbWVWaXNpYmxlIiwKICAgICAgICAiT25CZWNhbWVJbnZpc2libGUiLAogICAgICAgICJPbldpbGxSZW5kZXJPYmplY3QiLAogICAgICAgICJPblByZVJlbmRlciIsCiAgICAgICAgIk9uUmVuZGVyT2JqZWN0IiwKICAgICAgICAiT25Qb3N0UmVuZGVyIiwKICAgICAgICAiT25SZW5kZXJJbWFnZSIsCiAgICAgICAgIk9uR1VJIiwKICAgICAgICAiT25EcmF3R2l6bW9zIiwKICAgICAgICAiT25EcmF3R2l6bW9zU2VsZWN0ZWQiLAogICAgICAgICJPbkFwcGxpY2F0aW9uRm9jdXMiLAogICAgICAgICJPbkFwcGxpY2F0aW9uUGF1c2UiLAogICAgICAgICJPbkFwcGxpY2F0aW9uUXVpdCIsCiAgICAgICAgIk9uRGlzYWJsZSIsCiAgICAgICAgIk9uRGVzdG9yeSIsCiAgICAgICAgIk9uTGV2ZWxXYXNMb2FkZWQiLAogICAgICAgICJPbkFuaW1hdG9ySUsiLAogICAgICAgICJPbkFuaW1hdG9yTW92ZSIsCiAgICAgICAgIk9uQXBwbGljYXRpb25Gb2N1cyIsCiAgICAgICAgIk9uQXBwbGljYXRpb25QYXVzZSIsCiAgICAgICAgIk9uQXBwbGljYXRpb25RdWl0IiwKICAgICAgICAiT25BdWRpb0ZpbHRlclJlYWQiLAogICAgICAgICJPbkJlY2FtZUludmlzaWJsZSIsCiAgICAgICAgIk9uQmVjYW1lVmlzaWJsZSIsCiAgICAgICAgIk9uQ29ubmVjdGVkVG9TZXJ2ZXIiLAogICAgICAgICJPbkNvbnRyb2xsZXJDb2xsaWRlckhpdCIsCiAgICAgICAgIk9uRW5hYmxlIiwKICAgICAgICAiT25GYWlsZWRUb0Nvbm5lY3QiLAogICAgICAgICJPbkRpc2Nvbm5lY3RlZEZyb21TZXJ2ZXIiLAogICAgICAgICJPbkRyYXdHaXptb3MiLAogICAgICAgICJPbkRyYXdHaXptb3NTZWxlY3RlZCIsCiAgICAgICAgIk9uRW5hYmxlIiwKICAgICAgICAiT25GYWlsZWRUb0Nvbm5lY3QiLAogICAgICAgICJPbkZhaWxlZFRvQ29ubmVjdFRvTWFzdGVyU2VydmVyIiwKICAgICAgICAiT25Kb2ludEJyZWFrIiwKICAgICAgICAiT25Kb2ludEJyZWFrMkQiLAogICAgICAgICJPbk1hc3RlclNlcnZlckV2ZW50IiwKICAgICAgICAiT25OZXR3b3JrSW5zdGFudGlhdGUiLAogICAgICAgICJPblBhcnRpY2xlQ29sbGlzaW9uIiwKICAgICAgICAiT25QYXJ0aWNsZVN5c3RlbVN0b3BwZWQiLAogICAgICAgICJPblBhcnRpY2xlVHJpZ2dlciIsCiAgICAgICAgIk9uUGFydGljbGVVcGRhdGVKb2JTY2hlZHVsZWQiLAogICAgICAgICJPblBsYXllckNvbm5lY3RlZCIsCiAgICAgICAgIk9uUGxheWVyRGlzY29ubmVjdGVkIiwKICAgICAgICAiT25Qb3N0UmVuZGVyIiwKICAgICAgICAiT25QcmVDdWxsIiwKICAgICAgICAiT25QcmVSZW5kZXIiLAogICAgICAgICJPblJlbmRlckltYWdlIiwKICAgICAgICAiT25SZW5kZXJPYmplY3QiLAogICAgICAgICJPblNlcmlhbGl6ZU5ldHdvcmtWaWV3IiwKICAgICAgICAiT25TZXJ2ZXJJbml0aWFsaXplZCIsCiAgICAgICAgIk9uVHJhbnNmb3JtQ2hpbGRyZW5DaGFuZ2VkIiwKICAgICAgICAiT25UcmFuc2Zvcm1QYXJlbnRDaGFuZ2VkIiwKICAgICAgICAiT25WYWxpZGF0ZSIsCiAgICAgICAgIk9uV2lsbFJlbmRlck9iamVjdCIsCiAgICAgICAgIlJlc2V0IiwKICAgICAgICAiX18iLAogICAgICAgICJpbmNvbnRyb2wiLAogICAgICAgICJzdG9wIiwKICAgICAgICAib3B0aW9uIiwKICAgICAgICAicGF1c2VtYW5hZ2VyIiwKICAgICAgICAiZmFsbGluZ3JvY2siLAogICAgICAgICJwb3N0Zml4IiwKICAgICAgICAicHJlZml4IiwKICAgICAgICAidHJhbnNwaWxlciIKICAgIF0sCiAgICAiaWdub3JlRmllbGQiOlsKICAgICAgICAiaW5jb250cm9sIiwKICAgICAgICAiZW51bSIsCiAgICAgICAgIm9wdGlvbmFsIiwKICAgICAgICAiX18iCiAgICBdLAogICAgIi8vIjoi5Lul5LiK5Li66buY6K6k5b+955Wl5YiX6KGo77yM6buY6K6k5YyF5ZCr5YWo6YOo55qEVW5pdHnlhbPplK7mlrnms5XvvIzlu7rorq7kuI3opoHkv67mlLnvvIzku6XkuIvkuLroh6rlrprkuYnlv73nlaXliJfooajvvIzlj6/ku6XmoLnmja7pnIDopoHoh6rooYzmt7vliqAo5aaC5p6c6ZyA6KaB55So5Yiw5Y+N5bCE5oiW6ICF5Yqo5oCB6LCD55So55qE5pa55rOV77yM5bu66K6u5re75Yqg5Yiw6L+Z6YeMKSkiLAoKICAgICIvLyI6IuWFs+S6juWmguS9leaYr+S9v+eUqOiHquWumuS5ieW/veeVpeWIl+ihqO+8jOi/memHjOacieWHoOeCueW7uuiuriIsCiAgICAiLy8iOiIxLuWcqFVuaXR55Lit77yMR2FtZU9iamVjdOaIluiAhXByZWZhYnPliJ3lp4vnu5HlrprkuobohJrmnKzvvIzliJnor6XohJrmnKznmoTnsbvlkI3kuI3lj6/mt7fmt4bvvIzmlrnms5XlkI3lkozlrZfmrrXlkI3lj6/ku6Xmt7fmt4YiLAogICAgIi8vIjoiMi7lnKhVbml0eeS4re+8jEdhbWVPYmplY3TmiJbogIVwcmVmYWJz5Yid5aeL5rKh5pyJ57uR5a6a6ISa5pys77yM5L2G5piv5Zyo5Luj56CB5Lit5Yqo5oCB5re75Yqg5LqG6ISa5pys77yM5YiZ6K+l6ISa5pys55qE57G75ZCN44CB5pa55rOV5ZCN5ZKM5a2X5q615ZCN6YO95Y+v5Lul5re35reGIiwKICAgICIvLyI6IjMu5aaC5p6c6K+l6ISa5pys5Lit5raJ5Y+K5Yiw5LqGVUnnmoTkuovku7blk43lupQo5aaCQnV0dG9uLk9uQ2xpY2spLOWImeivpeiEmuacrOeahOexu+WQjeWSjOivpeaWueazleWQjemDveS4jeWPr+a3t+a3hizlrZfmrrXlkI3lj6/ku6Xmt7fmt4YiLAogICAgIi8vIjoiNC5Vbml0eeeahOeUn+WRveWRqOacn+aWueazleWSjOWbnuiwg+aWueazleS4jeiDvea3t+a3hizkuIrmlrnnmoTlv73nlaXliJfooajljIXlkKvkuoblpKflpJrmlbDluLjnlKjnmoTnlJ/lkb3lkajmnJ/lkozlm57osIPmlrnms5XvvIzlpoLmnpzmnInpgZfmvI/vvIzlj6/ku6Xoh6rooYzmt7vliqAiLAogICAgIi8vIjoiNS5Vbml0eeS4reeahEludm9rZeetieeJueauiuaWueazleaJgOiwg+eUqOeahOWHveaVsOaWueazleS4jeWPr+a3t+a3hizlkIznkIbljY/nqIvnsbvnmoTmlrnms5XkuZ/kuI3lj6/mt7fmt4Ys6K+36Ieq6KGM5re75Yqg5Yiw6Ieq5a6a5LmJ5b+955Wl5YiX6KGoIiwKICAgICIvLyI6IjYu6YOo5YiG5raJ5Y+K5Y+N5bCE57G755qE5Luj56CB5LiN6IO95re35reGLOWmglN5c3RlbS5SZWZsZWN0aW9uKEdldEZpZWxkLEdldE1ldGhvZCxJbnZva2XnrYkpLOivt+iHquihjOa3u+WKoOWIsOiHquWumuS5ieW/veeVpeWIl+ihqCIsCiAgICAiLy8iOiI3Lk5hdGl2ZeWxgumHjOebtOaOpeiwg+eUqEMj5oiW6YCa6L+HVW5pdHnlhoXnva5BUEnlj5HpgIHkuovku7bliLBDI+eahOexu+WSjOaWueazleS4jeWPr+a3t+a3hijlpKflpJrmlbDlnKjnp7vliqjlubPlj7DkuK0pIiwKICAgICIvLyI6Ijgu5LiA5Lqb54m55q6K5o+S5Lu25a+55bqU55qE6ISa5pys5LiN5Y+v5re35reG77yM5L6L5aaCeEx1YeWSjOS4juS5i+e7keWumueahEMj6ISa5pysIiwKCiAgICAKICAgICIvLyI6IuWvueS6juaWueazleWQjeeahOa3t+a3humHh+eUqOeahOaYr+eZveWQjeWNleaooeW8j++8jOWNs+m7mOiupOa3t+a3hu+8jOWmguaenOS4jemcgOimgea3t+a3hu+8jOWPr+S7pea3u+WKoOWIsOi/memHjCIsCiAgICAiY3VzdG9taWdub3JlTWV0aG9kIjpbCiAgICBdLAogICAgIi8vIjoi5a+55LqO5a2X5q615ZCN55qE5re35reG6YeH55So55qE5piv55m95ZCN5Y2V5qih5byP77yM5Y2z6buY6K6k5re35reG77yM5aaC5p6c5LiN6ZyA6KaB5re35reG77yM5Y+v5Lul5re75Yqg5Yiw6L+Z6YeMIiwKICAgICJjdXN0b21pZ25vcmVGaWVsZCI6WwogICAgXSwKICAgICIvLyI6IuWvueS6juexu+WQjeeahOa3t+a3humHh+eUqOeahOaYr+m7keWQjeWNleaooeW8j++8jOWNs+m7mOiupOS4jea3t+a3hu+8jOWmguaenOmcgOimgea3t+a3hu+8jOWPr+S7pea3u+WKoOWIsOi/memHjCIsCiAgICAiY3VzdG9taWdub3JlQ2xhc3MiOlsKICAgIF0KfQ=="; + } +} diff --git a/O&Z_Obfuscator/Program.cs b/O&Z_Obfuscator/Program.cs index 36c7140..1de5e04 100644 --- a/O&Z_Obfuscator/Program.cs +++ b/O&Z_Obfuscator/Program.cs @@ -15,6 +15,12 @@ class Program { static void Main(string[] args) { + AssemblyLoader loader = new AssemblyLoader("C:\\Users\\22864\\Desktop\\END_AUTO V2\\END_Data\\Managed\\Assembly-CSharp.dll.bak"); + ObfusFunc obfusFunc = new ObfusFunc(loader.Module); + obfusFunc.Excute(); + loader.Save(); + Console.ReadKey(); + /* AssemblyLoader loader; if (args.Length > 0) { @@ -61,6 +67,7 @@ static void Main(string[] args) Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } + */ } void printfinstr(ModuleDefMD Module) { diff --git a/O&Z_Obfuscator/README.md b/O&Z_Obfuscator/README.md index 414e884..8aebdd5 100644 --- a/O&Z_Obfuscator/README.md +++ b/O&Z_Obfuscator/README.md @@ -10,11 +10,7 @@ O&Z_IL2CPP_Security.exe input MonoObfus ~~~ 3. Enjoy Safe! xD -4. ~~您也可以直接使用命令行来操作加密你的NET程序集(*不仅是Unity Script,而是任何NET程序集!*)~~ - - (此功能已删除,目前已经将主程序合并到O&Z_IL2CPP_Security.exe中) - -  +4. 如果你想使用ObfusFunc参数来获取更加强大的混淆,请仔细阅 **读加密参数说明-ObfusFunc** 中的条例 ## 加密参数说明 - ControlFlow(控制流程加密) @@ -37,4 +33,27 @@ 使用本方法加密您游戏内的字符串常量,每一个字符串都单独对应一个单独和密码和单独的解密函数,使破解难度上升  - + - ObfusFunc(类&方法&字段混淆) + + 使用本方法加密您项目中所有的函数,类,甚至是参数,使程序的不可读性达到最高(我们采用了Unity函数名堆积作为字典,使得这种方法混淆的函数难以被反混淆器识别为Obfuscated或JunkFunc) + +  + ### 使用方法以及注意事项 + 1. 您需要配置 **keyfunc.json**,来完成本程序对于您项目的适配 +  + 2. 在配置keyfunc.json中,我们已经预先配置好了Unity中的大部分生命周期函数以及关键回调,这些都将会作为skip的部分跳过混淆 + 3. 我们为您提供了三种可以自定义的部分,用于适配您的程序 + - 忽略的方法(customignoreMethod): **此项采用白名单的模式**,如果您不需要混淆某个方法或者某个方法不能被混淆(例如使用了反射),可以将方法名称添加到这里 + - 忽略的字段(customignoreField): **此项采用白名单的模式**,如果您不需要混淆某个字段或者某个字段不能被混淆(例如使用了反射),可以将字段名称添加到这里 + - 需要混淆的类(customignoreClass): **此项采用白名单的模式**,因为涉及到Unity预制体的影响,类名一般来说不能够轻易混淆(*详细原因见下方*),如果你需要混淆某个类名,可以将类名添加到这里 + 4. **需要注意的事项** + - 在Unity中,GameObject或者prefabs初始绑定了脚本,则该脚本的类名不可混淆,方法名和字段名可以混淆 + - 在Unity中,GameObject或者prefabs初始没有绑定脚本,但是在代码中动态添加了脚本,则该脚本的类名、方法名和字段名都可以混淆 + - 如果该脚本中涉及到了UI的事件响应(如Button.OnClick),则该脚本的类名和该方法名都不可混淆,字段名可以混淆 + - Unity的生命周期方法和回调方法不能混淆,上方的忽略列表包含了大多数常用的生命周期和回调方法,如果有遗漏,可以自行添加 + - Unity中的Invoke等特殊方法所调用的函数方法不可混淆,同理协程类的方法也不可混淆,请自行添加到自定义忽略列表 + - 部分涉及反射类的代码不能混淆,如System.Reflection(GetField,GetMethod,Invoke等),请自行添加到自定义忽略列表 + - Native层里直接调用C#或通过Unity内置API发送事件到C#的类和方法不可混淆(大多数在移动平台中) + - 一些特殊插件对应的脚本不可混淆,例如xLua和与之绑定的C#脚本 + - 你可以将一些关键的方法(例如涉及到*游戏内购,广告的接入,游戏全局管理控制,游戏资源的管理,游戏本地化保存,与服务器云交互*等等)写到一个不涉及Unity预制体或者UI事件等情况的专用的脚本中,并对该脚本的类进行混淆 + 5. 正确的配置好keyfunc,可以最大程度为您的游戏带来安全,谢谢您的使用!如果有任何问题,欢迎联系作者QQ,添加讨论群或者在issue提出 diff --git a/O&Z_Obfuscator/img/config.png b/O&Z_Obfuscator/img/config.png index 8d272cf..2b8486d 100644 Binary files a/O&Z_Obfuscator/img/config.png and b/O&Z_Obfuscator/img/config.png differ diff --git a/O&Z_Obfuscator/img/funcobfus.png b/O&Z_Obfuscator/img/funcobfus.png new file mode 100644 index 0000000..b66e39e Binary files /dev/null and b/O&Z_Obfuscator/img/funcobfus.png differ diff --git a/O&Z_Obfuscator/img/keyfunc.png b/O&Z_Obfuscator/img/keyfunc.png new file mode 100644 index 0000000..1a8f3f4 Binary files /dev/null and b/O&Z_Obfuscator/img/keyfunc.png differ diff --git a/O&Z_Obfuscator/utils.cs b/O&Z_Obfuscator/utils.cs index 9a0b886..a8d7ada 100644 --- a/O&Z_Obfuscator/utils.cs +++ b/O&Z_Obfuscator/utils.cs @@ -8,7 +8,7 @@ using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; - +using O_Z_IL2CPP_Security.LitJson; namespace OZ_Obfus { public static class Extensions @@ -211,7 +211,6 @@ public static string GenertateRandomFuncName() { return FuncNames[RandomGenerator.Generate(FuncNames.Length)]; } - public static string[] FuncNames = { "Awake","Start","Updata","FixedUpdata", @@ -225,9 +224,11 @@ public static string GenertateRandomFuncName() "OnGUI","OnJointBreak","OnLevelWasLoaded","OnMouseDown","OnMouseDrag","OnMouseEnter", "OnMouseExit","OnMouseOver","OnMouseUp","OnPostRender","OnPreCull","OnPreRender", "OnRenderImage","OnRenderObject","OnSerializeNetworkView","OnServerInitialized", - "OnTriggerEnter","OnTriggerExit","OnTriggerStay" + "OnTriggerEnter","OnTriggerExit","OnTriggerStay","Reset","OnTransformParentChanged", + "OnPreCull","OnJointBreak","OnApplicationQuit","OnDestory","OnDisable","OnAnimatorIK", + "OnAnimatorMove","OnApplicationQuit","OnEnable","OnParticleTrigger","OnParticleUpdateJobScheduled", + "OnPlayerConnected","OnPostRender","__" }; - public const string ERROR = ";̥͓̠̙̠̺̫̱̹̮͈͈͓͍̟̻͆ͧ͒ͩͨ̉ͯ̂̈̉̽̉͑̔̊́͟͜;̢̧͔͓͉̝̆̒ͣͣ̄ͣ̊̈́̎̓͛̇͆ͯͪ̿͟;ͫͭ͒̉̐͑̀҉̭̭͕̟͇̰̺͖͎̗̰̩͉;̸̛̘̬̫̫͔̜͙̣̯̠̯̻͍̰͍̥͓ͦ̎ͯͯ͂ͤ̉̃̊͐̐̽͜;̵̧̂͐̉̆́̚̚҉̜̦̳͇͍;̙͈̞̪̖͚̬͍͙̹ͭ̿͒ͧͧͨ̀;͐̇̋̍̿̎̀͌ͣ͌҉ ̞̙̘̱͟͠_̍̽̋̑͒ͧ̌͐̿͞͡҉̯̣̥̹̗̫̥̩͈̘͟ͅͅ_̈͛̈͊̈́ͥͬ̌ͪ̃̽͑̓͋͛̆̈͋̽҉̸̛̠̝̜͈̮͢_͒͂̋̈́͋̉͒ͦ̊ͯ̐̾̂̐҉҉̧̯̜̣̮̦̱̦̖̗͡_̧̨̹̳̘̯̱͖͙̘̍ͥ͊͌̌ͧͥ̍ͨ̐͡_̵̺̮̞̖̰͔̮̺̳͖̳̳̥͖͖͊͐͛ͥͪ͛͑͠ͅ_ͧ̓ ̴̡̪͎̣̘̳̤̬͔̟̺̳̻̥͇ͧͫ̽͐̄ͤ̎̔_̸̠̪̺͕̩̮̹̦͇̫͙͖̦̻̏̈́̅ͦ͐_̴̸̢͚̤͙͓̱̬̫̝̞̣̥̽͛͊ͥͬ̍͆ͨ͑͋̍͊ͭ͗́ͅ^̵͖̖̹̦͎̦̜͋̉͋͐̈́ͪ̋̊̄́͘͟ ̨͚͙͖̫͚̙̊̏̍̐ͥ̅̏̎͆͗ͧ́̚͞!̧͕͈͕͙̱̟̆ͭ͋ͫ̕͢͞;̛̣̭̖̹̜̘̮̜̭͓̰̫͙͋̏ͯͤ̂ͬ͗ͥ̌ͥ̓ͮͪ͗́͞ͅ;̪̳̼̱̽ͨ͋͛̔ͪͬ̃͌̂̌͐̀ͧͬ̾ͨ̚̚;̛͍̘̗̣͉͓̘͖͙̪͙̦͇̩͈ͩ͋̄̓ͣ́̃ͦͫ͒̑͋̃ͣͥ̋̀;̢͚̰͈͍ͮͤͣ͂̆͋ͨ̀̐̕͞͞ͅ;̨̢̬̹̯̯̤͕͍̺̩̫͈͉̙̪̪̜̻͚̂͋̏̓͛ͣ͟;̥̖̭͕͔̝͇̞̠̰͐̿̆ͣ̈͟͡;̵̸̻̫͔̼͚̤͇̝̞̬̞͚͇̓̐͆̾ͭ̈́ͫ̈́́͜͞;̌ͨ͌̐̉̂̃̅̃̋ͤͤͣͯ҉̧̹̗̺̹͈̙͇̦̣ͅ;̸̫̙͈̫̮̻͎̱͓̗̍&a_̈͛̈͊̈́ͥͬ̌ͪ̃̽͑̓͋͛̆̈͋̽҉̸̛̠̝̜͈̮͢_͒&"; diff --git a/README.md b/README.md index 26cc689..ed4da60 100644 --- a/README.md +++ b/README.md @@ -5,25 +5,21 @@ O&Z Protector 是由 **Z1029[QQ:3408708525]** **和[oRangeSumMer](https://space. ***本程序基于[Net6.0](https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0) & [NETFramework4.8](https://dotnet.microsoft.com/zh-cn/download/dotnet-framework/net48)开发,运行需要[Net6.0](https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0) & [NETFramework4.8](https://dotnet.microsoft.com/zh-cn/download/dotnet-framework/net48)环境,请确保您的PC正确安装了NET Runtime或者NET SDK*** -## >>>[O&Z-IL2CPP(Click me!)](/O%26Z_IL2CPP_Security/README.md)<<< +## >>>[O&Z-IL2CPP(Click me!)](O%26Z_IL2CPP_Security/README.md)<<< -## >>>[O&Z-MonoObfuscator(Click me!)](/O%26Z_Obfuscator/README.md)<<< +## >>>[O&Z-MonoObfuscator(Click me!)](O%26Z_Obfuscator/README.md)<<< ## What's New -1. 我们正式完成了O&Z MonoObfuscator的编写并且在此次更新中release! -2. **修复了MonoObfuscate 功能使用过程中无法对路径中含有空格的程序集使用** - - 目前实现的功能: -- 字符串加密 -- 常量预设值加密 -- 流程混淆(ControlFlow) -- 局部变量转为Feild -- . . . . ([更多](/O%26Z_IL2CPP_Security/README.md)) +1. **修复了MonoObfuscate 功能使用过程中无法对路径中含有空格的程序集使用** +2. 在MonoObfuscate功能中,我们添加了对类,方法,字段名的混淆是的代码的不可读性和破解难度上升到了最高,而且此方法可以兼容Unity(需要自定义配置keyfunc.json文件)! +  ## 预告 1. UI窗口界面即将完成! 2. 正在测试对于所有unity版本il2cpp的支持,自动生成libil2cpp -3. 我们正在编写O&ZMonoObfus的函数与方法名称的混淆 +3. ~~我们正在编写O&ZMonoObfus的函数与方法名称的混淆~~ +4. 我们准备重写Mono虚拟机,在底层对Unity Mono的JIT,AOT等进行加密 +5. 我们正在尝试对于IL2CPP生成方式中,在生成IL代码时,插入MonoObfuscate的功能,使得IL2CPP获得最佳保险 ## 未来的规划 1. 对AssetBundle资源进行加密