• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   // This should never be set for a device build, as changing class defs ids
103   // conflict with profiles and verification passed by Play.
104   static constexpr bool kChangeClassDefOrder = false;
105   static_assert(!(kIsTargetBuild && kChangeClassDefOrder), "Never set class reordering on target");
106 
DexLayout(Options & options,ProfileCompilationInfo * info,FILE * out_file,dex_ir::Header * header)107   DexLayout(Options& options,
108             ProfileCompilationInfo* info,
109             FILE* out_file,
110             dex_ir::Header* header)
111       : options_(options),
112         info_(info),
113         out_file_(out_file),
114         header_(header) { }
115 
116   int ProcessFile(const char* file_name);
117   bool ProcessDexFile(const char* file_name,
118                       const DexFile* dex_file,
119                       size_t dex_file_index,
120                       std::unique_ptr<DexContainer>* dex_container,
121                       std::string* error_msg);
122 
GetHeader()123   dex_ir::Header* GetHeader() const { return header_; }
SetHeader(dex_ir::Header * header)124   void SetHeader(dex_ir::Header* header) { header_ = header; }
125 
GetSections()126   DexLayoutSections& GetSections() {
127     return dex_sections_;
128   }
129 
LayoutHotnessInfo()130   const DexLayoutHotnessInfo& LayoutHotnessInfo() const {
131     return layout_hotness_info_;
132   }
133 
GetOptions()134   const Options& GetOptions() const {
135     return options_;
136   }
137 
138  private:
139   void DumpAnnotationSetItem(dex_ir::AnnotationSetItem* set_item);
140   void DumpBytecodes(uint32_t idx, const dex_ir::CodeItem* code, uint32_t code_offset);
141   void DumpCatches(const dex_ir::CodeItem* code);
142   void DumpClass(int idx, char** last_package);
143   void DumpClassAnnotations(int idx);
144   void DumpClassDef(int idx);
145   void DumpCode(uint32_t idx,
146                 const dex_ir::CodeItem* code,
147                 uint32_t code_offset,
148                 const char* declaring_class_descriptor,
149                 const char* method_name,
150                 bool is_static,
151                 const dex_ir::ProtoId* proto);
152   void DumpEncodedAnnotation(dex_ir::EncodedAnnotation* annotation);
153   void DumpEncodedValue(const dex_ir::EncodedValue* data);
154   void DumpFileHeader();
155   void DumpIField(uint32_t idx, uint32_t flags, uint32_t hiddenapi_flags, int i);
156   void DumpInstruction(const dex_ir::CodeItem* code,
157                        uint32_t code_offset,
158                        uint32_t insn_idx,
159                        uint32_t insn_width,
160                        const Instruction* dec_insn);
161   void DumpInterface(const dex_ir::TypeId* type_item, int i);
162   void DumpLocalInfo(const dex_ir::CodeItem* code);
163   void DumpMethod(uint32_t idx,
164                   uint32_t flags,
165                   uint32_t hiddenapi_flags,
166                   const dex_ir::CodeItem* code,
167                   int i);
168   void DumpPositionInfo(const dex_ir::CodeItem* code);
169   void DumpSField(uint32_t idx,
170                   uint32_t flags,
171                   uint32_t hiddenapi_flags,
172                   int i,
173                   dex_ir::EncodedValue* init);
174   void DumpDexFile();
175 
176   void LayoutClassDefsAndClassData(const DexFile* dex_file);
177   void LayoutCodeItems(const DexFile* dex_file);
178   void LayoutStringData(const DexFile* dex_file);
179 
180   // Creates a new layout for the dex file based on profile info.
181   // Currently reorders ClassDefs, ClassDataItems, and CodeItems.
182   void LayoutOutputFile(const DexFile* dex_file);
183   bool OutputDexFile(const DexFile* input_dex_file,
184                      bool compute_offsets,
185                      std::unique_ptr<DexContainer>* dex_container,
186                      std::string* error_msg);
187 
188   void DumpCFG(const DexFile* dex_file, int idx);
189   void DumpCFG(const DexFile* dex_file, uint32_t dex_method_idx, const dex::CodeItem* code);
190 
191   Options& options_;
192   ProfileCompilationInfo* info_;
193   FILE* out_file_;
194   dex_ir::Header* header_;
195   DexLayoutSections dex_sections_;
196   // Layout hotness information is only calculated when dexlayout is enabled.
197   DexLayoutHotnessInfo layout_hotness_info_;
198 
199   DISALLOW_COPY_AND_ASSIGN(DexLayout);
200 };
201 
202 }  // namespace art
203 
204 #endif  // ART_DEXLAYOUT_DEXLAYOUT_H_
205