From 5c83c22501a3cce31afddf43eb6bf3da232bdb7a Mon Sep 17 00:00:00 2001 From: Skylot <118523+skylot@users.noreply.github.com> Date: Sat, 14 Sep 2024 22:33:28 +0100 Subject: [PATCH] feat(java-input): support StackMapTable to get stack info for unvisited jumps (#2271) --- .../jadx/core/dex/visitors/CheckCode.java | 6 +- .../dex/visitors/blocks/BlockProcessor.java | 6 +- .../integration/jbc/TestStackConvert.java | 40 ++++ .../src/test/raung/jbc/TestStackConvert.raung | 53 ++++++ .../input/java/data/ConstPoolReader.java | 2 +- .../input/java/data/JavaClassData.java | 10 +- .../data/attributes/AttributesReader.java | 114 ++++++------ .../java/data/attributes/JavaAttrType.java | 26 ++- .../data/attributes/stack/StackFrame.java | 47 +++++ .../data/attributes/stack/StackFrameType.java | 37 ++++ .../attributes/stack/StackMapTableReader.java | 176 ++++++++++++++++++ .../data/attributes/stack/StackValueType.java | 6 + .../data/attributes/stack/TypeInfoReader.java | 53 ++++++ .../attributes/types/StackMapTableAttr.java | 23 +++ .../input/java/data/code/CodeDecodeState.java | 55 ++++-- .../input/java/data/code/JavaCodeReader.java | 32 ++-- .../java/data/code/JavaInsnsRegister.java | 12 +- .../input/java/data/code/StackState.java | 35 ++-- .../data/code/decoders/LoadConstDecoder.java | 12 +- .../plugins/input/java/utils/DisasmUtils.java | 4 +- .../plugins/input/raung/RaungConvert.java | 2 +- 21 files changed, 620 insertions(+), 131 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/jbc/TestStackConvert.java create mode 100644 jadx-core/src/test/raung/jbc/TestStackConvert.raung create mode 100644 jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackFrame.java create mode 100644 jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackFrameType.java create mode 100644 jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackMapTableReader.java create mode 100644 jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackValueType.java create mode 100644 jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/TypeInfoReader.java create mode 100644 jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/types/StackMapTableAttr.java diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/CheckCode.java b/jadx-core/src/main/java/jadx/core/dex/visitors/CheckCode.java index e0894ebb3..98e4a62c8 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/CheckCode.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/CheckCode.java @@ -71,7 +71,11 @@ public class CheckCode extends AbstractVisitor { } insnNode.getRegisterArgs(list); for (RegisterArg arg : list) { - if (arg.getRegNum() >= regsCount) { + int regNum = arg.getRegNum(); + if (regNum < 0) { + throw new JadxRuntimeException("Incorrect negative register number in instruction: " + insnNode); + } + if (regNum >= regsCount) { throw new JadxRuntimeException("Incorrect register number in instruction: " + insnNode + ", expected to be less than " + regsCount); } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockProcessor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockProcessor.java index 57b5e4ddc..046ab6a12 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockProcessor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockProcessor.java @@ -90,7 +90,7 @@ public class BlockProcessor extends AbstractVisitor { } } - private static boolean deduplicateBlockInsns(BlockNode block) { + private static boolean deduplicateBlockInsns(MethodNode mth, BlockNode block) { if (block.contains(AFlag.LOOP_START) || block.contains(AFlag.LOOP_END)) { // search for same instruction at end of all predecessors blocks List predecessors = block.getPredecessors(); @@ -109,7 +109,7 @@ public class BlockProcessor extends AbstractVisitor { List insns = getLastInsns(predecessors.get(0), sameInsnCount); insertAtStart(block, insns); predecessors.forEach(pred -> getLastInsns(pred, sameInsnCount).clear()); - LOG.debug("Move duplicate insns, count: {} to block {}", sameInsnCount, block); + mth.addDebugComment("Move duplicate insns, count: " + sameInsnCount + " to block " + block); return true; } } @@ -318,7 +318,7 @@ public class BlockProcessor extends AbstractVisitor { boolean changed = false; List basicBlocks = mth.getBasicBlocks(); for (BlockNode basicBlock : basicBlocks) { - if (deduplicateBlockInsns(basicBlock)) { + if (deduplicateBlockInsns(mth, basicBlock)) { changed = true; } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/jbc/TestStackConvert.java b/jadx-core/src/test/java/jadx/tests/integration/jbc/TestStackConvert.java new file mode 100644 index 000000000..b3883eae2 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/jbc/TestStackConvert.java @@ -0,0 +1,40 @@ +package jadx.tests.integration.jbc; + +import org.junit.jupiter.api.Test; + +import jadx.tests.api.RaungTest; +import jadx.tests.api.extensions.profiles.TestProfile; +import jadx.tests.api.extensions.profiles.TestWithProfiles; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestStackConvert extends RaungTest { + + @SuppressWarnings({ "UnnecessaryLocalVariable", "CallToPrintStackTrace", "printstacktrace" }) + public static class TestCls { + public int parseIntDefault(String num, int defaultNum) { + try { + int defaultNum2 = Integer.parseInt(num); + return defaultNum2; + } catch (NumberFormatException e) { + System.out.println("Before println"); + e.printStackTrace(); + return defaultNum; + } + } + } + + @TestWithProfiles(TestProfile.JAVA11) + public void test() { + assertThat(getClassNode(TestCls.class)) + .code() + .containsOne("Integer.parseInt(num)"); + } + + @Test + public void testRaung() { + assertThat(getClassNodeFromRaung()) + .code() + .containsOne("Integer.parseInt(num)"); + } +} diff --git a/jadx-core/src/test/raung/jbc/TestStackConvert.raung b/jadx-core/src/test/raung/jbc/TestStackConvert.raung new file mode 100644 index 000000000..67d30c37e --- /dev/null +++ b/jadx-core/src/test/raung/jbc/TestStackConvert.raung @@ -0,0 +1,53 @@ +.version 52 # Java 8 +.class public super jbc/TestStackConvert + +.method public parseIntDefault(Ljava/lang/String;I)I + .max stack 3 + .max locals 5 + + :L0 + .local 0 "this" Ljbc/TestStackConvert; + .local 1 "num" Ljava/lang/String; + .local 2 "defaultNum" I + .line 13 + aload 1 + invokestatic java/lang/Integer parseInt (Ljava/lang/String;)I + :L1 + .catch java/lang/NumberFormatException :L0 .. :L1 goto :L2 + ireturn + :L3 + .line 14 + .stack full + stack 0 java/lang/NumberFormatException + local 0 jbc/TestStackConvert + local 1 java/lang/String + local 2 int + local 3 Top + local 4 java/lang/NumberFormatException + .end stack + astore 3 + .local 3 "e" Ljava/lang/NumberFormatException; + .line 15 + aload 3 + invokevirtual java/lang/NumberFormatException printStackTrace ()V + .line 17 + iload 2 + .end local 3 # "e" + ireturn + :L2 + .stack full + stack 0 java/lang/NumberFormatException + local 0 jbc/TestStackConvert + local 1 java/lang/String + local 2 int + .end stack + .end local 0 # "this" + .end local 1 # "num" + .end local 2 # "defaultNum" + astore 4 + getstatic java/lang/System out Ljava/io/PrintStream; + ldc "Before println" + invokevirtual java/io/PrintStream println (Ljava/lang/String;)V + aload 4 + goto :L3 +.end method diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/ConstPoolReader.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/ConstPoolReader.java index 0ca026bf2..a6e9db9b3 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/ConstPoolReader.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/ConstPoolReader.java @@ -103,7 +103,7 @@ public class ConstPoolReader { } private CallSite resolveMethodCallSite(int bootstrapMthIdx, int nameIdx, int descIdx) { - JavaBootstrapMethodsAttr bootstrapMethodsAttr = clsData.loadAttribute(data, JavaAttrType.BOOTSTRAP_METHODS); + JavaBootstrapMethodsAttr bootstrapMethodsAttr = clsData.loadClassAttribute(data, JavaAttrType.BOOTSTRAP_METHODS); if (bootstrapMethodsAttr == null) { throw new JavaClassParseException("Unexpected missing BootstrapMethods attribute"); } diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/JavaClassData.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/JavaClassData.java index 6b21e2ee1..becb16fba 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/JavaClassData.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/JavaClassData.java @@ -106,7 +106,7 @@ public class JavaClassData implements IClassData { int accessFlags = reader.readU2(); int nameIdx = reader.readU2(); int typeIdx = reader.readU2(); - JavaAttrStorage attributes = attributesReader.load(reader); + JavaAttrStorage attributes = attributesReader.loadAll(reader); field.setAccessFlags(accessFlags); field.setName(constPoolReader.getUtf8(nameIdx)); @@ -118,7 +118,7 @@ public class JavaClassData implements IClassData { int accessFlags = reader.readU2(); int nameIdx = reader.readU2(); int descriptorIdx = reader.readU2(); - JavaAttrStorage attributes = attributesReader.load(reader); + JavaAttrStorage attributes = attributesReader.loadAll(reader); JavaMethodRef methodRef = method.getMethodRef(); methodRef.reset(); @@ -140,7 +140,7 @@ public class JavaClassData implements IClassData { @Override public List getAttributes() { data.absPos(offsets.getAttributesOffset()); - JavaAttrStorage attributes = attributesReader.load(data); + JavaAttrStorage attributes = attributesReader.loadAll(data); int size = attributes.size(); if (size == 0) { return Collections.emptyList(); @@ -153,9 +153,9 @@ public class JavaClassData implements IClassData { return list; } - public T loadAttribute(DataReader reader, JavaAttrType type) { + public T loadClassAttribute(DataReader reader, JavaAttrType type) { reader.absPos(offsets.getAttributesOffset()); - return attributesReader.loadOne(type, reader); + return attributesReader.loadOne(reader, type); } @Override diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/AttributesReader.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/AttributesReader.java index 29dd77569..b50fa43c8 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/AttributesReader.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/AttributesReader.java @@ -2,6 +2,8 @@ package jadx.plugins.input.java.data.attributes; import java.util.HashMap; import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -14,6 +16,8 @@ import jadx.plugins.input.java.data.JavaClassData; public class AttributesReader { private static final Logger LOG = LoggerFactory.getLogger(AttributesReader.class); + private static final Predicate> LOAD_ALL = type -> true; + private final JavaClassData clsData; private final ConstPoolReader constPool; private final Map> attrCache = new HashMap<>(JavaAttrType.size()); @@ -23,77 +27,71 @@ public class AttributesReader { this.constPool = constPoolReader; } - public JavaAttrStorage load(DataReader reader) { - int attributesCount = reader.readU2(); - if (attributesCount == 0) { + public JavaAttrStorage loadAll(DataReader reader) { + return loadAttributes(reader, LOAD_ALL); + } + + public JavaAttrStorage loadMulti(DataReader reader, Set> types) { + return loadAttributes(reader, types::contains); + } + + /** + * Load attributes into storage + * + * @param reader - reader pos should be set to attributes section start + * @param condition - check if attribute should be parsed and added to storage + */ + private JavaAttrStorage loadAttributes(DataReader reader, Predicate> condition) { + int count = reader.readU2(); + if (count == 0) { return JavaAttrStorage.EMPTY; } JavaAttrStorage storage = new JavaAttrStorage(); - for (int i = 0; i < attributesCount; i++) { - readAndAdd(storage, reader); + for (int i = 0; i < count; i++) { + int nameIdx = reader.readU2(); + int len = reader.readU4(); + int end = reader.getOffset() + len; + try { + JavaAttrType attrType = resolveAttrReader(nameIdx); + if (attrType != null && condition.test(attrType)) { + IJavaAttributeReader attrReader = attrType.getReader(); + if (attrReader != null) { + IJavaAttribute attrValue = attrReader.read(clsData, reader); + if (attrValue != null) { + storage.add(attrType, attrValue); + } + } + } + } catch (Exception e) { + LOG.error("Failed to parse attribute: {}", constPool.getUtf8(nameIdx), e); + } finally { + reader.absPos(end); + } } return storage; } - private void readAndAdd(JavaAttrStorage storage, DataReader reader) { - int nameIdx = reader.readU2(); - int len = reader.readU4(); - int end = reader.getOffset() + len; - try { - JavaAttrType attrType = resolveAttrReader(nameIdx); - if (attrType == null) { - return; - } - IJavaAttributeReader attrReader = attrType.getReader(); - if (attrReader == null) { - // ignore attribute - return; - } - IJavaAttribute attrValue = attrReader.read(clsData, reader); - if (attrValue != null) { - storage.add(attrType, attrValue); - } - } catch (Exception e) { - LOG.error("Failed to parse attribute: {}", constPool.getUtf8(nameIdx), e); - } finally { - reader.absPos(end); - } - } - @SuppressWarnings("unchecked") - @Nullable - public T loadOne(JavaAttrType type, DataReader reader) { - int attributesCount = reader.readU2(); - if (attributesCount == 0) { - return null; - } - for (int i = 0; i < attributesCount; i++) { - IJavaAttribute attr = readType(type, reader); - if (attr != null) { - return (T) attr; + public @Nullable T loadOne(DataReader reader, JavaAttrType type) { + int count = reader.readU2(); + for (int i = 0; i < count; i++) { + int nameIdx = reader.readU2(); + int len = reader.readU4(); + int end = reader.getOffset() + len; + try { + JavaAttrType attrType = resolveAttrReader(nameIdx); + if (attrType == type) { + return (T) attrType.getReader().read(clsData, reader); + } + } catch (Exception e) { + LOG.error("Failed to parse attribute: {}", constPool.getUtf8(nameIdx), e); + } finally { + reader.absPos(end); } } return null; } - private IJavaAttribute readType(JavaAttrType type, DataReader reader) { - int nameIdx = reader.readU2(); - int len = reader.readU4(); - int end = reader.getOffset() + len; - try { - JavaAttrType attrType = resolveAttrReader(nameIdx); - if (attrType == null || attrType != type) { - return null; - } - return attrType.getReader().read(clsData, reader); - } catch (Exception e) { - LOG.error("Failed to parse attribute: {}", constPool.getUtf8(nameIdx), e); - return null; - } finally { - reader.absPos(end); - } - } - private JavaAttrType resolveAttrReader(int nameIdx) { return attrCache.computeIfAbsent(nameIdx, idx -> { String attrName = constPool.getUtf8(idx); diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/JavaAttrType.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/JavaAttrType.java index bfbc3a2df..6cf836a96 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/JavaAttrType.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/JavaAttrType.java @@ -9,6 +9,7 @@ import jadx.api.plugins.input.data.annotations.AnnotationVisibility; import jadx.plugins.input.java.data.attributes.debuginfo.LineNumberTableAttr; import jadx.plugins.input.java.data.attributes.debuginfo.LocalVarTypesAttr; import jadx.plugins.input.java.data.attributes.debuginfo.LocalVarsAttr; +import jadx.plugins.input.java.data.attributes.stack.StackMapTableReader; import jadx.plugins.input.java.data.attributes.types.CodeAttr; import jadx.plugins.input.java.data.attributes.types.ConstValueAttr; import jadx.plugins.input.java.data.attributes.types.IgnoredAttr; @@ -21,6 +22,7 @@ import jadx.plugins.input.java.data.attributes.types.JavaMethodParametersAttr; import jadx.plugins.input.java.data.attributes.types.JavaParamAnnsAttr; import jadx.plugins.input.java.data.attributes.types.JavaSignatureAttr; import jadx.plugins.input.java.data.attributes.types.JavaSourceFileAttr; +import jadx.plugins.input.java.data.attributes.types.StackMapTableAttr; public final class JavaAttrType { @@ -32,6 +34,7 @@ public final class JavaAttrType { public static final JavaAttrType CONST_VALUE; public static final JavaAttrType CODE; + public static final JavaAttrType STACK_MAP_TABLE; public static final JavaAttrType LINE_NUMBER_TABLE; public static final JavaAttrType LOCAL_VAR_TABLE; public static final JavaAttrType LOCAL_VAR_TYPE_TABLE; @@ -51,9 +54,12 @@ public final class JavaAttrType { public static final JavaAttrType DEPRECATED; public static final JavaAttrType SYNTHETIC; - public static final JavaAttrType STACK_MAP_TABLE; public static final JavaAttrType ENCLOSING_METHOD; + public static final JavaAttrType MODULE; + public static final JavaAttrType SOURCE_DEBUG_EXTENSION; + public static final JavaAttrType NEST_HOST; + public static final JavaAttrType NEST_MEMBERS; static { NAME_TO_TYPE_MAP = new HashMap<>(); @@ -79,17 +85,20 @@ public final class JavaAttrType { SIGNATURE = bind("Signature", JavaSignatureAttr.reader()); EXCEPTIONS = bind("Exceptions", JavaExceptionsAttr.reader()); METHOD_PARAMETERS = bind("MethodParameters", JavaMethodParametersAttr.reader()); + STACK_MAP_TABLE = bind("StackMapTable", new StackMapTableReader()); // ignored DEPRECATED = bind("Deprecated", null); // duplicated by annotation SYNTHETIC = bind("Synthetic", null); // duplicated by access flag - STACK_MAP_TABLE = bind("StackMapTable", null); ENCLOSING_METHOD = bind("EnclosingMethod", null); // TODO: not supported yet RUNTIME_TYPE_ANNOTATIONS = bind("RuntimeVisibleTypeAnnotations", null); BUILD_TYPE_ANNOTATIONS = bind("RuntimeInvisibleTypeAnnotations", null); MODULE = bind("Module", null); + NEST_HOST = bind("NestHost", null); + NEST_MEMBERS = bind("NestMembers", null); + SOURCE_DEBUG_EXTENSION = bind("SourceDebugExtension", null); } private static JavaAttrType bind(String name, IJavaAttributeReader reader) { @@ -129,6 +138,19 @@ public final class JavaAttrType { return reader; } + @Override + public int hashCode() { + return id; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + return id == ((JavaAttrType) o).id; + } + @Override public String toString() { return name; diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackFrame.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackFrame.java new file mode 100644 index 000000000..cfb561822 --- /dev/null +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackFrame.java @@ -0,0 +1,47 @@ +package jadx.plugins.input.java.data.attributes.stack; + +public class StackFrame { + private final int offset; + private final StackFrameType type; + + private int stackSize; + private StackValueType[] stackValueTypes; + private int localsCount; + + public StackFrame(int offset, StackFrameType type) { + this.offset = offset; + this.type = type; + } + + public int getOffset() { + return offset; + } + + public StackFrameType getType() { + return type; + } + + public int getLocalsCount() { + return localsCount; + } + + public void setLocalsCount(int localsCount) { + this.localsCount = localsCount; + } + + public int getStackSize() { + return stackSize; + } + + public void setStackSize(int stackSize) { + this.stackSize = stackSize; + } + + public StackValueType[] getStackValueTypes() { + return stackValueTypes; + } + + public void setStackValueTypes(StackValueType[] stackValueTypes) { + this.stackValueTypes = stackValueTypes; + } +} diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackFrameType.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackFrameType.java new file mode 100644 index 000000000..4c5e471d8 --- /dev/null +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackFrameType.java @@ -0,0 +1,37 @@ +package jadx.plugins.input.java.data.attributes.stack; + +import org.jetbrains.annotations.Nullable; + +public enum StackFrameType { + SAME_FRAME(0, 63), + SAME_LOCALS_1_STACK(64, 127), + SAME_LOCALS_1_STACK_EXTENDED(247, 247), + CHOP(248, 250), + SAME_FRAME_EXTENDED(251, 251), + APPEND(252, 254), + FULL(255, 255); + + private final int start; + private final int end; + + StackFrameType(int start, int end) { + this.start = start; + this.end = end; + } + + private static final StackFrameType[] MAPPING = buildMapping(); + + private static StackFrameType[] buildMapping() { + StackFrameType[] mapping = new StackFrameType[256]; + for (StackFrameType value : StackFrameType.values()) { + for (int i = value.start; i <= value.end; i++) { + mapping[i] = value; + } + } + return mapping; + } + + public static @Nullable StackFrameType getType(int data) { + return MAPPING[data]; + } +} diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackMapTableReader.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackMapTableReader.java new file mode 100644 index 000000000..751242ec5 --- /dev/null +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackMapTableReader.java @@ -0,0 +1,176 @@ +package jadx.plugins.input.java.data.attributes.stack; + +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; + +import jadx.plugins.input.java.data.DataReader; +import jadx.plugins.input.java.data.JavaClassData; +import jadx.plugins.input.java.data.attributes.IJavaAttribute; +import jadx.plugins.input.java.data.attributes.IJavaAttributeReader; +import jadx.plugins.input.java.data.attributes.types.StackMapTableAttr; +import jadx.plugins.input.java.utils.JavaClassParseException; + +public class StackMapTableReader implements IJavaAttributeReader { + + @Override + public IJavaAttribute read(JavaClassData clsData, DataReader reader) { + int count = reader.readU2(); + Map map = new HashMap<>(count, 1); + StackFrame prevFrame = null; + for (int i = 0; i < count; i++) { + StackFrame frame = readFrame(reader, prevFrame); + map.put(frame.getOffset(), frame); + prevFrame = frame; + } + return new StackMapTableAttr(map); + } + + private static final Map> FRAME_READERS = registerReaders(); + + private static Map> registerReaders() { + EnumMap> map = new EnumMap<>(StackFrameType.class); + map.put(StackFrameType.SAME_FRAME, context -> readSame(context, false)); + map.put(StackFrameType.SAME_FRAME_EXTENDED, context -> readSame(context, true)); + map.put(StackFrameType.SAME_LOCALS_1_STACK, context -> readSL1S(context, false)); + map.put(StackFrameType.SAME_LOCALS_1_STACK_EXTENDED, context -> readSL1S(context, true)); + map.put(StackFrameType.CHOP, StackMapTableReader::readChop); + map.put(StackFrameType.APPEND, StackMapTableReader::readAppend); + map.put(StackFrameType.FULL, StackMapTableReader::readFull); + return map; + } + + private StackFrame readFrame(DataReader reader, StackFrame prevFrame) { + int typeData = reader.readU1(); + StackFrameType frameType = StackFrameType.getType(typeData); + Consumer frameReader = FRAME_READERS.get(frameType); + if (frameReader == null) { + throw new JavaClassParseException("Found unsupported stack frame type: " + frameType); + } + FrameContext frameContext = new FrameContext(reader, typeData, prevFrame); + frameReader.accept(frameContext); + return Objects.requireNonNull(frameContext.getFrame()); + } + + private static void readSame(FrameContext context, boolean extended) { + int offsetDelta; + StackFrameType type; + if (extended) { + type = StackFrameType.SAME_FRAME_EXTENDED; + offsetDelta = context.getDataReader().readU2(); + } else { + type = StackFrameType.SAME_FRAME; + offsetDelta = context.getTypeData(); + } + StackFrame frame = new StackFrame(calcOffset(context, offsetDelta), type); + frame.setStackSize(0); + frame.setLocalsCount(getPrevLocalsCount(context)); + context.setFrame(frame); + } + + private static void readSL1S(FrameContext context, boolean extended) { + DataReader reader = context.getDataReader(); + int offsetDelta; + StackFrameType type; + if (extended) { + type = StackFrameType.SAME_LOCALS_1_STACK_EXTENDED; + offsetDelta = reader.readU2(); + } else { + type = StackFrameType.SAME_LOCALS_1_STACK; + offsetDelta = context.getTypeData() - 64; + } + StackValueType[] stackTypes = TypeInfoReader.readTypeInfoList(reader, 1); + StackFrame frame = new StackFrame(calcOffset(context, offsetDelta), type); + frame.setStackSize(1); + frame.setStackValueTypes(stackTypes); + frame.setLocalsCount(getPrevLocalsCount(context)); + context.setFrame(frame); + } + + private static void readChop(FrameContext context) { + int k = 251 - context.getTypeData(); + int offsetDelta = context.getDataReader().readU2(); + StackFrame frame = new StackFrame(calcOffset(context, offsetDelta), StackFrameType.CHOP); + frame.setStackSize(0); + frame.setLocalsCount(getPrevLocalsCount(context) - k); + context.setFrame(frame); + } + + private static void readAppend(FrameContext context) { + DataReader reader = context.getDataReader(); + int k = context.getTypeData() - 251; + int offsetDelta = reader.readU2(); + TypeInfoReader.skipTypeInfoList(reader, k); + StackFrame frame = new StackFrame(calcOffset(context, offsetDelta), StackFrameType.APPEND); + frame.setStackSize(0); + frame.setLocalsCount(getPrevLocalsCount(context) - k); + context.setFrame(frame); + } + + private static void readFull(FrameContext context) { + DataReader reader = context.getDataReader(); + int offsetDelta = reader.readU2(); + int localsCount = reader.readU2(); + TypeInfoReader.skipTypeInfoList(reader, localsCount); + int stackSize = reader.readU2(); + StackValueType[] stackTypes = TypeInfoReader.readTypeInfoList(reader, stackSize); + + StackFrame frame = new StackFrame(calcOffset(context, offsetDelta), StackFrameType.FULL); + frame.setLocalsCount(localsCount); + frame.setStackSize(stackSize); + frame.setStackValueTypes(stackTypes); + context.setFrame(frame); + } + + private static int calcOffset(FrameContext context, int offsetDelta) { + StackFrame prevFrame = context.getPrevFrame(); + if (prevFrame == null) { + return offsetDelta; + } + return prevFrame.getOffset() + offsetDelta + 1; + } + + private static int getPrevLocalsCount(FrameContext context) { + StackFrame prevFrame = context.getPrevFrame(); + if (prevFrame == null) { + return 0; + } + return prevFrame.getLocalsCount(); + } + + private static final class FrameContext { + private final DataReader dataReader; + private final int typeData; + private final StackFrame prevFrame; + + private StackFrame frame; + + private FrameContext(DataReader dataReader, int typeData, StackFrame prevFrame) { + this.dataReader = dataReader; + this.typeData = typeData; + this.prevFrame = prevFrame; + } + + public DataReader getDataReader() { + return dataReader; + } + + public int getTypeData() { + return typeData; + } + + public StackFrame getPrevFrame() { + return prevFrame; + } + + public StackFrame getFrame() { + return frame; + } + + public void setFrame(StackFrame frame) { + this.frame = frame; + } + } +} diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackValueType.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackValueType.java new file mode 100644 index 000000000..63f779459 --- /dev/null +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/StackValueType.java @@ -0,0 +1,6 @@ +package jadx.plugins.input.java.data.attributes.stack; + +public enum StackValueType { + NARROW, // int, float, etc + WIDE, // long, double +} diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/TypeInfoReader.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/TypeInfoReader.java new file mode 100644 index 000000000..e0593c4ef --- /dev/null +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/stack/TypeInfoReader.java @@ -0,0 +1,53 @@ +package jadx.plugins.input.java.data.attributes.stack; + +import jadx.plugins.input.java.data.DataReader; + +public class TypeInfoReader { + private static final int ITEM_TOP = 0; + private static final int ITEM_INT = 1; + private static final int ITEM_FLOAT = 2; + + private static final int ITEM_DOUBLE = 3; + private static final int ITEM_LONG = 4; + + private static final int ITEM_NULL = 5; + private static final int ITEM_UNINITIALIZED_THIS = 6; + + private static final int ITEM_OBJECT = 7; + private static final int ITEM_UNINITIALIZED = 8; + + static StackValueType[] readTypeInfoList(DataReader reader, int count) { + StackValueType[] types = new StackValueType[count]; + for (int i = 0; i < count; i++) { + int tag = reader.readU1(); + StackValueType type; + switch (tag) { + case ITEM_DOUBLE: + case ITEM_LONG: + type = StackValueType.WIDE; + break; + + case ITEM_OBJECT: + case ITEM_UNINITIALIZED: + reader.readU2(); // ignore + type = StackValueType.NARROW; + break; + + default: + type = StackValueType.NARROW; + break; + } + types[i] = type; + } + return types; + } + + static void skipTypeInfoList(DataReader reader, int count) { + for (int i = 0; i < count; i++) { + int tag = reader.readU1(); + if (tag == ITEM_OBJECT || tag == ITEM_UNINITIALIZED) { + reader.readU2(); + } + } + } +} diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/types/StackMapTableAttr.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/types/StackMapTableAttr.java new file mode 100644 index 000000000..d740de562 --- /dev/null +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/types/StackMapTableAttr.java @@ -0,0 +1,23 @@ +package jadx.plugins.input.java.data.attributes.types; + +import java.util.Collections; +import java.util.Map; + +import org.jetbrains.annotations.Nullable; + +import jadx.plugins.input.java.data.attributes.IJavaAttribute; +import jadx.plugins.input.java.data.attributes.stack.StackFrame; + +public class StackMapTableAttr implements IJavaAttribute { + public static final StackMapTableAttr EMPTY = new StackMapTableAttr(Collections.emptyMap()); + + private final Map map; + + public StackMapTableAttr(Map map) { + this.map = map; + } + + public @Nullable StackFrame getFor(int offset) { + return map.get(offset); + } +} diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/CodeDecodeState.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/CodeDecodeState.java index 9e891bd91..9cb64278c 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/CodeDecodeState.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/CodeDecodeState.java @@ -4,10 +4,15 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; +import org.jetbrains.annotations.Nullable; + import jadx.api.plugins.input.insns.Opcode; +import jadx.core.utils.Utils; import jadx.plugins.input.java.data.DataReader; import jadx.plugins.input.java.data.JavaClassData; -import jadx.plugins.input.java.data.code.StackState.SVType; +import jadx.plugins.input.java.data.attributes.stack.StackFrame; +import jadx.plugins.input.java.data.attributes.stack.StackValueType; +import jadx.plugins.input.java.data.attributes.types.StackMapTableAttr; @SuppressWarnings("UnusedReturnValue") public class CodeDecodeState { @@ -15,35 +20,49 @@ public class CodeDecodeState { private final DataReader reader; private final int maxStack; private final Set excHandlers; - + private final StackMapTableAttr stackMapTable; private final Map jumpStack = new HashMap<>(); // save current stack for jump target private JavaInsnData insn; private StackState stack; private boolean excHandler; - public CodeDecodeState(JavaClassData clsData, DataReader reader, int maxStack, Set excHandlers) { + public CodeDecodeState(JavaClassData clsData, DataReader reader, int maxStack, + Set excHandlers, @Nullable StackMapTableAttr stackMapTable) { this.clsData = clsData; this.reader = reader; this.maxStack = maxStack; this.excHandlers = excHandlers; this.stack = new StackState(maxStack); + this.stackMapTable = Utils.getOrElse(stackMapTable, StackMapTableAttr.EMPTY); } public void onInsn(int offset) { - StackState stackState = jumpStack.get(offset); - if (stackState != null) { - this.stack = stackState; + StackState newStack = loadStack(offset); + if (newStack != null) { + this.stack = newStack; } if (excHandlers.contains(offset)) { clear(); - stack.push(SVType.NARROW); // push exception + stack.push(StackValueType.NARROW); // push exception excHandler = true; } else { excHandler = false; } } + private @Nullable StackState loadStack(int offset) { + StackState stackState = jumpStack.get(offset); + if (stackState != null) { + return stackState.copy(); + } + StackFrame frame = stackMapTable.getFor(offset); + if (frame != null) { + return new StackState(maxStack).fillFromFrame(frame); + } + return null; + } + public void registerJump(int jumpOffset) { Integer key = jumpOffset; if (!jumpStack.containsKey(key)) { @@ -90,7 +109,7 @@ public class CodeDecodeState { return this; } - public SVType peekType(int at) { + public StackValueType peekType(int at) { return stack.peekTypeAt(at); } @@ -100,21 +119,21 @@ public class CodeDecodeState { } public CodeDecodeState push(int arg) { - insn.setArgReg(arg, stack.push(SVType.NARROW)); + insn.setArgReg(arg, stack.push(StackValueType.NARROW)); return this; } - public CodeDecodeState push(int arg, SVType type) { + public CodeDecodeState push(int arg, StackValueType type) { insn.setArgReg(arg, stack.push(type)); return this; } public CodeDecodeState pushWide(int arg) { - insn.setArgReg(arg, stack.push(SVType.WIDE)); + insn.setArgReg(arg, stack.push(StackValueType.WIDE)); return this; } - public int insert(int pos, SVType type) { + public int insert(int pos, StackValueType type) { return stack.insert(pos, type); } @@ -123,9 +142,9 @@ public class CodeDecodeState { } public void discardWord() { - SVType type = stack.peekTypeAt(0); + StackValueType type = stack.peekTypeAt(0); stack.pop(); - if (type == SVType.NARROW) { + if (type == StackValueType.NARROW) { stack.pop(); } } @@ -162,16 +181,16 @@ public class CodeDecodeState { return maxStack + local; } - public SVType fieldType() { + public StackValueType fieldType() { String type = insn.constPoolReader().getFieldType(insn().getIndex()); return getSVType(type); } - public SVType getSVType(String type) { + public StackValueType getSVType(String type) { if (type.equals("J") || type.equals("D")) { - return SVType.WIDE; + return StackValueType.WIDE; } - return SVType.NARROW; + return StackValueType.NARROW; } public int u1() { diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaCodeReader.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaCodeReader.java index 5074de1ba..de2f6b3c4 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaCodeReader.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaCodeReader.java @@ -28,6 +28,7 @@ import jadx.plugins.input.java.data.attributes.debuginfo.JavaLocalVar; import jadx.plugins.input.java.data.attributes.debuginfo.LineNumberTableAttr; import jadx.plugins.input.java.data.attributes.debuginfo.LocalVarTypesAttr; import jadx.plugins.input.java.data.attributes.debuginfo.LocalVarsAttr; +import jadx.plugins.input.java.data.attributes.types.StackMapTableAttr; import jadx.plugins.input.java.data.code.trycatch.JavaSingleCatch; import jadx.plugins.input.java.data.code.trycatch.JavaTryData; import jadx.plugins.input.java.utils.JavaClassParseException; @@ -52,11 +53,14 @@ public class JavaCodeReader implements ICodeReader { @Override public void visitInstructions(Consumer insnConsumer) { Set excHandlers = getExcHandlers(); + jumpToCodeAttributes(); + StackMapTableAttr stackMapTable = clsData.getAttributesReader().loadOne(reader, JavaAttrType.STACK_MAP_TABLE); + int maxStack = readMaxStack(); reader.skip(2); int codeSize = reader.readU4(); - CodeDecodeState state = new CodeDecodeState(clsData, reader, maxStack, excHandlers); + CodeDecodeState state = new CodeDecodeState(clsData, reader, maxStack, excHandlers, stackMapTable); JavaInsnData insn = new JavaInsnData(state); state.setInsn(insn); int offset = 0; @@ -116,15 +120,17 @@ public class JavaCodeReader implements ICodeReader { return reader.absPos(codeOffset + 4).readU4(); } + private static final Set> DEBUG_INFO_ATTRIBUTES = Set.of( + JavaAttrType.LINE_NUMBER_TABLE, + JavaAttrType.LOCAL_VAR_TABLE, + JavaAttrType.LOCAL_VAR_TYPE_TABLE); + @Override @Nullable public IDebugInfo getDebugInfo() { int maxStack = readMaxStack(); - reader.skip(2); - reader.skip(reader.readU4()); - reader.skip(reader.readU2() * 8); - - JavaAttrStorage attrs = clsData.getAttributesReader().load(reader); + jumpToCodeAttributes(); + JavaAttrStorage attrs = clsData.getAttributesReader().loadMulti(reader, DEBUG_INFO_ATTRIBUTES); LineNumberTableAttr linesAttr = attrs.get(JavaAttrType.LINE_NUMBER_TABLE); LocalVarsAttr varsAttr = attrs.get(JavaAttrType.LOCAL_VAR_TABLE); if (linesAttr == null && varsAttr == null) { @@ -162,7 +168,7 @@ public class JavaCodeReader implements ICodeReader { @Override public List getTries() { - skipToTries(); + jumpToTries(); int excTableLen = reader.readU2(); if (excTableLen == 0) { return Collections.emptyList(); @@ -212,7 +218,7 @@ public class JavaCodeReader implements ICodeReader { } private Set getExcHandlers() { - skipToTries(); + jumpToTries(); int excTableLen = reader.readU2(); if (excTableLen == 0) { return Collections.emptySet(); @@ -227,9 +233,13 @@ public class JavaCodeReader implements ICodeReader { return set; } - private void skipToTries() { + private void jumpToTries() { reader.absPos(codeOffset + 4); - int codeSize = reader.readU4(); - reader.skip(codeSize); + reader.skip(reader.readU4()); // code length + } + + private void jumpToCodeAttributes() { + jumpToTries(); + reader.skip(reader.readU2() * 8); // exceptions table } } diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaInsnsRegister.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaInsnsRegister.java index 83ecf2784..a5d1a38f5 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaInsnsRegister.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaInsnsRegister.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.Nullable; import jadx.api.plugins.input.insns.InsnIndexType; import jadx.api.plugins.input.insns.Opcode; -import jadx.plugins.input.java.data.code.StackState.SVType; +import jadx.plugins.input.java.data.attributes.stack.StackValueType; import jadx.plugins.input.java.data.code.decoders.IJavaInsnDecoder; import jadx.plugins.input.java.data.code.decoders.InvokeDecoder; import jadx.plugins.input.java.data.code.decoders.LoadConstDecoder; @@ -12,8 +12,8 @@ import jadx.plugins.input.java.data.code.decoders.LookupSwitchDecoder; import jadx.plugins.input.java.data.code.decoders.TableSwitchDecoder; import jadx.plugins.input.java.data.code.decoders.WideDecoder; -import static jadx.plugins.input.java.data.code.StackState.SVType.NARROW; -import static jadx.plugins.input.java.data.code.StackState.SVType.WIDE; +import static jadx.plugins.input.java.data.attributes.stack.StackValueType.NARROW; +import static jadx.plugins.input.java.data.attributes.stack.StackValueType.WIDE; @SuppressWarnings("SpellCheckingInspection") public class JavaInsnsRegister { @@ -351,11 +351,11 @@ public class JavaInsnsRegister { }; } - private static IJavaInsnDecoder oneRegWithResult(SVType type) { + private static IJavaInsnDecoder oneRegWithResult(StackValueType type) { return s -> s.pop(1).push(0, type); } - private static IJavaInsnDecoder twoRegsWithResult(SVType type) { + private static IJavaInsnDecoder twoRegsWithResult(StackValueType type) { return s -> s.pop(2).pop(1).push(0, type); } @@ -387,7 +387,7 @@ public class JavaInsnsRegister { private static void constInsn(JavaInsnInfo[] arr, int opcode, String name, Opcode apiOpcode, long literal) { register(arr, opcode, name, 0, 1, apiOpcode, InsnIndexType.NONE, state -> { state.insn().setLiteral(literal); - state.push(0, apiOpcode == Opcode.CONST_WIDE ? SVType.WIDE : NARROW); + state.push(0, apiOpcode == Opcode.CONST_WIDE ? StackValueType.WIDE : NARROW); }); } diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/StackState.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/StackState.java index 88a8a08a8..e777ee87d 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/StackState.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/StackState.java @@ -2,24 +2,18 @@ package jadx.plugins.input.java.data.code; import java.util.Arrays; +import jadx.plugins.input.java.data.attributes.stack.StackFrame; +import jadx.plugins.input.java.data.attributes.stack.StackValueType; + public class StackState { - - /** - * Stack value type - */ - public enum SVType { - NARROW, // int, float, etc - WIDE, // long, double - } - private int pos = -1; - private final SVType[] stack; + private final StackValueType[] stack; public StackState(int maxStack) { - this.stack = new SVType[maxStack]; + this.stack = new StackValueType[maxStack]; } - private StackState(int pos, SVType[] stack) { + private StackState(int pos, StackValueType[] stack) { this.pos = pos; this.stack = stack; } @@ -28,6 +22,15 @@ public class StackState { return new StackState(pos, Arrays.copyOf(stack, stack.length)); } + public StackState fillFromFrame(StackFrame frame) { + int stackSize = frame.getStackSize(); + this.pos = stackSize - 1; + if (stackSize > 0) { + System.arraycopy(frame.getStackValueTypes(), 0, this.stack, 0, stackSize); + } + return this; + } + public int peek() { return pos; } @@ -36,15 +39,15 @@ public class StackState { return pos - at; } - public SVType peekTypeAt(int at) { + public StackValueType peekTypeAt(int at) { int p = pos - at; if (checkStackIndex(p)) { return stack[p]; } - return SVType.NARROW; + return StackValueType.NARROW; } - public int insert(int at, SVType type) { + public int insert(int at, StackValueType type) { int p = pos - at; System.arraycopy(stack, p, stack, p + 1, at); stack[p] = type; @@ -52,7 +55,7 @@ public class StackState { return p; } - public int push(SVType type) { + public int push(StackValueType type) { int p = ++pos; if (checkStackIndex(p)) { stack[p] = type; diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/decoders/LoadConstDecoder.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/decoders/LoadConstDecoder.java index bacbb82eb..b3e1d3e71 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/decoders/LoadConstDecoder.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/decoders/LoadConstDecoder.java @@ -4,9 +4,9 @@ import jadx.api.plugins.input.insns.Opcode; import jadx.plugins.input.java.data.ConstPoolReader; import jadx.plugins.input.java.data.ConstantType; import jadx.plugins.input.java.data.DataReader; +import jadx.plugins.input.java.data.attributes.stack.StackValueType; import jadx.plugins.input.java.data.code.CodeDecodeState; import jadx.plugins.input.java.data.code.JavaInsnData; -import jadx.plugins.input.java.data.code.StackState.SVType; import jadx.plugins.input.java.utils.JavaClassParseException; public class LoadConstDecoder implements IJavaInsnDecoder { @@ -33,32 +33,32 @@ public class LoadConstDecoder implements IJavaInsnDecoder { case FLOAT: insn.setLiteral(constPoolReader.readU4()); insn.setOpcode(Opcode.CONST); - state.push(0, SVType.NARROW); + state.push(0, StackValueType.NARROW); break; case LONG: case DOUBLE: insn.setLiteral(constPoolReader.readU8()); insn.setOpcode(Opcode.CONST_WIDE); - state.push(0, SVType.WIDE); + state.push(0, StackValueType.WIDE); break; case STRING: insn.setIndex(constPoolReader.readU2()); insn.setOpcode(Opcode.CONST_STRING); - state.push(0, SVType.NARROW); + state.push(0, StackValueType.NARROW); break; case UTF8: insn.setIndex(index); insn.setOpcode(Opcode.CONST_STRING); - state.push(0, SVType.NARROW); + state.push(0, StackValueType.NARROW); break; case CLASS: insn.setIndex(index); insn.setOpcode(Opcode.CONST_CLASS); - state.push(0, SVType.NARROW); + state.push(0, StackValueType.NARROW); break; default: diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/utils/DisasmUtils.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/utils/DisasmUtils.java index 9f9a1f307..70e870410 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/utils/DisasmUtils.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/utils/DisasmUtils.java @@ -1,6 +1,5 @@ package jadx.plugins.input.java.utils; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -22,8 +21,7 @@ public class DisasmUtils { } private static String useRaung(byte[] bytes) { - return RaungDisasm.create() - .executeForInputStream(new ByteArrayInputStream(bytes)); + return RaungDisasm.create().executeForBytes(bytes); } /** diff --git a/jadx-plugins/jadx-raung-input/src/main/java/jadx/plugins/input/raung/RaungConvert.java b/jadx-plugins/jadx-raung-input/src/main/java/jadx/plugins/input/raung/RaungConvert.java index 51ae4522e..a91e6f429 100644 --- a/jadx-plugins/jadx-raung-input/src/main/java/jadx/plugins/input/raung/RaungConvert.java +++ b/jadx-plugins/jadx-raung-input/src/main/java/jadx/plugins/input/raung/RaungConvert.java @@ -30,7 +30,7 @@ public class RaungConvert implements Closeable { this.tmpJar = Files.createTempFile("jadx-raung-", ".jar"); RaungAsm.create() .output(tmpJar) - .inputs(input) + .inputs(raungInputs) .execute(); return true; } catch (Exception e) {