Interpret method with constant args

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@542 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 42dfa8092d
commit c8b176e899
  1. 120
      jode/jode/obfuscator/ConstantAnalyzer.java

@ -19,11 +19,14 @@
package jode.obfuscator;
import jode.MethodType;
import jode.Obfuscator;
import jode.Type;
import jode.bytecode.*;
import jode.jvm.InterpreterException;
import java.util.*;
import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.lang.reflect.InvocationTargetException;
interface ConstantListener {
public void constantChanged();
@ -120,6 +123,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
BytecodeInfo bytecode;
Hashtable constInfos = null;
Stack instrStack;
ConstantRuntimeEnvironment runtime;
final static int REACHABLE = 0x1;
final static int CONSTANT = 0x2;
@ -261,6 +265,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
public ConstantAnalyzer(BytecodeInfo code, MethodIdentifier method) {
this.bytecode = code;
this.m = method;
this.runtime = new ConstantRuntimeEnvironment(m);
}
public void mergeInfo(Instruction instr,
@ -968,20 +973,75 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
case opc_invokeinterface:
case opc_invokevirtual: {
Reference ref = (Reference) instr.objData;
handleReference(ref, opcode == opc_invokevirtual
|| opcode == opc_invokeinterface);
MethodType mt = (MethodType) Type.tType(ref.getType());
int size = (opcode == opc_invokestatic) ? 0 : 1;
for (int i=mt.getParameterTypes().length-1; i >=0; i--)
boolean constant = true;
int size = 0;
Object cls = null;
Object[] args = new Object[mt.getParameterTypes().length];
ConstantAnalyzerValue clsValue = null;
ConstantAnalyzerValue[] argValues =
new ConstantAnalyzerValue[mt.getParameterTypes().length];
for (int i=mt.getParameterTypes().length-1; i >=0; i--) {
size += mt.getParameterTypes()[i].stackSize();
ConstantAnalyzerInfo newInfo;
if (mt.getReturnType() != Type.tVoid) {
ConstantAnalyzerValue returnVal =
argValues[i] = info.getStack(size);
if (argValues[i].value != ConstantAnalyzerValue.VOLATILE)
args[i] = argValues[i].value;
else
constant = false;
}
if (opcode != opc_invokestatic) {
size++;
clsValue = info.getStack(size);
cls = clsValue.value;
if (cls == ConstantAnalyzerValue.VOLATILE
|| cls == null)
constant = false;
}
if (mt.getReturnType() == Type.tVoid) {
handleReference(ref, opcode == opc_invokevirtual
|| opcode == opc_invokeinterface);
mergeInfo(instr.nextByAddr, info.pop(size));
break;
}
Object methodResult = null;
if (constant) {
try {
if (jode.Obfuscator.isDebugging)
jode.Decompiler.isDebugging = true; /*XXX*/
methodResult = runtime.invokeMethod
(ref, opcode != opc_invokespecial, cls, args);
} catch (InterpreterException ex) {
constant = false;
Obfuscator.err.println("Can't interpret "+ref+": "
+ ex.getMessage());
/* result is not constant */
} catch (InvocationTargetException ex) {
constant = false;
Obfuscator.err.println("Method "+ref+" throwed exception: "
+ ex.getTargetException().getMessage());
/* method always throws exception ? */
} catch (Exception ex) {
Obfuscator.err.println("Unexpected exception in method: "+ref+" while analyzing "+m);
ex.printStackTrace(Obfuscator.err);
}
}
ConstantAnalyzerValue returnVal;
if (!constant) {
handleReference(ref, opcode == opc_invokevirtual
|| opcode == opc_invokeinterface);
returnVal =
unknownValue[mt.getReturnType().stackSize()-1];
newInfo = info.poppush(size, returnVal);
} else
newInfo = info.pop(size);
mergeInfo(instr.nextByAddr, newInfo);
} else {
shortInfo.flags |= CONSTANT;
shortInfo.constant = methodResult;
returnVal = new ConstantAnalyzerValue(methodResult);
returnVal.addConstantListener(shortInfo);
if (clsValue != null)
clsValue.addConstantListener(returnVal);
for (int i=0; i< argValues.length; i++)
argValues[i].addConstantListener(returnVal);
}
mergeInfo(instr.nextByAddr, info.poppush(size, returnVal));
break;
}
@ -1046,15 +1106,9 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
bytecode.getFirstInstr().tmpInfo = new ConstantAnalyzerInfo
(bytecode.getMaxLocals(), m.info.isStatic(), m.info.getType());
instrStack.push(bytecode.getFirstInstr());
try {
while (!instrStack.isEmpty()) {
Instruction instr = (Instruction) instrStack.pop();
// System.err.println("addr: "+m+","+instr.addr+";"+instr.tmpInfo);
handleOpcode(instr);
}
} catch (OutOfMemoryError err) {
System.err.println("Out of memory");
System.exit(0);
while (!instrStack.isEmpty()) {
Instruction instr = (Instruction) instrStack.pop();
handleOpcode(instr);
}
Handler[] handlers = bytecode.getExceptionHandlers();
@ -1151,21 +1205,35 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
insertOnePop(instr, 1);
} else
insertOnePop(instr, (instr.opcode == opc_putfield) ? 2 : 1);
break;
case opc_invokespecial:
case opc_invokestatic:
case opc_invokeinterface:
case opc_invokevirtual: {
Reference ref = (Reference) instr.objData;
MethodType mt = (MethodType) Type.tType(ref.getType());
for (int i=mt.getParameterTypes().length-1; i >=0; i--)
insertOnePop(instr, mt.getParameterTypes()[i].stackSize());
if (instr.opcode != opc_invokestatic)
insertOnePop(instr, 1);
}
}
}
public void appendJump(Instruction instr, Instruction dest) {
/* Add a goto instruction after this opcode. */
Instruction second = instr.appendInstruction(true);
Instruction second = instr.appendInstruction();
second.alwaysJumps = true;
second.opcode = Instruction.opc_goto;
second.length = 3;
second.succs = new Instruction[] { dest };
dest.preds.addElement(second);
dest.addPredecessor(second);
}
public BytecodeInfo stripCode() {
if (constInfos == null)
analyzeCode();
// bytecode.dumpCode(Obfuscator.err);
for (Instruction instr = bytecode.getFirstInstr();
instr != null; instr = instr.nextByAddr) {
ConstantInfo info = (ConstantInfo) constInfos.get(instr);
@ -1181,9 +1249,9 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
instr.localSlot = -1;
instr.length = 2;
instr.objData = info.constant;
// System.err.println(m+": Replacing "
// +opcodeString[instr.opcode]
// +" with constant "+info.constant);
// Obfuscator.err.println(m+": Replacing "
// +opcodeString[instr.opcode]
// +" with constant "+info.constant);
}
instr.tmpInfo = null;
} else if ((info.flags & CONSTANTFLOW) != 0) {
@ -1194,7 +1262,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
else
instr.opcode = opc_pop;
instr.alwaysJumps = false;
instr.succs[0].preds.removeElement(instr);
instr.succs[0].removePredecessor(instr);
instr.succs = null;
instr.length = 1;
while (instr.nextByAddr != null) {

Loading…
Cancel
Save