1 /*
2  * Copyright 2016, 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 
32 package org.jf.baksmali;
33 
34 import com.beust.jcommander.JCommander;
35 import com.beust.jcommander.Parameter;
36 import com.beust.jcommander.Parameters;
37 import org.jf.dexlib2.dexbacked.DexBackedDexFile;
38 import org.jf.dexlib2.dexbacked.raw.RawDexFile;
39 import org.jf.dexlib2.dexbacked.raw.util.DexAnnotator;
40 import org.jf.util.ConsoleUtil;
41 import org.jf.util.jcommander.ExtendedParameters;
42 
43 import javax.annotation.Nonnull;
44 import java.io.*;
45 import java.util.List;
46 
47 @Parameters(commandDescription = "Prints an annotated hex dump for the given dex file")
48 @ExtendedParameters(
49         commandName = "dump",
50         commandAliases = "du")
51 public class DumpCommand extends DexInputCommand {
52 
53     @Parameter(names = {"-h", "-?", "--help"}, help = true,
54             description = "Show usage information for this command.")
55     private boolean help;
56 
DumpCommand(@onnull List<JCommander> commandAncestors)57     public DumpCommand(@Nonnull List<JCommander> commandAncestors) {
58         super(commandAncestors);
59     }
60 
run()61     public void run() {
62         if (help || inputList == null || inputList.isEmpty()) {
63             usage();
64             return;
65         }
66 
67         if (inputList.size() > 1) {
68             System.err.println("Too many files specified");
69             usage();
70             return;
71         }
72 
73         String input = inputList.get(0);
74         loadDexFile(input);
75 
76         try {
77             dump(dexFile, System.out);
78         } catch (IOException ex) {
79             System.err.println("There was an error while dumping the dex file");
80             ex.printStackTrace(System.err);
81         }
82     }
83 
84     /**
85      * Writes an annotated hex dump of the given dex file to output.
86      *
87      * @param dexFile The dex file to dump
88      * @param output An OutputStream to write the annotated hex dump to. The caller is responsible for closing this
89      *               when needed.
90      *
91      * @throws IOException
92      */
dump(@onnull DexBackedDexFile dexFile, @Nonnull OutputStream output)93     public static void dump(@Nonnull DexBackedDexFile dexFile, @Nonnull OutputStream output)
94             throws IOException {
95         Writer writer = new BufferedWriter(new OutputStreamWriter(output));
96 
97         try {
98             int consoleWidth = ConsoleUtil.getConsoleWidth();
99             if (consoleWidth <= 0) {
100                 consoleWidth = 120;
101             }
102 
103             RawDexFile rawDexFile = new RawDexFile(dexFile.getOpcodes(), dexFile);
104             DexAnnotator annotator = new DexAnnotator(rawDexFile, consoleWidth);
105             annotator.writeAnnotations(writer);
106         } finally {
107             writer.close();
108         }
109     }
110 }
111