use of jadx.core.dex.nodes.MethodNode in project jadx by skylot.
the class ModVisitor method processAnonymousConstructor.
private static void processAnonymousConstructor(MethodNode mth, ConstructorInsn co) {
MethodInfo callMth = co.getCallMth();
MethodNode callMthNode = mth.dex().resolveMethod(callMth);
if (callMthNode == null) {
return;
}
ClassNode classNode = callMthNode.getParentClass();
ClassInfo classInfo = classNode.getClassInfo();
ClassNode parentClass = mth.getParentClass();
if (!classInfo.isInner() || !Character.isDigit(classInfo.getShortName().charAt(0)) || !parentClass.getInnerClasses().contains(classNode)) {
return;
}
if (!classNode.getAccessFlags().isStatic() && (callMth.getArgsCount() == 0 || !callMth.getArgumentsTypes().get(0).equals(parentClass.getClassInfo().getType()))) {
return;
}
// TODO: calculate this constructor and other constructor usage
Map<InsnArg, FieldNode> argsMap = getArgsToFieldsMapping(callMthNode, co);
if (argsMap.isEmpty()) {
return;
}
// all checks passed
classNode.add(AFlag.ANONYMOUS_CLASS);
callMthNode.add(AFlag.DONT_GENERATE);
for (Map.Entry<InsnArg, FieldNode> entry : argsMap.entrySet()) {
FieldNode field = entry.getValue();
if (field == null) {
continue;
}
InsnArg arg = entry.getKey();
field.addAttr(new FieldReplaceAttr(arg));
field.add(AFlag.DONT_GENERATE);
if (arg.isRegister()) {
RegisterArg reg = (RegisterArg) arg;
SSAVar sVar = reg.getSVar();
if (sVar != null) {
sVar.add(AFlag.FINAL);
sVar.add(AFlag.DONT_INLINE);
}
reg.add(AFlag.SKIP_ARG);
}
}
}
use of jadx.core.dex.nodes.MethodNode in project jadx by skylot.
the class CheckRegions method visit.
@Override
public void visit(MethodNode mth) throws JadxException {
if (mth.isNoCode() || mth.getBasicBlocks().isEmpty() || mth.contains(AType.JADX_ERROR)) {
return;
}
// check if all blocks included in regions
final Set<BlockNode> blocksInRegions = new HashSet<BlockNode>();
DepthRegionTraversal.traverse(mth, new AbstractRegionVisitor() {
@Override
public void processBlock(MethodNode mth, IBlock container) {
if (!(container instanceof BlockNode)) {
return;
}
BlockNode block = (BlockNode) container;
if (blocksInRegions.add(block)) {
return;
}
if (!block.contains(AFlag.RETURN) && !block.contains(AFlag.SKIP) && !block.contains(AFlag.SYNTHETIC) && !block.getInstructions().isEmpty()) {
// TODO
// mth.add(AFlag.INCONSISTENT_CODE);
LOG.debug(" Duplicated block: {} in {}", block, mth);
}
}
});
if (mth.getBasicBlocks().size() != blocksInRegions.size()) {
for (BlockNode block : mth.getBasicBlocks()) {
if (!blocksInRegions.contains(block) && !block.getInstructions().isEmpty() && !block.contains(AFlag.SKIP)) {
mth.add(AFlag.INCONSISTENT_CODE);
LOG.debug(" Missing block: {} in {}", block, mth);
}
}
}
// check loop conditions
DepthRegionTraversal.traverse(mth, new AbstractRegionVisitor() {
@Override
public boolean enterRegion(MethodNode mth, IRegion region) {
if (region instanceof LoopRegion) {
BlockNode loopHeader = ((LoopRegion) region).getHeader();
if (loopHeader != null && loopHeader.getInstructions().size() != 1) {
ErrorsCounter.methodError(mth, "Incorrect condition in loop: " + loopHeader);
}
}
return true;
}
});
}
use of jadx.core.dex.nodes.MethodNode in project jadx by skylot.
the class TestLineNumbers method test.
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
FieldNode field = cls.searchFieldByName("field");
MethodNode func = cls.searchMethodByName("func()V");
ClassNode inner = cls.getInnerClasses().get(0);
MethodNode innerFunc = inner.searchMethodByName("innerFunc()V");
MethodNode innerFunc2 = inner.searchMethodByName("innerFunc2()V");
MethodNode innerFunc3 = inner.searchMethodByName("innerFunc3()V");
FieldNode innerField = inner.searchFieldByName("innerField");
// check source lines (available only for instructions and methods)
int testClassLine = 18;
assertEquals(testClassLine + 3, func.getSourceLine());
assertEquals(testClassLine + 9, innerFunc.getSourceLine());
assertEquals(testClassLine + 12, innerFunc2.getSourceLine());
assertEquals(testClassLine + 20, innerFunc3.getSourceLine());
// check decompiled lines
String[] lines = code.split(CodeWriter.NL);
checkLine(lines, field, "int field;");
checkLine(lines, func, "public void func() {");
checkLine(lines, inner, "public static class Inner {");
checkLine(lines, innerField, "int innerField;");
checkLine(lines, innerFunc, "public void innerFunc() {");
checkLine(lines, innerFunc2, "public void innerFunc2() {");
checkLine(lines, innerFunc3, "public void innerFunc3() {");
}
use of jadx.core.dex.nodes.MethodNode in project jadx by skylot.
the class TestReturnSourceLine method test.
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
CodeWriter codeWriter = cls.getCode();
String code = codeWriter.toString();
String[] lines = code.split(CodeWriter.NL);
MethodNode test1 = cls.searchMethodByName("test1(Z)I");
checkLine(lines, codeWriter, test1, 3, "return 1;");
MethodNode test2 = cls.searchMethodByName("test2(I)I");
checkLine(lines, codeWriter, test2, 3, "return v - 1;");
// TODO:
// MethodNode test3 = cls.searchMethodByName("test3(I)I");
// checkLine(lines, codeWriter, test3, 3, "return v;");
}
use of jadx.core.dex.nodes.MethodNode in project jadx by skylot.
the class TestDuplicateCast method test.
@Test
public void test() {
dontUnloadClass();
ClassNode cls = getClassNode(TestCls.class);
MethodNode mth = getMethod(cls, "method");
String code = cls.getCode().toString();
assertThat(code, containsString("return (int[]) o;"));
List<InsnNode> insns = mth.getBasicBlocks().get(1).getInstructions();
assertEquals(insns.size(), 1);
InsnNode insnNode = insns.get(0);
assertEquals(InsnType.RETURN, insnNode.getType());
assertTrue(insnNode.getArg(0).isInsnWrap());
InsnNode wrapInsn = ((InsnWrapArg) insnNode.getArg(0)).getWrapInsn();
assertEquals(InsnType.CHECK_CAST, wrapInsn.getType());
assertFalse(wrapInsn.getArg(0).isInsnWrap());
}
Aggregations