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