mirror of
https://github.com/pxb1988/dex2jar.git
synced 2024-11-23 05:10:11 +00:00
Apply miscellaneous fixes
Most of these are from some fork # Conflicts: # build.gradle # d2j-j6/build.gradle # d2j-jasmin/build.gradle # d2j-smali/build.gradle # d2j-smali/src/test/java/a/SmaliTest.java # dex-reader-api/src/main/java/com/googlecode/d2j/DexConstants.java # dex-reader/build.gradle # dex-reader/src/main/java/com/googlecode/d2j/reader/DexFileReader.java # dex-tools/build.gradle # dex-tools/src/main/java/com/googlecode/d2j/tools/jar/InitOut.java # dex-tools/src/main/java/com/googlecode/d2j/tools/jar/InvocationWeaver.java # dex-translator/build.gradle # dex-translator/src/main/java/com/googlecode/d2j/dex/Dex2Asm.java # dex-translator/src/main/java/org/objectweb/asm/AsmBridge.java # gradle/wrapper/gradle-wrapper.properties
This commit is contained in:
parent
7fafa42fa6
commit
a3f93f5e2c
@ -25,7 +25,6 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
@ -103,7 +102,6 @@ public abstract class BaseCmd {
|
||||
throw new IOException("cant find zipfs support");
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
protected static class HelpException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 5538069795297477488L;
|
||||
@ -120,7 +118,7 @@ public abstract class BaseCmd {
|
||||
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Target(value = { ElementType.FIELD })
|
||||
static public @interface Opt {
|
||||
public @interface Opt {
|
||||
String argName() default "";
|
||||
|
||||
String description() default "";
|
||||
@ -190,7 +188,7 @@ public abstract class BaseCmd {
|
||||
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Target(value = { ElementType.TYPE })
|
||||
static public @interface Syntax {
|
||||
public @interface Syntax {
|
||||
|
||||
String cmd();
|
||||
|
||||
@ -212,8 +210,8 @@ public abstract class BaseCmd {
|
||||
@Opt(opt = "h", longOpt = "help", hasArg = false, description = "Print this help message")
|
||||
private boolean printHelp = false;
|
||||
|
||||
protected String remainingArgs[];
|
||||
protected String orginalArgs[];
|
||||
protected String[] remainingArgs;
|
||||
protected String[] originalArgs;
|
||||
|
||||
public BaseCmd() {
|
||||
}
|
||||
@ -235,8 +233,8 @@ public abstract class BaseCmd {
|
||||
this.desc = header;
|
||||
}
|
||||
|
||||
private Set<Option> collectRequriedOptions(Map<String, Option> optMap) {
|
||||
Set<Option> options = new HashSet<Option>();
|
||||
private Set<Option> collectRequiredOptions(Map<String, Option> optMap) {
|
||||
Set<Option> options = new HashSet<>();
|
||||
for (Map.Entry<String, Option> e : optMap.entrySet()) {
|
||||
Option option = e.getValue();
|
||||
if (option.required) {
|
||||
@ -275,14 +273,12 @@ public abstract class BaseCmd {
|
||||
try {
|
||||
type.asSubclass(Enum.class);
|
||||
return Enum.valueOf(type, value);
|
||||
} catch (Exception e) {
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
throw new RuntimeException("can't convert [" + value + "] to type " + type);
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
protected abstract void doCommandLine() throws Exception;
|
||||
|
||||
public void doMain(String... args) {
|
||||
@ -418,7 +414,7 @@ public abstract class BaseCmd {
|
||||
return;
|
||||
}
|
||||
Class<?> clz = Class.forName(args[0]);
|
||||
String newArgs[] = new String[args.length - 1];
|
||||
String[] newArgs = new String[args.length - 1];
|
||||
System.arraycopy(args, 1, newArgs, 0, newArgs.length);
|
||||
if (BaseCmd.class.isAssignableFrom(clz)) {
|
||||
BaseCmd baseCmd = (BaseCmd) clz.newInstance();
|
||||
@ -431,15 +427,15 @@ public abstract class BaseCmd {
|
||||
}
|
||||
|
||||
protected void parseSetArgs(String... args) throws IllegalArgumentException, IllegalAccessException {
|
||||
this.orginalArgs = args;
|
||||
List<String> remainsOptions = new ArrayList<String>();
|
||||
Set<Option> requiredOpts = collectRequriedOptions(optMap);
|
||||
this.originalArgs = args;
|
||||
List<String> remainsOptions = new ArrayList<>();
|
||||
Set<Option> requiredOpts = collectRequiredOptions(optMap);
|
||||
Option needArgOpt = null;
|
||||
for (String s : args) {
|
||||
if (needArgOpt != null) {
|
||||
needArgOpt.field.set(this, convert(s, needArgOpt.field.getType()));
|
||||
needArgOpt = null;
|
||||
} else if (s.startsWith("-")) {// its a short or long option
|
||||
} else if (s.startsWith("-")) {// it's a short or long option
|
||||
Option opt = optMap.get(s);
|
||||
requiredOpts.remove(opt);
|
||||
if (opt == null) {
|
||||
@ -461,7 +457,7 @@ public abstract class BaseCmd {
|
||||
System.err.println("ERROR: Option " + needArgOpt.getOptAndLongOpt() + " need an argument value");
|
||||
throw new HelpException();
|
||||
}
|
||||
this.remainingArgs = remainsOptions.toArray(new String[remainsOptions.size()]);
|
||||
this.remainingArgs = remainsOptions.toArray(new String[0]);
|
||||
if (this.printHelp) {
|
||||
throw new HelpException();
|
||||
}
|
||||
@ -478,7 +474,7 @@ public abstract class BaseCmd {
|
||||
sb.append(option.getOptAndLongOpt());
|
||||
}
|
||||
sb.append(" is required");
|
||||
System.err.println(sb.toString());
|
||||
System.err.println(sb);
|
||||
throw new HelpException();
|
||||
}
|
||||
|
||||
@ -498,7 +494,7 @@ public abstract class BaseCmd {
|
||||
// .-a,--aa.<arg>...desc1
|
||||
// .................desc2
|
||||
// .-b,--bb
|
||||
TreeSet<Option> options = new TreeSet<Option>(this.optMap.values());
|
||||
TreeSet<Option> options = new TreeSet<>(this.optMap.values());
|
||||
int palength = -1;
|
||||
for (Option option : options) {
|
||||
int pa = 4 + option.getOptAndLongOpt().length();
|
||||
@ -542,7 +538,7 @@ public abstract class BaseCmd {
|
||||
nextStart = desc.length();
|
||||
sb.setLength(0);
|
||||
} else {
|
||||
sb.append(desc.substring(nextStart, nextStart + pblength));
|
||||
sb.append(desc, nextStart, nextStart + pblength);
|
||||
out.println(sb);
|
||||
nextStart += pblength;
|
||||
sb.setLength(0);
|
||||
|
@ -22,7 +22,6 @@ import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.*;
|
||||
@ -78,7 +77,7 @@ public class Jar2JasminCmd extends BaseCmd {
|
||||
}
|
||||
}
|
||||
|
||||
private void disassemble0(Path in, final Path output) throws IOException, URISyntaxException {
|
||||
private void disassemble0(Path in, final Path output) throws IOException {
|
||||
if (Files.isDirectory(in)) { // a dir
|
||||
travelFileTree(in, output);
|
||||
} else if (in.toString().endsWith(".class")) {
|
||||
|
@ -26,7 +26,6 @@ import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
@ -34,9 +33,7 @@ import java.nio.file.attribute.BasicFileAttributes;
|
||||
|
||||
@BaseCmd.Syntax(cmd = "d2j-jasmin2jar", syntax = "[options] <jar>", desc = "Assemble .j files to .class file", onlineHelp = "https://sourceforge.net/p/dex2jar/wiki/Jasmin")
|
||||
public class Jasmin2JarCmd extends BaseCmd implements Opcodes {
|
||||
private static int versions[] = { 0, V1_1, V1_2, V1_3, V1_4, V1_5, V1_6, V1_7, 52 // V1_8 ?
|
||||
, 53 // V1_9 ?
|
||||
};
|
||||
private static final int[] versions = { 0, V1_1, V1_2, V1_3, V1_4, V1_5, V1_6, V1_7, V1_8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18 };
|
||||
@Opt(opt = "g", longOpt = "autogenerate-linenumbers", hasArg = false, description = "autogenerate-linenumbers")
|
||||
boolean autogenLines = false;
|
||||
@Opt(opt = "f", longOpt = "force", hasArg = false, description = "force overwrite")
|
||||
@ -52,8 +49,11 @@ public class Jasmin2JarCmd extends BaseCmd implements Opcodes {
|
||||
@Opt( longOpt = "no-compute-max", description = "", hasArg = false)
|
||||
private boolean noComputeMax;
|
||||
|
||||
@Opt(opt = "cv", longOpt = "class-version", description = "default .class version, [1~9], default 6 for JAVA6")
|
||||
private int classVersion = 6;
|
||||
@Opt(opt = "cv", longOpt = "class-version", description = "default .class version, [1~9], default 8 for JAVA8")
|
||||
private int classVersion = 8;
|
||||
|
||||
public Jasmin2JarCmd() {
|
||||
}
|
||||
|
||||
public static void main(String... args) throws ClassNotFoundException, SecurityException {
|
||||
new Jasmin2JarCmd().doMain(args);
|
||||
@ -65,8 +65,8 @@ public class Jasmin2JarCmd extends BaseCmd implements Opcodes {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
if (classVersion < 1 || classVersion > 9) {
|
||||
throw new HelpException("-cv,--class-version out of range, 1-9 is supported.");
|
||||
if (classVersion < 1 || classVersion > 18) {
|
||||
throw new HelpException("-cv,--class-version out of range, 1-18 is supported.");
|
||||
}
|
||||
|
||||
Path jar = new File(remainingArgs[0]).toPath().toAbsolutePath();
|
||||
@ -97,7 +97,7 @@ public class Jasmin2JarCmd extends BaseCmd implements Opcodes {
|
||||
}
|
||||
}
|
||||
|
||||
private void assemble0(Path in, Path output) throws IOException, URISyntaxException {
|
||||
private void assemble0(Path in, Path output) throws IOException {
|
||||
if (Files.isDirectory(in)) { // a dir
|
||||
travelFileTree(in, output);
|
||||
} else if (in.toString().endsWith(".j")) {
|
||||
|
@ -89,7 +89,7 @@ import java.util.*;
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class JasminDumper implements Opcodes {
|
||||
private static Set<String> ACCESS_KWS = new HashSet<String>(Arrays
|
||||
private static final Set<String> ACCESS_KWS = new HashSet<>(Arrays
|
||||
.asList("abstract", "private", "protected", "public", "enum", "final", "interface", "static", "strictfp", "native", "super"));
|
||||
|
||||
public JasminDumper(PrintWriter pw) {
|
||||
@ -187,10 +187,7 @@ public class JasminDumper implements Opcodes {
|
||||
}
|
||||
|
||||
for (FieldNode fn : cn.fields) {
|
||||
boolean annotations = false;
|
||||
if (fn.visibleAnnotations != null && fn.visibleAnnotations.size() > 0) {
|
||||
annotations = true;
|
||||
}
|
||||
boolean annotations = fn.visibleAnnotations != null && fn.visibleAnnotations.size() > 0;
|
||||
if (fn.invisibleAnnotations != null && fn.invisibleAnnotations.size() > 0) {
|
||||
annotations = true;
|
||||
}
|
||||
@ -388,13 +385,18 @@ public class JasminDumper implements Opcodes {
|
||||
pw.print('/');
|
||||
pw.print(name);
|
||||
pw.print(desc);
|
||||
if (opcode == Opcodes.INVOKEINTERFACE) {
|
||||
if (isInterface) {
|
||||
pw.print(' ');
|
||||
pw.print((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1);
|
||||
}
|
||||
pw.println();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
|
||||
visitMethodInsn(opcode, owner, name, desc, opcode == INVOKEINTERFACE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJumpInsn(int opcode, Label label) {
|
||||
print(opcode);
|
||||
@ -766,7 +768,7 @@ public class JasminDumper implements Opcodes {
|
||||
pw.print("[F = ");
|
||||
float[] v = (float[]) value;
|
||||
for (float element : v) {
|
||||
print(new Float(element));
|
||||
print(element);
|
||||
pw.print(' ');
|
||||
}
|
||||
pw.println();
|
||||
@ -774,7 +776,7 @@ public class JasminDumper implements Opcodes {
|
||||
pw.print("[D = ");
|
||||
double[] v = (double[]) value;
|
||||
for (double element : v) {
|
||||
print(new Double(element));
|
||||
print(element);
|
||||
pw.print(' ');
|
||||
}
|
||||
pw.println();
|
||||
@ -829,10 +831,10 @@ public class JasminDumper implements Opcodes {
|
||||
pw.println(((Byte) value).intValue());
|
||||
} else if (value instanceof Boolean) {
|
||||
pw.print("Z = ");
|
||||
pw.println(((Boolean) value).booleanValue() ? 1 : 0);
|
||||
pw.println((Boolean) value ? 1 : 0);
|
||||
} else if (value instanceof Character) {
|
||||
pw.print("C = ");
|
||||
pw.println(new Integer(((Character) value).charValue()));
|
||||
pw.println(new Integer((Character) value));
|
||||
} else if (value instanceof Short) {
|
||||
pw.print("S = ");
|
||||
pw.println(((Short) value).intValue());
|
||||
@ -870,9 +872,9 @@ public class JasminDumper implements Opcodes {
|
||||
} else if (value instanceof Byte) {
|
||||
pw.print(((Byte) value).intValue());
|
||||
} else if (value instanceof Boolean) {
|
||||
pw.print(((Boolean) value).booleanValue() ? 1 : 0);
|
||||
pw.print((Boolean) value ? 1 : 0);
|
||||
} else if (value instanceof Character) {
|
||||
pw.print(new Integer(((Character) value).charValue()));
|
||||
pw.print(new Integer((Character) value));
|
||||
} else if (value instanceof Short) {
|
||||
pw.print(((Short) value).intValue());
|
||||
} else if (value instanceof Type) {
|
||||
|
@ -46,6 +46,6 @@ public class Jasmins {
|
||||
}
|
||||
|
||||
public static ClassNode parse(String fileName, InputStream is) throws IOException, RecognitionException {
|
||||
return parse(fileName, new InputStreamReader(is, "UTF-8"));
|
||||
return parse(fileName, new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
apply plugin: 'antlr'
|
||||
|
||||
dependencies {
|
||||
compile 'org.antlr:antlr4-runtime:4.5'
|
||||
compile 'org.antlr:antlr4-runtime:4.9.3' // Newer versions only for Java 11+
|
||||
compile project(':dex-reader')
|
||||
antlr 'org.antlr:antlr4:4.5'
|
||||
antlr 'org.antlr:antlr4:4.9.3' // Newer versions only for Java 11+
|
||||
compile project(':d2j-base-cmd')
|
||||
compile project(':dex-writer')
|
||||
testImplementation "com.android.tools.smali:smali-baksmali:3.0.3"
|
||||
|
@ -33,7 +33,7 @@ HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
|
||||
|
||||
fragment
|
||||
ESC_SEQ
|
||||
: '\\' ('b'|'t'|'n'|'f'|'r'|'\''|'\"'|'\\')
|
||||
: '\\' ('b'|'t'|'n'|'f'|'r'|'\''|'"'|'\\')
|
||||
| UNICODE_ESC
|
||||
| OCTAL_ESC
|
||||
;
|
||||
@ -58,7 +58,7 @@ fragment
|
||||
FRAGMENT_ARRAY_TYPE: ('[')+ (FRAGMENT_PRIMITIVE_TYPE|FRAGMENT_OBJECT_TYPE);
|
||||
|
||||
fragment
|
||||
FRAGMENT_ID: (ESC_SEQ| ~('\\'|'\r'|'\n'|'\t'|' '|':'|'-'|'='|','|'{'|'}'|'('|')'|'+'|'\"'|'\''|'#'|'/'|'.'|';'|'@'))+;
|
||||
FRAGMENT_ID: (ESC_SEQ| ~('\\'|'\r'|'\n'|'\t'|' '|':'|'-'|'='|','|'{'|'}'|'('|')'|'+'|'"'|'\''|'#'|'/'|'.'|';'|'@'))+;
|
||||
fragment
|
||||
FRAGMENT_METHOD_PROTO: '(' (FRAGMENT_OBJECT_TYPE|FRAGMENT_ARRAY_TYPE|FRAGMENT_PRIMITIVE_TYPE)* ')' ('V' | FRAGMENT_OBJECT_TYPE|FRAGMENT_ARRAY_TYPE|FRAGMENT_PRIMITIVE_TYPE)
|
||||
;
|
||||
|
@ -87,7 +87,7 @@ public class AntlrSmaliUtil {
|
||||
private static class M {
|
||||
int locals;
|
||||
String[] paramNames;
|
||||
int map[];
|
||||
int[] map;
|
||||
public int total;
|
||||
|
||||
void setNameByIdx(int index, String name) {
|
||||
@ -116,7 +116,7 @@ public class AntlrSmaliUtil {
|
||||
M(Method method, int totals, int ins, boolean isStatic) {
|
||||
this.locals = totals - ins;
|
||||
this.total = totals;
|
||||
String paramTypes[] = method.getParameterTypes();
|
||||
String[] paramTypes = method.getParameterTypes();
|
||||
paramNames = new String[paramTypes.length];
|
||||
map = new int[ins];
|
||||
int start = 0;
|
||||
@ -242,8 +242,8 @@ public class AntlrSmaliUtil {
|
||||
public Object visitFspareswitch(SmaliParser.FspareswitchContext ctx) {
|
||||
List<TerminalNode> ints = ctx.INT();
|
||||
List<TerminalNode> ts = ctx.LABEL();
|
||||
int cases[] = new int[ts.size()];
|
||||
DexLabel labels[] = new DexLabel[ts.size()];
|
||||
int[] cases = new int[ts.size()];
|
||||
DexLabel[] labels = new DexLabel[ts.size()];
|
||||
for (int i = 0; i < ts.size(); i++) {
|
||||
cases[i] = parseInt(ints.get(i).getSymbol().getText());
|
||||
labels[i] = getLabel(ts.get(i).getSymbol().getText());
|
||||
@ -410,7 +410,7 @@ public class AntlrSmaliUtil {
|
||||
Op op = getOp(ctx.op);
|
||||
|
||||
List<TerminalNode> ts = ctx.REGISTER();
|
||||
int rs[] = new int[ts.size()];
|
||||
int[] rs = new int[ts.size()];
|
||||
for (int i = 0; i < ts.size(); i++) {
|
||||
rs[i] = m.pareReg(ts.get(i).getSymbol().getText());
|
||||
}
|
||||
@ -423,7 +423,7 @@ public class AntlrSmaliUtil {
|
||||
Op op = getOp(ctx.op);
|
||||
|
||||
List<TerminalNode> ts = ctx.REGISTER();
|
||||
int rs[] = new int[ts.size()];
|
||||
int[] rs = new int[ts.size()];
|
||||
for (int i = 0; i < ts.size(); i++) {
|
||||
rs[i] = m.pareReg(ts.get(i).getSymbol().getText());
|
||||
}
|
||||
@ -496,7 +496,7 @@ public class AntlrSmaliUtil {
|
||||
int start = m.pareReg(ctx.rstart.getText());
|
||||
int end = m.pareReg(ctx.rend.getText());
|
||||
int size = end - start + 1;
|
||||
int rs[] = new int[size];
|
||||
int[] rs = new int[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
rs[i] = start + i;
|
||||
}
|
||||
@ -513,7 +513,7 @@ public class AntlrSmaliUtil {
|
||||
int start = m.pareReg(ctx.rstart.getText());
|
||||
int end = m.pareReg(ctx.rend.getText());
|
||||
int size = end - start + 1;
|
||||
int rs[] = new int[size];
|
||||
int[] rs = new int[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
rs[i] = start + i;
|
||||
}
|
||||
@ -552,7 +552,7 @@ public class AntlrSmaliUtil {
|
||||
public Object visitFpackageswitch(SmaliParser.FpackageswitchContext ctx) {
|
||||
int start = parseInt(ctx.start.getText());
|
||||
List<TerminalNode> ts = ctx.LABEL();
|
||||
DexLabel labels[] = new DexLabel[ts.size()];
|
||||
DexLabel[] labels = new DexLabel[ts.size()];
|
||||
for (int i = 0; i < ts.size(); i++) {
|
||||
labels[i] = getLabel(ts.get(i).getSymbol().getText());
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ import java.util.*;
|
||||
this.debugLabelMap = debugLabelMap;
|
||||
}
|
||||
|
||||
class PackedSwitchStmt {
|
||||
static class PackedSwitchStmt {
|
||||
int first_case;
|
||||
|
||||
DexLabel[] labels;
|
||||
@ -59,7 +59,7 @@ import java.util.*;
|
||||
}
|
||||
}
|
||||
|
||||
class SparseSwitchStmt {
|
||||
static class SparseSwitchStmt {
|
||||
int[] cases;
|
||||
|
||||
DexLabel[] labels;
|
||||
@ -86,7 +86,7 @@ import java.util.*;
|
||||
dx.displayName = "L" + nextLabelNumber++;
|
||||
usedLabel.add(dx);
|
||||
out.s("%s %s, %s", op.displayName, reg(ra), xLabel(dx));
|
||||
appendLast.add(new AbstractMap.SimpleEntry<DexLabel, Object>(dx, array));
|
||||
appendLast.add(new AbstractMap.SimpleEntry<>(dx, array));
|
||||
}
|
||||
|
||||
@SuppressWarnings("incomplete-switch")
|
||||
@ -105,12 +105,12 @@ import java.util.*;
|
||||
}
|
||||
case CONST_WIDE_32: {
|
||||
Long v = (Long) value;
|
||||
value = (int) v.intValue();
|
||||
value = v.intValue();
|
||||
break;
|
||||
}
|
||||
case CONST_HIGH16: {
|
||||
Integer v = (Integer) value;
|
||||
value = (int) v.intValue() >> 16;
|
||||
value = v >> 16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -147,8 +147,8 @@ import java.util.*;
|
||||
out.s(".array-data 1");
|
||||
out.push();
|
||||
byte[] vs = (byte[]) array;
|
||||
for (int i = 0; i < vs.length; i++) {
|
||||
out.s(BaksmaliDumper.escapeValue(vs[i]));
|
||||
for (byte b : vs) {
|
||||
out.s(BaksmaliDumper.escapeValue(b));
|
||||
}
|
||||
out.pop();
|
||||
out.s(".end array-data");
|
||||
@ -156,8 +156,7 @@ import java.util.*;
|
||||
out.s(".array-data 2");
|
||||
out.push();
|
||||
short[] vs = (short[]) array;
|
||||
for (int i = 0; i < vs.length; i++) {
|
||||
short a = vs[i];
|
||||
for (short a : vs) {
|
||||
out.s("%s %s", BaksmaliDumper.escapeValue((byte) (a & 0xFF)),
|
||||
BaksmaliDumper.escapeValue((byte) (0xFF & (a >> 8))));
|
||||
}
|
||||
@ -167,8 +166,7 @@ import java.util.*;
|
||||
out.s(".array-data 4");
|
||||
out.push();
|
||||
int[] vs = (int[]) array;
|
||||
for (int i = 0; i < vs.length; i++) {
|
||||
int a = vs[i];
|
||||
for (int a : vs) {
|
||||
out.s("%s %s %s %s", BaksmaliDumper.escapeValue((byte) (a & 0xFF)),
|
||||
BaksmaliDumper.escapeValue((byte) (0xFF & (a >> 8))),
|
||||
BaksmaliDumper.escapeValue((byte) (0xFF & (a >> 16))),
|
||||
@ -180,8 +178,8 @@ import java.util.*;
|
||||
out.s(".array-data 4");
|
||||
out.push();
|
||||
float[] vs = (float[]) array;
|
||||
for (int i = 0; i < vs.length; i++) {
|
||||
int a = Float.floatToIntBits(vs[i]);
|
||||
for (float value : vs) {
|
||||
int a = Float.floatToIntBits(value);
|
||||
out.s("%s %s %s %s", BaksmaliDumper.escapeValue((byte) (a & 0xFF)),
|
||||
BaksmaliDumper.escapeValue((byte) (0xFF & (a >> 8))),
|
||||
BaksmaliDumper.escapeValue((byte) (0xFF & (a >> 16))),
|
||||
@ -193,8 +191,7 @@ import java.util.*;
|
||||
out.s(".array-data 8");
|
||||
out.push();
|
||||
long[] vs = (long[]) array;
|
||||
for (int i = 0; i < vs.length; i++) {
|
||||
long ttt = vs[i];
|
||||
for (long ttt : vs) {
|
||||
int a = (int) ttt;
|
||||
int b = (int) (ttt >>> 32);
|
||||
out.s("%s %s %s %s %s %s %s %s", BaksmaliDumper.escapeValue((byte) (a & 0xFF)),
|
||||
@ -212,8 +209,8 @@ import java.util.*;
|
||||
out.s(".array-data 8");
|
||||
out.push();
|
||||
double[] vs = (double[]) array;
|
||||
for (int i = 0; i < vs.length; i++) {
|
||||
long ttt = Double.doubleToLongBits(vs[i]);
|
||||
for (double value : vs) {
|
||||
long ttt = Double.doubleToLongBits(value);
|
||||
int a = (int) ttt;
|
||||
int b = (int) (ttt >>> 32);
|
||||
out.s("%s %s %s %s %s %s %s %s", BaksmaliDumper.escapeValue((byte) (a & 0xFF)),
|
||||
|
@ -15,13 +15,13 @@ import java.util.Set;
|
||||
public class BaksmaliDexFileVisitor extends DexFileVisitor {
|
||||
private final Path dir;
|
||||
private final BaksmaliDumper bs;
|
||||
private Set<String> hases;
|
||||
private final Set<String> hashes;
|
||||
private int i;
|
||||
|
||||
public BaksmaliDexFileVisitor(Path dir, BaksmaliDumper bs) {
|
||||
this.dir = dir;
|
||||
this.bs = bs;
|
||||
hases = new HashSet<String>();
|
||||
hashes = new HashSet<>();
|
||||
i = 1;
|
||||
}
|
||||
|
||||
@ -29,10 +29,10 @@ public class BaksmaliDexFileVisitor extends DexFileVisitor {
|
||||
s = BaksmaliDumper.escapeId(s);
|
||||
s = s.replace('\\', '-');
|
||||
String low = s.toLowerCase();
|
||||
if (hases.contains(low)) {
|
||||
if (hashes.contains(low)) {
|
||||
return s + "_d2j" + i++;
|
||||
} else {
|
||||
hases.add(low);
|
||||
hashes.add(low);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ public class BaksmaliDumper implements DexConstants {
|
||||
for (int i = 0; i < id.length(); ++i) {
|
||||
char c = id.charAt(i);
|
||||
if (c == '-') {
|
||||
sb.append(c);
|
||||
sb.append('-');
|
||||
} else {
|
||||
escape1(sb, c);
|
||||
}
|
||||
@ -235,35 +235,35 @@ public class BaksmaliDumper implements DexConstants {
|
||||
if (obj instanceof Integer) {
|
||||
int i = ((Integer) obj);
|
||||
if (i == Integer.MIN_VALUE) {
|
||||
return "0x" + Integer.toHexString(i);
|
||||
return "0x" + Integer.toHexString(Integer.MIN_VALUE);
|
||||
}
|
||||
return obj.toString();
|
||||
}
|
||||
if (obj instanceof Long) {
|
||||
Long v = ((Long) obj);
|
||||
long v = ((Long) obj);
|
||||
if (v == Long.MIN_VALUE) {
|
||||
return "0x" + Long.toHexString(v) + "L";
|
||||
return "0x" + Long.toHexString(Long.MIN_VALUE) + "L";
|
||||
} else {
|
||||
return ((Long) obj).toString() + "L";
|
||||
return obj + "L";
|
||||
}
|
||||
}
|
||||
if (obj instanceof Float) {
|
||||
return ((Float) obj).toString() + "F";
|
||||
return obj + "F";
|
||||
}
|
||||
if (obj instanceof Double) {
|
||||
return ((Double) obj).toString() + "D";
|
||||
return obj + "D";
|
||||
}
|
||||
if (obj instanceof Short) {
|
||||
return ((Short) obj).toString() + "S";
|
||||
return obj + "S";
|
||||
}
|
||||
if (obj instanceof Byte) {
|
||||
return ((Byte) obj).toString() + 't';
|
||||
}
|
||||
if (obj instanceof Character) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("\'");
|
||||
escape0(buf, ((Character) obj).charValue());
|
||||
buf.append("\'");
|
||||
buf.append("'");
|
||||
escape0(buf, (Character) obj);
|
||||
buf.append("'");
|
||||
return buf.toString();
|
||||
}
|
||||
if (obj instanceof Boolean) {
|
||||
|
@ -21,7 +21,11 @@ import com.googlecode.d2j.node.DexFileNode;
|
||||
import com.googlecode.d2j.smali.antlr4.SmaliLexer;
|
||||
import com.googlecode.d2j.smali.antlr4.SmaliParser;
|
||||
import com.googlecode.d2j.visitors.DexFileVisitor;
|
||||
import org.antlr.v4.runtime.*;
|
||||
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.CodePointCharStream;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -37,22 +41,19 @@ import java.nio.file.attribute.BasicFileAttributes;
|
||||
public class Smali {
|
||||
public static void smaliFile(Path path, DexFileVisitor dcv) throws IOException {
|
||||
try (Reader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
|
||||
ANTLRInputStream is = new ANTLRInputStream(reader);
|
||||
is.name = path.toString();
|
||||
CodePointCharStream is = CharStreams.fromReader(reader, path.toString());
|
||||
smali0(dcv, is);
|
||||
}
|
||||
}
|
||||
|
||||
public static void smaliFile(String name, String buff, DexFileVisitor dcv) throws IOException {
|
||||
ANTLRInputStream is = new ANTLRInputStream(buff);
|
||||
is.name = name;
|
||||
public static void smaliFile(String name, String buff, DexFileVisitor dcv) {
|
||||
CodePointCharStream is = CharStreams.fromString(buff, name);
|
||||
smali0(dcv, is);
|
||||
}
|
||||
|
||||
public static void smaliFile(String name, InputStream in, DexFileVisitor dcv) throws IOException {
|
||||
try (InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8)) {
|
||||
ANTLRInputStream is = new ANTLRInputStream(reader);
|
||||
is.name = name;
|
||||
CodePointCharStream is = CharStreams.fromReader(reader, name);
|
||||
smali0(dcv, is);
|
||||
}
|
||||
}
|
||||
@ -63,13 +64,13 @@ public class Smali {
|
||||
return dfn.clzs.size() > 0 ? dfn.clzs.get(0) : null;
|
||||
}
|
||||
|
||||
public static DexClassNode smaliFile2Node(String name, String buff) throws IOException {
|
||||
public static DexClassNode smaliFile2Node(String name, String buff) {
|
||||
DexFileNode dfn = new DexFileNode();
|
||||
smaliFile(name, buff, dfn);
|
||||
return dfn.clzs.size() > 0 ? dfn.clzs.get(0) : null;
|
||||
}
|
||||
|
||||
private static void smali0(DexFileVisitor dcv, CharStream is) throws IOException {
|
||||
private static void smali0(DexFileVisitor dcv, CharStream is) {
|
||||
SmaliLexer lexer = new SmaliLexer(is);
|
||||
CommonTokenStream ts = new CommonTokenStream(lexer);
|
||||
SmaliParser parser = new SmaliParser(ts);
|
||||
@ -79,10 +80,9 @@ public class Smali {
|
||||
}
|
||||
}
|
||||
|
||||
public static void smaliFile(String fileName, char[] data, DexFileVisitor dcv) throws IOException {
|
||||
public static void smaliFile(String fileName, char[] data, DexFileVisitor dcv) {
|
||||
// System.err.println("parsing " + f.getAbsoluteFile());
|
||||
ANTLRInputStream is = new ANTLRInputStream(data, data.length);
|
||||
is.name = fileName;
|
||||
CodePointCharStream is = CharStreams.fromString(new String(data), fileName);
|
||||
smali0(dcv, is);
|
||||
}
|
||||
|
||||
|
@ -32,12 +32,12 @@ public class SmaliCmd extends BaseCmd {
|
||||
if (showVersionThenExits) {
|
||||
System.out.println("smali 1.4.2p (https://sourceforge.net/p/dex2jar)");
|
||||
System.out.println("Copyright (c) 2009-2013 Panxiaobo (pxb1988@gmail.com)");
|
||||
System.out.println("Apache license (http://www.apache.org/licenses/LICENSE-2.0)");
|
||||
System.out.println("Apache license (https://www.apache.org/licenses/LICENSE-2.0)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!readSmaliFromStdin && remainingArgs.length < 1) {
|
||||
System.err.println("ERRPR: no file to process");
|
||||
System.err.println("ERROR: no file to process");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -45,7 +45,6 @@ public class SmaliCmd extends BaseCmd {
|
||||
output = new File("out.dex").toPath();
|
||||
}
|
||||
|
||||
Smali smali = new Smali();
|
||||
DexFileWriter fw = new DexFileWriter();
|
||||
|
||||
DexFileVisitor fv = new DexFileVisitor(fw) {
|
||||
@ -55,7 +54,7 @@ public class SmaliCmd extends BaseCmd {
|
||||
};
|
||||
|
||||
if (readSmaliFromStdin) {
|
||||
smali.smaliFile("<stdin>", System.in, fv);
|
||||
Smali.smaliFile("<stdin>", System.in, fv);
|
||||
System.err.println("smali <stdin> -> " + output);
|
||||
}
|
||||
|
||||
@ -65,7 +64,7 @@ public class SmaliCmd extends BaseCmd {
|
||||
System.err.println("skip " + file + ", it is not a dir or a file");
|
||||
} else {
|
||||
System.err.println("smali " + s + " -> " + output);
|
||||
smali.smali(file, fv);
|
||||
Smali.smali(file, fv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ public class SmaliCodeVisitor extends DexCodeNode {
|
||||
|
||||
public static class SparseSwitchStmt extends DexStmtNode {
|
||||
int[] cases;
|
||||
DexLabel labels[];
|
||||
DexLabel[] labels;
|
||||
|
||||
public SparseSwitchStmt(int[] cases, DexLabel[] labels) {
|
||||
super(null);
|
||||
@ -123,7 +123,7 @@ public class SmaliCodeVisitor extends DexCodeNode {
|
||||
}
|
||||
}
|
||||
|
||||
private List<DexStmtNode> needCareStmts = new ArrayList<DexStmtNode>();
|
||||
private List<DexStmtNode> needCareStmts = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
@ -207,7 +207,7 @@ public class SmaliCodeVisitor extends DexCodeNode {
|
||||
int[] vs1 = new int[vs.length / 4];
|
||||
for (int i = 0; i < vs1.length; i++) {
|
||||
int base = i * 4;
|
||||
vs1[i] = (vs[base + 0] & 0xFF) | ((vs[base + 1] & 0xFF) << 8)
|
||||
vs1[i] = (vs[base] & 0xFF) | ((vs[base + 1] & 0xFF) << 8)
|
||||
| ((vs[base + 2] & 0xFF) << 16) | ((vs[base + 3] & 0xFF) << 24);
|
||||
}
|
||||
v = vs1;
|
||||
@ -217,9 +217,9 @@ public class SmaliCodeVisitor extends DexCodeNode {
|
||||
long[] vs1 = new long[vs.length / 8];
|
||||
for (int i = 0; i < vs1.length; i++) {
|
||||
int base = i * 8;
|
||||
int a = ((vs[base + 0] & 0xFF) << 0) | ((vs[base + 1] & 0xFF) << 8)
|
||||
int a = ((vs[base] & 0xFF)) | ((vs[base + 1] & 0xFF) << 8)
|
||||
| ((vs[base + 2] & 0xFF) << 16) | ((vs[base + 3] & 0xFF) << 24);
|
||||
int b = ((vs[base + 4] & 0xFF) << 0) | ((vs[base + 5] & 0xFF) << 8)
|
||||
int b = ((vs[base + 4] & 0xFF)) | ((vs[base + 5] & 0xFF) << 8)
|
||||
| ((vs[base + 6] & 0xFF) << 16) | ((vs[base + 7] & 0xFF) << 24);
|
||||
vs1[i] = (((long) b) << 32) | a;
|
||||
}
|
||||
|
@ -39,50 +39,51 @@ public class Utils implements DexConstants {
|
||||
}
|
||||
|
||||
public static int getAcc(String name) {
|
||||
if (name.equals("public")) {
|
||||
switch (name) {
|
||||
case "public":
|
||||
return ACC_PUBLIC;
|
||||
} else if (name.equals("private")) {
|
||||
case "private":
|
||||
return ACC_PRIVATE;
|
||||
} else if (name.equals("protected")) {
|
||||
case "protected":
|
||||
return ACC_PROTECTED;
|
||||
} else if (name.equals("static")) {
|
||||
case "static":
|
||||
return ACC_STATIC;
|
||||
} else if (name.equals("final")) {
|
||||
case "final":
|
||||
return ACC_FINAL;
|
||||
} else if (name.equals("synchronized")) {
|
||||
case "synchronized":
|
||||
return ACC_SYNCHRONIZED;
|
||||
} else if (name.equals("volatile")) {
|
||||
case "volatile":
|
||||
return ACC_VOLATILE;
|
||||
} else if (name.equals("bridge")) {
|
||||
case "bridge":
|
||||
return ACC_BRIDGE;
|
||||
} else if (name.equals("varargs")) {
|
||||
case "varargs":
|
||||
return ACC_VARARGS;
|
||||
} else if (name.equals("transient")) {
|
||||
case "transient":
|
||||
return ACC_TRANSIENT;
|
||||
} else if (name.equals("native")) {
|
||||
case "native":
|
||||
return ACC_NATIVE;
|
||||
} else if (name.equals("interface")) {
|
||||
case "interface":
|
||||
return ACC_INTERFACE;
|
||||
} else if (name.equals("abstract")) {
|
||||
case "abstract":
|
||||
return ACC_ABSTRACT;
|
||||
} else if (name.equals("strict")) {
|
||||
case "strict":
|
||||
return ACC_STRICT;
|
||||
} else if (name.equals("synthetic")) {
|
||||
case "synthetic":
|
||||
return ACC_SYNTHETIC;
|
||||
} else if (name.equals("annotation")) {
|
||||
case "annotation":
|
||||
return ACC_ANNOTATION;
|
||||
} else if (name.equals("enum")) {
|
||||
case "enum":
|
||||
return ACC_ENUM;
|
||||
} else if (name.equals("constructor")) {
|
||||
case "constructor":
|
||||
return ACC_CONSTRUCTOR;
|
||||
} else if (name.equals("declared-synchronized")) {
|
||||
case "declared-synchronized":
|
||||
return ACC_DECLARED_SYNCHRONIZED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static List<String> listDesc(String desc) {
|
||||
List<String> list = new ArrayList(5);
|
||||
List<String> list = new ArrayList<>(5);
|
||||
if (desc == null) {
|
||||
return list;
|
||||
}
|
||||
@ -140,11 +141,11 @@ public class Utils implements DexConstants {
|
||||
}
|
||||
|
||||
static public Byte parseByte(String str) {
|
||||
return Byte.valueOf((byte) parseInt(str.substring(0, str.length() - 1)));
|
||||
return (byte) parseInt(str.substring(0, str.length() - 1));
|
||||
}
|
||||
|
||||
static public Short parseShort(String str) {
|
||||
return Short.valueOf((short) parseInt(str.substring(0, str.length() - 1)));
|
||||
return (short) parseInt(str.substring(0, str.length() - 1));
|
||||
}
|
||||
|
||||
static public Long parseLong(String str) {
|
||||
@ -201,7 +202,7 @@ public class Utils implements DexConstants {
|
||||
if (str.equals("infinity")) {
|
||||
return x < 0 ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
|
||||
}
|
||||
return (float) x * Float.parseFloat(str);
|
||||
return x * Float.parseFloat(str);
|
||||
}
|
||||
|
||||
static public double parseDouble(String str) {
|
||||
@ -269,7 +270,7 @@ public class Utils implements DexConstants {
|
||||
}
|
||||
|
||||
public static int[] toIntArray(List<String> ss) {
|
||||
int vs[] = new int[ss.size()];
|
||||
int[] vs = new int[ss.size()];
|
||||
for (int i = 0; i < ss.size(); i++) {
|
||||
vs[i] = parseInt(ss.get(i));
|
||||
}
|
||||
@ -277,14 +278,14 @@ public class Utils implements DexConstants {
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(List<Object> ss) {
|
||||
byte vs[] = new byte[ss.size()];
|
||||
byte[] vs = new byte[ss.size()];
|
||||
for (int i = 0; i < ss.size(); i++) {
|
||||
vs[i] = ((Number) (ss.get(i))).byteValue();
|
||||
}
|
||||
return vs;
|
||||
}
|
||||
|
||||
static Map<String, Op> ops = new HashMap();
|
||||
static Map<String, Op> ops = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (Op op : Op.values()) {
|
||||
@ -322,7 +323,6 @@ public class Utils implements DexConstants {
|
||||
i += 2;
|
||||
break;
|
||||
case 'u':
|
||||
String sub = str.substring(i + 2, i + 6);
|
||||
i += 6;
|
||||
break;
|
||||
default:
|
||||
@ -424,10 +424,10 @@ public class Utils implements DexConstants {
|
||||
|
||||
public static class Ann {
|
||||
public String name;
|
||||
public List<Map.Entry<String, Object>> elements = new ArrayList();
|
||||
public List<Map.Entry<String, Object>> elements = new ArrayList<>();
|
||||
|
||||
public void put(String name, Object value) {
|
||||
elements.add(new java.util.AbstractMap.SimpleEntry(name, value));
|
||||
elements.add(new java.util.AbstractMap.SimpleEntry<>(name, value));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,6 +64,10 @@ public class SmaliTest {
|
||||
for (File f : fs) {
|
||||
if (f.getName().endsWith(".dex") || f.getName().endsWith(".apk")) {
|
||||
System.out.println(f.getName());
|
||||
if (f.getName().equals("dex040.dex")) {
|
||||
// FIXME smali 3.0.3 not support space in SimpleName
|
||||
continue;
|
||||
}
|
||||
dotest(f);
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public class Cfg {
|
||||
|
||||
public static int[] countLocalReads(IrMethod method) {
|
||||
int size = reIndexLocal(method);
|
||||
final int readCounts[] = new int[size];
|
||||
final int[] readCounts = new int[size];
|
||||
travel(method.stmts, new TravelCallBack() {
|
||||
@Override
|
||||
public Value onAssign(Local v, AssignStmt as) {
|
||||
@ -168,7 +168,7 @@ public class Cfg {
|
||||
|
||||
}
|
||||
|
||||
public static interface DfsVisitor {
|
||||
public interface DfsVisitor {
|
||||
void onVisit(Stmt p);
|
||||
}
|
||||
|
||||
@ -220,7 +220,7 @@ public class Cfg {
|
||||
st.frame = null;
|
||||
}
|
||||
|
||||
Stack<Stmt> stack = new Stack<Stmt>();
|
||||
Stack<Stmt> stack = new Stack<>();
|
||||
Stmt first = stmts.getFirst();
|
||||
Stmt nop = null;
|
||||
if (first.st == ST.LABEL && first._cfg_froms.size() > 0) {
|
||||
@ -315,7 +315,7 @@ public class Cfg {
|
||||
value.setOp2(travelMod(value.getOp2(), callback));
|
||||
break;
|
||||
case En:
|
||||
Value ops[] = value.getOps();
|
||||
Value[] ops = value.getOps();
|
||||
for (int i = 0; i < ops.length; i++) {
|
||||
ops[i] = travelMod(ops[i], callback);
|
||||
}
|
||||
@ -339,9 +339,9 @@ public class Cfg {
|
||||
travel(value.getOp2(), callback);
|
||||
break;
|
||||
case En:
|
||||
Value ops[] = value.getOps();
|
||||
for (int i = 0; i < ops.length; i++) {
|
||||
travel(ops[i], callback);
|
||||
Value[] ops = value.getOps();
|
||||
for (Value op : ops) {
|
||||
travel(op, callback);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -440,9 +440,7 @@ public class Cfg {
|
||||
BaseSwitchStmt bss = (BaseSwitchStmt) stmt;
|
||||
tos.add(bss.defaultTarget);
|
||||
|
||||
for (Stmt target : bss.targets) {
|
||||
tos.add(target);
|
||||
}
|
||||
Collections.addAll(tos, bss.targets);
|
||||
}
|
||||
if (stmt.exceptionHandlers != null) {
|
||||
tos.addAll(stmt.exceptionHandlers);
|
||||
|
@ -45,12 +45,7 @@ import com.googlecode.dex2jar.ir.stmt.Stmt;
|
||||
*/
|
||||
public class RemoveConstantFromSSA extends StatedTransformer {
|
||||
|
||||
public static final Comparator<Local> LOCAL_COMPARATOR = new Comparator<Local>() {
|
||||
@Override
|
||||
public int compare(Local local, Local t1) {
|
||||
return Integer.compare(local._ls_index, t1._ls_index);
|
||||
}
|
||||
};
|
||||
public static final Comparator<Local> LOCAL_COMPARATOR = Comparator.comparingInt(local -> local._ls_index);
|
||||
|
||||
@Override
|
||||
public boolean transformReportChanged(IrMethod method) {
|
||||
|
@ -75,7 +75,7 @@ public class RemoveLocalFromSSA extends StatedTransformer {
|
||||
}
|
||||
}
|
||||
set.remove(phi.getOp1());
|
||||
phi.getOp2().setOps(set.toArray(new Value[set.size()]));
|
||||
phi.getOp2().setOps(set.toArray(new Value[0]));
|
||||
set.clear();
|
||||
}
|
||||
}
|
||||
@ -171,12 +171,7 @@ public class RemoveLocalFromSSA extends StatedTransformer {
|
||||
}
|
||||
for (Iterator<LabelStmt> itLabel = phiLabels.iterator(); itLabel.hasNext(); ) {
|
||||
LabelStmt labelStmt = itLabel.next();
|
||||
for (Iterator<AssignStmt> it = labelStmt.phis.iterator(); it.hasNext(); ) {
|
||||
AssignStmt phi = it.next();
|
||||
if (toDeletePhiAssign.contains(phi.getOp1())) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
labelStmt.phis.removeIf(phi -> toDeletePhiAssign.contains(phi.getOp1()));
|
||||
if (labelStmt.phis.size() == 0) {
|
||||
labelStmt.phis = null;
|
||||
itLabel.remove();
|
||||
@ -208,12 +203,7 @@ public class RemoveLocalFromSSA extends StatedTransformer {
|
||||
|
||||
static <T> void fixReplace(Map<Local, T> toReplace) {
|
||||
List<Map.Entry<Local, T>> set = new ArrayList<>(toReplace.entrySet());
|
||||
Collections.sort(set, new Comparator<Map.Entry<Local, T>>() {
|
||||
@Override
|
||||
public int compare(Map.Entry<Local, T> localTEntry, Map.Entry<Local, T> t1) {
|
||||
return Integer.compare(localTEntry.getKey()._ls_index, t1.getKey()._ls_index);
|
||||
}
|
||||
});
|
||||
set.sort(Comparator.comparingInt(localTEntry -> localTEntry.getKey()._ls_index));
|
||||
|
||||
boolean changed = true;
|
||||
while (changed) {
|
||||
|
@ -25,5 +25,5 @@ import com.googlecode.dex2jar.ir.IrMethod;
|
||||
*/
|
||||
public interface Transformer {
|
||||
|
||||
public void transform(IrMethod method);
|
||||
void transform(IrMethod method);
|
||||
}
|
||||
|
@ -61,16 +61,16 @@ public class TypeTransformer implements Transformer {
|
||||
cst.value = Constant.Null;
|
||||
}
|
||||
if (type.equals("[F") && cst.value instanceof int[]) {
|
||||
int x[] = (int[]) cst.value;
|
||||
float f[] = new float[x.length];
|
||||
int[] x = (int[]) cst.value;
|
||||
float[] f = new float[x.length];
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
f[i] = Float.intBitsToFloat(x[i]);
|
||||
}
|
||||
cst.value = f;
|
||||
}
|
||||
if (type.equals("[D") && cst.value instanceof long[]) {
|
||||
long x[] = (long[]) cst.value;
|
||||
double f[] = new double[x.length];
|
||||
long[] x = (long[]) cst.value;
|
||||
double[] f = new double[x.length];
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
f[i] = Double.longBitsToDouble(x[i]);
|
||||
}
|
||||
@ -283,7 +283,7 @@ public class TypeTransformer implements Transformer {
|
||||
}
|
||||
return thiz.provideDesc;
|
||||
}
|
||||
if (clz == TypeClass.JD) { // prefere Long if wide
|
||||
if (clz == TypeClass.JD) { // prefer Long if wide
|
||||
return "J";
|
||||
}
|
||||
if (thiz.uses != null) {
|
||||
@ -296,15 +296,14 @@ public class TypeTransformer implements Transformer {
|
||||
|
||||
switch (clz) {
|
||||
case ZI:
|
||||
return "I";
|
||||
case ZIFL:
|
||||
case ZIF:
|
||||
case ZIL:
|
||||
return "Z";
|
||||
case INT:
|
||||
case IF:
|
||||
return "I";
|
||||
default:
|
||||
case INT:
|
||||
case IF:
|
||||
return "I";
|
||||
case ZIFL:
|
||||
case ZIF:
|
||||
case ZIL:
|
||||
return "Z";
|
||||
default:
|
||||
}
|
||||
throw new RuntimeException();
|
||||
}
|
||||
@ -352,7 +351,7 @@ public class TypeTransformer implements Transformer {
|
||||
|
||||
private static class TypeAnalyze {
|
||||
protected IrMethod method;
|
||||
private List<TypeRef> refs = new ArrayList<>();
|
||||
private final List<TypeRef> refs = new ArrayList<>();
|
||||
|
||||
public TypeAnalyze(IrMethod method) {
|
||||
super();
|
||||
@ -485,7 +484,7 @@ public class TypeTransformer implements Transformer {
|
||||
return a;
|
||||
} else if (!ta.fixed && tb.fixed) {
|
||||
return b;
|
||||
} else if (ta.fixed && tb.fixed) {
|
||||
} else if (ta.fixed) {
|
||||
if (ta != tb) {
|
||||
if (as == 0) {
|
||||
throw new RuntimeException();
|
||||
@ -603,7 +602,7 @@ public class TypeTransformer implements Transformer {
|
||||
return a;
|
||||
} else if (!ta.fixed && tb.fixed) {
|
||||
return b;
|
||||
} else if (ta.fixed && tb.fixed) {
|
||||
} else if (ta.fixed) {
|
||||
// special allow merge of Z and I
|
||||
if ((ta == TypeClass.INT && tb == TypeClass.BOOLEAN) || (tb == TypeClass.INT && ta == TypeClass.BOOLEAN)) {
|
||||
return "I";
|
||||
@ -910,7 +909,7 @@ public class TypeTransformer implements Transformer {
|
||||
}
|
||||
|
||||
private void enexpr(EnExpr enExpr) {
|
||||
Value vbs[] = enExpr.ops;
|
||||
Value[] vbs = enExpr.ops;
|
||||
switch (enExpr.vt) {
|
||||
case INVOKE_NEW:
|
||||
case INVOKE_INTERFACE:
|
||||
@ -924,7 +923,7 @@ public class TypeTransformer implements Transformer {
|
||||
provideAs(enExpr, type);
|
||||
useAs(enExpr, type); // no one else will use it
|
||||
|
||||
String argTypes[] = ice.getProto().getParameterTypes();
|
||||
String[] argTypes = ice.getProto().getParameterTypes();
|
||||
if (argTypes.length == vbs.length) {
|
||||
for (int i = 0; i < vbs.length; i++) {
|
||||
useAs(vbs[i], argTypes[i]);
|
||||
@ -996,7 +995,7 @@ public class TypeTransformer implements Transformer {
|
||||
private TypeRef getDefTypeRef(Value v) {
|
||||
Object object = v.tag;
|
||||
TypeRef typeRef;
|
||||
if (object == null || !(object instanceof TypeRef)) {
|
||||
if (!(object instanceof TypeRef)) {
|
||||
typeRef = new TypeRef(v);
|
||||
refs.add(typeRef);
|
||||
v.tag = typeRef;
|
||||
@ -1061,8 +1060,6 @@ public class TypeTransformer implements Transformer {
|
||||
case TABLE_SWITCH:
|
||||
useAs(op, "I");
|
||||
break;
|
||||
case GOTO:
|
||||
break;
|
||||
case IF:
|
||||
useAs(op, "Z");
|
||||
break;
|
||||
|
@ -21,7 +21,7 @@ package com.googlecode.d2j;
|
||||
* @author <a href="mailto:pxb1988@gmail.com">Panxiaobo</a>
|
||||
* @version $Rev$
|
||||
*/
|
||||
public abstract interface DexConstants {
|
||||
public interface DexConstants {
|
||||
|
||||
int ACC_PUBLIC = 0x0001; // class, field, method
|
||||
int ACC_PRIVATE = 0x0002; // class, field, method
|
||||
|
@ -157,11 +157,11 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
final int MAGIC_ODEX = 0x6465790A & 0xFFFFFF00;// hex for 'dey ', ignore the 0A
|
||||
|
||||
if (magic == MAGIC_DEX) {
|
||||
;
|
||||
// ok
|
||||
} else if (magic == MAGIC_ODEX) {
|
||||
throw new DexException("Not support odex");
|
||||
throw new DexException("Odex unsupported.");
|
||||
} else {
|
||||
throw new DexException("not support magic.");
|
||||
throw new DexException("Magic unsupported.");
|
||||
}
|
||||
int version = in.getInt() >> 8;
|
||||
if (version < DEX_035 || version > DEX_040) {
|
||||
@ -178,7 +178,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
|
||||
int endian_tag = in.getInt();
|
||||
if (endian_tag != ENDIAN_CONSTANT) {
|
||||
throw new DexException("not support endian_tag");
|
||||
throw new DexException("Endian_tag unsupported");
|
||||
}
|
||||
|
||||
// skip uint link_size
|
||||
@ -320,13 +320,13 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
sb.append(' ');
|
||||
if (t instanceof DexException) {
|
||||
sb.append(t.getMessage());
|
||||
System.err.println(sb.toString());
|
||||
System.err.println(sb);
|
||||
if (t.getCause() != null) {
|
||||
niceExceptionMessage(t.getCause(), deep + 1);
|
||||
}
|
||||
} else {
|
||||
if (t != null) {
|
||||
System.err.println(sb.append("ROOT cause:").toString());
|
||||
System.err.println(sb.append("ROOT cause:"));
|
||||
t.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
@ -357,7 +357,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
for (int i = 0; i < bytes; ++i) {
|
||||
result |= ((long) (0xFF & in.get())) << (i * 8);
|
||||
}
|
||||
result <<= (8 - bytes) * 8;
|
||||
result <<= (8 - bytes) * 8L;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -379,7 +379,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
}
|
||||
|
||||
static void WARN(String fmt, Object... args) {
|
||||
System.err.println(String.format(fmt, args));
|
||||
System.err.printf((fmt) + "%n", args);
|
||||
}
|
||||
|
||||
static int ubyte(byte[] insns, int offset) {
|
||||
@ -437,7 +437,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
int address = 0;
|
||||
int line = readULeb128i(in);
|
||||
int szParams = readULeb128i(in);
|
||||
LocalEntry lastEntryForReg[] = new LocalEntry[regSize];
|
||||
LocalEntry[] lastEntryForReg = new LocalEntry[regSize];
|
||||
int argsSize = 0;
|
||||
for (String paramType : method.getParameterTypes()) {
|
||||
if (paramType.equals("J") || paramType.equals("D")) {
|
||||
@ -681,19 +681,19 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
int type = b & 0x1f;
|
||||
switch (type) {
|
||||
case VALUE_BYTE:
|
||||
return new Byte((byte) readIntBits(in, b));
|
||||
return (byte) readIntBits(in, b);
|
||||
|
||||
case VALUE_SHORT:
|
||||
return new Short((short) readIntBits(in, b));
|
||||
return (short) readIntBits(in, b);
|
||||
|
||||
case VALUE_CHAR:
|
||||
return new Character((char) readUIntBits(in, b));
|
||||
return (char) readUIntBits(in, b);
|
||||
|
||||
case VALUE_INT:
|
||||
return new Integer((int) readIntBits(in, b));
|
||||
return (int) readIntBits(in, b);
|
||||
|
||||
case VALUE_LONG:
|
||||
return new Long(readIntBits(in, b));
|
||||
return readIntBits(in, b);
|
||||
|
||||
case VALUE_FLOAT:
|
||||
return Float.intBitsToFloat((int) (readFloatBits(in, b) >> 32));
|
||||
@ -733,7 +733,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
case VALUE_NULL:
|
||||
return null;
|
||||
case VALUE_BOOLEAN: {
|
||||
return new Boolean(((b >> 5) & 0x3) != 0);
|
||||
return ((b >> 5) & 0x3) != 0;
|
||||
}
|
||||
default:
|
||||
throw new DexException("Not support yet.");
|
||||
@ -778,9 +778,9 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
Map<Integer, Integer> paramAnnotationPositions;
|
||||
if ((config & SKIP_ANNOTATION) == 0) {
|
||||
// 获取注解
|
||||
fieldAnnotationPositions = new HashMap<Integer, Integer>();
|
||||
methodAnnotationPositions = new HashMap<Integer, Integer>();
|
||||
paramAnnotationPositions = new HashMap<Integer, Integer>();
|
||||
fieldAnnotationPositions = new HashMap<>();
|
||||
methodAnnotationPositions = new HashMap<>();
|
||||
paramAnnotationPositions = new HashMap<>();
|
||||
if (annotations_off != 0) { // annotations_directory_item
|
||||
|
||||
annotationsDirectoryItemIn.position(annotations_off);
|
||||
@ -824,10 +824,10 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
ByteBuffer in = classDataIn;
|
||||
in.position(class_data_off);
|
||||
|
||||
int static_fields = (int) readULeb128i(in);
|
||||
int instance_fields = (int) readULeb128i(in);
|
||||
int direct_methods = (int) readULeb128i(in);
|
||||
int virtual_methods = (int) readULeb128i(in);
|
||||
int static_fields = readULeb128i(in);
|
||||
int instance_fields = readULeb128i(in);
|
||||
int direct_methods = readULeb128i(in);
|
||||
int virtual_methods = readULeb128i(in);
|
||||
{
|
||||
int lastIndex = 0;
|
||||
{
|
||||
@ -983,8 +983,8 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
|
||||
private int acceptField(ByteBuffer in, int lastIndex, DexClassVisitor dcv,
|
||||
Map<Integer, Integer> fieldAnnotationPositions, Object value, int config) {
|
||||
int diff = (int) readULeb128i(in);
|
||||
int field_access_flags = (int) readULeb128i(in);
|
||||
int diff = readULeb128i(in);
|
||||
int field_access_flags = readULeb128i(in);
|
||||
int field_id = lastIndex + diff;
|
||||
Field field = getField(field_id);
|
||||
// //////////////////////////////////////////////////////////////
|
||||
@ -1009,9 +1009,9 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
private int acceptMethod(ByteBuffer in, int lastIndex, DexClassVisitor cv, Map<Integer, Integer> methodAnnos,
|
||||
Map<Integer, Integer> parameterAnnos, int config, boolean firstMethod) {
|
||||
int offset = in.position();
|
||||
int diff = (int) readULeb128i(in);
|
||||
int method_access_flags = (int) readULeb128i(in);
|
||||
int code_off = (int) readULeb128i(in);
|
||||
int diff = readULeb128i(in);
|
||||
int method_access_flags = readULeb128i(in);
|
||||
int code_off = readULeb128i(in);
|
||||
int method_id = lastIndex + diff;
|
||||
Method method = getMethod(method_id);
|
||||
|
||||
@ -1120,7 +1120,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
|
||||
private void findLabels(byte[] insns, BitSet nextBit, BitSet badOps, Map<Integer, DexLabel> labelsMap, Set<Integer> handlers,
|
||||
Method method) {
|
||||
Queue<Integer> q = new LinkedList<Integer>();
|
||||
Queue<Integer> q = new LinkedList<>();
|
||||
q.add(0);
|
||||
q.addAll(handlers);
|
||||
handlers.clear();
|
||||
@ -1149,10 +1149,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
int opcode = 0xFF & insns[u1offset];
|
||||
Op op = null;
|
||||
if (opcode < Op.ops.length) {
|
||||
op = Op.ops[opcode];
|
||||
}
|
||||
Op op = Op.ops[opcode];
|
||||
if (op == null || op.format == null) {
|
||||
throw new BadOpException("zero-width instruction op=0x%02x", opcode);
|
||||
}
|
||||
@ -1307,7 +1304,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
if (op == Op.NOP) {
|
||||
switch (insns[u1offset + 1]) {
|
||||
case 0x00:
|
||||
q.add(offset + op.format.size);
|
||||
q.add(offset + Op.NOP.format.size);
|
||||
break;
|
||||
case 0x01: {
|
||||
int size = ushort(insns, u1offset + 2);
|
||||
@ -1350,25 +1347,25 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
handlerIn.position(encoded_catch_handler_list + handler_offset);// move to encoded_catch_handler
|
||||
|
||||
boolean catchAll = false;
|
||||
int listSize = (int) readLeb128i(handlerIn);
|
||||
int listSize = readLeb128i(handlerIn);
|
||||
int handlerCount = listSize;
|
||||
if (listSize <= 0) {
|
||||
listSize = -listSize;
|
||||
handlerCount = listSize + 1;
|
||||
catchAll = true;
|
||||
}
|
||||
DexLabel labels[] = new DexLabel[handlerCount];
|
||||
String types[] = new String[handlerCount];
|
||||
DexLabel[] labels = new DexLabel[handlerCount];
|
||||
String[] types = new String[handlerCount];
|
||||
for (int k = 0; k < listSize; k++) {
|
||||
int type_id = (int) readULeb128i(handlerIn);
|
||||
int handler = (int) readULeb128i(handlerIn);
|
||||
int type_id = readULeb128i(handlerIn);
|
||||
int handler = readULeb128i(handlerIn);
|
||||
order(labelsMap, handler);
|
||||
handlers.add(handler);
|
||||
types[k] = getType(type_id);
|
||||
labels[k] = labelsMap.get(handler);
|
||||
}
|
||||
if (catchAll) {
|
||||
int handler = (int) readULeb128i(handlerIn);
|
||||
int handler = readULeb128i(handlerIn);
|
||||
order(labelsMap, handler);
|
||||
handlers.add(handler);
|
||||
labels[listSize] = labelsMap.get(handler);
|
||||
@ -1391,8 +1388,8 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
in.get(insnsArray);
|
||||
dcv.visitRegister(registers_size);
|
||||
BitSet nextInsn = new BitSet();
|
||||
Map<Integer, DexLabel> labelsMap = new TreeMap<Integer, DexLabel>();
|
||||
Set<Integer> handlers = new HashSet<Integer>();
|
||||
Map<Integer, DexLabel> labelsMap = new TreeMap<>();
|
||||
Set<Integer> handlers = new HashSet<>();
|
||||
// 处理异常处理
|
||||
if (tries_size > 0) {
|
||||
if ((insns & 0x01) != 0) {// skip padding
|
||||
@ -1516,7 +1513,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
case 1: {
|
||||
byte[] data = new byte[size];
|
||||
System.arraycopy(insns, u1SwitchData + 8, data, 0, size);
|
||||
dcv.visitFillArrayDataStmt(op, a, data);
|
||||
dcv.visitFillArrayDataStmt(Op.FILL_ARRAY_DATA, a, data);
|
||||
}
|
||||
break;
|
||||
case 2: {
|
||||
@ -1524,7 +1521,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
for (int i = 0; i < size; i++) {
|
||||
data[i] = (short) sshort(insns, u1SwitchData + 8 + 2 * i);
|
||||
}
|
||||
dcv.visitFillArrayDataStmt(op, a, data);
|
||||
dcv.visitFillArrayDataStmt(Op.FILL_ARRAY_DATA, a, data);
|
||||
}
|
||||
break;
|
||||
case 4: {
|
||||
@ -1532,7 +1529,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
for (int i = 0; i < size; i++) {
|
||||
data[i] = sint(insns, u1SwitchData + 8 + 4 * i);
|
||||
}
|
||||
dcv.visitFillArrayDataStmt(op, a, data);
|
||||
dcv.visitFillArrayDataStmt(Op.FILL_ARRAY_DATA, a, data);
|
||||
}
|
||||
break;
|
||||
case 8: {
|
||||
@ -1540,20 +1537,20 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
for (int i = 0; i < size; i++) {
|
||||
int t = u1SwitchData + 8 + 8 * i;
|
||||
long z = 0;
|
||||
z |= ((long) ushort(insns, t + 0)) << 0;
|
||||
z |= (ushort(insns, t));
|
||||
z |= ((long) ushort(insns, t + 2)) << 16;
|
||||
z |= ((long) ushort(insns, t + 4)) << 32;
|
||||
z |= ((long) ushort(insns, t + 6)) << 48;
|
||||
data[i] = z;
|
||||
}
|
||||
dcv.visitFillArrayDataStmt(op, a, data);
|
||||
dcv.visitFillArrayDataStmt(Op.FILL_ARRAY_DATA, a, data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (op == Op.SPARSE_SWITCH) {
|
||||
int size = sshort(insns, u1SwitchData + 2);
|
||||
int keys[] = new int[size];
|
||||
DexLabel labels[] = new DexLabel[size];
|
||||
int[] keys = new int[size];
|
||||
DexLabel[] labels = new DexLabel[size];
|
||||
int z = u1SwitchData + 4;
|
||||
for (int i = 0; i < size; i++) {
|
||||
keys[i] = sint(insns, z + i * 4);
|
||||
@ -1562,11 +1559,11 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
for (int i = 0; i < size; i++) {
|
||||
labels[i] = labelsMap.get(offset + sint(insns, z + i * 4));
|
||||
}
|
||||
dcv.visitSparseSwitchStmt(op, a, keys, labels);
|
||||
dcv.visitSparseSwitchStmt(Op.SPARSE_SWITCH, a, keys, labels);
|
||||
} else {
|
||||
int size = sshort(insns, u1SwitchData + 2);
|
||||
int first_key = sint(insns, u1SwitchData + 4);
|
||||
DexLabel labels[] = new DexLabel[size];
|
||||
DexLabel[] labels = new DexLabel[size];
|
||||
int z = u1SwitchData + 8;
|
||||
for (int i = 0; i < size; i++) {
|
||||
labels[i] = labelsMap.get(offset + sint(insns, z));
|
||||
@ -1587,7 +1584,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
break;
|
||||
case kIndexTypeRef:
|
||||
if (op == Op.CONST_CLASS) {
|
||||
dcv.visitConstStmt(op, a, new DexType(getType(b)));
|
||||
dcv.visitConstStmt(Op.CONST_CLASS, a, new DexType(getType(b)));
|
||||
} else {
|
||||
dcv.visitTypeStmt(op, a, -1, getType(b));
|
||||
}
|
||||
@ -1629,18 +1626,18 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
int dc = ubyte(insns, u1offset + 4); // DC
|
||||
int fe = ubyte(insns, u1offset + 5); // FE
|
||||
|
||||
int regs[] = new int[a >> 4];
|
||||
int[] regs = new int[a >> 4];
|
||||
switch (a >> 4) {
|
||||
case 5:
|
||||
regs[4] = a & 0xF;// G
|
||||
case 4:
|
||||
regs[3] = 0xF & (fe >> 4);// F
|
||||
case 3:
|
||||
regs[2] = 0xF & (fe >> 0);// E
|
||||
regs[2] = 0xF & (fe);// E
|
||||
case 2:
|
||||
regs[1] = 0xF & (dc >> 4);// D
|
||||
case 1:
|
||||
regs[0] = 0xF & (dc >> 0);// C
|
||||
regs[0] = 0xF & (dc);// C
|
||||
}
|
||||
if (op.indexType == InstructionIndexType.kIndexTypeRef) {
|
||||
dcv.visitFilledNewArrayStmt(op, regs, getType(b));
|
||||
@ -1655,7 +1652,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
a = ubyte(insns, u1offset + 1);
|
||||
b = ushort(insns, u1offset + 2);
|
||||
c = ushort(insns, u1offset + 4);
|
||||
int regs[] = new int[a];
|
||||
int[] regs = new int[a];
|
||||
for (int i = 0; i < a; i++) {
|
||||
regs[i] = c + i;
|
||||
}
|
||||
@ -1675,18 +1672,18 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
int fe = ubyte(insns, u1offset + 5); // FE
|
||||
int h = ushort(insns, u1offset + 6);
|
||||
|
||||
int regs[] = new int[a >> 4];
|
||||
int[] regs = new int[a >> 4];
|
||||
switch (a >> 4) {
|
||||
case 5:
|
||||
regs[4] = a & 0xF;// G
|
||||
case 4:
|
||||
regs[3] = 0xF & (fe >> 4);// F
|
||||
case 3:
|
||||
regs[2] = 0xF & (fe >> 0);// E
|
||||
regs[2] = 0xF & (fe);// E
|
||||
case 2:
|
||||
regs[1] = 0xF & (dc >> 4);// D
|
||||
case 1:
|
||||
regs[0] = 0xF & (dc >> 0);// C
|
||||
regs[0] = 0xF & (dc);// C
|
||||
}
|
||||
dcv.visitMethodStmt(op, regs, getMethod(b), getProto(h));
|
||||
}
|
||||
@ -1696,7 +1693,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
b = ushort(insns, u1offset + 2);
|
||||
c = ushort(insns, u1offset + 4);
|
||||
int h = ushort(insns, u1offset + 6);
|
||||
int regs[] = new int[a];
|
||||
int[] regs = new int[a];
|
||||
for (int i = 0; i < a; i++) {
|
||||
regs[i] = c + i;
|
||||
}
|
||||
@ -1727,7 +1724,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
a = ubyte(insns, u1offset + 1);
|
||||
b = sshort(insns, u1offset + 2);
|
||||
if (op == Op.CONST_HIGH16) {
|
||||
dcv.visitConstStmt(op, a, b << 16);
|
||||
dcv.visitConstStmt(Op.CONST_HIGH16, a, b << 16);
|
||||
} else {
|
||||
dcv.visitConstStmt(op, a, ((long) b) << 48);
|
||||
}
|
||||
@ -1736,7 +1733,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
a = ubyte(insns, u1offset + 1);
|
||||
b = sshort(insns, u1offset + 2);
|
||||
if (op == Op.CONST_16) {
|
||||
dcv.visitConstStmt(op, a, b);
|
||||
dcv.visitConstStmt(Op.CONST_16, a, b);
|
||||
} else {
|
||||
dcv.visitConstStmt(op, a, (long) b);
|
||||
}
|
||||
@ -1757,7 +1754,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
a = ubyte(insns, u1offset + 1);
|
||||
b = sint(insns, u1offset + 2);
|
||||
if (op == Op.CONST) {
|
||||
dcv.visitConstStmt(op, a, b);
|
||||
dcv.visitConstStmt(Op.CONST, a, b);
|
||||
} else {
|
||||
dcv.visitConstStmt(op, a, (long) b);
|
||||
}
|
||||
@ -1765,7 +1762,7 @@ public class DexFileReader implements BaseDexFileReader {
|
||||
case kFmt51l:
|
||||
a = ubyte(insns, u1offset + 1);
|
||||
long z = 0;
|
||||
z |= ((long) ushort(insns, u1offset + 2)) << 0;
|
||||
z |= ushort(insns, u1offset + 2);
|
||||
z |= ((long) ushort(insns, u1offset + 4)) << 16;
|
||||
z |= ((long) ushort(insns, u1offset + 6)) << 32;
|
||||
z |= ((long) ushort(insns, u1offset + 8)) << 48;
|
||||
|
@ -20,22 +20,22 @@ import static com.googlecode.d2j.util.AccUtils.*;
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class InitOut {
|
||||
private static Set<String> keywords = new HashSet<String>(Arrays.asList("abstract", "continue", "for", "new",
|
||||
private static final Set<String> keywords = new HashSet<String>(Arrays.asList("abstract", "continue", "for", "new",
|
||||
"switch", "assert", "default", "goto", "package", "synchronized", "boolean", "do", "if", "private", "this",
|
||||
"break", "double", "implements", "protected", "throw", "byte", "else", "import", "public", "throws",
|
||||
"case", "enum", "instanceof", "return", "transient", "catch", "extends", "int", "short", "try", "char",
|
||||
"final", "interface", "static", "void", "class", "finally", "long", "strictfp", "volatile", "const",
|
||||
"float", "native", "super", "while"));
|
||||
private int clzIndex = 0;
|
||||
private Set<String> clzMap = new TreeSet<String>();
|
||||
private Set<String> clzSet = new TreeSet<String>();
|
||||
private Set<String> clzMap = new TreeSet<>();
|
||||
private Set<String> clzSet = new TreeSet<>();
|
||||
private Path from;
|
||||
private int maxLength = 40;
|
||||
private Set<String> memberMap = new TreeSet<String>();
|
||||
private Set<String> memberMap = new TreeSet<>();
|
||||
private int minLength = 2;
|
||||
private int pkgIndex = 0;
|
||||
private Set<String> pkgMap = new TreeSet<String>();
|
||||
private Set<String> pkgSet = new TreeSet<String>();
|
||||
private Set<String> pkgMap = new TreeSet<>();
|
||||
private Set<String> pkgSet = new TreeSet<>();
|
||||
private boolean initEnumNames = false;
|
||||
private boolean initSourceNames = false;
|
||||
private boolean initAssertionNames = false;
|
||||
@ -112,10 +112,10 @@ public class InitOut {
|
||||
}
|
||||
sb.append(short4LongName(member.name));
|
||||
if (x > 0) {
|
||||
memberMap.add("m " + owner + "." + member.name + member.desc + "=" + sb.toString());
|
||||
memberMap.add("m " + owner + "." + member.name + member.desc + "=" + sb);
|
||||
} else {
|
||||
memberMap.add("m " + owner + "." + member.name
|
||||
+ member.desc.substring(0, member.desc.indexOf(')') + 1) + "=" + sb.toString());
|
||||
+ member.desc.substring(0, member.desc.indexOf(')') + 1) + "=" + sb);
|
||||
}
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
@ -111,7 +111,7 @@ import java.util.jar.Manifest;
|
||||
*/
|
||||
public class InvocationWeaver extends BaseWeaver implements Opcodes {
|
||||
private static final Type OBJECT_TYPE = Type.getType(Object.class);
|
||||
private Remapper remapper = new Remapper() {
|
||||
private final Remapper remapper = new Remapper() {
|
||||
|
||||
@Override
|
||||
public String mapDesc(String desc) {
|
||||
@ -208,19 +208,19 @@ public class InvocationWeaver extends BaseWeaver implements Opcodes {
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] wave0(byte[] data) throws IOException {
|
||||
public byte[] wave0(byte[] data) {
|
||||
final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
wave0(data, cw);
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
public void wave0(byte[] data, final ClassVisitor cv) throws IOException {
|
||||
public void wave0(byte[] data, final ClassVisitor cv) {
|
||||
new ClassReader(data).accept(wrapper(cv), ClassReader.EXPAND_FRAMES);
|
||||
}
|
||||
|
||||
public ClassVisitor wrapper(final ClassVisitor cv) {
|
||||
return new ClassRemapper(cv, remapper) {
|
||||
Map<MtdInfo, MtdInfo> toCreate = new HashMap<MtdInfo, MtdInfo>();
|
||||
final Map<MtdInfo, MtdInfo> toCreate = new HashMap<>();
|
||||
String clzName;
|
||||
|
||||
private MtdInfo newMethodA(int opcode, MtdInfo t, MtdInfo mapTo) {
|
||||
@ -239,7 +239,7 @@ public class InvocationWeaver extends BaseWeaver implements Opcodes {
|
||||
List<Type> ts = new ArrayList<>(args.length + 1);
|
||||
ts.add(Type.getType(t.owner));
|
||||
ts.addAll(Arrays.asList(args));
|
||||
n.desc = Type.getMethodDescriptor(ret, ts.toArray(new Type[ts.size()]));
|
||||
n.desc = Type.getMethodDescriptor(ret, ts.toArray(new Type[0]));
|
||||
} else {
|
||||
n.desc = t.desc;
|
||||
}
|
||||
@ -357,9 +357,8 @@ public class InvocationWeaver extends BaseWeaver implements Opcodes {
|
||||
t1.owner = "L" + clzName + ";";
|
||||
t1.name = buildMethodAName(name) ;
|
||||
t1.desc = desc;
|
||||
final MtdInfo t = t1;
|
||||
final MtdInfo src = new MtdInfo();
|
||||
src.owner = t.owner;
|
||||
src.owner = t1.owner;
|
||||
src.name = name;
|
||||
src.desc = desc;
|
||||
return new MethodNode(ASM9, access, name, desc, signature, exceptions) {
|
||||
@ -382,10 +381,10 @@ public class InvocationWeaver extends BaseWeaver implements Opcodes {
|
||||
} else {
|
||||
opcode = Opcodes.INVOKEVIRTUAL;
|
||||
}
|
||||
genMethodACode(opcode, t, mapTo, superMv, src);
|
||||
genMethodACode(opcode, t1, mapTo, superMv, src);
|
||||
|
||||
int newAccess = (access & ~(ACC_PRIVATE | ACC_PROTECTED)) | ACC_PUBLIC; // make sure public
|
||||
MethodVisitor rmv = wrap(superMethodVisitor(newAccess, t.name, desc, null, null));
|
||||
MethodVisitor rmv = wrap(superMethodVisitor(newAccess, t1.name, desc, null, null));
|
||||
if(rmv!=null) {
|
||||
rmv.visitCode();
|
||||
int n, i;
|
||||
@ -423,14 +422,15 @@ public class InvocationWeaver extends BaseWeaver implements Opcodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean isInterface) {
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc,
|
||||
boolean isInterface) {
|
||||
MtdInfo mapTo = findTargetMethod("L" + owner + ";", name, desc);
|
||||
if (mapTo != null) {
|
||||
boolean isStatic = opcode == INVOKESTATIC;
|
||||
Type orgRet = Type.getReturnType(desc);
|
||||
Type orgArgs[] = Type.getArgumentTypes(desc);
|
||||
Type[] orgArgs = Type.getArgumentTypes(desc);
|
||||
Type nRet = Type.getReturnType(mapTo.desc);
|
||||
Type nArgs[] = Type.getArgumentTypes(mapTo.desc);
|
||||
Type[] nArgs = Type.getArgumentTypes(mapTo.desc);
|
||||
if (orgRet.getSort() != Type.VOID && nRet.getSort() == Type.VOID) {
|
||||
throw new RuntimeException("can't cast " + nRet + " to " + orgRet);
|
||||
}
|
||||
@ -472,6 +472,11 @@ public class InvocationWeaver extends BaseWeaver implements Opcodes {
|
||||
super.visitMethodInsn(opcode, owner, name, desc, isInterface);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
|
||||
visitMethodInsn(opcode, owner, name, desc, opcode == INVOKEINTERFACE);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@ -479,42 +484,38 @@ public class InvocationWeaver extends BaseWeaver implements Opcodes {
|
||||
|
||||
public void wave(Path from, final Path to) throws IOException {
|
||||
|
||||
BaseCmd.walkJarOrDir(from, new BaseCmd.FileVisitorX() {
|
||||
@Override
|
||||
public void visitFile(Path file, String relative) throws IOException {
|
||||
String name = relative;
|
||||
Path targetPath = to.resolve(relative);
|
||||
BaseCmd.createParentDirectories(targetPath);
|
||||
if (name.endsWith(".class")) {
|
||||
String clzName = name.substring(0, name.length() - ".class".length());
|
||||
if (ignores.contains(clzName)) {
|
||||
Files.copy(file, targetPath);
|
||||
BaseCmd.walkJarOrDir(from, (file, relative) -> {
|
||||
Path targetPath = to.resolve(relative);
|
||||
BaseCmd.createParentDirectories(targetPath);
|
||||
if (relative.endsWith(".class")) {
|
||||
String clzName = relative.substring(0, relative.length() - ".class".length());
|
||||
if (ignores.contains(clzName)) {
|
||||
Files.copy(file, targetPath);
|
||||
} else {
|
||||
byte[] out = wave0(Files.readAllBytes(file));
|
||||
Files.write(targetPath, out);
|
||||
}
|
||||
} else {
|
||||
if (relative.startsWith("META-INF/")) {
|
||||
if (relative.equals(JarFile.MANIFEST_NAME)) {
|
||||
try (InputStream in = Files.newInputStream(file)) {
|
||||
Manifest mf = new Manifest(in);
|
||||
mf.getMainAttributes().put(new Name("X-NOTICE"), "Modified");
|
||||
mf.getEntries().clear();
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
mf.write(baos);
|
||||
baos.flush();
|
||||
Files.write(targetPath, baos.toByteArray());
|
||||
}
|
||||
} else if (relative.endsWith(".DSA") || relative.endsWith(".RSA") || relative.endsWith(".SF")
|
||||
|| relative.endsWith(".ECDSA")) {
|
||||
// ignored
|
||||
} else {
|
||||
byte[] out = wave0(Files.readAllBytes(file));
|
||||
Files.write(targetPath, out);
|
||||
Files.copy(file, targetPath);
|
||||
}
|
||||
} else {
|
||||
if (name.startsWith("META-INF/")) {
|
||||
if (name.equals(JarFile.MANIFEST_NAME)) {
|
||||
try (InputStream in = Files.newInputStream(file)) {
|
||||
Manifest mf = new Manifest(in);
|
||||
mf.getMainAttributes().put(new Name("X-NOTICE"), "Modified");
|
||||
mf.getEntries().clear();
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
mf.write(baos);
|
||||
baos.flush();
|
||||
Files.write(targetPath, baos.toByteArray());
|
||||
}
|
||||
} else if (name.endsWith(".DSA") || name.endsWith(".RSA") || name.endsWith(".SF")
|
||||
|| name.endsWith(".ECDSA")) {
|
||||
// ignored
|
||||
} else {
|
||||
Files.copy(file, targetPath);
|
||||
}
|
||||
} else {
|
||||
Files.copy(file, targetPath);
|
||||
}
|
||||
Files.copy(file, targetPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -558,24 +559,9 @@ public class InvocationWeaver extends BaseWeaver implements Opcodes {
|
||||
mv.visitEnd();
|
||||
}
|
||||
{
|
||||
genSwitchMethod(cw, typeName, "getMethodOwner", new CB() {
|
||||
@Override
|
||||
public String getKey(MtdInfo mtd) {
|
||||
return toInternal(mtd.owner);
|
||||
}
|
||||
});
|
||||
genSwitchMethod(cw, typeName, "getMethodName", new CB() {
|
||||
@Override
|
||||
public String getKey(MtdInfo mtd) {
|
||||
return mtd.name;
|
||||
}
|
||||
});
|
||||
genSwitchMethod(cw, typeName, "getMethodDesc", new CB() {
|
||||
@Override
|
||||
public String getKey(MtdInfo mtd) {
|
||||
return mtd.desc;
|
||||
}
|
||||
});
|
||||
genSwitchMethod(cw, typeName, "getMethodOwner", mtd -> toInternal(mtd.owner));
|
||||
genSwitchMethod(cw, typeName, "getMethodName", mtd -> mtd.name);
|
||||
genSwitchMethod(cw, typeName, "getMethodDesc", mtd -> mtd.desc);
|
||||
}
|
||||
{
|
||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getArguments", "()[Ljava/lang/Object;", null, null);
|
||||
|
@ -117,7 +117,7 @@ public class Dex2jarCmd extends BaseCmd {
|
||||
: exceptionFile;
|
||||
System.err.println("Detail Error Information in File " + errorFile);
|
||||
System.err.println(BaksmaliBaseDexExceptionHandler.REPORT_MESSAGE);
|
||||
handler.dump(errorFile, orginalArgs);
|
||||
handler.dump(errorFile, originalArgs);
|
||||
}
|
||||
}
|
||||
// long endTS = System.currentTimeMillis();
|
||||
|
@ -52,8 +52,7 @@ public class Dex2jarMultiThreadCmd extends BaseCmd {
|
||||
|
||||
@Override
|
||||
protected void doCommandLine() throws Exception {
|
||||
List<String> f = new ArrayList<>();
|
||||
f.addAll(Arrays.asList(remainingArgs));
|
||||
List<String> f = new ArrayList<>(Arrays.asList(remainingArgs));
|
||||
if (fileList != null) {
|
||||
f.addAll(Files.readAllLines(fileList, StandardCharsets.UTF_8));
|
||||
}
|
||||
@ -117,7 +116,7 @@ public class Dex2jarMultiThreadCmd extends BaseCmd {
|
||||
// FIXME handle 'java.lang.RuntimeException: Method code too large!'
|
||||
data = cw.toByteArray();
|
||||
} catch (Exception ex) {
|
||||
System.err.println(String.format("ASM fail to generate .class file: %s", className));
|
||||
System.err.printf("ASM fail to generate .class file: %s%n", className);
|
||||
exceptionHandler.handleFileException(ex);
|
||||
return;
|
||||
}
|
||||
|
@ -92,11 +92,11 @@ public class Jar2Dex extends BaseCmd {
|
||||
Class<?> c = Class.forName("com.android.dx.command.Main");
|
||||
Method m = c.getMethod("main", String[].class);
|
||||
|
||||
List<String> ps = new ArrayList<String>();
|
||||
ps.addAll(Arrays.asList("--dex", "--no-strict", "--output=" + output.toAbsolutePath().toString(), realJar
|
||||
List<String> ps = new ArrayList<>(Arrays.asList("--dex", "--no-strict",
|
||||
"--output=" + output.toAbsolutePath(), realJar
|
||||
.toAbsolutePath().toString()));
|
||||
System.out.println("call com.android.dx.command.Main.main" + ps);
|
||||
m.invoke(null, new Object[] { ps.toArray(new String[ps.size()]) });
|
||||
m.invoke(null, new Object[] { ps.toArray(new String[0]) });
|
||||
} finally {
|
||||
if (tmp != null) {
|
||||
Files.deleteIfExists(tmp);
|
||||
|
@ -86,7 +86,7 @@ public class Dex2Asm {
|
||||
|
||||
void addInner(Clz clz) {
|
||||
if (inners == null) {
|
||||
inners = new HashSet<Clz>();
|
||||
inners = new HashSet<>();
|
||||
}
|
||||
inners.add(clz);
|
||||
}
|
||||
@ -101,11 +101,10 @@ public class Dex2Asm {
|
||||
return false;
|
||||
Clz other = (Clz) obj;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
return true;
|
||||
return other.name == null;
|
||||
} else {
|
||||
return name.equals(other.name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -281,7 +280,7 @@ public class Dex2Asm {
|
||||
}
|
||||
|
||||
private static MethodVisitor collectBasicMethodInfo(DexMethodNode methodNode, ClassVisitor cv) {
|
||||
String xthrows[] = null;
|
||||
String[] xthrows = null;
|
||||
String signature = null;
|
||||
if (methodNode.anns != null) {
|
||||
for (DexAnnotationNode ann : methodNode.anns) {
|
||||
@ -370,7 +369,7 @@ public class Dex2Asm {
|
||||
}
|
||||
break;
|
||||
case DexConstants.ANNOTATION_MEMBER_CLASSES_TYPE: {
|
||||
Object ts[] = (Object[]) findAnnotationAttribute(ann, "value");
|
||||
Object[] ts = (Object[]) findAnnotationAttribute(ann, "value");
|
||||
for (Object v : ts) {
|
||||
DexType type = (DexType) v;
|
||||
Clz inner = get(classes, type.desc);
|
||||
@ -447,7 +446,7 @@ public class Dex2Asm {
|
||||
}
|
||||
}
|
||||
}
|
||||
String interfaceInterNames[] = null;
|
||||
String[] interfaceInterNames = null;
|
||||
if (classNode.interfaceNames != null) {
|
||||
interfaceInterNames = new String[classNode.interfaceNames.length];
|
||||
for (int i = 0; i < classNode.interfaceNames.length; i++) {
|
||||
@ -475,7 +474,7 @@ public class Dex2Asm {
|
||||
cv.visit(version, access, toInternalName(classNode.className), signature,
|
||||
classNode.superClass == null ? null : toInternalName(classNode.superClass), interfaceInterNames);
|
||||
|
||||
List<InnerClassNode> innerClassNodes = new ArrayList<InnerClassNode>(5);
|
||||
List<InnerClassNode> innerClassNodes = new ArrayList<>(5);
|
||||
if (clzInfo != null) {
|
||||
searchInnerClass(clzInfo, innerClassNodes, classNode.className);
|
||||
}
|
||||
@ -590,7 +589,7 @@ public class Dex2Asm {
|
||||
for (DexAnnotationNode ann : fieldNode.anns) {
|
||||
if (ann.visibility == Visibility.SYSTEM) {
|
||||
switch (ann.type) {
|
||||
case DexConstants.ANNOTATION_SIGNATURE_TYPE: {
|
||||
case DexConstants.ANNOTATION_SIGNATURE_TYPE:
|
||||
Object[] strs = (Object[]) findAnnotationAttribute(ann, "value");
|
||||
if (strs != null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@ -599,7 +598,6 @@ public class Dex2Asm {
|
||||
}
|
||||
signature = sb.toString();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ public class Dex2jar {
|
||||
readerConfig |= DexFileReader.SKIP_DEBUG;
|
||||
}
|
||||
|
||||
private void doTranslate(final Path dist) throws IOException {
|
||||
private void doTranslate(final Path dist) {
|
||||
|
||||
DexFileNode fileNode = new DexFileNode();
|
||||
try {
|
||||
@ -102,7 +102,7 @@ public class Dex2jar {
|
||||
// FIXME handle 'java.lang.RuntimeException: Method code too large!'
|
||||
data = cw.toByteArray();
|
||||
} catch (Exception ex) {
|
||||
System.err.println(String.format("ASM fail to generate .class file: %s", className));
|
||||
System.err.printf("ASM fail to generate .class file: %s%n", className);
|
||||
exceptionHandler.handleFileException(ex);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user