Search in sources :

Example 1 with BaksmaliWriter

use of org.jf.baksmali.formatter.BaksmaliWriter in project jadx by skylot.

the class SmaliUtils method getSmaliCode.

public static String getSmaliCode(byte[] dexBuf, int clsDefOffset) {
    StringWriter stringWriter = new StringWriter();
    try {
        DexBackedDexFile dexFile = new DexBackedDexFile(null, dexBuf);
        DexBackedClassDef dexBackedClassDef = new DexBackedClassDef(dexFile, clsDefOffset, 0);
        ClassDefinition classDefinition = new ClassDefinition(new BaksmaliOptions(), dexBackedClassDef);
        classDefinition.writeTo(new BaksmaliWriter(stringWriter));
    } catch (Exception e) {
        LOG.error("Error generating smali", e);
        stringWriter.append("Error generating smali code: ");
        stringWriter.append(e.getMessage());
        stringWriter.append(System.lineSeparator());
        e.printStackTrace(new PrintWriter(stringWriter, true));
    }
    return stringWriter.toString();
}
Also used : DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) StringWriter(java.io.StringWriter) BaksmaliWriter(org.jf.baksmali.formatter.BaksmaliWriter) ClassDefinition(org.jf.baksmali.Adaptors.ClassDefinition) DexBackedClassDef(org.jf.dexlib2.dexbacked.DexBackedClassDef) BaksmaliOptions(org.jf.baksmali.BaksmaliOptions) PrintWriter(java.io.PrintWriter)

Example 2 with BaksmaliWriter

use of org.jf.baksmali.formatter.BaksmaliWriter in project smali by JesusFreke.

the class MethodDefinition method addAnalyzedInstructionMethodItems.

private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) {
    MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classDef.options.classPath, method, classDef.options.inlineResolver, classDef.options.normalizeVirtualMethods);
    AnalysisException analysisException = methodAnalyzer.getAnalysisException();
    if (analysisException != null) {
        // TODO: need to keep track of whether any errors occurred, so we can exit with a non-zero result
        methodItems.add(new CommentMethodItem(String.format("AnalysisException: %s", analysisException.getMessage()), analysisException.codeAddress, Integer.MIN_VALUE));
        analysisException.printStackTrace(System.err);
    }
    List<AnalyzedInstruction> instructions = methodAnalyzer.getAnalyzedInstructions();
    int currentCodeAddress = 0;
    for (int i = 0; i < instructions.size(); i++) {
        AnalyzedInstruction instruction = instructions.get(i);
        MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, currentCodeAddress, instruction.getInstruction());
        methodItems.add(methodItem);
        if (instruction.getInstruction().getOpcode().format == Format.UnresolvedOdexInstruction) {
            methodItems.add(new CommentedOutMethodItem(InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, currentCodeAddress, instruction.getOriginalInstruction())));
        }
        if (i != instructions.size() - 1) {
            methodItems.add(new BlankMethodItem(currentCodeAddress));
        }
        if (classDef.options.codeOffsets) {
            methodItems.add(new MethodItem(currentCodeAddress) {

                @Override
                public double getSortOrder() {
                    return -1000;
                }

                @Override
                public boolean writeTo(BaksmaliWriter writer) throws IOException {
                    writer.write("#@");
                    writer.writeUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL);
                    return true;
                }
            });
        }
        if (classDef.options.registerInfo != 0 && !instruction.getInstruction().getOpcode().format.isPayloadFormat) {
            methodItems.add(new PreInstructionRegisterInfoMethodItem(classDef.options.registerInfo, methodAnalyzer, registerFormatter, instruction, currentCodeAddress));
            methodItems.add(new PostInstructionRegisterInfoMethodItem(registerFormatter, instruction, currentCodeAddress));
        }
        currentCodeAddress += instruction.getInstruction().getCodeUnits();
    }
}
Also used : DebugMethodItem(org.jf.baksmali.Adaptors.Debug.DebugMethodItem) MethodAnalyzer(org.jf.dexlib2.analysis.MethodAnalyzer) IOException(java.io.IOException) AnalyzedInstruction(org.jf.dexlib2.analysis.AnalyzedInstruction) BaksmaliWriter(org.jf.baksmali.formatter.BaksmaliWriter) AnalysisException(org.jf.dexlib2.analysis.AnalysisException)

Example 3 with BaksmaliWriter

use of org.jf.baksmali.formatter.BaksmaliWriter in project smali by JesusFreke.

the class Baksmali method disassembleClass.

