public String getShortName(String fullName, boolean imported) { ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(fullName.replace('.', '/')); String result = null; if (node != null && node.classStruct.isOwn()) { result = node.simpleName; while (node.parent != null && node.type == ClassNode.CLASS_MEMBER) { result = node.parent.simpleName + '.' + result; node = node.parent; } if (node.type == ClassNode.CLASS_ROOT) { fullName = node.classStruct.qualifiedName; fullName = fullName.replace('/', '.'); } else { return result; } } else { fullName = fullName.replace('$', '.'); } String shortName = fullName; String packageName = ""; int lastDot = fullName.lastIndexOf('.'); if (lastDot >= 0) { shortName = fullName.substring(lastDot + 1); packageName = fullName.substring(0, lastDot); } StructContext context = DecompilerContext.getStructContext(); // check for another class which could 'shadow' this one. Two cases: // 1) class with the same short name in the current package // 2) class with the same short name in the default package boolean existsDefaultClass = (context.getClass(currentPackageSlash + shortName) != null && !packageName.equals(currentPackagePoint)) || // current package (context.getClass(shortName) != null && !currentPackagePoint.isEmpty()); // default package if (existsDefaultClass || (mapSimpleNames.containsKey(shortName) && !packageName.equals(mapSimpleNames.get(shortName)))) { // don't return full name because if the class is a inner class, full name refers to the // parent full name, not the child full name return result == null ? fullName : (packageName + "." + result); } else if (!mapSimpleNames.containsKey(shortName)) { mapSimpleNames.put(shortName, packageName); if (!imported) { setNotImportedNames.add(shortName); } } return result == null ? shortName : result; }
@Override public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { tracer.addMapping(bytecode); if (exitType == EXIT_RETURN) { TextBuffer buffer = new TextBuffer("return"); if (retType.type != CodeConstants.TYPE_VOID) { buffer.append(' '); ExprProcessor.getCastedExprent(value, retType, buffer, indent, false, tracer); } return buffer; } else { MethodWrapper method = (MethodWrapper) DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER); ClassNode node = ((ClassNode) DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE)); if (method != null && node != null) { StructExceptionsAttribute attr = (StructExceptionsAttribute) method.methodStruct.getAttributes().getWithKey("Exceptions"); if (attr != null) { String classname = null; for (int i = 0; i < attr.getThrowsExceptions().size(); i++) { String exClassName = attr.getExcClassname(i, node.classStruct.getPool()); if ("java/lang/Throwable".equals(exClassName)) { classname = exClassName; break; } else if ("java/lang/Exception".equals(exClassName)) { classname = exClassName; } } if (classname != null) { VarType exType = new VarType(classname, true); TextBuffer buffer = new TextBuffer("throw "); ExprProcessor.getCastedExprent(value, exType, buffer, indent, false, tracer); return buffer; } } } return value.toJava(indent, tracer).prepend("throw "); } }
@Override public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buffer = new TextBuffer(); tracer.addMapping(bytecode); if (classdef) { ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(vartype.value); new ClassWriter().classToJava(child, buffer, indent, tracer); } else { String name = null; if (processor != null) { name = processor.getVarName(new VarVersionPaar(index, version)); } if (definition) { if (processor != null && processor.getVarFinal(new VarVersionPaar(index, version)) == VarTypeProcessor.VAR_FINALEXPLICIT) { buffer.append("final "); } buffer.append(ExprProcessor.getCastTypeName(getVartype())).append(" "); } buffer.append(name == null ? ("var" + index + (version == 0 ? "" : "_" + version)) : name); } return buffer; }
@Override public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buffer = new TextBuffer(); buffer.appendIndent(indent); buffer.append('@'); buffer.append( DecompilerContext.getImportCollector() .getShortName(ExprProcessor.buildJavaClassName(className))); int type = getAnnotationType(); if (type != ANNOTATION_MARKER) { buffer.append('('); boolean oneLiner = type == ANNOTATION_SINGLE_ELEMENT || indent < 0; for (int i = 0; i < parNames.size(); i++) { if (!oneLiner) { buffer.appendLineSeparator().appendIndent(indent + 1); } if (type != ANNOTATION_SINGLE_ELEMENT) { buffer.append(parNames.get(i)); buffer.append(" = "); } buffer.append(parValues.get(i).toJava(0, tracer)); if (i < parNames.size() - 1) { buffer.append(','); } } if (!oneLiner) { buffer.appendLineSeparator().appendIndent(indent); } buffer.append(')'); } return buffer; }
public void setVarVersions(RootStatement root) { StructMethod mt = (StructMethod) DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD); SSAConstructorSparseEx ssa = new SSAConstructorSparseEx(); ssa.splitVariables(root, mt); FlattenStatementsHelper flattenHelper = new FlattenStatementsHelper(); DirectGraph graph = flattenHelper.buildDirectGraph(root); mergePhiVersions(ssa, graph); typeProcessor = new VarTypeProcessor(); typeProcessor.calculateVarTypes(root, graph); simpleMerge(typeProcessor, graph, mt); // FIXME: advanced merging eliminateNonJavaTypes(typeProcessor); setNewVarIndices(typeProcessor, graph); }
private void setNewVarIndices(VarTypeProcessor typeProcessor, DirectGraph graph) { final Map<VarVersionPair, VarType> mapExprentMaxTypes = typeProcessor.getMapExprentMaxTypes(); Map<VarVersionPair, VarType> mapExprentMinTypes = typeProcessor.getMapExprentMinTypes(); Map<VarVersionPair, Integer> mapFinalVars = typeProcessor.getMapFinalVars(); CounterContainer counters = DecompilerContext.getCounterContainer(); final Map<VarVersionPair, Integer> mapVarPaar = new HashMap<VarVersionPair, Integer>(); Map<Integer, Integer> mapOriginalVarIndices = new HashMap<Integer, Integer>(); // map var-version pairs on new var indexes Set<VarVersionPair> set = new HashSet<VarVersionPair>(mapExprentMinTypes.keySet()); for (VarVersionPair pair : set) { if (pair.version >= 0) { int newIndex = pair.version == 1 ? pair.var : counters.getCounterAndIncrement(CounterContainer.VAR_COUNTER); VarVersionPair newVar = new VarVersionPair(newIndex, 0); mapExprentMinTypes.put(newVar, mapExprentMinTypes.get(pair)); mapExprentMaxTypes.put(newVar, mapExprentMaxTypes.get(pair)); if (mapFinalVars.containsKey(pair)) { mapFinalVars.put(newVar, mapFinalVars.remove(pair)); } mapVarPaar.put(pair, newIndex); mapOriginalVarIndices.put(newIndex, pair.var); } } // set new vars graph.iterateExprents( new DirectGraph.ExprentIterator() { @Override public int processExprent(Exprent exprent) { List<Exprent> lst = exprent.getAllExprents(true); lst.add(exprent); for (Exprent expr : lst) { if (expr.type == Exprent.EXPRENT_VAR) { VarExprent newVar = (VarExprent) expr; Integer newVarIndex = mapVarPaar.get(new VarVersionPair(newVar)); if (newVarIndex != null) { newVar.setIndex(newVarIndex); newVar.setVersion(0); } } else if (expr.type == Exprent.EXPRENT_CONST) { VarType maxType = mapExprentMaxTypes.get(new VarVersionPair(expr.id, -1)); if (maxType != null && maxType.equals(VarType.VARTYPE_CHAR)) { ((ConstExprent) expr).setConstType(maxType); } } } return 0; } }); this.mapOriginalVarIndices = mapOriginalVarIndices; }
{ // set statement id id = DecompilerContext.getCounterContainer() .getCounterAndIncrement(CounterContainer.STATEMENT_COUNTER); }