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
@@ -27,10 +27,21 @@ public class JadxPluginManager {
public void register(JadxPlugin plugin) {
Objects.requireNonNull(plugin);
LOG.debug("Loaded plugin: {}", plugin.getPluginInfo().getName());
LOG.debug("Register plugin: {}", plugin.getPluginInfo().getPluginId());
allPlugins.put(plugin.getClass(), plugin);
}
public boolean unload(String pluginId) {
return allPlugins.values().removeIf(p -> {
String id = p.getPluginInfo().getPluginId();
boolean match = id.equals(pluginId);
if (match) {
LOG.debug("Unload plugin: {}", id);
}
return match;
});
}
public List<JadxPlugin> getAllPlugins() {
return new ArrayList<>(allPlugins.values());
}
@@ -19,6 +19,7 @@ public class AccessFlags {
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;
@@ -72,6 +73,9 @@ public class AccessFlags {
break;
case CLASS:
if (hasFlag(flags, MODULE)) {
code.append("module ");
}
if (hasFlag(flags, STRICT)) {
code.append("strict ");
}
@@ -3,8 +3,9 @@ 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 {
public interface ICallSite extends ICustomPayload {
List<EncodedValue> getValues();
@@ -5,12 +5,13 @@ import java.util.function.Consumer;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.data.annotations.IAnnotation;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
public interface IClassData {
IClassData copy();
String getInputFileName();
String getType();
int getAccessFlags();
@@ -20,15 +21,9 @@ public interface IClassData {
List<String> getInterfacesTypes();
String getSourceFile();
String getInputFileName();
void visitFieldsAndMethods(Consumer<IFieldData> fieldsConsumer, Consumer<IMethodData> mthConsumer);
List<EncodedValue> getStaticFieldInitValues();
List<IAnnotation> getAnnotations();
List<IJadxAttribute> getAttributes();
String getDisassembledCode();
}
@@ -14,7 +14,9 @@ public interface ICodeReader {
int getRegistersCount();
int getInsnsCount();
int getArgsStartReg();
int getUnitsCount();
@Nullable
IDebugInfo getDebugInfo();
@@ -2,16 +2,11 @@ package jadx.api.plugins.input.data;
import java.util.List;
import jadx.api.plugins.input.data.annotations.IAnnotation;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
public interface IFieldData {
String getParentClassType();
String getType();
String getName();
public interface IFieldData extends IFieldRef {
int getAccessFlags();
List<IAnnotation> getAnnotations();
List<IJadxAttribute> getAttributes();
}
@@ -0,0 +1,9 @@
package jadx.api.plugins.input.data;
public interface IFieldRef {
String getParentClassType();
String getName();
String getType();
}
@@ -4,7 +4,7 @@ import java.util.List;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.annotations.IAnnotation;
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
public interface IMethodData {
@@ -12,14 +12,10 @@ public interface IMethodData {
int getAccessFlags();
boolean isDirect();
@Nullable
ICodeReader getCodeReader();
String disassembleMethod();
List<IAnnotation> getAnnotations();
List<List<IAnnotation>> getParamsAnnotations();
List<IJadxAttribute> getAttributes();
}
@@ -4,7 +4,7 @@ public interface IMethodHandle {
MethodHandleType getType();
IFieldData getFieldRef();
IFieldRef getFieldRef();
IMethodRef getMethodRef();
@@ -1,8 +1,8 @@
package jadx.api.plugins.input.data;
import java.util.List;
import jadx.api.plugins.input.insns.custom.ICustomPayload;
public interface IMethodRef {
public interface IMethodRef extends IMethodProto, ICustomPayload {
int getUniqId();
@@ -14,8 +14,4 @@ public interface IMethodRef {
String getParentClassType();
String getName();
String getReturnType();
List<String> getArgTypes();
}
@@ -5,5 +5,5 @@ public interface ITry {
int getStartAddress();
int getInstructionCount();
int getEndAddress();
}
@@ -2,7 +2,11 @@ package jadx.api.plugins.input.data.annotations;
import java.util.Objects;
public class 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;
public class EncodedValue implements IJadxAttribute {
public static final EncodedValue NULL = new EncodedValue(EncodedType.ENCODED_NULL, null);
private final EncodedType type;
@@ -33,6 +37,11 @@ public class EncodedValue {
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());
@@ -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,9 @@
package jadx.api.plugins.input.data.attributes;
/**
* Marker interface for attribute type.
* Used for attach attribute instance class information (T).
* T - class of attribute instance
*/
public interface IJadxAttrType<T extends IJadxAttribute> {
}
@@ -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,38 @@
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.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.MethodParamsAttr;
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<MethodParamsAttr> ANNOTATION_MTH_PARAMETERS = bind();
public static final JadxAttrType<AnnotationDefaultAttr> ANNOTATION_DEFAULT = bind();
public static final JadxAttrType<ExceptionsAttr> EXCEPTIONS = 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,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,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 MethodParamsAttr extends PinnedAttribute {
@Nullable
public static MethodParamsAttr 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 MethodParamsAttr(list);
}
private final List<AnnotationsAttr> paramList;
private MethodParamsAttr(List<AnnotationsAttr> paramsList) {
this.paramList = paramsList;
}
public List<AnnotationsAttr> getParamList() {
return paramList;
}
@Override
public JadxAttrType<MethodParamsAttr> getAttrType() {
return JadxAttrType.ANNOTATION_MTH_PARAMETERS;
}
@Override
public String toString() {
return paramList.toString();
}
}
@@ -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,36 @@
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;
}
}
@@ -0,0 +1,43 @@
package jadx.api.plugins.input.data.impl;
import jadx.api.plugins.input.data.ICatch;
public class CatchData implements ICatch {
private final int[] addr;
private final String[] types;
private final int allAddr;
public CatchData(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;
}
@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(addr[i]);
}
if (allAddr != -1) {
sb.append(" all->").append(allAddr);
}
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 + '}';
}
}
@@ -1,16 +1,16 @@
package jadx.api.plugins.input.data.impl;
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.IMethodRef;
import jadx.api.plugins.input.data.MethodHandleType;
public class FieldRefHandle implements IMethodHandle {
private final IFieldData fieldRef;
private final IFieldRef fieldRef;
private final MethodHandleType type;
public FieldRefHandle(MethodHandleType type, IFieldData fieldRef) {
public FieldRefHandle(MethodHandleType type, IFieldRef fieldRef) {
this.fieldRef = fieldRef;
this.type = type;
}
@@ -21,7 +21,7 @@ public class FieldRefHandle implements IMethodHandle {
}
@Override
public IFieldData getFieldRef() {
public IFieldRef getFieldRef() {
return fieldRef;
}
@@ -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;
}
}
@@ -7,12 +7,12 @@ import jadx.api.plugins.input.data.MethodHandleType;
public class MethodRefHandle implements IMethodHandle {
private final IMethodRef methodRef;
private final MethodHandleType type;
private final IMethodRef methodRef;
public MethodRefHandle(MethodHandleType type, IMethodRef methodRef) {
this.methodRef = methodRef;
this.type = type;
this.methodRef = methodRef;
}
@Override
@@ -0,0 +1,37 @@
package jadx.api.plugins.input.data.impl;
import jadx.api.plugins.input.data.ICatch;
import jadx.api.plugins.input.data.ITry;
public class TryData implements ITry {
private final int startAddr;
private final int endAddr;
private final ICatch catchHandler;
public TryData(int startAddr, int endAddr, ICatch catchHandler) {
this.startAddr = startAddr;
this.endAddr = endAddr;
this.catchHandler = catchHandler;
}
@Override
public ICatch getCatch() {
return catchHandler;
}
@Override
public int getStartAddress() {
return startAddr;
}
@Override
public int getEndAddress() {
return endAddr;
}
@Override
public String toString() {
return "Try{" + startAddr + " - " + endAddr + ": " + catchHandler + '}';
}
}
@@ -1,8 +1,10 @@
package jadx.api.plugins.input.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.custom.ICustomPayload;
public interface InsnData {
@@ -25,6 +27,13 @@ public interface InsnData {
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();
@@ -35,7 +44,7 @@ public interface InsnData {
String getIndexAsType();
IFieldData getIndexAsField();
IFieldRef getIndexAsField();
IMethodRef getIndexAsMethod();
@@ -45,6 +54,5 @@ public interface InsnData {
IMethodHandle getIndexAsMethodHandle();
@Nullable
ICustomPayload getPayload();
}
@@ -5,5 +5,6 @@ public enum InsnIndexType {
TYPE_REF,
STRING_REF,
FIELD_REF,
METHOD_REF
METHOD_REF,
CALL_SITE
}
@@ -17,6 +17,7 @@ public enum Opcode {
AGET,
AGET_BOOLEAN,
AGET_BYTE,
AGET_BYTE_BOOLEAN,
AGET_CHAR,
AGET_OBJECT,
AGET_SHORT,
@@ -25,6 +26,7 @@ public enum Opcode {
APUT,
APUT_BOOLEAN,
APUT_BYTE,
APUT_BYTE_BOOLEAN,
APUT_CHAR,
APUT_OBJECT,
APUT_SHORT,
@@ -40,8 +42,6 @@ public enum Opcode {
CMPG_FLOAT,
CMPL_DOUBLE,
CMPL_FLOAT,
CMP_G,
CMP_L,
CMP_LONG,
CONST,
@@ -112,6 +112,7 @@ public enum Opcode {
MONITOR_EXIT,
MOVE,
MOVE_MULTI,
MOVE_EXCEPTION,
MOVE_OBJECT,
MOVE_RESULT,
@@ -130,7 +131,6 @@ public enum Opcode {
NEG_LONG,
NEW_INSTANCE,
NOT,
NOT_INT,
NOT_LONG,
@@ -172,11 +172,9 @@ public enum Opcode {
FILLED_NEW_ARRAY,
FILLED_NEW_ARRAY_RANGE,
FILL_ARRAY,
FILL_ARRAY_DATA,
FILL_ARRAY_DATA_PAYLOAD,
SWITCH,
PACKED_SWITCH,
PACKED_SWITCH_PAYLOAD,
SPARSE_SWITCH,
@@ -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;
}
}
@@ -0,0 +1,69 @@
package jadx.api.plugins.utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import org.jetbrains.annotations.Nullable;
public class Utils {
public static <T> void addToList(List<T> list, @Nullable T item) {
if (item != null) {
list.add(item);
}
}
public static <T, I> void addToList(List<T> list, @Nullable I item, Function<I, T> map) {
if (item != null) {
T value = map.apply(item);
if (value != null) {
list.add(value);
}
}
}
public static <T> List<T> concat(List<T> a, List<T> b) {
int aSize = a.size();
int bSize = b.size();
if (aSize == 0 && bSize == 0) {
return Collections.emptyList();
}
if (aSize == 0) {
return b;
}
if (bSize == 0) {
return a;
}
List<T> list = new ArrayList<>(aSize + bSize);
list.addAll(a);
list.addAll(b);
return list;
}
public static <T> String listToStr(List<T> list) {
if (list == null) {
return "null";
}
if (list.isEmpty()) {
return "";
}
if (list.size() == 1) {
return Objects.toString(list.get(0));
}
StringBuilder sb = new StringBuilder();
Iterator<T> it = list.iterator();
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);
}
}