mirror of
https://github.com/SuspiciousActivity/ByteEdit.git
synced 2026-08-13 17:56:17 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1710ea6a5 | ||
|
|
ad55d6793c | ||
|
|
ac247a89ca | ||
|
|
b5e4847be5 | ||
|
|
30c9c81d38 | ||
|
|
65235c6b5b | ||
|
|
d8096a4ec5 |
No files matched your search
@@ -53,7 +53,7 @@ import me.ByteEdit.utils.UnicodeUtils;
|
|||||||
|
|
||||||
public class Assembler {
|
public class Assembler {
|
||||||
|
|
||||||
private static final Pattern SPACE = Pattern.compile(" ");
|
public static final Pattern SPACE = Pattern.compile(" ");
|
||||||
|
|
||||||
public static ClassNode assemble(String input) {
|
public static ClassNode assemble(String input) {
|
||||||
Main.txtByteEditView.removeAllLineHighlights();
|
Main.txtByteEditView.removeAllLineHighlights();
|
||||||
@@ -674,124 +674,41 @@ public class Assembler {
|
|||||||
labels.put(ln, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new LineNumberNode(Integer.parseInt(s.split(" ")[0]), ln);
|
return new LineNumberNode(Integer.parseInt(s.split(" ")[0]), ln);
|
||||||
} else if (s.startsWith("// frame ")) {
|
} else if (s.startsWith("// frame ")) {
|
||||||
String str1 = s.substring(7);
|
String str1 = s.substring(9);
|
||||||
String str = str1.substring(str1.indexOf(' ', 3) + 1);
|
String[] split = str1.split(" ", 2);
|
||||||
Object[] local;
|
|
||||||
Object[] stack;
|
|
||||||
ArrayList<Object> arr = new ArrayList<>();
|
|
||||||
if (str.startsWith("l:null")) {
|
|
||||||
local = new Object[0];
|
|
||||||
} else {
|
|
||||||
String l = str.substring(3, str.indexOf("s:") - 2);
|
|
||||||
if (l.isEmpty()) {
|
|
||||||
local = new Object[0];
|
|
||||||
} else {
|
|
||||||
for (String asd : l.split(", ")) {
|
|
||||||
if (!asd.startsWith("(")) {
|
|
||||||
int frameType = ClassUtil.getFrameTypeByName(asd);
|
|
||||||
if (frameType != -1)
|
|
||||||
arr.add(new Integer(frameType));
|
|
||||||
else {
|
|
||||||
String frame = UnicodeUtils.unescape(hsr, asd);
|
|
||||||
frame = frame.substring(1, frame.length() - 1);
|
|
||||||
arr.add(frame);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (asd.startsWith("(label) ")) {
|
|
||||||
int labelNr = Integer.parseInt(asd.split(" ")[1]);
|
|
||||||
boolean found = false;
|
|
||||||
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
|
||||||
if (entry.getValue() == labelNr) {
|
|
||||||
arr.add(entry.getKey());
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
LabelNode ln = new LabelNode(new Label());
|
|
||||||
labels.put(ln, labelNr);
|
|
||||||
arr.add(ln);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
arr.add(ClassUtil.getCastedValue(asd.split(" ")[1], asd.split("\\) ")[0].substring(1)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
local = new Object[arr.size()];
|
|
||||||
int c = 0;
|
|
||||||
for (Object o : arr) {
|
|
||||||
local[c] = o;
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arr.clear();
|
|
||||||
if (str.endsWith("s:null")) {
|
|
||||||
stack = new Object[0];
|
|
||||||
} else {
|
|
||||||
String st = str.substring(str.indexOf("s:") + 3, str.length() - 1);
|
|
||||||
if (st.isEmpty()) {
|
|
||||||
stack = new Object[0];
|
|
||||||
} else {
|
|
||||||
for (String asd : st.split(", ")) {
|
|
||||||
if (!asd.startsWith("(")) {
|
|
||||||
int frameType = ClassUtil.getFrameTypeByName(asd);
|
|
||||||
if (frameType != -1)
|
|
||||||
arr.add(new Integer(frameType));
|
|
||||||
else {
|
|
||||||
String frame = UnicodeUtils.unescape(hsr, asd);
|
|
||||||
frame = frame.substring(1, frame.length() - 1);
|
|
||||||
arr.add(frame);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (asd.startsWith("(label) ")) {
|
|
||||||
int labelNr = Integer.parseInt(asd.split(" ")[1]);
|
|
||||||
boolean found = false;
|
|
||||||
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
|
||||||
if (entry.getValue() == labelNr) {
|
|
||||||
arr.add(entry.getKey());
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
LabelNode ln = new LabelNode(new Label());
|
|
||||||
labels.put(ln, labelNr);
|
|
||||||
arr.add(ln);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
arr.add(ClassUtil.getCastedValue(asd.split(" ")[1], asd.split("\\) ")[0].substring(1)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stack = new Object[arr.size()];
|
|
||||||
int c = 0;
|
|
||||||
for (Object o : arr) {
|
|
||||||
stack[c] = o;
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int type = 0;
|
int type = 0;
|
||||||
switch (str1.substring(str1.indexOf(' ', 1) + 1, str1.indexOf(' ', 3))) {
|
Object[] local = null;
|
||||||
case "NEW":
|
Object[] stack = null;
|
||||||
type = Opcodes.F_NEW;
|
int localLen = 0;
|
||||||
break;
|
int stackLen = 0;
|
||||||
case "FULL":
|
switch (split[0].toUpperCase()) {
|
||||||
type = Opcodes.F_FULL;
|
|
||||||
break;
|
|
||||||
case "APPEND":
|
|
||||||
type = Opcodes.F_APPEND;
|
|
||||||
break;
|
|
||||||
case "CHOP":
|
|
||||||
type = Opcodes.F_CHOP;
|
|
||||||
break;
|
|
||||||
case "SAME":
|
case "SAME":
|
||||||
type = Opcodes.F_SAME;
|
type = Opcodes.F_SAME;
|
||||||
break;
|
break;
|
||||||
case "SAME1":
|
case "SAME1":
|
||||||
type = Opcodes.F_SAME1;
|
type = Opcodes.F_SAME1;
|
||||||
|
stack = parseFrameList(hsr, split[1], labels);
|
||||||
|
stackLen = stack.length;
|
||||||
|
break;
|
||||||
|
case "CHOP":
|
||||||
|
type = Opcodes.F_CHOP;
|
||||||
|
localLen = Integer.parseInt(split[1]);
|
||||||
|
break;
|
||||||
|
case "APPEND":
|
||||||
|
type = Opcodes.F_APPEND;
|
||||||
|
local = parseFrameList(hsr, split[1], labels);
|
||||||
|
localLen = local.length;
|
||||||
|
break;
|
||||||
|
case "FULL":
|
||||||
|
type = Opcodes.F_FULL;
|
||||||
|
split = split[1].split("\\] \\[", 2);
|
||||||
|
local = parseFrameList(hsr, split[0] + "]", labels);
|
||||||
|
localLen = local.length;
|
||||||
|
stack = parseFrameList(hsr, "[" + split[1], labels);
|
||||||
|
stackLen = stack.length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return new FrameNode(type, local.length, local, stack.length, stack);
|
return new FrameNode(type, localLen, local, stackLen, stack);
|
||||||
} else {
|
} else {
|
||||||
String[] split = s.split(" ");
|
String[] split = s.split(" ");
|
||||||
String command = split[0];
|
String command = split[0];
|
||||||
@@ -829,10 +746,10 @@ public class Assembler {
|
|||||||
case "dconst_1":
|
case "dconst_1":
|
||||||
return new InsnNode(15);
|
return new InsnNode(15);
|
||||||
case "bipush": {
|
case "bipush": {
|
||||||
return new IntInsnNode(16, Integer.parseInt(split[1]));
|
return new IntInsnNode(16, (byte) Integer.parseInt(split[1]));
|
||||||
}
|
}
|
||||||
case "sipush": {
|
case "sipush": {
|
||||||
return new IntInsnNode(17, Integer.parseInt(split[1]));
|
return new IntInsnNode(17, (short) Integer.parseInt(split[1]));
|
||||||
}
|
}
|
||||||
case "ldc": {
|
case "ldc": {
|
||||||
String str = consolidateStrings(split, 1);
|
String str = consolidateStrings(split, 1);
|
||||||
@@ -847,7 +764,9 @@ public class Assembler {
|
|||||||
UnicodeUtils.unescape(hsr, split2[3].substring(6, split2[3].length() - 1)),
|
UnicodeUtils.unescape(hsr, split2[3].substring(6, split2[3].length() - 1)),
|
||||||
Integer.parseInt(split2[1].substring(7)), Integer.parseInt(split2[2].substring(5)));
|
Integer.parseInt(split2[1].substring(7)), Integer.parseInt(split2[2].substring(5)));
|
||||||
} else if (str.startsWith("\"") && str.endsWith("\"")) {
|
} else if (str.startsWith("\"") && str.endsWith("\"")) {
|
||||||
val = UnicodeUtils.unescape(hsr, str.substring(1, str.length() - 1));
|
val = UnicodeUtils.unescape(hsr, str.substring(1, str.length() - 1), true);
|
||||||
|
} else if (str.startsWith("#")) {
|
||||||
|
val = UnicodeUtils.unescape(hsr, str);
|
||||||
} else if (str.endsWith("l")) {
|
} else if (str.endsWith("l")) {
|
||||||
val = Long.parseLong(str.substring(0, str.length() - 1));
|
val = Long.parseLong(str.substring(0, str.length() - 1));
|
||||||
} else if (str.endsWith("f")) {
|
} else if (str.endsWith("f")) {
|
||||||
@@ -1637,4 +1556,48 @@ public class Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Object[] parseFrameList(HugeStringsRev hsr, String str, HashMap<LabelNode, Integer> labels) {
|
||||||
|
ArrayList<Object> list = new ArrayList<>();
|
||||||
|
String l = str.substring(1, str.length() - 1);
|
||||||
|
if (l.isEmpty()) {
|
||||||
|
return new Object[0];
|
||||||
|
} else {
|
||||||
|
for (String asd : l.split(", ")) {
|
||||||
|
if (!asd.startsWith("(")) {
|
||||||
|
int frameType = ClassUtil.getFrameTypeByName(asd);
|
||||||
|
if (frameType != -1)
|
||||||
|
list.add(new Integer(frameType));
|
||||||
|
else
|
||||||
|
list.add(UnicodeUtils.unescape(hsr, asd.substring(1, asd.length() - 1)));
|
||||||
|
} else {
|
||||||
|
if (asd.startsWith("(label) ")) {
|
||||||
|
int labelNr = Integer.parseInt(asd.split(" ")[1]);
|
||||||
|
boolean found = false;
|
||||||
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
|
if (entry.getValue() == labelNr) {
|
||||||
|
list.add(entry.getKey());
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
LabelNode ln = new LabelNode(new Label());
|
||||||
|
labels.put(ln, labelNr);
|
||||||
|
list.add(ln);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list.add(ClassUtil.getCastedValue(asd.split(" ")[1], asd.split("\\) ")[0].substring(1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object[] arr = new Object[list.size()];
|
||||||
|
int c = 0;
|
||||||
|
for (Object o : list) {
|
||||||
|
arr[c] = o;
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,22 @@
|
|||||||
package me.ByteEdit.edit;
|
package me.ByteEdit.edit;
|
||||||
|
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.FIELD_INSN;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.FRAME;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.IINC_INSN;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.INSN;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.INT_INSN;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.INVOKE_DYNAMIC_INSN;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.JUMP_INSN;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.LABEL;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.LDC_INSN;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.LINE;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.LOOKUPSWITCH_INSN;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.METHOD_INSN;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.MULTIANEWARRAY_INSN;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.TABLESWITCH_INSN;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.TYPE_INSN;
|
||||||
|
import static org.objectweb.asm.tree.AbstractInsnNode.VAR_INSN;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -9,6 +26,7 @@ import java.util.concurrent.ExecutionException;
|
|||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.FutureTask;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import org.objectweb.asm.Handle;
|
import org.objectweb.asm.Handle;
|
||||||
@@ -23,7 +41,7 @@ import org.objectweb.asm.tree.FieldNode;
|
|||||||
import org.objectweb.asm.tree.FrameNode;
|
import org.objectweb.asm.tree.FrameNode;
|
||||||
import org.objectweb.asm.tree.IincInsnNode;
|
import org.objectweb.asm.tree.IincInsnNode;
|
||||||
import org.objectweb.asm.tree.InnerClassNode;
|
import org.objectweb.asm.tree.InnerClassNode;
|
||||||
import org.objectweb.asm.tree.InsnNode;
|
import org.objectweb.asm.tree.InsnList;
|
||||||
import org.objectweb.asm.tree.IntInsnNode;
|
import org.objectweb.asm.tree.IntInsnNode;
|
||||||
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
|
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
|
||||||
import org.objectweb.asm.tree.JumpInsnNode;
|
import org.objectweb.asm.tree.JumpInsnNode;
|
||||||
@@ -40,6 +58,7 @@ import org.objectweb.asm.tree.TryCatchBlockNode;
|
|||||||
import org.objectweb.asm.tree.TypeInsnNode;
|
import org.objectweb.asm.tree.TypeInsnNode;
|
||||||
import org.objectweb.asm.tree.VarInsnNode;
|
import org.objectweb.asm.tree.VarInsnNode;
|
||||||
|
|
||||||
|
import me.ByteEdit.main.Main;
|
||||||
import me.ByteEdit.utils.ClassUtil;
|
import me.ByteEdit.utils.ClassUtil;
|
||||||
import me.ByteEdit.utils.OpcodesReverse;
|
import me.ByteEdit.utils.OpcodesReverse;
|
||||||
import me.ByteEdit.utils.UnicodeUtils;
|
import me.ByteEdit.utils.UnicodeUtils;
|
||||||
@@ -215,10 +234,11 @@ public class Disassembler {
|
|||||||
|
|
||||||
private static String doMethods(List<MethodNode> methods, String className, Object nodeToFind,
|
private static String doMethods(List<MethodNode> methods, String className, Object nodeToFind,
|
||||||
AtomicInteger lineFound, HugeStrings hs) throws InterruptedException, ExecutionException {
|
AtomicInteger lineFound, HugeStrings hs) throws InterruptedException, ExecutionException {
|
||||||
|
boolean multithreaded = Main.INSTANCE.mntmMultithreaded.isSelected();
|
||||||
Future<String>[] futures = new Future[methods.size()];
|
Future<String>[] futures = new Future[methods.size()];
|
||||||
for (int i = 0; i < futures.length; i++) {
|
for (int i = 0; i < futures.length; i++) {
|
||||||
MethodNode mn = methods.get(i);
|
MethodNode mn = methods.get(i);
|
||||||
futures[i] = exec.submit(new Callable<String>() {
|
Callable<String> callable = new Callable<String>() {
|
||||||
@Override
|
@Override
|
||||||
public String call() throws Exception {
|
public String call() throws Exception {
|
||||||
String ms = "";
|
String ms = "";
|
||||||
@@ -318,10 +338,13 @@ public class Disassembler {
|
|||||||
}
|
}
|
||||||
return ms;
|
return ms;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
futures[i] = multithreaded ? exec.submit(callable) : new FutureTask<>(callable);
|
||||||
}
|
}
|
||||||
StringContext ctx = new StringContext(futures.length);
|
StringContext ctx = new StringContext(futures.length);
|
||||||
for (Future<String> f : futures) {
|
for (Future<String> f : futures) {
|
||||||
|
if (f instanceof FutureTask)
|
||||||
|
((FutureTask) f).run();
|
||||||
ctx.next(f.get());
|
ctx.next(f.get());
|
||||||
}
|
}
|
||||||
String s = ctx.finish();
|
String s = ctx.finish();
|
||||||
@@ -413,9 +436,18 @@ public class Disassembler {
|
|||||||
HashMap<Label, Integer> labels = new HashMap<Label, Integer>();
|
HashMap<Label, Integer> labels = new HashMap<Label, Integer>();
|
||||||
String localVarTable;
|
String localVarTable;
|
||||||
String tryCatchTable;
|
String tryCatchTable;
|
||||||
for (AbstractInsnNode n : mn.instructions.toArray()) {
|
|
||||||
|
InsnList insnList = mn.instructions;
|
||||||
|
boolean deobfNumbers = Main.INSTANCE.mntmNumbers.isSelected();
|
||||||
|
|
||||||
|
ArrayList<Label> labelsReversed = deobfNumbers ? new ArrayList<>() : null;
|
||||||
|
|
||||||
|
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
||||||
if (n instanceof LabelNode) {
|
if (n instanceof LabelNode) {
|
||||||
labels.put(((LabelNode) n).getLabel(), labels.size() + 1);
|
int id = labels.size() + 1;
|
||||||
|
if (deobfNumbers)
|
||||||
|
labelsReversed.add(((LabelNode) n).getLabel());
|
||||||
|
labels.put(((LabelNode) n).getLabel(), id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mn.localVariables != null && !mn.localVariables.isEmpty()) {
|
if (mn.localVariables != null && !mn.localVariables.isEmpty()) {
|
||||||
@@ -443,110 +475,62 @@ public class Disassembler {
|
|||||||
tryCatchTable = ctx.finish();
|
tryCatchTable = ctx.finish();
|
||||||
} else
|
} else
|
||||||
tryCatchTable = "";
|
tryCatchTable = "";
|
||||||
AbstractInsnNode[] insns = mn.instructions.toArray();
|
|
||||||
StringContext ctx = new StringContext(insns.length);
|
if (deobfNumbers) {
|
||||||
for (AbstractInsnNode n : insns) {
|
StackBasedCalculator calc = new StackBasedCalculator(insnList);
|
||||||
|
calc.run();
|
||||||
|
insnList = calc.get();
|
||||||
|
int i = 0;
|
||||||
|
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
||||||
|
if (n instanceof LabelNode) {
|
||||||
|
((LabelNode) n).setLabel(labelsReversed.get(i++));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringContext ctx = new StringContext(insnList.size());
|
||||||
|
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
||||||
ctx.next(disassembleInstruction(n, labels, hs));
|
ctx.next(disassembleInstruction(n, labels, hs));
|
||||||
}
|
}
|
||||||
return new String[] { ctx.finish(), localVarTable, tryCatchTable };
|
return new String[] { ctx.finish(), localVarTable, tryCatchTable };
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final HashMap<Class, InstructionInterface> iiMap = new HashMap<>();
|
public static String disassembleInstruction(AbstractInsnNode n, HashMap<Label, Integer> labels, HugeStrings hs) {
|
||||||
|
switch (n.getType()) {
|
||||||
static {
|
case INSN: {
|
||||||
iiMap.put(FieldInsnNode.class, (n, labels, hs) -> {
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + "\n";
|
||||||
|
}
|
||||||
|
case INT_INSN: {
|
||||||
|
IntInsnNode node = (IntInsnNode) n;
|
||||||
|
if (n.getOpcode() == Opcodes.NEWARRAY) {
|
||||||
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
|
||||||
|
+ ClassUtil.getArrayTypeByID(node.operand) + "\n";
|
||||||
|
} else {
|
||||||
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.operand + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case VAR_INSN: {
|
||||||
|
VarInsnNode node = (VarInsnNode) n;
|
||||||
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + "\n";
|
||||||
|
}
|
||||||
|
case TYPE_INSN: {
|
||||||
|
TypeInsnNode node = (TypeInsnNode) n;
|
||||||
|
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
||||||
|
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + "\n";
|
||||||
|
}
|
||||||
|
case FIELD_INSN: {
|
||||||
FieldInsnNode node = (FieldInsnNode) n;
|
FieldInsnNode node = (FieldInsnNode) n;
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
||||||
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + UnicodeUtils.escapeWithSpaces(hs, node.owner)
|
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + UnicodeUtils.escapeWithSpaces(hs, node.owner)
|
||||||
+ "/" + UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n";
|
+ "/" + UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n";
|
||||||
});
|
}
|
||||||
iiMap.put(LabelNode.class, (n, labels, hs) -> {
|
case METHOD_INSN: {
|
||||||
LabelNode node = (LabelNode) n;
|
MethodInsnNode node = (MethodInsnNode) n;
|
||||||
return "\t\t// label " + labels.get(node.getLabel()) + "\n";
|
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
||||||
});
|
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + UnicodeUtils.escapeWithSpaces(hs, node.owner)
|
||||||
iiMap.put(FrameNode.class, (n, labels, hs) -> {
|
+ "/" + UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n";
|
||||||
FrameNode node = (FrameNode) n;
|
}
|
||||||
String type = "";
|
case INVOKE_DYNAMIC_INSN: {
|
||||||
switch (node.type) {
|
|
||||||
case Opcodes.F_NEW:
|
|
||||||
type = "NEW";
|
|
||||||
break;
|
|
||||||
case Opcodes.F_FULL:
|
|
||||||
type = "FULL";
|
|
||||||
break;
|
|
||||||
case Opcodes.F_APPEND:
|
|
||||||
type = "APPEND";
|
|
||||||
break;
|
|
||||||
case Opcodes.F_CHOP:
|
|
||||||
type = "CHOP";
|
|
||||||
break;
|
|
||||||
case Opcodes.F_SAME:
|
|
||||||
type = "SAME";
|
|
||||||
break;
|
|
||||||
case Opcodes.F_SAME1:
|
|
||||||
type = "SAME1";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
String s = "\t\t// frame " + type + " l:";
|
|
||||||
ArrayList<String> arr = new ArrayList<>();
|
|
||||||
if (node.local != null) {
|
|
||||||
for (Object o : node.local) {
|
|
||||||
if (o == null) {
|
|
||||||
arr.add(null);
|
|
||||||
} else {
|
|
||||||
if (o instanceof String) {
|
|
||||||
arr.add("\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"");
|
|
||||||
} else if (o instanceof LabelNode) {
|
|
||||||
arr.add("(label) " + labels.get(((LabelNode) o).getLabel()));
|
|
||||||
} else if (o instanceof Integer) {
|
|
||||||
String frameType = ClassUtil.getFrameTypeByID(((Integer) o).intValue());
|
|
||||||
if (frameType != null)
|
|
||||||
arr.add(frameType);
|
|
||||||
else
|
|
||||||
arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o);
|
|
||||||
} else {
|
|
||||||
arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s += arr.toString();
|
|
||||||
} else {
|
|
||||||
s += "null";
|
|
||||||
}
|
|
||||||
arr.clear();
|
|
||||||
s += " s:";
|
|
||||||
if (node.stack != null) {
|
|
||||||
for (Object o : node.stack) {
|
|
||||||
if (o == null) {
|
|
||||||
arr.add(null);
|
|
||||||
} else {
|
|
||||||
if (o instanceof String) {
|
|
||||||
arr.add("\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"");
|
|
||||||
} else if (o instanceof LabelNode) {
|
|
||||||
arr.add("(label) " + labels.get(((LabelNode) o).getLabel()));
|
|
||||||
} else if (o instanceof Integer) {
|
|
||||||
String frameType = ClassUtil.getFrameTypeByID(((Integer) o).intValue());
|
|
||||||
if (frameType != null)
|
|
||||||
arr.add(frameType);
|
|
||||||
else
|
|
||||||
arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o);
|
|
||||||
} else {
|
|
||||||
arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s += arr.toString();
|
|
||||||
} else {
|
|
||||||
s += "null";
|
|
||||||
}
|
|
||||||
s += "\n";
|
|
||||||
return s;
|
|
||||||
});
|
|
||||||
iiMap.put(LineNumberNode.class, (n, labels, hs) -> {
|
|
||||||
LineNumberNode node = (LineNumberNode) n;
|
|
||||||
return "\t\t// line " + node.line + " " + labels.get(node.start.getLabel()) + "\n";
|
|
||||||
});
|
|
||||||
iiMap.put(InvokeDynamicInsnNode.class, (n, labels, hs) -> {
|
|
||||||
InvokeDynamicInsnNode node = (InvokeDynamicInsnNode) n;
|
InvokeDynamicInsnNode node = (InvokeDynamicInsnNode) n;
|
||||||
String s = "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " [\n\t\t\tname: "
|
String s = "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " [\n\t\t\tname: "
|
||||||
+ UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n\t\t\tdesc: "
|
+ UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n\t\t\tdesc: "
|
||||||
@@ -582,24 +566,17 @@ public class Disassembler {
|
|||||||
}
|
}
|
||||||
s += "\t\t\t]\n\t\t]\n";
|
s += "\t\t\t]\n\t\t]\n";
|
||||||
return s;
|
return s;
|
||||||
});
|
}
|
||||||
iiMap.put(MethodInsnNode.class, (n, labels, hs) -> {
|
case JUMP_INSN: {
|
||||||
MethodInsnNode node = (MethodInsnNode) n;
|
JumpInsnNode node = (JumpInsnNode) n;
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + labels.get(node.label.getLabel())
|
||||||
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + UnicodeUtils.escapeWithSpaces(hs, node.owner)
|
+ "\n";
|
||||||
+ "/" + UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n";
|
}
|
||||||
});
|
case LABEL: {
|
||||||
iiMap.put(TypeInsnNode.class, (n, labels, hs) -> {
|
LabelNode node = (LabelNode) n;
|
||||||
TypeInsnNode node = (TypeInsnNode) n;
|
return "\t\t// label " + labels.get(node.getLabel()) + "\n";
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
}
|
||||||
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + "\n";
|
case LDC_INSN: {
|
||||||
});
|
|
||||||
iiMap.put(MultiANewArrayInsnNode.class, (n, labels, hs) -> {
|
|
||||||
MultiANewArrayInsnNode node = (MultiANewArrayInsnNode) n;
|
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
|
||||||
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + node.dims + "\n";
|
|
||||||
});
|
|
||||||
iiMap.put(LdcInsnNode.class, (n, labels, hs) -> {
|
|
||||||
LdcInsnNode node = (LdcInsnNode) n;
|
LdcInsnNode node = (LdcInsnNode) n;
|
||||||
if (node.cst instanceof Type) {
|
if (node.cst instanceof Type) {
|
||||||
Type type = (Type) node.cst;
|
Type type = (Type) node.cst;
|
||||||
@@ -613,33 +590,21 @@ public class Disassembler {
|
|||||||
s += "\n\t\t]\n";
|
s += "\n\t\t]\n";
|
||||||
return s;
|
return s;
|
||||||
} else {
|
} else {
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
String decomp = ClassUtil.getDecompiledValue(node.cst, "", hs);
|
||||||
+ ClassUtil.getDecompiledValue(node.cst, "", hs) + "\n";
|
if (node.cst instanceof String) {
|
||||||
|
if (decomp.startsWith("\"#") && decomp.endsWith("\""))
|
||||||
|
decomp = decomp.substring(1, decomp.length() - 1);
|
||||||
|
else if (decomp.startsWith("\"\\u0023"))
|
||||||
|
decomp = "\"#" + decomp.substring(7);
|
||||||
|
}
|
||||||
|
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + decomp + "\n";
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
iiMap.put(VarInsnNode.class, (n, labels, hs) -> {
|
case IINC_INSN: {
|
||||||
VarInsnNode node = (VarInsnNode) n;
|
IincInsnNode node = (IincInsnNode) n;
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + "\n";
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + " " + node.incr + "\n";
|
||||||
});
|
}
|
||||||
iiMap.put(InsnNode.class, (n, labels, hs) -> {
|
case TABLESWITCH_INSN: {
|
||||||
InsnNode node = (InsnNode) n;
|
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + "\n";
|
|
||||||
});
|
|
||||||
iiMap.put(IntInsnNode.class, (n, labels, hs) -> {
|
|
||||||
IntInsnNode node = (IntInsnNode) n;
|
|
||||||
if (n.getOpcode() == Opcodes.NEWARRAY) {
|
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
|
|
||||||
+ ClassUtil.getArrayTypeByID(node.operand) + "\n";
|
|
||||||
} else {
|
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.operand + "\n";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
iiMap.put(JumpInsnNode.class, (n, labels, hs) -> {
|
|
||||||
JumpInsnNode node = (JumpInsnNode) n;
|
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + labels.get(node.label.getLabel())
|
|
||||||
+ "\n";
|
|
||||||
});
|
|
||||||
iiMap.put(TableSwitchInsnNode.class, (n, labels, hs) -> {
|
|
||||||
TableSwitchInsnNode node = (TableSwitchInsnNode) n;
|
TableSwitchInsnNode node = (TableSwitchInsnNode) n;
|
||||||
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tmin: " + node.min
|
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tmin: " + node.min
|
||||||
+ "\n\t\t\tmax: " + node.max + "\n\t\t\tdefault: " + labels.get(node.dflt.getLabel())
|
+ "\n\t\t\tmax: " + node.max + "\n\t\t\tdefault: " + labels.get(node.dflt.getLabel())
|
||||||
@@ -649,8 +614,8 @@ public class Disassembler {
|
|||||||
}
|
}
|
||||||
s += "\t\t\t]\n\t\t]\n";
|
s += "\t\t\t]\n\t\t]\n";
|
||||||
return s;
|
return s;
|
||||||
});
|
}
|
||||||
iiMap.put(LookupSwitchInsnNode.class, (n, labels, hs) -> {
|
case LOOKUPSWITCH_INSN: {
|
||||||
LookupSwitchInsnNode node = (LookupSwitchInsnNode) n;
|
LookupSwitchInsnNode node = (LookupSwitchInsnNode) n;
|
||||||
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tdefault: "
|
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tdefault: "
|
||||||
+ labels.get(node.dflt.getLabel()) + "\n\t\t\tkeys: [\n";
|
+ labels.get(node.dflt.getLabel()) + "\n\t\t\tkeys: [\n";
|
||||||
@@ -663,24 +628,70 @@ public class Disassembler {
|
|||||||
}
|
}
|
||||||
s += "\t\t\t]\n\t\t]\n";
|
s += "\t\t\t]\n\t\t]\n";
|
||||||
return s;
|
return s;
|
||||||
});
|
}
|
||||||
iiMap.put(IincInsnNode.class, (n, labels, hs) -> {
|
case MULTIANEWARRAY_INSN: {
|
||||||
IincInsnNode node = (IincInsnNode) n;
|
MultiANewArrayInsnNode node = (MultiANewArrayInsnNode) n;
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + " " + node.incr + "\n";
|
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
||||||
});
|
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + node.dims + "\n";
|
||||||
}
|
}
|
||||||
|
case FRAME: {
|
||||||
static interface InstructionInterface {
|
FrameNode node = (FrameNode) n;
|
||||||
String apply(AbstractInsnNode n, HashMap<Label, Integer> labels, HugeStrings hs);
|
String out = "";
|
||||||
}
|
switch (node.type) {
|
||||||
|
case Opcodes.F_SAME:
|
||||||
public static String disassembleInstruction(AbstractInsnNode n, HashMap<Label, Integer> labels, HugeStrings hs) {
|
out = "SAME";
|
||||||
InstructionInterface ii = iiMap.get(n.getClass());
|
break;
|
||||||
if (ii != null)
|
case Opcodes.F_SAME1:
|
||||||
return ii.apply(n, labels, hs);
|
out = "SAME1 " + getFrameArray(hs, node.stack, labels);
|
||||||
else
|
break;
|
||||||
|
case Opcodes.F_CHOP:
|
||||||
|
out = "CHOP " + Integer.toString(node.local.size());
|
||||||
|
break;
|
||||||
|
case Opcodes.F_APPEND:
|
||||||
|
out = "APPEND " + getFrameArray(hs, node.local, labels);
|
||||||
|
break;
|
||||||
|
case Opcodes.F_FULL:
|
||||||
|
out = "FULL " + getFrameArray(hs, node.local, labels) + " " + getFrameArray(hs, node.stack, labels);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "\t\t// frame " + out + "\n";
|
||||||
|
}
|
||||||
|
case LINE: {
|
||||||
|
LineNumberNode node = (LineNumberNode) n;
|
||||||
|
return "\t\t// line " + node.line + " " + labels.get(node.start.getLabel()) + "\n";
|
||||||
|
}
|
||||||
|
default: {
|
||||||
return "\t\tNOT HANDLED! " + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
|
return "\t\tNOT HANDLED! " + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
|
||||||
+ n.getClass().getSimpleName() + "\n";
|
+ n.getClass().getSimpleName() + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getFrameArray(HugeStrings hs, List<Object> list, HashMap<Label, Integer> labels) {
|
||||||
|
ArrayList<String> arr = new ArrayList<>();
|
||||||
|
if (list != null) {
|
||||||
|
for (Object o : list) {
|
||||||
|
if (o == null) {
|
||||||
|
arr.add(null);
|
||||||
|
} else {
|
||||||
|
if (o instanceof String) {
|
||||||
|
arr.add("\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"");
|
||||||
|
} else if (o instanceof LabelNode) {
|
||||||
|
arr.add("(label) " + labels.get(((LabelNode) o).getLabel()));
|
||||||
|
} else if (o instanceof Integer) {
|
||||||
|
String frameType = ClassUtil.getFrameTypeByID(((Integer) o).intValue());
|
||||||
|
if (frameType != null)
|
||||||
|
arr.add(frameType);
|
||||||
|
else
|
||||||
|
arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o);
|
||||||
|
} else {
|
||||||
|
arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr.toString();
|
||||||
|
}
|
||||||
|
return "null";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ import me.ByteEdit.utils.UnicodeUtils;
|
|||||||
|
|
||||||
public class HugeStrings {
|
public class HugeStrings {
|
||||||
|
|
||||||
public static final int THRESHOLD = 1000;
|
public static int THRESHOLD = 1000;
|
||||||
private final HashMap<String, HugeData> map = new HashMap<>();
|
private final HashMap<String, HugeData> map = new HashMap<>();
|
||||||
|
|
||||||
public String onString(String s) {
|
public String onString(String s) {
|
||||||
|
|||||||
@@ -0,0 +1,689 @@
|
|||||||
|
package me.ByteEdit.edit;
|
||||||
|
|
||||||
|
import java.util.EmptyStackException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||||
|
import org.objectweb.asm.tree.InsnList;
|
||||||
|
import org.objectweb.asm.tree.InsnNode;
|
||||||
|
import org.objectweb.asm.tree.IntInsnNode;
|
||||||
|
import org.objectweb.asm.tree.LabelNode;
|
||||||
|
import org.objectweb.asm.tree.LdcInsnNode;
|
||||||
|
|
||||||
|
public class StackBasedCalculator implements Opcodes, Runnable {
|
||||||
|
|
||||||
|
private final InsnList insns;
|
||||||
|
private final Stack<Number> stack = new Stack<>();
|
||||||
|
private AbstractInsnNode start;
|
||||||
|
private int startIdx = -1;
|
||||||
|
private boolean isAtEnd = false;
|
||||||
|
|
||||||
|
public StackBasedCalculator(InsnList insns) {
|
||||||
|
this.insns = new InsnList();
|
||||||
|
|
||||||
|
HashMap<LabelNode, LabelNode> labelMap = new HashMap<>();
|
||||||
|
for (AbstractInsnNode node = insns.getFirst(); node != null; node = node.getNext()) {
|
||||||
|
if (node.getType() == AbstractInsnNode.LABEL) {
|
||||||
|
labelMap.put((LabelNode) node, new LabelNode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AbstractInsnNode node = insns.getFirst(); node != null; node = node.getNext()) {
|
||||||
|
this.insns.add(node.clone(labelMap));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public InsnList get() {
|
||||||
|
return insns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (!isAtEnd) {
|
||||||
|
out: {
|
||||||
|
AbstractInsnNode[] arr = insns.toArray();
|
||||||
|
for (int i = startIdx == -1 ? 0 : startIdx; i < arr.length; i++) {
|
||||||
|
if (!handle(arr[i]))
|
||||||
|
break out;
|
||||||
|
}
|
||||||
|
isAtEnd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean handle(AbstractInsnNode node) {
|
||||||
|
try {
|
||||||
|
switch (node.getOpcode()) {
|
||||||
|
case ICONST_0:
|
||||||
|
stack.push(Integer.valueOf(0));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case ICONST_1:
|
||||||
|
stack.push(Integer.valueOf(1));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case ICONST_2:
|
||||||
|
stack.push(Integer.valueOf(2));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case ICONST_3:
|
||||||
|
stack.push(Integer.valueOf(3));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case ICONST_4:
|
||||||
|
stack.push(Integer.valueOf(4));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case ICONST_5:
|
||||||
|
stack.push(Integer.valueOf(5));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case ICONST_M1:
|
||||||
|
stack.push(Integer.valueOf(-1));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case DCONST_0:
|
||||||
|
stack.push(Double.valueOf(0));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case DCONST_1:
|
||||||
|
stack.push(Double.valueOf(1));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case FCONST_0:
|
||||||
|
stack.push(Float.valueOf(0));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case FCONST_1:
|
||||||
|
stack.push(Float.valueOf(1));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case FCONST_2:
|
||||||
|
stack.push(Float.valueOf(2));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case LCONST_0:
|
||||||
|
stack.push(Long.valueOf(0));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case LCONST_1:
|
||||||
|
stack.push(Long.valueOf(1));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case BIPUSH:
|
||||||
|
case SIPUSH:
|
||||||
|
stack.push(((IntInsnNode) node).operand);
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case D2F:
|
||||||
|
stack.push(((Double) stack.pop()).floatValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case D2I:
|
||||||
|
stack.push(((Double) stack.pop()).intValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case D2L:
|
||||||
|
stack.push(((Double) stack.pop()).longValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case F2D:
|
||||||
|
stack.push(((Float) stack.pop()).doubleValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case F2I:
|
||||||
|
stack.push(((Float) stack.pop()).intValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case F2L:
|
||||||
|
stack.push(((Float) stack.pop()).longValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case L2D:
|
||||||
|
stack.push(((Long) stack.pop()).doubleValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case L2F:
|
||||||
|
stack.push(((Long) stack.pop()).floatValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case L2I:
|
||||||
|
stack.push(((Long) stack.pop()).intValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case I2B:
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
case I2C:
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
case I2D:
|
||||||
|
stack.push(((Integer) stack.pop()).doubleValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case I2F:
|
||||||
|
stack.push(((Integer) stack.pop()).floatValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case I2L:
|
||||||
|
stack.push(((Integer) stack.pop()).longValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case I2S:
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
case NOP:
|
||||||
|
break;
|
||||||
|
case LDC:
|
||||||
|
LdcInsnNode ldc = (LdcInsnNode) node;
|
||||||
|
if (ldc.cst instanceof Number) {
|
||||||
|
stack.push((Number) ldc.cst);
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
} else {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// long
|
||||||
|
case LADD: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom + top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LSUB: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom - top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LMUL: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom * top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LDIV: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom / top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LREM: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom % top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LNEG: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(-top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LAND: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom & top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LOR: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom | top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LXOR: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom ^ top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LSHR: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom >> top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LSHL: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom << top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LUSHR: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom >>> top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// int
|
||||||
|
case IADD: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom + top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case ISUB: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom - top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IMUL: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom * top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IDIV: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom / top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IREM: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom % top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case INEG: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(-top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IAND: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom & top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IOR: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom | top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IXOR: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom ^ top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case ISHR: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom >> top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case ISHL: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom << top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IUSHR: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom >>> top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// double
|
||||||
|
case DADD: {
|
||||||
|
double top = ((Double) stack.pop()).doubleValue();
|
||||||
|
double bottom = ((Double) stack.pop()).doubleValue();
|
||||||
|
stack.push(bottom + top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DSUB: {
|
||||||
|
double top = ((Double) stack.pop()).doubleValue();
|
||||||
|
double bottom = ((Double) stack.pop()).doubleValue();
|
||||||
|
stack.push(bottom - top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DMUL: {
|
||||||
|
double top = ((Double) stack.pop()).doubleValue();
|
||||||
|
double bottom = ((Double) stack.pop()).doubleValue();
|
||||||
|
stack.push(bottom * top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DDIV: {
|
||||||
|
double top = ((Double) stack.pop()).doubleValue();
|
||||||
|
double bottom = ((Double) stack.pop()).doubleValue();
|
||||||
|
stack.push(bottom / top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DREM: {
|
||||||
|
double top = ((Double) stack.pop()).doubleValue();
|
||||||
|
double bottom = ((Double) stack.pop()).doubleValue();
|
||||||
|
stack.push(bottom % top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DNEG: {
|
||||||
|
double top = ((Double) stack.pop()).doubleValue();
|
||||||
|
stack.push(-top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// float
|
||||||
|
case FADD: {
|
||||||
|
float top = ((Float) stack.pop()).floatValue();
|
||||||
|
float bottom = ((Float) stack.pop()).floatValue();
|
||||||
|
stack.push(bottom + top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case FSUB: {
|
||||||
|
float top = ((Float) stack.pop()).floatValue();
|
||||||
|
float bottom = ((Float) stack.pop()).floatValue();
|
||||||
|
stack.push(bottom - top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case FMUL: {
|
||||||
|
float top = ((Float) stack.pop()).floatValue();
|
||||||
|
float bottom = ((Float) stack.pop()).floatValue();
|
||||||
|
stack.push(bottom * top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case FDIV: {
|
||||||
|
float top = ((Float) stack.pop()).floatValue();
|
||||||
|
float bottom = ((Float) stack.pop()).floatValue();
|
||||||
|
stack.push(bottom / top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case FREM: {
|
||||||
|
float top = ((Float) stack.pop()).floatValue();
|
||||||
|
float bottom = ((Float) stack.pop()).floatValue();
|
||||||
|
stack.push(bottom % top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case FNEG: {
|
||||||
|
float top = ((Float) stack.pop()).floatValue();
|
||||||
|
stack.push(-top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// dup
|
||||||
|
case DUP: {
|
||||||
|
Number num = stack.pop();
|
||||||
|
if (num instanceof Double || num instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
stack.push(num);
|
||||||
|
stack.push(num);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DUP_X1: {
|
||||||
|
Number top = stack.pop();
|
||||||
|
Number bottom = stack.pop();
|
||||||
|
if (bottom instanceof Double || bottom instanceof Long || top instanceof Double
|
||||||
|
|| top instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
stack.push(top);
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DUP_X2: {
|
||||||
|
Number top = stack.pop();
|
||||||
|
Number bottom = stack.pop();
|
||||||
|
if (top instanceof Double || top instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Number bottom2 = null;
|
||||||
|
if (!(bottom instanceof Double || bottom instanceof Long)) {
|
||||||
|
bottom2 = stack.pop();
|
||||||
|
if (bottom instanceof Double || bottom instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stack.push(top);
|
||||||
|
if (bottom2 != null)
|
||||||
|
stack.push(bottom2);
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DUP2: {
|
||||||
|
Number top = stack.pop();
|
||||||
|
Number bottom = null;
|
||||||
|
if (!(top instanceof Double || top instanceof Long)) {
|
||||||
|
bottom = stack.pop();
|
||||||
|
if (bottom instanceof Double || bottom instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bottom != null)
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
if (bottom != null)
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DUP2_X1: {
|
||||||
|
Number top = stack.pop();
|
||||||
|
Number bottom = null;
|
||||||
|
if (!(top instanceof Double || top instanceof Long)) {
|
||||||
|
bottom = stack.pop();
|
||||||
|
if (bottom instanceof Double || bottom instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Number bottom2 = stack.pop();
|
||||||
|
if (bottom != null)
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
stack.push(bottom2);
|
||||||
|
if (bottom != null)
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DUP2_X2: {
|
||||||
|
Number top = stack.pop();
|
||||||
|
Number bottom = null;
|
||||||
|
if (!(top instanceof Double || top instanceof Long)) {
|
||||||
|
bottom = stack.pop();
|
||||||
|
if (bottom instanceof Double || bottom instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Number top2 = stack.pop();
|
||||||
|
Number bottom2 = null;
|
||||||
|
if (!(top2 instanceof Double || top2 instanceof Long)) {
|
||||||
|
bottom2 = stack.pop();
|
||||||
|
if (bottom2 instanceof Double || bottom2 instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bottom != null)
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
if (bottom2 != null)
|
||||||
|
stack.push(bottom2);
|
||||||
|
stack.push(top2);
|
||||||
|
if (bottom != null)
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// stack
|
||||||
|
case POP:
|
||||||
|
stack.pop();
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case POP2:
|
||||||
|
stack.pop();
|
||||||
|
stack.pop();
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case SWAP: {
|
||||||
|
Number top = stack.pop();
|
||||||
|
Number bottom = stack.pop();
|
||||||
|
if (bottom instanceof Double || bottom instanceof Long || top instanceof Double
|
||||||
|
|| top instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
stack.push(top);
|
||||||
|
stack.push(bottom);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (ClassCastException | EmptyStackException ex) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void error(AbstractInsnNode node) {
|
||||||
|
change(node.getPrevious());
|
||||||
|
stack.clear();
|
||||||
|
start = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void change(AbstractInsnNode node) {
|
||||||
|
if (start == null)
|
||||||
|
return;
|
||||||
|
int idx = insns.indexOf(start);
|
||||||
|
startIdx = idx;
|
||||||
|
int idx2 = insns.indexOf(node);
|
||||||
|
if (idx != idx2) {
|
||||||
|
for (int i = 0; i <= idx2 - idx; i++) {
|
||||||
|
insns.remove(insns.get(idx));
|
||||||
|
}
|
||||||
|
while (!stack.isEmpty()) {
|
||||||
|
addNode(idx, stack.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stack.clear();
|
||||||
|
start = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addNode(int idx, Number n) {
|
||||||
|
if (n instanceof Double) {
|
||||||
|
double val = n.doubleValue();
|
||||||
|
if (val == 0.0)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(DCONST_0));
|
||||||
|
else if (val == 1.0)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(DCONST_1));
|
||||||
|
else
|
||||||
|
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
|
||||||
|
} else if (n instanceof Float) {
|
||||||
|
float val = n.floatValue();
|
||||||
|
if (val == 0.0f)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(FCONST_0));
|
||||||
|
else if (val == 1.0f)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(FCONST_1));
|
||||||
|
else if (val == 2.0f)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(FCONST_2));
|
||||||
|
else
|
||||||
|
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
|
||||||
|
} else if (n instanceof Long) {
|
||||||
|
long val = n.longValue();
|
||||||
|
if (val == 0l)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(LCONST_0));
|
||||||
|
else if (val == 1l)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(LCONST_1));
|
||||||
|
else
|
||||||
|
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
|
||||||
|
} else if (n instanceof Integer) {
|
||||||
|
int val = n.intValue();
|
||||||
|
if (val == 0)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_0));
|
||||||
|
else if (val == 1)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_1));
|
||||||
|
else if (val == 2)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_2));
|
||||||
|
else if (val == 3)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_3));
|
||||||
|
else if (val == 4)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_4));
|
||||||
|
else if (val == 5)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_5));
|
||||||
|
else if (val == -1)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_M1));
|
||||||
|
else if (val == (byte) val)
|
||||||
|
insns.insertBefore(insns.get(idx), new IntInsnNode(BIPUSH, (byte) val));
|
||||||
|
else if (val == (short) val)
|
||||||
|
insns.insertBefore(insns.get(idx), new IntInsnNode(SIPUSH, (short) val));
|
||||||
|
else
|
||||||
|
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unexpected number: " + n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+184
-27
@@ -17,11 +17,14 @@ import java.awt.event.ActionEvent;
|
|||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.KeyAdapter;
|
import java.awt.event.KeyAdapter;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.StringReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -37,6 +40,8 @@ import java.util.regex.Matcher;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.swing.ButtonGroup;
|
||||||
|
import javax.swing.JCheckBoxMenuItem;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
@@ -46,6 +51,7 @@ import javax.swing.JMenuBar;
|
|||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JRadioButtonMenuItem;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JSplitPane;
|
import javax.swing.JSplitPane;
|
||||||
import javax.swing.JTree;
|
import javax.swing.JTree;
|
||||||
@@ -72,7 +78,9 @@ import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
|||||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||||
import org.fife.ui.rsyntaxtextarea.folding.CurlyFoldParser;
|
import org.fife.ui.rsyntaxtextarea.folding.CurlyFoldParser;
|
||||||
import org.fife.ui.rsyntaxtextarea.folding.FoldParserManager;
|
import org.fife.ui.rsyntaxtextarea.folding.FoldParserManager;
|
||||||
|
import org.fife.ui.rtextarea.RTextArea;
|
||||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||||
|
import org.fife.ui.rtextarea.ToolTipSupplier;
|
||||||
import org.objectweb.asm.ClassReader;
|
import org.objectweb.asm.ClassReader;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
@@ -81,7 +89,6 @@ import org.objectweb.asm.tree.MethodNode;
|
|||||||
|
|
||||||
import me.ByteEdit.boxes.CompilationBox;
|
import me.ByteEdit.boxes.CompilationBox;
|
||||||
import me.ByteEdit.boxes.GlobalSearchBox;
|
import me.ByteEdit.boxes.GlobalSearchBox;
|
||||||
import me.ByteEdit.boxes.OptionBox;
|
|
||||||
import me.ByteEdit.boxes.RenameBox;
|
import me.ByteEdit.boxes.RenameBox;
|
||||||
import me.ByteEdit.boxes.SearchBox;
|
import me.ByteEdit.boxes.SearchBox;
|
||||||
import me.ByteEdit.boxes.ThemeBox;
|
import me.ByteEdit.boxes.ThemeBox;
|
||||||
@@ -90,6 +97,7 @@ import me.ByteEdit.boxes.UnicodeBox;
|
|||||||
import me.ByteEdit.edit.Assembler;
|
import me.ByteEdit.edit.Assembler;
|
||||||
import me.ByteEdit.edit.Disassembler;
|
import me.ByteEdit.edit.Disassembler;
|
||||||
import me.ByteEdit.edit.Disassembler.DisassembleTuple;
|
import me.ByteEdit.edit.Disassembler.DisassembleTuple;
|
||||||
|
import me.ByteEdit.edit.HugeStrings;
|
||||||
import me.ByteEdit.utils.ClassUtil;
|
import me.ByteEdit.utils.ClassUtil;
|
||||||
import me.ByteEdit.utils.OpcodesReverse;
|
import me.ByteEdit.utils.OpcodesReverse;
|
||||||
import me.ByteEdit.utils.UnicodeUtils;
|
import me.ByteEdit.utils.UnicodeUtils;
|
||||||
@@ -107,7 +115,6 @@ public class Main extends JFrame {
|
|||||||
public static GlobalSearchBox globalSearchBox;
|
public static GlobalSearchBox globalSearchBox;
|
||||||
public static SearchBox searchBox;
|
public static SearchBox searchBox;
|
||||||
public static TypeOpenBox typeOpenBox;
|
public static TypeOpenBox typeOpenBox;
|
||||||
public static OptionBox optionBox;
|
|
||||||
public static UnicodeBox unicodeBox;
|
public static UnicodeBox unicodeBox;
|
||||||
public static RenameBox renameBox;
|
public static RenameBox renameBox;
|
||||||
public static CompilationBox compilationBox;
|
public static CompilationBox compilationBox;
|
||||||
@@ -116,6 +123,34 @@ public class Main extends JFrame {
|
|||||||
public static RTextScrollPane scrollPane_ByteEdit;
|
public static RTextScrollPane scrollPane_ByteEdit;
|
||||||
public static File saveFolder;
|
public static File saveFolder;
|
||||||
|
|
||||||
|
private static final Pattern SLASH = Pattern.compile("/");
|
||||||
|
private JMenuBar menuBar;
|
||||||
|
private JMenu mnFile;
|
||||||
|
private JMenuItem mntmOpenJar;
|
||||||
|
private JMenuItem mntmSaveBytecode;
|
||||||
|
private JMenuItem mntmSaveJar;
|
||||||
|
private JMenu mnWindow;
|
||||||
|
private JMenuItem mntmThemes;
|
||||||
|
private JMenuItem mntmSearchMembers;
|
||||||
|
private JMenuItem mntmSearch;
|
||||||
|
private JMenuItem mntmOpenType;
|
||||||
|
private JMenuItem mntmUnicode;
|
||||||
|
private JMenuItem mntmCompiler;
|
||||||
|
private JMenu mnSearch;
|
||||||
|
private JMenu mnOptions;
|
||||||
|
private JCheckBoxMenuItem mntmComputeFrames;
|
||||||
|
private JCheckBoxMenuItem mntmComputeMax;
|
||||||
|
private JMenu mnStringLimit;
|
||||||
|
private JRadioButtonMenuItem rdbtnmntm0;
|
||||||
|
private JMenuItem rdbtnmntm100;
|
||||||
|
private JMenuItem rdbtnmntm1000;
|
||||||
|
private JMenuItem rdbtnmntm500;
|
||||||
|
private JMenuItem rdbtnmntm5000;
|
||||||
|
private JMenuItem rdbtnmntm10000;
|
||||||
|
public JCheckBoxMenuItem mntmMultithreaded;
|
||||||
|
private JMenu mnDeobfuscation;
|
||||||
|
public JCheckBoxMenuItem mntmNumbers;
|
||||||
|
|
||||||
public static final Object treeLock = new Object();
|
public static final Object treeLock = new Object();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -196,7 +231,17 @@ public class Main extends JFrame {
|
|||||||
"// #Max: l:0 s:0\n\t// #TryCatch:\n\t// #LocalVars:\n\tpublic static method ()V {\n\t\treturn\n\t}",
|
"// #Max: l:0 s:0\n\t// #TryCatch:\n\t// #LocalVars:\n\tpublic static method ()V {\n\t\treturn\n\t}",
|
||||||
null, "<html><b><u>method</u></b><br>Creates an example method</html>"));
|
null, "<html><b><u>method</u></b><br>Creates an example method</html>"));
|
||||||
provider.addCompletion(new ShorthandCompletion(provider, "frame", "frame FULL l:[] s:[]", null,
|
provider.addCompletion(new ShorthandCompletion(provider, "frame", "frame FULL l:[] s:[]", null,
|
||||||
"<html><b><u>frame</u></b><br>Creates a stack map frame</html>"));
|
"<html><b><u>frame</u></b><br>Creates a stack map frame<br><br><b>Possible frames:</b><br><ul><li><code>SAME: same locals, empty stack</code></li><li><code>SAME1: same locals, stack has 1 entry</code></li><li><code>CHOP: same locals - k, empty stack</code></li><li><code>APPEND: same locals + k, empty stack</code></li><li><code>FULL: define locals, define stack</code></li></ul></html>"));
|
||||||
|
provider.addCompletion(new BasicCompletion(provider, "SAME", null,
|
||||||
|
"<html><b><u>Frames:</u></b><br><code>SAME</code><br><br><u>Locals:</u> same as previous<br><u>Stack:</u> empty</html>"));
|
||||||
|
provider.addCompletion(new BasicCompletion(provider, "SAME1", null,
|
||||||
|
"<html><b><u>Frames:</u></b><br><code>SAME1 [(type)]</code><br><br><u>Locals:</u> same as previous<br><u>Stack:</u> 1 entry</html>"));
|
||||||
|
provider.addCompletion(new BasicCompletion(provider, "CHOP", null,
|
||||||
|
"<html><b><u>Frames:</u></b><br><code>CHOP (int:k)</code><br><br><u>Locals:</u> removes the top <i>k</i> elements<br><u>Stack:</u> empty</html>"));
|
||||||
|
provider.addCompletion(new BasicCompletion(provider, "APPEND", null,
|
||||||
|
"<html><b><u>Frames:</u></b><br><code>APPEND [(type), (type), ...]</code><br><br><u>Locals:</u> adds the elements to the top<br><u>Stack:</u> empty</html>"));
|
||||||
|
provider.addCompletion(new BasicCompletion(provider, "FULL", null,
|
||||||
|
"<html><b><u>Frames:</u></b><br><code>FULL [(type), (type), ...] [(type), (type), ...]</code><br><i>first locals, then stack</i><br><br><u>Locals:</u> sets the elements<br><u>Stack:</u> sets the elements</html>"));
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +254,6 @@ public class Main extends JFrame {
|
|||||||
globalSearchBox = new GlobalSearchBox();
|
globalSearchBox = new GlobalSearchBox();
|
||||||
searchBox = new SearchBox();
|
searchBox = new SearchBox();
|
||||||
typeOpenBox = new TypeOpenBox();
|
typeOpenBox = new TypeOpenBox();
|
||||||
optionBox = new OptionBox();
|
|
||||||
unicodeBox = new UnicodeBox();
|
unicodeBox = new UnicodeBox();
|
||||||
renameBox = new RenameBox();
|
renameBox = new RenameBox();
|
||||||
compilationBox = new CompilationBox();
|
compilationBox = new CompilationBox();
|
||||||
@@ -217,7 +261,6 @@ public class Main extends JFrame {
|
|||||||
ThemeManager.registerFrames(globalSearchBox);
|
ThemeManager.registerFrames(globalSearchBox);
|
||||||
ThemeManager.registerFrames(searchBox);
|
ThemeManager.registerFrames(searchBox);
|
||||||
ThemeManager.registerFrames(typeOpenBox);
|
ThemeManager.registerFrames(typeOpenBox);
|
||||||
ThemeManager.registerFrames(optionBox);
|
|
||||||
ThemeManager.registerFrames(unicodeBox);
|
ThemeManager.registerFrames(unicodeBox);
|
||||||
ThemeManager.registerFrames(renameBox);
|
ThemeManager.registerFrames(renameBox);
|
||||||
ThemeManager.registerFrames(compilationBox);
|
ThemeManager.registerFrames(compilationBox);
|
||||||
@@ -278,7 +321,6 @@ public class Main extends JFrame {
|
|||||||
globalSearchBox.setVisible(false);
|
globalSearchBox.setVisible(false);
|
||||||
searchBox.setVisible(false);
|
searchBox.setVisible(false);
|
||||||
typeOpenBox.setVisible(false);
|
typeOpenBox.setVisible(false);
|
||||||
optionBox.setVisible(false);
|
|
||||||
unicodeBox.setVisible(false);
|
unicodeBox.setVisible(false);
|
||||||
renameBox.setVisible(false);
|
renameBox.setVisible(false);
|
||||||
compilationBox.setVisible(false);
|
compilationBox.setVisible(false);
|
||||||
@@ -336,6 +378,62 @@ public class Main extends JFrame {
|
|||||||
mntmCompiler = new JMenuItem("Compiler");
|
mntmCompiler = new JMenuItem("Compiler");
|
||||||
mntmCompiler.addActionListener(e -> compilationBox.setVisible(true));
|
mntmCompiler.addActionListener(e -> compilationBox.setVisible(true));
|
||||||
mnWindow.add(mntmCompiler);
|
mnWindow.add(mntmCompiler);
|
||||||
|
|
||||||
|
mnOptions = new JMenu("Options");
|
||||||
|
menuBar.add(mnOptions);
|
||||||
|
|
||||||
|
mntmComputeFrames = new JCheckBoxMenuItem("Compute Frames");
|
||||||
|
mnOptions.add(mntmComputeFrames);
|
||||||
|
|
||||||
|
mntmComputeMax = new JCheckBoxMenuItem("Compute Max");
|
||||||
|
mnOptions.add(mntmComputeMax);
|
||||||
|
|
||||||
|
mntmMultithreaded = new JCheckBoxMenuItem("Multithreaded");
|
||||||
|
mntmMultithreaded.setSelected(true);
|
||||||
|
mnOptions.add(mntmMultithreaded);
|
||||||
|
|
||||||
|
mnStringLimit = new JMenu("Huge String Limit");
|
||||||
|
mnOptions.add(mnStringLimit);
|
||||||
|
|
||||||
|
rdbtnmntm0 = new JRadioButtonMenuItem("0");
|
||||||
|
rdbtnmntm0.addActionListener(e -> HugeStrings.THRESHOLD = 0);
|
||||||
|
mnStringLimit.add(rdbtnmntm0);
|
||||||
|
|
||||||
|
rdbtnmntm100 = new JRadioButtonMenuItem("100");
|
||||||
|
rdbtnmntm100.addActionListener(e -> HugeStrings.THRESHOLD = 100);
|
||||||
|
mnStringLimit.add(rdbtnmntm100);
|
||||||
|
|
||||||
|
rdbtnmntm500 = new JRadioButtonMenuItem("500");
|
||||||
|
rdbtnmntm500.addActionListener(e -> HugeStrings.THRESHOLD = 500);
|
||||||
|
mnStringLimit.add(rdbtnmntm500);
|
||||||
|
|
||||||
|
rdbtnmntm1000 = new JRadioButtonMenuItem("1000");
|
||||||
|
rdbtnmntm1000.addActionListener(e -> HugeStrings.THRESHOLD = 1000);
|
||||||
|
rdbtnmntm1000.setSelected(true);
|
||||||
|
mnStringLimit.add(rdbtnmntm1000);
|
||||||
|
|
||||||
|
rdbtnmntm5000 = new JRadioButtonMenuItem("5000");
|
||||||
|
rdbtnmntm5000.addActionListener(e -> HugeStrings.THRESHOLD = 5000);
|
||||||
|
mnStringLimit.add(rdbtnmntm5000);
|
||||||
|
|
||||||
|
rdbtnmntm10000 = new JRadioButtonMenuItem("10000");
|
||||||
|
rdbtnmntm10000.addActionListener(e -> HugeStrings.THRESHOLD = 10000);
|
||||||
|
mnStringLimit.add(rdbtnmntm10000);
|
||||||
|
|
||||||
|
ButtonGroup group = new ButtonGroup();
|
||||||
|
group.add(rdbtnmntm0);
|
||||||
|
group.add(rdbtnmntm100);
|
||||||
|
group.add(rdbtnmntm500);
|
||||||
|
group.add(rdbtnmntm1000);
|
||||||
|
group.add(rdbtnmntm5000);
|
||||||
|
group.add(rdbtnmntm10000);
|
||||||
|
|
||||||
|
mnDeobfuscation = new JMenu("Deobfuscation");
|
||||||
|
menuBar.add(mnDeobfuscation);
|
||||||
|
|
||||||
|
mntmNumbers = new JCheckBoxMenuItem("Numbers");
|
||||||
|
mnDeobfuscation.add(mntmNumbers);
|
||||||
|
|
||||||
contentPane = new JPanel();
|
contentPane = new JPanel();
|
||||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
setContentPane(contentPane);
|
setContentPane(contentPane);
|
||||||
@@ -472,7 +570,6 @@ public class Main extends JFrame {
|
|||||||
globalSearchBox.setVisible(false);
|
globalSearchBox.setVisible(false);
|
||||||
searchBox.setVisible(false);
|
searchBox.setVisible(false);
|
||||||
typeOpenBox.setVisible(false);
|
typeOpenBox.setVisible(false);
|
||||||
optionBox.setVisible(false);
|
|
||||||
unicodeBox.setVisible(false);
|
unicodeBox.setVisible(false);
|
||||||
renameBox.setVisible(false);
|
renameBox.setVisible(false);
|
||||||
compilationBox.setVisible(false);
|
compilationBox.setVisible(false);
|
||||||
@@ -520,6 +617,84 @@ public class Main extends JFrame {
|
|||||||
txtByteEditView = new RSyntaxTextArea();
|
txtByteEditView = new RSyntaxTextArea();
|
||||||
ac.install(txtByteEditView);
|
ac.install(txtByteEditView);
|
||||||
txtByteEditView.setCodeFoldingEnabled(true);
|
txtByteEditView.setCodeFoldingEnabled(true);
|
||||||
|
// ToolTips for HugeStrings
|
||||||
|
txtByteEditView.setToolTipSupplier(new ToolTipSupplier() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getToolTipText(RTextArea textArea, MouseEvent e) {
|
||||||
|
int idx = textArea.viewToModel(e.getPoint());
|
||||||
|
if (idx < 0)
|
||||||
|
return null;
|
||||||
|
int subIdx = Math.max(idx - 15, 0);
|
||||||
|
int subLen = Math.min(30, textArea.getDocument().getLength() - subIdx);
|
||||||
|
if (subLen <= 0)
|
||||||
|
return null;
|
||||||
|
try {
|
||||||
|
String cut = textArea.getText(subIdx, subLen);
|
||||||
|
int hashIdx = -1;
|
||||||
|
for (int off = idx - subIdx; off >= 0; off--) {
|
||||||
|
if (cut.charAt(off) == '#') {
|
||||||
|
hashIdx = off;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hashIdx < 0) {
|
||||||
|
for (int off = idx - subIdx; off < cut.length(); off++) {
|
||||||
|
if (cut.charAt(off) == '#') {
|
||||||
|
hashIdx = off;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hashIdx < 0)
|
||||||
|
return null;
|
||||||
|
if (hashIdx >= 5 && cut.substring(hashIdx - 5, hashIdx).equals("ldc \"")) // ldc "#..."
|
||||||
|
return null;
|
||||||
|
int numLen = 1;
|
||||||
|
for (int i = hashIdx + 1; i < cut.length(); i++) {
|
||||||
|
if (!(cut.charAt(i) - '0' >= 0 && cut.charAt(i) - '0' <= 9)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
numLen++;
|
||||||
|
}
|
||||||
|
if (numLen < 2 || hashIdx > idx - subIdx || idx - subIdx - numLen >= hashIdx)
|
||||||
|
return null;
|
||||||
|
String hashNum = cut.substring(hashIdx, hashIdx + numLen);
|
||||||
|
|
||||||
|
String txt = txtByteEditView.getText();
|
||||||
|
int len = 0;
|
||||||
|
for (String asm : txt.split("\\/\\/ #Annotations:\n")) {
|
||||||
|
len += 19; // "\\/\\/ #Annotations:\n".length()
|
||||||
|
if (asm.isEmpty())
|
||||||
|
continue;
|
||||||
|
if (idx >= len && idx < len + asm.length()) {
|
||||||
|
try (BufferedReader reader = new BufferedReader(new StringReader(asm))) {
|
||||||
|
String s;
|
||||||
|
while (!(s = reader.readLine()).startsWith("// #SourceFile: ")) {
|
||||||
|
}
|
||||||
|
while (!(s = reader.readLine()).equals("// #Fields")) {
|
||||||
|
if (s.startsWith("#")) {
|
||||||
|
String[] split = Assembler.SPACE.split(s, 2);
|
||||||
|
if (hashNum.equals(split[0].substring(0, split[0].length() - 1))) {
|
||||||
|
String toolTip = split[1];
|
||||||
|
if (toolTip.length() > 500)
|
||||||
|
toolTip = toolTip.substring(0, 500) + "...";
|
||||||
|
return toolTip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e1) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
len += asm.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e1) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
txtByteEditView.addKeyListener(new KeyAdapter() {
|
txtByteEditView.addKeyListener(new KeyAdapter() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -551,7 +726,6 @@ public class Main extends JFrame {
|
|||||||
KeyStroke ctrlT = KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlT = KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_DOWN_MASK);
|
||||||
KeyStroke ctrlS = KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlS = KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK);
|
||||||
KeyStroke ctrlG = KeyStroke.getKeyStroke(KeyEvent.VK_G, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlG = KeyStroke.getKeyStroke(KeyEvent.VK_G, KeyEvent.CTRL_DOWN_MASK);
|
||||||
KeyStroke ctrlO = KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_DOWN_MASK);
|
|
||||||
KeyStroke ctrlU = KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlU = KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_DOWN_MASK);
|
||||||
KeyStroke ctrlR = KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlR = KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK);
|
||||||
KeyStroke ctrlE = KeyStroke.getKeyStroke(KeyEvent.VK_E, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlE = KeyStroke.getKeyStroke(KeyEvent.VK_E, KeyEvent.CTRL_DOWN_MASK);
|
||||||
@@ -574,8 +748,6 @@ public class Main extends JFrame {
|
|||||||
typeOpenBox.txtSearch.requestFocusInWindow();
|
typeOpenBox.txtSearch.requestFocusInWindow();
|
||||||
typeOpenBox.txtSearch.select(0, typeOpenBox.txtSearch.getText().length());
|
typeOpenBox.txtSearch.select(0, typeOpenBox.txtSearch.getText().length());
|
||||||
}, ctrlT, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
}, ctrlT, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
txtByteEditView.registerKeyboardAction(e -> optionBox.setVisible(true), ctrlO,
|
|
||||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
|
||||||
txtByteEditView.registerKeyboardAction(e -> unicodeBox.setVisible(true), ctrlU,
|
txtByteEditView.registerKeyboardAction(e -> unicodeBox.setVisible(true), ctrlU,
|
||||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
txtByteEditView.registerKeyboardAction(e -> compilationBox.setVisible(true), ctrlE,
|
txtByteEditView.registerKeyboardAction(e -> compilationBox.setVisible(true), ctrlE,
|
||||||
@@ -901,10 +1073,10 @@ public class Main extends JFrame {
|
|||||||
output.closeEntry();
|
output.closeEntry();
|
||||||
}
|
}
|
||||||
int computeFlags = 0;
|
int computeFlags = 0;
|
||||||
if (optionBox.chckbxComputeFrames.isSelected()) {
|
if (mntmComputeFrames.isSelected()) {
|
||||||
computeFlags |= ClassWriter.COMPUTE_FRAMES;
|
computeFlags |= ClassWriter.COMPUTE_FRAMES;
|
||||||
}
|
}
|
||||||
if (optionBox.chckbxComputeMax.isSelected()) {
|
if (mntmComputeMax.isSelected()) {
|
||||||
computeFlags |= ClassWriter.COMPUTE_MAXS;
|
computeFlags |= ClassWriter.COMPUTE_MAXS;
|
||||||
}
|
}
|
||||||
for (ClassNode node : classes) {
|
for (ClassNode node : classes) {
|
||||||
@@ -941,21 +1113,6 @@ public class Main extends JFrame {
|
|||||||
return s + ".class";
|
return s + ".class";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Pattern SLASH = Pattern.compile("/");
|
|
||||||
private JMenuBar menuBar;
|
|
||||||
private JMenu mnFile;
|
|
||||||
private JMenuItem mntmOpenJar;
|
|
||||||
private JMenuItem mntmSaveBytecode;
|
|
||||||
private JMenuItem mntmSaveJar;
|
|
||||||
private JMenu mnWindow;
|
|
||||||
private JMenuItem mntmThemes;
|
|
||||||
private JMenuItem mntmSearchMembers;
|
|
||||||
private JMenuItem mntmSearch;
|
|
||||||
private JMenuItem mntmOpenType;
|
|
||||||
private JMenuItem mntmUnicode;
|
|
||||||
private JMenuItem mntmCompiler;
|
|
||||||
private JMenu mnSearch;
|
|
||||||
|
|
||||||
class ArchiveTreeModel extends DefaultTreeModel {
|
class ArchiveTreeModel extends DefaultTreeModel {
|
||||||
|
|
||||||
public ArrayList<String> paths = new ArrayList<>();
|
public ArrayList<String> paths = new ArrayList<>();
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user