public string WriteOutMethod(Class dexClass, Method method, Indentation indent, bool renderOpcodes = true) { string output = ""; var jumpTable = BuildJumpTable(method); /*foreach (var annotation in method.Annotations) * { * AnnotationToString(output, annotation.Values, dexClass, indent); * } * * foreach (var annotation in method.ParameterAnnotations) * { * AnnotationToString(output, annotation.Values, dexClass, indent); * }*/ // Initialize a pointer to the first jump target var targets = jumpTable.Targets.Keys.GetEnumerator(); targets.MoveNext(); output += (indent.ToString()); output += (MethodToString(method)); output += (" {") + "\n"; if (renderOpcodes) { indent++; var lastTryBlockId = 0; var activeTryBlocks = new List <TryCatchBlock>(); TryCatchBlock currentTryBlock = null; foreach (var opcode in method.GetInstructions()) { long offset = opcode.OpCodeOffset; // Print out jump target labels while (offset == targets.Current) { output += "\n"; //output += "{0}:{1}", indent.ToString(), string.Join(", ", jumpTable.GetTargetLabels(targets.Current)) \n ; output += indent.ToString() + ":" + string.Join(", ", jumpTable.GetTargetLabels(targets.Current)) + "\n"; if (!targets.MoveNext()) { break; } } // Test for the end of the current try block if (currentTryBlock != null && !currentTryBlock.IsInBlock(offset)) { //WriteOutCatchStatements(output, indent, currentTryBlock, jumpTable); activeTryBlocks.Remove(currentTryBlock); if (activeTryBlocks.Count > 0) { currentTryBlock = activeTryBlocks[activeTryBlocks.Count - 1]; } else { currentTryBlock = null; } } // Should open a new try block? if (method.TryCatchBlocks != null && method.TryCatchBlocks.Length > lastTryBlockId) { var tryBlock = method.TryCatchBlocks[lastTryBlockId]; if (tryBlock.IsInBlock(offset)) { output += indent.ToString(); output += "try" + "\n"; activeTryBlocks.Add(tryBlock); currentTryBlock = tryBlock; lastTryBlockId++; indent++; } } if (opcode.Instruction != Instructions.Nop) { output += indent.ToString(); output += OpCodeToString(opcode, dexClass, method, jumpTable) + "\n"; } } if (currentTryBlock != null) { //WriteOutCatchStatements(output, indent, currentTryBlock, jumpTable); } indent--; } output += indent.ToString(); output += "}" + "\n"; return(output); }
public void WriteOutMethod(Class dexClass, Method method, TextWriter output, Indentation indent, bool renderOpcodes = false) { var stringIndent = indent.ToString(); var proto = _dex.GetPrototype(method.PrototypeIndex); output.WriteLine(string.Format("{0}.METHOD {1} : {2}", stringIndent, method.Name, _dex.GetTypeName(proto.ReturnTypeIndex))); indent++; var paramCount = 0; foreach (var param in proto.Parameters) { output.WriteLine(string.Format("{0}.PARAM {1}", indent.ToString(), _dex.GetTypeName(param))); if (method.ParameterAnnotations.Count > paramCount) { indent++; WriteOutAnnotation(output, method.ParameterAnnotations[paramCount].Values, dexClass, indent); indent--; } paramCount++; } indent--; output.WriteLine(string.Format("{0}.MODIFIERS {1}", stringIndent, _helper.AccessFlagsToString(((AccessFlag)method.AccessFlags)))); output.WriteLine(string.Format("{0}.REGISTERS {1}", stringIndent, method.GetRegisterCount())); foreach (var annotation in method.Annotations) { WriteOutAnnotation(output, annotation.Values, dexClass, indent); } if (renderOpcodes) { output.WriteLine(string.Format("{0}.CODE", stringIndent)); indent++; stringIndent = indent.ToString(); long offset = 0; var lastTryBlockId = 0; var activeTryBlocks = new List <TryCatchBlock> (); TryCatchBlock currentTryBlock = null; foreach (var opcode in method.GetInstructions()) { offset = opcode.OpCodeOffset; // Test for the end of the current try block if (currentTryBlock != null && !currentTryBlock.IsInBlock(offset)) { WriteOutCatchStatements(output, indent, currentTryBlock); activeTryBlocks.Remove(currentTryBlock); if (activeTryBlocks.Count > 0) { currentTryBlock = activeTryBlocks [activeTryBlocks.Count - 1]; } else { currentTryBlock = null; } } // Should open a new try block? if (method.TryCatchBlocks != null && method.TryCatchBlocks.Length > lastTryBlockId) { var tryBlock = method.TryCatchBlocks [lastTryBlockId]; if (tryBlock.IsInBlock(offset)) { output.WriteLine(string.Format("{0}{1} {2} #{3}", stringIndent, "".PadLeft(12, ' '), ".TRY", lastTryBlockId)); activeTryBlocks.Add(tryBlock); currentTryBlock = tryBlock; lastTryBlockId++; } } if (opcode.Instruction != Instructions.Nop) { output.WriteLine(string.Format("{0}{1} {2}", stringIndent, offset.ToString().PadLeft(12, ' '), opcode.ToString())); } } if (currentTryBlock != null) { WriteOutCatchStatements(output, indent, currentTryBlock); } indent--; } }