com.googlecode.dex2jar.tools.GenerateCompileStubFromOdex Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle Show documentation
Show all versions of gradle Show documentation
fakeradnroid gradle builder
package com.googlecode.dex2jar.tools;
import com.googlecode.d2j.dex.ClassVisitorFactory;
import com.googlecode.d2j.dex.Dex2Asm;
import com.googlecode.d2j.node.DexFileNode;
import com.googlecode.d2j.reader.DexFileReader;
import org.objectweb.asm.*;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
@BaseCmd.Syntax(cmd = "d2j-generate-stub-from-odex", syntax = "[options] [odex1 ... odexN]", desc = "Genenerate no-code jar from odex")
public class GenerateCompileStubFromOdex extends BaseCmd {
private static final int MAGIC_ODEX = 0x0A796564 & 0x00FFFFFF;// hex for 'dey ', ignore the 0A
private static final int MAGIC_DEX = 0x0A786564 & 0x00FFFFFF;// hex for 'dex ', ignore the 0A
public static void main(String... args) {
new GenerateCompileStubFromOdex().doMain(args);
}
@Opt(opt = "o", longOpt = "output", description = "output .jar file, default is stub.jar", argName = "out-jar-file")
private Path output;
@Opt(opt = "npri", longOpt = "no-private", description = "", hasArg = false)
private boolean noPrivate;
@Override
protected void doCommandLine() throws Exception {
if (remainingArgs.length == 0) {
throw new HelpException("no odex");
}
if (output == null) {
output = new File("stub.jar").toPath();
}
try (FileSystem fs = createZip(output)) {
Path out = fs.getPath("/");
for (String x : remainingArgs) {
System.err.println("process " + x + " ...");
ByteBuffer bs = ByteBuffer.wrap(Files.readAllBytes(new File(x).toPath()))
.order(ByteOrder.LITTLE_ENDIAN);
int magic = bs.getInt(0) & 0x00FFFFFF;
if (magic == MAGIC_ODEX) {
int offset = bs.getInt(8);
int length = bs.getInt(12);
bs.position(offset);
ByteBuffer n = (ByteBuffer) bs.slice().limit(length);
doDex(n, out);
} else if (magic == MAGIC_DEX) {
doDex(bs, out);
} else {
throw new RuntimeException("file " + x + " is not an dex or odex");
}
}
}
}
private void doDex(ByteBuffer bs, final Path out) {
DexFileReader reader = new DexFileReader(bs);
DexFileNode fileNode = new DexFileNode();
reader.accept(fileNode, DexFileReader.SKIP_CODE);
Dex2Asm dex2Asm = new Dex2Asm();
dex2Asm.convertDex(fileNode, new ClassVisitorFactory() {
@Override
public ClassVisitor create(final String classInternalName) {
final Path target = out.resolve(classInternalName + ".class");
if (Files.exists(target)) {
System.err.println("class " + classInternalName + " is already exists, skipping.");
return null;
}
return new ClassVisitor(Opcodes.ASM4, new ClassWriter(ClassWriter.COMPUTE_MAXS)) {
@Override
public void visitEnd() {
super.visitEnd();
ClassWriter cw = (ClassWriter) cv;
byte[] data = cw.toByteArray();
try {
BaseCmd.createParentDirectories(target);
Files.write(target, data);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
if (noPrivate && 0 != (access & Opcodes.ACC_PRIVATE)) {
return null;
}
return super.visitField(access, name, desc, signature, value);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature,
String[] exceptions) {
if (noPrivate && 0 != (access & Opcodes.ACC_PRIVATE)) {
return null;
}
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
if (0 != ((Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT) & access)) {
return mv;
}
mv.visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException");
mv.visitInsn(Opcodes.DUP);
mv.visitLdcInsn("stub");
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException", "",
"(Ljava/lang/String;)V");
mv.visitInsn(Opcodes.ATHROW);
return mv;
}
};
}
});
}
}