提交 401d08ea 编写于 作者: S Skylot

refactor: move all smali libs usage to one utility class

上级 ba17f7bc
package jadx.api;
import java.io.File;
import java.io.StringWriter;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
......@@ -16,13 +14,6 @@ import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import org.jetbrains.annotations.Nullable;
import org.jf.baksmali.Adaptors.ClassDefinition;
import org.jf.baksmali.BaksmaliOptions;
import org.jf.dexlib2.DexFileFactory;
import org.jf.dexlib2.Opcodes;
import org.jf.dexlib2.dexbacked.DexBackedClassDef;
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.util.IndentingWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -35,7 +26,6 @@ import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode;
import jadx.core.dex.visitors.SaveCode;
import jadx.core.export.ExportGradleProject;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.core.utils.files.InputFile;
import jadx.core.xmlgen.BinaryXMLParser;
......@@ -291,30 +281,6 @@ public final class JadxDecompiler {
root.getErrorsCounter().printReport();
}
void generateSmali(ClassNode cls) {
Path path = cls.dex().getDexFile().getPath();
String className = Utils.makeQualifiedObjectName(cls.getClassInfo().getType().getObject());
try {
DexBackedDexFile dexFile = DexFileFactory.loadDexFile(path.toFile(), Opcodes.getDefault());
boolean decompiled = false;
for (DexBackedClassDef classDef : dexFile.getClasses()) {
if (classDef.getType().equals(className)) {
ClassDefinition classDefinition = new ClassDefinition(new BaksmaliOptions(), classDef);
StringWriter sw = new StringWriter();
classDefinition.writeTo(new IndentingWriter(sw));
cls.setSmali(sw.toString());
decompiled = true;
break;
}
}
if (!decompiled) {
LOG.error("Failed to find smali class {}", className);
}
} catch (Exception e) {
LOG.error("Error generating smali", e);
}
}
RootNode getRoot() {
return root;
}
......
......@@ -59,12 +59,6 @@ public final class JavaClass implements JavaNode {
}
public synchronized String getSmali() {
if (decompiler == null) {
return null;
}
if (cls.getSmali() == null) {
decompiler.generateSmali(cls);
}
return cls.getSmali();
}
......
......@@ -111,9 +111,8 @@ public final class ResourcesLoader {
private static ResContainer decodeImage(ResourceFile rf, InputStream inputStream) {
String name = rf.getName();
if (name.endsWith(".9.png")) {
Res9patchStreamDecoder decoder = new Res9patchStreamDecoder();
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
Res9patchStreamDecoder decoder = new Res9patchStreamDecoder();
decoder.decode(inputStream, os);
return ResContainer.decodedData(rf.getName(), os.toByteArray());
} catch (Exception e) {
......
......@@ -35,6 +35,7 @@ import jadx.core.dex.nodes.parser.AnnotationsParser;
import jadx.core.dex.nodes.parser.FieldInitAttr;
import jadx.core.dex.nodes.parser.SignatureParser;
import jadx.core.dex.nodes.parser.StaticValuesParser;
import jadx.core.utils.SmaliUtils;
import jadx.core.utils.exceptions.DecodeException;
import jadx.core.utils.exceptions.JadxRuntimeException;
......@@ -45,6 +46,7 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
private static final Logger LOG = LoggerFactory.getLogger(ClassNode.class);
private final DexNode dex;
private final int clsDefOffset;
private final ClassInfo clsInfo;
private AccessInfo accessFlags;
private ArgType superClass;
......@@ -68,6 +70,7 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
public ClassNode(DexNode dex, ClassDef cls) {
this.dex = dex;
this.clsDefOffset = cls.getOffset();
this.clsInfo = ClassInfo.fromDex(dex, cls.getTypeIndex());
try {
if (cls.getSupertypeIndex() == DexNode.NO_INDEX) {
......@@ -135,6 +138,7 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
// empty synthetic class
public ClassNode(DexNode dex, String name, int accessFlags) {
this.dex = dex;
this.clsDefOffset = 0;
this.clsInfo = ClassInfo.fromName(dex.root(), name);
this.interfaces = new ArrayList<>();
this.methods = new ArrayList<>();
......@@ -495,11 +499,10 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
return clsInfo.getAliasPkg();
}
public void setSmali(String smali) {
this.smali = smali;
}
public String getSmali() {
if (smali == null) {
smali = SmaliUtils.getSmaliCode(dex, clsDefOffset);
}
return smali;
}
......
package jadx.core.utils;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Path;
import org.jetbrains.annotations.NotNull;
import org.jf.baksmali.Adaptors.ClassDefinition;
import org.jf.baksmali.BaksmaliOptions;
import org.jf.dexlib2.DexFileFactory;
import org.jf.dexlib2.dexbacked.DexBackedClassDef;
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.smali.Smali;
import org.jf.smali.SmaliOptions;
import org.jf.util.IndentingWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.core.dex.nodes.DexNode;
import jadx.core.utils.exceptions.JadxRuntimeException;
// TODO: move smali dependencies out from jadx-core
public class SmaliUtils {
private static final Logger LOG = LoggerFactory.getLogger(SmaliUtils.class);
public static void assembleDex(String outputDexFile, String inputSmali) {
try {
SmaliOptions options = new SmaliOptions();
options.outputDexFile = outputDexFile;
Smali.assemble(options, inputSmali);
} catch (Exception e) {
throw new JadxRuntimeException("Smali assemble error", e);
}
}
@NotNull
public static String getSmaliCode(DexNode dex, int clsDefOffset) {
try {
Path path = dex.getDexFile().getPath();
DexBackedDexFile dexFile = DexFileFactory.loadDexFile(path.toFile(), null);
DexBackedClassDef dexBackedClassDef = new DexBackedClassDef(dexFile, clsDefOffset);
return getSmaliCode(dexBackedClassDef);
} catch (Exception e) {
LOG.error("Error generating smali", e);
return "Error generating smali code: " + e.getMessage()
+ '\n' + Utils.getStackTrace(e);
}
}
private static String getSmaliCode(DexBackedClassDef classDef) throws IOException {
ClassDefinition classDefinition = new ClassDefinition(new BaksmaliOptions(), classDef);
StringWriter sw = new StringWriter();
classDefinition.writeTo(new IndentingWriter(sw));
return sw.toString();
}
}
......@@ -17,7 +17,6 @@
package jadx.core.utils.android;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.IOException;
import java.io.InputStream;
......@@ -25,27 +24,23 @@ import java.io.OutputStream;
import javax.imageio.ImageIO;
import com.google.common.io.ByteStreams;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.exceptions.JadxRuntimeException;
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public class Res9patchStreamDecoder {
public void decode(InputStream in, OutputStream out) throws JadxException {
public void decode(InputStream in, OutputStream out) {
try {
byte[] data = ByteStreams.toByteArray(in);
BufferedImage im = ImageIO.read(new ByteArrayInputStream(data));
BufferedImage im = ImageIO.read(in);
int w = im.getWidth();
int h = im.getHeight();
BufferedImage im2 = new BufferedImage(w + 2, h + 2, BufferedImage.TYPE_INT_ARGB);
im2.createGraphics().drawImage(im, 1, 1, w, h, null);
NinePatch np = getNinePatch(data);
NinePatch np = getNinePatch(in);
drawHLine(im2, h + 1, np.padLeft + 1, w - np.padRight);
drawVLine(im2, w + 1, np.padTop + 1, h - np.padBottom);
......@@ -60,25 +55,25 @@ public class Res9patchStreamDecoder {
}
ImageIO.write(im2, "png", out);
} catch (IOException | NullPointerException ex) {
throw new JadxException(ex.toString());
} catch (Exception e) {
throw new JadxRuntimeException("9patch image decode error", e);
}
}
private NinePatch getNinePatch(byte[] data) throws JadxException, IOException {
ExtDataInput di = new ExtDataInput(new ByteArrayInputStream(data));
private NinePatch getNinePatch(InputStream in) throws IOException {
ExtDataInput di = new ExtDataInput(in);
find9patchChunk(di);
return NinePatch.decode(di);
}
private void find9patchChunk(DataInput di) throws JadxException, IOException {
private void find9patchChunk(DataInput di) throws IOException {
di.skipBytes(8);
while (true) {
int size;
try {
size = di.readInt();
} catch (IOException ex) {
throw new JadxException("Cant find nine patch chunk", ex);
throw new JadxRuntimeException("Cant find nine patch chunk", ex);
}
if (di.readInt() == NP_CHUNK_TYPE) {
return;
......
package jadx.core.utils.files;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
......@@ -122,6 +123,13 @@ public class FileUtils {
}
}
public static byte[] streamToByteArray(InputStream input) throws IOException {
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
copyStream(input, out);
return out.toByteArray();
}
}
public static void close(Closeable c) {
if (c == null) {
return;
......
......@@ -14,8 +14,6 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.jetbrains.annotations.Nullable;
import org.jf.smali.Smali;
import org.jf.smali.SmaliOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -23,6 +21,7 @@ import com.android.dex.Dex;
import com.android.dex.DexException;
import jadx.core.utils.AsmUtils;
import jadx.core.utils.SmaliUtils;
import jadx.core.utils.exceptions.DecodeException;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.exceptions.JadxRuntimeException;
......@@ -58,9 +57,7 @@ public class InputFile {
}
if (fileName.endsWith(".smali")) {
Path output = FileUtils.createTempFile(".dex");
SmaliOptions options = new SmaliOptions();
options.outputDexFile = output.toAbsolutePath().toString();
Smali.assemble(options, file.getAbsolutePath());
SmaliUtils.assembleDex(output.toAbsolutePath().toString(), file.getAbsolutePath());
addDexFile(fileName, output);
return;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册