• 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 DumpMethodHandle(int idx);
144   void DumpCallSite(int idx);
145   void DumpClassAnnotations(int idx);
146   void DumpClassDef(int idx);
147   void DumpCode(uint32_t idx,
148                 const dex_ir::CodeItem* code,
149                 uint32_t code_offset,
150                 const char* declaring_class_descriptor,
151                 const char* method_name,
152                 bool is_static,
153                 const dex_ir::ProtoId* proto);
154   void DumpEncodedAnnotation(dex_ir::EncodedAnnotation* annotation);
155   void DumpEncodedValue(const dex_ir::EncodedValue* data);
156   void DumpFileHeader();
157   void DumpIField(uint32_t idx, uint32_t flags, uint32_t hiddenapi_flags, int i);
158   void DumpInstruction(const dex_ir::CodeItem* code,
159                        uint32_t code_offset,
160                        uint32_t insn_idx,
161                        uint32_t insn_width,
162                        const Instruction* dec_insn);
163   void DumpInterface(const dex_ir::TypeId* type_item, int i);
164   void DumpLocalInfo(const dex_ir::CodeItem* code);
165   void DumpMethod(uint32_t idx,
166                   uint32_t flags,
167                   uint32_t hiddenapi_flags,
168                   const dex_ir::CodeItem* code,
169                   int i);
170   void DumpPositionInfo(const dex_ir::CodeItem* code);
171   void DumpSField(uint32_t idx,
172                   uint32_t flags,
173                   uint32_t hiddenapi_flags,
174                   int i,
175                   dex_ir::EncodedValue* init);
176   void DumpDexFile();
177 
178   void LayoutClassDefsAndClassData(const DexFile* dex_file);
179   void LayoutCodeItems(const DexFile* dex_file);
180   void LayoutStringData(const DexFile* dex_file);
181 
182   // Creates a new layout for the dex file based on profile info.
183   // Currently reorders ClassDefs, ClassDataItems, and CodeItems.
184   void LayoutOutputFile(const DexFile* dex_file);
185   bool OutputDexFile(const DexFile* input_dex_file,
186                      bool compute_offsets,
187                      std::unique_ptr<DexContainer>* dex_container,
188                      std::string* error_msg);
189 
190   void DumpCFG(const DexFile* dex_file, int idx);
191   void DumpCFG(const DexFile* dex_file, uint32_t dex_method_idx, const dex::CodeItem* code);
192 
193   Options& options_;
194   ProfileCompilationInfo* info_;
195   FILE* out_file_;
196   dex_ir::Header* header_;
197   DexLayoutSections dex_sections_;
198   // Layout hotness information is only calculated when dexlayout is enabled.
199   DexLayoutHotnessInfo layout_hotness_info_;
200 
201   DISALLOW_COPY_AND_ASSIGN(DexLayout);
202 };
203 
204 class DexLoaderContainer : public MemoryDexFileContainer {
205  public:
DexLoaderContainer(const uint8_t * begin,const uint8_t * end,const uint8_t * data_begin,const uint8_t * data_end)206   DexLoaderContainer(const uint8_t* begin,
207                      const uint8_t* end,
208                      const uint8_t* data_begin,
209                      const uint8_t* data_end)
210       : MemoryDexFileContainer(begin, end), data_(data_begin, data_end - data_begin) {}
Data()211   ArrayRef<const uint8_t> Data() const override { return data_; }
212 
213  private:
214   ArrayRef<const uint8_t> data_;
215 };
216 
217 }  // namespace art
218 
219 #endif  // ART_DEXLAYOUT_DEXLAYOUT_H_
220