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