提交 476b2c37 编写于 作者: S Skylot

core: fix inner class handling in classpath and signature parser

上级 5258c836
...@@ -5,6 +5,7 @@ import jadx.core.utils.exceptions.DecodeException; ...@@ -5,6 +5,7 @@ import jadx.core.utils.exceptions.DecodeException;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
...@@ -44,36 +45,48 @@ public class ClspGraph { ...@@ -44,36 +45,48 @@ public class ClspGraph {
throw new JadxRuntimeException("Classpath must be loaded first"); throw new JadxRuntimeException("Classpath must be loaded first");
} }
int size = classes.size(); int size = classes.size();
for (ClassNode cls : classes) {
size += cls.getInnerClasses().size();
}
NClass[] nClasses = new NClass[size]; NClass[] nClasses = new NClass[size];
for (int i = 0; i < size; i++) { int k = 0;
ClassNode cls = classes.get(i); for (ClassNode cls : classes) {
NClass nClass = new NClass(cls.getRawName(), -1); nClasses[k++] = addClass(cls);
nClasses[i] = nClass; for (ClassNode inner : cls.getInnerClasses()) {
nameMap.put(cls.getRawName(), nClass); nClasses[k++] = addClass(inner);
}
} }
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
nClasses[i].setParents(ClsSet.makeParentsArray(classes.get(i), nameMap)); nClasses[i].setParents(ClsSet.makeParentsArray(classes.get(i), nameMap));
} }
} }
private NClass addClass(ClassNode cls) {
NClass nClass = new NClass(cls.getRawName(), -1);
nameMap.put(cls.getRawName(), nClass);
return nClass;
}
public boolean isImplements(String clsName, String implClsName) { public boolean isImplements(String clsName, String implClsName) {
Set<String> anc = getAncestors(clsName); Set<String> anc = getAncestors(clsName);
return anc.contains(implClsName); return anc.contains(implClsName);
} }
public String getCommonAncestor(String clsName, String implClsName) { public String getCommonAncestor(String clsName, String implClsName) {
if (clsName.equals(implClsName)) {
return clsName;
}
NClass cls = nameMap.get(implClsName);
if (cls != null) {
if (isImplements(clsName, implClsName)) { if (isImplements(clsName, implClsName)) {
return implClsName; return implClsName;
} }
Set<String> anc = getAncestors(clsName); Set<String> anc = getAncestors(clsName);
NClass cls = nameMap.get(implClsName);
if (cls != null) {
return searchCommonParent(anc, cls); return searchCommonParent(anc, cls);
} else { }
LOG.debug("Missing class: {}", implClsName); LOG.debug("Missing class: {}", implClsName);
return null; return null;
} }
}
private String searchCommonParent(Set<String> anc, NClass cls) { private String searchCommonParent(Set<String> anc, NClass cls) {
for (NClass p : cls.getParents()) { for (NClass p : cls.getParents()) {
...@@ -92,18 +105,22 @@ public class ClspGraph { ...@@ -92,18 +105,22 @@ public class ClspGraph {
private Set<String> getAncestors(String clsName) { private Set<String> getAncestors(String clsName) {
Set<String> result = ancestorCache.get(clsName); Set<String> result = ancestorCache.get(clsName);
if (result == null) { if (result != null) {
result = new HashSet<String>(); return result;
ancestorCache.put(clsName, result); }
NClass cls = nameMap.get(clsName); NClass cls = nameMap.get(clsName);
if (cls != null) { if (cls != null) {
result = new HashSet<String>();
addAncestorsNames(cls, result); addAncestorsNames(cls, result);
} else { if (result.isEmpty()) {
LOG.debug("Missing class: {}", clsName); result = Collections.emptySet();
}
} }
ancestorCache.put(clsName, result);
return result; return result;
} }
LOG.debug("Missing class: {}", clsName);
return Collections.emptySet();
}
private void addAncestorsNames(NClass cls, Set<String> result) { private void addAncestorsNames(NClass cls, Set<String> result) {
result.add(cls.getName()); result.add(cls.getName());
......
...@@ -72,7 +72,7 @@ public final class ClassInfo { ...@@ -72,7 +72,7 @@ public final class ClassInfo {
int sep = clsName.lastIndexOf('$'); int sep = clsName.lastIndexOf('$');
if (canBeInner && sep > 0 && sep != clsName.length() - 1) { if (canBeInner && sep > 0 && sep != clsName.length() - 1) {
String parClsName = pkg + '.' + clsName.substring(0, sep); String parClsName = pkg + "." + clsName.substring(0, sep);
parentClass = fromName(parClsName); parentClass = fromName(parClsName);
clsName = clsName.substring(sep + 1); clsName = clsName.substring(sep + 1);
} else { } else {
......
...@@ -179,6 +179,11 @@ public abstract class ArgType { ...@@ -179,6 +179,11 @@ public abstract class ArgType {
this.bounds = bound; this.bounds = bound;
} }
@Override
public boolean isGeneric() {
return true;
}
@Override @Override
public ArgType getWildcardType() { public ArgType getWildcardType() {
return type; return type;
...@@ -224,13 +229,18 @@ public abstract class ArgType { ...@@ -224,13 +229,18 @@ public abstract class ArgType {
} }
public GenericObject(GenericObject outerType, String innerName, ArgType[] generics) { public GenericObject(GenericObject outerType, String innerName, ArgType[] generics) {
super(outerType.getObject() + "." + innerName); super(outerType.getObject() + "$" + innerName);
this.outerType = outerType; this.outerType = outerType;
this.generics = generics; this.generics = generics;
this.hash = outerType.hashCode() + 31 * innerName.hashCode() this.hash = outerType.hashCode() + 31 * innerName.hashCode()
+ 31 * 31 * Arrays.hashCode(generics); + 31 * 31 * Arrays.hashCode(generics);
} }
@Override
public boolean isGeneric() {
return true;
}
@Override @Override
public ArgType[] getGenericTypes() { public ArgType[] getGenericTypes() {
return generics; return generics;
...@@ -370,6 +380,10 @@ public abstract class ArgType { ...@@ -370,6 +380,10 @@ public abstract class ArgType {
return false; return false;
} }
public boolean isGeneric() {
return false;
}
public boolean isGenericType() { public boolean isGenericType() {
return false; return false;
} }
......
...@@ -3,6 +3,9 @@ package jadx.core.dex.instructions.args; ...@@ -3,6 +3,9 @@ package jadx.core.dex.instructions.args;
import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.InsnNode;
import jadx.core.utils.InsnUtils; import jadx.core.utils.InsnUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.android.dx.io.instructions.DecodedInstruction; import com.android.dx.io.instructions.DecodedInstruction;
/** /**
...@@ -11,6 +14,8 @@ import com.android.dx.io.instructions.DecodedInstruction; ...@@ -11,6 +14,8 @@ import com.android.dx.io.instructions.DecodedInstruction;
*/ */
public abstract class InsnArg extends Typed { public abstract class InsnArg extends Typed {
private static final Logger LOG = LoggerFactory.getLogger(InsnArg.class);
protected InsnNode parentInsn; protected InsnNode parentInsn;
public static RegisterArg reg(int regNum, ArgType type) { public static RegisterArg reg(int regNum, ArgType type) {
...@@ -72,7 +77,10 @@ public abstract class InsnArg extends Typed { ...@@ -72,7 +77,10 @@ public abstract class InsnArg extends Typed {
if (parent == null) { if (parent == null) {
return null; return null;
} }
assert parent != insn : "Can't wrap instruction info itself"; if (parent == insn) {
LOG.debug("Can't wrap instruction info itself: " + insn);
return null;
}
int count = parent.getArgsCount(); int count = parent.getArgsCount();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
if (parent.getArg(i) == this) { if (parent.getArg(i) == this) {
......
...@@ -6,8 +6,13 @@ import jadx.core.dex.instructions.args.TypedVar; ...@@ -6,8 +6,13 @@ import jadx.core.dex.instructions.args.TypedVar;
import jadx.core.dex.nodes.DexNode; import jadx.core.dex.nodes.DexNode;
import jadx.core.utils.InsnUtils; import jadx.core.utils.InsnUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
final class LocalVar extends RegisterArg { final class LocalVar extends RegisterArg {
private static final Logger LOG = LoggerFactory.getLogger(LocalVar.class);
private boolean isEnd; private boolean isEnd;
private int startAddr; private int startAddr;
...@@ -29,13 +34,32 @@ final class LocalVar extends RegisterArg { ...@@ -29,13 +34,32 @@ final class LocalVar extends RegisterArg {
private void init(String name, ArgType type, String sign) { private void init(String name, ArgType type, String sign) {
if (sign != null) { if (sign != null) {
type = ArgType.generic(sign); ArgType gType = ArgType.generic(sign);
if (checkSignature(type, sign, gType)) {
type = gType;
}
} }
TypedVar tv = new TypedVar(type); TypedVar tv = new TypedVar(type);
tv.setName(name); tv.setName(name);
forceSetTypedVar(tv); forceSetTypedVar(tv);
} }
private boolean checkSignature(ArgType type, String sign, ArgType gType) {
boolean apply = false;
ArgType el = gType.getArrayRootElement();
if (el.isGeneric()) {
if (!type.getObject().equals(el.getObject())) {
LOG.warn("Generic type in debug info not equals: {} != {}", type, gType);
}
apply = true;
} else if (el.isGenericType()) {
apply = true;
} else {
LOG.debug("Local var signature from debug info not generic: {}, parsed: {}", sign, gType);
}
return apply;
}
public void start(int addr, int line) { public void start(int addr, int line) {
this.isEnd = false; this.isEnd = false;
this.startAddr = addr; this.startAddr = addr;
......
package jadx.core.dex.visitors.regions; package jadx.core.dex.visitors.regions;
import jadx.core.dex.attributes.AttributeFlag; import jadx.core.dex.attributes.AttributeFlag;
import jadx.core.dex.attributes.AttributeType;
import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IBlock; import jadx.core.dex.nodes.IBlock;
import jadx.core.dex.nodes.IRegion; import jadx.core.dex.nodes.IRegion;
...@@ -21,7 +22,9 @@ public class CheckRegions extends AbstractVisitor { ...@@ -21,7 +22,9 @@ public class CheckRegions extends AbstractVisitor {
@Override @Override
public void visit(MethodNode mth) throws JadxException { public void visit(MethodNode mth) throws JadxException {
if (mth.isNoCode() || mth.getBasicBlocks().isEmpty()) { if (mth.isNoCode()
|| mth.getBasicBlocks().isEmpty()
|| mth.getAttributes().contains(AttributeType.JADX_ERROR)) {
return; return;
} }
......
...@@ -50,7 +50,7 @@ public class TestSignatureParser { ...@@ -50,7 +50,7 @@ public class TestSignatureParser {
"c", new ArgType[]{ArgType.genericType("V")})); "c", new ArgType[]{ArgType.genericType("V")}));
assertEquals(p("La<TV;>.LinkedHashIterator<Lb$c<Ls;TV;>;>;").consumeType().getObject(), assertEquals(p("La<TV;>.LinkedHashIterator<Lb$c<Ls;TV;>;>;").consumeType().getObject(),
"a.LinkedHashIterator"); "a$LinkedHashIterator");
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册