private static boolean disassembleClass(ClassDef classDef, ClassFileNameHandler fileNameHandler, BaksmaliOptions options) {
    /**
     * The path for the disassembly file is based on the package name
     * The class descriptor will look something like:
     * Ljava/lang/Object;
     * Where the there is leading 'L' and a trailing ';', and the parts of the
     * package name are separated by '/'
     */
    String classDescriptor = classDef.getType();
    // validate that the descriptor is formatted like we expect
    if (classDescriptor.charAt(0) != 'L' || classDescriptor.charAt(classDescriptor.length() - 1) != ';') {
        System.err.println("Unrecognized class descriptor - " + classDescriptor + " - skipping class");
        return false;
    }
    File smaliFile = null;
    try {
        smaliFile = fileNameHandler.getUniqueFilenameForClass(classDescriptor);
    } catch (IOException ex) {
        System.err.println("\n\nError occurred while creating file for class " + classDescriptor);
        ex.printStackTrace();
        return false;
    }
    // create and initialize the top level string template
    ClassDefinition classDefinition = new ClassDefinition(options, classDef);
    // write the disassembly
    BaksmaliWriter writer = null;
    try {
        File smaliParent = smaliFile.getParentFile();
        if (!smaliParent.exists()) {
            if (!smaliParent.mkdirs()) {
                // check again, it's likely it was created in a different thread
                if (!smaliParent.exists()) {
                    System.err.println("Unable to create directory " + smaliParent.toString() + " - skipping class");
                    return false;
                }
            }
        }
        if (!smaliFile.exists()) {
            if (!smaliFile.createNewFile()) {
                System.err.println("Unable to create file " + smaliFile.toString() + " - skipping class");
                return false;
            }
        }
        BufferedWriter bufWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(smaliFile), "UTF8"));
        writer = new BaksmaliWriter(bufWriter, options.implicitReferences ? classDef.getType() : null);
        classDefinition.writeTo(writer);
    } catch (Exception ex) {
        System.err.println("\n\nError occurred while disassembling class " + classDescriptor.replace('/', '.') + " - skipping class");
        ex.printStackTrace();
        // noinspection ResultOfMethodCallIgnored
        smaliFile.delete();
        return false;
    } finally {
        if (writer != null) {
            try {
                writer.close();
            } catch (Throwable ex) {
                System.err.println("\n\nError occurred while closing file " + smaliFile.toString());
                ex.printStackTrace();
            }
        }
    }
    return true;
}
Also used : BaksmaliWriter(org.jf.baksmali.formatter.BaksmaliWriter) ClassDefinition(org.jf.baksmali.Adaptors.ClassDefinition) DexFile(org.jf.dexlib2.iface.DexFile)

Example 4 with BaksmaliWriter

use of org.jf.baksmali.formatter.BaksmaliWriter in project smali by JesusFreke.

the class MethodDefinition method addInstructionMethodItems.

private void addInstructionMethodItems(List<MethodItem> methodItems) {
    int currentCodeAddress = 0;
    for (int i = 0; i < effectiveInstructions.size(); i++) {
        Instruction instruction = effectiveInstructions.get(i);
        MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, currentCodeAddress, instruction);
        methodItems.add(methodItem);
        if (i != effectiveInstructions.size() - 1) {
            methodItems.add(new BlankMethodItem(currentCodeAddress));
        }
        if (classDef.options.codeOffsets) {
            methodItems.add(new MethodItem(currentCodeAddress) {

                @Override
                public double getSortOrder() {
                    return -1000;
                }

                @Override
                public boolean writeTo(BaksmaliWriter writer) throws IOException {
                    writer.write("#@");
                    writer.writeUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL);
                    return true;
                }
            });
        }
        if (classDef.options.accessorComments && classDef.options.syntheticAccessorResolver != null && (instruction instanceof ReferenceInstruction)) {
            Opcode opcode = instruction.getOpcode();
            if (opcode.referenceType == ReferenceType.METHOD) {
                MethodReference methodReference = (MethodReference) ((ReferenceInstruction) instruction).getReference();
                try {
                    methodReference.validateReference();
                    if (SyntheticAccessorResolver.looksLikeSyntheticAccessor(methodReference.getName())) {
                        AccessedMember accessedMember = classDef.options.syntheticAccessorResolver.getAccessedMember(methodReference);
                        if (accessedMember != null) {
                            methodItems.add(new SyntheticAccessCommentMethodItem(classDef, accessedMember, currentCodeAddress));
                        }
                    }
                } catch (Reference.InvalidReferenceException e) {
                // Just ignore for now. We'll deal with it when processing the instruction
                }
            }
        }
        currentCodeAddress += instruction.getCodeUnits();
    }
}
Also used : DebugMethodItem(org.jf.baksmali.Adaptors.Debug.DebugMethodItem) Reference(org.jf.dexlib2.iface.reference.Reference) MethodReference(org.jf.dexlib2.iface.reference.MethodReference) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) IOException(java.io.IOException) OffsetInstruction(org.jf.dexlib2.iface.instruction.OffsetInstruction) AnalyzedInstruction(org.jf.dexlib2.analysis.AnalyzedInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) AccessedMember(org.jf.dexlib2.util.SyntheticAccessorResolver.AccessedMember) BaksmaliWriter(org.jf.baksmali.formatter.BaksmaliWriter) MethodReference(org.jf.dexlib2.iface.reference.MethodReference)

