bool ScanMethodBody(ITypeDefinition analyzedEntity, IMethod method, MethodBodyBlock methodBody) { bool found = false; var blob = methodBody.GetILReader(); var module = (MetadataModule)method.ParentModule; var genericContext = new Decompiler.TypeSystem.GenericContext(); // type parameters don't matter for this analyzer while (!found && blob.RemainingBytes > 0) { var opCode = blob.DecodeOpCode(); if (!CanBeReference(opCode)) { blob.SkipOperand(opCode); continue; } EntityHandle methodHandle = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); if (!methodHandle.Kind.IsMemberKind()) { continue; } var ctor = module.ResolveMethod(methodHandle, genericContext); if (ctor == null || !ctor.IsConstructor) { continue; } if (ctor.DeclaringTypeDefinition?.MetadataToken == analyzedEntity.MetadataToken && ctor.ParentModule.PEFile == analyzedEntity.ParentModule.PEFile) { return(true); } } return(false); }
public static int GetCodeSize(this MethodBodyBlock body) { if (body == null) { throw new ArgumentNullException(nameof(body)); } return(body.GetILReader().Length); }
bool ScanMethodBody(IField analyzedField, IMethod method, MethodBodyBlock methodBody) { if (methodBody == null) { return(false); } var mainModule = (MetadataModule)method.ParentModule; var blob = methodBody.GetILReader(); var genericContext = new Decompiler.TypeSystem.GenericContext(); // type parameters don't matter for this analyzer while (blob.RemainingBytes > 0) { ILOpCode opCode; try { opCode = blob.DecodeOpCode(); if (!CanBeReference(opCode)) { blob.SkipOperand(opCode); continue; } } catch (BadImageFormatException) { return(false); } EntityHandle fieldHandle = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); if (!fieldHandle.Kind.IsMemberKind()) { continue; } IField field; try { field = mainModule.ResolveEntity(fieldHandle, genericContext) as IField; } catch (BadImageFormatException) { continue; } if (field == null) { continue; } if (field.MetadataToken == analyzedField.MetadataToken && field.ParentModule.PEFile == analyzedField.ParentModule.PEFile) { return(true); } } return(false); }
public void Read(MethodBodyBlock body) { BlobReader ilReader = body.GetILReader(); this.Read(ref ilReader); }
void ScanMethodBody(TypeDefinitionUsedVisitor visitor, IMethod method, MethodBodyBlock methodBody, AnalyzerContext context) { if (methodBody == null) { return; } var module = (MetadataModule)method.ParentModule; var genericContext = new Decompiler.TypeSystem.GenericContext(); // type parameters don't matter for this analyzer if (!methodBody.LocalSignature.IsNil) { ImmutableArray <IType> localSignature; try { localSignature = module.DecodeLocalSignature(methodBody.LocalSignature, genericContext); } catch (BadImageFormatException) { // Issue #2197: ignore invalid local signatures localSignature = ImmutableArray <IType> .Empty; } foreach (var type in localSignature) { type.AcceptVisitor(visitor); if (visitor.Found) { return; } } } var blob = methodBody.GetILReader(); while (!visitor.Found && blob.RemainingBytes > 0) { var opCode = blob.DecodeOpCode(); switch (opCode.GetOperandType()) { case OperandType.Field: case OperandType.Method: case OperandType.Sig: case OperandType.Tok: case OperandType.Type: var member = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); if (member.IsNil) { continue; } switch (member.Kind) { case HandleKind.TypeReference: case HandleKind.TypeSpecification: case HandleKind.TypeDefinition: module.ResolveType(member, genericContext).AcceptVisitor(visitor); if (visitor.Found) { return; } break; case HandleKind.FieldDefinition: case HandleKind.MethodDefinition: case HandleKind.MemberReference: case HandleKind.MethodSpecification: VisitMember(visitor, module.ResolveEntity(member, genericContext) as IMember, context); if (visitor.Found) { return; } break; case HandleKind.StandaloneSignature: var(_, fpt) = module.DecodeMethodSignature((StandaloneSignatureHandle)member, genericContext); fpt.AcceptVisitor(visitor); if (visitor.Found) { return; } break; default: break; } break; default: blob.SkipOperand(opCode); break; } } }
void CollectNamespacesFromMethodBody(MethodBodyBlock method, MetadataModule module) { var metadata = module.metadata; var instructions = method.GetILReader(); if (!method.LocalSignature.IsNil) { ImmutableArray <IType> localSignature; try { localSignature = module.DecodeLocalSignature(method.LocalSignature, genericContext); } catch (BadImageFormatException) { // Issue #1211: ignore invalid local signatures localSignature = ImmutableArray <IType> .Empty; } foreach (var type in localSignature) { CollectNamespacesForTypeReference(type); } } foreach (var region in method.ExceptionRegions) { if (region.CatchType.IsNil) { continue; } IType ty; try { ty = module.ResolveType(region.CatchType, genericContext); } catch (BadImageFormatException) { continue; } CollectNamespacesForTypeReference(ty); } while (instructions.RemainingBytes > 0) { ILOpCode opCode; try { opCode = instructions.DecodeOpCode(); } catch (BadImageFormatException) { return; } switch (opCode.GetOperandType()) { case OperandType.Field: case OperandType.Method: case OperandType.Sig: case OperandType.Tok: case OperandType.Type: var handle = MetadataTokenHelpers.EntityHandleOrNil(instructions.ReadInt32()); if (handle.IsNil) { break; } switch (handle.Kind) { case HandleKind.TypeDefinition: case HandleKind.TypeReference: case HandleKind.TypeSpecification: IType type; try { type = module.ResolveType(handle, genericContext); } catch (BadImageFormatException) { break; } CollectNamespacesForTypeReference(type); break; case HandleKind.FieldDefinition: case HandleKind.MethodDefinition: case HandleKind.MethodSpecification: case HandleKind.MemberReference: IMember member; try { member = module.ResolveEntity(handle, genericContext) as IMember; } catch (BadImageFormatException) { break; } CollectNamespacesForMemberReference(member); break; case HandleKind.StandaloneSignature: StandaloneSignature sig; try { sig = metadata.GetStandaloneSignature((StandaloneSignatureHandle)handle); } catch (BadImageFormatException) { break; } if (sig.GetKind() == StandaloneSignatureKind.Method) { MethodSignature <IType> methodSig; try { methodSig = module.DecodeMethodSignature((StandaloneSignatureHandle)handle, genericContext); } catch (BadImageFormatException) { break; } CollectNamespacesForTypeReference(methodSig.ReturnType); foreach (var paramType in methodSig.ParameterTypes) { CollectNamespacesForTypeReference(paramType); } } break; } break; default: try { instructions.SkipOperand(opCode); } catch (BadImageFormatException) { return; } break; } } }
public ILStructure(PEFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, MethodBodyBlock body) : this(module, handle, genericContext, ILStructureType.Root, 0, body.GetILReader().Length) { // Build the tree of exception structures: for (int i = 0; i < body.ExceptionRegions.Length; i++) { ExceptionRegion eh = body.ExceptionRegions[i]; if (!body.ExceptionRegions.Take(i).Any(oldEh => oldEh.TryOffset == eh.TryOffset && oldEh.TryLength == eh.TryLength)) { AddNestedStructure(new ILStructure(module, handle, genericContext, ILStructureType.Try, eh.TryOffset, eh.TryOffset + eh.TryLength, eh)); } if (eh.Kind == ExceptionRegionKind.Filter) { AddNestedStructure(new ILStructure(module, handle, genericContext, ILStructureType.Filter, eh.FilterOffset, eh.HandlerOffset, eh)); } AddNestedStructure(new ILStructure(module, handle, genericContext, ILStructureType.Handler, eh.HandlerOffset, eh.HandlerOffset + eh.HandlerLength, eh)); } // Very simple loop detection: look for backward branches (var allBranches, var isAfterUnconditionalBranch) = FindAllBranches(body.GetILReader()); // We go through the branches in reverse so that we find the biggest possible loop boundary first (think loops with "continue;") for (int i = allBranches.Count - 1; i >= 0; i--) { int loopEnd = allBranches[i].Source.End; int loopStart = allBranches[i].Target; if (loopStart < loopEnd) { // We found a backward branch. This is a potential loop. // Check that is has only one entry point: int entryPoint = -1; // entry point is first instruction in loop if prev inst isn't an unconditional branch if (loopStart > 0 && !isAfterUnconditionalBranch[loopStart]) { entryPoint = allBranches[i].Target; } bool multipleEntryPoints = false; foreach (var branch in allBranches) { if (branch.Source.Start < loopStart || branch.Source.Start >= loopEnd) { if (loopStart <= branch.Target && branch.Target < loopEnd) { // jump from outside the loop into the loop if (entryPoint < 0) { entryPoint = branch.Target; } else if (branch.Target != entryPoint) { multipleEntryPoints = true; } } } } if (!multipleEntryPoints) { AddNestedStructure(new ILStructure(module, handle, genericContext, ILStructureType.Loop, loopStart, loopEnd, entryPoint)); } } } SortChildren(); }