// Add a range of local variables to a local signature encoder internal static void AddRange(this LocalVariablesEncoder sig, IEnumerable <LocalVariableInfo> localVariables, IAssemblyMetadata metadata) { foreach (var v in localVariables) { Add(sig, v, metadata); } }
// Add a local variable to a local variable signature encoder internal static void Add(this LocalVariablesEncoder sig, LocalVariableInfo localVariableInfo, IAssemblyMetadata metadata) { if (localVariableInfo.LocalType.IsByRef) { sig.AddVariable().Type( true, localVariableInfo.IsPinned) .FromSystemType(localVariableInfo.LocalType.GetElementType(), metadata); } else { sig.AddVariable().Type( false, localVariableInfo.IsPinned) .FromSystemType(localVariableInfo.LocalType, metadata); } }
/// <summary> /// Extracts the method signature from the metadata by rid /// </summary> public ReadyToRunMethod( ReadyToRunReader readyToRunReader, IAssemblyMetadata componentReader, EntityHandle methodHandle, int entryPointId, string owningType, string constrainedType, string[] instanceArgs, int?fixupOffset) { InstanceArgs = (string[])instanceArgs?.Clone(); _readyToRunReader = readyToRunReader; _fixupOffset = fixupOffset; MethodHandle = methodHandle; EntryPointRuntimeFunctionId = entryPointId; ComponentReader = componentReader; EntityHandle owningTypeHandle; GenericParameterHandleCollection genericParams = default(GenericParameterHandleCollection); DisassemblingGenericContext genericContext = new DisassemblingGenericContext(typeParameters: Array.Empty <string>(), methodParameters: instanceArgs); DisassemblingTypeProvider typeProvider = new DisassemblingTypeProvider(); // get the method signature from the method handle switch (MethodHandle.Kind) { case HandleKind.MethodDefinition: { MethodDefinition methodDef = ComponentReader.MetadataReader.GetMethodDefinition((MethodDefinitionHandle)MethodHandle); if (methodDef.RelativeVirtualAddress != 0) { MethodBodyBlock mbb = ComponentReader.ImageReader.GetMethodBody(methodDef.RelativeVirtualAddress); if (!mbb.LocalSignature.IsNil) { StandaloneSignature ss = ComponentReader.MetadataReader.GetStandaloneSignature(mbb.LocalSignature); LocalSignature = ss.DecodeLocalSignature(typeProvider, genericContext); } } Name = ComponentReader.MetadataReader.GetString(methodDef.Name); Signature = methodDef.DecodeSignature <string, DisassemblingGenericContext>(typeProvider, genericContext); owningTypeHandle = methodDef.GetDeclaringType(); genericParams = methodDef.GetGenericParameters(); } break; case HandleKind.MemberReference: { MemberReference memberRef = ComponentReader.MetadataReader.GetMemberReference((MemberReferenceHandle)MethodHandle); Name = ComponentReader.MetadataReader.GetString(memberRef.Name); Signature = memberRef.DecodeMethodSignature <string, DisassemblingGenericContext>(typeProvider, genericContext); owningTypeHandle = memberRef.Parent; } break; default: throw new NotImplementedException(); } if (owningType != null) { DeclaringType = owningType; } else { DeclaringType = MetadataNameFormatter.FormatHandle(ComponentReader.MetadataReader, owningTypeHandle); } StringBuilder sb = new StringBuilder(); sb.Append(Signature.ReturnType); sb.Append(" "); sb.Append(DeclaringType); sb.Append("."); sb.Append(Name); if (Signature.GenericParameterCount != 0) { sb.Append("<"); for (int i = 0; i < Signature.GenericParameterCount; i++) { if (i > 0) { sb.Append(", "); } if (instanceArgs != null && instanceArgs.Length > i) { sb.Append(instanceArgs[i]); } else { sb.Append("!"); sb.Append(i); } } sb.Append(">"); } sb.Append("("); for (int i = 0; i < Signature.ParameterTypes.Length; i++) { if (i > 0) { sb.Append(", "); } sb.AppendFormat($"{Signature.ParameterTypes[i]}"); } sb.Append(")"); SignatureString = sb.ToString(); }
internal static void FromSystemType(this SignatureTypeEncoder typeEncoder, Type type, IAssemblyMetadata metadata) { if (type.IsByRef) { throw new ArgumentException("ByRef types should be handled by parameter encoder or return type encoder"); } else if (type.IsPointer) { typeEncoder.Pointer().FromSystemType(type.GetElementType(), metadata); } else if (type.IsPrimitive) { typeEncoder.PrimitiveType(GetPrimitiveTypeCode(type)); } else if (type == typeof(string)) { typeEncoder.String(); } else if (type == typeof(object)) { typeEncoder.Object(); } else if (type == typeof(void)) { throw new ArgumentException( "Void type is not allowed in SignatureTypeEncoder. Please, use FromSystemType from ReturnTypeEncoder.", nameof(type)); } else if (type.IsArray) { var elementType = type.GetElementType(); if (type.GetArrayRank() == 1) { typeEncoder.SZArray().FromSystemType(elementType, metadata); } else { typeEncoder.Array( x => x.FromSystemType(elementType, metadata), x => x.Shape( type.GetArrayRank(), ImmutableArray.Create <int>(), ImmutableArray.CreateRange <int>(Enumerable.Repeat(0, type.GetArrayRank())) // better matches metadata from C# )); } } else if (type.IsGenericType) { var genericTypeDef = type.GetGenericTypeDefinition(); var typeHandler = metadata.GetTypeHandle(genericTypeDef); var genericArguments = type.GetGenericArguments(); var inst = typeEncoder.GenericInstantiation(typeHandler, genericArguments.Length, type.IsValueType); foreach (var ga in genericArguments) { if (ga.IsGenericMethodParameter()) { inst.AddArgument().GenericMethodTypeParameter(ga.GenericParameterPosition); } else if (ga.IsGenericParameter) { inst.AddArgument().GenericTypeParameter(ga.GenericParameterPosition); } else { inst.AddArgument().FromSystemType(ga, metadata); } } } else if (type.IsGenericMethodParameter()) { typeEncoder.GenericMethodTypeParameter(type.GenericParameterPosition); } else if (type.IsGenericParameter) { typeEncoder.GenericTypeParameter(type.GenericParameterPosition); } else { var typeHandler = metadata.GetTypeHandle(type); typeEncoder.Type(typeHandler, type.IsValueType); } }
public MethodBodyStreamWriter(IAssemblyMetadata metadata) { _metadata = metadata; }
public PgoInfoKey(IAssemblyMetadata componentReader, string owningType, EntityHandle methodHandle, string[] instanceArgs) { ComponentReader = componentReader; EntityHandle owningTypeHandle; DisassemblingGenericContext genericContext = new DisassemblingGenericContext(typeParameters: Array.Empty <string>(), methodParameters: instanceArgs); DisassemblingTypeProvider typeProvider = new DisassemblingTypeProvider(); MethodHandle = methodHandle; // get the method signature from the method handle switch (MethodHandle.Kind) { case HandleKind.MethodDefinition: { MethodDefinition methodDef = componentReader.MetadataReader.GetMethodDefinition((MethodDefinitionHandle)MethodHandle); Name = componentReader.MetadataReader.GetString(methodDef.Name); Signature = methodDef.DecodeSignature <string, DisassemblingGenericContext>(typeProvider, genericContext); owningTypeHandle = methodDef.GetDeclaringType(); } break; case HandleKind.MemberReference: { MemberReference memberRef = componentReader.MetadataReader.GetMemberReference((MemberReferenceHandle)MethodHandle); Name = componentReader.MetadataReader.GetString(memberRef.Name); Signature = memberRef.DecodeMethodSignature <string, DisassemblingGenericContext>(typeProvider, genericContext); owningTypeHandle = memberRef.Parent; } break; default: throw new NotImplementedException(); } if (owningType != null) { DeclaringType = owningType; } else { DeclaringType = MetadataNameFormatter.FormatHandle(componentReader.MetadataReader, owningTypeHandle); } StringBuilder sb = new StringBuilder(); sb.Append(Signature.ReturnType); sb.Append(" "); sb.Append(DeclaringType); sb.Append("."); sb.Append(Name); if (Signature.GenericParameterCount != 0) { sb.Append("<"); for (int i = 0; i < Signature.GenericParameterCount; i++) { if (i > 0) { sb.Append(", "); } if (instanceArgs != null && instanceArgs.Length > i) { sb.Append(instanceArgs[i]); } else { sb.Append("!"); sb.Append(i); } } sb.Append(">"); } sb.Append("("); for (int i = 0; i < Signature.ParameterTypes.Length; i++) { if (i > 0) { sb.Append(", "); } sb.AppendFormat($"{Signature.ParameterTypes[i]}"); } sb.Append(")"); SignatureString = sb.ToString(); }
public static void Write(IAssemblyMetadata metadata, IReadOnlyList <Instruction> il) { for (var i = 0; i < il.Count; i++) { var opCode = il[i].OpCode; opCode.WriteOpCode(metadata.ILBuilder.WriteByte); switch (opCode.OperandType) { case OperandType.InlineNone: break; case OperandType.InlineSwitch: var branches = (int[])il[i].Operand; metadata.ILBuilder.WriteInt32(branches.Length); for (var k = 0; k < branches.Length; k++) { var branchOffset = branches[k]; metadata.ILBuilder.WriteInt32(branchOffset); } break; case OperandType.ShortInlineBrTarget: var offset8 = (sbyte)il[i].Operand; metadata.ILBuilder.WriteSByte(offset8); break; case OperandType.InlineBrTarget: var offset32 = (int)il[i].Operand; // offset convention in IL: zero is at next instruction metadata.ILBuilder.WriteInt32(offset32); break; case OperandType.ShortInlineI: if (opCode == OpCodes.Ldc_I4_S) { metadata.ILBuilder.WriteSByte((sbyte)il[i].Operand); } else { metadata.ILBuilder.WriteByte((byte)il[i].Operand); } break; case OperandType.InlineI: metadata.ILBuilder.WriteInt32((int)il[i].Operand); break; case OperandType.ShortInlineR: metadata.ILBuilder.WriteSingle((float)il[i].Operand); break; case OperandType.InlineR: metadata.ILBuilder.WriteDouble((double)il[i].Operand); break; case OperandType.InlineI8: metadata.ILBuilder.WriteInt64((long)il[i].Operand); break; case OperandType.InlineSig: metadata.ILBuilder.WriteBytes((byte[])il[i].Operand); break; case OperandType.InlineString: metadata.ILBuilder.WriteInt32( MetadataTokens.GetToken(metadata.GetOrAddUserString((string)il[i].Operand))); break; case OperandType.InlineType: case OperandType.InlineTok: case OperandType.InlineMethod: case OperandType.InlineField: switch (il[i].Operand) { case Type type: metadata.ILBuilder.WriteInt32(MetadataTokens.GetToken(metadata.GetTypeHandle(type))); break; case ConstructorInfo constructorInfo: metadata.ILBuilder.WriteInt32( MetadataTokens.GetToken(metadata.GetConstructorHandle(constructorInfo))); break; case FieldInfo fieldInfo: metadata.ILBuilder.WriteInt32( MetadataTokens.GetToken(metadata.GetFieldHandle(fieldInfo))); break; case MethodInfo methodInfo: metadata.ILBuilder.WriteInt32( MetadataTokens.GetToken(metadata.GetMethodHandle(methodInfo))); break; default: throw new NotSupportedException($"Unsupported inline operand: {il[i].Operand}"); } break; case OperandType.ShortInlineVar: var bLocalVariableInfo = il[i].Operand as LocalVariableInfo; var bParameterInfo = il[i].Operand as ParameterInfo; if (bLocalVariableInfo != null) { metadata.ILBuilder.WriteByte((byte)bLocalVariableInfo.LocalIndex); } else if (bParameterInfo != null) { metadata.ILBuilder.WriteByte((byte)bParameterInfo.Position); } else { throw new NotSupportedException($"Unsupported short inline variable: {il[i].Operand}"); } break; case OperandType.InlineVar: var sLocalVariableInfo = il[i].Operand as LocalVariableInfo; var sParameterInfo = il[i].Operand as ParameterInfo; if (sLocalVariableInfo != null) { metadata.ILBuilder.WriteUInt16((ushort)sLocalVariableInfo.LocalIndex); } else if (sParameterInfo != null) { metadata.ILBuilder.WriteUInt16((ushort)sParameterInfo.Position); } else { throw new NotSupportedException($"Unsupported inline variable: {il[i].Operand}"); } break; default: throw new NotSupportedException($"Unsupported operand type: {opCode.OperandType}"); } } }
/// <summary> /// Parse a single available types section. For composite R2R images this method is called multiple times /// as available types are stored separately for each component assembly of the composite R2R executable. /// </summary> /// <param name="availableTypesSection"></param> private void ParseAvailableTypesSection(int assemblyIndex, ReadyToRunSection availableTypesSection, IAssemblyMetadata metadataReader) { _readyToRunAssemblies[assemblyIndex]._availableTypes = new List <string>(); int availableTypesOffset = GetOffset(availableTypesSection.RelativeVirtualAddress); NativeParser parser = new NativeParser(Image, (uint)availableTypesOffset); NativeHashtable availableTypes = new NativeHashtable(Image, parser, (uint)(availableTypesOffset + availableTypesSection.Size)); NativeHashtable.AllEntriesEnumerator allEntriesEnum = availableTypes.EnumerateAllEntries(); NativeParser curParser = allEntriesEnum.GetNext(); while (!curParser.IsNull()) { uint rid = curParser.GetUnsigned(); bool isExportedType = (rid & 1) != 0; rid = rid >> 1; if (isExportedType) { ExportedTypeHandle exportedTypeHandle = MetadataTokens.ExportedTypeHandle((int)rid); string exportedTypeName = GetExportedTypeFullName(metadataReader.MetadataReader, exportedTypeHandle); _readyToRunAssemblies[assemblyIndex]._availableTypes.Add("exported " + exportedTypeName); } else { TypeDefinitionHandle typeDefHandle = MetadataTokens.TypeDefinitionHandle((int)rid); string typeDefName = MetadataNameFormatter.FormatHandle(metadataReader.MetadataReader, typeDefHandle); _readyToRunAssemblies[assemblyIndex]._availableTypes.Add(typeDefName); } curParser = allEntriesEnum.GetNext(); } }
/// <summary> /// Initialize generic method instances with argument types and runtime function indices from InstanceMethodEntrypoints /// </summary> private void ParseInstanceMethodEntrypoints(bool[] isEntryPoint) { if (!ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.InstanceMethodEntryPoints, out ReadyToRunSection instMethodEntryPointSection)) { return; } int instMethodEntryPointsOffset = GetOffset(instMethodEntryPointSection.RelativeVirtualAddress); NativeParser parser = new NativeParser(Image, (uint)instMethodEntryPointsOffset); NativeHashtable instMethodEntryPoints = new NativeHashtable(Image, parser, (uint)(instMethodEntryPointsOffset + instMethodEntryPointSection.Size)); NativeHashtable.AllEntriesEnumerator allEntriesEnum = instMethodEntryPoints.EnumerateAllEntries(); NativeParser curParser = allEntriesEnum.GetNext(); while (!curParser.IsNull()) { IAssemblyMetadata mdReader = GetGlobalMetadata(); SignatureFormattingOptions dummyOptions = new SignatureFormattingOptions(); SignatureDecoder decoder = new SignatureDecoder(_assemblyResolver, dummyOptions, mdReader?.MetadataReader, this, (int)curParser.Offset); string owningType = null; uint methodFlags = decoder.ReadUInt(); if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_OwnerType) != 0) { mdReader = decoder.GetMetadataReaderFromModuleOverride() ?? mdReader; if ((_composite) && mdReader == null) { // The only types that don't have module overrides on them in composite images are primitive types within the system module mdReader = GetSystemModuleMetadataReader(); } owningType = decoder.ReadTypeSignatureNoEmit(); } if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_SlotInsteadOfToken) != 0) { throw new NotImplementedException(); } EntityHandle methodHandle; int rid = (int)decoder.ReadUInt(); if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_MemberRefToken) != 0) { methodHandle = MetadataTokens.MemberReferenceHandle(rid); } else { methodHandle = MetadataTokens.MethodDefinitionHandle(rid); } string[] methodTypeArgs = null; if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_MethodInstantiation) != 0) { uint typeArgCount = decoder.ReadUInt(); methodTypeArgs = new string[typeArgCount]; for (int typeArgIndex = 0; typeArgIndex < typeArgCount; typeArgIndex++) { methodTypeArgs[typeArgIndex] = decoder.ReadTypeSignatureNoEmit(); } } string constrainedType = null; if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_Constrained) != 0) { constrainedType = decoder.ReadTypeSignatureNoEmit(); } int runtimeFunctionId; int?fixupOffset; GetRuntimeFunctionIndexFromOffset((int)decoder.Offset, out runtimeFunctionId, out fixupOffset); ReadyToRunMethod method = new ReadyToRunMethod( this, mdReader, methodHandle, runtimeFunctionId, owningType, constrainedType, methodTypeArgs, fixupOffset); if (method.EntryPointRuntimeFunctionId >= 0 && method.EntryPointRuntimeFunctionId < isEntryPoint.Length) { isEntryPoint[method.EntryPointRuntimeFunctionId] = true; } _instanceMethods.Add(new InstanceMethod(curParser.LowHashcode, method)); curParser = allEntriesEnum.GetNext(); } }
/// <summary> /// Parse a single method def entrypoint section. For composite R2R images, this method is called multiple times /// are method entrypoints are stored separately for each component assembly of the composite R2R executable. /// </summary> /// <param name="section">Method entrypoint section to parse</param> /// <param name="metadataReader">ECMA metadata reader representing this method entrypoint section</param> /// <param name="isEntryPoint">Set to true for each runtime function index representing a method entrypoint</param> private void ParseMethodDefEntrypointsSectionCustom <TType, TMethod, TGenericContext>(IR2RSignatureTypeProvider <TType, TMethod, TGenericContext> provider, Dictionary <TMethod, ReadyToRunMethod> foundMethods, ReadyToRunSection section, IAssemblyMetadata metadataReader) { int methodDefEntryPointsOffset = GetOffset(section.RelativeVirtualAddress); NativeArray methodEntryPoints = new NativeArray(Image, (uint)methodDefEntryPointsOffset); uint nMethodEntryPoints = methodEntryPoints.GetCount(); for (uint rid = 1; rid <= nMethodEntryPoints; rid++) { int offset = 0; if (methodEntryPoints.TryGetAt(Image, rid - 1, ref offset)) { EntityHandle methodHandle = MetadataTokens.MethodDefinitionHandle((int)rid); int runtimeFunctionId; int? fixupOffset; GetRuntimeFunctionIndexFromOffset(offset, out runtimeFunctionId, out fixupOffset); ReadyToRunMethod r2rMethod = _runtimeFunctionToMethod[runtimeFunctionId]; var customMethod = provider.GetMethodFromMethodDef(metadataReader.MetadataReader, MetadataTokens.MethodDefinitionHandle((int)rid), default(TType)); if (!Object.ReferenceEquals(customMethod, null) && !foundMethods.ContainsKey(customMethod)) { foundMethods.Add(customMethod, r2rMethod); } } } }
internal static void FromSystemType(this SignatureTypeEncoder typeEncoder, Type type, IAssemblyMetadata metadata) { if (type.IsByRef && type.GetElementType().IsPrimitive) { typeEncoder.PrimitiveType(GetPrimitiveTypeCode(type.GetElementType())); } else if (type.IsPrimitive) { typeEncoder.PrimitiveType(GetPrimitiveTypeCode(type)); } else if (type == typeof(string)) { typeEncoder.String(); } else if (type == typeof(object)) { typeEncoder.Object(); } else if (type == typeof(void)) { throw new ArgumentException( "Void type is not allowed in SignatureTypeEncoder. Please, use FromSystemType from ReturnTypeEncoder.", nameof(type)); } else if (type.IsArray) { var elementType = type.GetElementType(); typeEncoder.Array( x => x.FromSystemType(elementType, metadata), x => x.Shape( type.GetArrayRank(), ImmutableArray.Create <int>(), ImmutableArray.Create <int>())); } else if (type.IsGenericType) { var genericTypeDef = type.GetGenericTypeDefinition(); var typeHandler = metadata.GetTypeHandle(genericTypeDef); var genericArguments = type.GetGenericArguments(); var inst = typeEncoder.GenericInstantiation(typeHandler, genericArguments.Length, false); foreach (var ga in genericArguments) { if (ga.IsGenericParameter) { inst.AddArgument().GenericTypeParameter(ga.GenericParameterPosition); } else { inst.AddArgument().FromSystemType(ga, metadata); } } } else { var typeHandler = metadata.GetTypeHandle(type); typeEncoder.Type(typeHandler, type.IsValueType); } }