private VBStyleCollection <BasicBlock, int> CreateBasicBlocks(short[] startblock, InstructionSequence instrseq, Dictionary <int, BasicBlock> mapInstrBlocks) { VBStyleCollection <BasicBlock, int> col = new VBStyleCollection <BasicBlock, int>(); InstructionSequence currseq = null; List <int> lstOffs = null; int len = startblock.Length; short counter = 0; int blockoffset = 0; BasicBlock currentBlock = null; for (int i = 0; i < len; i++) { if (startblock[i] == 1) { currentBlock = new BasicBlock(++counter); currseq = currentBlock.GetSeq(); lstOffs = currentBlock.GetInstrOldOffsets(); col.AddWithKey(currentBlock, currentBlock.id); blockoffset = instrseq.GetOffset(i); } startblock[i] = counter; Sharpen.Collections.Put(mapInstrBlocks, i, currentBlock); currseq.AddInstruction(instrseq.GetInstr(i), instrseq.GetOffset(i) - blockoffset); lstOffs.Add(instrseq.GetOffset(i)); } last_id = counter; return(col); }
private static short[] FindStartInstructions(InstructionSequence seq) { int len = seq.Length(); short[] inststates = new short[len]; HashSet <int> excSet = new HashSet <int>(); foreach (ExceptionHandler handler in seq.GetExceptionTable().GetHandlers()) { excSet.Add(handler.from_instr); excSet.Add(handler.to_instr); excSet.Add(handler.handler_instr); } for (int i = 0; i < len; i++) { // exception blocks if (excSet.Contains(i)) { inststates[i] = 1; } Instruction instr = seq.GetInstr(i); switch (instr.group) { case Group_Jump: { inststates[((JumpInstruction)instr).destination] = 1; goto case Group_Return; } case Group_Return: { if (i + 1 < len) { inststates[i + 1] = 1; } break; } case Group_Switch: { SwitchInstruction swinstr = (SwitchInstruction)instr; int[] dests = swinstr.GetDestinations(); for (int j = dests.Length - 1; j >= 0; j--) { inststates[dests[j]] = 1; } inststates[swinstr.GetDefaultDestination()] = 1; if (i + 1 < len) { inststates[i + 1] = 1; } break; } } } // first instruction inststates[0] = 1; return(inststates); }
private static void RemoveJsrInstructions(ConstantPool pool, BasicBlock block, DataPoint data) { ListStack <VarType> stack = data.GetStack(); InstructionSequence seq = block.GetSeq(); for (int i = 0; i < seq.Length(); i++) { Instruction instr = seq.GetInstr(i); VarType var = null; if (instr.opcode == ICodeConstants.opc_astore || instr.opcode == ICodeConstants.opc_pop) { var = stack.GetByOffset(-1); } InstructionImpact.StepTypes(data, instr, pool); switch (instr.opcode) { case ICodeConstants.opc_jsr: case ICodeConstants.opc_ret: { seq.RemoveInstruction(i); i--; break; } case ICodeConstants.opc_astore: case ICodeConstants.opc_pop: { if (var.type == ICodeConstants.Type_Address) { seq.RemoveInstruction(i); i--; } break; } } } block.mark = 1; for (int i = 0; i < block.GetSuccs().Count; i++) { BasicBlock suc = block.GetSuccs()[i]; if (suc.mark != 1) { RemoveJsrInstructions(pool, suc, data.Copy()); } } for (int i = 0; i < block.GetSuccExceptions().Count; i++) { BasicBlock suc = block.GetSuccExceptions()[i]; if (suc.mark != 1) { DataPoint point = new DataPoint(); point.SetLocalVariables(new List <VarType>(data.GetLocalVariables())); point.GetStack().Push(new VarType(ICodeConstants.Type_Object, 0, null)); RemoveJsrInstructions(pool, suc, point); } } }
public virtual void BuildMonitorFlags() { foreach (Statement st in stats) { st.BuildMonitorFlags(); } switch (type) { case Type_Basicblock: { BasicBlockStatement bblock = (BasicBlockStatement)this; InstructionSequence seq = bblock.GetBlock().GetSeq(); if (seq != null && seq.Length() > 0) { for (int i = 0; i < seq.Length(); i++) { if (seq.GetInstr(i).opcode == ICodeConstants.opc_monitorexit) { containsMonitorExit = true; break; } } isMonitorEnter__ = (seq.GetLastInstr().opcode == ICodeConstants.opc_monitorenter); } break; } case Type_Sequence: case Type_If: { containsMonitorExit = false; foreach (Statement st in stats) { containsMonitorExit |= st.IsContainsMonitorExit(); } break; } case Type_Syncronized: case Type_Root: case Type_General: { break; } default: { containsMonitorExit = false; foreach (Statement st in stats) { containsMonitorExit |= st.IsContainsMonitorExit(); } break; } } }
private static bool IsAnonymous(StructClass cl, StructClass enclosingCl) { // checking super class and interfaces int[] interfaces = cl.GetInterfaces(); if (interfaces.Length > 0) { bool hasNonTrivialSuperClass = cl.superClass != null && !VarType.Vartype_Object.Equals (new VarType(cl.superClass.GetString(), true)); if (hasNonTrivialSuperClass || interfaces.Length > 1) { // can't have multiple 'sources' string message = "Inconsistent anonymous class definition: '" + cl.qualifiedName + "'. Multiple interfaces and/or super class defined."; DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn ); return(false); } } else if (cl.superClass == null) { // neither interface nor super class defined string message = "Inconsistent anonymous class definition: '" + cl.qualifiedName + "'. Neither interface nor super class defined."; DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn ); return(false); } // FIXME: check constructors // FIXME: check enclosing class/method ConstantPool pool = enclosingCl.GetPool(); int refCounter = 0; bool refNotNew = false; StructEnclosingMethodAttribute attribute = cl.GetAttribute(StructGeneralAttribute .Attribute_Enclosing_Method); string enclosingMethod = attribute != null?attribute.GetMethodName() : null; // checking references in the enclosing class foreach (StructMethod mt in enclosingCl.GetMethods()) { if (enclosingMethod != null && !enclosingMethod.Equals(mt.GetName())) { continue; } try { mt.ExpandData(); InstructionSequence seq = mt.GetInstructionSequence(); if (seq != null) { int len = seq.Length(); for (int i = 0; i < len; i++) { Instruction instr = seq.GetInstr(i); switch (instr.opcode) { case opc_checkcast: case opc_instanceof: { if (cl.qualifiedName.Equals(pool.GetPrimitiveConstant(instr.Operand(0)).GetString ())) { refCounter++; refNotNew = true; } break; } case opc_new: case opc_anewarray: case opc_multianewarray: { if (cl.qualifiedName.Equals(pool.GetPrimitiveConstant(instr.Operand(0)).GetString ())) { refCounter++; } break; } case opc_getstatic: case opc_putstatic: { if (cl.qualifiedName.Equals(pool.GetLinkConstant(instr.Operand(0)).classname)) { refCounter++; refNotNew = true; } break; } } } } mt.ReleaseResources(); } catch (IOException) { string message = "Could not read method while checking anonymous class definition: '" + enclosingCl.qualifiedName + "', '" + InterpreterUtil.MakeUniqueKey(mt.GetName (), mt.GetDescriptor()) + "'"; DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn ); return(false); } if (refCounter > 1 || refNotNew) { string message = "Inconsistent references to the class '" + cl.qualifiedName + "' which is supposed to be anonymous"; DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn ); return(false); } } return(true); }
public static void RestorePopRanges(ControlFlowGraph graph) { List <ExceptionDeobfuscator.Range> lstRanges = new List <ExceptionDeobfuscator.Range >(); // aggregate ranges foreach (ExceptionRangeCFG range in graph.GetExceptions()) { bool found = false; foreach (ExceptionDeobfuscator.Range arr in lstRanges) { if (arr.handler == range.GetHandler() && InterpreterUtil.EqualObjects(range.GetUniqueExceptionsString (), arr.uniqueStr)) { Sharpen.Collections.AddAll(arr.protectedRange, range.GetProtectedRange()); found = true; break; } } if (!found) { // doesn't matter, which range chosen lstRanges.Add(new ExceptionDeobfuscator.Range(range.GetHandler(), range.GetUniqueExceptionsString (), new HashSet <BasicBlock>(range.GetProtectedRange()), range)); } } // process aggregated ranges foreach (ExceptionDeobfuscator.Range range in lstRanges) { if (range.uniqueStr != null) { BasicBlock handler = range.handler; InstructionSequence seq = handler.GetSeq(); Instruction firstinstr; if (seq.Length() > 0) { firstinstr = seq.GetInstr(0); if (firstinstr.opcode == ICodeConstants.opc_pop || firstinstr.opcode == ICodeConstants .opc_astore) { HashSet <BasicBlock> setrange = new HashSet <BasicBlock>(range.protectedRange); foreach (ExceptionDeobfuscator.Range range_super in lstRanges) { // finally or strict superset if (range != range_super) { HashSet <BasicBlock> setrange_super = new HashSet <BasicBlock>(range_super.protectedRange ); if (!setrange.Contains(range_super.handler) && !setrange_super.Contains(handler) && (range_super.uniqueStr == null || setrange.All(setrange_super.Contains))) { if (range_super.uniqueStr == null) { setrange_super.IntersectWith(setrange); } else { setrange_super.ExceptWith(setrange); } if (!(setrange_super.Count == 0)) { BasicBlock newblock = handler; // split the handler if (seq.Length() > 1) { newblock = new BasicBlock(++graph.last_id); InstructionSequence newseq = new SimpleInstructionSequence(); newseq.AddInstruction(firstinstr.Clone(), -1); newblock.SetSeq(newseq); graph.GetBlocks().AddWithKey(newblock, newblock.id); List <BasicBlock> lstTemp = new List <BasicBlock>(); Sharpen.Collections.AddAll(lstTemp, handler.GetPreds()); Sharpen.Collections.AddAll(lstTemp, handler.GetPredExceptions()); // replace predecessors foreach (BasicBlock pred in lstTemp) { pred.ReplaceSuccessor(handler, newblock); } // replace handler foreach (ExceptionRangeCFG range_ext in graph.GetExceptions()) { if (range_ext.GetHandler() == handler) { range_ext.SetHandler(newblock); } else if (range_ext.GetProtectedRange().Contains(handler)) { newblock.AddSuccessorException(range_ext.GetHandler()); range_ext.GetProtectedRange().Add(newblock); } } newblock.AddSuccessor(handler); if (graph.GetFirst() == handler) { graph.SetFirst(newblock); } // remove the first pop in the handler seq.RemoveInstruction(0); } newblock.AddSuccessorException(range_super.handler); range_super.rangeCFG.GetProtectedRange().Add(newblock); handler = range.rangeCFG.GetHandler(); seq = handler.GetSeq(); } } } } } } } } }
public static void IncorporateValueReturns(ControlFlowGraph graph) { foreach (BasicBlock block in graph.GetBlocks()) { InstructionSequence seq = block.GetSeq(); int len = seq.Length(); if (len > 0 && len < 3) { bool ok = false; if (seq.GetLastInstr().opcode >= ICodeConstants.opc_ireturn && seq.GetLastInstr() .opcode <= ICodeConstants.opc_return) { if (len == 1) { ok = true; } else if (seq.GetLastInstr().opcode != ICodeConstants.opc_return) { switch (seq.GetInstr(0).opcode) { case ICodeConstants.opc_iload: case ICodeConstants.opc_lload: case ICodeConstants.opc_fload: case ICodeConstants.opc_dload: case ICodeConstants.opc_aload: case ICodeConstants.opc_aconst_null: case ICodeConstants.opc_bipush: case ICodeConstants.opc_sipush: case ICodeConstants.opc_lconst_0: case ICodeConstants.opc_lconst_1: case ICodeConstants.opc_fconst_0: case ICodeConstants.opc_fconst_1: case ICodeConstants.opc_fconst_2: case ICodeConstants.opc_dconst_0: case ICodeConstants.opc_dconst_1: case ICodeConstants.opc_ldc: case ICodeConstants.opc_ldc_w: case ICodeConstants.opc_ldc2_w: { ok = true; break; } } } } if (ok) { if (!(block.GetPreds().Count == 0)) { HashSet <BasicBlock> setPredHandlersUnion = new HashSet <BasicBlock>(); HashSet <BasicBlock> setPredHandlersIntersection = new HashSet <BasicBlock>(); bool firstpred = true; foreach (BasicBlock pred in block.GetPreds()) { if (firstpred) { Sharpen.Collections.AddAll(setPredHandlersIntersection, pred.GetSuccExceptions()); firstpred = false; } else { setPredHandlersIntersection.IntersectWith(pred.GetSuccExceptions()); } Sharpen.Collections.AddAll(setPredHandlersUnion, pred.GetSuccExceptions()); } // add exception ranges from predecessors setPredHandlersIntersection.ExceptWith(block.GetSuccExceptions()); BasicBlock predecessor = block.GetPreds()[0]; foreach (BasicBlock handler in setPredHandlersIntersection) { ExceptionRangeCFG range = graph.GetExceptionRange(handler, predecessor); range.GetProtectedRange().Add(block); block.AddSuccessorException(handler); } // remove redundant ranges HashSet <BasicBlock> setRangesToBeRemoved = new HashSet <BasicBlock>(block.GetSuccExceptions ()); setRangesToBeRemoved.ExceptWith(setPredHandlersUnion); foreach (BasicBlock handler in setRangesToBeRemoved) { ExceptionRangeCFG range = graph.GetExceptionRange(handler, block); if (range.GetProtectedRange().Count > 1) { range.GetProtectedRange().Remove(block); block.RemoveSuccessorException(handler); } } } if (block.GetPreds().Count == 1 && (block.GetPredExceptions().Count == 0)) { BasicBlock bpred = block.GetPreds()[0]; if (bpred.GetSuccs().Count == 1) { // add exception ranges of predecessor foreach (BasicBlock succ in bpred.GetSuccExceptions()) { if (!block.GetSuccExceptions().Contains(succ)) { ExceptionRangeCFG range = graph.GetExceptionRange(succ, bpred); range.GetProtectedRange().Add(block); block.AddSuccessorException(succ); } } // remove superfluous ranges from successors foreach (BasicBlock succ in new HashSet <BasicBlock>(block.GetSuccExceptions())) { if (!bpred.GetSuccExceptions().Contains(succ)) { ExceptionRangeCFG range = graph.GetExceptionRange(succ, block); if (range.GetProtectedRange().Count > 1) { range.GetProtectedRange().Remove(block); block.RemoveSuccessorException(succ); } } } } } } } } }
public static void ExtendSynchronizedRangeToMonitorexit(ControlFlowGraph graph) { while (true) { bool range_extended = false; foreach (ExceptionRangeCFG range in graph.GetExceptions()) { HashSet <BasicBlock> setPreds = new HashSet <BasicBlock>(); foreach (BasicBlock block in range.GetProtectedRange()) { Sharpen.Collections.AddAll(setPreds, block.GetPreds()); } setPreds.ExceptWith(range.GetProtectedRange()); if (setPreds.Count != 1) { continue; } // multiple predecessors, obfuscated range var setPredsEnumerator = new EnumeratorAdapter <BasicBlock>(setPreds.GetEnumerator()); BasicBlock predBlock = setPredsEnumerator.Next(); InstructionSequence predSeq = predBlock.GetSeq(); if (predSeq.IsEmpty() || predSeq.GetLastInstr().opcode != ICodeConstants.opc_monitorenter) { continue; } // not a synchronized range bool monitorexit_in_range = false; HashSet <BasicBlock> setProtectedBlocks = new HashSet <BasicBlock>(); Sharpen.Collections.AddAll(setProtectedBlocks, range.GetProtectedRange()); setProtectedBlocks.Add(range.GetHandler()); foreach (BasicBlock block in setProtectedBlocks) { InstructionSequence blockSeq = block.GetSeq(); for (int i = 0; i < blockSeq.Length(); i++) { if (blockSeq.GetInstr(i).opcode == ICodeConstants.opc_monitorexit) { monitorexit_in_range = true; break; } } if (monitorexit_in_range) { break; } } if (monitorexit_in_range) { continue; } // protected range already contains monitorexit HashSet <BasicBlock> setSuccs = new HashSet <BasicBlock>(); foreach (BasicBlock block in range.GetProtectedRange()) { Sharpen.Collections.AddAll(setSuccs, block.GetSuccs()); } setSuccs.ExceptWith(range.GetProtectedRange()); if (setSuccs.Count != 1) { continue; } // non-unique successor BasicBlock succBlock = new Sharpen.EnumeratorAdapter <BasicBlock>(setSuccs.GetEnumerator()).Next(); InstructionSequence succSeq = succBlock.GetSeq(); int succ_monitorexit_index = -1; for (int i = 0; i < succSeq.Length(); i++) { if (succSeq.GetInstr(i).opcode == ICodeConstants.opc_monitorexit) { succ_monitorexit_index = i; break; } } if (succ_monitorexit_index < 0) { continue; } // monitorexit not found in the single successor block BasicBlock handlerBlock = range.GetHandler(); if (handlerBlock.GetSuccs().Count != 1) { continue; } // non-unique handler successor BasicBlock succHandler = handlerBlock.GetSuccs()[0]; InstructionSequence succHandlerSeq = succHandler.GetSeq(); if (succHandlerSeq.IsEmpty() || succHandlerSeq.GetLastInstr().opcode != ICodeConstants .opc_athrow) { continue; } // not a standard synchronized range int handler_monitorexit_index = -1; for (int i = 0; i < succHandlerSeq.Length(); i++) { if (succHandlerSeq.GetInstr(i).opcode == ICodeConstants.opc_monitorexit) { handler_monitorexit_index = i; break; } } if (handler_monitorexit_index < 0) { continue; } // monitorexit not found in the handler successor block // checks successful, prerequisites satisfied, now extend the range if (succ_monitorexit_index < succSeq.Length() - 1) { // split block SimpleInstructionSequence seq = new SimpleInstructionSequence(); for (int counter = 0; counter < succ_monitorexit_index; counter++) { seq.AddInstruction(succSeq.GetInstr(0), -1); succSeq.RemoveInstruction(0); } // build a separate block BasicBlock newblock = new BasicBlock(++graph.last_id); newblock.SetSeq(seq); // insert new block foreach (BasicBlock block in succBlock.GetPreds()) { block.ReplaceSuccessor(succBlock, newblock); } newblock.AddSuccessor(succBlock); graph.GetBlocks().AddWithKey(newblock, newblock.id); succBlock = newblock; } // copy exception edges and extend protected ranges (successor block) BasicBlock rangeExitBlock = succBlock.GetPreds()[0]; for (int j = 0; j < rangeExitBlock.GetSuccExceptions().Count; j++) { BasicBlock hd = rangeExitBlock.GetSuccExceptions()[j]; succBlock.AddSuccessorException(hd); ExceptionRangeCFG rng = graph.GetExceptionRange(hd, rangeExitBlock); rng.GetProtectedRange().Add(succBlock); } // copy instructions (handler successor block) InstructionSequence handlerSeq = handlerBlock.GetSeq(); for (int counter = 0; counter < handler_monitorexit_index; counter++) { handlerSeq.AddInstruction(succHandlerSeq.GetInstr(0), -1); succHandlerSeq.RemoveInstruction(0); } range_extended = true; break; } if (!range_extended) { break; } } }
private bool CompareBasicBlocksEx(ControlFlowGraph graph, BasicBlock pattern, BasicBlock sample, int type, int finallytype, List <int[]> lstStoreVars) { InstructionSequence seqPattern = pattern.GetSeq(); InstructionSequence seqSample = sample.GetSeq(); if (type != 0) { seqPattern = seqPattern.Clone(); if ((type & 1) > 0) { // first if (finallytype > 0) { seqPattern.RemoveInstruction(0); } } if ((type & 2) > 0) { // last if (finallytype == 0 || finallytype == 2) { seqPattern.RemoveLast(); } if (finallytype == 2) { seqPattern.RemoveLast(); } } } if (seqPattern.Length() > seqSample.Length()) { return(false); } for (int i = 0; i < seqPattern.Length(); i++) { Instruction instrPattern = seqPattern.GetInstr(i); Instruction instrSample = seqSample.GetInstr(i); // compare instructions with respect to jumps if (!EqualInstructions(instrPattern, instrSample, lstStoreVars)) { return(false); } } if (seqPattern.Length() < seqSample.Length()) { // split in two blocks SimpleInstructionSequence seq = new SimpleInstructionSequence(); LinkedList <int> oldOffsets = new LinkedList <int>(); for (int i = seqSample.Length() - 1; i >= seqPattern.Length(); i--) { seq.AddInstruction(0, seqSample.GetInstr(i), -1); oldOffsets.AddFirst(sample.GetOldOffset(i)); seqSample.RemoveInstruction(i); } BasicBlock newblock = new BasicBlock(++graph.last_id); newblock.SetSeq(seq); Sharpen.Collections.AddAll(newblock.GetInstrOldOffsets(), oldOffsets); List <BasicBlock> lstTemp = new List <BasicBlock>(sample.GetSuccs()); // move successors foreach (BasicBlock suc in lstTemp) { sample.RemoveSuccessor(suc); newblock.AddSuccessor(suc); } sample.AddSuccessor(newblock); graph.GetBlocks().AddWithKey(newblock, newblock.id); HashSet <BasicBlock> setFinallyExits = graph.GetFinallyExits(); if (setFinallyExits.Contains(sample)) { setFinallyExits.Remove(sample); setFinallyExits.Add(newblock); } // copy exception edges and extend protected ranges for (int j = 0; j < sample.GetSuccExceptions().Count; j++) { BasicBlock hd = sample.GetSuccExceptions()[j]; newblock.AddSuccessorException(hd); ExceptionRangeCFG range = graph.GetExceptionRange(hd, sample); range.GetProtectedRange().Add(newblock); } } return(true); }
private static BasicBlock GetUniqueNext(ControlFlowGraph graph, HashSet <BasicBlock []> setNext) { // precondition: there is at most one true exit path in a finally statement BasicBlock next = null; bool multiple = false; foreach (BasicBlock[] arr in setNext) { if (arr[2] != null) { next = arr[1]; multiple = false; break; } else { if (next == null) { next = arr[1]; } else if (next != arr[1]) { multiple = true; } if (arr[1].GetPreds().Count == 1) { next = arr[1]; } } } if (multiple) { // TODO: generic solution foreach (BasicBlock[] arr in setNext) { BasicBlock block = arr[1]; if (block != next) { if (InterpreterUtil.EqualSets(next.GetSuccs(), block.GetSuccs())) { InstructionSequence seqNext = next.GetSeq(); InstructionSequence seqBlock = block.GetSeq(); if (seqNext.Length() == seqBlock.Length()) { for (int i = 0; i < seqNext.Length(); i++) { Instruction instrNext = seqNext.GetInstr(i); Instruction instrBlock = seqBlock.GetInstr(i); if (!Instruction.Equals(instrNext, instrBlock)) { return(null); } for (int j = 0; j < instrNext.OperandsCount(); j++) { if (instrNext.Operand(j) != instrBlock.Operand(j)) { return(null); } } } } else { return(null); } } else { return(null); } } } // try { // DotExporter.toDotFile(graph, new File("c:\\Temp\\fern5.dot"), true); // } catch(IOException ex) { // ex.printStackTrace(); // } foreach (BasicBlock[] arr in setNext) { if (arr[1] != next) { // FIXME: exception edge possible? arr[0].RemoveSuccessor(arr[1]); arr[0].AddSuccessor(next); } } DeadCodeHelper.RemoveDeadBlocks(graph); } return(next); }
public virtual Instruction GetInstruction(int index) { return(seq.GetInstr(index)); }
/// <exception cref="IOException"/> public virtual void ProcessClass(ClassesProcessor.ClassNode node) { foreach (ClassesProcessor.ClassNode child in node.nested) { ProcessClass(child); } ClassesProcessor clProcessor = DecompilerContext.GetClassProcessor(); StructClass cl = node.classStruct; if (cl.GetBytecodeVersion() < ICodeConstants.Bytecode_Java_8) { // lambda beginning with Java 8 return; } StructBootstrapMethodsAttribute bootstrap = cl.GetAttribute(StructGeneralAttribute .Attribute_Bootstrap_Methods); if (bootstrap == null || bootstrap.GetMethodsNumber() == 0) { return; } // no bootstrap constants in pool BitSet lambda_methods = new BitSet(); // find lambda bootstrap constants for (int i = 0; i < bootstrap.GetMethodsNumber(); ++i) { LinkConstant method_ref = bootstrap.GetMethodReference(i); // method handle // FIXME: extend for Eclipse etc. at some point if (Javac_Lambda_Class.Equals(method_ref.classname) && (Javac_Lambda_Method.Equals (method_ref.elementname) || Javac_Lambda_Alt_Method.Equals(method_ref.elementname ))) { lambda_methods.Set(i); } } if (lambda_methods.IsEmpty()) { return; } // no lambda bootstrap constant found Dictionary <string, string> mapMethodsLambda = new Dictionary <string, string>(); // iterate over code and find invocations of bootstrap methods. Replace them with anonymous classes. foreach (StructMethod mt in cl.GetMethods()) { mt.ExpandData(); InstructionSequence seq = mt.GetInstructionSequence(); if (seq != null && seq.Length() > 0) { int len = seq.Length(); for (int i = 0; i < len; ++i) { Instruction instr = seq.GetInstr(i); if (instr.opcode == ICodeConstants.opc_invokedynamic) { LinkConstant invoke_dynamic = cl.GetPool().GetLinkConstant(instr.Operand(0)); if (lambda_methods.Get(invoke_dynamic.index1)) { // lambda invocation found List <PooledConstant> bootstrap_arguments = bootstrap.GetMethodArguments(invoke_dynamic .index1); MethodDescriptor md = MethodDescriptor.ParseDescriptor(invoke_dynamic.descriptor); string lambda_class_name = md.ret.value; string lambda_method_name = invoke_dynamic.elementname; string lambda_method_descriptor = ((PrimitiveConstant)bootstrap_arguments[2]).GetString (); // method type LinkConstant content_method_handle = (LinkConstant)bootstrap_arguments[1]; ClassesProcessor.ClassNode node_lambda = new ClassesProcessor.ClassNode(content_method_handle .classname, content_method_handle.elementname, content_method_handle.descriptor, content_method_handle.index1, lambda_class_name, lambda_method_name, lambda_method_descriptor , cl); node_lambda.simpleName = cl.qualifiedName + "##Lambda_" + invoke_dynamic.index1 + "_" + invoke_dynamic.index2; node_lambda.enclosingMethod = InterpreterUtil.MakeUniqueKey(mt.GetName(), mt.GetDescriptor ()); node.nested.Add(node_lambda); node_lambda.parent = node; Sharpen.Collections.Put(clProcessor.GetMapRootClasses(), node_lambda.simpleName, node_lambda); if (!node_lambda.lambdaInformation.is_method_reference) { Sharpen.Collections.Put(mapMethodsLambda, node_lambda.lambdaInformation.content_method_key , node_lambda.simpleName); } } } } } mt.ReleaseResources(); } // build class hierarchy on lambda foreach (ClassesProcessor.ClassNode nd in node.nested) { if (nd.type == ClassesProcessor.ClassNode.Class_Lambda) { string parent_class_name = mapMethodsLambda.GetOrNull(nd.enclosingMethod); if (parent_class_name != null) { ClassesProcessor.ClassNode parent_class = clProcessor.GetMapRootClasses().GetOrNull (parent_class_name); parent_class.nested.Add(nd); nd.parent = parent_class; } } } }