123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- #include "il2cpp-config.h"
- #include <vector>
- #include <map>
- #include <limits>
- #include "os/Mutex.h"
- #include "utils/StringUtils.h"
- #include "vm/Array.h"
- #include "vm/Class.h"
- #include "vm/Image.h"
- #include "vm/MetadataCache.h"
- #include "vm/Reflection.h"
- #include "vm/StackTrace.h"
- #include "vm/Type.h"
- #include "utils/HashUtils.h"
- #include "utils/Il2CppHashMap.h"
- #include "utils/MemoryMappedFile.h"
- #include "utils/StringUtils.h"
- #include "vm-utils/VmStringUtils.h"
- #include "Baselib.h"
- #include "Cpp/ReentrantLock.h"
- struct NamespaceAndNamePairHash
- {
- size_t operator()(const std::pair<const char*, const char*>& pair) const
- {
- return il2cpp::utils::HashUtils::Combine(il2cpp::utils::StringUtils::Hash(pair.first), il2cpp::utils::StringUtils::Hash(pair.second));
- }
- };
- struct NamespaceAndNamePairEquals
- {
- bool operator()(const std::pair<const char*, const char*>& p1, const std::pair<const char*, const char*>& p2) const
- {
- return !strcmp(p1.first, p2.first) && !strcmp(p1.second, p2.second);
- }
- };
- struct NamespaceAndNamePairLess
- {
- bool operator()(const std::pair<const char*, const char*>& p1, const std::pair<const char*, const char*>& p2) const
- {
- int namespaceCompare = strcmp(p1.first, p2.first);
- if (namespaceCompare < 0)
- return true;
- if (namespaceCompare > 0)
- return false;
- return strcmp(p1.second, p2.second) < 0;
- }
- };
- struct Il2CppNameToTypeHandleHashTable : public Il2CppHashMap<std::pair<const char*, const char*>, Il2CppMetadataTypeHandle, NamespaceAndNamePairHash, NamespaceAndNamePairEquals>
- {
- typedef Il2CppHashMap<std::pair<const char*, const char*>, Il2CppMetadataTypeHandle, NamespaceAndNamePairHash, NamespaceAndNamePairEquals> Base;
- Il2CppNameToTypeHandleHashTable() : Base()
- {
- }
- };
- namespace il2cpp
- {
- namespace vm
- {
- const Il2CppAssembly* Image::GetAssembly(const Il2CppImage* image)
- {
- return image->assembly;
- }
- typedef il2cpp::vm::StackFrames::const_reverse_iterator StackReverseIterator;
- static bool IsSystemType(Il2CppClass* klass)
- {
- return strcmp(klass->namespaze, "System") == 0 && strcmp(klass->name, "Type") == 0;
- }
- static bool IsSystemReflectionAssembly(Il2CppClass* klass)
- {
- return strcmp(klass->namespaze, "System.Reflection") == 0 && strcmp(klass->name, "Assembly") == 0;
- }
- static StackReverseIterator GetNextImageFromStack(StackReverseIterator first, StackReverseIterator last)
- {
- for (StackReverseIterator it = first; it != last; it++)
- {
- Il2CppClass* klass = it->method->klass;
- if (klass->image != NULL && !IsSystemType(klass) && !IsSystemReflectionAssembly(klass))
- {
- return it;
- }
- }
- return last;
- }
- const Il2CppImage* Image::GetExecutingImage()
- {
- const il2cpp::vm::StackFrames& stack = *StackTrace::GetStackFrames();
- StackReverseIterator imageIt = GetNextImageFromStack(stack.rbegin(), stack.rend());
- if (imageIt != stack.rend())
- {
- return imageIt->method->klass->image;
- }
- // Fallback to corlib if no image is found
- return const_cast<Il2CppImage*>(Image::GetCorlib());
- }
- const Il2CppImage* Image::GetCallingImage()
- {
- const il2cpp::vm::StackFrames& stack = *StackTrace::GetStackFrames();
- StackReverseIterator imageIt = GetNextImageFromStack(stack.rbegin(), stack.rend());
- if (imageIt != stack.rend())
- {
- imageIt = GetNextImageFromStack(++imageIt, stack.rend());
- if (imageIt != stack.rend())
- {
- return imageIt->method->klass->image;
- }
- }
- // Fallback to corlib if no image is found
- return const_cast<Il2CppImage*>(Image::GetCorlib());
- }
- const char * Image::GetName(const Il2CppImage* image)
- {
- return image->name;
- }
- const char * Image::GetFileName(const Il2CppImage* image)
- {
- return image->name;
- }
- const MethodInfo* Image::GetEntryPoint(const Il2CppImage* image)
- {
- return MetadataCache::GetAssemblyEntryPoint(image);
- }
- Il2CppImage* Image::GetCorlib()
- {
- return il2cpp_defaults.corlib;
- }
- static baselib::ReentrantLock s_ClassFromNameMutex;
- static void AddNestedTypesToNametoClassHashTable(Il2CppNameToTypeHandleHashTable* hashTable, const char *namespaze, const std::string& parentName, Il2CppMetadataTypeHandle handle)
- {
- std::pair<const char*, const char*> namespaceAndName = MetadataCache::GetTypeNamespaceAndName(handle);
- std::string name = parentName + "/" + namespaceAndName.second;
- char *pName = (char*)IL2CPP_CALLOC(name.size() + 1, sizeof(char));
- strcpy(pName, name.c_str());
- hashTable->insert(std::make_pair(std::make_pair(namespaze, (const char*)pName), handle));
- void *iter = NULL;
- while (Il2CppMetadataTypeHandle nestedClass = MetadataCache::GetNestedTypes(handle, &iter))
- AddNestedTypesToNametoClassHashTable(hashTable, namespaze, name, nestedClass);
- }
- static void AddNestedTypesToNametoClassHashTable(const Il2CppImage* image, Il2CppMetadataTypeHandle handle)
- {
- std::pair<const char*, const char*> namespaceAndName = MetadataCache::GetTypeNamespaceAndName(handle);
- void *iter = NULL;
- while (Il2CppMetadataTypeHandle nestedClass = MetadataCache::GetNestedTypes(handle, &iter))
- {
- AddNestedTypesToNametoClassHashTable(image->nameToClassHashTable, namespaceAndName.first, namespaceAndName.second, nestedClass);
- }
- }
- // This must be called when the s_ClassFromNameMutex is held.
- static void AddTypeToNametoClassHashTable(const Il2CppImage* image, Il2CppMetadataTypeHandle typeHandle)
- {
- if (typeHandle == NULL)
- return;
- // don't add nested types
- if (MetadataCache::TypeIsNested(typeHandle))
- return;
- if (image != il2cpp_defaults.corlib)
- AddNestedTypesToNametoClassHashTable(image, typeHandle);
- image->nameToClassHashTable->insert(std::make_pair(MetadataCache::GetTypeNamespaceAndName(typeHandle), typeHandle));
- }
- void Image::InitNestedTypes(const Il2CppImage *image)
- {
- for (uint32_t index = 0; index < image->typeCount; index++)
- {
- Il2CppMetadataTypeHandle handle = MetadataCache::GetAssemblyTypeHandle(image, index);
- // don't add nested types
- if (MetadataCache::TypeIsNested(handle))
- return;
- AddNestedTypesToNametoClassHashTable(image, handle);
- }
- for (uint32_t index = 0; index < image->exportedTypeCount; index++)
- {
- Il2CppMetadataTypeHandle handle = MetadataCache::GetAssemblyExportedTypeHandle(image, index);
- // don't add nested types
- if (MetadataCache::TypeIsNested(handle))
- return;
- AddNestedTypesToNametoClassHashTable(image, handle);
- }
- }
- Il2CppClass* Image::ClassFromName(const Il2CppImage* image, const char* namespaze, const char *name)
- {
- if (!image->nameToClassHashTable)
- {
- os::FastAutoLock lock(&s_ClassFromNameMutex);
- if (!image->nameToClassHashTable)
- {
- image->nameToClassHashTable = new Il2CppNameToTypeHandleHashTable();
- for (uint32_t index = 0; index < image->typeCount; index++)
- {
- AddTypeToNametoClassHashTable(image, MetadataCache::GetAssemblyTypeHandle(image, index));
- }
- for (uint32_t index = 0; index < image->exportedTypeCount; index++)
- {
- AddTypeToNametoClassHashTable(image, MetadataCache::GetAssemblyExportedTypeHandle(image, index));
- }
- }
- }
- Il2CppNameToTypeHandleHashTable::const_iterator iter = image->nameToClassHashTable->find(std::make_pair(namespaze, name));
- if (iter != image->nameToClassHashTable->end())
- return MetadataCache::GetTypeInfoFromHandle(iter->second);
- return NULL;
- }
- static bool IsExported(const Il2CppClass* type)
- {
- if ((type->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_PUBLIC)
- {
- return true;
- }
- if ((type->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC)
- {
- IL2CPP_ASSERT(type->declaringType);
- return IsExported(type->declaringType);
- }
- return false;
- }
- void Image::GetTypes(const Il2CppImage* image, bool exportedOnly, TypeVector* target)
- {
- uint32_t typeCount = Image::GetNumTypes(image);
- target->reserve(typeCount);
- for (uint32_t sourceIndex = 0; sourceIndex < typeCount; sourceIndex++)
- {
- const Il2CppClass* type = Image::GetType(image, sourceIndex);
- if (strcmp(type->name, "<Module>") == 0)
- {
- continue;
- }
- if (exportedOnly && !IsExported(type))
- {
- continue;
- }
- target->push_back(type);
- }
- }
- Il2CppArray* Image::GetTypes(const Il2CppImage* image, bool exportedOnly)
- {
- TypeVector types;
- GetTypes(image, exportedOnly, &types);
- Il2CppArray* result = Array::New(il2cpp_defaults.monotype_class, (il2cpp_array_size_t)types.size());
- size_t index = 0;
- for (vm::TypeVector::const_iterator type = types.begin(); type != types.end(); ++type)
- {
- Il2CppReflectionType* reflectionType = Reflection::GetTypeObject(&(*type)->byval_arg);
- il2cpp_array_setref(result, index, reflectionType);
- index++;
- }
- return result;
- }
- uint32_t Image::GetNumTypes(const Il2CppImage* image)
- {
- return image->typeCount;
- }
- const Il2CppClass* Image::GetType(const Il2CppImage* image, AssemblyTypeIndex index)
- {
- IL2CPP_ASSERT(index <= std::numeric_limits<AssemblyTypeIndex>::max());
- return MetadataCache::GetTypeInfoFromHandle(MetadataCache::GetAssemblyTypeHandle(image, index));
- }
- static bool StringsMatch(const char* left, const char* right, bool ignoreCase)
- {
- if (!ignoreCase)
- {
- return strcmp(left, right) == 0;
- }
- else
- {
- utils::VmStringUtils::CaseInsensitiveComparer comparer;
- return comparer(left, right);
- }
- }
- static bool ClassMatches(Il2CppMetadataTypeHandle typeHandle, const char* namespaze, bool ignoreCase, const char* name)
- {
- if (MetadataCache::TypeIsNested(typeHandle))
- return false;
- std::pair<const char*, const char*> namespaceAndName = MetadataCache::GetTypeNamespaceAndName(typeHandle);
- return StringsMatch(name, namespaceAndName.second, ignoreCase) && StringsMatch(namespaze, namespaceAndName.first, ignoreCase);
- }
- static Il2CppClass* FindClassMatching(const Il2CppImage* image, const char* namespaze, const char *name, bool ignoreCase)
- {
- for (uint32_t i = 0; i < image->typeCount; i++)
- {
- Il2CppMetadataTypeHandle typeHandle = MetadataCache::GetAssemblyTypeHandle(image, i);
- if (ClassMatches(typeHandle, namespaze, ignoreCase, name))
- return MetadataCache::GetTypeInfoFromHandle(typeHandle);
- }
- return NULL;
- }
- static Il2CppClass* FindExportedClassMatching(const Il2CppImage* image, const char* namespaze, const char *name, bool ignoreCase)
- {
- for (uint32_t i = 0; i < image->exportedTypeCount; i++)
- {
- Il2CppMetadataTypeHandle typeHandle = MetadataCache::GetAssemblyExportedTypeHandle(image, i);
- if (ClassMatches(typeHandle, namespaze, ignoreCase, name))
- return MetadataCache::GetTypeInfoFromHandle(typeHandle);
- }
- return NULL;
- }
- static Il2CppClass* FindNestedType(Il2CppClass* klass, const char* name, bool ignoreCase)
- {
- void* iter = NULL;
- while (Il2CppClass* nestedType = Class::GetNestedTypes(klass, &iter))
- {
- if (StringsMatch(name, nestedType->name, ignoreCase))
- return nestedType;
- }
- return NULL;
- }
- Il2CppClass* Image::FromTypeNameParseInfo(const Il2CppImage* image, const TypeNameParseInfo &info, bool ignoreCase)
- {
- const char* ns = info.ns().c_str();
- const char* name = info.name().c_str();
- Il2CppClass *parent_class = FindClassMatching(image, ns, name, ignoreCase);
- if (parent_class == NULL)
- {
- parent_class = FindExportedClassMatching(image, ns, name, ignoreCase);
- if (parent_class == NULL)
- return NULL;
- }
- std::vector<std::string>::const_iterator it = info.nested().begin();
- while (it != info.nested().end())
- {
- parent_class = FindNestedType(parent_class, (*it).c_str(), ignoreCase);
- if (parent_class == NULL)
- return NULL;
- ++it;
- }
- return parent_class;
- }
- static baselib::ReentrantLock s_Mutex;
- static std::vector<Image::EmbeddedResourceData> s_CachedResourceData;
- static std::map<Il2CppReflectionAssembly*, void*> s_CachedMemoryMappedResourceFiles;
- void Image::CacheMemoryMappedResourceFile(Il2CppReflectionAssembly* assembly, void* memoryMappedFile)
- {
- os::FastAutoLock lock(&s_Mutex);
- s_CachedMemoryMappedResourceFiles[assembly] = memoryMappedFile;
- }
- void* Image::GetCachedMemoryMappedResourceFile(Il2CppReflectionAssembly* assembly)
- {
- os::FastAutoLock lock(&s_Mutex);
- std::map<Il2CppReflectionAssembly*, void*>::iterator entry = s_CachedMemoryMappedResourceFiles.find(assembly);
- if (entry != s_CachedMemoryMappedResourceFiles.end())
- return entry->second;
- return NULL;
- }
- void Image::CacheResourceData(EmbeddedResourceRecord record, void* data)
- {
- os::FastAutoLock lock(&s_Mutex);
- s_CachedResourceData.push_back(EmbeddedResourceData(record, data));
- }
- void* Image::GetCachedResourceData(const Il2CppImage* image, const std::string& name)
- {
- os::FastAutoLock lock(&s_Mutex);
- for (std::vector<EmbeddedResourceData>::iterator it = s_CachedResourceData.begin(); it != s_CachedResourceData.end(); ++it)
- {
- if (it->record.image == image && it->record.name == name)
- return it->data;
- }
- return NULL;
- }
- void Image::ClearCachedResourceData()
- {
- os::FastAutoLock lock(&s_Mutex);
- for (std::map<Il2CppReflectionAssembly*, void*>::iterator i = s_CachedMemoryMappedResourceFiles.begin(); i != s_CachedMemoryMappedResourceFiles.end(); ++i)
- utils::MemoryMappedFile::Unmap(i->second);
- s_CachedMemoryMappedResourceFiles.clear();
- s_CachedResourceData.clear();
- }
- } /* namespace vm */
- } /* namespace il2cpp */
|