blob: fdeb299aa4ccdfa88dda0a8b8574cc8b84078fe0 [file] [log] [blame]
Jeff Haoa8621002016-10-04 18:13:44 +00001/*
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 an in-memory representation of DEX files.
17 */
18
19#ifndef ART_DEXLAYOUT_DEX_WRITER_H_
20#define ART_DEXLAYOUT_DEX_WRITER_H_
21
Mathieu Chartier3e0c5172017-11-12 12:58:40 -080022#include <functional>
23
Jeff Haoa8621002016-10-04 18:13:44 +000024#include "base/unix_file/fd_file.h"
David Sehr9e734c72018-01-04 17:56:19 -080025#include "dex/compact_dex_level.h"
Mathieu Chartier8892c6b2018-01-09 15:10:17 -080026#include "dex/dex_file.h"
Jeff Haoa8621002016-10-04 18:13:44 +000027#include "dex_ir.h"
Jeff Haoea7c6292016-11-14 18:10:16 -080028#include "mem_map.h"
Jeff Haoa8621002016-10-04 18:13:44 +000029#include "os.h"
30
Mathieu Chartier3e0c5172017-11-12 12:58:40 -080031#include <queue>
32
Jeff Haoa8621002016-10-04 18:13:44 +000033namespace art {
34
Mathieu Chartier3e0c5172017-11-12 12:58:40 -080035class DexLayout;
36class DexLayoutHotnessInfo;
37
38struct MapItem {
39 // Not using DexFile::MapItemType since compact dex and standard dex file may have different
40 // sections.
41 MapItem() = default;
42 MapItem(uint32_t type, uint32_t size, uint32_t offset)
43 : type_(type), size_(size), offset_(offset) { }
44
45 // Sort by decreasing order since the priority_queue puts largest elements first.
46 bool operator>(const MapItem& other) const {
47 return offset_ > other.offset_;
48 }
49
50 uint32_t type_ = 0u;
51 uint32_t size_ = 0u;
52 uint32_t offset_ = 0u;
53};
54
55class MapItemQueue : public
56 std::priority_queue<MapItem, std::vector<MapItem>, std::greater<MapItem>> {
57 public:
58 void AddIfNotEmpty(const MapItem& item);
59};
60
Jeff Haoa8621002016-10-04 18:13:44 +000061class DexWriter {
62 public:
Mathieu Chartier8892c6b2018-01-09 15:10:17 -080063 static constexpr uint32_t kDataSectionAlignment = sizeof(uint32_t) * 2;
64 static constexpr uint32_t kDexSectionWordAlignment = 4;
65 static constexpr uint32_t kDexTryItemAlignment = sizeof(uint32_t);
66
67 static inline constexpr uint32_t SectionAlignment(DexFile::MapItemType type) {
68 switch (type) {
69 case DexFile::kDexTypeClassDataItem:
70 case DexFile::kDexTypeStringDataItem:
71 case DexFile::kDexTypeDebugInfoItem:
72 case DexFile::kDexTypeAnnotationItem:
73 case DexFile::kDexTypeEncodedArrayItem:
74 return alignof(uint8_t);
75
76 default:
77 // All other sections are kDexAlignedSection.
78 return DexWriter::kDexSectionWordAlignment;
79 }
80 }
81
Mathieu Chartier3e0c5172017-11-12 12:58:40 -080082 DexWriter(dex_ir::Header* header,
83 MemMap* mem_map,
84 DexLayout* dex_layout,
85 bool compute_offsets)
86 : header_(header),
87 mem_map_(mem_map),
88 dex_layout_(dex_layout),
89 compute_offsets_(compute_offsets) {}
Jeff Haoa8621002016-10-04 18:13:44 +000090
Mathieu Chartier3e0c5172017-11-12 12:58:40 -080091 static void Output(dex_ir::Header* header,
92 MemMap* mem_map,
93 DexLayout* dex_layout,
94 bool compute_offsets,
95 CompactDexLevel compact_dex_level);
Jeff Haoa8621002016-10-04 18:13:44 +000096
Mathieu Chartierf95a75e2017-11-03 15:25:52 -070097 virtual ~DexWriter() {}
98
99 protected:
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800100 virtual void WriteMemMap();
Jeff Haoa8621002016-10-04 18:13:44 +0000101
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800102 size_t Write(const void* buffer, size_t length, size_t offset) WARN_UNUSED;
103 size_t WriteSleb128(uint32_t value, size_t offset) WARN_UNUSED;
104 size_t WriteUleb128(uint32_t value, size_t offset) WARN_UNUSED;
105 size_t WriteEncodedValue(dex_ir::EncodedValue* encoded_value, size_t offset) WARN_UNUSED;
106 size_t WriteEncodedValueHeader(int8_t value_type, size_t value_arg, size_t offset) WARN_UNUSED;
107 size_t WriteEncodedArray(dex_ir::EncodedValueVector* values, size_t offset) WARN_UNUSED;
108 size_t WriteEncodedAnnotation(dex_ir::EncodedAnnotation* annotation, size_t offset) WARN_UNUSED;
109 size_t WriteEncodedFields(dex_ir::FieldItemVector* fields, size_t offset) WARN_UNUSED;
110 size_t WriteEncodedMethods(dex_ir::MethodItemVector* methods, size_t offset) WARN_UNUSED;
Jeff Haoa8621002016-10-04 18:13:44 +0000111
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800112 // Header and id section
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700113 virtual void WriteHeader();
Mathieu Chartierf6e31472017-12-28 13:32:08 -0800114 virtual size_t GetHeaderSize() const;
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800115 // reserve_only means don't write, only reserve space. This is required since the string data
116 // offsets must be assigned.
117 uint32_t WriteStringIds(uint32_t offset, bool reserve_only);
118 uint32_t WriteTypeIds(uint32_t offset);
119 uint32_t WriteProtoIds(uint32_t offset, bool reserve_only);
120 uint32_t WriteFieldIds(uint32_t offset);
121 uint32_t WriteMethodIds(uint32_t offset);
122 uint32_t WriteClassDefs(uint32_t offset, bool reserve_only);
123 uint32_t WriteCallSiteIds(uint32_t offset, bool reserve_only);
124
125 uint32_t WriteEncodedArrays(uint32_t offset);
126 uint32_t WriteAnnotations(uint32_t offset);
127 uint32_t WriteAnnotationSets(uint32_t offset);
128 uint32_t WriteAnnotationSetRefs(uint32_t offset);
129 uint32_t WriteAnnotationsDirectories(uint32_t offset);
130
131 // Data section.
132 uint32_t WriteDebugInfoItems(uint32_t offset);
133 uint32_t WriteCodeItems(uint32_t offset, bool reserve_only);
134 uint32_t WriteTypeLists(uint32_t offset);
135 uint32_t WriteStringDatas(uint32_t offset);
136 uint32_t WriteClassDatas(uint32_t offset);
137 uint32_t WriteMethodHandles(uint32_t offset);
138 uint32_t WriteMapItems(uint32_t offset, MapItemQueue* queue);
139 uint32_t GenerateAndWriteMapItems(uint32_t offset);
140
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800141 virtual uint32_t WriteCodeItemPostInstructionData(dex_ir::CodeItem* item,
142 uint32_t offset,
143 bool reserve_only);
144 virtual uint32_t WriteCodeItem(dex_ir::CodeItem* item, uint32_t offset, bool reserve_only);
145
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800146 // Process an offset, if compute_offset is set, write into the dex ir item, otherwise read the
147 // existing offset and use that for writing.
148 void ProcessOffset(uint32_t* const offset, dex_ir::Item* item) {
149 if (compute_offsets_) {
150 item->SetOffset(*offset);
151 } else {
152 // Not computing offsets, just use the one in the item.
153 *offset = item->GetOffset();
154 }
155 }
Jeff Haoa8621002016-10-04 18:13:44 +0000156
Jeff Haoea7c6292016-11-14 18:10:16 -0800157 dex_ir::Header* const header_;
158 MemMap* const mem_map_;
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800159 DexLayout* const dex_layout_;
160 bool compute_offsets_;
Jeff Haoa8621002016-10-04 18:13:44 +0000161
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700162 private:
Jeff Haoa8621002016-10-04 18:13:44 +0000163 DISALLOW_COPY_AND_ASSIGN(DexWriter);
164};
165
Jeff Haoa8621002016-10-04 18:13:44 +0000166} // namespace art
167
168#endif // ART_DEXLAYOUT_DEX_WRITER_H_