Commit 7ac0b9f5 authored by Skylot's avatar Skylot

fix: redone class alias processing (#532)

parent 699f7f67
...@@ -36,7 +36,6 @@ import jadx.core.utils.CodegenUtils; ...@@ -36,7 +36,6 @@ import jadx.core.utils.CodegenUtils;
import jadx.core.utils.ErrorsCounter; import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.Utils; import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.CodegenException; import jadx.core.utils.exceptions.CodegenException;
import jadx.core.utils.exceptions.JadxRuntimeException;
public class ClassGen { public class ClassGen {
...@@ -84,14 +83,14 @@ public class ClassGen { ...@@ -84,14 +83,14 @@ public class ClassGen {
int importsCount = imports.size(); int importsCount = imports.size();
if (importsCount != 0) { if (importsCount != 0) {
List<ClassInfo> sortedImports = new ArrayList<>(imports); List<ClassInfo> sortedImports = new ArrayList<>(imports);
sortedImports.sort(Comparator.comparing(classInfo -> classInfo.getAlias().getFullName())); sortedImports.sort(Comparator.comparing(ClassInfo::getAliasFullName));
sortedImports.forEach(classInfo -> { sortedImports.forEach(classInfo -> {
clsCode.startLine("import "); clsCode.startLine("import ");
ClassNode classNode = cls.root().resolveClass(classInfo); ClassNode classNode = cls.root().resolveClass(classInfo);
if (classNode != null) { if (classNode != null) {
clsCode.attachAnnotation(classNode); clsCode.attachAnnotation(classNode);
} }
clsCode.add(classInfo.getAlias().getFullName()); clsCode.add(classInfo.getAliasFullName());
clsCode.add(';'); clsCode.add(';');
}); });
clsCode.newLine(); clsCode.newLine();
...@@ -123,7 +122,7 @@ public class ClassGen { ...@@ -123,7 +122,7 @@ public class ClassGen {
} }
// 'static' and 'private' modifier not allowed for top classes (not inner) // 'static' and 'private' modifier not allowed for top classes (not inner)
if (!cls.getAlias().isInner()) { if (!cls.getClassInfo().isInner()) {
af = af.remove(AccessFlags.ACC_STATIC).remove(AccessFlags.ACC_PRIVATE); af = af.remove(AccessFlags.ACC_STATIC).remove(AccessFlags.ACC_PRIVATE);
} }
...@@ -142,7 +141,7 @@ public class ClassGen { ...@@ -142,7 +141,7 @@ public class ClassGen {
clsCode.add("class "); clsCode.add("class ");
} }
clsCode.attachDefinition(cls); clsCode.attachDefinition(cls);
clsCode.add(cls.getAlias().getShortName()); clsCode.add(cls.getClassInfo().getAliasShortName());
addGenericMap(clsCode, cls.getGenericMap(), true); addGenericMap(clsCode, cls.getGenericMap(), true);
clsCode.add(' '); clsCode.add(' ');
...@@ -200,7 +199,9 @@ public class ClassGen { ...@@ -200,7 +199,9 @@ public class ClassGen {
code.add(g.getObject()); code.add(g.getObject());
} else { } else {
useClass(code, g); useClass(code, g);
if (classDeclaration && !cls.getAlias().isInner()) { if (classDeclaration
&& !cls.getClassInfo().isInner()
&& cls.root().getArgs().isUseImports()) {
addImport(ClassInfo.fromType(cls.root(), g)); addImport(ClassInfo.fromType(cls.root(), g));
} }
} }
...@@ -507,11 +508,11 @@ public class ClassGen { ...@@ -507,11 +508,11 @@ public class ClassGen {
} }
private String useClassInternal(ClassInfo useCls, ClassInfo extClsInfo) { private String useClassInternal(ClassInfo useCls, ClassInfo extClsInfo) {
String fullName = extClsInfo.getAlias().makeFullName(); String fullName = extClsInfo.getAliasFullName();
if (fallback || !useImports) { if (fallback || !useImports) {
return fullName; return fullName;
} }
String shortName = extClsInfo.getAlias().getShortName(); String shortName = extClsInfo.getAliasShortName();
if (extClsInfo.getPackage().equals("java.lang") && extClsInfo.getParentClass() == null) { if (extClsInfo.getPackage().equals("java.lang") && extClsInfo.getParentClass() == null) {
return shortName; return shortName;
} }
...@@ -537,12 +538,12 @@ public class ClassGen { ...@@ -537,12 +538,12 @@ public class ClassGen {
if (extClsInfo.isDefaultPackage()) { if (extClsInfo.isDefaultPackage()) {
return shortName; return shortName;
} }
if (extClsInfo.getAlias().getPackage().equals(useCls.getAlias().getPackage())) { if (extClsInfo.getAliasPkg().equals(useCls.getAliasPkg())) {
fullName = extClsInfo.getAlias().getNameWithoutPackage(); fullName = extClsInfo.getAliasNameWithoutPackage();
} }
for (ClassInfo importCls : getImports()) { for (ClassInfo importCls : getImports()) {
if (!importCls.equals(extClsInfo) if (!importCls.equals(extClsInfo)
&& importCls.getAlias().getShortName().equals(shortName)) { && importCls.getAliasShortName().equals(shortName)) {
if (extClsInfo.isInner()) { if (extClsInfo.isInner()) {
String parent = useClassInternal(useCls, extClsInfo.getParentClass()); String parent = useClassInternal(useCls, extClsInfo.getParentClass());
return parent + '.' + shortName; return parent + '.' + shortName;
...@@ -559,9 +560,6 @@ public class ClassGen { ...@@ -559,9 +560,6 @@ public class ClassGen {
if (parentGen != null) { if (parentGen != null) {
parentGen.addImport(classInfo); parentGen.addImport(classInfo);
} else { } else {
if (classInfo.isAlias()) {
throw new JadxRuntimeException("Don't add aliases class info to import list: " + classInfo);
}
imports.add(classInfo); imports.add(classInfo);
} }
} }
...@@ -596,15 +594,15 @@ public class ClassGen { ...@@ -596,15 +594,15 @@ public class ClassGen {
if (useCls == null) { if (useCls == null) {
return false; return false;
} }
String shortName = searchCls.getAlias().getShortName(); String shortName = searchCls.getAliasShortName();
if (useCls.getAlias().getShortName().equals(shortName)) { if (useCls.getAliasShortName().equals(shortName)) {
return true; return true;
} }
ClassNode classNode = dex.resolveClass(useCls); ClassNode classNode = dex.resolveClass(useCls);
if (classNode != null) { if (classNode != null) {
for (ClassNode inner : classNode.getInnerClasses()) { for (ClassNode inner : classNode.getInnerClasses()) {
if (inner.getAlias().getShortName().equals(shortName) if (inner.getShortName().equals(shortName)
&& !inner.getAlias().equals(searchCls.getAlias())) { && !inner.getFullName().equals(searchCls.getAliasFullName())) {
return true; return true;
} }
} }
...@@ -621,7 +619,7 @@ public class ClassGen { ...@@ -621,7 +619,7 @@ public class ClassGen {
private void insertRenameInfo(CodeWriter code, ClassNode cls) { private void insertRenameInfo(CodeWriter code, ClassNode cls) {
ClassInfo classInfo = cls.getClassInfo(); ClassInfo classInfo = cls.getClassInfo();
if (classInfo.isRenamed()) { if (classInfo.hasAlias()) {
code.startLine("/* renamed from: ").add(classInfo.getType().getObject()).add(" */"); code.startLine("/* renamed from: ").add(classInfo.getType().getObject()).add(" */");
} }
} }
......
...@@ -653,7 +653,7 @@ public class InsnGen { ...@@ -653,7 +653,7 @@ public class InsnGen {
break; break;
case STATIC: case STATIC:
ClassInfo insnCls = mth.getParentClass().getAlias(); ClassInfo insnCls = mth.getParentClass().getClassInfo();
ClassInfo declClass = callMth.getDeclClass(); ClassInfo declClass = callMth.getDeclClass();
if (!insnCls.equals(declClass)) { if (!insnCls.equals(declClass)) {
useClass(code, declClass); useClass(code, declClass);
...@@ -673,7 +673,7 @@ public class InsnGen { ...@@ -673,7 +673,7 @@ public class InsnGen {
@Nullable @Nullable
private ClassInfo getClassForSuperCall(CodeWriter code, MethodInfo callMth) { private ClassInfo getClassForSuperCall(CodeWriter code, MethodInfo callMth) {
ClassNode useCls = mth.getParentClass(); ClassNode useCls = mth.getParentClass();
ClassInfo insnCls = useCls.getAlias(); ClassInfo insnCls = useCls.getClassInfo();
ClassInfo declClass = callMth.getDeclClass(); ClassInfo declClass = callMth.getDeclClass();
if (insnCls.equals(declClass)) { if (insnCls.equals(declClass)) {
return null; return null;
......
...@@ -187,7 +187,7 @@ public class MethodGen { ...@@ -187,7 +187,7 @@ public class MethodGen {
code.startLine("*/"); code.startLine("*/");
code.startLine("throw new UnsupportedOperationException(\"Method not decompiled: ") code.startLine("throw new UnsupportedOperationException(\"Method not decompiled: ")
.add(mth.getParentClass().getAlias().makeFullName()) .add(mth.getParentClass().getClassInfo().getAliasFullName())
.add('.') .add('.')
.add(mth.getAlias()) .add(mth.getAlias())
.add('(') .add('(')
......
...@@ -65,7 +65,7 @@ public class NameGen { ...@@ -65,7 +65,7 @@ public class NameGen {
varNames.add(field.getAlias()); varNames.add(field.getAlias());
} }
for (ClassNode innerClass : parentClass.getInnerClasses()) { for (ClassNode innerClass : parentClass.getInnerClasses()) {
varNames.add(innerClass.getAlias().getShortName()); varNames.add(innerClass.getClassInfo().getAliasShortName());
} }
// add all root package names to avoid collisions with full class names // add all root package names to avoid collisions with full class names
varNames.addAll(mth.root().getCacheStorage().getRootPkgs()); varNames.addAll(mth.root().getCacheStorage().getRootPkgs());
...@@ -259,10 +259,10 @@ public class NameGen { ...@@ -259,10 +259,10 @@ public class NameGen {
if (name.startsWith("get") || name.startsWith("set")) { if (name.startsWith("get") || name.startsWith("set")) {
return fromName(name.substring(3)); return fromName(name.substring(3));
} }
ArgType declType = callMth.getDeclClass().getAlias().getType();
if ("iterator".equals(name)) { if ("iterator".equals(name)) {
return "it"; return "it";
} }
ArgType declType = callMth.getDeclClass().getType();
if ("toString".equals(name)) { if ("toString".equals(name)) {
return makeNameForType(declType); return makeNameForType(declType);
} }
......
...@@ -6,6 +6,7 @@ import java.util.ArrayList; ...@@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -43,7 +44,7 @@ public class Deobfuscator { ...@@ -43,7 +44,7 @@ public class Deobfuscator {
private final List<DexNode> dexNodes; private final List<DexNode> dexNodes;
private final DeobfPresets deobfPresets; private final DeobfPresets deobfPresets;
private final Map<ClassInfo, DeobfClsInfo> clsMap = new HashMap<>(); private final Map<ClassInfo, DeobfClsInfo> clsMap = new LinkedHashMap<>();
private final Map<FieldInfo, String> fldMap = new HashMap<>(); private final Map<FieldInfo, String> fldMap = new HashMap<>();
private final Map<MethodInfo, String> mthMap = new HashMap<>(); private final Map<MethodInfo, String> mthMap = new HashMap<>();
...@@ -230,9 +231,19 @@ public class Deobfuscator { ...@@ -230,9 +231,19 @@ public class Deobfuscator {
return; return;
} }
ClassInfo clsInfo = cls.getClassInfo(); ClassInfo clsInfo = cls.getClassInfo();
String fullName = getClassFullName(clsInfo); DeobfClsInfo deobfClsInfo = clsMap.get(clsInfo);
if (!fullName.equals(clsInfo.getFullName())) { if (deobfClsInfo != null) {
clsInfo.rename(cls.root(), fullName); clsInfo.changeShortName(deobfClsInfo.getAlias());
PackageNode pkgNode = deobfClsInfo.getPkg();
if (!clsInfo.isInner() && pkgNode.hasAnyAlias()) {
clsInfo.changePkg(pkgNode.getFullAlias());
}
} else if (!clsInfo.isInner()) {
// check if package renamed
PackageNode pkgNode = getPackageNode(clsInfo.getPackage(), false);
if (pkgNode.hasAnyAlias()) {
clsInfo.changePkg(pkgNode.getFullAlias());
}
} }
for (FieldNode field : cls.getFields()) { for (FieldNode field : cls.getFields()) {
if (field.contains(AFlag.DONT_RENAME)) { if (field.contains(AFlag.DONT_RENAME)) {
...@@ -397,7 +408,7 @@ public class Deobfuscator { ...@@ -397,7 +408,7 @@ public class Deobfuscator {
} else if (name.endsWith(".kt")) { } else if (name.endsWith(".kt")) {
name = name.substring(0, name.length() - ".kt".length()); name = name.substring(0, name.length() - ".kt".length());
} }
if (!NameMapper.isValidIdentifier(name) || NameMapper.isReserved(name)) { if (!NameMapper.isValidIdentifier(name) || !NameMapper.isAllCharsPrintable(name)) {
return null; return null;
} }
for (DeobfClsInfo deobfClsInfo : clsMap.values()) { for (DeobfClsInfo deobfClsInfo : clsMap.values()) {
...@@ -405,7 +416,7 @@ public class Deobfuscator { ...@@ -405,7 +416,7 @@ public class Deobfuscator {
return null; return null;
} }
} }
ClassNode otherCls = cls.dex().root().searchClassByName(cls.getPackage() + '.' + name); ClassNode otherCls = cls.root().searchClassByName(cls.getPackage() + '.' + name);
if (otherCls != null) { if (otherCls != null) {
return null; return null;
} }
...@@ -537,10 +548,7 @@ public class Deobfuscator { ...@@ -537,10 +548,7 @@ public class Deobfuscator {
} }
private String getClassFullName(ClassNode cls) { private String getClassFullName(ClassNode cls) {
return getClassFullName(cls.getClassInfo()); ClassInfo clsInfo = cls.getClassInfo();
}
private String getClassFullName(ClassInfo clsInfo) {
DeobfClsInfo deobfClsInfo = clsMap.get(clsInfo); DeobfClsInfo deobfClsInfo = clsMap.get(clsInfo);
if (deobfClsInfo != null) { if (deobfClsInfo != null) {
return deobfClsInfo.getFullName(); return deobfClsInfo.getFullName();
......
...@@ -126,7 +126,7 @@ public class NameMapper { ...@@ -126,7 +126,7 @@ public class NameMapper {
* <p> * <p>
*/ */
public static String removeInvalidCharsMiddle(String name) { public static String removeInvalidCharsMiddle(String name) {
if (isValidIdentifier(name)) { if (isValidIdentifier(name) && isAllCharsPrintable(name)) {
return name; return name;
} }
int len = name.length(); int len = name.length();
......
...@@ -58,6 +58,16 @@ public class PackageNode { ...@@ -58,6 +58,16 @@ public class PackageNode {
return packageAlias != null; return packageAlias != null;
} }
public boolean hasAnyAlias() {
if (hasAlias()) {
return true;
}
if (parentPackage != this) {
return parentPackage.hasAnyAlias();
}
return false;
}
public String getFullAlias() { public String getFullAlias() {
if (cachedPackageFullAlias == null) { if (cachedPackageFullAlias == null) {
Deque<PackageNode> pp = getParentPackages(); Deque<PackageNode> pp = getParentPackages();
......
package jadx.core.dex.info;
import org.jetbrains.annotations.Nullable;
class ClassAliasInfo {
private final String shortName;
@Nullable
private final String pkg;
@Nullable
private String fullName;
ClassAliasInfo(@Nullable String pkg, String shortName) {
this.pkg = pkg;
this.shortName = shortName;
}
@Nullable
public String getPkg() {
return pkg;
}
public String getShortName() {
return shortName;
}
@Nullable
public String getFullName() {
return fullName;
}
public void setFullName(@Nullable String fullName) {
this.fullName = fullName;
}
@Override
public String toString() {
return "Alias{" + shortName + ", pkg=" + pkg + ", fullName=" + fullName + '}';
}
}
...@@ -12,48 +12,42 @@ import jadx.core.dex.nodes.RootNode; ...@@ -12,48 +12,42 @@ import jadx.core.dex.nodes.RootNode;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
public final class ClassInfo implements Comparable<ClassInfo> { public final class ClassInfo implements Comparable<ClassInfo> {
private final ArgType type; private final ArgType type;
private String pkg;
private String name; private String name;
@Nullable("for inner classes")
private String pkg;
private String fullName; private String fullName;
// for inner class not equals null @Nullable
private ClassInfo parentClass; private ClassInfo parentClass;
// class info after rename (deobfuscation) @Nullable
private ClassInfo alias; private ClassAliasInfo alias;
private ClassInfo(ArgType type) {
this.type = checkClassType(type);
this.alias = this;
}
private ClassInfo(RootNode root, ArgType type) {
this(root, type, true);
}
private ClassInfo(RootNode root, ArgType type, boolean inner) { private ClassInfo(RootNode root, ArgType type, boolean inner) {
this(type); this.type = type;
splitAndApplyNames(root, type, inner); splitAndApplyNames(root, type, inner);
} }
private ClassInfo(ArgType type, String pkg, String name, @Nullable ClassInfo parentClass) {
this(type);
this.pkg = pkg;
this.name = name;
this.parentClass = parentClass;
this.fullName = makeFullClsName(name, false);
}
public static ClassInfo fromType(RootNode root, ArgType type) { public static ClassInfo fromType(RootNode root, ArgType type) {
ArgType clsType = checkClassType(type); ArgType clsType = checkClassType(type);
ClassInfo cls = root.getInfoStorage().getCls(clsType); ClassInfo cls = root.getInfoStorage().getCls(clsType);
if (cls != null) { if (cls != null) {
return cls; return cls;
} }
ClassInfo newClsInfo = new ClassInfo(root, clsType); ClassInfo newClsInfo = new ClassInfo(root, clsType, true);
return root.getInfoStorage().putCls(newClsInfo); return root.getInfoStorage().putCls(newClsInfo);
} }
public static ClassInfo fromDex(DexNode dex, int clsIndex) {
if (clsIndex == DexNode.NO_INDEX) {
return null;
}
return fromType(dex.root(), dex.getType(clsIndex));
}
public static ClassInfo fromName(RootNode root, String clsName) {
return fromType(root, ArgType.object(clsName));
}
private static ArgType checkClassType(ArgType type) { private static ArgType checkClassType(ArgType type) {
if (type == null) { if (type == null) {
throw new JadxRuntimeException("Null class type"); throw new JadxRuntimeException("Null class type");
...@@ -71,135 +65,164 @@ public final class ClassInfo implements Comparable<ClassInfo> { ...@@ -71,135 +65,164 @@ public final class ClassInfo implements Comparable<ClassInfo> {
return type; return type;
} }
public static ClassInfo fromDex(DexNode dex, int clsIndex) { public void changeShortName(String aliasName) {
if (clsIndex == DexNode.NO_INDEX) { if (!Objects.equals(name, aliasName)) {
return null; ClassAliasInfo newAlias = new ClassAliasInfo(getAliasPkg(), aliasName);
fillAliasFullName(newAlias);
this.alias = newAlias;
} }
return fromType(dex.root(), dex.getType(clsIndex));
} }
public static ClassInfo fromName(RootNode root, String clsName) { public void changePkg(String aliasPkg) {
return fromType(root, ArgType.object(clsName)); if (isInner()) {
} throw new JadxRuntimeException("Can't change package for inner class");
}
public void rename(RootNode root, String fullName) { if (!Objects.equals(getAliasPkg(), aliasPkg)) {
if (!alias.makeFullName().equals(fullName)) { ClassAliasInfo newAlias = new ClassAliasInfo(aliasPkg, getAliasShortName());
ClassInfo newAlias = new ClassInfo(type); fillAliasFullName(newAlias);
newAlias.splitAndApplyNames(root, fullName, isInner());
newAlias.alias = null;
this.alias = newAlias; this.alias = newAlias;
} }
} }
public void renameShortName(String aliasName) { private void fillAliasFullName(ClassAliasInfo alias) {
if (!Objects.equals(name, aliasName)) { if (parentClass == null) {
ClassInfo newAlias = new ClassInfo(type, alias.pkg, aliasName, parentClass); alias.setFullName(makeFullClsName(alias.getPkg(), alias.getShortName(), null, true, false));
newAlias.alias = null;
this.alias = newAlias;
} }
} }
public void renamePkg(String aliasPkg) { public String getAliasPkg() {
if (!Objects.equals(pkg, aliasPkg)) { if (isInner()) {
ClassInfo newAlias = new ClassInfo(type, aliasPkg, alias.name, parentClass); return parentClass.getAliasPkg();
newAlias.alias = null;
this.alias = newAlias;
} }
return alias == null ? getPackage() : alias.getPkg();
} }
public boolean isRenamed() { public String getAliasShortName() {
return alias != this; return alias == null ? getShortName() : alias.getShortName();
} }
public ClassInfo getAlias() { public String getAliasFullName() {
return alias == null ? this : alias; if (alias != null) {
String aliasFullName = alias.getFullName();
if (aliasFullName == null) {
return makeAliasFullName();
}
return aliasFullName;
}
if (parentClass != null && parentClass.hasAlias()) {
return makeAliasFullName();
}
return getFullName();
} }
public boolean isAlias() { public boolean hasAlias() {
return alias == null; if (alias != null) {
return true;
}
return parentClass != null && parentClass.hasAlias();
} }
private void splitAndApplyNames(RootNode root, ArgType type, boolean canBeInner) { private void splitAndApplyNames(RootNode root, ArgType type, boolean canBeInner) {
splitAndApplyNames(root, type.getObject(), canBeInner); String fullObjectName = type.getObject();
} String clsPkg;
private void splitAndApplyNames(RootNode root, String fullObjectName, boolean canBeInner) {
String clsName; String clsName;
int dot = fullObjectName.lastIndexOf('.'); int dot = fullObjectName.lastIndexOf('.');
if (dot == -1) { if (dot == -1) {
pkg = ""; clsPkg = "";
clsName = fullObjectName; clsName = fullObjectName;
} else { } else {
pkg = fullObjectName.substring(0, dot); clsPkg = fullObjectName.substring(0, dot);
clsName = fullObjectName.substring(dot + 1); clsName = fullObjectName.substring(dot + 1);
} }
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 = clsPkg + '.' + clsName.substring(0, sep);
if (pkg.isEmpty()) { if (clsPkg.isEmpty()) {
parClsName = clsName.substring(0, sep); parClsName = clsName.substring(0, sep);
} }
pkg = null;
parentClass = fromName(root, parClsName); parentClass = fromName(root, parClsName);
clsName = clsName.substring(sep + 1); clsName = clsName.substring(sep + 1);
} else { } else {
pkg = clsPkg;
parentClass = null; parentClass = null;
} }
this.name = clsName; this.name = clsName;
this.fullName = makeFullClsName(clsName, false); this.fullName = makeFullName();
} }
private String makeFullClsName(String shortName, boolean raw) { private static String makeFullClsName(String pkg, String shortName, ClassInfo parentClass, boolean alias, boolean raw) {
if (parentClass != null) { if (parentClass != null) {
String innerSep = raw ? "$" : "."; String innerSep = raw ? "$" : ".";
return parentClass.makeFullClsName(parentClass.getShortName(), raw) + innerSep + shortName; String parentFullName;
if (alias) {
parentFullName = raw ? parentClass.makeAliasRawFullName() : parentClass.getAliasFullName();
} else {
parentFullName = raw ? parentClass.makeRawFullName() : parentClass.getFullName();
}
return parentFullName + innerSep + shortName;
} }
return pkg.isEmpty() ? shortName : pkg + '.' + shortName; return pkg.isEmpty() ? shortName : pkg + '.' + shortName;
} }
public String makeFullName() { private String makeFullName() {
return makeFullClsName(this.name, false); return makeFullClsName(pkg, name, parentClass, false, false);
} }
public String makeRawFullName() { public String makeRawFullName() {
return makeFullClsName(this.name, true); return makeFullClsName(pkg, name, parentClass, false, true);
}
private String makeAliasFullName() {
return makeFullClsName(getAliasPkg(), getAliasShortName(), parentClass, true, false);
}
private String makeAliasRawFullName() {
return makeFullClsName(pkg, name, parentClass, true, true);
} }
public String getFullPath() { public String getAliasFullPath() {
ClassInfo usedAlias = getAlias(); return getAliasPkg().replace('.', File.separatorChar)
return usedAlias.getPackage().replace('.', File.separatorChar)
+ File.separatorChar + File.separatorChar
+ usedAlias.getNameWithoutPackage().replace('.', '_'); + getAliasNameWithoutPackage().replace('.', '_');
} }
public String getFullName() { public String getFullName() {
return makeFullName(); return fullName;
} }
public String getShortName() { public String getShortName() {
return name; return name;
} }
@NotNull
public String getPackage() { public String getPackage() {
if (parentClass != null) {
return parentClass.getPackage();
}
if (pkg == null) {
throw new JadxRuntimeException("Package is null for not inner class");
}
return pkg; return pkg;
} }
public boolean isDefaultPackage() { public boolean isDefaultPackage() {
return pkg.isEmpty(); return getPackage().isEmpty();
} }
public String getRawName() { public String getRawName() {
return type.getObject(); return type.getObject();
} }
public String getNameWithoutPackage() { public String getAliasNameWithoutPackage() {
if (parentClass == null) { if (parentClass == null) {
return name; return getAliasShortName();
} }
return parentClass.getNameWithoutPackage() + '.' + name; return parentClass.getAliasNameWithoutPackage() + '.' + getAliasShortName();
} }
@Nullable
public ClassInfo getParentClass() { public ClassInfo getParentClass() {
return parentClass; return parentClass;
} }
...@@ -231,7 +254,7 @@ public final class ClassInfo implements Comparable<ClassInfo> { ...@@ -231,7 +254,7 @@ public final class ClassInfo implements Comparable<ClassInfo> {
@Override @Override
public String toString() { public String toString() {
return makeFullName(); return getFullName();
} }
@Override @Override
...@@ -253,6 +276,6 @@ public final class ClassInfo implements Comparable<ClassInfo> { ...@@ -253,6 +276,6 @@ public final class ClassInfo implements Comparable<ClassInfo> {
@Override @Override
public int compareTo(@NotNull ClassInfo o) { public int compareTo(@NotNull ClassInfo o) {
return fullName.compareTo(o.fullName); return getFullName().compareTo(o.getFullName());
} }
} }
...@@ -459,23 +459,16 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode { ...@@ -459,23 +459,16 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
return clsInfo; return clsInfo;
} }
/**
* Class info for external usage (code generation and external api).
*/
public ClassInfo getAlias() {
return clsInfo.getAlias();
}
public String getShortName() { public String getShortName() {
return clsInfo.getAlias().getShortName(); return clsInfo.getAliasShortName();
} }
public String getFullName() { public String getFullName() {
return clsInfo.getAlias().getFullName(); return clsInfo.getAliasFullName();
} }
public String getPackage() { public String getPackage() {
return clsInfo.getAlias().getPackage(); return clsInfo.getAliasPkg();
} }
public void setCode(CodeWriter code) { public void setCode(CodeWriter code) {
......
...@@ -25,7 +25,6 @@ import jadx.core.dex.info.ClassInfo; ...@@ -25,7 +25,6 @@ import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo; import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo; import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.core.utils.files.DexFile; import jadx.core.utils.files.DexFile;
public class DexNode implements IDexNode { public class DexNode implements IDexNode {
...@@ -95,9 +94,6 @@ public class DexNode implements IDexNode { ...@@ -95,9 +94,6 @@ public class DexNode implements IDexNode {
@Nullable @Nullable
ClassNode resolveClassLocal(ClassInfo clsInfo) { ClassNode resolveClassLocal(ClassInfo clsInfo) {
if (clsInfo.isAlias()) {
throw new JadxRuntimeException("Don't resolve class by alias: " + clsInfo);
}
return clsMap.get(clsInfo); return clsMap.get(clsInfo);
} }
......
...@@ -116,7 +116,7 @@ public class DotGraphVisitor extends AbstractVisitor { ...@@ -116,7 +116,7 @@ public class DotGraphVisitor extends AbstractVisitor {
+ (useRegions ? ".regions" : "") + (useRegions ? ".regions" : "")
+ (rawInsn ? ".raw" : "") + (rawInsn ? ".raw" : "")
+ ".dot"; + ".dot";
dot.save(dir, mth.getParentClass().getClassInfo().getFullPath() + "_graphs", fileName); dot.save(dir, mth.getParentClass().getClassInfo().getAliasFullPath() + "_graphs", fileName);
} }
private void processMethodRegion(MethodNode mth) { private void processMethodRegion(MethodNode mth) {
......
...@@ -154,7 +154,8 @@ public class PrepareForCodeGen extends AbstractVisitor { ...@@ -154,7 +154,8 @@ public class PrepareForCodeGen extends AbstractVisitor {
private static void modifyArith(BlockNode block) { private static void modifyArith(BlockNode block) {
List<InsnNode> list = block.getInstructions(); List<InsnNode> list = block.getInstructions();
for (InsnNode insn : list) { for (InsnNode insn : list) {
if (insn.getType() == InsnType.ARITH) { if (insn.getType() == InsnType.ARITH
&& !insn.contains(AFlag.DECLARE_VAR)) { // TODO: move this modify before ProcessVariable
RegisterArg res = insn.getResult(); RegisterArg res = insn.getResult();
InsnArg arg = insn.getArg(0); InsnArg arg = insn.getArg(0);
boolean replace = false; boolean replace = false;
......
...@@ -59,11 +59,10 @@ public class RenameVisitor extends AbstractVisitor { ...@@ -59,11 +59,10 @@ public class RenameVisitor extends AbstractVisitor {
Set<String> clsFullPaths = new HashSet<>(classes.size()); Set<String> clsFullPaths = new HashSet<>(classes.size());
for (ClassNode cls : classes) { for (ClassNode cls : classes) {
ClassInfo clsInfo = cls.getClassInfo(); ClassInfo clsInfo = cls.getClassInfo();
ClassInfo aliasClsInfo = clsInfo.getAlias(); if (!clsFullPaths.add(clsInfo.getAliasFullPath().toLowerCase())) {
if (!clsFullPaths.add(aliasClsInfo.getFullPath().toLowerCase())) {
String newShortName = deobfuscator.getClsAlias(cls); String newShortName = deobfuscator.getClsAlias(cls);
clsInfo.renameShortName(newShortName); clsInfo.changeShortName(newShortName);
clsFullPaths.add(clsInfo.getAlias().getFullPath().toLowerCase()); clsFullPaths.add(clsInfo.getAliasFullPath().toLowerCase());
} }
} }
} }
...@@ -72,14 +71,28 @@ public class RenameVisitor extends AbstractVisitor { ...@@ -72,14 +71,28 @@ public class RenameVisitor extends AbstractVisitor {
private void checkClassName(ClassNode cls, JadxArgs args) { private void checkClassName(ClassNode cls, JadxArgs args) {
ClassInfo classInfo = cls.getClassInfo(); ClassInfo classInfo = cls.getClassInfo();
String clsName = classInfo.getAlias().getShortName(); String clsName = classInfo.getAliasShortName();
String newShortName = fixClsShortName(args, clsName); String newShortName = fixClsShortName(args, clsName);
if (!newShortName.equals(clsName)) { if (!newShortName.equals(clsName)) {
classInfo.renameShortName(newShortName); classInfo.changeShortName(newShortName);
} }
if (classInfo.getAlias().getPackage().isEmpty()) { if (args.isRenameValid()) {
classInfo.renamePkg(Consts.DEFAULT_PACKAGE_NAME); if (classInfo.isInner()) {
ClassInfo parentClass = classInfo.getParentClass();
while (parentClass != null) {
if (parentClass.getAliasShortName().equals(clsName)) {
String clsAlias = deobfuscator.getClsAlias(cls);
classInfo.changeShortName(clsAlias);
break;
}
parentClass = parentClass.getParentClass();
}
} else {
if (classInfo.getAliasPkg().isEmpty()) {
classInfo.changePkg(Consts.DEFAULT_PACKAGE_NAME);
}
}
} }
} }
...@@ -157,7 +170,7 @@ public class RenameVisitor extends AbstractVisitor { ...@@ -157,7 +170,7 @@ public class RenameVisitor extends AbstractVisitor {
private static Set<String> collectRootPkgs(List<ClassNode> classes) { private static Set<String> collectRootPkgs(List<ClassNode> classes) {
Set<String> fullPkgs = new HashSet<>(); Set<String> fullPkgs = new HashSet<>();
for (ClassNode cls : classes) { for (ClassNode cls : classes) {
fullPkgs.add(cls.getAlias().getPackage()); fullPkgs.add(cls.getClassInfo().getAliasPkg());
} }
Set<String> rootPkgs = new HashSet<>(); Set<String> rootPkgs = new HashSet<>();
for (String pkg : fullPkgs) { for (String pkg : fullPkgs) {
......
...@@ -21,7 +21,7 @@ public class SaveCode { ...@@ -21,7 +21,7 @@ public class SaveCode {
if (clsCode == null) { if (clsCode == null) {
throw new JadxRuntimeException("Code not generated for class " + cls.getFullName()); throw new JadxRuntimeException("Code not generated for class " + cls.getFullName());
} }
String fileName = cls.getClassInfo().getFullPath() + ".java"; String fileName = cls.getClassInfo().getAliasFullPath() + ".java";
if (args.isFallbackMode()) { if (args.isFallbackMode()) {
fileName += ".jadx"; fileName += ".jadx";
} }
......
...@@ -74,7 +74,7 @@ public class AndroidResourcesUtils { ...@@ -74,7 +74,7 @@ public class AndroidResourcesUtils {
if (parentClass != null && parentClass.getShortName().equals("R")) { if (parentClass != null && parentClass.getShortName().equals("R")) {
clsGen.useClass(code, parentClass); clsGen.useClass(code, parentClass);
code.add('.'); code.add('.');
code.add(declClass.getAlias().getShortName()); code.add(declClass.getAliasShortName());
return true; return true;
} }
return false; return false;
......
...@@ -3,6 +3,7 @@ package jadx.core.xmlgen; ...@@ -3,6 +3,7 @@ package jadx.core.xmlgen;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode; import jadx.core.dex.nodes.RootNode;
...@@ -28,9 +29,10 @@ public class XmlDeobf { ...@@ -28,9 +29,10 @@ public class XmlDeobf {
private static String getNewClassName(RootNode rootNode, String old) { private static String getNewClassName(RootNode rootNode, String old) {
if (DEOBF_MAP.isEmpty()) { if (DEOBF_MAP.isEmpty()) {
for (ClassNode classNode : rootNode.getClasses(true)) { for (ClassNode classNode : rootNode.getClasses(true)) {
if (classNode.getAlias() != null) { ClassInfo classInfo = classNode.getClassInfo();
String oldName = classNode.getClassInfo().getFullName(); if (classInfo.hasAlias()) {
String newName = classNode.getAlias().getFullName(); String oldName = classInfo.getFullName();
String newName = classInfo.getAliasFullName();
if (!oldName.equals(newName)) { if (!oldName.equals(newName)) {
DEOBF_MAP.put(oldName, newName); DEOBF_MAP.put(oldName, newName);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment