refactor: extract input-api into library (#1821)

This commit is contained in:
Skylot
2023-04-15 15:40:50 +01:00
parent 2e652b4219
commit 9417671606
60 changed files with 25 additions and 6 deletions
@@ -0,0 +1,13 @@
package jadx.api.plugins.input;
import java.io.Closeable;
import java.util.function.Consumer;
import jadx.api.plugins.input.data.IClassData;
public interface ICodeLoader extends Closeable {
void visitClasses(Consumer<IClassData> consumer);
boolean isEmpty();
}
@@ -0,0 +1,8 @@
package jadx.api.plugins.input;
import java.nio.file.Path;
import java.util.List;
public interface JadxCodeInput {
ICodeLoader loadFiles(List<Path> input);
}
@@ -0,0 +1,95 @@
package jadx.api.plugins.input.data;
public class AccessFlags {
public static final int PUBLIC = 0x1;
public static final int PRIVATE = 0x2;
public static final int PROTECTED = 0x4;
public static final int STATIC = 0x8;
public static final int FINAL = 0x10;
public static final int SYNCHRONIZED = 0x20;
public static final int SUPER = 0x20;
public static final int VOLATILE = 0x40;
public static final int BRIDGE = 0x40;
public static final int TRANSIENT = 0x80;
public static final int VARARGS = 0x80;
public static final int NATIVE = 0x100;
public static final int INTERFACE = 0x200;
public static final int ABSTRACT = 0x400;
public static final int STRICT = 0x800;
public static final int SYNTHETIC = 0x1000;
public static final int ANNOTATION = 0x2000;
public static final int ENUM = 0x4000;
public static final int MODULE = 0x8000;
public static final int CONSTRUCTOR = 0x10000;
public static final int DECLARED_SYNCHRONIZED = 0x20000;
public static boolean hasFlag(int flags, int flagValue) {
return (flags & flagValue) != 0;
}
public static String format(int flags, AccessFlagsScope scope) {
StringBuilder code = new StringBuilder();
if (hasFlag(flags, PUBLIC)) {
code.append("public ");
}
if (hasFlag(flags, PRIVATE)) {
code.append("private ");
}
if (hasFlag(flags, PROTECTED)) {
code.append("protected ");
}
if (hasFlag(flags, STATIC)) {
code.append("static ");
}
if (hasFlag(flags, FINAL)) {
code.append("final ");
}
if (hasFlag(flags, ABSTRACT)) {
code.append("abstract ");
}
if (hasFlag(flags, NATIVE)) {
code.append("native ");
}
switch (scope) {
case METHOD:
if (hasFlag(flags, SYNCHRONIZED)) {
code.append("synchronized ");
}
if (hasFlag(flags, BRIDGE)) {
code.append("bridge ");
}
if (hasFlag(flags, VARARGS)) {
code.append("varargs ");
}
break;
case FIELD:
if (hasFlag(flags, VOLATILE)) {
code.append("volatile ");
}
if (hasFlag(flags, TRANSIENT)) {
code.append("transient ");
}
break;
case CLASS:
if (hasFlag(flags, MODULE)) {
code.append("module ");
}
if (hasFlag(flags, STRICT)) {
code.append("strict ");
}
if (hasFlag(flags, SUPER)) {
code.append("super ");
}
if (hasFlag(flags, ENUM)) {
code.append("enum ");
}
break;
}
if (hasFlag(flags, SYNTHETIC)) {
code.append("synthetic ");
}
return code.toString();
}
}
@@ -0,0 +1,5 @@
package jadx.api.plugins.input.data;
public enum AccessFlagsScope {
CLASS, FIELD, METHOD
}
@@ -0,0 +1,13 @@
package jadx.api.plugins.input.data;
import java.util.List;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.insns.custom.ICustomPayload;
public interface ICallSite extends ICustomPayload {
List<EncodedValue> getValues();
void load();
}
@@ -0,0 +1,9 @@
package jadx.api.plugins.input.data;
public interface ICatch {
String[] getTypes();
int[] getHandlers();
int getCatchAllHandler();
}
@@ -0,0 +1,28 @@
package jadx.api.plugins.input.data;
import java.util.List;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
public interface IClassData {
IClassData copy();
String getInputFileName();
String getType();
int getAccessFlags();
@Nullable
String getSuperType();
List<String> getInterfacesTypes();
void visitFieldsAndMethods(ISeqConsumer<IFieldData> fieldsConsumer, ISeqConsumer<IMethodData> mthConsumer);
List<IJadxAttribute> getAttributes();
String getDisassembledCode();
}
@@ -0,0 +1,27 @@
package jadx.api.plugins.input.data;
import java.util.List;
import java.util.function.Consumer;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.insns.InsnData;
public interface ICodeReader {
ICodeReader copy();
void visitInstructions(Consumer<InsnData> insnConsumer);
int getRegistersCount();
int getArgsStartReg();
int getUnitsCount();
@Nullable
IDebugInfo getDebugInfo();
int getCodeOffset();
List<ITry> getTries();
}
@@ -0,0 +1,14 @@
package jadx.api.plugins.input.data;
import java.util.List;
import java.util.Map;
public interface IDebugInfo {
/**
* Map instruction offset to source line number
*/
Map<Integer, Integer> getSourceLineMapping();
List<ILocalVar> getLocalVars();
}
@@ -0,0 +1,12 @@
package jadx.api.plugins.input.data;
import java.util.List;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
public interface IFieldData extends IFieldRef {
int getAccessFlags();
List<IJadxAttribute> getAttributes();
}
@@ -0,0 +1,9 @@
package jadx.api.plugins.input.data;
public interface IFieldRef {
String getParentClassType();
String getName();
String getType();
}
@@ -0,0 +1,24 @@
package jadx.api.plugins.input.data;
import org.jetbrains.annotations.Nullable;
public interface ILocalVar {
String getName();
int getRegNum();
String getType();
@Nullable
String getSignature();
int getStartOffset();
int getEndOffset();
/**
* Hint if variable is a method parameter.
* Can be incorrect and shouldn't be trusted.
*/
boolean isMarkedAsParameter();
}
@@ -0,0 +1,21 @@
package jadx.api.plugins.input.data;
import java.util.List;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
public interface IMethodData {
IMethodRef getMethodRef();
int getAccessFlags();
@Nullable
ICodeReader getCodeReader();
String disassembleMethod();
List<IJadxAttribute> getAttributes();
}
@@ -0,0 +1,12 @@
package jadx.api.plugins.input.data;
public interface IMethodHandle {
MethodHandleType getType();
IFieldRef getFieldRef();
IMethodRef getMethodRef();
void load();
}
@@ -0,0 +1,10 @@
package jadx.api.plugins.input.data;
import java.util.List;
public interface IMethodProto {
String getReturnType();
List<String> getArgTypes();
}
@@ -0,0 +1,22 @@
package jadx.api.plugins.input.data;
import jadx.api.plugins.input.insns.custom.ICustomPayload;
public interface IMethodRef extends IMethodProto, ICustomPayload {
/**
* Method unique id (will be used for caching).
*
* @return 0 if can't calculate good unique identifier (disable caching)
*/
int getUniqId();
/**
* Lazy loading for method info, until load() is called only getUniqId() can be used
*/
void load();
String getParentClassType();
String getName();
}
@@ -0,0 +1,4 @@
package jadx.api.plugins.input.data;
public interface IResourceData {
}
@@ -0,0 +1,13 @@
package jadx.api.plugins.input.data;
import java.util.function.Consumer;
/**
* "Sequence consumer" allows getting count of elements available
*/
public interface ISeqConsumer<T> extends Consumer<T> {
default void init(int count) {
// no-op implementation
}
}
@@ -0,0 +1,9 @@
package jadx.api.plugins.input.data;
public interface ITry {
ICatch getCatch();
int getStartOffset();
int getEndOffset();
}
@@ -0,0 +1,26 @@
package jadx.api.plugins.input.data;
public enum MethodHandleType {
STATIC_PUT,
STATIC_GET,
INSTANCE_PUT,
INSTANCE_GET,
INVOKE_STATIC,
INVOKE_INSTANCE,
INVOKE_DIRECT,
INVOKE_CONSTRUCTOR,
INVOKE_INTERFACE;
public boolean isField() {
switch (this) {
case STATIC_PUT:
case STATIC_GET:
case INSTANCE_PUT:
case INSTANCE_GET:
return true;
default:
return false;
}
}
}
@@ -0,0 +1,7 @@
package jadx.api.plugins.input.data.annotations;
public enum AnnotationVisibility {
BUILD,
RUNTIME,
SYSTEM
}
@@ -0,0 +1,22 @@
package jadx.api.plugins.input.data.annotations;
public enum EncodedType {
ENCODED_NULL,
ENCODED_BOOLEAN,
ENCODED_BYTE,
ENCODED_SHORT,
ENCODED_CHAR,
ENCODED_INT,
ENCODED_LONG,
ENCODED_FLOAT,
ENCODED_DOUBLE,
ENCODED_STRING,
ENCODED_TYPE,
ENCODED_ENUM,
ENCODED_FIELD,
ENCODED_METHOD,
ENCODED_METHOD_TYPE,
ENCODED_METHOD_HANDLE,
ENCODED_ARRAY,
ENCODED_ANNOTATION
}
@@ -0,0 +1,64 @@
package jadx.api.plugins.input.data.annotations;
import java.util.Objects;
import jadx.api.plugins.input.data.attributes.IJadxAttrType;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.PinnedAttribute;
public class EncodedValue extends PinnedAttribute {
public static final EncodedValue NULL = new EncodedValue(EncodedType.ENCODED_NULL, null);
private final EncodedType type;
private final Object value;
public EncodedValue(EncodedType type, Object value) {
this.type = type;
this.value = value;
}
public EncodedType getType() {
return type;
}
public Object getValue() {
return value;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EncodedValue that = (EncodedValue) o;
return type == that.getType() && Objects.equals(value, that.getValue());
}
@Override
public IJadxAttrType<? extends IJadxAttribute> getAttrType() {
return JadxAttrType.CONSTANT_VALUE;
}
@Override
public int hashCode() {
return Objects.hash(getType(), getValue());
}
@Override
public String toString() {
switch (type) {
case ENCODED_NULL:
return "null";
case ENCODED_ARRAY:
return "[" + value + "]";
case ENCODED_STRING:
return "{STRING: \"" + value + "\"}";
default:
return "{" + type.toString().substring(8) + ": " + value + '}';
}
}
}
@@ -0,0 +1,18 @@
package jadx.api.plugins.input.data.annotations;
import java.util.Map;
import org.jetbrains.annotations.Nullable;
public interface IAnnotation {
String getAnnotationClass();
AnnotationVisibility getVisibility();
Map<String, EncodedValue> getValues();
@Nullable
default EncodedValue getDefaultValue() {
return getValues().get("value");
}
}
@@ -0,0 +1,35 @@
package jadx.api.plugins.input.data.annotations;
import java.util.Map;
public class JadxAnnotation implements IAnnotation {
private final AnnotationVisibility visibility;
private final String type;
private final Map<String, EncodedValue> values;
public JadxAnnotation(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 "Annotation{" + visibility + ", type=" + type + ", values=" + values + '}';
}
}
@@ -0,0 +1,21 @@
package jadx.api.plugins.input.data.attributes;
/**
* Marker interface for attribute type.
* Similar to enumeration but extensible.
* <p>
* Used for attach attribute instance class information (T).
* T - class of attribute instance
* <p>
* To create new one define static field like this:
* {@code
* static final IJadxAttrType<AttrTypeClass> ATTR_TYPE = IJadxAttrType.create();
* }
*/
public interface IJadxAttrType<T extends IJadxAttribute> {
static <A extends IJadxAttribute> IJadxAttrType<A> create() {
return new IJadxAttrType<>() {
};
}
}
@@ -0,0 +1,17 @@
package jadx.api.plugins.input.data.attributes;
public interface IJadxAttribute {
IJadxAttrType<? extends IJadxAttribute> getAttrType();
/**
* Mark type to skip unloading on node unload
*/
default boolean keepLoaded() {
return false;
}
default String toAttrString() {
return this.toString();
}
}
@@ -0,0 +1,40 @@
package jadx.api.plugins.input.data.attributes;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.data.attributes.types.AnnotationDefaultAttr;
import jadx.api.plugins.input.data.attributes.types.AnnotationDefaultClassAttr;
import jadx.api.plugins.input.data.attributes.types.AnnotationMethodParamsAttr;
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.MethodParametersAttr;
import jadx.api.plugins.input.data.attributes.types.SignatureAttr;
import jadx.api.plugins.input.data.attributes.types.SourceFileAttr;
public final class JadxAttrType<T extends IJadxAttribute> implements IJadxAttrType<T> {
// class, method, field
public static final JadxAttrType<AnnotationsAttr> ANNOTATION_LIST = bind();
public static final JadxAttrType<SignatureAttr> SIGNATURE = bind();
// class
public static final JadxAttrType<SourceFileAttr> SOURCE_FILE = bind();
public static final JadxAttrType<InnerClassesAttr> INNER_CLASSES = bind();
public static final JadxAttrType<AnnotationDefaultClassAttr> ANNOTATION_DEFAULT_CLASS = bind(); // dex specific
// field
public static final JadxAttrType<EncodedValue> CONSTANT_VALUE = bind();
// method
public static final JadxAttrType<AnnotationMethodParamsAttr> ANNOTATION_MTH_PARAMETERS = bind();
public static final JadxAttrType<AnnotationDefaultAttr> ANNOTATION_DEFAULT = bind();
public static final JadxAttrType<ExceptionsAttr> EXCEPTIONS = bind();
public static final JadxAttrType<MethodParametersAttr> METHOD_PARAMETERS = bind();
private static <T extends IJadxAttribute> JadxAttrType<T> bind() {
return new JadxAttrType<>();
}
private JadxAttrType() {
}
}
@@ -0,0 +1,9 @@
package jadx.api.plugins.input.data.attributes;
public abstract class PinnedAttribute implements IJadxAttribute {
@Override
public final boolean keepLoaded() {
return true;
}
}
@@ -0,0 +1,30 @@
package jadx.api.plugins.input.data.attributes.types;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.data.attributes.IJadxAttrType;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.PinnedAttribute;
public class AnnotationDefaultAttr extends PinnedAttribute {
private final EncodedValue value;
public AnnotationDefaultAttr(EncodedValue value) {
this.value = value;
}
public EncodedValue getValue() {
return value;
}
@Override
public IJadxAttrType<? extends IJadxAttribute> getAttrType() {
return JadxAttrType.ANNOTATION_DEFAULT;
}
@Override
public String toString() {
return "ANNOTATION_DEFAULT: " + value;
}
}
@@ -0,0 +1,32 @@
package jadx.api.plugins.input.data.attributes.types;
import java.util.Map;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.data.attributes.IJadxAttrType;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.PinnedAttribute;
public class AnnotationDefaultClassAttr extends PinnedAttribute {
private final Map<String, EncodedValue> values;
public AnnotationDefaultClassAttr(Map<String, EncodedValue> values) {
this.values = values;
}
public Map<String, EncodedValue> getValues() {
return values;
}
@Override
public IJadxAttrType<? extends IJadxAttribute> getAttrType() {
return JadxAttrType.ANNOTATION_DEFAULT_CLASS;
}
@Override
public String toString() {
return "ANNOTATION_DEFAULT_CLASS: " + values;
}
}
@@ -0,0 +1,45 @@
package jadx.api.plugins.input.data.attributes.types;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.annotations.IAnnotation;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.PinnedAttribute;
public class AnnotationMethodParamsAttr extends PinnedAttribute {
@Nullable
public static AnnotationMethodParamsAttr pack(List<List<IAnnotation>> annotationRefList) {
if (annotationRefList.isEmpty()) {
return null;
}
List<AnnotationsAttr> list = new ArrayList<>(annotationRefList.size());
for (List<IAnnotation> annList : annotationRefList) {
list.add(AnnotationsAttr.pack(annList));
}
return new AnnotationMethodParamsAttr(list);
}
private final List<AnnotationsAttr> paramList;
private AnnotationMethodParamsAttr(List<AnnotationsAttr> paramsList) {
this.paramList = paramsList;
}
public List<AnnotationsAttr> getParamList() {
return paramList;
}
@Override
public JadxAttrType<AnnotationMethodParamsAttr> getAttrType() {
return JadxAttrType.ANNOTATION_MTH_PARAMETERS;
}
@Override
public String toString() {
return paramList.toString();
}
}
@@ -0,0 +1,71 @@
package jadx.api.plugins.input.data.attributes.types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.annotations.AnnotationVisibility;
import jadx.api.plugins.input.data.annotations.IAnnotation;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.PinnedAttribute;
public class AnnotationsAttr extends PinnedAttribute {
@Nullable
public static AnnotationsAttr pack(List<IAnnotation> annotationList) {
if (annotationList.isEmpty()) {
return null;
}
Map<String, IAnnotation> annMap = new HashMap<>(annotationList.size());
for (IAnnotation ann : annotationList) {
if (ann.getVisibility() != AnnotationVisibility.SYSTEM) {
annMap.put(ann.getAnnotationClass(), ann);
}
}
if (annMap.isEmpty()) {
return null;
}
return new AnnotationsAttr(annMap);
}
private final Map<String, IAnnotation> map;
public AnnotationsAttr(Map<String, IAnnotation> map) {
this.map = map;
}
public IAnnotation get(String className) {
return map.get(className);
}
public Collection<IAnnotation> getAll() {
return map.values();
}
public List<IAnnotation> getList() {
return map.isEmpty() ? Collections.emptyList() : new ArrayList<>(map.values());
}
public int size() {
return map.size();
}
public boolean isEmpty() {
return map.isEmpty();
}
@Override
public JadxAttrType<AnnotationsAttr> getAttrType() {
return JadxAttrType.ANNOTATION_LIST;
}
@Override
public String toString() {
return map.toString();
}
}
@@ -0,0 +1,29 @@
package jadx.api.plugins.input.data.attributes.types;
import java.util.List;
import jadx.api.plugins.input.data.attributes.IJadxAttrType;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.PinnedAttribute;
public class ExceptionsAttr extends PinnedAttribute {
private final List<String> list;
public ExceptionsAttr(List<String> list) {
this.list = list;
}
public List<String> getList() {
return list;
}
@Override
public IJadxAttrType<ExceptionsAttr> getAttrType() {
return JadxAttrType.EXCEPTIONS;
}
@Override
public String toString() {
return "EXCEPTIONS:" + list;
}
}
@@ -0,0 +1,30 @@
package jadx.api.plugins.input.data.attributes.types;
import java.util.Map;
import jadx.api.plugins.input.data.attributes.IJadxAttrType;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.PinnedAttribute;
public class InnerClassesAttr extends PinnedAttribute {
private final Map<String, InnerClsInfo> map;
public InnerClassesAttr(Map<String, InnerClsInfo> map) {
this.map = map;
}
public Map<String, InnerClsInfo> getMap() {
return map;
}
@Override
public IJadxAttrType<InnerClassesAttr> getAttrType() {
return JadxAttrType.INNER_CLASSES;
}
@Override
public String toString() {
return "INNER_CLASSES:" + map;
}
}
@@ -0,0 +1,45 @@
package jadx.api.plugins.input.data.attributes.types;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.AccessFlags;
import jadx.api.plugins.input.data.AccessFlagsScope;
public class InnerClsInfo {
private final String innerCls;
private final @Nullable String outerCls;
private final @Nullable String name;
private final int accessFlags;
public InnerClsInfo(String innerCls, @Nullable String outerCls, @Nullable String name, int accessFlags) {
this.innerCls = innerCls;
this.outerCls = outerCls;
this.name = name;
this.accessFlags = accessFlags;
}
public String getInnerCls() {
return innerCls;
}
public @Nullable String getOuterCls() {
return outerCls;
}
public @Nullable String getName() {
return name;
}
public int getAccessFlags() {
return accessFlags;
}
@Override
public String toString() {
return "InnerCls{" + innerCls
+ ", outerCls=" + outerCls
+ ", name=" + name
+ ", accessFlags=" + AccessFlags.format(accessFlags, AccessFlagsScope.CLASS)
+ '}';
}
}
@@ -0,0 +1,54 @@
package jadx.api.plugins.input.data.attributes.types;
import java.util.List;
import jadx.api.plugins.input.data.AccessFlags;
import jadx.api.plugins.input.data.AccessFlagsScope;
import jadx.api.plugins.input.data.attributes.IJadxAttrType;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.PinnedAttribute;
public class MethodParametersAttr extends PinnedAttribute {
public static class Info {
private final int accFlags;
private final String name;
public Info(int accFlags, String name) {
this.accFlags = accFlags;
this.name = name;
}
public int getAccFlags() {
return accFlags;
}
public String getName() {
return name;
}
public String toString() {
return AccessFlags.format(accFlags, AccessFlagsScope.METHOD) + name;
}
}
private final List<Info> list;
public MethodParametersAttr(List<Info> list) {
this.list = list;
}
public List<Info> getList() {
return list;
}
@Override
public IJadxAttrType<MethodParametersAttr> getAttrType() {
return JadxAttrType.METHOD_PARAMETERS;
}
@Override
public String toString() {
return "METHOD_PARAMETERS: " + list;
}
}
@@ -0,0 +1,29 @@
package jadx.api.plugins.input.data.attributes.types;
import jadx.api.plugins.input.data.attributes.IJadxAttrType;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.PinnedAttribute;
public class SignatureAttr extends PinnedAttribute {
private final String signature;
public SignatureAttr(String signature) {
this.signature = signature;
}
public String getSignature() {
return signature;
}
@Override
public IJadxAttrType<? extends IJadxAttribute> getAttrType() {
return JadxAttrType.SIGNATURE;
}
@Override
public String toString() {
return "SIGNATURE: " + signature;
}
}
@@ -0,0 +1,28 @@
package jadx.api.plugins.input.data.attributes.types;
import jadx.api.plugins.input.data.attributes.IJadxAttrType;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.PinnedAttribute;
public class SourceFileAttr extends PinnedAttribute {
private final String fileName;
public SourceFileAttr(String fileName) {
this.fileName = fileName;
}
public String getFileName() {
return fileName;
}
@Override
public IJadxAttrType<SourceFileAttr> getAttrType() {
return JadxAttrType.SOURCE_FILE;
}
@Override
public String toString() {
return "SOURCE:" + fileName;
}
}
@@ -0,0 +1,41 @@
package jadx.api.plugins.input.data.impl;
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 CallSite implements ICallSite {
private final List<EncodedValue> values;
public CallSite(List<EncodedValue> values) {
this.values = values;
}
@Override
public void load() {
for (EncodedValue value : values) {
switch (value.getType()) {
case ENCODED_METHOD_HANDLE:
((IMethodHandle) value.getValue()).load();
break;
case ENCODED_METHOD:
((IMethodRef) value.getValue()).load();
break;
}
}
}
@Override
public List<EncodedValue> getValues() {
return values;
}
@Override
public String toString() {
return "CallSite{" + values + '}';
}
}
@@ -0,0 +1,45 @@
package jadx.api.plugins.input.data.impl;
import jadx.api.plugins.input.data.ICatch;
import static jadx.api.plugins.input.data.impl.InputUtils.formatOffset;
public class CatchData implements ICatch {
private final int[] handlers;
private final String[] types;
private final int allHandler;
public CatchData(int[] handlers, String[] types, int allHandler) {
this.handlers = handlers;
this.types = types;
this.allHandler = allHandler;
}
@Override
public int[] getHandlers() {
return handlers;
}
@Override
public String[] getTypes() {
return types;
}
@Override
public int getCatchAllHandler() {
return allHandler;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Catch:");
int size = types.length;
for (int i = 0; i < size; i++) {
sb.append(' ').append(types[i]).append("->").append(formatOffset(handlers[i]));
}
if (allHandler != -1) {
sb.append(" all->").append(formatOffset(allHandler));
}
return sb.toString();
}
}
@@ -0,0 +1,33 @@
package jadx.api.plugins.input.data.impl;
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{lines=" + sourceLineMap + ", localVars=" + localVars + '}';
}
}
@@ -0,0 +1,25 @@
package jadx.api.plugins.input.data.impl;
import java.io.IOException;
import java.util.function.Consumer;
import jadx.api.plugins.input.ICodeLoader;
import jadx.api.plugins.input.data.IClassData;
public class EmptyCodeLoader implements ICodeLoader {
public static final EmptyCodeLoader INSTANCE = new EmptyCodeLoader();
@Override
public boolean isEmpty() {
return true;
}
@Override
public void visitClasses(Consumer<IClassData> consumer) {
}
@Override
public void close() throws IOException {
}
}
@@ -0,0 +1,42 @@
package jadx.api.plugins.input.data.impl;
import jadx.api.plugins.input.data.IFieldRef;
import jadx.api.plugins.input.data.IMethodHandle;
import jadx.api.plugins.input.data.IMethodRef;
import jadx.api.plugins.input.data.MethodHandleType;
public class FieldRefHandle implements IMethodHandle {
private final IFieldRef fieldRef;
private final MethodHandleType type;
public FieldRefHandle(MethodHandleType type, IFieldRef fieldRef) {
this.fieldRef = fieldRef;
this.type = type;
}
@Override
public MethodHandleType getType() {
return type;
}
@Override
public IFieldRef getFieldRef() {
return fieldRef;
}
@Override
public IMethodRef getMethodRef() {
return null;
}
@Override
public void load() {
// already loaded
}
@Override
public String toString() {
return type + ": " + fieldRef;
}
}
@@ -0,0 +1,7 @@
package jadx.api.plugins.input.data.impl;
public class InputUtils {
public static String formatOffset(int offset) {
return String.format("0x%04x", offset);
}
}
@@ -0,0 +1,50 @@
package jadx.api.plugins.input.data.impl;
import jadx.api.plugins.input.data.IFieldRef;
public class JadxFieldRef implements IFieldRef {
private String parentClassType;
private String name;
private String type;
public JadxFieldRef() {
}
public JadxFieldRef(String parentClassType, String name, String type) {
this.parentClassType = parentClassType;
this.name = name;
this.type = type;
}
@Override
public String getParentClassType() {
return parentClassType;
}
public void setParentClassType(String parentClassType) {
this.parentClassType = parentClassType;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return parentClassType + "->" + name + ":" + type;
}
}
@@ -0,0 +1,35 @@
package jadx.api.plugins.input.data.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import jadx.api.plugins.input.data.ISeqConsumer;
public class ListConsumer<T, R> implements ISeqConsumer<T> {
private final Function<T, R> convert;
private List<R> list;
public ListConsumer(Function<T, R> convert) {
this.convert = convert;
}
@Override
public void init(int count) {
list = count == 0 ? Collections.emptyList() : new ArrayList<>(count);
}
@Override
public void accept(T t) {
list.add(convert.apply(t));
}
public List<R> getResult() {
if (list == null) {
// init not called
return Collections.emptyList();
}
return list;
}
}
@@ -0,0 +1,42 @@
package jadx.api.plugins.input.data.impl;
import jadx.api.plugins.input.data.IFieldData;
import jadx.api.plugins.input.data.IMethodHandle;
import jadx.api.plugins.input.data.IMethodRef;
import jadx.api.plugins.input.data.MethodHandleType;
public class MethodRefHandle implements IMethodHandle {
private final MethodHandleType type;
private final IMethodRef methodRef;
public MethodRefHandle(MethodHandleType type, IMethodRef methodRef) {
this.type = type;
this.methodRef = methodRef;
}
@Override
public MethodHandleType getType() {
return type;
}
@Override
public IMethodRef getMethodRef() {
return methodRef;
}
@Override
public IFieldData getFieldRef() {
return null;
}
@Override
public void load() {
methodRef.load();
}
@Override
public String toString() {
return type + ": " + methodRef;
}
}
@@ -0,0 +1,39 @@
package jadx.api.plugins.input.data.impl;
import jadx.api.plugins.input.data.ICatch;
import jadx.api.plugins.input.data.ITry;
import static jadx.api.plugins.input.data.impl.InputUtils.formatOffset;
public class TryData implements ITry {
private final int startOffset;
private final int endOffset;
private final ICatch catchHandler;
public TryData(int startOffset, int endOffset, ICatch catchHandler) {
this.startOffset = startOffset;
this.endOffset = endOffset;
this.catchHandler = catchHandler;
}
@Override
public ICatch getCatch() {
return catchHandler;
}
@Override
public int getStartOffset() {
return startOffset;
}
@Override
public int getEndOffset() {
return endOffset;
}
@Override
public String toString() {
return "Try{" + formatOffset(startOffset) + " - " + formatOffset(endOffset) + ": " + catchHandler + '}';
}
}
@@ -0,0 +1,60 @@
package jadx.api.plugins.input.insns;
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.custom.ICustomPayload;
public interface InsnData {
void decode();
int getOffset(); // offset within method
int getFileOffset(); // offset within dex file
Opcode getOpcode();
String getOpcodeMnemonic();
byte[] getByteCode();
InsnIndexType getIndexType();
int getRawOpcodeUnit();
int getRegsCount();
int getReg(int argNum);
/**
* Workaround to set result reg without additional move-result insn
*
* @return result reg number or -1 if not needed
*/
int getResultReg();
long getLiteral();
int getTarget();
int getIndex();
String getIndexAsString();
String getIndexAsType();
IFieldRef getIndexAsField();
IMethodRef getIndexAsMethod();
ICallSite getIndexAsCallSite();
IMethodProto getIndexAsProto(int protoIndex);
IMethodHandle getIndexAsMethodHandle();
ICustomPayload getPayload();
}
@@ -0,0 +1,10 @@
package jadx.api.plugins.input.insns;
public enum InsnIndexType {
NONE,
TYPE_REF,
STRING_REF,
FIELD_REF,
METHOD_REF,
CALL_SITE
}
@@ -0,0 +1,192 @@
package jadx.api.plugins.input.insns;
public enum Opcode {
UNKNOWN,
NOP,
ADD_DOUBLE,
ADD_FLOAT,
ADD_INT,
ADD_INT_LIT,
ADD_LONG,
AND_INT,
AND_INT_LIT,
AND_LONG,
AGET,
AGET_BOOLEAN,
AGET_BYTE,
AGET_BYTE_BOOLEAN,
AGET_CHAR,
AGET_OBJECT,
AGET_SHORT,
AGET_WIDE,
APUT,
APUT_BOOLEAN,
APUT_BYTE,
APUT_BYTE_BOOLEAN,
APUT_CHAR,
APUT_OBJECT,
APUT_SHORT,
APUT_WIDE,
ARITH,
ARRAY_LENGTH,
CAST,
CHECK_CAST,
CMPG_DOUBLE,
CMPG_FLOAT,
CMPL_DOUBLE,
CMPL_FLOAT,
CMP_LONG,
CONST,
CONST_CLASS,
CONST_STRING,
CONST_WIDE,
DIV_DOUBLE,
DIV_FLOAT,
DIV_INT,
DIV_INT_LIT,
DIV_LONG,
DOUBLE_TO_FLOAT,
DOUBLE_TO_INT,
DOUBLE_TO_LONG,
FLOAT_TO_DOUBLE,
FLOAT_TO_INT,
FLOAT_TO_LONG,
GOTO,
IF,
IF_EQ,
IF_EQZ,
IF_GE,
IF_GEZ,
IF_GT,
IF_GTZ,
IF_LE,
IF_LEZ,
IF_LT,
IF_LTZ,
IF_NE,
IF_NEZ,
INSTANCE_OF,
INT_TO_BYTE,
INT_TO_CHAR,
INT_TO_DOUBLE,
INT_TO_FLOAT,
INT_TO_LONG,
INT_TO_SHORT,
INVOKE_DIRECT,
INVOKE_DIRECT_RANGE,
INVOKE_INTERFACE,
INVOKE_INTERFACE_RANGE,
INVOKE_STATIC,
INVOKE_STATIC_RANGE,
INVOKE_SUPER,
INVOKE_SUPER_RANGE,
INVOKE_VIRTUAL,
INVOKE_VIRTUAL_RANGE,
INVOKE_SPECIAL,
IGET,
IPUT,
SGET,
SPUT,
LONG_TO_DOUBLE,
LONG_TO_FLOAT,
LONG_TO_INT,
MONITOR_ENTER,
MONITOR_EXIT,
MOVE,
MOVE_MULTI,
MOVE_EXCEPTION,
MOVE_OBJECT,
MOVE_RESULT,
MOVE_WIDE,
MUL_DOUBLE,
MUL_FLOAT,
MUL_INT,
MUL_INT_LIT,
MUL_LONG,
NEG,
NEG_DOUBLE,
NEG_FLOAT,
NEG_INT,
NEG_LONG,
NEW_INSTANCE,
NOT_INT,
NOT_LONG,
OR_INT,
OR_INT_LIT,
OR_LONG,
REM_DOUBLE,
REM_FLOAT,
REM_INT,
REM_INT_LIT,
REM_LONG,
RETURN,
RETURN_VOID,
RSUB_INT,
SHL_INT,
SHL_INT_LIT,
SHL_LONG,
SHR_INT,
SHR_INT_LIT,
SHR_LONG,
SUB_DOUBLE,
SUB_FLOAT,
SUB_INT,
SUB_LONG,
THROW,
USHR_INT,
USHR_INT_LIT,
USHR_LONG,
XOR_INT,
XOR_INT_LIT,
XOR_LONG,
NEW_ARRAY,
FILLED_NEW_ARRAY,
FILLED_NEW_ARRAY_RANGE,
FILL_ARRAY_DATA,
FILL_ARRAY_DATA_PAYLOAD,
PACKED_SWITCH,
PACKED_SWITCH_PAYLOAD,
SPARSE_SWITCH,
SPARSE_SWITCH_PAYLOAD,
INVOKE_POLYMORPHIC,
INVOKE_POLYMORPHIC_RANGE,
INVOKE_CUSTOM,
INVOKE_CUSTOM_RANGE,
CONST_METHOD_HANDLE,
CONST_METHOD_TYPE,
}
@@ -0,0 +1,9 @@
package jadx.api.plugins.input.insns.custom;
public interface IArrayPayload extends ICustomPayload {
int getSize();
int getElementSize();
Object getData();
}
@@ -0,0 +1,4 @@
package jadx.api.plugins.input.insns.custom;
public interface ICustomPayload {
}
@@ -0,0 +1,9 @@
package jadx.api.plugins.input.insns.custom;
public interface ISwitchPayload extends ICustomPayload {
int getSize();
int[] getKeys();
int[] getTargets();
}
@@ -0,0 +1,31 @@
package jadx.api.plugins.input.insns.custom.impl;
import jadx.api.plugins.input.insns.custom.ISwitchPayload;
public class SwitchPayload implements ISwitchPayload {
private final int size;
private final int[] keys;
private final int[] targets;
public SwitchPayload(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;
}
}