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