public void Read(MethodBody body, InstructionMapper mapper) { var method_token = body.Method.MetadataToken; PdbFunction function; if (!functions.TryGetValue(method_token.ToUInt32(), out function)) { return; } ReadSequencePoints(function, mapper); ReadScopeAndLocals(function.scopes, null, body, mapper); if (!string.IsNullOrEmpty(function.iteratorClass)) { body.IteratorType = body.Method.DeclaringType.GetNestedType(function.iteratorClass); } if (function.iteratorScopes != null) { foreach (Microsoft.Cci.ILocalScope scope in function.iteratorScopes) { InstructionRange range = new InstructionRange(); SetInstructionRange(body, mapper, range, scope.Offset, scope.Length); body.IteratorScopes.Add(range); } } }
/// <summary> /// Convert the given set of bytecodes into a list of Ast nodes. /// </summary> private static IEnumerable <AstNode> ConvertRangeToAst(IEnumerable <ByteCode> range) { var ast = new List <AstNode>(); // Convert stack-based java bytecode code to Ast tree foreach (var byteCode in range) { var ilRange = new InstructionRange(byteCode.Offset, byteCode.EndOffset); if (byteCode.StackBefore == null) { // Unreachable code continue; } var expr = new AstExpression(byteCode.SourceLocation, byteCode.Code, byteCode.Operand); expr.ILRanges.Add(ilRange); // Label for this instruction if (byteCode.Label(false) != null) { ast.Add(byteCode.Label(false)); } // Reference arguments using temporary variables var popCount = byteCode.PopCount ?? byteCode.StackBefore.Length; for (var i = byteCode.StackBefore.Length - popCount; i < byteCode.StackBefore.Length; i++) { var slot = byteCode.StackBefore[i]; expr.Arguments.Add(new AstExpression(byteCode.SourceLocation, AstCode.Ldloc, slot.LoadFrom)); } // Store the result to temporary variable(s) if needed if (byteCode.StoreTo == null || byteCode.StoreTo.Count == 0) { ast.Add(expr); } else if (byteCode.StoreTo.Count == 1) { ast.Add(new AstExpression(byteCode.SourceLocation, AstCode.Stloc, byteCode.StoreTo[0], expr)); } else { var tmpVar = new AstGeneratedVariable("expr_" + byteCode.Offset.ToString("X2"), byteCode.StoreTo.Select(x => x.OriginalName).FirstOrDefault()); ast.Add(new AstExpression(byteCode.SourceLocation, AstCode.Stloc, tmpVar, expr)); foreach (var storeTo in byteCode.StoreTo.AsEnumerable().Reverse()) { ast.Add(new AstExpression(byteCode.SourceLocation, AstCode.Stloc, storeTo, new AstExpression(byteCode.SourceLocation, AstCode.Ldloc, tmpVar))); } } } return(ast); }
static void SetInstructionRange(MethodBody body, InstructionMapper mapper, InstructionRange range, uint offset, uint length) { range.Start = mapper((int)offset); range.End = mapper((int)(offset + length)); if (range.End == null) { range.End = body.Instructions[body.Instructions.Count - 1]; } else { range.End = range.End.Previous; } if (range.Start == null) { range.Start = range.End; } }
private List<AstNode> ConvertToAst(IEnumerable<ByteCode> body) { var ast = new List<AstNode>(); // Convert stack-based IL code to ILAst tree foreach (var byteCode in body) { var ilRange = new InstructionRange(byteCode.Offset, byteCode.EndOffset); if (byteCode.StackBefore == null) { // Unreachable code continue; } var expr = new AstExpression(byteCode.SequencePoint, byteCode.Code, byteCode.Operand); expr.ILRanges.Add(ilRange); if (byteCode.Prefixes != null && byteCode.Prefixes.Length > 0) { var prefixes = new AstExpressionPrefix[byteCode.Prefixes.Length]; for (var i = 0; i < prefixes.Length; i++) { var operand = byteCode.Prefixes[i].Operand; if (operand is FieldReference) { operand = XBuilder.AsFieldReference(module, (FieldReference) operand); } else if (operand is MethodReference) { operand = XBuilder.AsMethodReference(module, (MethodReference)operand); } else if (operand is TypeReference) { operand = XBuilder.AsTypeReference(module, (TypeReference) operand); } prefixes[i] = new AstExpressionPrefix((AstCode)byteCode.Prefixes[i].OpCode.Code, operand); } expr.Prefixes = prefixes; } // Label for this instruction if (byteCode.Label != null) { ast.Add(byteCode.Label); } // Reference arguments using temporary variables var popCount = byteCode.PopCount ?? byteCode.StackBefore.Length; for (var i = byteCode.StackBefore.Length - popCount; i < byteCode.StackBefore.Length; i++) { var slot = byteCode.StackBefore[i]; expr.Arguments.Add(new AstExpression(byteCode.SequencePoint, AstCode.Ldloc, slot.LoadFrom)); } // Store the result to temporary variable(s) if needed if (byteCode.StoreTo == null || byteCode.StoreTo.Count == 0) { ast.Add(expr); } else if (byteCode.StoreTo.Count == 1) { ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, byteCode.StoreTo[0], expr)); } else { var tmpVar = new AstGeneratedVariable("expr_" + byteCode.Offset.ToString("X2"), byteCode.StoreTo.Select(x => x.OriginalName).FirstOrDefault()); ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, tmpVar, expr)); foreach (var storeTo in byteCode.StoreTo.AsEnumerable().Reverse()) { ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, storeTo, new AstExpression(byteCode.SequencePoint, AstCode.Ldloc, tmpVar))); } } } return ast; }
void InventoryPage_draw() { // Change the equipment slot drawing code to draw the 4 additional slots. InstructionRange range = null; try { range = FindCode( // switch (equipmentIcon.name) { Instructions.Ldloca_S(3), OpCodes.Call, Instructions.Stloc_S(4), Instructions.Ldloc_S(4), Instructions.Ldfld(typeof(ClickableComponent), nameof(ClickableComponent.name)), Instructions.Stloc_S(5), Instructions.Ldloc_S(5), // case "Hat": Instructions.Ldstr("Hat") ); } catch (System.Exception err) { LogException(err, LogLevel.Trace); range = FindCode( // switch (equipmentIcon.name) { Instructions.Ldloca_S(1), OpCodes.Call, Instructions.Stloc_0(), Instructions.Ldloc_0(), Instructions.Ldfld(typeof(ClickableComponent), nameof(ClickableComponent.name)), Instructions.Stloc_2(), Instructions.Ldloc_2(), // case null (shortcut) OpCodes.Brfalse, Instructions.Ldloc_2(), // case "Hat": Instructions.Ldstr("Hat") ); } if (range.length != 8 && range.length != 10) { throw new System.Exception($"Failed to properly match code. Length={range.length}"); } range.Extend(range.Follow(-1)); range.Replace( range[0], range[1], Instructions.Ldarg_1(), Instructions.Call(typeof(ModEntry), nameof(DrawEquipment), typeof(ClickableComponent), typeof(Microsoft.Xna.Framework.Graphics.SpriteBatch)) ); // Move other stuff 32/64px to the right to eliminate overlap. for (int i = 0; i < 11; i++) { range = range.FindNext( OpCodes.Ldarg_0, Instructions.Ldfld(typeof(IClickableMenu), nameof(IClickableMenu.xPositionOnScreen)), OpCodes.Ldc_I4, OpCodes.Add ); int val = (int)range[2].operand + 32; if (val < 256) { val = 256; } range[2].operand = val; } }
private List <AstNode> ConvertToAst(IEnumerable <ByteCode> body) { var ast = new List <AstNode>(); // Convert stack-based IL code to ILAst tree foreach (var byteCode in body) { var ilRange = new InstructionRange(byteCode.Offset, byteCode.EndOffset); if (byteCode.StackBefore == null) { // Unreachable code continue; } var expr = new AstExpression(byteCode.SequencePoint, byteCode.Code, byteCode.Operand); expr.ILRanges.Add(ilRange); if (byteCode.Prefixes != null && byteCode.Prefixes.Length > 0) { var prefixes = new AstExpressionPrefix[byteCode.Prefixes.Length]; for (var i = 0; i < prefixes.Length; i++) { var operand = byteCode.Prefixes[i].Operand; if (operand is FieldReference) { operand = XBuilder.AsFieldReference(module, (FieldReference)operand); } else if (operand is MethodReference) { operand = XBuilder.AsMethodReference(module, (MethodReference)operand); } else if (operand is TypeReference) { operand = XBuilder.AsTypeReference(module, (TypeReference)operand); } prefixes[i] = new AstExpressionPrefix((AstCode)byteCode.Prefixes[i].OpCode.Code, operand); } expr.Prefixes = prefixes; } // Label for this instruction if (byteCode.Label != null) { ast.Add(byteCode.Label); } // Reference arguments using temporary variables var popCount = byteCode.PopCount ?? byteCode.StackBefore.Length; for (var i = byteCode.StackBefore.Length - popCount; i < byteCode.StackBefore.Length; i++) { var slot = byteCode.StackBefore[i]; expr.Arguments.Add(new AstExpression(byteCode.SequencePoint, AstCode.Ldloc, slot.LoadFrom)); } // Store the result to temporary variable(s) if needed if (byteCode.StoreTo == null || byteCode.StoreTo.Count == 0) { ast.Add(expr); } else if (byteCode.StoreTo.Count == 1) { ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, byteCode.StoreTo[0], expr)); } else { var tmpVar = new AstGeneratedVariable("expr_" + byteCode.Offset.ToString("X2"), byteCode.StoreTo.Select(x => x.OriginalName).FirstOrDefault()); ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, tmpVar, expr)); foreach (var storeTo in byteCode.StoreTo.AsEnumerable().Reverse()) { ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, storeTo, new AstExpression(byteCode.SequencePoint, AstCode.Ldloc, tmpVar))); } } } return(ast); }