Exemplo n.º 1
0
		public ILStructure(CilBody body)
			: this(ILStructureType.Root, 0, body.GetCodeSize())
		{
			// Build the tree of exception structures:
			for (int i = 0; i < body.ExceptionHandlers.Count; i++) {
				ExceptionHandler eh = body.ExceptionHandlers[i];
				if (!body.ExceptionHandlers.Take(i).Any(oldEh => oldEh.TryStart == eh.TryStart && oldEh.TryEnd == eh.TryEnd))
					AddNestedStructure(new ILStructure(ILStructureType.Try, (int)eh.TryStart.GetOffset(), (int)eh.TryEnd.GetOffset(), eh));
				if (eh.HandlerType == ExceptionHandlerType.Filter)
					AddNestedStructure(new ILStructure(ILStructureType.Filter, (int)eh.FilterStart.GetOffset(), (int)eh.HandlerStart.GetOffset(), eh));
				AddNestedStructure(new ILStructure(ILStructureType.Handler, (int)eh.HandlerStart.GetOffset(), eh.HandlerEnd == null ? body.GetCodeSize() : (int)eh.HandlerEnd.GetOffset(), eh));
			}
			// Very simple loop detection: look for backward branches
			List<KeyValuePair<Instruction, Instruction>> allBranches = FindAllBranches(body);
			// 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].Key.GetEndOffset();
				int loopStart = (int)allBranches[i].Value.Offset;
				if (loopStart < loopEnd) {
					// We found a backward branch. This is a potential loop.
					// Check that is has only one entry point:
					Instruction entryPoint = null;
					
					// entry point is first instruction in loop if prev inst isn't an unconditional branch
					Instruction prev = body.GetPrevious(allBranches[i].Value);
					if (prev != null && !OpCodeInfo.IsUnconditionalBranch(prev.OpCode))
						entryPoint = allBranches[i].Value;
					
					bool multipleEntryPoints = false;
					foreach (var pair in allBranches) {
						if (pair.Key.Offset < loopStart || pair.Key.Offset >= loopEnd) {
							if (loopStart <= pair.Value.Offset && pair.Value.Offset < loopEnd) {
								// jump from outside the loop into the loop
								if (entryPoint == null)
									entryPoint = pair.Value;
								else if (pair.Value != entryPoint)
									multipleEntryPoints = true;
							}
						}
					}
					if (!multipleEntryPoints) {
						AddNestedStructure(new ILStructure(ILStructureType.Loop, loopStart, loopEnd, entryPoint));
					}
				}
			}
			SortChildren();
		}
		public void Disassemble(MethodDef method, CilBody body, MemberMapping methodMapping)
		{
			// start writing IL code
			output.WriteLineComment("// Method Token is 0x{0:x8}", method.MDToken.Raw);
			output.WriteLineComment("// Method begins at RVA 0x{0:x}", method.RVA);
			output.WriteLineComment("// Code size {0} (0x{0:x})", body.GetCodeSize());
			output.WriteKeyword(".maxstack ");
			output.WriteLiteral(body.MaxStack.ToString());
			output.WriteLine();
			if (method.DeclaringType.Module.Assembly != null && method.DeclaringType.Module.EntryPoint == method) {
				output.WriteKeyword(".entrypoint");
				output.WriteLine();
			}
			
			if (method.Body.HasVariables) {
				output.WriteKeyword(".locals ");
				if (method.Body.InitLocals)
					output.WriteKeyword("init ");
				output.WriteLine("(");
				output.Indent();
				foreach (var v in method.Body.Variables) {
					output.WriteDefinition("[" + v.Index + "]", v, true);
					output.Write(" ");
					v.Type.WriteTo(output);
					if (!string.IsNullOrEmpty(v.Name)) {
						output.Write(' ');
						output.Write(DisassemblerHelpers.Escape(v.Name));
					}
					if (v.Index + 1 < method.Body.Variables.Count)
						output.Write(',');
					output.WriteLine();
				}
				output.Unindent();
				output.WriteLine(")");
			}
			output.WriteLine();
			
			if (detectControlStructure && body.Instructions.Count > 0) {
				Instruction inst = body.Instructions[0];
				var branchTargets = GetBranchTargets(body.Instructions);
				WriteStructureBody(method, body, new ILStructure(body), branchTargets, ref inst, methodMapping, method.Body.GetCodeSize());
			} else {
				foreach (var inst in method.Body.Instructions) {
					var startLocation = output.Location;
					inst.WriteTo(method, body, output);
					
					if (methodMapping != null) {
						var next = inst.GetNext(body);
						// add IL code mappings - used in debugger
						methodMapping.MemberCodeMappings.Add(
							new SourceCodeMapping() {
								StartLocation = output.Location,
								EndLocation = output.Location,
								ILInstructionOffset = new ILRange { From = inst.Offset, To = next == null ? method.Body.GetCodeSize() : next.Offset },
								MemberMapping = methodMapping
							});
					}
					
					output.WriteLine();
				}
				if (method.Body.HasExceptionHandlers) {
					output.WriteLine();
					foreach (var eh in method.Body.ExceptionHandlers) {
						eh.WriteTo(output);
						output.WriteLine();
					}
				}
			}
		}