diff --git a/src/brut/androlib/AndrolibSmali.java b/src/brut/androlib/AndrolibSmali.java index 836f1c9f..8d0b44df 100644 --- a/src/brut/androlib/AndrolibSmali.java +++ b/src/brut/androlib/AndrolibSmali.java @@ -17,11 +17,24 @@ package brut.androlib; +import brut.directory.DirectoryException; +import brut.directory.FileDirectory; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import org.antlr.runtime.ANTLRInputStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.CommonTreeNodeStream; import org.jf.baksmali.baksmali; +import org.jf.dexlib.CodeItem; import org.jf.dexlib.DexFile; -import org.jf.smali.main; +import org.jf.dexlib.Util.ByteArrayAnnotatedOutput; +import org.jf.smali.smaliLexer; +import org.jf.smali.smaliParser; +import org.jf.smali.smaliTreeWalker; /** * @author Ryszard Wiśniewski @@ -44,7 +57,73 @@ public class AndrolibSmali { smali(dir.getAbsolutePath(), dexFile.getAbsolutePath()); } - public void smali(String dir, String dexFile) throws AndrolibException { - main.main(new String[]{dir, "-o", dexFile}); + public void smali(String dir, String dexFileName) throws AndrolibException { + try { + DexFile dexFile = new DexFile(); + + for (String fileName : new FileDirectory(dir).getFiles(true)) { + if (! assembleSmaliFile( + new File(dir + "/" + fileName), dexFile)) { + throw new AndrolibException( + "Could not smali file: " + fileName); + } + } + + dexFile.place(); + for (CodeItem codeItem: dexFile.CodeItemsSection.getItems()) { + codeItem.fixInstructions(true, true); + } + + dexFile.place(); + + ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(); + dexFile.writeTo(out); + byte[] bytes = out.toByteArray(); + + DexFile.calcSignature(bytes); + DexFile.calcChecksum(bytes); + + FileOutputStream fileOutputStream = new FileOutputStream(dexFileName); + fileOutputStream.write(bytes); + fileOutputStream.close(); + } catch (IOException ex) { + throw new AndrolibException("Could not smali files", ex); + } catch (DirectoryException ex) { + throw new AndrolibException("Could not smali files", ex); + } catch (RecognitionException ex) { + throw new AndrolibException("Could not smali files", ex); + } + } + + private static boolean assembleSmaliFile(File smaliFile, DexFile dexFile) throws IOException, RecognitionException { + ANTLRInputStream input = new ANTLRInputStream(new FileInputStream(smaliFile)); + input.name = smaliFile.getAbsolutePath(); + + smaliLexer lexer = new smaliLexer(input); + + CommonTokenStream tokens = new CommonTokenStream(lexer); + smaliParser parser = new smaliParser(tokens); + + smaliParser.smali_file_return result = parser.smali_file(); + + if (parser.getNumberOfSyntaxErrors() > 0 || lexer.getNumberOfLexerErrors() > 0) { + return false; + } + + CommonTree t = (CommonTree) result.getTree(); + + CommonTreeNodeStream treeStream = new CommonTreeNodeStream(t); + treeStream.setTokenStream(tokens); + + smaliTreeWalker dexGen = new smaliTreeWalker(treeStream); + + dexGen.dexFile = dexFile; + dexGen.smali_file(); + + if (dexGen.getNumberOfSyntaxErrors() > 0) { + return false; + } + + return true; } }