Example 5 with BaksmaliWriter

use of org.jf.baksmali.formatter.BaksmaliWriter in project smali by JesusFreke.

the class ClassDefinition method writeVirtualMethods.

private void writeVirtualMethods(BaksmaliWriter writer, Set<String> directMethods) throws IOException {
    boolean wroteHeader = false;
    Set<String> writtenMethods = new HashSet<String>();
    Iterable<? extends Method> virtualMethods;
    if (classDef instanceof DexBackedClassDef) {
        virtualMethods = ((DexBackedClassDef) classDef).getVirtualMethods(false);
    } else {
        virtualMethods = classDef.getVirtualMethods();
    }
    for (Method method : virtualMethods) {
        if (!wroteHeader) {
            writer.write("\n\n");
            writer.write("# virtual methods");
            wroteHeader = true;
        }
        writer.write('\n');
        // TODO: check for method validation errors
        String methodString = formatter.getShortMethodDescriptor(method);
        BaksmaliWriter methodWriter = writer;
        if (!writtenMethods.add(methodString)) {
            writer.write("# duplicate method ignored\n");
            methodWriter = getCommentingWriter(writer);
        } else if (directMethods.contains(methodString)) {
            writer.write("# There is both a direct and virtual method with this signature.\n" + "# You will need to rename one of these methods, including all references.\n");
            System.err.println(String.format("Duplicate direct+virtual method found: %s->%s", classDef.getType(), methodString));
            System.err.println("You will need to rename one of these methods, including all references.");
        }
        MethodImplementation methodImpl = method.getImplementation();
        if (methodImpl == null) {
            MethodDefinition.writeEmptyMethodTo(methodWriter, method, this);
        } else {
            MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
            methodDefinition.writeTo(methodWriter);
        }
    }
}
Also used : BaksmaliWriter(org.jf.baksmali.formatter.BaksmaliWriter) DexBackedClassDef(org.jf.dexlib2.dexbacked.DexBackedClassDef) HashSet(java.util.HashSet)

Aggregations

BaksmaliWriter (org.jf.baksmali.formatter.BaksmaliWriter)11 ClassDefinition (org.jf.baksmali.Adaptors.ClassDefinition)5 DexBackedClassDef (org.jf.dexlib2.dexbacked.DexBackedClassDef)5 StringWriter (java.io.StringWriter)4 HashSet (java.util.HashSet)4 IOException (java.io.IOException)2 DebugMethodItem (org.jf.baksmali.Adaptors.Debug.DebugMethodItem)2 AnalyzedInstruction (org.jf.dexlib2.analysis.AnalyzedInstruction)2 DexFile (org.jf.dexlib2.iface.DexFile)2 PrintWriter (java.io.PrintWriter)1 ArrayList (java.util.ArrayList)1 Nonnull (javax.annotation.Nonnull)1 InstructionMethodItem (org.jf.baksmali.Adaptors.Format.InstructionMethodItem)1 MethodDefinition (org.jf.baksmali.Adaptors.MethodDefinition)1 RegisterFormatter (org.jf.baksmali.Adaptors.RegisterFormatter)1 BaksmaliOptions (org.jf.baksmali.BaksmaliOptions)1 AnalysisException (org.jf.dexlib2.analysis.AnalysisException)1 ClassPath (org.jf.dexlib2.analysis.ClassPath)1 MethodAnalyzer (org.jf.dexlib2.analysis.MethodAnalyzer)1 BaseStringReference (org.jf.dexlib2.base.reference.BaseStringReference)1