baksmali.java revision e9ee92dc4c0848146e00d5607eb4baa5750361c8
1/* 2 * [The "BSD licence"] 3 * Copyright (c) 2009 Ben Gruver 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29package org.jf.baksmali; 30 31import org.antlr.stringtemplate.StringTemplate; 32import org.antlr.stringtemplate.StringTemplateGroup; 33import org.jf.baksmali.Adaptors.ClassDefinition; 34import org.jf.baksmali.Renderers.*; 35import org.jf.dexlib.DexFile; 36import org.jf.dexlib.ClassDefItem; 37 38import java.io.*; 39import java.net.URL; 40 41public class baksmali { 42 public static void main(String[] args) throws Exception 43 { 44 if (args.length < 2) { 45 throw new UsageException(); 46 } 47 48 String dexFileName = args[0]; 49 String outputDirName = args[1]; 50 51 File dexFileFile = new File(dexFileName); 52 if (!dexFileFile.exists()) { 53 System.out.println("Can't find the file " + dexFileFile.toString()); 54 System.exit(1); 55 } 56 57 File outputDir = new File(outputDirName); 58 if (!outputDir.exists()) { 59 if (!outputDir.mkdirs()) { 60 System.out.println("Can't create the output directory " + outputDir.toString()); 61 System.exit(1); 62 } 63 } 64 65 DexFile dexFile = new DexFile(dexFileFile); 66 67 InputStream templateStream = baksmali.class.getClassLoader().getResourceAsStream("templates/baksmali.stg"); 68 StringTemplateGroup templates = new StringTemplateGroup(new InputStreamReader(templateStream)); 69 70 templates.registerRenderer(Long.class, new LongRenderer()); 71 templates.registerRenderer(Integer.class, new IntegerRenderer()); 72 templates.registerRenderer(Short.class, new ShortRenderer()); 73 templates.registerRenderer(Byte.class, new ByteRenderer()); 74 templates.registerRenderer(Float.class, new FloatRenderer()); 75 templates.registerRenderer(Character.class, new CharRenderer()); 76 77 int classCount = dexFile.ClassDefsSection.size(); 78 for (int i=0; i<classCount; i++) { 79 ClassDefItem classDef = dexFile.ClassDefsSection.getByIndex(i); 80 81 String classDescriptor = classDef.getClassType().getTypeDescriptor(); 82 if (classDescriptor.charAt(0) != 'L' || 83 classDescriptor.charAt(classDescriptor.length()-1) != ';') { 84 System.out.println("Unrecognized class descriptor - " + classDescriptor + " - skipping class"); 85 continue; 86 } 87 //trim off the leading L and trailing ; 88 classDescriptor = classDescriptor.substring(1, classDescriptor.length()-1); 89 String[] pathElements = classDescriptor.split("/"); 90 91 //build the path to the smali file to generate for this class 92 StringBuilder smaliPath = new StringBuilder(outputDir.getPath()); 93 for (String pathElement: pathElements) { 94 smaliPath.append(File.separatorChar); 95 smaliPath.append(pathElement); 96 } 97 smaliPath.append(".smali"); 98 99 File smaliFile = new File(smaliPath.toString()); 100 101 StringTemplate smaliFileST = templates.getInstanceOf("smaliFile"); 102 smaliFileST.setAttribute("classDef", new ClassDefinition(classDef)); 103 104 String output = smaliFileST.toString(); 105 106 FileWriter writer = null; 107 try 108 { 109 if (!smaliFile.getParentFile().exists()) { 110 if (!smaliFile.getParentFile().mkdirs()) { 111 System.out.println("Unable to create directory " + smaliFile.getParentFile().toString() + " - skipping class"); 112 continue; 113 } 114 } 115 if (!smaliFile.exists()){ 116 if (!smaliFile.createNewFile()) { 117 System.out.println("Unable to create file " + smaliFile.toString() + " - skipping class"); 118 continue; 119 } 120 } 121 122 writer = new FileWriter(smaliFile); 123 writer.write(output); 124 }finally 125 { 126 if (writer != null) 127 writer.close(); 128 } 129 } 130 } 131} 132