diff --git a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java index 127531da4..cdb64763e 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java @@ -575,9 +575,12 @@ public class InsnGen { MethodInfo callMth = insn.getCallMth(); // inline method - MethodNode callMthNode = mth.dex().resolveMethod(callMth); - if (callMthNode != null && inlineMethod(callMthNode, insn, code)) { - return; + MethodNode callMthNode = mth.dex().deepResolveMethod(callMth); + if (callMthNode != null) { + if (inlineMethod(callMthNode, insn, code)) { + return; + } + callMth = callMthNode.getMethodInfo(); } int k = 0; diff --git a/jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java b/jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java index e6a8e5fb2..ef25003d4 100644 --- a/jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java +++ b/jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java @@ -28,17 +28,7 @@ public final class MethodInfo { ProtoId proto = dex.getProtoId(mthId.getProtoIndex()); retType = dex.getType(proto.getReturnTypeIndex()); args = dex.readParamList(proto.getParametersOffset()); - - StringBuilder signature = new StringBuilder(); - signature.append(name); - signature.append('('); - for (ArgType arg : args) { - signature.append(TypeGen.signature(arg)); - } - signature.append(')'); - signature.append(TypeGen.signature(retType)); - - shortId = signature.toString(); + shortId = makeSignature(true); } public static MethodInfo fromDex(DexNode dex, int mthIndex) { @@ -50,6 +40,20 @@ public final class MethodInfo { return dex.getInfoStorage().putMethod(mthIndex, mth); } + public String makeSignature(boolean includeRetType) { + StringBuilder signature = new StringBuilder(); + signature.append(name); + signature.append('('); + for (ArgType arg : args) { + signature.append(TypeGen.signature(arg)); + } + signature.append(')'); + if (includeRetType) { + signature.append(TypeGen.signature(retType)); + } + return signature.toString(); + } + public String getName() { return name; } diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java index faac0cc1a..1e08e5efe 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java @@ -14,6 +14,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.android.dex.ClassData; @@ -87,7 +88,15 @@ public class DexNode { } @Nullable - public MethodNode resolveMethod(MethodInfo mth) { + public ClassNode resolveClass(@NotNull ArgType type) { + if (type.isGeneric()) { + type = ArgType.object(type.getObject()); + } + return resolveClass(ClassInfo.fromType(this, type)); + } + + @Nullable + public MethodNode resolveMethod(@NotNull MethodInfo mth) { ClassNode cls = resolveClass(mth.getDeclClass()); if (cls != null) { return cls.searchMethod(mth); @@ -95,6 +104,48 @@ public class DexNode { return null; } + /** + * Search method in class hierarchy. + */ + @Nullable + public MethodNode deepResolveMethod(@NotNull MethodInfo mth) { + ClassNode cls = resolveClass(mth.getDeclClass()); + if (cls == null) { + return null; + } + return deepResolveMethod(cls, mth.makeSignature(false)); + } + + @Nullable + private MethodNode deepResolveMethod(@NotNull ClassNode cls, String signature) { + for (MethodNode m : cls.getMethods()) { + if (m.getMethodInfo().getShortId().startsWith(signature)) { + return m; + } + } + MethodNode found; + ArgType superClass = cls.getSuperClass(); + if (superClass != null) { + ClassNode superNode = resolveClass(superClass); + if (superNode != null) { + found = deepResolveMethod(superNode, signature); + if (found != null) { + return found; + } + } + } + for (ArgType iFaceType : cls.getInterfaces()) { + ClassNode iFaceNode = resolveClass(iFaceType); + if (iFaceNode != null) { + found = deepResolveMethod(iFaceNode, signature); + if (found != null) { + return found; + } + } + } + return null; + } + @Nullable public FieldNode resolveField(FieldInfo field) { ClassNode cls = resolveClass(field.getDeclClass());