- method attribute 'default' (Java 8)

- instruction 'invokedynamic' (Java 7)
- bugfixing
This commit is contained in:
Stiver 2014-03-13 23:02:30 +01:00
parent c9c426ded7
commit 96379678e6
16 changed files with 419 additions and 301 deletions

View File

@ -16,6 +16,16 @@ package de.fernflower.code;
public interface CodeConstants {
// ----------------------------------------------------------------------
// BYTECODE VERSIONS
// ----------------------------------------------------------------------
public final static int BYTECODE_JAVA_LE_4 = 1;
public final static int BYTECODE_JAVA_5 = 2;
public final static int BYTECODE_JAVA_6 = 3;
public final static int BYTECODE_JAVA_7 = 4;
public final static int BYTECODE_JAVA_8 = 5;
// ----------------------------------------------------------------------
// VARIABLE TYPES
// ----------------------------------------------------------------------
@ -339,6 +349,7 @@ public interface CodeConstants {
public final static int opc_invokespecial = 183;
public final static int opc_invokestatic = 184;
public final static int opc_invokeinterface = 185;
public final static int opc_invokedynamic = 186;
public final static int opc_xxxunusedxxx = 186;
public final static int opc_new = 187;
public final static int opc_newarray = 188;

View File

@ -30,6 +30,7 @@ import de.fernflower.code.optinstructions.GOTO_W;
import de.fernflower.code.optinstructions.IINC;
import de.fernflower.code.optinstructions.ILOAD;
import de.fernflower.code.optinstructions.INSTANCEOF;
import de.fernflower.code.optinstructions.INVOKEDYNAMIC;
import de.fernflower.code.optinstructions.INVOKEINTERFACE;
import de.fernflower.code.optinstructions.INVOKESPECIAL;
import de.fernflower.code.optinstructions.INVOKESTATIC;
@ -58,17 +59,18 @@ public class ConstantsUtil {
return opcodeNames[opcode];
}
public static Instruction getInstructionInstance(int opcode, boolean wide, int group, int[] operands) {
public static Instruction getInstructionInstance(int opcode, boolean wide, int group, int bytecode_version, int[] operands) {
Instruction instr = getInstructionInstance(opcode);
Instruction instr = getInstructionInstance(opcode, bytecode_version);
instr.wide = wide;
instr.group = group;
instr.bytecode_version = bytecode_version;
instr.setOperands(operands);
return instr;
}
public static Instruction getInstructionInstance(int opcode) {
private static Instruction getInstructionInstance(int opcode, int bytecode_version) {
try {
Instruction instr;
@ -78,7 +80,13 @@ public class ConstantsUtil {
opcode == CodeConstants.opc_ifnonnull) {
instr = new IfInstruction();
} else {
Class cl = opcodeClasses[opcode];
if(opcode == CodeConstants.opc_invokedynamic && bytecode_version < CodeConstants.BYTECODE_JAVA_7) {
cl = null; // instruction unused in Java 6 and before
}
if(cl == null) {
instr = new Instruction();
} else {
@ -282,7 +290,8 @@ public class ConstantsUtil {
"invokespecial", // "invokespecial",
"invokestatic", // "invokestatic",
"invokeinterface", // "invokeinterface",
"xxxunusedxxx", // "xxxunusedxxx",
//"xxxunusedxxx", // "xxxunusedxxx", Java 6 and before
"invokedynamic", // "invokedynamic", Java 7 and later
"new", // "new",
"newarray", // "newarray",
"anewarray", // "anewarray",
@ -487,7 +496,7 @@ public class ConstantsUtil {
INVOKESPECIAL.class, // "invokespecial",
INVOKESTATIC.class, // "invokestatic",
INVOKEINTERFACE.class, // "invokeinterface",
null , // "xxxunusedxxx",
INVOKEDYNAMIC.class, // "xxxunusedxxx" Java 6 and before, "invokedynamic" Java 7 and later
NEW.class, // "new",
NEWARRAY.class, // "newarray",
ANEWARRAY.class, // "anewarray",

View File

@ -29,6 +29,7 @@ public class Instruction implements CodeConstants {
public boolean wide = false;
public int bytecode_version = BYTECODE_JAVA_LE_4;
// *****************************************************************************
// private fields
@ -55,7 +56,7 @@ public class Instruction implements CodeConstants {
}
public Instruction clone() {
return ConstantsUtil.getInstructionInstance(opcode, wide, group, operands==null?null:(int[])operands.clone());
return ConstantsUtil.getInstructionInstance(opcode, wide, group, bytecode_version, operands==null?null:(int[])operands.clone());
}
public String toString() {

View File

@ -413,6 +413,8 @@ public class InstructionImpact {
case CodeConstants.opc_invokeinterface:
stack.pop();
case CodeConstants.opc_invokestatic:
case CodeConstants.opc_invokedynamic:
if(instr.opcode != CodeConstants.opc_invokedynamic || instr.bytecode_version >= CodeConstants.BYTECODE_JAVA_7) {
ck = pool.getLinkConstant(instr.getOperand(0));
MethodDescriptor md = MethodDescriptor.parseDescriptor(ck.descriptor);
for(int i=0;i<md.params.length;i++) {
@ -424,6 +426,7 @@ public class InstructionImpact {
stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY));
}
}
}
break;
case CodeConstants.opc_new:
cn = pool.getPrimitiveConstant(instr.getOperand(0));

View File

@ -0,0 +1,20 @@
package de.fernflower.code.optinstructions;
import java.io.DataOutputStream;
import java.io.IOException;
import de.fernflower.code.Instruction;
public class INVOKEDYNAMIC extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_invokedynamic);
out.writeShort(getOperand(0));
out.writeByte(0);
out.writeByte(0);
}
public int length() {
return 5;
}
}

View File

@ -95,16 +95,19 @@ public class ClassReference14Processor {
ClassWrapper wrapper = node.wrapper;
int major_version = wrapper.getClassStruct().major_version;
int minor_version = wrapper.getClassStruct().minor_version;
// int major_version = wrapper.getClassStruct().major_version;
// int minor_version = wrapper.getClassStruct().minor_version;
//
// if(major_version > 48 || (major_version == 48 && minor_version > 0)) {
// // version 1.5 or above
// return;
// }
if(major_version > 48 || (major_version == 48 && minor_version > 0)) {
if(wrapper.getClassStruct().isVersionGE_1_5()) {
// version 1.5 or above
return;
}
// find the synthetic method Class class$(String) if present
HashMap<ClassWrapper, MethodWrapper> mapClassMeths = new HashMap<ClassWrapper, MethodWrapper>();
findClassMethod(node, mapClassMeths);

View File

@ -587,6 +587,11 @@ public class ClassWriter {
}
}
// 'default' modifier (Java 8)
if(isInterface && mt.containsCode()) {
bufstrwriter.write("default ");
}
GenericMethodDescriptor descriptor = null;
if(DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) {
StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute)mt.getAttributes().getWithKey("Signature");

View File

@ -142,7 +142,7 @@ public class MethodProcessorThread implements Runnable {
DecompilerContext.getCountercontainer().setCounter(CounterContainer.VAR_COUNTER, mt.getLocalVariables());
//DotExporter.toDotFile(graph, new File("c:\\Temp\\fern3.dot"), true);
System.out.println(graph.toString());
//System.out.println(graph.toString());
if(ExceptionDeobfuscator.hasObfuscatedExceptions(graph)) {
DecompilerContext.getLogger().writeMessage("Heavily obfuscated exception ranges found!", IFernflowerLogger.WARNING);
@ -157,7 +157,7 @@ public class MethodProcessorThread implements Runnable {
//DotExporter.toDotFile(graph, new File("c:\\Temp\\fern2.dot"), true);
//System.out.println(graph.toString());
System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
//System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
root = DomHelper.parseGraph(graph);
}

View File

@ -527,12 +527,15 @@ public class ExprProcessor implements CodeConstants {
case opc_invokespecial:
case opc_invokestatic:
case opc_invokeinterface:
case opc_invokedynamic:
if(instr.opcode != opc_invokedynamic || instr.bytecode_version >= CodeConstants.BYTECODE_JAVA_7) {
InvocationExprent exprinv = new InvocationExprent(instr.opcode, pool.getLinkConstant(instr.getOperand(0)), stack);
if (exprinv.getDescriptor().ret.type == CodeConstants.TYPE_VOID) {
exprlist.add(exprinv);
} else {
pushEx(stack, exprlist, exprinv);
}
}
break;
case opc_new:
case opc_anewarray:

View File

@ -14,16 +14,13 @@
package de.fernflower.modules.decompiler;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import test.util.DotExporter;
import de.fernflower.code.CodeConstants;
import de.fernflower.code.ConstantsUtil;
import de.fernflower.code.Instruction;
@ -73,6 +70,8 @@ public class FinallyProcessor {
private boolean processStatementEx(StructMethod mt, RootStatement root, ControlFlowGraph graph) {
int bytecode_version = mt.getClassStruct().getBytecodeVersion();
LinkedList<Statement> stack = new LinkedList<Statement>();
stack.add(root);
@ -110,7 +109,7 @@ public class FinallyProcessor {
} else {
int varindex = DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER);
insertSemaphore(graph, getAllBasicBlocks(fin.getFirst()), head, handler, varindex, inf);
insertSemaphore(graph, getAllBasicBlocks(fin.getFirst()), head, handler, varindex, inf, bytecode_version);
finallyBlockIDs.put(handler.id, varindex);
}
@ -360,7 +359,7 @@ public class FinallyProcessor {
return new Object[] {firstcode, mapLast};
}
private void insertSemaphore(ControlFlowGraph graph, HashSet<BasicBlock> setTry, BasicBlock head, BasicBlock handler, int var, Object[] information) {
private void insertSemaphore(ControlFlowGraph graph, HashSet<BasicBlock> setTry, BasicBlock head, BasicBlock handler, int var, Object[] information, int bytecode_version) {
HashSet<BasicBlock> setCopy = new HashSet<BasicBlock>(setTry);
@ -389,8 +388,8 @@ public class FinallyProcessor {
// disable semaphore
SimpleInstructionSequence seq = new SimpleInstructionSequence();
seq.addInstruction(ConstantsUtil.getInstructionInstance(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, new int[]{0}) , -1);
seq.addInstruction(ConstantsUtil.getInstructionInstance(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, new int[]{var}) , -1);
seq.addInstruction(ConstantsUtil.getInstructionInstance(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{0}) , -1);
seq.addInstruction(ConstantsUtil.getInstructionInstance(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{var}) , -1);
// build a separate block
BasicBlock newblock = new BasicBlock(++graph.last_id);
@ -419,8 +418,8 @@ public class FinallyProcessor {
// enable semaphor at the statement entrance
SimpleInstructionSequence seq = new SimpleInstructionSequence();
seq.addInstruction(ConstantsUtil.getInstructionInstance(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, new int[]{1}) , -1);
seq.addInstruction(ConstantsUtil.getInstructionInstance(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, new int[]{var}) , -1);
seq.addInstruction(ConstantsUtil.getInstructionInstance(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{1}) , -1);
seq.addInstruction(ConstantsUtil.getInstructionInstance(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{var}) , -1);
BasicBlock newhead = new BasicBlock(++graph.last_id);
newhead.setSeq(seq);
@ -429,8 +428,8 @@ public class FinallyProcessor {
// initialize semaphor with false
seq = new SimpleInstructionSequence();
seq.addInstruction(ConstantsUtil.getInstructionInstance(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, new int[]{0}) , -1);
seq.addInstruction(ConstantsUtil.getInstructionInstance(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, new int[]{var}) , -1);
seq.addInstruction(ConstantsUtil.getInstructionInstance(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{0}) , -1);
seq.addInstruction(ConstantsUtil.getInstructionInstance(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{var}) , -1);
BasicBlock newheadinit = new BasicBlock(++graph.last_id);
newheadinit.setSeq(seq);
@ -566,9 +565,9 @@ public class FinallyProcessor {
lstAreas.add(new Object[] {start, arr[0], arr[1]});
}
try {
DotExporter.toDotFile(graph, new File("c:\\Temp\\fern5.dot"), true);
} catch(Exception ex){ex.printStackTrace();}
// try {
// DotExporter.toDotFile(graph, new File("c:\\Temp\\fern5.dot"), true);
// } catch(Exception ex){ex.printStackTrace();}
// delete areas
for(Object[] area: lstAreas) {
@ -941,6 +940,10 @@ public class FinallyProcessor {
// remove all the blocks inbetween
for(BasicBlock block: setBlocks) {
// artificial basic blocks (those resulted from splitting)
// can belong to more than one area
if(graph.getBlocks().containsKey(block.id)) {
if(!block.getSuccExceptions().containsAll(setCommonExceptionHandlers)) {
is_outside_range = true;
}
@ -956,10 +959,6 @@ public class FinallyProcessor {
setCommonRemovedExceptionRanges.retainAll(setRemovedExceptionRanges);
}
// artificial basic blocks (those resulted from splitting)
// can belong to more than one area
if(graph.getBlocks().containsKey(block.id)) {
// shift extern edges on splitted blocks
if(block.getSeq().isEmpty() && block.getSuccs().size() == 1) {
BasicBlock succs = block.getSuccs().get(0);

View File

@ -43,6 +43,7 @@ public class InvocationExprent extends Exprent {
public static final int INVOKE_VIRTUAL = 2;
public static final int INVOKE_STATIC = 3;
public static final int INVOKE_INTERFACE = 4;
public static final int INVOKE_DYNAMIC = 5;
public static final int TYP_GENERAL = 1;
public static final int TYP_INIT = 2;
@ -93,6 +94,10 @@ public class InvocationExprent extends Exprent {
break;
case CodeConstants.opc_invokeinterface:
invocationTyp = INVOKE_INTERFACE;
break;
case CodeConstants.opc_invokedynamic:
invocationTyp = INVOKE_DYNAMIC;
classname = "java/lang/Class"; // dummy class name
}
if("<init>".equals(name)) {
@ -108,7 +113,7 @@ public class InvocationExprent extends Exprent {
lstParameters.add(0, stack.pop());
}
if(opcode == CodeConstants.opc_invokestatic) {
if(opcode == CodeConstants.opc_invokestatic || opcode == CodeConstants.opc_invokedynamic) {
isStatic = true;
} else {
instance = stack.pop();
@ -174,10 +179,12 @@ public class InvocationExprent extends Exprent {
boolean isInstanceThis = false;
if(isStatic) {
if(invocationTyp != INVOKE_DYNAMIC) {
ClassNode node = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASSNODE);
if(node == null || !classname.equals(node.classStruct.qualifiedName)) {
buf.append(DecompilerContext.getImpcollector().getShortName(ExprProcessor.buildJavaClassName(classname)));
}
}
} else {
if(instance != null && instance.type == Exprent.EXPRENT_VAR) {
@ -249,7 +256,12 @@ public class InvocationExprent extends Exprent {
buf.append(".");
}
buf.append(name+"(");
buf.append(name);
if(invocationTyp == INVOKE_DYNAMIC) {
buf.append("<invokedynamic>");
}
buf.append("(");
break;
case TYP_CLINIT:
throw new RuntimeException("Explicite invocation of <clinit>");

View File

@ -408,17 +408,19 @@ public class FlattenStatementsHelper {
if(finallyShortRangeSource != null) {
boolean isContinueEdge = (edgetype == StatEdge.TYPE_CONTINUE);
List<String[]> lst = mapShortRangeFinallyPathIds.get(sourcenode.id);
if(lst == null) {
mapShortRangeFinallyPathIds.put(sourcenode.id, lst = new ArrayList<String[]>());
}
lst.add(new String[]{finallyShortRangeSource.id, destination.id.toString(), finallyShortRangeEntry.id.toString(), isFinallyMonitorExceptionPath?"1":null});
lst.add(new String[]{finallyShortRangeSource.id, destination.id.toString(), finallyShortRangeEntry.id.toString(), isFinallyMonitorExceptionPath?"1":null, isContinueEdge?"1":null});
lst = mapLongRangeFinallyPathIds.get(sourcenode.id);
if(lst == null) {
mapLongRangeFinallyPathIds.put(sourcenode.id, lst = new ArrayList<String[]>());
}
lst.add(new String[]{finallyLongRangeSource.id, destination.id.toString(), finallyLongRangeEntry.id.toString()});
lst.add(new String[]{finallyLongRangeSource.id, destination.id.toString(), finallyLongRangeEntry.id.toString(), isContinueEdge?"1":null});
}
}
@ -454,7 +456,10 @@ public class FlattenStatementsHelper {
List<String[]> lst = ent.getValue();
for(String[] arr : lst) {
DirectNode dest = graph.nodes.getWithKey(mapDestinationNodes.get(Integer.parseInt(arr[1]))[0]);
boolean isContinueEdge = arr[i==0?4:3] != null;
DirectNode dest = graph.nodes.getWithKey(mapDestinationNodes.get(Integer.parseInt(arr[1]))[isContinueEdge?1:0]);
DirectNode enter = graph.nodes.getWithKey(mapDestinationNodes.get(Integer.parseInt(arr[2]))[0]);
newLst.add(new FinallyPathWrapper(arr[0], dest.id, enter.id));
@ -505,6 +510,10 @@ public class FlattenStatementsHelper {
public int hashCode() {
return (source+":"+destination+":"+entry).hashCode();
}
public String toString() {
return source + "->(" + entry + ")->" + destination;
}
}

View File

@ -14,12 +14,14 @@
package de.fernflower.modules.decompiler.sforms;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import test.util.DotExporter;
import de.fernflower.code.CodeConstants;
import de.fernflower.modules.decompiler.exps.AssignmentExprent;
import de.fernflower.modules.decompiler.exps.Exprent;
@ -34,9 +36,9 @@ import de.fernflower.modules.decompiler.vars.VarVersionPaar;
import de.fernflower.struct.StructMethod;
import de.fernflower.struct.gen.MethodDescriptor;
import de.fernflower.util.FastSparseSetFactory;
import de.fernflower.util.FastSparseSetFactory.FastSparseSet;
import de.fernflower.util.InterpreterUtil;
import de.fernflower.util.SFormsFastMapDirect;
import de.fernflower.util.FastSparseSetFactory.FastSparseSet;
public class SSAConstructorSparseEx {
@ -99,6 +101,16 @@ public class SSAConstructorSparseEx {
for(DirectNode node : dgraph.nodes) {
// if (node.id.endsWith("_inc")) {
// System.out.println();
//
// try {
// DotExporter.toDotFile(dgraph, new File("c:\\Temp\\gr1_my.dot"));
// } catch (Exception ex) {
// ex.printStackTrace();
// }
// }
updated.remove(node.id);
mergeInVarMaps(node, dgraph);
@ -140,7 +152,6 @@ public class SSAConstructorSparseEx {
return;
}
VarExprent varassign = null;
boolean finished = false;
@ -212,7 +223,6 @@ public class SSAConstructorSparseEx {
return;
}
List<Exprent> lst = expr.getAllExprents();
lst.remove(varassign);
@ -220,7 +230,6 @@ public class SSAConstructorSparseEx {
processExprent(ex, varmaparr);
}
SFormsFastMapDirect varmap = varmaparr[0];
if (varassign != null) {
@ -309,8 +318,7 @@ public class SSAConstructorSparseEx {
inVarVersions.put(node.id, mapNew);
}
private SFormsFastMapDirect getFilteredOutMap(String nodeid, String predid, DirectGraph dgraph,
String destid) {
private SFormsFastMapDirect getFilteredOutMap(String nodeid, String predid, DirectGraph dgraph, String destid) {
SFormsFastMapDirect mapNew = new SFormsFastMapDirect();
@ -396,7 +404,6 @@ public class SSAConstructorSparseEx {
return mapNew;
}
private SFormsFastMapDirect mergeMaps(SFormsFastMapDirect mapTo, SFormsFastMapDirect map2) {
if (map2 != null && !map2.isEmpty()) {
@ -427,7 +434,6 @@ public class SSAConstructorSparseEx {
return true;
}
private void setCurrentVar(SFormsFastMapDirect varmap, Integer var, Integer vers) {
FastSparseSet<Integer> set = factory.spawnEmptySet();
set.add(vers);

View File

@ -146,6 +146,7 @@ public class SSAUConstructorSparseEx {
|| (outNegVarVersions.containsKey(node.id) && !mapsEqual(varmaparr[1], outNegVarVersions.get(node.id)));
if(this_updated) {
outVarVersions.put(node.id, varmaparr[0]);
if(dgraph.mapNegIfBranch.containsKey(node.id)) {
outNegVarVersions.put(node.id, varmaparr[1]);
@ -246,45 +247,45 @@ public class SSAUConstructorSparseEx {
SFormsFastMapDirect varmap = varmaparr[0];
// field access
if(expr.type == Exprent.EXPRENT_FIELD) {
int index;
if(mapFieldVars.containsKey(expr.id)) {
index = mapFieldVars.get(expr.id);
} else {
index = fieldvarcounter--;
mapFieldVars.put(expr.id, index);
// ssu graph
ssuversions.createNode(new VarVersionPaar(index, 1));
}
setCurrentVar(varmap, index, 1);
} else if(expr.type == Exprent.EXPRENT_INVOCATION ||
(expr.type == Exprent.EXPRENT_ASSIGNMENT && ((AssignmentExprent)expr).getLeft().type == Exprent.EXPRENT_FIELD) ||
(expr.type == Exprent.EXPRENT_NEW && ((NewExprent)expr).getNewtype().type == CodeConstants.TYPE_OBJECT) ||
expr.type == Exprent.EXPRENT_FUNCTION) {
boolean ismmpp = true;
if(expr.type == Exprent.EXPRENT_FUNCTION) {
ismmpp = false;
FunctionExprent fexpr = (FunctionExprent)expr;
if(fexpr.getFunctype() >= FunctionExprent.FUNCTION_IMM && fexpr.getFunctype() <= FunctionExprent.FUNCTION_PPI) {
if(fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD) {
ismmpp = true;
}
}
}
if(ismmpp) {
varmap.removeAllFields();
}
}
// // field access
// if(expr.type == Exprent.EXPRENT_FIELD) {
//
// int index;
// if(mapFieldVars.containsKey(expr.id)) {
// index = mapFieldVars.get(expr.id);
// } else {
// index = fieldvarcounter--;
// mapFieldVars.put(expr.id, index);
//
// // ssu graph
// ssuversions.createNode(new VarVersionPaar(index, 1));
// }
//
// setCurrentVar(varmap, index, 1);
//
// } else if(expr.type == Exprent.EXPRENT_INVOCATION ||
// (expr.type == Exprent.EXPRENT_ASSIGNMENT && ((AssignmentExprent)expr).getLeft().type == Exprent.EXPRENT_FIELD) ||
// (expr.type == Exprent.EXPRENT_NEW && ((NewExprent)expr).getNewtype().type == CodeConstants.TYPE_OBJECT) ||
// expr.type == Exprent.EXPRENT_FUNCTION) {
//
// boolean ismmpp = true;
//
// if(expr.type == Exprent.EXPRENT_FUNCTION) {
//
// ismmpp = false;
//
// FunctionExprent fexpr = (FunctionExprent)expr;
// if(fexpr.getFunctype() >= FunctionExprent.FUNCTION_IMM && fexpr.getFunctype() <= FunctionExprent.FUNCTION_PPI) {
// if(fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD) {
// ismmpp = true;
// }
// }
// }
//
// if(ismmpp) {
// varmap.removeAllFields();
// }
// }
if(varassign != null) {

View File

@ -22,6 +22,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import de.fernflower.code.CodeConstants;
import de.fernflower.struct.attr.StructGeneralAttribute;
import de.fernflower.struct.consts.ConstantPool;
import de.fernflower.struct.consts.PrimitiveConstant;
@ -318,4 +319,26 @@ public class StructClass {
return loader;
}
public boolean isVersionGE_1_5() {
return (major_version > 48 || (major_version == 48 && minor_version > 0)); // FIXME: check second condition
}
public boolean isVersionGE_1_7() {
return (major_version >= 51);
}
public int getBytecodeVersion() {
switch(major_version) {
case 52:
return CodeConstants.BYTECODE_JAVA_8;
case 51:
return CodeConstants.BYTECODE_JAVA_7;
case 50:
return CodeConstants.BYTECODE_JAVA_6;
case 49:
return CodeConstants.BYTECODE_JAVA_5;
}
return CodeConstants.BYTECODE_JAVA_LE_4;
}
}

View File

@ -280,6 +280,8 @@ public class StructMethod implements CodeConstants {
VBStyleCollection<Instruction, Integer> collinstr = new VBStyleCollection<Instruction, Integer>();
int bytecode_version = classStruct.getBytecodeVersion();
for(int i=0;i<length;) {
int offset = i;
@ -362,6 +364,14 @@ public class StructMethod implements CodeConstants {
group = GROUP_INVOCATION;
}
break;
case opc_invokedynamic:
if(classStruct.isVersionGE_1_7()) { // instruction unused in Java 6 and before
operands.add(new Integer(in.readUnsignedShort()));
in.skip(2);
group = GROUP_INVOCATION;
i+=4;
}
break;
case opc_iload:
case opc_lload:
case opc_fload:
@ -466,7 +476,7 @@ public class StructMethod implements CodeConstants {
ops[j] = ((Integer)operands.get(j)).intValue();
}
Instruction instr = ConstantsUtil.getInstructionInstance(opcode, wide, group, ops);
Instruction instr = ConstantsUtil.getInstructionInstance(opcode, wide, group, bytecode_version, ops);
collinstr.addWithKey(instr, new Integer(offset));
@ -542,6 +552,9 @@ public class StructMethod implements CodeConstants {
return classStruct;
}
public boolean containsCode() {
return containsCode;
}
}