build samples without debug info, fix try/catch processing

This commit is contained in:
Skylot
2013-07-29 18:44:01 +04:00
parent 1f21760bbe
commit 54f4c6d2cb
19 changed files with 180 additions and 76 deletions
@@ -19,6 +19,7 @@ import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.InsnWrapArg;
import jadx.core.dex.instructions.args.LiteralArg;
import jadx.core.dex.instructions.args.NamedArg;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.mods.ConstructorInsn;
import jadx.core.dex.nodes.ClassNode;
@@ -77,10 +78,14 @@ public class InsnGen {
return arg((RegisterArg) arg);
} else if (arg.isLiteral()) {
return lit((LiteralArg) arg);
} else {
} else if (arg.isInsnWrap()) {
CodeWriter code = new CodeWriter();
makeInsn(((InsnWrapArg) arg).getWrapInsn(), code, true);
return code.toString();
} else if (arg.isNamed()) {
return ((NamedArg) arg).getName();
} else {
throw new CodegenException("Unknown arg type " + arg);
}
}
@@ -318,7 +323,7 @@ public class InsnGen {
case MONITOR_EXIT:
if (isFallback()) {
code.add("monitor-exit(").add(arg(insn.getArg(0))).add(')');
code.add("monitor-exit(").add(arg(insn, 0)).add(')');
} else {
state.add(InsnGenState.SKIP);
}
@@ -328,11 +333,7 @@ public class InsnGen {
if (isFallback()) {
code.add("move-exception");
} else {
// don't have body
if (state.contains(InsnGenState.BODY_ONLY))
code.add(arg(insn.getResult()));
else
state.add(InsnGenState.SKIP);
code.add(arg(insn, 0));
}
break;
@@ -340,7 +341,7 @@ public class InsnGen {
break;
case ARGS:
code.add(arg(insn.getArg(0)));
code.add(arg(insn, 0));
break;
case NOP:
@@ -8,6 +8,7 @@ import jadx.core.dex.attributes.JadxErrorAttr;
import jadx.core.dex.attributes.annotations.MethodParameters;
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.NamedArg;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
@@ -118,7 +119,7 @@ public class MethodGen {
(MethodParameters) mth.getAttributes().get(AttributeType.ANNOTATION_MTH_PARAMETERS);
int i = 0;
for (Iterator<RegisterArg> it = args.iterator(); it.hasNext();) {
for (Iterator<RegisterArg> it = args.iterator(); it.hasNext(); ) {
RegisterArg arg = it.next();
// add argument annotation
@@ -179,16 +180,12 @@ public class MethodGen {
/**
* Put variable declaration and return variable name (used for assignments)
*
* @param arg
* register variable
* @param arg register variable
* @return variable name
*/
public String assignArg(RegisterArg arg) {
String name = makeArgName(arg);
if (varNames.add(name))
return name;
if (fallback)
if (varNames.add(name) || fallback)
return name;
name = getUniqVarName(name);
@@ -196,6 +193,16 @@ public class MethodGen {
return name;
}
public String assignNamedArg(NamedArg arg) {
String name = arg.getName();
if (varNames.add(name) || fallback)
return name;
name = getUniqVarName(name);
arg.setName(name);
return name;
}
private String getUniqVarName(String name) {
String r;
int i = 2;
@@ -270,7 +270,7 @@ public class RegionGen extends InsnGen {
code.startLine("} catch (");
code.add(handler.isCatchAll() ? "Throwable" : useClass(handler.getCatchType()));
code.add(' ');
code.add(mgen.assignArg(handler.getArg()));
code.add(mgen.assignNamedArg(handler.getArg()));
code.add(") {");
makeRegionIndent(code, region);
}
@@ -32,8 +32,7 @@ public final class BlockRegState {
regType = new TypedVar(arg.getType());
regs[arg.getRegNum()].setTypedVar(regType);
}
arg.replace(regType);
regType.getUseList().add(arg);
regType.use(arg);
}
public RegisterArg getRegister(int r) {
@@ -4,6 +4,7 @@ import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.NamedArg;
import jadx.core.dex.instructions.args.PrimitiveType;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.DexNode;
@@ -387,7 +388,8 @@ public class InsnDecoder {
case Opcodes.MOVE_EXCEPTION:
return insn(InsnType.MOVE_EXCEPTION,
InsnArg.reg(insn, 0, ArgType.unknown(PrimitiveType.OBJECT)));
InsnArg.reg(insn, 0, ArgType.unknown(PrimitiveType.OBJECT)),
new NamedArg("e", ArgType.unknown(PrimitiveType.OBJECT)));
case Opcodes.RETURN_VOID:
return new InsnNode(InsnType.RETURN, 0);
@@ -668,13 +670,27 @@ public class InsnDecoder {
return inode;
}
private InsnNode insn(InsnType type, RegisterArg res) {
InsnNode node = new InsnNode(type, 0);
node.setResult(res);
return node;
}
private InsnNode insn(InsnType type, RegisterArg res, InsnArg arg) {
InsnNode node = new InsnNode(type, 1);
node.setResult(res);
node.addArg(arg);
return node;
}
private InsnNode insn(InsnType type, RegisterArg res, InsnArg... args) {
InsnNode inode = new InsnNode(type, args == null ? 0 : args.length);
inode.setResult(res);
if (args != null)
InsnNode node = new InsnNode(type, args == null ? 0 : args.length);
node.setResult(res);
if (args != null) {
for (InsnArg arg : args)
inode.addArg(arg);
return inode;
node.addArg(arg);
}
return node;
}
private int getMoveResultRegister(DecodedInstruction[] insnArr, int offset) {
@@ -344,6 +344,11 @@ public abstract class ArgType {
}
}
} else {
if(a.isGenericType())
return a;
if(b.isGenericType())
return b;
if (a.isObject() && b.isObject()) {
if (a.getObject().equals(b.getObject())) {
if (a.getGenericTypes() != null)
@@ -0,0 +1,23 @@
package jadx.core.dex.instructions.args;
public class ImmutableTypedVar extends TypedVar {
public ImmutableTypedVar(ArgType initType) {
super(initType);
}
@Override
public boolean forceSetType(ArgType newType) {
return false;
}
@Override
public boolean merge(TypedVar typedVar) {
return false;
}
@Override
public boolean merge(ArgType mtype) {
return false;
}
}
@@ -14,7 +14,6 @@ public abstract class InsnArg extends Typed {
protected InsnNode parentInsn;
public static RegisterArg reg(int regNum, ArgType type) {
assert regNum >= 0 : "Register number must be positive";
return new RegisterArg(regNum, type);
}
@@ -46,6 +45,10 @@ public abstract class InsnArg extends Typed {
return false;
}
public boolean isNamed() {
return false;
}
public InsnNode getParentInsn() {
return parentInsn;
}
@@ -75,5 +78,4 @@ public abstract class InsnArg extends Typed {
public int getRegNum() {
throw new UnsupportedOperationException("Must be called from RegisterArg");
}
}
@@ -2,7 +2,7 @@ package jadx.core.dex.instructions.args;
import jadx.core.dex.nodes.InsnNode;
public class InsnWrapArg extends InsnArg {
public final class InsnWrapArg extends InsnArg {
private final InsnNode wrappedInsn;
@@ -3,7 +3,7 @@ package jadx.core.dex.instructions.args;
import jadx.core.codegen.TypeGen;
import jadx.core.utils.exceptions.JadxRuntimeException;
public class LiteralArg extends InsnArg {
public final class LiteralArg extends InsnArg {
private final long literal;
@@ -0,0 +1,29 @@
package jadx.core.dex.instructions.args;
public final class NamedArg extends InsnArg {
private String name;
public NamedArg(String name, ArgType type) {
this.name = name;
this.typedVar = new TypedVar(type);
}
public String getName() {
return name;
}
@Override
public boolean isNamed() {
return true;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "(" + name + " " + typedVar + ")";
}
}
@@ -29,7 +29,6 @@ public abstract class Typed {
}
public void replace(TypedVar newVar) {
assert newVar != null;
if (typedVar == newVar)
return;
@@ -43,6 +43,11 @@ public class TypedVar {
}
}
public void use(InsnArg arg) {
arg.replace(this);
useList.add(arg);
}
public List<InsnArg> getUseList() {
return useList;
}
@@ -7,6 +7,7 @@ import jadx.core.utils.exceptions.DecodeException;
import jadx.core.utils.files.InputFile;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -99,7 +100,7 @@ public class DexNode {
for (short t : paramList.getTypes()) {
args.add(getType(t));
}
return args;
return Collections.unmodifiableList(args);
}
public Code readCode(Method mth) {
@@ -169,23 +169,24 @@ public class MethodNode extends LineAttrNode implements ILoadable {
if (argsTypes == null)
return false;
if (argsTypes.size() != mthInfo.getArgumentsTypes().size()) {
List<ArgType> mthArgs = mthInfo.getArgumentsTypes();
if (argsTypes.size() != mthArgs.size()) {
if (argsTypes.isEmpty()) {
return false;
}
if (!mthInfo.isConstructor()) {
LOG.warn("Wrong signature parse result: " + sign + " -> " + argsTypes
+ ", not generic version: " + mthInfo.getArgumentsTypes());
+ ", not generic version: " + mthArgs);
return false;
} else if (getParentClass().getAccessFlags().isEnum()) {
// TODO:
argsTypes.add(0, mthInfo.getArgumentsTypes().get(0));
argsTypes.add(1, mthInfo.getArgumentsTypes().get(1));
argsTypes.add(0, mthArgs.get(0));
argsTypes.add(1, mthArgs.get(1));
} else {
// add synthetic arg for outer class
argsTypes.add(0, mthInfo.getArgumentsTypes().get(0));
argsTypes.add(0, mthArgs.get(0));
}
if (argsTypes.size() != mthInfo.getArgumentsTypes().size()) {
if (argsTypes.size() != mthArgs.size()) {
return false;
}
}
@@ -454,6 +455,11 @@ public class MethodNode extends LineAttrNode implements ILoadable {
return exceptionHandlers;
}
public boolean isMethodOverloaded() {
// TODO
return false;
}
public int getRegsCount() {
return regsCount;
}
@@ -505,5 +511,4 @@ public class MethodNode extends LineAttrNode implements ILoadable {
+ " " + parentClass.getFullName() + "." + mthInfo.getName()
+ "(" + Utils.listToString(mthInfo.getArgumentsTypes()) + ")";
}
}
@@ -2,7 +2,7 @@ package jadx.core.dex.trycatch;
import jadx.core.Consts;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.args.NamedArg;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IContainer;
import jadx.core.utils.InsnUtils;
@@ -18,7 +18,7 @@ public class ExceptionHandler {
private BlockNode handleBlock;
private final List<BlockNode> blocks = new ArrayList<BlockNode>();
private IContainer handlerRegion;
private RegisterArg arg;
private NamedArg arg;
private TryCatchBlock tryBlock;
@@ -63,11 +63,11 @@ public class ExceptionHandler {
this.handlerRegion = handlerRegion;
}
public RegisterArg getArg() {
public NamedArg getArg() {
return arg;
}
public void setArg(RegisterArg arg) {
public void setArg(NamedArg arg) {
this.arg = arg;
}
@@ -3,6 +3,7 @@ package jadx.core.dex.visitors;
import jadx.core.dex.attributes.AttributeType;
import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.NamedArg;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.InsnNode;
@@ -40,15 +41,22 @@ public class BlockProcessingHelper {
if (!block.getInstructions().isEmpty()) {
InsnNode me = block.getInstructions().get(0);
ExcHandlerAttr handlerAttr = (ExcHandlerAttr) me.getAttributes().get(AttributeType.EXC_HANDLER);
if (handlerAttr != null) {
if (handlerAttr != null && me.getType() == InsnType.MOVE_EXCEPTION) {
ExceptionHandler excHandler = handlerAttr.getHandler();
assert me.getType() == InsnType.MOVE_EXCEPTION && me.getOffset() == excHandler.getHandleOffset();
assert me.getOffset() == excHandler.getHandleOffset();
// set correct type for 'move-exception' operation
RegisterArg excArg = me.getResult();
if (excHandler.isCatchAll())
excArg.getTypedVar().forceSetType(ArgType.THROWABLE);
else
excArg.getTypedVar().forceSetType(excHandler.getCatchType().getType());
RegisterArg resArg = me.getResult();
NamedArg excArg = (NamedArg) me.getArg(0);
ArgType type;
if (excHandler.isCatchAll()) {
type = ArgType.THROWABLE;
excArg.setName("th");
} else {
type = excHandler.getCatchType().getType();
excArg.setName("e");
}
resArg.getTypedVar().forceSetType(type);
excArg.getTypedVar().forceSetType(type);
excHandler.setArg(excArg);
block.getAttributes().add(handlerAttr);
@@ -70,18 +70,20 @@ public class CodeShrinker extends AbstractVisitor {
} else {
// TODO implement rules for shrink insn from different blocks
BlockNode useBlock = BlockUtils.getBlockByInsn(mth, useInsn);
if (useBlock != null && useBlock.getPredecessors().contains(block)) {
if (useBlock != null
&& (useBlock.getPredecessors().contains(block)
|| insn.getType() == InsnType.MOVE_EXCEPTION)) {
wrap = true;
}
}
if (wrap) {
if (useInsn.getType() == InsnType.MOVE) {
// TODO
// remover.add(useInsn);
} else {
// if (useInsn.getType() == InsnType.MOVE) {
// // TODO
// // remover.add(useInsn);
// } else {
useInsnArg.wrapInstruction(insn);
remover.add(insn);
}
// }
}
}
}
@@ -193,7 +195,7 @@ public class CodeShrinker extends AbstractVisitor {
while (i.isInsnWrap()) {
InsnNode wrapInsn = ((InsnWrapArg) i).getWrapInsn();
chain.add(wrapInsn);
if(wrapInsn.getArgsCount() == 0)
if (wrapInsn.getArgsCount() == 0)
break;
i = wrapInsn.getArg(0);
@@ -19,7 +19,6 @@ import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.trycatch.ExcHandlerAttr;
import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.utils.BlockUtils;
import jadx.core.utils.exceptions.JadxRuntimeException;
@@ -188,45 +187,48 @@ public class ModVisitor extends AbstractVisitor {
if (handlerAttr == null)
return;
TryCatchBlock tryBlock = handlerAttr.getTryBlock();
ExceptionHandler excHandler = handlerAttr.getHandler();
List<InsnNode> blockInsns = block.getInstructions();
int size = blockInsns.size();
if (size > 0 && blockInsns.get(0).getType() == InsnType.MOVE_EXCEPTION) {
InstructionRemover.remove(block, 0);
}
int totalSize = 0;
boolean noExitNode = true; // check if handler has exit edge to block not from this handler
for (BlockNode excBlock : excHandler.getBlocks()) {
List<InsnNode> insns = excBlock.getInstructions();
size = insns.size();
if (noExitNode)
if (noExitNode) {
noExitNode = excHandler.getBlocks().containsAll(excBlock.getCleanSuccessors());
}
List<InsnNode> insns = excBlock.getInstructions();
int size = insns.size();
if (excHandler.isCatchAll()
&& size > 0
&& insns.get(size - 1).getType() == InsnType.THROW) {
InstructionRemover.remove(excBlock, size - 1);
size = insns.size();
// move not removed instructions to 'finally' block
if (size != 0) {
if (insns.size() != 0) {
// TODO: support instructions from several blocks
// tryBlock.setFinalBlockFromInsns(mth, insns);
// TODO; because of incomplete realization don't extract final block,
// TODO: because of incomplete realization don't extract final block,
// just remove unnecessary instructions
insns.clear();
size = insns.size();
}
}
totalSize += size;
}
if (totalSize == 0 && noExitNode)
tryBlock.removeHandler(mth, excHandler);
List<InsnNode> blockInsns = block.getInstructions();
if (blockInsns.size() > 0) {
InsnNode insn = blockInsns.get(0);
if (insn.getType() == InsnType.MOVE_EXCEPTION
&& insn.getResult().getTypedVar().getUseList().size() <= 1) {
InstructionRemover.remove(block, 0);
}
}
int totalSize = 0;
for (BlockNode excBlock : excHandler.getBlocks()) {
totalSize += excBlock.getInstructions().size();
}
if (totalSize == 0 && noExitNode) {
handlerAttr.getTryBlock().removeHandler(mth, excHandler);
}
}
/**