1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.dx.command.dump; 18 19import com.android.dex.util.FileUtils; 20import com.android.dx.cf.iface.ParseException; 21import com.android.dx.util.HexParser; 22import java.io.UnsupportedEncodingException; 23 24/** 25 * Main class for the class file dumper. 26 */ 27public class Main { 28 29 private final Args parsedArgs = new Args(); 30 31 /** 32 * This class is uninstantiable. 33 */ 34 private Main() { 35 // This space intentionally left blank. 36 } 37 38 public static void main(String[] args) { 39 new Main().run(args); 40 } 41 42 /** 43 * Run! 44 */ 45 private void run(String[] args) { 46 int at = 0; 47 48 for (/*at*/; at < args.length; at++) { 49 String arg = args[at]; 50 if (arg.equals("--") || !arg.startsWith("--")) { 51 break; 52 } else if (arg.equals("--bytes")) { 53 parsedArgs.rawBytes = true; 54 } else if (arg.equals("--basic-blocks")) { 55 parsedArgs.basicBlocks = true; 56 } else if (arg.equals("--rop-blocks")) { 57 parsedArgs.ropBlocks = true; 58 } else if (arg.equals("--optimize")) { 59 parsedArgs.optimize = true; 60 } else if (arg.equals("--ssa-blocks")) { 61 parsedArgs.ssaBlocks = true; 62 } else if (arg.startsWith("--ssa-step=")) { 63 parsedArgs.ssaStep = arg.substring(arg.indexOf('=') + 1); 64 } else if (arg.equals("--debug")) { 65 parsedArgs.debug = true; 66 } else if (arg.equals("--dot")) { 67 parsedArgs.dotDump = true; 68 } else if (arg.equals("--strict")) { 69 parsedArgs.strictParse = true; 70 } else if (arg.startsWith("--width=")) { 71 arg = arg.substring(arg.indexOf('=') + 1); 72 parsedArgs.width = Integer.parseInt(arg); 73 } else if (arg.startsWith("--method=")) { 74 arg = arg.substring(arg.indexOf('=') + 1); 75 parsedArgs.method = arg; 76 } else { 77 System.err.println("unknown option: " + arg); 78 throw new RuntimeException("usage"); 79 } 80 } 81 82 if (at == args.length) { 83 System.err.println("no input files specified"); 84 throw new RuntimeException("usage"); 85 } 86 87 for (/*at*/; at < args.length; at++) { 88 try { 89 String name = args[at]; 90 System.out.println("reading " + name + "..."); 91 byte[] bytes = FileUtils.readFile(name); 92 if (!name.endsWith(".class")) { 93 String src; 94 try { 95 src = new String(bytes, "utf-8"); 96 } catch (UnsupportedEncodingException ex) { 97 throw new RuntimeException("shouldn't happen", ex); 98 } 99 bytes = HexParser.parse(src); 100 } 101 processOne(name, bytes); 102 } catch (ParseException ex) { 103 System.err.println("\ntrouble parsing:"); 104 if (parsedArgs.debug) { 105 ex.printStackTrace(); 106 } else { 107 ex.printContext(System.err); 108 } 109 } 110 } 111 } 112 113 /** 114 * Processes one file. 115 * 116 * @param name {@code non-null;} name of the file 117 * @param bytes {@code non-null;} contents of the file 118 */ 119 private void processOne(String name, byte[] bytes) { 120 if (parsedArgs.dotDump) { 121 DotDumper.dump(bytes, name, parsedArgs); 122 } else if (parsedArgs.basicBlocks) { 123 BlockDumper.dump(bytes, System.out, name, false, parsedArgs); 124 } else if (parsedArgs.ropBlocks) { 125 BlockDumper.dump(bytes, System.out, name, true, parsedArgs); 126 } else if (parsedArgs.ssaBlocks) { 127 // --optimize ignored with --ssa-blocks 128 parsedArgs.optimize = false; 129 SsaDumper.dump(bytes, System.out, name, parsedArgs); 130 } else { 131 ClassDumper.dump(bytes, System.out, name, parsedArgs); 132 } 133 } 134} 135