Commit a5035278 authored by Skylot's avatar Skylot

core: use resources ids in manifest decoding

parent ff093aee
...@@ -281,7 +281,7 @@ public class ClassNode extends LineAttrNode implements ILoadable { ...@@ -281,7 +281,7 @@ public class ClassNode extends LineAttrNode implements ILoadable {
if (field == null && obj instanceof Integer) { if (field == null && obj instanceof Integer) {
String str = dex.root().getResourcesNames().get(obj); String str = dex.root().getResourcesNames().get(obj);
if (str != null) { if (str != null) {
return new ResRefField(dex, str); return new ResRefField(dex, str.replace('/', '.'));
} }
} }
return field; return field;
......
...@@ -12,7 +12,6 @@ import jadx.core.utils.exceptions.JadxException; ...@@ -12,7 +12,6 @@ import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.files.InputFile; import jadx.core.utils.files.InputFile;
import jadx.core.xmlgen.ResTableParser; import jadx.core.xmlgen.ResTableParser;
import jadx.core.xmlgen.ResourceStorage; import jadx.core.xmlgen.ResourceStorage;
import jadx.core.xmlgen.entry.ResourceEntry;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
...@@ -32,6 +31,10 @@ public class RootNode { ...@@ -32,6 +31,10 @@ public class RootNode {
private final ErrorsCounter errorsCounter = new ErrorsCounter(); private final ErrorsCounter errorsCounter = new ErrorsCounter();
private List<DexNode> dexNodes; private List<DexNode> dexNodes;
/**
* Resources *
*/
private Map<Integer, String> resourcesNames = new HashMap<Integer, String>(); private Map<Integer, String> resourcesNames = new HashMap<Integer, String>();
@Nullable @Nullable
private String appPackage; private String appPackage;
...@@ -95,10 +98,7 @@ public class RootNode { ...@@ -95,10 +98,7 @@ public class RootNode {
} }
ResourceStorage resStorage = parser.getResStorage(); ResourceStorage resStorage = parser.getResStorage();
appPackage = resStorage.getAppPackage(); resourcesNames = resStorage.getResourcesNames();
for (ResourceEntry entry : resStorage.getResources()) {
resourcesNames.put(entry.getId(), entry.getTypeName() + "." + entry.getKeyName());
}
} }
public void initAppResClass() { public void initAppResClass() {
......
...@@ -7,6 +7,7 @@ import jadx.core.dex.nodes.FieldNode; ...@@ -7,6 +7,7 @@ import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.RootNode; import jadx.core.dex.nodes.RootNode;
import jadx.core.utils.Utils; import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.core.xmlgen.entry.ValuesParser;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
...@@ -42,8 +43,10 @@ public class BinaryXMLParser extends CommonBinaryParser { ...@@ -42,8 +43,10 @@ public class BinaryXMLParser extends CommonBinaryParser {
private boolean firstElement; private boolean firstElement;
private boolean wasOneLiner = false; private boolean wasOneLiner = false;
private Map<Integer, String> styleMap = new HashMap<Integer, String>(); private final Map<Integer, String> styleMap = new HashMap<Integer, String>();
private Map<Integer, FieldNode> localStyleMap = new HashMap<Integer, FieldNode>(); private final Map<Integer, FieldNode> localStyleMap = new HashMap<Integer, FieldNode>();
private final Map<Integer, String> resNames;
private ValuesParser valuesParser;
private final ManifestAttributes attributes; private final ManifestAttributes attributes;
...@@ -62,6 +65,9 @@ public class BinaryXMLParser extends CommonBinaryParser { ...@@ -62,6 +65,9 @@ public class BinaryXMLParser extends CommonBinaryParser {
} }
} }
} }
resNames = root.getResourcesNames();
attributes = new ManifestAttributes(); attributes = new ManifestAttributes();
attributes.parse(); attributes.parse();
} catch (Exception e) { } catch (Exception e) {
...@@ -103,6 +109,7 @@ public class BinaryXMLParser extends CommonBinaryParser { ...@@ -103,6 +109,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
break; break;
case RES_STRING_POOL_TYPE: case RES_STRING_POOL_TYPE:
strings = parseStringPoolNoType(); strings = parseStringPoolNoType();
valuesParser = new ValuesParser(strings, resNames);
break; break;
case RES_XML_RESOURCE_MAP_TYPE: case RES_XML_RESOURCE_MAP_TYPE:
parseResourceMap(); parseResourceMap();
...@@ -121,7 +128,7 @@ public class BinaryXMLParser extends CommonBinaryParser { ...@@ -121,7 +128,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
break; break;
default: default:
die("Type: " + Integer.toHexString(type) + " not yet implemented"); die("Type: 0x" + Integer.toHexString(type) + " not yet implemented");
break; break;
} }
} }
...@@ -244,48 +251,32 @@ public class BinaryXMLParser extends CommonBinaryParser { ...@@ -244,48 +251,32 @@ public class BinaryXMLParser extends CommonBinaryParser {
} }
private void decodeAttribute(int attributeNS, int attrValDataType, int attrValData) { private void decodeAttribute(int attributeNS, int attrValDataType, int attrValData) {
switch (attrValDataType) { if (attrValDataType == TYPE_REFERENCE) {
case 0x3: // reference custom processing
writer.add(strings[attrValData]); String name = styleMap.get(attrValData);
break; if (name != null) {
writer.add("@*");
case 0x10: if (attributeNS != -1) {
writer.add(String.valueOf(attrValData)); writer.add(nsPrefix).add(':');
break;
case 0x12:
// FIXME: What to do, when data is always -1?
if (attrValData == 0) {
writer.add("false");
} else if (attrValData == 1 || attrValData == -1) {
writer.add("true");
} else {
writer.add("UNKNOWN_BOOLEAN_TYPE");
} }
break; writer.add("style/").add(name.replaceAll("_", "."));
} else {
case 0x1: FieldNode field = localStyleMap.get(attrValData);
String name = styleMap.get(attrValData); if (field != null) {
if (name != null) { String cls = field.getParentClass().getShortName().toLowerCase();
writer.add("@*"); writer.add("@").add(cls).add("/").add(field.getName());
if (attributeNS != -1) {
writer.add(nsPrefix).add(':');
}
writer.add("style/").add(name.replaceAll("_", "."));
} else { } else {
FieldNode field = localStyleMap.get(attrValData); String resName = resNames.get(attrValData);
if (field != null) { if (resName != null) {
String cls = field.getParentClass().getShortName().toLowerCase(); writer.add("@").add(resName);
writer.add("@").add(cls).add("/").add(field.getName());
} else { } else {
writer.add("0x").add(Integer.toHexString(attrValData)); writer.add("0x").add(Integer.toHexString(attrValData));
} }
} }
break; }
} else {
default: String str = valuesParser.decodeValue(attrValDataType, attrValData);
writer.add("UNKNOWN_DATA_TYPE_0x" + Integer.toHexString(attrValDataType)); writer.add(str);
break;
} }
} }
......
...@@ -71,7 +71,10 @@ public class ResTableParser extends CommonBinaryParser { ...@@ -71,7 +71,10 @@ public class ResTableParser extends CommonBinaryParser {
} }
CodeWriter writer = new CodeWriter(); CodeWriter writer = new CodeWriter();
ValuesParser vp = new ValuesParser(strings, resStorage); writer.add("app package: ").add(resStorage.getAppPackage());
writer.startLine();
ValuesParser vp = new ValuesParser(strings, resStorage.getResourcesNames());
for (ResourceEntry ri : resStorage.getResources()) { for (ResourceEntry ri : resStorage.getResources()) {
writer.startLine(ri + ": " + vp.getValueString(ri)); writer.startLine(ri + ": " + vp.getValueString(ri));
} }
......
...@@ -7,7 +7,9 @@ import java.util.ArrayList; ...@@ -7,7 +7,9 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
public class ResourceStorage { public class ResourceStorage {
...@@ -49,4 +51,12 @@ public class ResourceStorage { ...@@ -49,4 +51,12 @@ public class ResourceStorage {
public void setAppPackage(String appPackage) { public void setAppPackage(String appPackage) {
this.appPackage = appPackage; this.appPackage = appPackage;
} }
public Map<Integer, String> getResourcesNames() {
Map<Integer, String> map = new HashMap<Integer, String>();
for (ResourceEntry entry : list) {
map.put(entry.getId(), entry.getTypeName() + "/" + entry.getKeyName());
}
return map;
}
} }
...@@ -73,14 +73,6 @@ public final class ResourceEntry { ...@@ -73,14 +73,6 @@ public final class ResourceEntry {
return config; return config;
} }
public String formatAsRef() {
return "@" + typeName + "/" + keyName;
}
public String formatAsAttribute() {
return "?" + typeName + "/" + keyName;
}
@Override @Override
public String toString() { public String toString() {
return " 0x" + Integer.toHexString(id) + " (" + id + ")" + config + " = " + typeName + "." + keyName; return " 0x" + Integer.toHexString(id) + " (" + id + ")" + config + " = " + typeName + "." + keyName;
......
package jadx.core.xmlgen.entry; package jadx.core.xmlgen.entry;
import jadx.core.xmlgen.ParserConstants; import jadx.core.xmlgen.ParserConstants;
import jadx.core.xmlgen.ResourceStorage;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -14,11 +14,11 @@ public class ValuesParser extends ParserConstants { ...@@ -14,11 +14,11 @@ public class ValuesParser extends ParserConstants {
private static final Logger LOG = LoggerFactory.getLogger(ValuesParser.class); private static final Logger LOG = LoggerFactory.getLogger(ValuesParser.class);
private final String[] strings; private final String[] strings;
private final ResourceStorage resStorage; private final Map<Integer, String> resMap;
public ValuesParser(String[] strings, ResourceStorage resourceStorage) { public ValuesParser(String[] strings, Map<Integer, String> resMap) {
this.strings = strings; this.strings = strings;
this.resStorage = resourceStorage; this.resMap = resMap;
} }
public String getValueString(ResourceEntry ri) { public String getValueString(ResourceEntry ri) {
...@@ -43,6 +43,10 @@ public class ValuesParser extends ParserConstants { ...@@ -43,6 +43,10 @@ public class ValuesParser extends ParserConstants {
public String decodeValue(RawValue value) { public String decodeValue(RawValue value) {
int dataType = value.getDataType(); int dataType = value.getDataType();
int data = value.getData(); int data = value.getData();
return decodeValue(dataType, data);
}
public String decodeValue(int dataType, int data) {
switch (dataType) { switch (dataType) {
case TYPE_NULL: case TYPE_NULL:
return null; return null;
...@@ -67,19 +71,19 @@ public class ValuesParser extends ParserConstants { ...@@ -67,19 +71,19 @@ public class ValuesParser extends ParserConstants {
return String.format("#%03x", data & 0xFFF); return String.format("#%03x", data & 0xFFF);
case TYPE_REFERENCE: { case TYPE_REFERENCE: {
ResourceEntry ri = resStorage.getByRef(data); String ri = resMap.get(data);
if (ri == null) { if (ri == null) {
return "?unknown_ref: " + Integer.toHexString(data); return "?unknown_ref: " + Integer.toHexString(data);
} }
return ri.formatAsRef(); return "@" + ri;
} }
case TYPE_ATTRIBUTE: { case TYPE_ATTRIBUTE: {
ResourceEntry ri = resStorage.getByRef(data); String ri = resMap.get(data);
if (ri == null) { if (ri == null) {
return "?unknown_ref: " + Integer.toHexString(data); return "?unknown_attr_ref: " + Integer.toHexString(data);
} }
return ri.formatAsAttribute(); return "?" + ri;
} }
case TYPE_DIMENSION: case TYPE_DIMENSION:
...@@ -101,9 +105,9 @@ public class ValuesParser extends ParserConstants { ...@@ -101,9 +105,9 @@ public class ValuesParser extends ParserConstants {
return null; return null;
} }
} }
ResourceEntry ri = resStorage.getByRef(ref); String ri = resMap.get(ref);
if (ri != null) { if (ri != null) {
return ri.getTypeName() + "." + ri.getKeyName(); return ri.replace('/', '.');
} }
return "?0x" + Integer.toHexString(nameRef); return "?0x" + Integer.toHexString(nameRef);
} }
......
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