public virtual string GetDebugName(StructMethod method) { StructLocalVariableTableAttribute attr = method.GetLocalVariableAttr(); if (attr != null && processor != null) { int?origIndex = processor.GetVarOriginalIndex(index); if (origIndex != null) { string name = attr.GetName(origIndex.Value, visibleOffset); if (name != null && TextUtil.IsValidIdentifier(name, method.GetClassStruct().GetBytecodeVersion ())) { return(name); } } } return(null); }
public virtual void SetDebugVarNames(Dictionary <int, string> mapDebugVarNames) { if (varVersions == null) { return; } Dictionary <int, int> mapOriginalVarIndices = varVersions.GetMapOriginalVarIndices (); List <VarVersionPair> listVars = new List <VarVersionPair>(mapVarNames.Keys); listVars.Sort((pair, versionPair) => pair.var.CompareTo(versionPair.var)); Dictionary <string, int> mapNames = new Dictionary <string, int>(); foreach (VarVersionPair pair in listVars) { string name = mapVarNames.GetOrNull(pair); int? index = mapOriginalVarIndices.GetOrNullable(pair.var); if (index != null) { string debugName = mapDebugVarNames.GetOrNull(index.Value); if (debugName != null && TextUtil.IsValidIdentifier(debugName, method.GetClassStruct ().GetBytecodeVersion())) { name = debugName; } } int?counter = mapNames.GetOrNullable(name); Sharpen.Collections.Put(mapNames, name, counter == null ? counter = 0 : ++counter ); if (counter.Value > 0) { name += counter.ToString(); } Sharpen.Collections.Put(mapVarNames, pair, name); } }
public virtual byte[] LoadBytecode(StructMethod mt, int codeFullLength) { string className = mt.GetClassStruct().qualifiedName; try { using (DataInputFullStream @in = GetClassStream(className)) { if (@in != null) { @in.Discard(8); ConstantPool pool = mt.GetClassStruct().GetPool(); if (pool == null) { pool = new ConstantPool(@in); } else { ConstantPool.SkipPool(@in); } @in.Discard(6); // interfaces @in.Discard(@in.ReadUnsignedShort() * 2); // fields int size = @in.ReadUnsignedShort(); for (int i = 0; i < size; i++) { @in.Discard(6); SkipAttributes(@in); } // methods size = @in.ReadUnsignedShort(); for (int i = 0; i < size; i++) { @in.Discard(2); int nameIndex = @in.ReadUnsignedShort(); int descriptorIndex = @in.ReadUnsignedShort(); string[] values = pool.GetClassElement(ConstantPool.Method, className, nameIndex, descriptorIndex); if (!mt.GetName().Equals(values[0]) || !mt.GetDescriptor().Equals(values[1])) { SkipAttributes(@in); continue; } int attrSize = @in.ReadUnsignedShort(); for (int j = 0; j < attrSize; j++) { int attrNameIndex = @in.ReadUnsignedShort(); string attrName = pool.GetPrimitiveConstant(attrNameIndex).GetString(); if (!StructGeneralAttribute.Attribute_Code.GetName().Equals(attrName)) { @in.Discard(@in.ReadInt()); continue; } @in.Discard(12); return(@in.Read(codeFullLength)); } break; } } return(null); } } catch (IOException ex) { throw; } }
private bool ProcessStatementEx(StructMethod mt, RootStatement root, ControlFlowGraph graph) { int bytecode_version = mt.GetClassStruct().GetBytecodeVersion(); LinkedList <Statement> stack = new LinkedList <Statement>(); stack.AddLast(root); while (!(stack.Count == 0)) { Statement stat = Sharpen.Collections.RemoveLast(stack); Statement parent = stat.GetParent(); if (parent != null && parent.type == Statement.Type_Catchall && stat == parent.GetFirst () && !parent.IsCopied()) { CatchAllStatement fin = (CatchAllStatement)parent; BasicBlock head = fin.GetBasichead().GetBlock(); BasicBlock handler = fin.GetHandler().GetBasichead().GetBlock(); if (catchallBlockIDs.ContainsKey(handler.id)) { } else if (finallyBlockIDs.ContainsKey(handler.id)) { // do nothing fin.SetFinally(true); int?var = finallyBlockIDs.GetOrNullable(handler.id); fin.SetMonitor(var == null ? null : new VarExprent(var.Value, VarType.Vartype_Int , varProcessor)); } else { FinallyProcessor.Record inf = GetFinallyInformation(mt, root, fin); if (inf == null) { // inconsistent finally Sharpen.Collections.Put(catchallBlockIDs, handler.id, null); } else { if (DecompilerContext.GetOption(IFernflowerPreferences.Finally_Deinline) && VerifyFinallyEx (graph, fin, inf)) { Sharpen.Collections.Put(finallyBlockIDs, handler.id, null); } else { int varindex = DecompilerContext.GetCounterContainer().GetCounterAndIncrement(CounterContainer .Var_Counter); InsertSemaphore(graph, GetAllBasicBlocks(fin.GetFirst()), head, handler, varindex , inf, bytecode_version); Sharpen.Collections.Put(finallyBlockIDs, handler.id, varindex); } DeadCodeHelper.RemoveDeadBlocks(graph); // e.g. multiple return blocks after a nested finally DeadCodeHelper.RemoveEmptyBlocks(graph); DeadCodeHelper.MergeBasicBlocks(graph); } return(true); } } Sharpen.Collections.AddAll(stack, stat.GetStats()); } return(false); }
private FinallyProcessor.Record GetFinallyInformation(StructMethod mt, RootStatement root, CatchAllStatement fstat) { Dictionary <BasicBlock, bool> mapLast = new Dictionary <BasicBlock, bool>(); BasicBlockStatement firstBlockStatement = fstat.GetHandler().GetBasichead(); BasicBlock firstBasicBlock = firstBlockStatement.GetBlock(); Instruction instrFirst = firstBasicBlock.GetInstruction(0); int firstcode = 0; switch (instrFirst.opcode) { case ICodeConstants.opc_pop: { firstcode = 1; break; } case ICodeConstants.opc_astore: { firstcode = 2; break; } } ExprProcessor proc = new ExprProcessor(methodDescriptor, varProcessor); proc.ProcessStatement(root, mt.GetClassStruct()); SSAConstructorSparseEx ssa = new SSAConstructorSparseEx(); ssa.SplitVariables(root, mt); List <Exprent> lstExprents = firstBlockStatement.GetExprents(); VarVersionPair varpaar = new VarVersionPair((VarExprent)((AssignmentExprent)lstExprents [firstcode == 2 ? 1 : 0]).GetLeft()); FlattenStatementsHelper flatthelper = new FlattenStatementsHelper(); DirectGraph dgraph = flatthelper.BuildDirectGraph(root); LinkedList <DirectNode> stack = new LinkedList <DirectNode>(); stack.AddLast(dgraph.first); HashSet <DirectNode> setVisited = new HashSet <DirectNode>(); while (!(stack.Count == 0)) { DirectNode node = Sharpen.Collections.RemoveFirst(stack); if (setVisited.Contains(node)) { continue; } setVisited.Add(node); BasicBlockStatement blockStatement = null; if (node.block != null) { blockStatement = node.block; } else if (node.preds.Count == 1) { blockStatement = node.preds[0].block; } bool isTrueExit = true; if (firstcode != 1) { isTrueExit = false; for (int i = 0; i < node.exprents.Count; i++) { Exprent exprent = node.exprents[i]; if (firstcode == 0) { List <Exprent> lst = exprent.GetAllExprents(); lst.Add(exprent); bool found = false; foreach (Exprent expr in lst) { if (expr.type == Exprent.Exprent_Var && new VarVersionPair((VarExprent)expr).Equals (varpaar)) { found = true; break; } } if (found) { found = false; if (exprent.type == Exprent.Exprent_Exit) { ExitExprent exexpr = (ExitExprent)exprent; if (exexpr.GetExitType() == ExitExprent.Exit_Throw && exexpr.GetValue().type == Exprent .Exprent_Var) { found = true; } } if (!found) { return(null); } else { isTrueExit = true; } } } else if (firstcode == 2) { // search for a load instruction if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent assexpr = (AssignmentExprent)exprent; if (assexpr.GetRight().type == Exprent.Exprent_Var && new VarVersionPair((VarExprent )assexpr.GetRight()).Equals(varpaar)) { Exprent next = null; if (i == node.exprents.Count - 1) { if (node.succs.Count == 1) { DirectNode nd = node.succs[0]; if (!(nd.exprents.Count == 0)) { next = nd.exprents[0]; } } } else { next = node.exprents[i + 1]; } bool found = false; if (next != null && next.type == Exprent.Exprent_Exit) { ExitExprent exexpr = (ExitExprent)next; if (exexpr.GetExitType() == ExitExprent.Exit_Throw && exexpr.GetValue().type == Exprent .Exprent_Var && assexpr.GetLeft().Equals(exexpr.GetValue())) { found = true; } } if (!found) { return(null); } else { isTrueExit = true; } } } } } } // find finally exits if (blockStatement != null && blockStatement.GetBlock() != null) { Statement handler = fstat.GetHandler(); foreach (StatEdge edge in blockStatement.GetSuccessorEdges(Statement.Statedge_Direct_All )) { if (edge.GetType() != StatEdge.Type_Regular && handler.ContainsStatement(blockStatement ) && !handler.ContainsStatement(edge.GetDestination())) { bool?existingFlag = mapLast.GetOrNullable(blockStatement.GetBlock()); // note: the dummy node is also processed! if (existingFlag == null || !existingFlag.Value) { Sharpen.Collections.Put(mapLast, blockStatement.GetBlock(), isTrueExit); break; } } } } Sharpen.Collections.AddAll(stack, node.succs); } // empty finally block? if (fstat.GetHandler().type == Statement.Type_Basicblock) { bool isEmpty = false; bool isFirstLast = mapLast.ContainsKey(firstBasicBlock); InstructionSequence seq = firstBasicBlock.GetSeq(); switch (firstcode) { case 0: { isEmpty = isFirstLast && seq.Length() == 1; break; } case 1: { isEmpty = seq.Length() == 1; break; } case 2: { isEmpty = isFirstLast ? seq.Length() == 3 : seq.Length() == 1; break; } } if (isEmpty) { firstcode = 3; } } return(new FinallyProcessor.Record(firstcode, mapLast)); }
private void RemoveJsr(StructMethod mt) { RemoveJsrInstructions(mt.GetClassStruct().GetPool(), first, DataPoint.GetInitialDataPoint (mt)); }
/// <exception cref="System.IO.IOException"/> public static RootStatement CodeToJava(StructMethod mt, MethodDescriptor md, VarProcessor varProc) { StructClass cl = mt.GetClassStruct(); bool isInitializer = ICodeConstants.Clinit_Name.Equals(mt.GetName()); // for now static initializer only mt.ExpandData(); InstructionSequence seq = mt.GetInstructionSequence(); ControlFlowGraph graph = new ControlFlowGraph(seq); DeadCodeHelper.RemoveDeadBlocks(graph); graph.InlineJsr(mt); // TODO: move to the start, before jsr inlining DeadCodeHelper.ConnectDummyExitBlock(graph); DeadCodeHelper.RemoveGotos(graph); ExceptionDeobfuscator.RemoveCircularRanges(graph); ExceptionDeobfuscator.RestorePopRanges(graph); if (DecompilerContext.GetOption(IFernflowerPreferences.Remove_Empty_Ranges)) { ExceptionDeobfuscator.RemoveEmptyRanges(graph); } if (DecompilerContext.GetOption(IFernflowerPreferences.Ensure_Synchronized_Monitor )) { // special case: search for 'synchronized' ranges w/o monitorexit instruction (as generated by Kotlin and Scala) DeadCodeHelper.ExtendSynchronizedRangeToMonitorexit(graph); } if (DecompilerContext.GetOption(IFernflowerPreferences.No_Exceptions_Return)) { // special case: single return instruction outside of a protected range DeadCodeHelper.IncorporateValueReturns(graph); } // ExceptionDeobfuscator.restorePopRanges(graph); ExceptionDeobfuscator.InsertEmptyExceptionHandlerBlocks(graph); DeadCodeHelper.MergeBasicBlocks(graph); DecompilerContext.GetCounterContainer().SetCounter(CounterContainer.Var_Counter, mt.GetLocalVariables()); if (ExceptionDeobfuscator.HasObfuscatedExceptions(graph)) { DecompilerContext.GetLogger().WriteMessage("Heavily obfuscated exception ranges found!" , IFernflowerLogger.Severity.Warn); if (!ExceptionDeobfuscator.HandleMultipleEntryExceptionRanges(graph)) { DecompilerContext.GetLogger().WriteMessage("Found multiple entry exception ranges which could not be splitted" , IFernflowerLogger.Severity.Warn); } ExceptionDeobfuscator.InsertDummyExceptionHandlerBlocks(graph, cl.GetBytecodeVersion ()); } RootStatement root = DomHelper.ParseGraph(graph); FinallyProcessor fProc = new FinallyProcessor(md, varProc); while (fProc.IterateGraph(mt, root, graph)) { root = DomHelper.ParseGraph(graph); } // remove synchronized exception handler // not until now because of comparison between synchronized statements in the finally cycle DomHelper.RemoveSynchronizedHandler(root); // LabelHelper.lowContinueLabels(root, new HashSet<StatEdge>()); SequenceHelper.CondenseSequences(root); ClearStructHelper.ClearStatements(root); ExprProcessor proc = new ExprProcessor(md, varProc); proc.ProcessStatement(root, cl); SequenceHelper.CondenseSequences(root); StackVarsProcessor stackProc = new StackVarsProcessor(); do { stackProc.SimplifyStackVars(root, mt, cl); varProc.SetVarVersions(root); }while (new PPandMMHelper().FindPPandMM(root)); while (true) { LabelHelper.CleanUpEdges(root); do { MergeHelper.EnhanceLoops(root); }while (LoopExtractHelper.ExtractLoops(root) || IfHelper.MergeAllIfs(root)); if (DecompilerContext.GetOption(IFernflowerPreferences.Idea_Not_Null_Annotation)) { if (IdeaNotNullHelper.RemoveHardcodedChecks(root, mt)) { SequenceHelper.CondenseSequences(root); stackProc.SimplifyStackVars(root, mt, cl); varProc.SetVarVersions(root); } } LabelHelper.IdentifyLabels(root); if (InlineSingleBlockHelper.InlineSingleBlocks(root)) { continue; } // initializer may have at most one return point, so no transformation of method exits permitted if (isInitializer || !ExitHelper.CondenseExits(root)) { break; } } // FIXME: !! //if(!EliminateLoopsHelper.eliminateLoops(root)) { // break; //} ExitHelper.RemoveRedundantReturns(root); SecondaryFunctionsHelper.IdentifySecondaryFunctions(root, varProc); varProc.SetVarDefinitions(root); // must be the last invocation, because it makes the statement structure inconsistent // FIXME: new edge type needed LabelHelper.ReplaceContinueWithBreak(root); mt.ReleaseResources(); return(root); }