Commit 4e982722 authored by Skylot's avatar Skylot

core: fix incorrect package for R class (#99)

parent 2b1f815c
......@@ -501,6 +501,10 @@ public class ClassGen {
if (searchCollision(cls.dex(), useCls, extClsInfo)) {
return fullName;
}
// ignore classes from default package
if (extClsInfo.isDefaultPackage()) {
return shortName;
}
if (extClsInfo.getPackage().equals(useCls.getPackage())) {
fullName = extClsInfo.getNameWithoutPackage();
}
......
......@@ -52,6 +52,8 @@ import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static jadx.core.utils.android.AndroidResourcesUtils.handleAppResField;
public class InsnGen {
private static final Logger LOG = LoggerFactory.getLogger(InsnGen.class);
......@@ -169,12 +171,7 @@ public class InsnGen {
boolean fieldFromThisClass = clsGen.getClassNode().getClassInfo().equals(declClass);
if (!fieldFromThisClass) {
// Android specific resources class handler
ClassInfo parentClass = declClass.getParentClass();
if (parentClass != null && parentClass.getShortName().equals("R")) {
clsGen.useClass(code, parentClass);
code.add('.');
code.add(declClass.getAlias().getShortName());
} else {
if (!handleAppResField(code, clsGen, declClass)) {
clsGen.useClass(code, declClass);
}
code.add('.');
......
......@@ -125,6 +125,10 @@ public final class ClassInfo {
return pkg;
}
public boolean isDefaultPackage() {
return pkg.isEmpty();
}
public String getRawName() {
return type.getObject();
}
......
......@@ -17,10 +17,8 @@ public class FieldNode extends LineAttrNode {
private ArgType type; // store signature
public FieldNode(ClassNode cls, Field field) {
this.parent = cls;
this.fieldInfo = FieldInfo.fromDex(cls.dex(), field.getFieldIndex());
this.type = fieldInfo.getType();
this.accFlags = new AccessInfo(field.getAccessFlags(), AFType.FIELD);
this(cls, FieldInfo.fromDex(cls.dex(), field.getFieldIndex()),
field.getAccessFlags());
}
public FieldNode(ClassNode cls, FieldInfo fieldInfo, int accessFlags) {
......
......@@ -9,6 +9,7 @@ import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.ConstStorage;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.StringUtils;
import jadx.core.utils.android.AndroidResourcesUtils;
import jadx.core.utils.exceptions.DecodeException;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.files.DexFile;
......@@ -97,24 +98,7 @@ public class RootNode {
}
public void initAppResClass() {
ClassNode resCls;
if (appPackage == null) {
appResClass = makeClass("R");
return;
}
String fullName = appPackage + ".R";
resCls = searchClassByName(fullName);
if (resCls != null) {
appResClass = resCls;
} else {
appResClass = makeClass(fullName);
}
}
private ClassNode makeClass(String clsName) {
DexNode firstDex = dexNodes.get(0);
ClassInfo r = ClassInfo.fromName(firstDex, clsName);
return new ClassNode(firstDex, r);
appResClass = AndroidResourcesUtils.searchAppResClass(this);
}
public void initClassPath() throws DecodeException {
......@@ -169,6 +153,18 @@ public class RootNode {
return null;
}
public List<ClassNode> searchClassByShortName(String shortName) {
List<ClassNode> list = new ArrayList<ClassNode>();
for (DexNode dexNode : dexNodes) {
for (ClassNode cls : dexNode.getClasses()) {
if (cls.getClassInfo().getShortName().equals(shortName)) {
list.add(cls);
}
}
}
return list;
}
public List<DexNode> getDexNodes() {
return dexNodes;
}
......
package jadx.core.utils.android;
import jadx.core.codegen.ClassGen;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.DexNode;
import jadx.core.dex.nodes.RootNode;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Android resources specific handlers
*/
public class AndroidResourcesUtils {
private static final Logger LOG = LoggerFactory.getLogger(AndroidResourcesUtils.class);
public static ClassNode searchAppResClass(RootNode root) {
String appPackage = root.getAppPackage();
String fullName = appPackage != null ? appPackage + ".R" : "R";
ClassNode resCls = root.searchClassByName(fullName);
if (resCls != null) {
return resCls;
}
List<ClassNode> candidates = root.searchClassByShortName("R");
if (candidates.size() == 1) {
return candidates.get(0);
}
if (!candidates.isEmpty()) {
LOG.info("Found several 'R' class candidates: {}", candidates);
}
LOG.warn("Unknown 'R' class, create references to '{}'", fullName);
return makeClass(root, fullName);
}
public static boolean handleAppResField(CodeWriter code, ClassGen clsGen, ClassInfo declClass) {
ClassInfo parentClass = declClass.getParentClass();
if (parentClass != null && parentClass.getShortName().equals("R")) {
clsGen.useClass(code, parentClass);
code.add('.');
code.add(declClass.getAlias().getShortName());
return true;
}
return false;
}
private static ClassNode makeClass(RootNode root, String clsName) {
DexNode firstDex = root.getDexNodes().get(0);
ClassInfo r = ClassInfo.fromName(firstDex, clsName);
return new ClassNode(firstDex, r);
}
}
......@@ -9,6 +9,8 @@ import java.util.Map;
import org.junit.Test;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
public class TestRFieldRestore extends IntegrationTest {
......@@ -31,5 +33,6 @@ public class TestRFieldRestore extends IntegrationTest {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
assertThat(code, containsOne("return R.id.Button;"));
assertThat(code, not(containsString("import R;")));
}
}
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