1 /*
2  * Copyright (C) 2016 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  * Header file of the dexlayout utility.
17  *
18  * This is a tool to read dex files into an internal representation,
19  * reorganize the representation, and emit dex files with a better
20  * file layout.
21  */
22 
23 #ifndef ART_DEXLAYOUT_DEXLAYOUT_H_
24 #define ART_DEXLAYOUT_DEXLAYOUT_H_
25 
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <unordered_map>
29 
30 #include "dex/compact_dex_level.h"
31 #include "dex_container.h"
32 #include "dex/dex_file_layout.h"
33 #include "dex_ir.h"
34 
35 namespace art {
36 
37 class DexFile;
38 class Instruction;
39 class ProfileCompilationInfo;
40 
41 /* Supported output formats. */
42 enum OutputFormat {
43   kOutputPlain = 0,  // default
44   kOutputXml,        // XML-style
45 };
46 
47 /* Command-line options. */
48 class Options {
49  public:
50   Options() = default;
51 
52   bool dump_ = false;
53   bool build_dex_ir_ = false;
54   bool checksum_only_ = false;
55   bool disassemble_ = false;
56   bool exports_only_ = false;
57   bool ignore_bad_checksum_ = false;
58   bool output_to_container_ = false;
59   bool show_annotations_ = false;
60   bool show_file_headers_ = false;
61   bool show_section_headers_ = false;
62   bool show_section_statistics_ = false;
63   bool verbose_ = false;
64   bool verify_output_ = kIsDebugBuild;
65   bool visualize_pattern_ = false;
66   bool update_checksum_ = false;
67   CompactDexLevel compact_dex_level_ = CompactDexLevel::kCompactDexLevelNone;
68   bool dedupe_code_items_ = true;
69   OutputFormat output_format_ = kOutputPlain;
70   const char* output_dex_directory_ = nullptr;
71   const char* output_file_name_ = nullptr;
72   const char* profile_file_name_ = nullptr;
73   // Filter that removes classes that don't have a matching descriptor (during IR creation).
74   // This speeds up cases when the output only requires a single class.
75   std::set<std::string> class_filter_;
76 };
77 
78 // Hotness info
79 class DexLayoutHotnessInfo {
80  public:
81   // Store layout information so that the offset calculation can specify the section sizes.
82   std::unordered_map<dex_ir::CodeItem*, LayoutType> code_item_layout_;
83 };
84 
85 class DexLayout {
86  public:
87   class VectorOutputContainer {
88    public:
89     // Begin is not necessarily aligned (for now).
Begin()90     uint8_t* Begin() {
91       return &data_[0];
92     }
93 
94    private:
95     std::vector<uint8_t> data_;
96   };
97 
98 
99   // Setting this to false disables class def layout entirely, which is stronger than strictly
100   // necessary to ensure the partial order w.r.t. class derivation. TODO: Re-enable (b/68317550).
101   static constexpr bool kChangeClassDefOrder = false;
102 
DexLayout(Options & options,ProfileCompilationInfo * info,FILE * out_file,dex_ir::Header * header)103   DexLayout(Options& options,
104             ProfileCompilationInfo* info,
105             FILE* out_file,
106             dex_ir::Header* header)
107       : options_(options),
108         info_(info),
109         out_file_(out_file),
110         header_(header) { }
111 
112   int ProcessFile(const char* file_name);
113   bool ProcessDexFile(const char* file_name,
114                       const DexFile* dex_file,
115                       size_t dex_file_index,
116                       std::unique_ptr<DexContainer>* dex_container,
117                       std::string* error_msg);
118 
GetHeader()119   dex_ir::Header* GetHeader() const { return header_; }
SetHeader(dex_ir::Header * header)120   void SetHeader(dex_ir::Header* header) { header_ = header; }
121 
GetSections()122   DexLayoutSections& GetSections() {
123     return dex_sections_;
124   }
125 
LayoutHotnessInfo()126   const DexLayoutHotnessInfo& LayoutHotnessInfo() const {
127     return layout_hotness_info_;
128   }
129 
GetOptions()130   const Options& GetOptions() const {
131     return options_;
132   }
133 
134  private:
135   void DumpAnnotationSetItem(dex_ir::AnnotationSetItem* set_item);
136   void DumpBytecodes(uint32_t idx, const dex_ir::CodeItem* code, uint32_t code_offset);
137   void DumpCatches(const dex_ir::CodeItem* code);
138   void DumpClass(int idx, char** last_package);
139   void DumpClassAnnotations(int idx);
140   void DumpClassDef(int idx);
141   void DumpCode(uint32_t idx,
142                 const dex_ir::CodeItem* code,
143                 uint32_t code_offset,
144                 const char* declaring_class_descriptor,
145                 const char* method_name,
146                 bool is_static,
147                 const dex_ir::ProtoId* proto);
148   void DumpEncodedAnnotation(dex_ir::EncodedAnnotation* annotation);
149   void DumpEncodedValue(const dex_ir::EncodedValue* data);
150   void DumpFileHeader();
151   void DumpIField(uint32_t idx, uint32_t flags, int i);
152   void DumpInstruction(const dex_ir::CodeItem* code,
153                        uint32_t code_offset,
154                        uint32_t insn_idx,
155                        uint32_t insn_width,
156                        const Instruction* dec_insn);
157   void DumpInterface(const dex_ir::TypeId* type_item, int i);
158   void DumpLocalInfo(const dex_ir::CodeItem* code);
159   void DumpMethod(uint32_t idx, uint32_t flags, const dex_ir::CodeItem* code, int i);
160   void DumpPositionInfo(const dex_ir::CodeItem* code);
161   void DumpSField(uint32_t idx, uint32_t flags, int i, dex_ir::EncodedValue* init);
162   void DumpDexFile();
163 
164   void LayoutClassDefsAndClassData(const DexFile* dex_file);
165   void LayoutCodeItems(const DexFile* dex_file);
166   void LayoutStringData(const DexFile* dex_file);
167 
168   // Creates a new layout for the dex file based on profile info.
169   // Currently reorders ClassDefs, ClassDataItems, and CodeItems.
170   void LayoutOutputFile(const DexFile* dex_file);
171   bool OutputDexFile(const DexFile* input_dex_file,
172                      bool compute_offsets,
173                      std::unique_ptr<DexContainer>* dex_container,
174                      std::string* error_msg);
175 
176   void DumpCFG(const DexFile* dex_file, int idx);
177   void DumpCFG(const DexFile* dex_file, uint32_t dex_method_idx, const DexFile::CodeItem* code);
178 
179   Options& options_;
180   ProfileCompilationInfo* info_;
181   FILE* out_file_;
182   dex_ir::Header* header_;
183   DexLayoutSections dex_sections_;
184   // Layout hotness information is only calculated when dexlayout is enabled.
185   DexLayoutHotnessInfo layout_hotness_info_;
186 
187   DISALLOW_COPY_AND_ASSIGN(DexLayout);
188 };
189 
190 }  // namespace art
191 
192 #endif  // ART_DEXLAYOUT_DEXLAYOUT_H_
193