DumpVtables.java revision b2ce899471be1c136aa13d502e885585fa59d460
1/* 2 * Copyright 2013, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32package org.jf.dexlib2.analysis; 33 34import com.google.common.base.Splitter; 35import com.google.common.collect.Lists; 36import org.apache.commons.cli.*; 37import org.jf.dexlib2.DexFileFactory; 38import org.jf.dexlib2.dexbacked.DexBackedDexFile; 39import org.jf.dexlib2.iface.ClassDef; 40import org.jf.dexlib2.iface.Method; 41import org.jf.util.ConsoleUtil; 42 43import java.io.File; 44import java.io.FileOutputStream; 45import java.io.IOException; 46import java.util.ArrayList; 47import java.util.List; 48 49public class DumpVtables { 50 private static final Options options; 51 52 static { 53 options = new Options(); 54 buildOptions(); 55 } 56 57 public static void main(String[] args) { 58 CommandLineParser parser = new PosixParser(); 59 CommandLine commandLine; 60 61 try { 62 commandLine = parser.parse(options, args); 63 } catch (ParseException ex) { 64 usage(); 65 return; 66 } 67 68 String[] remainingArgs = commandLine.getArgs(); 69 70 Option[] parsedOptions = commandLine.getOptions(); 71 ArrayList<String> bootClassPathDirs = Lists.newArrayList(); 72 String outFile = "vtables.txt"; 73 int apiLevel = 15; 74 75 for (int i=0; i<parsedOptions.length; i++) { 76 Option option = parsedOptions[i]; 77 String opt = option.getOpt(); 78 79 switch (opt.charAt(0)) { 80 case 'd': 81 bootClassPathDirs.add(option.getValue()); 82 break; 83 case 'o': 84 outFile = option.getValue(); 85 break; 86 case 'a': 87 apiLevel = Integer.parseInt(commandLine.getOptionValue("a")); 88 break; 89 default: 90 assert false; 91 } 92 } 93 94 if (remainingArgs.length != 1) { 95 usage(); 96 return; 97 } 98 99 String inputDexFileName = remainingArgs[0]; 100 101 File dexFileFile = new File(inputDexFileName); 102 if (!dexFileFile.exists()) { 103 System.err.println("Can't find the file " + inputDexFileName); 104 System.exit(1); 105 } 106 107 try { 108 DexBackedDexFile dexFile = DexFileFactory.loadDexFile(dexFileFile, apiLevel); 109 Iterable<String> bootClassPaths = Splitter.on(":").split("core.jar:ext.jar:framework.jar:android.policy.jar:services.jar"); 110 ClassPath classPath = ClassPath.fromClassPath(bootClassPathDirs, bootClassPaths, dexFile, apiLevel); 111 FileOutputStream outStream = new FileOutputStream(outFile); 112 113 for (ClassDef classDef: dexFile.getClasses()) { 114 ClassProto classProto = (ClassProto) classPath.getClass(classDef); 115 Method[] methods = classProto.getVtable(); 116 String className = "Class " + classDef.getType() + " extends " + classDef.getSuperclass() + " : " + methods.length + " methods\n"; 117 outStream.write(className.getBytes()); 118 for (int i=0;i<methods.length;i++) { 119 String method = i + ":" + methods[i].getDefiningClass() + "->" + methods[i].getName() + "("; 120 for (CharSequence parameter: methods[i].getParameterTypes()) { 121 method += parameter; 122 } 123 method += ")" + methods[i].getReturnType() + "\n"; 124 outStream.write(method.getBytes()); 125 } 126 outStream.write("\n".getBytes()); 127 } 128 outStream.close(); 129 } catch (IOException ex) { 130 System.out.println("IOException thrown when trying to open a dex file or write out vtables: " + ex); 131 } 132 133 } 134 135 /** 136 * Prints the usage message. 137 */ 138 private static void usage() { 139 int consoleWidth = ConsoleUtil.getConsoleWidth(); 140 if (consoleWidth <= 0) { 141 consoleWidth = 80; 142 } 143 144 System.out.println("java -cp baksmali.jar org.jf.dexlib2.analysis.DumpVtables -d path/to/jar/files <dex-file>"); 145 } 146 147 private static void buildOptions() { 148 Option classPathDirOption = OptionBuilder.withLongOpt("bootclasspath-dir") 149 .withDescription("the base folder to look for the bootclasspath files in. Defaults to the current " + 150 "directory") 151 .hasArg() 152 .withArgName("DIR") 153 .create("d"); 154 155 Option outputFileOption = OptionBuilder.withLongOpt("out-file") 156 .withDescription("output file") 157 .hasArg() 158 .withArgName("FILE") 159 .create("o"); 160 161 Option apiLevelOption = OptionBuilder.withLongOpt("api-level") 162 .withDescription("The numeric api-level of the file being disassembled. If not " + 163 "specified, it defaults to 15 (ICS).") 164 .hasArg() 165 .withArgName("API_LEVEL") 166 .create("a"); 167 168 options.addOption(classPathDirOption); 169 options.addOption(outputFileOption); 170 options.addOption(apiLevelOption); 171 } 172} 173