feat: input plugin for java bytecode

This commit is contained in:
Skylot
2021-08-01 17:50:39 +01:00
parent 2d9bcdb87a
commit 1efdcd7b10
242 changed files with 5988 additions and 1174 deletions
@@ -2,7 +2,11 @@ package jadx.plugins.input.dex.insns;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.*;
import jadx.api.plugins.input.data.ICallSite;
import jadx.api.plugins.input.data.IFieldRef;
import jadx.api.plugins.input.data.IMethodHandle;
import jadx.api.plugins.input.data.IMethodProto;
import jadx.api.plugins.input.data.IMethodRef;
import jadx.api.plugins.input.insns.InsnData;
import jadx.api.plugins.input.insns.InsnIndexType;
import jadx.api.plugins.input.insns.Opcode;
@@ -82,6 +86,11 @@ public class DexInsnData implements InsnData {
return argsReg[argNum];
}
@Override
public int getResultReg() {
return -1;
}
@Override
public long getLiteral() {
return literal;
@@ -113,8 +122,8 @@ public class DexInsnData implements InsnData {
}
@Override
public IFieldData getIndexAsField() {
return externalReader.getFieldData(index);
public IFieldRef getIndexAsField() {
return externalReader.getFieldRef(index);
}
@Override
@@ -1,8 +1,8 @@
package jadx.plugins.input.dex.insns;
import jadx.api.plugins.input.insns.custom.impl.SwitchPayload;
import jadx.plugins.input.dex.DexException;
import jadx.plugins.input.dex.insns.payloads.DexArrayPayload;
import jadx.plugins.input.dex.insns.payloads.DexSwitchPayload;
import jadx.plugins.input.dex.sections.SectionReader;
public abstract class DexInsnFormat {
@@ -158,6 +158,7 @@ public abstract class DexInsnFormat {
regs[0] = nibble2(opcodeUnit);
regs[1] = nibble3(opcodeUnit);
insn.setIndex(in.readUShort());
insn.setLiteral(0L);
}
};
@@ -262,7 +263,7 @@ public abstract class DexInsnFormat {
targets[i] = in.readInt();
keys[i] = firstKey + i;
}
insn.setPayload(new DexSwitchPayload(size, keys, targets));
insn.setPayload(new SwitchPayload(size, keys, targets));
insn.setLength(size * 2 + 4);
}
@@ -286,7 +287,7 @@ public abstract class DexInsnFormat {
for (int i = 0; i < size; i++) {
targets[i] = in.readInt();
}
insn.setPayload(new DexSwitchPayload(size, keys, targets));
insn.setPayload(new SwitchPayload(size, keys, targets));
insn.setLength(size * 4 + 2);
}
@@ -282,8 +282,8 @@ public class DexInsnInfo {
register(arr, DexOpcodes.INVOKE_POLYMORPHIC, Opcode.INVOKE_POLYMORPHIC, DexInsnFormat.FORMAT_45CC);
register(arr, DexOpcodes.INVOKE_POLYMORPHIC_RANGE, Opcode.INVOKE_POLYMORPHIC_RANGE, DexInsnFormat.FORMAT_4RCC);
register(arr, DexOpcodes.INVOKE_CUSTOM, Opcode.INVOKE_CUSTOM, DexInsnFormat.FORMAT_35C);
register(arr, DexOpcodes.INVOKE_CUSTOM_RANGE, Opcode.INVOKE_CUSTOM_RANGE, DexInsnFormat.FORMAT_3RC);
register(arr, DexOpcodes.INVOKE_CUSTOM, Opcode.INVOKE_CUSTOM, DexInsnFormat.FORMAT_35C, InsnIndexType.CALL_SITE);
register(arr, DexOpcodes.INVOKE_CUSTOM_RANGE, Opcode.INVOKE_CUSTOM_RANGE, DexInsnFormat.FORMAT_3RC, InsnIndexType.CALL_SITE);
register(arr, DexOpcodes.CONST_METHOD_HANDLE, Opcode.CONST_METHOD_HANDLE, DexInsnFormat.FORMAT_21C);
register(arr, DexOpcodes.CONST_METHOD_TYPE, Opcode.CONST_METHOD_TYPE, DexInsnFormat.FORMAT_21C);
@@ -1,31 +0,0 @@
package jadx.plugins.input.dex.insns.payloads;
import jadx.api.plugins.input.insns.custom.ISwitchPayload;
public class DexSwitchPayload implements ISwitchPayload {
private final int size;
private final int[] keys;
private final int[] targets;
public DexSwitchPayload(int size, int[] keys, int[] targets) {
this.size = size;
this.keys = keys;
this.targets = targets;
}
@Override
public int getSize() {
return size;
}
@Override
public int[] getKeys() {
return keys;
}
@Override
public int[] getTargets() {
return targets;
}
}
@@ -0,0 +1,103 @@
package jadx.plugins.input.dex.sections;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.plugins.input.data.annotations.AnnotationVisibility;
import jadx.api.plugins.input.data.annotations.EncodedType;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.data.annotations.IAnnotation;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
import jadx.api.plugins.input.data.attributes.types.AnnotationDefaultClassAttr;
import jadx.api.plugins.input.data.attributes.types.AnnotationsAttr;
import jadx.api.plugins.input.data.attributes.types.ExceptionsAttr;
import jadx.api.plugins.input.data.attributes.types.InnerClassesAttr;
import jadx.api.plugins.input.data.attributes.types.InnerClsInfo;
import jadx.api.plugins.input.data.attributes.types.SignatureAttr;
import jadx.api.plugins.utils.Utils;
public class DexAnnotationsConvert {
private static final Logger LOG = LoggerFactory.getLogger(DexAnnotationsConvert.class);
public static void forClass(String cls, List<IJadxAttribute> list, List<IAnnotation> annotationList) {
appendAnnotations(cls, list, annotationList);
}
public static void forMethod(List<IJadxAttribute> list, List<IAnnotation> annotationList) {
appendAnnotations(null, list, annotationList);
}
public static void forField(List<IJadxAttribute> list, List<IAnnotation> annotationList) {
appendAnnotations(null, list, annotationList);
}
private static void appendAnnotations(String cls, List<IJadxAttribute> attributes, List<IAnnotation> annotations) {
if (annotations.isEmpty()) {
return;
}
for (IAnnotation annotation : annotations) {
if (annotation.getVisibility() == AnnotationVisibility.SYSTEM) {
convertSystemAnnotations(cls, attributes, annotation);
}
}
Utils.addToList(attributes, AnnotationsAttr.pack(annotations));
}
@SuppressWarnings("unchecked")
private static void convertSystemAnnotations(String cls, List<IJadxAttribute> attributes, IAnnotation annotation) {
switch (annotation.getAnnotationClass()) {
case "Ldalvik/annotation/Signature;":
attributes.add(new SignatureAttr(extractSignature(annotation)));
break;
case "Ldalvik/annotation/InnerClass;":
Map<String, EncodedValue> values = annotation.getValues();
String name = (String) values.get("name").getValue();
int accFlags = (Integer) values.get("accessFlags").getValue();
Map<String, InnerClsInfo> map = Collections.singletonMap(cls, new InnerClsInfo(cls, null, name, accFlags));
attributes.add(new InnerClassesAttr(map));
break;
case "Ldalvik/annotation/AnnotationDefault;":
EncodedValue annValue = annotation.getDefaultValue();
if (annValue != null && annValue.getType() == EncodedType.ENCODED_ANNOTATION) {
IAnnotation defAnnotation = (IAnnotation) annValue.getValue();
attributes.add(new AnnotationDefaultClassAttr(defAnnotation.getValues()));
}
break;
case "Ldalvik/annotation/Throws;":
try {
EncodedValue defaultValue = annotation.getDefaultValue();
if (defaultValue != null) {
List<String> excs = ((List<EncodedValue>) defaultValue.getValue())
.stream()
.map(ev -> ((String) ev.getValue()))
.collect(Collectors.toList());
attributes.add(new ExceptionsAttr(excs));
}
} catch (Exception e) {
LOG.warn("Failed to convert dalvik throws annotation", e);
}
break;
}
}
@SuppressWarnings({ "unchecked", "ConstantConditions" })
private static String extractSignature(IAnnotation annotation) {
List<EncodedValue> values = (List<EncodedValue>) annotation.getDefaultValue().getValue();
if (values.size() == 1) {
return (String) values.get(0).getValue();
}
StringBuilder sb = new StringBuilder();
for (EncodedValue part : values) {
sb.append((String) part.getValue());
}
return sb.toString();
}
}
@@ -1,39 +0,0 @@
package jadx.plugins.input.dex.sections;
import java.util.List;
import jadx.api.plugins.input.data.ICallSite;
import jadx.api.plugins.input.data.IMethodHandle;
import jadx.api.plugins.input.data.IMethodRef;
import jadx.api.plugins.input.data.annotations.EncodedValue;
public class DexCallSite implements ICallSite {
private final List<EncodedValue> values;
public DexCallSite(List<EncodedValue> values) {
this.values = values;
}
@Override
public List<EncodedValue> getValues() {
return values;
}
@Override
public void load() {
for (EncodedValue value : values) {
Object obj = value.getValue();
if (obj instanceof IMethodRef) {
((IMethodRef) obj).load();
} else if (obj instanceof IMethodHandle) {
((IMethodHandle) obj).load();
}
}
}
@Override
public String toString() {
return "CallSite{" + values + '}';
}
}
@@ -1,21 +1,27 @@
package jadx.plugins.input.dex.sections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.plugins.input.data.IClassData;
import jadx.api.plugins.input.data.IFieldData;
import jadx.api.plugins.input.data.IMethodData;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.data.annotations.IAnnotation;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
import jadx.api.plugins.input.data.attributes.types.SourceFileAttr;
import jadx.plugins.input.dex.sections.annotations.AnnotationsParser;
import jadx.plugins.input.dex.utils.SmaliUtils;
public class DexClassData implements IClassData {
private static final Logger LOG = LoggerFactory.getLogger(DexClassData.class);
public static final int SIZE = 8 * 4;
private final SectionReader in;
@@ -63,8 +69,7 @@ public class DexClassData implements IClassData {
}
@Nullable
@Override
public String getSourceFile() {
private String getSourceFile() {
int strIdx = in.pos(4 * 4).readInt();
return in.getString(strIdx);
}
@@ -107,12 +112,13 @@ public class DexClassData implements IClassData {
Map<Integer, Integer> annotationOffsetMap = annotationsParser.readFieldsAnnotationOffsetMap();
DexFieldData fieldData = new DexFieldData(annotationsParser);
fieldData.setParentClassType(getType());
readFields(fieldConsumer, data, fieldData, staticFieldsCount, annotationOffsetMap);
readFields(fieldConsumer, data, fieldData, instanceFieldsCount, annotationOffsetMap);
readFields(fieldConsumer, data, fieldData, staticFieldsCount, annotationOffsetMap, true);
readFields(fieldConsumer, data, fieldData, instanceFieldsCount, annotationOffsetMap, false);
}
private void readFields(Consumer<IFieldData> fieldConsumer, SectionReader data, DexFieldData fieldData, int count,
Map<Integer, Integer> annOffsetMap) {
Map<Integer, Integer> annOffsetMap, boolean staticFields) {
List<EncodedValue> constValues = staticFields ? getStaticFieldInitValues(data.copy()) : null;
int fieldId = 0;
for (int i = 0; i < count; i++) {
fieldId += data.readUleb128();
@@ -120,6 +126,7 @@ public class DexClassData implements IClassData {
in.fillFieldData(fieldData, fieldId);
fieldData.setAccessFlags(accFlags);
fieldData.setAnnotationsOffset(getOffsetFromMap(fieldId, annOffsetMap));
fieldData.setConstValue(staticFields && i < constValues.size() ? constValues.get(i) : null);
fieldConsumer.accept(fieldData);
}
}
@@ -130,9 +137,7 @@ public class DexClassData implements IClassData {
Map<Integer, Integer> annotationOffsetMap = annotationsParser.readMethodsAnnotationOffsetMap();
Map<Integer, Integer> paramsAnnOffsetMap = annotationsParser.readMethodParamsAnnRefOffsetMap();
methodData.setDirect(true);
readMethods(mthConsumer, data, methodData, directMthCount, annotationOffsetMap, paramsAnnOffsetMap);
methodData.setDirect(false);
readMethods(mthConsumer, data, methodData, virtualMthCount, annotationOffsetMap, paramsAnnOffsetMap);
}
@@ -167,20 +172,29 @@ public class DexClassData implements IClassData {
return offset != null ? offset : 0;
}
@Override
public List<EncodedValue> getStaticFieldInitValues() {
private List<EncodedValue> getStaticFieldInitValues(SectionReader reader) {
int staticValuesOff = getStaticValuesOff();
if (staticValuesOff == 0) {
return Collections.emptyList();
}
in.absPos(staticValuesOff);
return annotationsParser.parseEncodedArray(in);
reader.absPos(staticValuesOff);
return annotationsParser.parseEncodedArray(reader);
}
private List<IAnnotation> getAnnotations() {
annotationsParser.setOffset(getAnnotationsOff());
return annotationsParser.readClassAnnotations();
}
@Override
public List<IAnnotation> getAnnotations() {
annotationsParser.setOffset(getAnnotationsOff());
return annotationsParser.readClassAnnotations();
public List<IJadxAttribute> getAttributes() {
List<IJadxAttribute> list = new ArrayList<>();
String sourceFile = getSourceFile();
if (sourceFile != null && !sourceFile.isEmpty()) {
list.add(new SourceFileAttr(sourceFile));
}
DexAnnotationsConvert.forClass(getType(), list, getAnnotations());
return list;
}
public int getClassDefOffset() {
@@ -13,14 +13,14 @@ import jadx.api.plugins.input.data.ICatch;
import jadx.api.plugins.input.data.ICodeReader;
import jadx.api.plugins.input.data.IDebugInfo;
import jadx.api.plugins.input.data.ITry;
import jadx.api.plugins.input.data.impl.CatchData;
import jadx.api.plugins.input.data.impl.TryData;
import jadx.api.plugins.input.insns.InsnData;
import jadx.plugins.input.dex.DexException;
import jadx.plugins.input.dex.insns.DexInsnData;
import jadx.plugins.input.dex.insns.DexInsnFormat;
import jadx.plugins.input.dex.insns.DexInsnInfo;
import jadx.plugins.input.dex.sections.debuginfo.DebugInfoParser;
import jadx.plugins.input.dex.sections.trycatch.DexCatch;
import jadx.plugins.input.dex.sections.trycatch.DexTryData;
public class DexCodeReader implements ICodeReader {
@@ -48,7 +48,12 @@ public class DexCodeReader implements ICodeReader {
}
@Override
public int getInsnsCount() {
public int getArgsStartReg() {
return -1;
}
@Override
public int getUnitsCount() {
return in.pos(12).readInt();
}
@@ -108,7 +113,7 @@ public class DexCodeReader implements ICodeReader {
return null;
}
int regsCount = getRegistersCount();
DebugInfoParser debugInfoParser = new DebugInfoParser(in, regsCount, getInsnsCount());
DebugInfoParser debugInfoParser = new DebugInfoParser(in, regsCount, getUnitsCount());
debugInfoParser.initMthArgs(regsCount, in.getMethodParamTypes(mthId));
return debugInfoParser.process(debugOff);
}
@@ -122,7 +127,7 @@ public class DexCodeReader implements ICodeReader {
if (triesCount == 0) {
return -1;
}
int insnsCount = getInsnsCount();
int insnsCount = getUnitsCount();
int padding = insnsCount % 2 == 1 ? 2 : 0;
return 4 * 4 + insnsCount * 2 + padding;
}
@@ -145,7 +150,7 @@ public class DexCodeReader implements ICodeReader {
if (catchHandler == null) {
throw new DexException("Catch handler not found by byte offset: " + handlerOff);
}
triesList.add(new DexTryData(catchHandler, startAddr, insnsCount));
triesList.add(new TryData(startAddr, startAddr + insnsCount - 1, catchHandler));
}
return triesList;
}
@@ -171,7 +176,7 @@ public class DexCodeReader implements ICodeReader {
} else {
catchAllAddr = -1;
}
map.put(byteIndex, new DexCatch(addr, types, catchAllAddr));
map.put(byteIndex, new CatchData(addr, types, catchAllAddr));
}
return map;
}
@@ -1,11 +1,15 @@
package jadx.plugins.input.dex.sections;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.IFieldData;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.data.annotations.IAnnotation;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
import jadx.api.plugins.utils.Utils;
import jadx.plugins.input.dex.sections.annotations.AnnotationsParser;
public class DexFieldData implements IFieldData {
@@ -17,6 +21,7 @@ public class DexFieldData implements IFieldData {
private String name;
private int accessFlags;
private int annotationsOffset;
private EncodedValue constValue;
public DexFieldData(@Nullable AnnotationsParser parser) {
this.annotationsParser = parser;
@@ -62,14 +67,25 @@ public class DexFieldData implements IFieldData {
this.annotationsOffset = annotationsOffset;
}
@Override
public List<IAnnotation> getAnnotations() {
public void setConstValue(EncodedValue constValue) {
this.constValue = constValue;
}
private List<IAnnotation> getAnnotations() {
if (annotationsParser == null) {
throw new NullPointerException("Annotation parser not initialized");
}
return annotationsParser.readAnnotationList(annotationsOffset);
}
@Override
public List<IJadxAttribute> getAttributes() {
List<IJadxAttribute> list = new ArrayList<>(2);
Utils.addToList(list, constValue);
DexAnnotationsConvert.forField(list, getAnnotations());
return list;
}
@Override
public String toString() {
return getParentClassType() + "->" + getName() + ":" + getType();
@@ -1,5 +1,6 @@
package jadx.plugins.input.dex.sections;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.annotations.Nullable;
@@ -7,6 +8,9 @@ import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.ICodeReader;
import jadx.api.plugins.input.data.IMethodData;
import jadx.api.plugins.input.data.annotations.IAnnotation;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
import jadx.api.plugins.input.data.attributes.types.MethodParamsAttr;
import jadx.api.plugins.utils.Utils;
import jadx.plugins.input.dex.sections.annotations.AnnotationsParser;
import jadx.plugins.input.dex.smali.SmaliPrinter;
@@ -17,7 +21,6 @@ public class DexMethodData implements IMethodData {
private DexMethodRef methodRef;
private int accessFlags;
private boolean isDirect;
private int annotationsOffset;
private int paramAnnotationsOffset;
@@ -46,15 +49,6 @@ public class DexMethodData implements IMethodData {
this.accessFlags = accessFlags;
}
@Override
public boolean isDirect() {
return isDirect;
}
public void setDirect(boolean direct) {
isDirect = direct;
}
@Nullable
@Override
public ICodeReader getCodeReader() {
@@ -78,16 +72,22 @@ public class DexMethodData implements IMethodData {
this.paramAnnotationsOffset = paramAnnotationsOffset;
}
@Override
public List<IAnnotation> getAnnotations() {
private List<IAnnotation> getAnnotations() {
return getAnnotationsParser().readAnnotationList(annotationsOffset);
}
@Override
public List<List<IAnnotation>> getParamsAnnotations() {
private List<List<IAnnotation>> getParamsAnnotations() {
return getAnnotationsParser().readAnnotationRefList(paramAnnotationsOffset);
}
@Override
public List<IJadxAttribute> getAttributes() {
List<IJadxAttribute> list = new ArrayList<>();
DexAnnotationsConvert.forMethod(list, getAnnotations());
Utils.addToList(list, MethodParamsAttr.pack(getParamsAnnotations()));
return list;
}
private AnnotationsParser getAnnotationsParser() {
if (annotationsParser == null) {
throw new NullPointerException("Annotation parser not initialized");
@@ -3,7 +3,7 @@ package jadx.plugins.input.dex.sections;
import java.util.List;
import jadx.api.plugins.input.data.IMethodProto;
import jadx.plugins.input.dex.utils.Utils;
import jadx.api.plugins.utils.Utils;
public class DexMethodProto implements IMethodProto {
private final List<String> argTypes;
@@ -3,8 +3,8 @@ package jadx.plugins.input.dex.sections;
import java.util.List;
import jadx.api.plugins.input.data.IMethodRef;
import jadx.api.plugins.utils.Utils;
import jadx.plugins.input.dex.DexReader;
import jadx.plugins.input.dex.utils.Utils;
public class DexMethodRef implements IMethodRef {
@@ -10,9 +10,10 @@ import java.util.List;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.ICallSite;
import jadx.api.plugins.input.data.IFieldData;
import jadx.api.plugins.input.data.IFieldRef;
import jadx.api.plugins.input.data.IMethodHandle;
import jadx.api.plugins.input.data.MethodHandleType;
import jadx.api.plugins.input.data.impl.CallSite;
import jadx.api.plugins.input.data.impl.FieldRefHandle;
import jadx.api.plugins.input.data.impl.MethodRefHandle;
import jadx.plugins.input.dex.DexReader;
@@ -177,7 +178,7 @@ public class SectionReader {
return MUtf8.decode(this);
}
public IFieldData getFieldData(int idx) {
public IFieldRef getFieldRef(int idx) {
DexFieldData fieldData = new DexFieldData(null);
int clsTypeIdx = fillFieldData(fieldData, idx);
fieldData.setParentClassType(getType(clsTypeIdx));
@@ -205,7 +206,7 @@ public class SectionReader {
int callSiteOff = dexReader.getHeader().getCallSiteOff();
absPos(callSiteOff + idx * 4);
absPos(readInt());
return new DexCallSite(EncodedValueParser.parseEncodedArray(this, ext));
return new CallSite(EncodedValueParser.parseEncodedArray(this, ext));
}
public IMethodHandle getMethodHandle(int idx) {
@@ -215,7 +216,7 @@ public class SectionReader {
skip(2);
int refId = readUShort();
if (handleType.isField()) {
return new FieldRefHandle(handleType, getFieldData(refId));
return new FieldRefHandle(handleType, getFieldRef(refId));
}
return new MethodRefHandle(handleType, getMethodRef(refId));
}
@@ -10,6 +10,7 @@ import java.util.Map;
import jadx.api.plugins.input.data.annotations.AnnotationVisibility;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.data.annotations.IAnnotation;
import jadx.api.plugins.input.data.annotations.JadxAnnotation;
import jadx.plugins.input.dex.DexException;
import jadx.plugins.input.dex.sections.SectionReader;
@@ -149,7 +150,7 @@ public class AnnotationsParser {
values.put(name, EncodedValueParser.parseValue(in, ext));
}
String type = ext.getType(typeIndex);
return new DexAnnotation(visibility, type, values);
return new JadxAnnotation(visibility, type, values);
}
private static AnnotationVisibility getVisibilityValue(int value) {
@@ -1,39 +0,0 @@
package jadx.plugins.input.dex.sections.annotations;
import java.util.Map;
import jadx.api.plugins.input.data.annotations.AnnotationVisibility;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.data.annotations.IAnnotation;
public class DexAnnotation implements IAnnotation {
private final AnnotationVisibility visibility;
private final String type;
private final Map<String, EncodedValue> values;
public DexAnnotation(AnnotationVisibility visibility, String type, Map<String, EncodedValue> values) {
this.visibility = visibility;
this.type = type;
this.values = values;
}
@Override
public String getAnnotationClass() {
return type;
}
@Override
public AnnotationVisibility getVisibility() {
return visibility;
}
@Override
public Map<String, EncodedValue> getValues() {
return values;
}
@Override
public String toString() {
return "DexAnnotation{" + visibility + ", type=" + type + ", values=" + values + '}';
}
}
@@ -66,7 +66,7 @@ public class EncodedValueParser {
case ENCODED_FIELD:
case ENCODED_ENUM:
return new EncodedValue(EncodedType.ENCODED_FIELD, ext.getFieldData(parseUnsignedInt(in, size)));
return new EncodedValue(EncodedType.ENCODED_FIELD, ext.getFieldRef(parseUnsignedInt(in, size)));
case ENCODED_ARRAY:
return new EncodedValue(EncodedType.ENCODED_ARRAY, parseEncodedArray(in, ext));
@@ -1,33 +0,0 @@
package jadx.plugins.input.dex.sections.debuginfo;
import java.util.List;
import java.util.Map;
import jadx.api.plugins.input.data.IDebugInfo;
import jadx.api.plugins.input.data.ILocalVar;
public class DebugInfo implements IDebugInfo {
private final Map<Integer, Integer> sourceLineMap;
private final List<ILocalVar> localVars;
public DebugInfo(Map<Integer, Integer> sourceLineMap, List<ILocalVar> localVars) {
this.sourceLineMap = sourceLineMap;
this.localVars = localVars;
}
@Override
public Map<Integer, Integer> getSourceLineMapping() {
return sourceLineMap;
}
@Override
public List<ILocalVar> getLocalVars() {
return localVars;
}
@Override
public String toString() {
return "DebugInfo{sourceLineMap=" + sourceLineMap + ", localVars=" + localVars + '}';
}
}
@@ -9,6 +9,7 @@ import java.util.Map;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.ILocalVar;
import jadx.api.plugins.input.data.impl.DebugInfo;
import jadx.plugins.input.dex.sections.DexConsts;
import jadx.plugins.input.dex.sections.SectionReader;
@@ -34,7 +35,7 @@ public class DebugInfoParser {
private final SectionReader in;
private final SectionReader ext;
private final LocalVar[] locals;
private final DexLocalVar[] locals;
private final int codeSize;
private List<ILocalVar> resultList;
@@ -48,7 +49,7 @@ public class DebugInfoParser {
public DebugInfoParser(SectionReader in, int regsCount, int codeSize) {
this.in = in;
this.ext = in.copy();
this.locals = new LocalVar[regsCount];
this.locals = new DexLocalVar[regsCount];
this.codeSize = codeSize;
}
@@ -96,7 +97,7 @@ public class DebugInfoParser {
String name = ext.getString(nameId);
if (name != null && i < argsCount) {
int regNum = argRegs[i];
startVar(new LocalVar(regNum, name, argTypes.get(i)), -1);
startVar(new DexLocalVar(regNum, name, argTypes.get(i)), -1);
varsInfoFound = true;
}
}
@@ -123,7 +124,7 @@ public class DebugInfoParser {
int regNum = in.readUleb128();
int nameId = in.readUleb128() - 1;
int type = in.readUleb128() - 1;
LocalVar var = new LocalVar(ext, regNum, nameId, type, DexConsts.NO_INDEX);
DexLocalVar var = new DexLocalVar(ext, regNum, nameId, type, DexConsts.NO_INDEX);
startVar(var, addr);
varsInfoFound = true;
break;
@@ -133,7 +134,7 @@ public class DebugInfoParser {
int nameId = in.readUleb128p1();
int type = in.readUleb128p1();
int sign = in.readUleb128p1();
LocalVar var = new LocalVar(ext, regNum, nameId, type, sign);
DexLocalVar var = new DexLocalVar(ext, regNum, nameId, type, sign);
startVar(var, addr);
varsInfoFound = true;
break;
@@ -146,7 +147,7 @@ public class DebugInfoParser {
}
case DBG_END_LOCAL: {
int regNum = in.readUleb128();
LocalVar var = locals[regNum];
DexLocalVar var = locals[regNum];
if (var != null) {
endVar(var, addr);
}
@@ -178,7 +179,7 @@ public class DebugInfoParser {
}
if (varsInfoFound) {
for (LocalVar var : locals) {
for (DexLocalVar var : locals) {
if (var != null && !var.isEnd()) {
endVar(var, codeSize - 1);
}
@@ -208,17 +209,17 @@ public class DebugInfoParser {
}
private void restartVar(int regNum, int addr) {
LocalVar prev = locals[regNum];
DexLocalVar prev = locals[regNum];
if (prev != null) {
endVar(prev, addr);
LocalVar newVar = new LocalVar(regNum, prev.getName(), prev.getType(), prev.getSignature());
DexLocalVar newVar = new DexLocalVar(regNum, prev.getName(), prev.getType(), prev.getSignature());
startVar(newVar, addr);
}
}
private void startVar(LocalVar newVar, int addr) {
private void startVar(DexLocalVar newVar, int addr) {
int regNum = newVar.getRegNum();
LocalVar prev = locals[regNum];
DexLocalVar prev = locals[regNum];
if (prev != null) {
endVar(prev, addr);
}
@@ -226,7 +227,7 @@ public class DebugInfoParser {
locals[regNum] = newVar;
}
private void endVar(LocalVar var, int addr) {
private void endVar(DexLocalVar var, int addr) {
if (var.end(addr)) {
resultList.add(var);
}
@@ -3,10 +3,10 @@ package jadx.plugins.input.dex.sections.debuginfo;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.ILocalVar;
import jadx.api.plugins.utils.Utils;
import jadx.plugins.input.dex.sections.SectionReader;
import jadx.plugins.input.dex.utils.Utils;
public class LocalVar implements ILocalVar {
public class DexLocalVar implements ILocalVar {
private final int regNum;
private final String name;
private final String type;
@@ -17,15 +17,15 @@ public class LocalVar implements ILocalVar {
private int startOffset;
private int endOffset;
public LocalVar(SectionReader dex, int regNum, int nameId, int typeId, int signId) {
public DexLocalVar(SectionReader dex, int regNum, int nameId, int typeId, int signId) {
this(regNum, dex.getString(nameId), dex.getType(typeId), dex.getString(signId));
}
public LocalVar(int regNum, String name, String type) {
public DexLocalVar(int regNum, String name, String type) {
this(regNum, name, type, null);
}
public LocalVar(int regNum, String name, String type, @Nullable String sign) {
public DexLocalVar(int regNum, String name, String type, @Nullable String sign) {
this.regNum = regNum;
this.name = name;
this.type = type;
@@ -99,7 +99,7 @@ public class LocalVar implements ILocalVar {
@Override
public String toString() {
return Utils.formatOffset(startOffset)
return (startOffset == -1 ? "-1 " : Utils.formatOffset(startOffset))
+ '-' + (isEnd ? Utils.formatOffset(endOffset) : " ")
+ ": r" + regNum + " '" + name + "' " + type
+ (sign != null ? ", signature: " + sign : "");
@@ -1,30 +0,0 @@
package jadx.plugins.input.dex.sections.trycatch;
import jadx.api.plugins.input.data.ICatch;
public class DexCatch implements ICatch {
private final int[] addr;
private final String[] types;
private final int allAddr;
public DexCatch(int[] addr, String[] types, int allAddr) {
this.addr = addr;
this.types = types;
this.allAddr = allAddr;
}
@Override
public int[] getAddresses() {
return addr;
}
@Override
public String[] getTypes() {
return types;
}
@Override
public int getCatchAllAddress() {
return allAddr;
}
}
@@ -1,32 +0,0 @@
package jadx.plugins.input.dex.sections.trycatch;
import jadx.api.plugins.input.data.ICatch;
import jadx.api.plugins.input.data.ITry;
public class DexTryData implements ITry {
private final ICatch catchHandler;
private final int startAddr;
private final int insnsCount;
public DexTryData(ICatch catchHandler, int startAddr, int insnsCount) {
this.catchHandler = catchHandler;
this.startAddr = startAddr;
this.insnsCount = insnsCount;
}
@Override
public ICatch getCatch() {
return catchHandler;
}
@Override
public int getStartAddress() {
return startAddr;
}
@Override
public int getInstructionCount() {
return insnsCount;
}
}
@@ -1,8 +1,7 @@
package jadx.plugins.input.dex.smali;
import java.util.*;
import jadx.api.plugins.input.data.*;
import jadx.api.plugins.input.data.AccessFlags;
import jadx.api.plugins.input.data.ICodeReader;
import jadx.plugins.input.dex.sections.DexMethodData;
import jadx.plugins.input.dex.sections.DexMethodRef;
@@ -1,29 +0,0 @@
package jadx.plugins.input.dex.utils;
import java.util.Iterator;
import java.util.List;
public class Utils {
public static <T> String listToStr(List<T> collection) {
if (collection == null) {
return "null";
}
if (collection.isEmpty()) {
return "";
}
StringBuilder sb = new StringBuilder();
Iterator<T> it = collection.iterator();
if (it.hasNext()) {
sb.append(it.next());
}
while (it.hasNext()) {
sb.append(", ").append(it.next());
}
return sb.toString();
}
public static String formatOffset(int offset) {
return String.format("0x%04x", offset);
}
}
@@ -46,7 +46,7 @@ class DexInputPluginTest {
System.out.println("AccessFlags: " + AccessFlags.format(cls.getAccessFlags(), AccessFlagsScope.CLASS));
System.out.println("SuperType: " + cls.getSuperType());
System.out.println("Interfaces: " + cls.getInterfacesTypes());
System.out.println("SourceFile: " + cls.getSourceFile());
System.out.println("Attributes: " + cls.getAttributes());
count.getAndIncrement();
cls.visitFieldsAndMethods(