// Binary file format, all data is little-endian: // // [Magic string] # XATS // [Format version] # 32-bit unsigned integer, 4 bytes // [Entry count] # 32-bit unsigned integer, 4 bytes // [Java type name width] # 32-bit unsigned integer, 4 bytes // [Managed type name width] # 32-bit unsigned integer, 4 bytes // [Assembly name size] # 32-bit unsigned integer, 4 bytes // [Assembly name] # Non-null terminated assembly name // [Java-to-managed map] # Format described below, [Entry count] entries // [Managed-to-java map] # Format described below, [Entry count] entries // // Java-to-managed map format: // // [Java type name]<NUL>[Managed type table index] // // Each name is padded with <NUL> to the width specified in the [Java type name width] field above. // Names are written without the size prefix, instead they are always terminated with a nul character // to make it easier and faster to handle by the native runtime. // // Each [Managed type table index] is an unsigned 32-bit integer, 4 bytes // // // Managed-to-java map is identical to the [Java-to-managed] table above, with the exception of the index // pointing to the Java name table. // void OutputModule(BinaryWriter bw, ModuleDebugData moduleData) { if ((uint)moduleData.JavaToManagedMap.Count == InvalidJavaToManagedMappingIndex) { throw new InvalidOperationException($"Too many types in module {moduleData.ModuleName}"); } bw.Write(moduleMagicString); bw.Write(TypeMapFormatVersion); bw.Write(moduleData.JavaToManagedMap.Count); bw.Write(moduleData.JavaNameWidth); bw.Write(moduleData.ManagedNameWidth); bw.Write(moduleData.ModuleNameBytes.Length); bw.Write(moduleData.ModuleNameBytes); foreach (TypeMapDebugEntry entry in moduleData.JavaToManagedMap) { bw.Write(outputEncoding.GetBytes(entry.JavaName)); PadField(bw, entry.JavaName.Length, (int)moduleData.JavaNameWidth); TypeMapGenerator.TypeMapDebugEntry managedEntry = entry.DuplicateForJavaToManaged != null ? entry.DuplicateForJavaToManaged : entry; bw.Write(managedEntry.SkipInJavaToManaged ? InvalidJavaToManagedMappingIndex : (uint)managedEntry.ManagedIndex); } foreach (TypeMapDebugEntry entry in moduleData.ManagedToJavaMap) { bw.Write(outputEncoding.GetBytes(entry.ManagedName)); PadField(bw, entry.ManagedName.Length, (int)moduleData.ManagedNameWidth); bw.Write(entry.JavaIndex); } }
protected override void WriteSymbols(StreamWriter output) { bool haveJavaToManaged = data.JavaToManagedMap != null && data.JavaToManagedMap.Count > 0; bool haveManagedToJava = data.ManagedToJavaMap != null && data.ManagedToJavaMap.Count > 0; using (var sharedOutput = MemoryStreamPool.Shared.CreateStreamWriter(output.Encoding)) { WriteSharedBits(sharedOutput, haveJavaToManaged, haveManagedToJava); sharedOutput.Flush(); MonoAndroidHelper.CopyIfStreamChanged(sharedOutput.BaseStream, SharedIncludeFile); } if (haveJavaToManaged || haveManagedToJava) { output.Write(Indent); output.Write(".include"); output.Write(Indent); output.Write('"'); output.Write(Path.GetFileName(SharedIncludeFile)); output.WriteLine('"'); output.WriteLine(); } uint size = 0; WriteCommentLine(output, "Managed to java map: START", indent: false); WriteSection(output, $".data.rel.{ManagedToJavaSymbol}", hasStrings: false, writable: true); WriteStructureSymbol(output, ManagedToJavaSymbol, alignBits: TargetProvider.DebugTypeMapAlignBits, isGlobal: false); if (haveManagedToJava) { foreach (TypeMapGenerator.TypeMapDebugEntry entry in data.ManagedToJavaMap) { size += WritePointer(output, entry.ManagedLabel); size += WritePointer(output, entry.JavaLabel); } } WriteStructureSize(output, ManagedToJavaSymbol, size, alwaysWriteSize: true); WriteCommentLine(output, "Managed to java map: END", indent: false); output.WriteLine(); size = 0; WriteCommentLine(output, "Java to managed map: START", indent: false); WriteSection(output, $".data.rel.{JavaToManagedSymbol}", hasStrings: false, writable: true); WriteStructureSymbol(output, JavaToManagedSymbol, alignBits: TargetProvider.DebugTypeMapAlignBits, isGlobal: false); if (haveJavaToManaged) { foreach (TypeMapGenerator.TypeMapDebugEntry entry in data.JavaToManagedMap) { size += WritePointer(output, entry.JavaLabel); TypeMapGenerator.TypeMapDebugEntry managedEntry = entry.DuplicateForJavaToManaged != null ? entry.DuplicateForJavaToManaged : entry; size += WritePointer(output, managedEntry.SkipInJavaToManaged ? null : managedEntry.ManagedLabel); } } WriteStructureSize(output, JavaToManagedSymbol, size, alwaysWriteSize: true); WriteCommentLine(output, "Java to managed map: END", indent: false); output.WriteLine(); // MUST match src/monodroid/xamarin-app.hh WriteCommentLine(output, "TypeMap structure"); WriteSection(output, $".data.rel.ro.{TypeMapSymbol}", hasStrings: false, writable: true); WriteStructureSymbol(output, TypeMapSymbol, alignBits: TargetProvider.DebugTypeMapAlignBits, isGlobal: true); size = WriteStructure(output, packed: false, structureWriter: () => WriteTypeMapStruct(output)); WriteStructureSize(output, TypeMapSymbol, size); }