Skip to content

Commit

Permalink
fix: handle inlined classes while collecting override related methods (
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Mar 25, 2022
1 parent fe91d77 commit 3d45191
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 11 deletions.
34 changes: 26 additions & 8 deletions jadx-core/src/main/java/jadx/api/JadxDecompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import jadx.api.plugins.options.JadxPluginOptions;
import jadx.core.Jadx;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.InlinedAttr;
import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.FieldNode;
Expand Down Expand Up @@ -483,12 +485,12 @@ public JavaClass getJavaClassByNode(ClassNode cls) {
if (parentClass.contains(AFlag.DONT_GENERATE)) {
return null;
}
if (parentClass != cls) {
JavaClass parentJavaClass = classesMap.get(parentClass);
if (parentJavaClass == null) {
getClasses();
parentJavaClass = classesMap.get(parentClass);
}
JavaClass parentJavaClass = classesMap.get(parentClass);
if (parentJavaClass == null) {
getClasses();
parentJavaClass = classesMap.get(parentClass);
}
if (parentJavaClass != null) {
loadJavaClass(parentJavaClass);
javaClass = classesMap.get(cls);
if (javaClass != null) {
Expand All @@ -512,7 +514,9 @@ private JavaMethod getJavaMethodByNode(MethodNode mth) {
return null;
}
// parent class not loaded yet
JavaClass javaClass = getJavaClassByNode(mth.getParentClass().getTopParentClass());
ClassNode parentClass = mth.getParentClass();
ClassNode codeCls = getCodeParentClass(parentClass);
JavaClass javaClass = getJavaClassByNode(codeCls);
if (javaClass == null) {
return null;
}
Expand All @@ -521,12 +525,26 @@ private JavaMethod getJavaMethodByNode(MethodNode mth) {
if (javaMethod != null) {
return javaMethod;
}
if (mth.getParentClass().hasNotGeneratedParent()) {
if (parentClass.hasNotGeneratedParent()) {
return null;
}
throw new JadxRuntimeException("JavaMethod not found by MethodNode: " + mth);
}

private ClassNode getCodeParentClass(ClassNode cls) {
ClassNode codeCls;
InlinedAttr inlinedAttr = cls.get(AType.INLINED);
if (inlinedAttr != null) {
codeCls = inlinedAttr.getInlineCls().getTopParentClass();
} else {
codeCls = cls.getTopParentClass();
}
if (codeCls == cls) {
return codeCls;
}
return getCodeParentClass(codeCls);
}

@Nullable
private JavaField getJavaFieldByNode(FieldNode fld) {
JavaField javaField = fieldsMap.get(fld);
Expand Down
13 changes: 12 additions & 1 deletion jadx-core/src/main/java/jadx/api/JavaMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.jetbrains.annotations.ApiStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.MethodOverrideAttr;
Expand All @@ -14,6 +17,7 @@
import jadx.core.utils.Utils;

public final class JavaMethod implements JavaNode {
private static final Logger LOG = LoggerFactory.getLogger(JavaMethod.class);
private final MethodNode mth;
private final JavaClass parent;

Expand Down Expand Up @@ -73,7 +77,14 @@ public List<JavaMethod> getOverrideRelatedMethods() {
}
JadxDecompiler decompiler = getDeclaringClass().getRootDecompiler();
return ovrdAttr.getRelatedMthNodes().stream()
.map(m -> ((JavaMethod) decompiler.convertNode(m)))
.map(m -> {
JavaMethod javaMth = (JavaMethod) decompiler.convertNode(m);
if (javaMth == null) {
LOG.warn("Failed convert to java method: {}", m);
}
return javaMth;
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
}

Expand Down
2 changes: 2 additions & 0 deletions jadx-core/src/main/java/jadx/core/dex/attributes/AType.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import jadx.core.dex.attributes.nodes.FieldReplaceAttr;
import jadx.core.dex.attributes.nodes.ForceReturnAttr;
import jadx.core.dex.attributes.nodes.GenericInfoAttr;
import jadx.core.dex.attributes.nodes.InlinedAttr;
import jadx.core.dex.attributes.nodes.JadxCommentsAttr;
import jadx.core.dex.attributes.nodes.JadxError;
import jadx.core.dex.attributes.nodes.JumpInfo;
Expand Down Expand Up @@ -55,6 +56,7 @@ public final class AType<T extends IJadxAttribute> implements IJadxAttrType<T> {
public static final AType<EnumMapAttr> ENUM_MAP = new AType<>();
public static final AType<ClassTypeVarsAttr> CLASS_TYPE_VARS = new AType<>();
public static final AType<AnonymousClassAttr> ANONYMOUS_CLASS = new AType<>();
public static final AType<InlinedAttr> INLINED = new AType<>();

// field
public static final AType<FieldInitInsnAttr> FIELD_INIT_INSN = new AType<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package jadx.core.dex.attributes.nodes;

import jadx.api.plugins.input.data.attributes.IJadxAttrType;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.nodes.ClassNode;

public class InlinedAttr implements IJadxAttribute {

private final ClassNode inlineCls;

public InlinedAttr(ClassNode inlineCls) {
this.inlineCls = inlineCls;
}

public ClassNode getInlineCls() {
return inlineCls;
}

@Override
public IJadxAttrType<InlinedAttr> getAttrType() {
return AType.INLINED;
}

@Override
public String toString() {
return "INLINED: " + inlineCls;
}
}
2 changes: 2 additions & 0 deletions jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import jadx.core.ProcessClass;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.InlinedAttr;
import jadx.core.dex.attributes.nodes.NotificationAttrNode;
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.info.AccessInfo.AFType;
Expand Down Expand Up @@ -633,6 +634,7 @@ public void addInlinedClass(ClassNode cls) {
if (inlinedClasses.isEmpty()) {
inlinedClasses = new ArrayList<>(5);
}
cls.addAttr(new InlinedAttr(this));
inlinedClasses.add(cls);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ private static void markAnonymousClass(ClassNode cls) {
return;
}
ClassNode outerCls = anonymousConstructor.getUseIn().get(0).getParentClass();
outerCls.addInlinedClass(cls);
cls.addAttr(new AnonymousClassAttr(outerCls, baseType));
cls.add(AFlag.DONT_GENERATE);
anonymousConstructor.add(AFlag.ANONYMOUS_CONSTRUCTOR);
Expand Down
7 changes: 5 additions & 2 deletions jadx-gui/src/main/java/jadx/gui/ui/dialog/UsageDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,11 @@ private void collectUsageData() {
private List<JavaNode> getMethodUseIn() {
if (node instanceof JMethod) {
JavaMethod method = ((JMethod) node).getJavaMethod();
if (null != method.getMethodNode().get(AType.METHOD_OVERRIDE)) {
return method.getOverrideRelatedMethods().stream().flatMap(m -> m.getUseIn().stream()).collect(Collectors.toList());
if (method.getMethodNode().contains(AType.METHOD_OVERRIDE)) {
return method.getOverrideRelatedMethods()
.stream()
.flatMap(m -> m.getUseIn().stream())
.collect(Collectors.toList());
}
}
return node.getJavaNode().getUseIn();
Expand Down

0 comments on commit 3d45191

Please sign in to comment.