bool GenerateDebugNativeAssembly(bool skipJniAddNativeMethodRegistrationAttributeScan, List <TypeDefinition> javaTypes, TypeDefinitionCache cache, string outputDirectory, ApplicationConfigTaskState appConfState) { var javaToManaged = new List <TypeMapDebugEntry> (); var managedToJava = new List <TypeMapDebugEntry> (); var javaDuplicates = new Dictionary <string, List <TypeMapDebugEntry> > (StringComparer.Ordinal); foreach (TypeDefinition td in javaTypes) { UpdateApplicationConfig(td, appConfState); TypeMapDebugEntry entry = GetDebugEntry(td); HandleDebugDuplicates(javaDuplicates, entry, td, cache); javaToManaged.Add(entry); managedToJava.Add(entry); } SyncDebugDuplicates(javaDuplicates); var data = new ModuleDebugData { EntryCount = (uint)javaToManaged.Count, JavaToManagedMap = javaToManaged, ManagedToJavaMap = managedToJava, }; PrepareDebugMaps(data); GenerateNativeAssembly( (NativeAssemblerTargetProvider asmTargetProvider, bool sharedBitsWritten, bool sharedIncludeUsesAbiPrefix) => { return(new TypeMappingDebugNativeAssemblyGenerator(asmTargetProvider, data, outputDirectory, sharedBitsWritten, sharedIncludeUsesAbiPrefix)); } ); return(true); }
// 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); } }
void OutputModule(ModuleDebugData moduleData) { if (moduleData.JavaToManagedMap.Count == 0) { return; } using (var bw = MemoryStreamPool.Shared.CreateBinaryWriter()) { OutputModule(bw, moduleData); bw.Flush(); Files.CopyIfStreamChanged(bw.BaseStream, moduleData.OutputFilePath); } GeneratedBinaryTypeMaps.Add(moduleData.OutputFilePath); }
void PrepareDebugMaps(ModuleDebugData module) { module.JavaToManagedMap.Sort((TypeMapDebugEntry a, TypeMapDebugEntry b) => String.Compare(a.JavaName, b.JavaName, StringComparison.Ordinal)); module.ManagedToJavaMap.Sort((TypeMapDebugEntry a, TypeMapDebugEntry b) => String.Compare(a.ManagedName, b.ManagedName, StringComparison.Ordinal)); for (int i = 0; i < module.JavaToManagedMap.Count; i++) { module.JavaToManagedMap[i].JavaIndex = i; } for (int i = 0; i < module.ManagedToJavaMap.Count; i++) { module.ManagedToJavaMap[i].ManagedIndex = i; } }
public void AddModule(VMModule module) { if (_debugDataByModule.ContainsKey(module)) { return; } ModuleDebugData data = new ModuleDebugData { ReplacedInstructionsByFunction = new Dictionary <int, Dictionary <int, Instruction> >() }; _debugDataByModule.Add(module, data); ReplaceInstructionForAllBreakpointsInModule(module); }
// 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) { 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); bw.Write(entry.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); } }
bool GenerateDebugFiles(bool skipJniAddNativeMethodRegistrationAttributeScan, List <TypeDefinition> javaTypes, TypeDefinitionCache cache, string outputDirectory, ApplicationConfigTaskState appConfState) { var modules = new Dictionary <string, ModuleDebugData> (StringComparer.Ordinal); int maxModuleFileNameWidth = 0; int maxModuleNameWidth = 0; var javaDuplicates = new Dictionary <string, List <TypeMapDebugEntry> > (StringComparer.Ordinal); foreach (TypeDefinition td in javaTypes) { UpdateApplicationConfig(td, appConfState); string moduleName = td.Module.Assembly.Name.Name; ModuleDebugData module; if (!modules.TryGetValue(moduleName, out module)) { string outputFileName = $"{moduleName}{TypemapExtension}"; module = new ModuleDebugData { EntryCount = 0, JavaNameWidth = 0, ManagedNameWidth = 0, JavaToManagedMap = new List <TypeMapDebugEntry> (), ManagedToJavaMap = new List <TypeMapDebugEntry> (), OutputFilePath = Path.Combine(outputDirectory, outputFileName), ModuleName = moduleName, ModuleNameBytes = outputEncoding.GetBytes(moduleName), }; if (module.ModuleNameBytes.Length > maxModuleNameWidth) { maxModuleNameWidth = module.ModuleNameBytes.Length; } if (outputFileName.Length > maxModuleFileNameWidth) { maxModuleFileNameWidth = outputFileName.Length; } modules.Add(moduleName, module); } TypeMapDebugEntry entry = GetDebugEntry(td); HandleDebugDuplicates(javaDuplicates, entry, td, cache); if (entry.JavaName.Length > module.JavaNameWidth) { module.JavaNameWidth = (uint)entry.JavaName.Length + 1; } if (entry.ManagedName.Length > module.ManagedNameWidth) { module.ManagedNameWidth = (uint)entry.ManagedName.Length + 1; } module.JavaToManagedMap.Add(entry); module.ManagedToJavaMap.Add(entry); } SyncDebugDuplicates(javaDuplicates); foreach (ModuleDebugData module in modules.Values) { PrepareDebugMaps(module); } string typeMapIndexPath = Path.Combine(outputDirectory, "typemap.index"); using (var indexWriter = MemoryStreamPool.Shared.CreateBinaryWriter()) { OutputModules(modules, indexWriter, maxModuleFileNameWidth + 1); indexWriter.Flush(); Files.CopyIfStreamChanged(indexWriter.BaseStream, typeMapIndexPath); } GeneratedBinaryTypeMaps.Add(typeMapIndexPath); GenerateNativeAssembly( (NativeAssemblerTargetProvider asmTargetProvider, bool sharedBitsWritten, bool sharedIncludeUsesAbiPrefix) => { return(new TypeMappingDebugNativeAssemblyGenerator(asmTargetProvider, new ModuleDebugData(), outputDirectory, sharedBitsWritten)); } ); return(true); }