List <TypeMapJava> LoadJavaTypes(string filePath) { ulong javaTypeCount = (ulong)ELF.GetUInt32(JavaTypeCountSymbolName); ulong javaNameWidth = (ulong)ELF.GetUInt32(JavaNameWidthSymbolName); // MUST be kept in sync with: src/monodroid/jni/xamarin-app.hh (struct TypeMapModule) ulong size = 0; size += GetPaddedSize <uint> (size); // module_index size += GetPaddedSize <uint> (size); // type_token_id size += javaNameWidth; byte[] data = ELF.GetData(MapJavaSymbolName); if (data.Length == 0) { throw new InvalidOperationException($"{filePath} doesn't have a valid '{MapJavaSymbolName}' symbol"); } ulong calculatedJavaTypeCount = (ulong)data.LongLength / size; if (calculatedJavaTypeCount != javaTypeCount) { throw new InvalidOperationException($"{filePath} has invalid '{JavaTypeCountSymbolName}' symbol value ({javaTypeCount}), '{JavaTypeCountSymbolName}' size indicates there are {calculatedJavaTypeCount} managedToJava instead"); } var ret = new List <TypeMapJava> (); ulong offset = 0; for (ulong i = 0; i < javaTypeCount; i++) { var javaEntry = new TypeMapJava { module_index = ReadUInt32(data, ref offset, packed: true), type_token_id = ReadUInt32(data, ref offset, packed: true), }; javaEntry.java_name = ELF.GetASCIIZ(data, offset); offset += javaNameWidth; ret.Add(javaEntry); } return(ret); }
List <TypeMapModule> LoadMapModules(string filePath) { ulong moduleCount = (ulong)ELF.GetUInt32(ModuleCountSymbolName); // MUST be kept in sync with: src/monodroid/jni/xamarin-app.hh (struct TypeMapModule) ulong size; size = 16; // module_uuid size += GetPaddedSize <uint> (size); // entry_count size += GetPaddedSize <uint> (size); // duplicate_count size += GetPaddedSize <string> (size); // map (pointer) size += GetPaddedSize <string> (size); // duplicate_map (pointer) size += GetPaddedSize <string> (size); // assembly_name (pointer) size += GetPaddedSize <string> (size); // image (pointer) size += GetPaddedSize <uint> (size); // java_name_width size += GetPaddedSize <string> (size); // java_map (pointer) byte[] moduleData = ELF.GetData(MapModulesSymbolName); if (moduleData.Length == 0) { throw new InvalidOperationException($"{filePath} doesn't have a valid '{MapModulesSymbolName}' symbol"); } ulong calculatedModuleCount = (ulong)moduleData.Length / size; if (calculatedModuleCount != moduleCount) { throw new InvalidOperationException($"{filePath} has invalid '{ModuleCountSymbolName}' symbol value ({moduleCount}), '{MapModulesSymbolName}' size indicates there are {calculatedModuleCount} managedToJava instead"); } var ret = new List <TypeMapModule> (); ulong offset = 0; for (ulong i = 0; i < moduleCount; i++) { Log.Debug($"Module {i + 1}"); var module = new TypeMapModule(); byte[] mvid = new byte[16]; Array.Copy(moduleData, (int)offset, mvid, 0, mvid.Length); module.module_uuid = new Guid(mvid); offset += (ulong)mvid.Length; Log.Debug($" module_uuid == {module.module_uuid}"); module.entry_count = ReadUInt32(moduleData, ref offset); Log.Debug($" entry_count == {module.entry_count}"); module.duplicate_count = ReadUInt32(moduleData, ref offset); Log.Debug($" duplicate_count == {module.duplicate_count}"); // MUST be kept in sync with: src/monodroid/jni/xamarin-app.hh (struct TypeMapModuleEntry) ulong pointer = ReadPointer(moduleData, ref offset); size = 0; size += GetPaddedSize <uint> (size); // type_token_id size += GetPaddedSize <uint> (size); // java_map_index ulong mapSize = size * module.entry_count; byte[] data = ELF.GetData(pointer, mapSize); module.map = new List <TypeMapModuleEntry> (); ReadMapEntries(module.map, data, module.entry_count); // MUST be kept in sync with: src/monodroid/jni/xamarin-app.hh (struct TypeMapModuleEntry) pointer = ReadPointer(moduleData, ref offset); if (pointer != 0) { mapSize = size * module.duplicate_count; data = ELF.GetData(pointer, mapSize); module.duplicate_map = new List <TypeMapModuleEntry> (); ReadMapEntries(module.duplicate_map, data, module.duplicate_count); } pointer = ReadPointer(moduleData, ref offset); module.assembly_name = ELF.GetASCIIZ(pointer); Log.Debug($" assembly_name == {module.assembly_name}"); Log.Debug(""); // Read the values to properly adjust the offset taking padding into account ReadPointer(moduleData, ref offset); ReadUInt32(moduleData, ref offset); ReadPointer(moduleData, ref offset); ret.Add(module); } return(ret); void ReadMapEntries(List <TypeMapModuleEntry> map, byte[] inputData, uint entryCount) { ulong mapOffset = 0; for (uint i = 0; i < entryCount; i++) { var entry = new TypeMapModuleEntry { type_token_id = ReadUInt32(inputData, ref mapOffset), java_map_index = ReadUInt32(inputData, ref mapOffset) }; map.Add(entry); } } }