baksmali.java revision d166b746b91c114cd8d8fe4b054069083c33170b
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; 37import org.apache.commons.cli.*; 38 39import java.io.*; 40import java.net.URL; 41 42public class baksmali { 43 public static void main(String[] args) throws Exception 44 { 45 Options options = new Options(); 46 47 Option helpOption = OptionBuilder.withLongOpt("help") 48 .withDescription("prints the usage information for the -dis command") 49 .create("?"); 50 51 Option outputDirOption = OptionBuilder.withLongOpt("output") 52 .withDescription("the directory where the disassembled files will be placed. The default is out") 53 .hasArg() 54 .withArgName("DIR") 55 .create("out"); 56 57 options.addOption(helpOption); 58 options.addOption(outputDirOption); 59 60 CommandLineParser parser = new PosixParser(); 61 CommandLine commandLine; 62 63 try { 64 commandLine = parser.parse(options, args); 65 } catch (ParseException ex) { 66 printHelp(options); 67 return; 68 } 69 70 if (commandLine.hasOption("?")) { 71 printHelp(options); 72 return; 73 } 74 75 76 String[] leftover = commandLine.getArgs(); 77 78 if (leftover.length != 1) { 79 printHelp(options); 80 return; 81 } 82 83 String dexFileName = leftover[0]; 84 String outputDirName = commandLine.getOptionValue("out", "out"); 85 86 File dexFileFile = new File(dexFileName); 87 if (!dexFileFile.exists()) { 88 System.out.println("Can't find the file " + dexFileFile.toString()); 89 System.exit(1); 90 } 91 92 File outputDir = new File(outputDirName); 93 if (!outputDir.exists()) { 94 if (!outputDir.mkdirs()) { 95 System.out.println("Can't create the output directory " + outputDir.toString()); 96 System.exit(1); 97 } 98 } 99 100 DexFile dexFile = new DexFile(dexFileFile); 101 102 InputStream templateStream = baksmali.class.getClassLoader().getResourceAsStream("templates/baksmali.stg"); 103 StringTemplateGroup templates = new StringTemplateGroup(new InputStreamReader(templateStream)); 104 105 templates.registerRenderer(Long.class, new LongRenderer()); 106 templates.registerRenderer(Integer.class, new IntegerRenderer()); 107 templates.registerRenderer(Short.class, new ShortRenderer()); 108 templates.registerRenderer(Byte.class, new ByteRenderer()); 109 templates.registerRenderer(Float.class, new FloatRenderer()); 110 templates.registerRenderer(Character.class, new CharRenderer()); 111 112 int classCount = dexFile.ClassDefsSection.size(); 113 for (int i=0; i<classCount; i++) { 114 ClassDefItem classDef = dexFile.ClassDefsSection.getByIndex(i); 115 116 String classDescriptor = classDef.getClassType().getTypeDescriptor(); 117 if (classDescriptor.charAt(0) != 'L' || 118 classDescriptor.charAt(classDescriptor.length()-1) != ';') { 119 System.out.println("Unrecognized class descriptor - " + classDescriptor + " - skipping class"); 120 continue; 121 } 122 //trim off the leading L and trailing ; 123 classDescriptor = classDescriptor.substring(1, classDescriptor.length()-1); 124 String[] pathElements = classDescriptor.split("/"); 125 126 //build the path to the smali file to generate for this class 127 StringBuilder smaliPath = new StringBuilder(outputDir.getPath()); 128 for (String pathElement: pathElements) { 129 smaliPath.append(File.separatorChar); 130 smaliPath.append(pathElement); 131 } 132 smaliPath.append(".smali"); 133 134 File smaliFile = new File(smaliPath.toString()); 135 136 StringTemplate smaliFileST = templates.getInstanceOf("smaliFile"); 137 smaliFileST.setAttribute("classDef", new ClassDefinition(classDef)); 138 139 String output = smaliFileST.toString(); 140 141 FileWriter writer = null; 142 try 143 { 144 if (!smaliFile.getParentFile().exists()) { 145 if (!smaliFile.getParentFile().mkdirs()) { 146 System.out.println("Unable to create directory " + smaliFile.getParentFile().toString() + " - skipping class"); 147 continue; 148 } 149 } 150 if (!smaliFile.exists()){ 151 if (!smaliFile.createNewFile()) { 152 System.out.println("Unable to create file " + smaliFile.toString() + " - skipping class"); 153 continue; 154 } 155 } 156 157 writer = new FileWriter(smaliFile); 158 writer.write(output); 159 }finally 160 { 161 if (writer != null) 162 writer.close(); 163 } 164 } 165 } 166 167 /** 168 * Prints the usage message. 169 */ 170 private static void printHelp(Options options) { 171 HelpFormatter formatter = new HelpFormatter(); 172 formatter.printHelp("java -jar baksmali.jar -dis [-out <DIR>] <dexfile>", 173 "Disassembles the given dex file", options, ""); 174 } 175} 176