Commit 6116a750 authored by Skylot's avatar Skylot

fix: rename R fields using resource names (#465)

parent 7243ab5c
package jadx.core.utils.android; package jadx.core.utils.android;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import com.android.dx.rop.code.AccessFlags; import com.android.dx.rop.code.AccessFlags;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import jadx.core.codegen.ClassGen; import jadx.core.codegen.ClassGen;
import jadx.core.codegen.CodeWriter; import jadx.core.codegen.CodeWriter;
import jadx.core.deobf.NameMapper;
import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.AType;
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.info.ClassInfo; import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.ConstStorage;
import jadx.core.dex.info.FieldInfo; import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
...@@ -86,6 +91,7 @@ public class AndroidResourcesUtils { ...@@ -86,6 +91,7 @@ public class AndroidResourcesUtils {
} }
private static void addResourceFields(ClassNode resCls, ResourceStorage resStorage, boolean rClsExists) { private static void addResourceFields(ClassNode resCls, ResourceStorage resStorage, boolean rClsExists) {
Map<Integer, FieldNode> resFieldsMap = fillResFieldsMap(resCls);
Map<String, ClassNode> innerClsMap = new TreeMap<>(); Map<String, ClassNode> innerClsMap = new TreeMap<>();
if (rClsExists) { if (rClsExists) {
for (ClassNode innerClass : resCls.getInnerClasses()) { for (ClassNode innerClass : resCls.getInnerClasses()) {
...@@ -93,18 +99,14 @@ public class AndroidResourcesUtils { ...@@ -93,18 +99,14 @@ public class AndroidResourcesUtils {
} }
} }
for (ResourceEntry resource : resStorage.getResources()) { for (ResourceEntry resource : resStorage.getResources()) {
ClassNode typeCls = innerClsMap.computeIfAbsent(resource.getTypeName(), name -> { ClassNode typeCls = innerClsMap.computeIfAbsent(
ClassNode newTypeCls = new ClassNode(resCls.dex(), resCls.getFullName() + "$" + name, resource.getTypeName(),
AccessFlags.ACC_PUBLIC | AccessFlags.ACC_STATIC | AccessFlags.ACC_FINAL); name -> addClassForResType(resCls, rClsExists, name)
resCls.addInnerClass(newTypeCls); );
if (rClsExists) { String resName = resource.getKeyName();
newTypeCls.addAttr(AType.COMMENTS, "added by JADX"); FieldNode rField = typeCls.searchFieldByName(resName);
}
return newTypeCls;
});
FieldNode rField = typeCls.searchFieldByName(resource.getKeyName());
if (rField == null) { if (rField == null) {
FieldInfo rFieldInfo = FieldInfo.from(typeCls.dex(), typeCls.getClassInfo(), resource.getKeyName(), ArgType.INT); FieldInfo rFieldInfo = FieldInfo.from(typeCls.dex(), typeCls.getClassInfo(), resName, ArgType.INT);
rField = new FieldNode(typeCls, rFieldInfo, AccessFlags.ACC_PUBLIC | AccessFlags.ACC_STATIC | AccessFlags.ACC_FINAL); rField = new FieldNode(typeCls, rFieldInfo, AccessFlags.ACC_PUBLIC | AccessFlags.ACC_STATIC | AccessFlags.ACC_FINAL);
rField.addAttr(FieldInitAttr.constValue(resource.getId())); rField.addAttr(FieldInitAttr.constValue(resource.getId()));
typeCls.getFields().add(rField); typeCls.getFields().add(rField);
...@@ -112,6 +114,42 @@ public class AndroidResourcesUtils { ...@@ -112,6 +114,42 @@ public class AndroidResourcesUtils {
rField.addAttr(AType.COMMENTS, "added by JADX"); rField.addAttr(AType.COMMENTS, "added by JADX");
} }
} }
FieldNode fieldNode = resFieldsMap.get(resource.getId());
if (fieldNode != null
&& !fieldNode.getName().equals(resName)
&& NameMapper.isValidIdentifier(resName)) {
fieldNode.getFieldInfo().setAlias(resName);
}
}
}
@NotNull
private static ClassNode addClassForResType(ClassNode resCls, boolean rClsExists, String typeName) {
ClassNode newTypeCls = new ClassNode(resCls.dex(), resCls.getFullName() + "$" + typeName,
AccessFlags.ACC_PUBLIC | AccessFlags.ACC_STATIC | AccessFlags.ACC_FINAL);
resCls.addInnerClass(newTypeCls);
if (rClsExists) {
newTypeCls.addAttr(AType.COMMENTS, "added by JADX");
}
return newTypeCls;
}
@NotNull
private static Map<Integer, FieldNode> fillResFieldsMap(ClassNode resCls) {
Map<Integer, FieldNode> resFieldsMap = new HashMap<>();
ConstStorage constStorage = resCls.root().getConstValues();
Map<Object, FieldNode> constFields = constStorage.getGlobalConstFields();
for (Map.Entry<Object, FieldNode> entry : constFields.entrySet()) {
Object key = entry.getKey();
FieldNode field = entry.getValue();
AccessInfo accessFlags = field.getAccessFlags();
if (field.getType().equals(ArgType.INT)
&& accessFlags.isStatic()
&& accessFlags.isFinal()
&& key instanceof Integer) {
resFieldsMap.put((Integer) key, field);
}
} }
return resFieldsMap;
} }
} }
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