reworked, fixed some bugs

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@829 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 25 years ago
parent a8d6ca1e9a
commit 1f6b400671
  1. 282
      jode/jode/obfuscator/RemovePopAnalyzer.java

@ -46,185 +46,6 @@ public class RemovePopAnalyzer implements CodeAnalyzer, Opcodes {
Instruction nextInstr;
}
Instruction findMatchingPush(Instruction instr) {
int count = 0;
while (true) {
if (instr.preds != null)
return null;
instr = instr.prevByAddr;
switch (instr.opcode) {
case opc_ldc2_w:
case opc_lload: case opc_dload:
if (count < 2)
return count == 0 ? instr : null;
count -= 2;
break;
case opc_ldc:
case opc_iload: case opc_fload: case opc_aload:
case opc_new:
if (count == 0)
return instr;
count --;
break;
case opc_iaload: case opc_faload: case opc_aaload:
case opc_baload: case opc_caload: case opc_saload:
if (count == 0)
return instr;
count++;
break;
case opc_dup: case opc_dup_x1: case opc_dup_x2: {
/* XXX This is a very special case, if we pop a value
* that is dupped we can omit the dup; it doesn't matter
* if we pop the dupped value or the original value.
*/
int depth = (instr.opcode - opc_dup);
if (count < 2 + depth)
return (count == 0 || count == depth+1) ? instr : null;
count --;
break;
}
case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: {
int depth = (instr.opcode - opc_dup2);
if (count < 4 + depth)
return count == 0 ? instr : null;
count -= 2;
break;
}
case opc_swap:
case opc_lneg: case opc_dneg:
case opc_l2d: case opc_d2l:
case opc_laload: case opc_daload:
if (count < 2)
return count == 0 ? instr : null;
break;
case opc_ineg: case opc_fneg:
case opc_i2f: case opc_f2i:
case opc_i2b: case opc_i2c: case opc_i2s:
case opc_newarray: case opc_anewarray:
case opc_arraylength:
case opc_checkcast:
case opc_instanceof:
if (count == 0)
return instr;
break;
case opc_iadd: case opc_fadd:
case opc_isub: case opc_fsub:
case opc_imul: case opc_fmul:
case opc_idiv: case opc_fdiv:
case opc_irem: case opc_frem:
case opc_iand: case opc_ior : case opc_ixor:
case opc_ishl: case opc_ishr: case opc_iushr:
case opc_fcmpl: case opc_fcmpg:
case opc_l2i: case opc_l2f:
case opc_d2i: case opc_d2f:
if (count == 0)
return instr;
count++;
break;
case opc_ladd: case opc_dadd:
case opc_lsub: case opc_dsub:
case opc_lmul: case opc_dmul:
case opc_ldiv: case opc_ddiv:
case opc_lrem: case opc_drem:
case opc_land: case opc_lor : case opc_lxor:
if (count < 2)
return count == 0 ? instr : null;
count += 2;
break;
case opc_lshl: case opc_lshr: case opc_lushr:
if (count < 2)
return count == 0 ? instr : null;
count++;
break;
case opc_i2l: case opc_i2d:
case opc_f2l: case opc_f2d:
if (count < 2)
return count == 0 ? instr : null;
count--;
break;
case opc_lcmp:
case opc_dcmpl: case opc_dcmpg:
if (count == 0)
return instr;
count += 3;
break;
case opc_invokevirtual:
case opc_invokespecial:
case opc_invokestatic:
case opc_invokeinterface: {
Reference ref = (Reference) instr.objData;
MethodType mt = (MethodType) Type.tType(ref.getType());
if (count < mt.getReturnType().stackSize())
return (count == 0) ? instr : null;
count -= mt.getReturnType().stackSize();
if (instr.opcode != opc_invokestatic)
count++;
for (int i = mt.getParameterTypes().length-1; i >= 0; i--)
count += mt.getParameterTypes()[i].stackSize();
break;
}
case opc_getstatic:
case opc_getfield: {
Reference ref = (Reference) instr.objData;
int size = Type.tType(ref.getType()).stackSize();
if (count < size)
return count == 0 ? instr : null;
count -= size;
if (instr.opcode == opc_getfield)
count++;
break;
}
case opc_multianewarray: {
if (count == 0)
return instr;
int dims = instr.prevByAddr.intData;
count += dims - 1;
break;
}
case opc_nop:
case opc_iinc:
break;
case opc_putfield:
count++;
/* fall through */
case opc_putstatic:
count += instr.objData instanceof Long
|| instr.objData instanceof Double ? 2 : 1;
break;
case opc_monitorenter:
case opc_monitorexit:
case opc_istore:
case opc_fstore: case opc_astore:
case opc_pop:
count++;
break;
case opc_lstore: case opc_dstore:
case opc_pop2:
count += 2;
break;
case opc_iastore:
case opc_fastore: case opc_aastore:
case opc_bastore: case opc_castore: case opc_sastore:
count += 3;
break;
case opc_lastore: case opc_dastore:
count += 4;
break;
default:
return null;
}
}
}
static Instruction shrinkPop(Instruction popInstr, int amount) {
int newPop = popInstr.opcode - (opc_pop-1) - amount;
if (newPop < 0)
@ -239,6 +60,7 @@ public class RemovePopAnalyzer implements CodeAnalyzer, Opcodes {
}
public BytecodeInfo stripCode() {
int poppush[] = new int[2];
Instruction instr = bytecode.getFirstInstr();
while (instr != null) {
switch (instr.opcode) {
@ -250,39 +72,77 @@ public class RemovePopAnalyzer implements CodeAnalyzer, Opcodes {
}
case opc_pop:
case opc_pop2: {
Instruction prevInstr = findMatchingPush(instr);
int opcode = prevInstr == null ? -1 : prevInstr.opcode;
/* find push instruction */
int count = 0;
Instruction pushInstr = instr;
while (true) {
if (pushInstr.preds != null) {
pushInstr = null;
break;
}
pushInstr = pushInstr.prevByAddr;
if (pushInstr == null
|| pushInstr.succs != null
|| pushInstr.alwaysJumps) {
pushInstr = null;
break;
}
pushInstr.getStackPopPush(poppush);
if (count < poppush[1])
break;
count += poppush[0] - poppush[1];
}
int opcode = pushInstr == null ? -1 : pushInstr.opcode;
if (count > 0) {
/* If this is a dup and the instruction popped is the
* duplicated element, remove the dup
*/
if (count <= 2 && opcode == (opc_dup + count - 1)) {
pushInstr.removeInstruction();
instr = shrinkPop(instr, 1);
continue;
}
if (instr.opcode == opc_pop2
&& count > 1 && count <= 3
&& opcode == (opc_dup2 + count-2)) {
pushInstr.removeInstruction();
instr = shrinkPop(instr, 2);
continue;
}
/* Otherwise popping is not possible */
opcode = -1;
}
switch (opcode) {
case opc_ldc2_w:
case opc_lload: case opc_dload:
prevInstr.removeInstruction();
pushInstr.removeInstruction();
instr = shrinkPop(instr, 2);
continue;
case opc_ldc:
case opc_iload: case opc_fload: case opc_aload:
case opc_dup:
case opc_new:
prevInstr.removeInstruction();
pushInstr.removeInstruction();
instr = shrinkPop(instr, 1);
continue;
case opc_iaload: case opc_faload: case opc_aaload:
case opc_baload: case opc_caload: case opc_saload:
/* We have to pop one entry more. */
prevInstr.opcode = opc_pop;
instr = prevInstr;
pushInstr.opcode = opc_pop;
instr = pushInstr;
continue;
case opc_dup_x1:
prevInstr.opcode = opc_swap;
pushInstr.opcode = opc_swap;
instr = shrinkPop(instr, 1);
continue;
case opc_dup2:
if (instr.opcode == opc_pop2) {
prevInstr.removeInstruction();
} else
prevInstr.opcode = opc_dup;
instr = instr.nextByAddr;
instr.prevByAddr.removeInstruction();
pushInstr.removeInstruction();
instr = shrinkPop(instr, 2);
}
continue;
case opc_lneg: case opc_dneg:
@ -297,7 +157,7 @@ public class RemovePopAnalyzer implements CodeAnalyzer, Opcodes {
case opc_newarray: case opc_anewarray:
case opc_arraylength:
case opc_instanceof:
prevInstr.removeInstruction();
pushInstr.removeInstruction();
continue;
case opc_iadd: case opc_fadd:
@ -310,9 +170,9 @@ public class RemovePopAnalyzer implements CodeAnalyzer, Opcodes {
case opc_fcmpl: case opc_fcmpg:
case opc_l2i: case opc_l2f:
case opc_d2i: case opc_d2f:
prevInstr.opcode = opc_pop2;
pushInstr.opcode = opc_pop2;
shrinkPop(instr, 1);
instr = prevInstr;
instr = pushInstr;
continue;
case opc_ladd: case opc_dadd:
case opc_lsub: case opc_dsub:
@ -322,27 +182,27 @@ public class RemovePopAnalyzer implements CodeAnalyzer, Opcodes {
case opc_land: case opc_lor : case opc_lxor:
if (instr.opcode != opc_pop2)
break;
prevInstr.opcode = opc_pop2;
instr = prevInstr;
pushInstr.opcode = opc_pop2;
instr = pushInstr;
continue;
case opc_lshl: case opc_lshr: case opc_lushr:
if (instr.opcode != opc_pop2)
break;
prevInstr.opcode = opc_pop;
instr = prevInstr;
pushInstr.opcode = opc_pop;
instr = pushInstr;
continue;
case opc_i2l: case opc_i2d:
case opc_f2l: case opc_f2d:
if (instr.opcode != opc_pop2)
break;
prevInstr.removeInstruction();
pushInstr.removeInstruction();
instr.opcode = opc_pop;
continue;
case opc_lcmp:
case opc_dcmpl: case opc_dcmpg:
prevInstr.opcode = opc_pop2;
pushInstr.opcode = opc_pop2;
if (instr.opcode == opc_pop)
instr.opcode = opc_pop2;
else {
@ -350,24 +210,24 @@ public class RemovePopAnalyzer implements CodeAnalyzer, Opcodes {
thirdPop.length = 1;
thirdPop.opcode = opc_pop;
}
instr = prevInstr;
instr = pushInstr;
continue;
case opc_getstatic:
case opc_getfield: {
Reference ref = (Reference) prevInstr.objData;
int count = Type.tType(ref.getType()).stackSize();
if (prevInstr.opcode == opc_getfield)
count--;
prevInstr.removeInstruction();
if (count > 0)
instr = shrinkPop(instr, count);
Reference ref = (Reference) pushInstr.objData;
int size = Type.tType(ref.getType()).stackSize();
if (pushInstr.opcode == opc_getfield)
size--;
pushInstr.removeInstruction();
if (size > 0)
instr = shrinkPop(instr, size);
continue;
}
case opc_multianewarray: {
int dims = prevInstr.intData;
prevInstr.removeInstruction();
int dims = pushInstr.intData;
pushInstr.removeInstruction();
if (dims == 0)
instr = shrinkPop(instr, 1);
else {
@ -388,7 +248,7 @@ public class RemovePopAnalyzer implements CodeAnalyzer, Opcodes {
case opc_invokestatic:
case opc_invokeinterface:
if (((MethodType)
Type.tType(((Reference) prevInstr.objData).getType()))
Type.tType(((Reference) pushInstr.objData).getType()))
.getReturnType().stackSize() != 1)
break;
/* fall through */

Loading…
Cancel
Save