private void WriteIgnoredOpenGeneric(JitWriteContext context, MethodBase method) { WriteSignatureFromReflection(context, method); var writer = context.Writer; writer.WriteLine(" ; Open generics cannot be JIT-compiled."); }
private void DisassembleAndWriteMembers(JitWriteContext context, TypeInfo type, ImmutableArray <Type>?genericArgumentTypes = null) { if (type.IsGenericTypeDefinition) { if (TryDisassembleAndWriteMembersOfGeneric(context, type, genericArgumentTypes)) { return; } } foreach (var constructor in type.DeclaredConstructors) { DisassembleAndWriteMethod(context, constructor); } foreach (var method in type.DeclaredMethods) { if (method.IsAbstract) { continue; } DisassembleAndWriteMethod(context, method); } foreach (var nested in type.DeclaredNestedTypes) { DisassembleAndWriteMembers(context, nested, genericArgumentTypes); } }
private static void WriteSignatureFromReflection(JitWriteContext context, MethodBase method) { context.Writer.WriteLine(); var md = (ulong)method.MethodHandle.Value.ToInt64(); var signature = context.Runtime.DacLibrary.SOSDacInterface.GetMethodDescName(md); context.Writer.WriteLine(signature ?? "Unknown Method"); }
private bool TryDisassembleAndWriteMembersOfGeneric(JitWriteContext context, TypeInfo type, ImmutableArray <Type>?parentArgumentTypes = null) { if (parentArgumentTypes is not null) { var genericInstance = type.MakeGenericType(parentArgumentTypes.Value.ToArray()); DisassembleAndWriteMembers(context, genericInstance.GetTypeInfo(), parentArgumentTypes); return(true); } return(false); }
private void DisassembleAndWriteMethod(JitWriteContext context, MethodBase method) { if ((method.MethodImplementationFlags & MethodImplAttributes.Runtime) == MethodImplAttributes.Runtime) { WriteSignatureFromReflection(context, method); context.Writer.WriteLine(" ; Cannot produce JIT assembly for runtime-implemented method."); return; } if (method.DeclaringType?.IsGenericTypeDefinition ?? false) { WriteIgnoredOpenGeneric(context, method); return; } if (method.IsGenericMethodDefinition) { DisassembleAndWriteGenericMethod(context, (MethodInfo)method); return; } DisassembleAndWriteSimpleMethod(context, method); }
private void Decompile(Stream dll, TextWriter codeWriter) { using (var loadContext = new CustomAssemblyLoadContext(shouldShareAssembly: _ => true)) { var assembly = loadContext.LoadFromStream(dll); ValidateStaticConstructors(assembly); using var runtimeLease = _runtimePool.GetOrCreate(); var runtime = runtimeLease.Object; runtime.Flush(); var context = new JitWriteContext(codeWriter, runtime); WriteJitInfo(runtime.ClrInfo, codeWriter); foreach (var type in assembly.DefinedTypes) { if (type.IsNested) { continue; // it's easier to handle nested generic types recursively, so we suppress all nested for consistency } DisassembleAndWriteMembers(context, type); } } }
private void DisassembleAndWriteSimpleMethod(JitWriteContext context, MethodBase method) { var handle = method.MethodHandle; RuntimeHelpers.PrepareMethod(handle); var clrMethod = context.Runtime.GetMethodByHandle((ulong)handle.Value.ToInt64()); var regions = FindNonEmptyHotColdInfo(clrMethod); if (clrMethod is null || regions is null) { context.Runtime.Flush(); clrMethod = context.Runtime.GetMethodByHandle((ulong)handle.Value.ToInt64()); regions = FindNonEmptyHotColdInfo(clrMethod); } if (clrMethod is null || regions is null) { var address = (ulong)handle.GetFunctionPointer().ToInt64(); clrMethod = context.Runtime.GetMethodByAddress(address); regions = FindNonEmptyHotColdInfo(clrMethod); } var writer = context.Writer; if (clrMethod is not null) { writer.WriteLine(); writer.WriteLine(clrMethod.GetFullSignature()); } else { WriteSignatureFromReflection(context, method); } if (regions is null) { if (method.IsGenericMethod || (method.DeclaringType?.IsGenericType ?? false)) { writer.WriteLine(" ; Failed to find HotColdInfo for generic method (reference types?)."); return; } writer.WriteLine(" ; Failed to find HotColdRegions."); return; } var methodAddress = regions.HotStart; var methodLength = regions.HotSize; var reader = new MemoryCodeReader(new IntPtr(unchecked ((long)methodAddress)), methodLength); var decoder = Decoder.Create(MapArchitectureToBitness(context.Runtime.DataTarget.Architecture), reader); var instructions = new InstructionList(); decoder.IP = methodAddress; while (decoder.IP < (methodAddress + methodLength)) { decoder.Decode(out instructions.AllocUninitializedElement()); } var resolver = new JitAsmSymbolResolver(context.Runtime, methodAddress, methodLength); var formatter = new IntelFormatter(FormatterOptions, resolver); var output = new StringOutput(); foreach (ref var instruction in instructions) { formatter.Format(instruction, output); writer.Write(" L"); writer.Write((instruction.IP - methodAddress).ToString("x4")); writer.Write(": "); writer.WriteLine(output.ToStringAndReset()); } }
private void DisassembleAndWriteGenericMethod(JitWriteContext context, MethodInfo method) => WriteIgnoredOpenGeneric(context, method);