1*f0dffb02SXin Li /*
2*f0dffb02SXin Li * Copyright (C) 2017 The Android Open Source Project
3*f0dffb02SXin Li *
4*f0dffb02SXin Li * Licensed under the Apache License, Version 2.0 (the "License");
5*f0dffb02SXin Li * you may not use this file except in compliance with the License.
6*f0dffb02SXin Li * You may obtain a copy of the License at
7*f0dffb02SXin Li *
8*f0dffb02SXin Li * http://www.apache.org/licenses/LICENSE-2.0
9*f0dffb02SXin Li *
10*f0dffb02SXin Li * Unless required by applicable law or agreed to in writing, software
11*f0dffb02SXin Li * distributed under the License is distributed on an "AS IS" BASIS,
12*f0dffb02SXin Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*f0dffb02SXin Li * See the License for the specific language governing permissions and
14*f0dffb02SXin Li * limitations under the License.
15*f0dffb02SXin Li */
16*f0dffb02SXin Li
17*f0dffb02SXin Li #include "slicer/writer.h"
18*f0dffb02SXin Li
19*f0dffb02SXin Li #include "slicer/common.h"
20*f0dffb02SXin Li #include "slicer/scopeguard.h"
21*f0dffb02SXin Li #include "slicer/dex_bytecode.h"
22*f0dffb02SXin Li #include "slicer/dex_format.h"
23*f0dffb02SXin Li #include "slicer/dex_ir.h"
24*f0dffb02SXin Li #include "slicer/dex_leb128.h"
25*f0dffb02SXin Li
26*f0dffb02SXin Li #include <assert.h>
27*f0dffb02SXin Li #include <type_traits>
28*f0dffb02SXin Li #include <vector>
29*f0dffb02SXin Li #include <string.h>
30*f0dffb02SXin Li #include <algorithm>
31*f0dffb02SXin Li
32*f0dffb02SXin Li namespace dex {
33*f0dffb02SXin Li
34*f0dffb02SXin Li // Returns the IR node index, or kNoIndex for null IR nodes
35*f0dffb02SXin Li template <class T>
OptIndex(const T * ir_node)36*f0dffb02SXin Li static dex::u4 OptIndex(const T* ir_node) {
37*f0dffb02SXin Li return ir_node != nullptr ? ir_node->index : dex::kNoIndex;
38*f0dffb02SXin Li }
39*f0dffb02SXin Li
40*f0dffb02SXin Li // Helper for creating the header of an encoded value
WriteEncodedValueHeader(dex::u1 type,int arg,Section & data)41*f0dffb02SXin Li static void WriteEncodedValueHeader(dex::u1 type, int arg, Section& data) {
42*f0dffb02SXin Li assert((type & ~dex::kEncodedValueTypeMask) == 0);
43*f0dffb02SXin Li assert(arg >= 0 && arg < 8);
44*f0dffb02SXin Li dex::u1 header = dex::u1(type | (arg << dex::kEncodedValueArgShift));
45*f0dffb02SXin Li data.Push<dex::u1>(header);
46*f0dffb02SXin Li }
47*f0dffb02SXin Li
48*f0dffb02SXin Li // Writes an integer encoded value
49*f0dffb02SXin Li template <class T>
WriteIntValue(dex::u1 type,T value,Section & data)50*f0dffb02SXin Li static void WriteIntValue(dex::u1 type, T value, Section& data) {
51*f0dffb02SXin Li dex::u1 buff[sizeof(T)] = {};
52*f0dffb02SXin Li dex::u1* dst = buff;
53*f0dffb02SXin Li
54*f0dffb02SXin Li if (std::is_signed<T>::value) {
55*f0dffb02SXin Li const bool positive = (value >= 0);
56*f0dffb02SXin Li while (positive ? value >= 0x80 : value < -0x80) {
57*f0dffb02SXin Li *dst++ = value & 0xff;
58*f0dffb02SXin Li value >>= 8;
59*f0dffb02SXin Li }
60*f0dffb02SXin Li *dst++ = value & 0xff;
61*f0dffb02SXin Li } else {
62*f0dffb02SXin Li do {
63*f0dffb02SXin Li *dst++ = value & 0xff;
64*f0dffb02SXin Li value >>= 8;
65*f0dffb02SXin Li } while (value != 0);
66*f0dffb02SXin Li }
67*f0dffb02SXin Li
68*f0dffb02SXin Li size_t size = dst - buff;
69*f0dffb02SXin Li assert(size > 0 && size <= sizeof(T));
70*f0dffb02SXin Li WriteEncodedValueHeader(type, size - 1, data);
71*f0dffb02SXin Li data.Push(buff, size);
72*f0dffb02SXin Li }
73*f0dffb02SXin Li
74*f0dffb02SXin Li // Writes a floating point encoded value
75*f0dffb02SXin Li template <class T>
WriteFloatValue(dex::u1 type,T value,Section & data)76*f0dffb02SXin Li static void WriteFloatValue(dex::u1 type, T value, Section& data) {
77*f0dffb02SXin Li dex::u1 buff[sizeof(T)] = {};
78*f0dffb02SXin Li auto src = reinterpret_cast<const dex::u1*>(&value);
79*f0dffb02SXin Li size_t size = sizeof(T);
80*f0dffb02SXin Li
81*f0dffb02SXin Li // skip "rightmost" zero bytes
82*f0dffb02SXin Li while (size > 1 && *src == 0) {
83*f0dffb02SXin Li --size;
84*f0dffb02SXin Li ++src;
85*f0dffb02SXin Li }
86*f0dffb02SXin Li
87*f0dffb02SXin Li // copy the rest...
88*f0dffb02SXin Li for (size_t i = 0; i < size; ++i) {
89*f0dffb02SXin Li buff[i] = src[i];
90*f0dffb02SXin Li }
91*f0dffb02SXin Li
92*f0dffb02SXin Li assert(size > 0 && size <= sizeof(T));
93*f0dffb02SXin Li WriteEncodedValueHeader(type, size - 1, data);
94*f0dffb02SXin Li data.Push(buff, size);
95*f0dffb02SXin Li }
96*f0dffb02SXin Li
97*f0dffb02SXin Li static void WriteEncodedArray(const ir::EncodedArray* ir_array, Section& data);
98*f0dffb02SXin Li static void WriteAnnotation(const ir::Annotation* ir_annotation, Section& data);
99*f0dffb02SXin Li
100*f0dffb02SXin Li // "encoded_value"
WriteEncodedValue(const ir::EncodedValue * ir_value,Section & data)101*f0dffb02SXin Li static void WriteEncodedValue(const ir::EncodedValue* ir_value, Section& data) {
102*f0dffb02SXin Li SLICER_EXTRA(auto offset = data.size());
103*f0dffb02SXin Li
104*f0dffb02SXin Li dex::u1 type = ir_value->type;
105*f0dffb02SXin Li switch (type) {
106*f0dffb02SXin Li case dex::kEncodedByte:
107*f0dffb02SXin Li WriteIntValue(type, ir_value->u.byte_value, data);
108*f0dffb02SXin Li break;
109*f0dffb02SXin Li
110*f0dffb02SXin Li case dex::kEncodedShort:
111*f0dffb02SXin Li WriteIntValue(type, ir_value->u.short_value, data);
112*f0dffb02SXin Li break;
113*f0dffb02SXin Li
114*f0dffb02SXin Li case dex::kEncodedChar:
115*f0dffb02SXin Li WriteIntValue(type, ir_value->u.char_value, data);
116*f0dffb02SXin Li break;
117*f0dffb02SXin Li
118*f0dffb02SXin Li case dex::kEncodedInt:
119*f0dffb02SXin Li WriteIntValue(type, ir_value->u.int_value, data);
120*f0dffb02SXin Li break;
121*f0dffb02SXin Li
122*f0dffb02SXin Li case dex::kEncodedLong:
123*f0dffb02SXin Li WriteIntValue(type, ir_value->u.long_value, data);
124*f0dffb02SXin Li break;
125*f0dffb02SXin Li
126*f0dffb02SXin Li case dex::kEncodedFloat:
127*f0dffb02SXin Li WriteFloatValue(type, ir_value->u.float_value, data);
128*f0dffb02SXin Li break;
129*f0dffb02SXin Li
130*f0dffb02SXin Li case dex::kEncodedDouble:
131*f0dffb02SXin Li WriteFloatValue(type, ir_value->u.double_value, data);
132*f0dffb02SXin Li break;
133*f0dffb02SXin Li
134*f0dffb02SXin Li case dex::kEncodedString:
135*f0dffb02SXin Li WriteIntValue<dex::u4>(type, ir_value->u.string_value->index, data);
136*f0dffb02SXin Li break;
137*f0dffb02SXin Li
138*f0dffb02SXin Li case dex::kEncodedType:
139*f0dffb02SXin Li WriteIntValue<dex::u4>(type, ir_value->u.type_value->index, data);
140*f0dffb02SXin Li break;
141*f0dffb02SXin Li
142*f0dffb02SXin Li case dex::kEncodedField:
143*f0dffb02SXin Li WriteIntValue<dex::u4>(type, ir_value->u.field_value->index, data);
144*f0dffb02SXin Li break;
145*f0dffb02SXin Li
146*f0dffb02SXin Li case dex::kEncodedMethod:
147*f0dffb02SXin Li WriteIntValue<dex::u4>(type, ir_value->u.method_value->index, data);
148*f0dffb02SXin Li break;
149*f0dffb02SXin Li
150*f0dffb02SXin Li case dex::kEncodedEnum:
151*f0dffb02SXin Li WriteIntValue<dex::u4>(type, ir_value->u.enum_value->index, data);
152*f0dffb02SXin Li break;
153*f0dffb02SXin Li
154*f0dffb02SXin Li case dex::kEncodedArray:
155*f0dffb02SXin Li WriteEncodedValueHeader(type, 0, data);
156*f0dffb02SXin Li WriteEncodedArray(ir_value->u.array_value, data);
157*f0dffb02SXin Li break;
158*f0dffb02SXin Li
159*f0dffb02SXin Li case dex::kEncodedAnnotation:
160*f0dffb02SXin Li WriteEncodedValueHeader(type, 0, data);
161*f0dffb02SXin Li WriteAnnotation(ir_value->u.annotation_value, data);
162*f0dffb02SXin Li break;
163*f0dffb02SXin Li
164*f0dffb02SXin Li case dex::kEncodedNull:
165*f0dffb02SXin Li WriteEncodedValueHeader(type, 0, data);
166*f0dffb02SXin Li break;
167*f0dffb02SXin Li
168*f0dffb02SXin Li case dex::kEncodedBoolean: {
169*f0dffb02SXin Li int arg = ir_value->u.bool_value ? 1 : 0;
170*f0dffb02SXin Li WriteEncodedValueHeader(type, arg, data);
171*f0dffb02SXin Li } break;
172*f0dffb02SXin Li
173*f0dffb02SXin Li default:
174*f0dffb02SXin Li SLICER_CHECK(!"unexpected value type");
175*f0dffb02SXin Li }
176*f0dffb02SXin Li
177*f0dffb02SXin Li // optionally check the encoding against the original one
178*f0dffb02SXin Li // (if possible, some of the values contain relocated indexes)
179*f0dffb02SXin Li SLICER_EXTRA({
180*f0dffb02SXin Li switch (type) {
181*f0dffb02SXin Li case dex::kEncodedByte:
182*f0dffb02SXin Li case dex::kEncodedShort:
183*f0dffb02SXin Li case dex::kEncodedChar:
184*f0dffb02SXin Li case dex::kEncodedInt:
185*f0dffb02SXin Li case dex::kEncodedLong:
186*f0dffb02SXin Li case dex::kEncodedFloat:
187*f0dffb02SXin Li case dex::kEncodedDouble:
188*f0dffb02SXin Li case dex::kEncodedNull:
189*f0dffb02SXin Li case dex::kEncodedBoolean:
190*f0dffb02SXin Li auto ptr = data.ptr<const dex::u1>(offset);
191*f0dffb02SXin Li auto size = data.size() - offset;
192*f0dffb02SXin Li SLICER_CHECK_EQ(size, ir_value->original.size());
193*f0dffb02SXin Li SLICER_CHECK_EQ(memcmp(ptr, ir_value->original.ptr(), size), 0);
194*f0dffb02SXin Li break;
195*f0dffb02SXin Li }
196*f0dffb02SXin Li });
197*f0dffb02SXin Li }
198*f0dffb02SXin Li
199*f0dffb02SXin Li // "encoded_annotation"
WriteAnnotation(const ir::Annotation * ir_annotation,Section & data)200*f0dffb02SXin Li static void WriteAnnotation(const ir::Annotation* ir_annotation, Section& data) {
201*f0dffb02SXin Li data.PushULeb128(ir_annotation->type->index);
202*f0dffb02SXin Li data.PushULeb128(ir_annotation->elements.size());
203*f0dffb02SXin Li for (auto irAnnotationElement : ir_annotation->elements) {
204*f0dffb02SXin Li data.PushULeb128(irAnnotationElement->name->index);
205*f0dffb02SXin Li WriteEncodedValue(irAnnotationElement->value, data);
206*f0dffb02SXin Li }
207*f0dffb02SXin Li }
208*f0dffb02SXin Li
209*f0dffb02SXin Li // "encoded_array"
WriteEncodedArray(const ir::EncodedArray * ir_array,Section & data)210*f0dffb02SXin Li static void WriteEncodedArray(const ir::EncodedArray* ir_array, Section& data) {
211*f0dffb02SXin Li const auto& values = ir_array->values;
212*f0dffb02SXin Li data.PushULeb128(values.size());
213*f0dffb02SXin Li for (auto irEncodedValue : values) {
214*f0dffb02SXin Li WriteEncodedValue(irEncodedValue, data);
215*f0dffb02SXin Li }
216*f0dffb02SXin Li }
217*f0dffb02SXin Li
218*f0dffb02SXin Li // helper for concatenating .dex sections into the final image
219*f0dffb02SXin Li template <class T>
CopySection(const T & section,dex::u1 * image,dex::u4 image_size)220*f0dffb02SXin Li static void CopySection(const T& section, dex::u1* image, dex::u4 image_size) {
221*f0dffb02SXin Li if (section.size() == 0) {
222*f0dffb02SXin Li SLICER_CHECK_EQ(section.ItemsCount(), 0);
223*f0dffb02SXin Li return;
224*f0dffb02SXin Li }
225*f0dffb02SXin Li
226*f0dffb02SXin Li SLICER_CHECK_GT(section.ItemsCount(), 0);
227*f0dffb02SXin Li dex::u4 offset = section.SectionOffset();
228*f0dffb02SXin Li dex::u4 size = section.size();
229*f0dffb02SXin Li SLICER_CHECK_GE(offset, dex::Header::kV40Size);
230*f0dffb02SXin Li SLICER_CHECK_LE(offset + size, image_size);
231*f0dffb02SXin Li
232*f0dffb02SXin Li ::memcpy(image + offset, section.data(), size);
233*f0dffb02SXin Li }
234*f0dffb02SXin Li
ReadU4(const u2 * ptr)235*f0dffb02SXin Li static u4 ReadU4(const u2* ptr) { return ptr[0] | (u4(ptr[1]) << 16); }
236*f0dffb02SXin Li
WriteU4(u2 * ptr,u4 val)237*f0dffb02SXin Li static void WriteU4(u2* ptr, u4 val) {
238*f0dffb02SXin Li ptr[0] = val & 0xffff;
239*f0dffb02SXin Li ptr[1] = val >> 16;
240*f0dffb02SXin Li }
241*f0dffb02SXin Li
242*f0dffb02SXin Li // This is the main interface for the .dex writer
243*f0dffb02SXin Li // (returns nullptr on failure)
CreateImage(Allocator * allocator,size_t * new_image_size)244*f0dffb02SXin Li dex::u1* Writer::CreateImage(Allocator* allocator, size_t* new_image_size) {
245*f0dffb02SXin Li // create a new DexImage
246*f0dffb02SXin Li dex_.reset(new DexImage);
247*f0dffb02SXin Li
248*f0dffb02SXin Li SLICER_SCOPE_EXIT {
249*f0dffb02SXin Li dex_.reset();
250*f0dffb02SXin Li };
251*f0dffb02SXin Li
252*f0dffb02SXin Li // TODO: revisit IR normalization
253*f0dffb02SXin Li // (ideally we shouldn't change the IR while generating an image)
254*f0dffb02SXin Li dex_ir_->Normalize();
255*f0dffb02SXin Li
256*f0dffb02SXin Li int version = Header::GetVersion(dex_ir_->magic.ptr());
257*f0dffb02SXin Li SLICER_CHECK_NE(version, 0);
258*f0dffb02SXin Li SLICER_CHECK_GE(version, Header::kMinVersion);
259*f0dffb02SXin Li SLICER_CHECK_LE(version, Header::kMaxVersion);
260*f0dffb02SXin Li u4 header_size = version >= Header::kV41 ? Header::kV41Size : Header::kV40Size;
261*f0dffb02SXin Li
262*f0dffb02SXin Li // track the current offset within the .dex image
263*f0dffb02SXin Li dex::u4 offset = 0;
264*f0dffb02SXin Li
265*f0dffb02SXin Li // allocate the image and index sections
266*f0dffb02SXin Li // (they will be back-filled)
267*f0dffb02SXin Li offset += header_size;
268*f0dffb02SXin Li offset += dex_->string_ids.Init(offset, dex_ir_->strings.size());
269*f0dffb02SXin Li offset += dex_->type_ids.Init(offset, dex_ir_->types.size());
270*f0dffb02SXin Li offset += dex_->proto_ids.Init(offset, dex_ir_->protos.size());
271*f0dffb02SXin Li offset += dex_->field_ids.Init(offset, dex_ir_->fields.size());
272*f0dffb02SXin Li offset += dex_->method_ids.Init(offset, dex_ir_->methods.size());
273*f0dffb02SXin Li offset += dex_->class_defs.Init(offset, dex_ir_->classes.size());
274*f0dffb02SXin Li offset += dex_->method_handles.Init(offset, dex_ir_->method_handles.size());
275*f0dffb02SXin Li
276*f0dffb02SXin Li // the base offset for the "data" meta-section
277*f0dffb02SXin Li SLICER_CHECK_EQ(offset % 4, 0);
278*f0dffb02SXin Li const dex::u4 data_offset = offset;
279*f0dffb02SXin Li
280*f0dffb02SXin Li // we must create the sections in a very specific
281*f0dffb02SXin Li // order due to file pointers across sections
282*f0dffb02SXin Li offset += CreateStringDataSection(offset);
283*f0dffb02SXin Li offset += CreateTypeListsSection(offset);
284*f0dffb02SXin Li offset += CreateDebugInfoSection(offset);
285*f0dffb02SXin Li offset += CreateEncodedArrayItemSection(offset);
286*f0dffb02SXin Li offset += CreateCodeItemSection(offset);
287*f0dffb02SXin Li offset += CreateClassDataSection(offset);
288*f0dffb02SXin Li offset += CreateAnnItemSection(offset);
289*f0dffb02SXin Li offset += CreateAnnSetsSection(offset);
290*f0dffb02SXin Li offset += CreateAnnSetRefListsSection(offset);
291*f0dffb02SXin Li offset += CreateAnnDirectoriesSection(offset);
292*f0dffb02SXin Li offset += CreateMapSection(offset);
293*f0dffb02SXin Li
294*f0dffb02SXin Li // back-fill the indexes
295*f0dffb02SXin Li FillTypes();
296*f0dffb02SXin Li FillFields();
297*f0dffb02SXin Li FillProtos();
298*f0dffb02SXin Li FillMethods();
299*f0dffb02SXin Li FillClassDefs();
300*f0dffb02SXin Li FillMethodHandles();
301*f0dffb02SXin Li
302*f0dffb02SXin Li // allocate the final buffer for the .dex image
303*f0dffb02SXin Li SLICER_CHECK_EQ(offset % 4, 0);
304*f0dffb02SXin Li const dex::u4 image_size = offset;
305*f0dffb02SXin Li dex::u1* image = static_cast<dex::u1*>(allocator->Allocate(image_size));
306*f0dffb02SXin Li if (image == nullptr) {
307*f0dffb02SXin Li // memory allocation failed, bailing out...
308*f0dffb02SXin Li return nullptr;
309*f0dffb02SXin Li }
310*f0dffb02SXin Li memset(image, 0, image_size);
311*f0dffb02SXin Li
312*f0dffb02SXin Li // finally, back-fill the header
313*f0dffb02SXin Li SLICER_CHECK_GT(image_size, header_size);
314*f0dffb02SXin Li
315*f0dffb02SXin Li dex::Header* header = reinterpret_cast<dex::Header*>(image + 0);
316*f0dffb02SXin Li
317*f0dffb02SXin Li // magic signature
318*f0dffb02SXin Li memcpy(header->magic, dex_ir_->magic.ptr(), dex_ir_->magic.size());
319*f0dffb02SXin Li
320*f0dffb02SXin Li header->file_size = image_size;
321*f0dffb02SXin Li header->header_size = header_size;
322*f0dffb02SXin Li header->endian_tag = dex::kEndianConstant;
323*f0dffb02SXin Li
324*f0dffb02SXin Li header->link_size = 0;
325*f0dffb02SXin Li header->link_off = 0;
326*f0dffb02SXin Li
327*f0dffb02SXin Li header->map_off = dex_->map_list.SectionOffset();
328*f0dffb02SXin Li header->string_ids_size = dex_->string_ids.ItemsCount();
329*f0dffb02SXin Li header->string_ids_off = dex_->string_ids.SectionOffset();
330*f0dffb02SXin Li header->type_ids_size = dex_->type_ids.ItemsCount();
331*f0dffb02SXin Li header->type_ids_off = dex_->type_ids.SectionOffset();
332*f0dffb02SXin Li header->proto_ids_size = dex_->proto_ids.ItemsCount();
333*f0dffb02SXin Li header->proto_ids_off = dex_->proto_ids.SectionOffset();
334*f0dffb02SXin Li header->field_ids_size = dex_->field_ids.ItemsCount();
335*f0dffb02SXin Li header->field_ids_off = dex_->field_ids.SectionOffset();
336*f0dffb02SXin Li header->method_ids_size = dex_->method_ids.ItemsCount();
337*f0dffb02SXin Li header->method_ids_off = dex_->method_ids.SectionOffset();
338*f0dffb02SXin Li header->class_defs_size = dex_->class_defs.ItemsCount();
339*f0dffb02SXin Li header->class_defs_off = dex_->class_defs.SectionOffset();
340*f0dffb02SXin Li header->data_size = image_size - data_offset;
341*f0dffb02SXin Li header->data_off = data_offset;
342*f0dffb02SXin Li if (version >= Header::kV41) {
343*f0dffb02SXin Li header->data_size = 0;
344*f0dffb02SXin Li header->data_off = 0;
345*f0dffb02SXin Li header->SetContainer(0, header->file_size);
346*f0dffb02SXin Li }
347*f0dffb02SXin Li
348*f0dffb02SXin Li // copy the individual sections to the final image
349*f0dffb02SXin Li CopySection(dex_->string_ids, image, image_size);
350*f0dffb02SXin Li CopySection(dex_->type_ids, image, image_size);
351*f0dffb02SXin Li CopySection(dex_->proto_ids, image, image_size);
352*f0dffb02SXin Li CopySection(dex_->field_ids, image, image_size);
353*f0dffb02SXin Li CopySection(dex_->method_ids, image, image_size);
354*f0dffb02SXin Li CopySection(dex_->class_defs, image, image_size);
355*f0dffb02SXin Li CopySection(dex_->method_handles, image, image_size);
356*f0dffb02SXin Li CopySection(dex_->string_data, image, image_size);
357*f0dffb02SXin Li CopySection(dex_->type_lists, image, image_size);
358*f0dffb02SXin Li CopySection(dex_->debug_info, image, image_size);
359*f0dffb02SXin Li CopySection(dex_->encoded_arrays, image, image_size);
360*f0dffb02SXin Li CopySection(dex_->code, image, image_size);
361*f0dffb02SXin Li CopySection(dex_->class_data, image, image_size);
362*f0dffb02SXin Li CopySection(dex_->ann_directories, image, image_size);
363*f0dffb02SXin Li CopySection(dex_->ann_set_ref_lists, image, image_size);
364*f0dffb02SXin Li CopySection(dex_->ann_sets, image, image_size);
365*f0dffb02SXin Li CopySection(dex_->ann_items, image, image_size);
366*f0dffb02SXin Li CopySection(dex_->map_list, image, image_size);
367*f0dffb02SXin Li
368*f0dffb02SXin Li // checksum
369*f0dffb02SXin Li header->checksum = dex::ComputeChecksum(header);
370*f0dffb02SXin Li
371*f0dffb02SXin Li *new_image_size = image_size;
372*f0dffb02SXin Li return image;
373*f0dffb02SXin Li }
374*f0dffb02SXin Li
375*f0dffb02SXin Li // "string_id_item" + string data section
CreateStringDataSection(dex::u4 section_offset)376*f0dffb02SXin Li dex::u4 Writer::CreateStringDataSection(dex::u4 section_offset) {
377*f0dffb02SXin Li auto& section = dex_->string_data;
378*f0dffb02SXin Li section.SetOffset(section_offset);
379*f0dffb02SXin Li
380*f0dffb02SXin Li const auto& strings = dex_ir_->strings;
381*f0dffb02SXin Li for (size_t i = 0; i < strings.size(); ++i) {
382*f0dffb02SXin Li const auto& ir_string = strings[i];
383*f0dffb02SXin Li auto dexStringId = &dex_->string_ids[i];
384*f0dffb02SXin Li
385*f0dffb02SXin Li dex::u4 offset = section.AddItem();
386*f0dffb02SXin Li section.Push(ir_string->data);
387*f0dffb02SXin Li dexStringId->string_data_off = section.AbsoluteOffset(offset);
388*f0dffb02SXin Li }
389*f0dffb02SXin Li
390*f0dffb02SXin Li dex::u4 size = section.Seal(4);
391*f0dffb02SXin Li return size;
392*f0dffb02SXin Li }
393*f0dffb02SXin Li
394*f0dffb02SXin Li // Helper for creating the map section
395*f0dffb02SXin Li template <class T>
AddMapItem(const T & section,std::vector<dex::MapItem> & items)396*f0dffb02SXin Li static void AddMapItem(const T& section, std::vector<dex::MapItem>& items) {
397*f0dffb02SXin Li if (section.ItemsCount() > 0) {
398*f0dffb02SXin Li SLICER_CHECK_GE(section.SectionOffset(), dex::Header::kV40Size);
399*f0dffb02SXin Li dex::MapItem map_item = {};
400*f0dffb02SXin Li map_item.type = section.MapEntryType();
401*f0dffb02SXin Li map_item.size = section.ItemsCount();
402*f0dffb02SXin Li map_item.offset = section.SectionOffset();
403*f0dffb02SXin Li items.push_back(map_item);
404*f0dffb02SXin Li }
405*f0dffb02SXin Li }
406*f0dffb02SXin Li
407*f0dffb02SXin Li // map_list section
CreateMapSection(dex::u4 section_offset)408*f0dffb02SXin Li dex::u4 Writer::CreateMapSection(dex::u4 section_offset) {
409*f0dffb02SXin Li auto& section = dex_->map_list;
410*f0dffb02SXin Li section.SetOffset(section_offset);
411*f0dffb02SXin Li section.AddItem(4);
412*f0dffb02SXin Li
413*f0dffb02SXin Li std::vector<dex::MapItem> map_items;
414*f0dffb02SXin Li
415*f0dffb02SXin Li dex::MapItem headerItem = {};
416*f0dffb02SXin Li headerItem.type = dex::kHeaderItem;
417*f0dffb02SXin Li headerItem.size = 1;
418*f0dffb02SXin Li headerItem.offset = 0;
419*f0dffb02SXin Li map_items.push_back(headerItem);
420*f0dffb02SXin Li
421*f0dffb02SXin Li AddMapItem(dex_->string_ids, map_items);
422*f0dffb02SXin Li AddMapItem(dex_->type_ids, map_items);
423*f0dffb02SXin Li AddMapItem(dex_->proto_ids, map_items);
424*f0dffb02SXin Li AddMapItem(dex_->field_ids, map_items);
425*f0dffb02SXin Li AddMapItem(dex_->method_ids, map_items);
426*f0dffb02SXin Li AddMapItem(dex_->class_defs, map_items);
427*f0dffb02SXin Li AddMapItem(dex_->method_handles, map_items);
428*f0dffb02SXin Li AddMapItem(dex_->string_data, map_items);
429*f0dffb02SXin Li AddMapItem(dex_->type_lists, map_items);
430*f0dffb02SXin Li AddMapItem(dex_->debug_info, map_items);
431*f0dffb02SXin Li AddMapItem(dex_->encoded_arrays, map_items);
432*f0dffb02SXin Li AddMapItem(dex_->code, map_items);
433*f0dffb02SXin Li AddMapItem(dex_->class_data, map_items);
434*f0dffb02SXin Li AddMapItem(dex_->ann_directories, map_items);
435*f0dffb02SXin Li AddMapItem(dex_->ann_set_ref_lists, map_items);
436*f0dffb02SXin Li AddMapItem(dex_->ann_sets, map_items);
437*f0dffb02SXin Li AddMapItem(dex_->ann_items, map_items);
438*f0dffb02SXin Li AddMapItem(dex_->map_list, map_items);
439*f0dffb02SXin Li
440*f0dffb02SXin Li std::sort(map_items.begin(), map_items.end(),
441*f0dffb02SXin Li [](const dex::MapItem& a, const dex::MapItem& b) {
442*f0dffb02SXin Li SLICER_CHECK_NE(a.offset, b.offset);
443*f0dffb02SXin Li return a.offset < b.offset;
444*f0dffb02SXin Li });
445*f0dffb02SXin Li
446*f0dffb02SXin Li section.Push<dex::u4>(map_items.size());
447*f0dffb02SXin Li section.Push(map_items);
448*f0dffb02SXin Li return section.Seal(4);
449*f0dffb02SXin Li }
450*f0dffb02SXin Li
451*f0dffb02SXin Li // annotation_item section
CreateAnnItemSection(dex::u4 section_offset)452*f0dffb02SXin Li dex::u4 Writer::CreateAnnItemSection(dex::u4 section_offset) {
453*f0dffb02SXin Li dex_->ann_items.SetOffset(section_offset);
454*f0dffb02SXin Li
455*f0dffb02SXin Li for (const auto& ir_node : dex_ir_->annotations) {
456*f0dffb02SXin Li if (ir_node->visibility != dex::kVisibilityEncoded) {
457*f0dffb02SXin Li // TODO: factor out the node_offset_ updating
458*f0dffb02SXin Li dex::u4& offset = node_offset_[ir_node.get()];
459*f0dffb02SXin Li SLICER_CHECK_EQ(offset, 0);
460*f0dffb02SXin Li offset = WriteAnnotationItem(ir_node.get());
461*f0dffb02SXin Li }
462*f0dffb02SXin Li }
463*f0dffb02SXin Li
464*f0dffb02SXin Li return dex_->ann_items.Seal(4);
465*f0dffb02SXin Li }
466*f0dffb02SXin Li
467*f0dffb02SXin Li // annotation_set_item section
CreateAnnSetsSection(dex::u4 section_offset)468*f0dffb02SXin Li dex::u4 Writer::CreateAnnSetsSection(dex::u4 section_offset) {
469*f0dffb02SXin Li dex_->ann_sets.SetOffset(section_offset);
470*f0dffb02SXin Li
471*f0dffb02SXin Li for (const auto& ir_node : dex_ir_->annotation_sets) {
472*f0dffb02SXin Li dex::u4& offset = node_offset_[ir_node.get()];
473*f0dffb02SXin Li SLICER_CHECK_EQ(offset, 0);
474*f0dffb02SXin Li offset = WriteAnnotationSet(ir_node.get());
475*f0dffb02SXin Li }
476*f0dffb02SXin Li
477*f0dffb02SXin Li return dex_->ann_sets.Seal(4);
478*f0dffb02SXin Li }
479*f0dffb02SXin Li
480*f0dffb02SXin Li // annotation_set_ref_list section
CreateAnnSetRefListsSection(dex::u4 section_offset)481*f0dffb02SXin Li dex::u4 Writer::CreateAnnSetRefListsSection(dex::u4 section_offset) {
482*f0dffb02SXin Li dex_->ann_set_ref_lists.SetOffset(section_offset);
483*f0dffb02SXin Li
484*f0dffb02SXin Li for (const auto& ir_node : dex_ir_->annotation_set_ref_lists) {
485*f0dffb02SXin Li dex::u4& offset = node_offset_[ir_node.get()];
486*f0dffb02SXin Li SLICER_CHECK_EQ(offset, 0);
487*f0dffb02SXin Li offset = WriteAnnotationSetRefList(ir_node.get());
488*f0dffb02SXin Li }
489*f0dffb02SXin Li
490*f0dffb02SXin Li return dex_->ann_set_ref_lists.Seal(4);
491*f0dffb02SXin Li }
492*f0dffb02SXin Li
493*f0dffb02SXin Li // type_list section
CreateTypeListsSection(dex::u4 section_offset)494*f0dffb02SXin Li dex::u4 Writer::CreateTypeListsSection(dex::u4 section_offset) {
495*f0dffb02SXin Li dex_->type_lists.SetOffset(section_offset);
496*f0dffb02SXin Li
497*f0dffb02SXin Li for (const auto& ir_type_list : dex_ir_->type_lists) {
498*f0dffb02SXin Li dex::u4& offset = node_offset_[ir_type_list.get()];
499*f0dffb02SXin Li SLICER_CHECK_EQ(offset, 0);
500*f0dffb02SXin Li offset = WriteTypeList(ir_type_list->types);
501*f0dffb02SXin Li }
502*f0dffb02SXin Li
503*f0dffb02SXin Li return dex_->type_lists.Seal(4);
504*f0dffb02SXin Li }
505*f0dffb02SXin Li
506*f0dffb02SXin Li // code_item section
CreateCodeItemSection(dex::u4 section_offset)507*f0dffb02SXin Li dex::u4 Writer::CreateCodeItemSection(dex::u4 section_offset) {
508*f0dffb02SXin Li dex_->code.SetOffset(section_offset);
509*f0dffb02SXin Li
510*f0dffb02SXin Li for (const auto& ir_node : dex_ir_->code) {
511*f0dffb02SXin Li dex::u4& offset = node_offset_[ir_node.get()];
512*f0dffb02SXin Li SLICER_CHECK_EQ(offset, 0);
513*f0dffb02SXin Li offset = WriteCode(ir_node.get());
514*f0dffb02SXin Li }
515*f0dffb02SXin Li
516*f0dffb02SXin Li dex::u4 size = dex_->code.Seal(4);
517*f0dffb02SXin Li return size;
518*f0dffb02SXin Li }
519*f0dffb02SXin Li
520*f0dffb02SXin Li // debug info section
CreateDebugInfoSection(dex::u4 section_offset)521*f0dffb02SXin Li dex::u4 Writer::CreateDebugInfoSection(dex::u4 section_offset) {
522*f0dffb02SXin Li dex_->debug_info.SetOffset(section_offset);
523*f0dffb02SXin Li
524*f0dffb02SXin Li for (const auto& ir_node : dex_ir_->debug_info) {
525*f0dffb02SXin Li dex::u4& offset = node_offset_[ir_node.get()];
526*f0dffb02SXin Li SLICER_CHECK_EQ(offset, 0);
527*f0dffb02SXin Li offset = WriteDebugInfo(ir_node.get());
528*f0dffb02SXin Li }
529*f0dffb02SXin Li
530*f0dffb02SXin Li dex::u4 size = dex_->debug_info.Seal(4);
531*f0dffb02SXin Li return size;
532*f0dffb02SXin Li }
533*f0dffb02SXin Li
534*f0dffb02SXin Li // class_data_item section
CreateClassDataSection(dex::u4 section_offset)535*f0dffb02SXin Li dex::u4 Writer::CreateClassDataSection(dex::u4 section_offset) {
536*f0dffb02SXin Li dex_->class_data.SetOffset(section_offset);
537*f0dffb02SXin Li
538*f0dffb02SXin Li const auto& classes = dex_ir_->classes;
539*f0dffb02SXin Li for (size_t i = 0; i < classes.size(); ++i) {
540*f0dffb02SXin Li auto ir_class = classes[i].get();
541*f0dffb02SXin Li auto dex_class_def = &dex_->class_defs[i];
542*f0dffb02SXin Li dex_class_def->class_data_off = WriteClassData(ir_class);
543*f0dffb02SXin Li }
544*f0dffb02SXin Li
545*f0dffb02SXin Li dex::u4 size = dex_->class_data.Seal(4);
546*f0dffb02SXin Li return size;
547*f0dffb02SXin Li }
548*f0dffb02SXin Li
549*f0dffb02SXin Li // annotations_directory section
CreateAnnDirectoriesSection(dex::u4 section_offset)550*f0dffb02SXin Li dex::u4 Writer::CreateAnnDirectoriesSection(dex::u4 section_offset) {
551*f0dffb02SXin Li dex_->ann_directories.SetOffset(section_offset);
552*f0dffb02SXin Li
553*f0dffb02SXin Li const auto& classes = dex_ir_->classes;
554*f0dffb02SXin Li for (size_t i = 0; i < classes.size(); ++i) {
555*f0dffb02SXin Li auto ir_class = classes[i].get();
556*f0dffb02SXin Li auto dex_class_def = &dex_->class_defs[i];
557*f0dffb02SXin Li dex_class_def->annotations_off = WriteClassAnnotations(ir_class);
558*f0dffb02SXin Li }
559*f0dffb02SXin Li
560*f0dffb02SXin Li return dex_->ann_directories.Seal(4);
561*f0dffb02SXin Li }
562*f0dffb02SXin Li
563*f0dffb02SXin Li // encoded_array_item section
CreateEncodedArrayItemSection(dex::u4 section_offset)564*f0dffb02SXin Li dex::u4 Writer::CreateEncodedArrayItemSection(dex::u4 section_offset) {
565*f0dffb02SXin Li dex_->encoded_arrays.SetOffset(section_offset);
566*f0dffb02SXin Li
567*f0dffb02SXin Li const auto& classes = dex_ir_->classes;
568*f0dffb02SXin Li for (size_t i = 0; i < classes.size(); ++i) {
569*f0dffb02SXin Li auto ir_class = classes[i].get();
570*f0dffb02SXin Li auto dex_class_def = &dex_->class_defs[i];
571*f0dffb02SXin Li dex_class_def->static_values_off = WriteClassStaticValues(ir_class);
572*f0dffb02SXin Li }
573*f0dffb02SXin Li
574*f0dffb02SXin Li return dex_->encoded_arrays.Seal(4);
575*f0dffb02SXin Li }
576*f0dffb02SXin Li
577*f0dffb02SXin Li // "type_id_item"
FillTypes()578*f0dffb02SXin Li void Writer::FillTypes() {
579*f0dffb02SXin Li const auto& types = dex_ir_->types;
580*f0dffb02SXin Li for (size_t i = 0; i < types.size(); ++i) {
581*f0dffb02SXin Li const auto& ir_type = types[i];
582*f0dffb02SXin Li auto dexTypeId = &dex_->type_ids[i];
583*f0dffb02SXin Li // CONSIDER: an automatic index check would be nice
584*f0dffb02SXin Li dexTypeId->descriptor_idx = ir_type->descriptor->index;
585*f0dffb02SXin Li }
586*f0dffb02SXin Li }
587*f0dffb02SXin Li
588*f0dffb02SXin Li // "proto_id_item"
FillProtos()589*f0dffb02SXin Li void Writer::FillProtos() {
590*f0dffb02SXin Li const auto& protos = dex_ir_->protos;
591*f0dffb02SXin Li for (size_t i = 0; i < protos.size(); ++i) {
592*f0dffb02SXin Li
593*f0dffb02SXin Li const auto& irProto = protos[i];
594*f0dffb02SXin Li auto dexProtoId = &dex_->proto_ids[i];
595*f0dffb02SXin Li
596*f0dffb02SXin Li dexProtoId->shorty_idx = irProto->shorty->index;
597*f0dffb02SXin Li dexProtoId->return_type_idx = irProto->return_type->index;
598*f0dffb02SXin Li dexProtoId->parameters_off = FilePointer(irProto->param_types);
599*f0dffb02SXin Li }
600*f0dffb02SXin Li }
601*f0dffb02SXin Li
FillMethodHandles()602*f0dffb02SXin Li void Writer::FillMethodHandles(){
603*f0dffb02SXin Li const auto& methodHandles = dex_ir_->method_handles;
604*f0dffb02SXin Li for(size_t i = 0; i < methodHandles.size(); ++i){
605*f0dffb02SXin Li
606*f0dffb02SXin Li const auto& irMethodHandle = methodHandles[i];
607*f0dffb02SXin Li auto dexMethodHandle = &dex_->method_handles[i];
608*f0dffb02SXin Li
609*f0dffb02SXin Li dexMethodHandle->method_handle_type = irMethodHandle->method_handle_type;
610*f0dffb02SXin Li
611*f0dffb02SXin Li if(irMethodHandle->IsField()){
612*f0dffb02SXin Li dexMethodHandle->field_or_method_id = irMethodHandle->field->index;
613*f0dffb02SXin Li }
614*f0dffb02SXin Li else{
615*f0dffb02SXin Li dexMethodHandle->field_or_method_id = irMethodHandle->method->index;
616*f0dffb02SXin Li }
617*f0dffb02SXin Li }
618*f0dffb02SXin Li }
619*f0dffb02SXin Li
620*f0dffb02SXin Li // "field_id_item"
FillFields()621*f0dffb02SXin Li void Writer::FillFields() {
622*f0dffb02SXin Li const auto& fields = dex_ir_->fields;
623*f0dffb02SXin Li for (size_t i = 0; i < fields.size(); ++i) {
624*f0dffb02SXin Li const auto& ir_field = fields[i];
625*f0dffb02SXin Li auto dexFieldId = &dex_->field_ids[i];
626*f0dffb02SXin Li dexFieldId->class_idx = ir_field->parent->index;
627*f0dffb02SXin Li dexFieldId->type_idx = ir_field->type->index;
628*f0dffb02SXin Li dexFieldId->name_idx = ir_field->name->index;
629*f0dffb02SXin Li }
630*f0dffb02SXin Li }
631*f0dffb02SXin Li
632*f0dffb02SXin Li // "method_id_item"
FillMethods()633*f0dffb02SXin Li void Writer::FillMethods() {
634*f0dffb02SXin Li const auto& methods = dex_ir_->methods;
635*f0dffb02SXin Li for (size_t i = 0; i < methods.size(); ++i) {
636*f0dffb02SXin Li const auto& ir_method = methods[i];
637*f0dffb02SXin Li auto dexMethodId = &dex_->method_ids[i];
638*f0dffb02SXin Li dexMethodId->class_idx = ir_method->parent->index;
639*f0dffb02SXin Li dexMethodId->proto_idx = ir_method->prototype->index;
640*f0dffb02SXin Li dexMethodId->name_idx = ir_method->name->index;
641*f0dffb02SXin Li }
642*f0dffb02SXin Li }
643*f0dffb02SXin Li
644*f0dffb02SXin Li // "class_def_item"
FillClassDefs()645*f0dffb02SXin Li void Writer::FillClassDefs() {
646*f0dffb02SXin Li const auto& classes = dex_ir_->classes;
647*f0dffb02SXin Li for (size_t i = 0; i < classes.size(); ++i) {
648*f0dffb02SXin Li auto ir_class = classes[i].get();
649*f0dffb02SXin Li auto dex_class_def = &dex_->class_defs[i];
650*f0dffb02SXin Li dex_class_def->class_idx = ir_class->type->index;
651*f0dffb02SXin Li dex_class_def->access_flags = ir_class->access_flags;
652*f0dffb02SXin Li dex_class_def->superclass_idx = OptIndex(ir_class->super_class);
653*f0dffb02SXin Li dex_class_def->source_file_idx = OptIndex(ir_class->source_file);
654*f0dffb02SXin Li dex_class_def->interfaces_off = FilePointer(ir_class->interfaces);
655*f0dffb02SXin Li
656*f0dffb02SXin Li // NOTE: we already set some offsets when we created the
657*f0dffb02SXin Li // corresponding .dex section:
658*f0dffb02SXin Li //
659*f0dffb02SXin Li // ->annotations_off
660*f0dffb02SXin Li // ->class_data_off
661*f0dffb02SXin Li // ->static_values_off
662*f0dffb02SXin Li }
663*f0dffb02SXin Li }
664*f0dffb02SXin Li
665*f0dffb02SXin Li // "type_list"
WriteTypeList(const std::vector<ir::Type * > & types)666*f0dffb02SXin Li dex::u4 Writer::WriteTypeList(const std::vector<ir::Type*>& types) {
667*f0dffb02SXin Li if (types.empty()) {
668*f0dffb02SXin Li return 0;
669*f0dffb02SXin Li }
670*f0dffb02SXin Li
671*f0dffb02SXin Li auto& data = dex_->type_lists;
672*f0dffb02SXin Li dex::u4 offset = data.AddItem(4);
673*f0dffb02SXin Li data.Push<dex::u4>(types.size());
674*f0dffb02SXin Li for (auto ir_type : types) {
675*f0dffb02SXin Li data.Push<dex::u2>(ir_type->index);
676*f0dffb02SXin Li }
677*f0dffb02SXin Li return data.AbsoluteOffset(offset);
678*f0dffb02SXin Li }
679*f0dffb02SXin Li
680*f0dffb02SXin Li // "annotation_item"
WriteAnnotationItem(const ir::Annotation * ir_annotation)681*f0dffb02SXin Li dex::u4 Writer::WriteAnnotationItem(const ir::Annotation* ir_annotation) {
682*f0dffb02SXin Li SLICER_CHECK_NE(ir_annotation->visibility, dex::kVisibilityEncoded);
683*f0dffb02SXin Li
684*f0dffb02SXin Li auto& data = dex_->ann_items;
685*f0dffb02SXin Li dex::u4 offset = data.AddItem();
686*f0dffb02SXin Li data.Push<dex::u1>(ir_annotation->visibility);
687*f0dffb02SXin Li WriteAnnotation(ir_annotation, data);
688*f0dffb02SXin Li return data.AbsoluteOffset(offset);
689*f0dffb02SXin Li }
690*f0dffb02SXin Li
691*f0dffb02SXin Li // "annotation_set_item"
WriteAnnotationSet(const ir::AnnotationSet * ir_annotation_set)692*f0dffb02SXin Li dex::u4 Writer::WriteAnnotationSet(const ir::AnnotationSet* ir_annotation_set) {
693*f0dffb02SXin Li SLICER_CHECK_NE(ir_annotation_set, nullptr);
694*f0dffb02SXin Li
695*f0dffb02SXin Li const auto& annotations = ir_annotation_set->annotations;
696*f0dffb02SXin Li
697*f0dffb02SXin Li auto& data = dex_->ann_sets;
698*f0dffb02SXin Li dex::u4 offset = data.AddItem(4);
699*f0dffb02SXin Li data.Push<dex::u4>(annotations.size());
700*f0dffb02SXin Li for (auto ir_annotation : annotations) {
701*f0dffb02SXin Li data.Push<dex::u4>(FilePointer(ir_annotation));
702*f0dffb02SXin Li }
703*f0dffb02SXin Li return data.AbsoluteOffset(offset);
704*f0dffb02SXin Li }
705*f0dffb02SXin Li
706*f0dffb02SXin Li // "annotation_set_ref_list"
WriteAnnotationSetRefList(const ir::AnnotationSetRefList * ir_annotation_set_ref_list)707*f0dffb02SXin Li dex::u4 Writer::WriteAnnotationSetRefList(
708*f0dffb02SXin Li const ir::AnnotationSetRefList* ir_annotation_set_ref_list) {
709*f0dffb02SXin Li SLICER_CHECK_NE(ir_annotation_set_ref_list, nullptr);
710*f0dffb02SXin Li
711*f0dffb02SXin Li const auto& annotations = ir_annotation_set_ref_list->annotations;
712*f0dffb02SXin Li
713*f0dffb02SXin Li auto& data = dex_->ann_set_ref_lists;
714*f0dffb02SXin Li dex::u4 offset = data.AddItem(4);
715*f0dffb02SXin Li data.Push<dex::u4>(annotations.size());
716*f0dffb02SXin Li for (auto ir_annotation_set : annotations) {
717*f0dffb02SXin Li data.Push<dex::u4>(FilePointer(ir_annotation_set));
718*f0dffb02SXin Li }
719*f0dffb02SXin Li return data.AbsoluteOffset(offset);
720*f0dffb02SXin Li }
721*f0dffb02SXin Li
722*f0dffb02SXin Li // "annotations_directory_item"
WriteClassAnnotations(const ir::Class * ir_class)723*f0dffb02SXin Li dex::u4 Writer::WriteClassAnnotations(const ir::Class* ir_class) {
724*f0dffb02SXin Li if (ir_class->annotations == nullptr) {
725*f0dffb02SXin Li return 0;
726*f0dffb02SXin Li }
727*f0dffb02SXin Li
728*f0dffb02SXin Li auto ir_annotations = ir_class->annotations;
729*f0dffb02SXin Li
730*f0dffb02SXin Li dex::u4& offset = node_offset_[ir_annotations];
731*f0dffb02SXin Li if (offset == 0) {
732*f0dffb02SXin Li // in order to write a contiguous "annotations_directory_item" we do two
733*f0dffb02SXin Li // passes :
734*f0dffb02SXin Li // 1. write the field/method/params annotations content
735*f0dffb02SXin Li // 2. write the directory (including the field/method/params arrays)
736*f0dffb02SXin Li std::vector<dex::FieldAnnotationsItem> dex_field_annotations;
737*f0dffb02SXin Li std::vector<dex::MethodAnnotationsItem> dex_method_annotations;
738*f0dffb02SXin Li std::vector<dex::ParameterAnnotationsItem> dex_param_annotations;
739*f0dffb02SXin Li
740*f0dffb02SXin Li for (auto irItem : ir_annotations->field_annotations) {
741*f0dffb02SXin Li dex::FieldAnnotationsItem dex_item = {};
742*f0dffb02SXin Li dex_item.field_idx = irItem->field_decl->index;
743*f0dffb02SXin Li dex_item.annotations_off = FilePointer(irItem->annotations);
744*f0dffb02SXin Li dex_field_annotations.push_back(dex_item);
745*f0dffb02SXin Li }
746*f0dffb02SXin Li
747*f0dffb02SXin Li for (auto irItem : ir_annotations->method_annotations) {
748*f0dffb02SXin Li dex::MethodAnnotationsItem dex_item = {};
749*f0dffb02SXin Li dex_item.method_idx = irItem->method_decl->index;
750*f0dffb02SXin Li dex_item.annotations_off = FilePointer(irItem->annotations);
751*f0dffb02SXin Li dex_method_annotations.push_back(dex_item);
752*f0dffb02SXin Li }
753*f0dffb02SXin Li
754*f0dffb02SXin Li for (auto irItem : ir_annotations->param_annotations) {
755*f0dffb02SXin Li dex::ParameterAnnotationsItem dex_item = {};
756*f0dffb02SXin Li dex_item.method_idx = irItem->method_decl->index;
757*f0dffb02SXin Li dex_item.annotations_off = FilePointer(irItem->annotations);
758*f0dffb02SXin Li dex_param_annotations.push_back(dex_item);
759*f0dffb02SXin Li }
760*f0dffb02SXin Li
761*f0dffb02SXin Li dex::u4 class_annotations_offset =
762*f0dffb02SXin Li FilePointer(ir_annotations->class_annotation);
763*f0dffb02SXin Li
764*f0dffb02SXin Li // now that the annotations content is written,
765*f0dffb02SXin Li // we can write down the "annotations_directory_item"
766*f0dffb02SXin Li dex::AnnotationsDirectoryItem dex_annotations = {};
767*f0dffb02SXin Li dex_annotations.class_annotations_off = class_annotations_offset;
768*f0dffb02SXin Li dex_annotations.fields_size = ir_annotations->field_annotations.size();
769*f0dffb02SXin Li dex_annotations.methods_size = ir_annotations->method_annotations.size();
770*f0dffb02SXin Li dex_annotations.parameters_size = ir_annotations->param_annotations.size();
771*f0dffb02SXin Li
772*f0dffb02SXin Li auto& data = dex_->ann_directories;
773*f0dffb02SXin Li offset = data.AddItem(4);
774*f0dffb02SXin Li data.Push(dex_annotations);
775*f0dffb02SXin Li data.Push(dex_field_annotations);
776*f0dffb02SXin Li data.Push(dex_method_annotations);
777*f0dffb02SXin Li data.Push(dex_param_annotations);
778*f0dffb02SXin Li offset = data.AbsoluteOffset(offset);
779*f0dffb02SXin Li }
780*f0dffb02SXin Li return offset;
781*f0dffb02SXin Li }
782*f0dffb02SXin Li
783*f0dffb02SXin Li // "debug_info_item"
WriteDebugInfo(const ir::DebugInfo * ir_debug_info)784*f0dffb02SXin Li dex::u4 Writer::WriteDebugInfo(const ir::DebugInfo* ir_debug_info) {
785*f0dffb02SXin Li SLICER_CHECK_NE(ir_debug_info, nullptr);
786*f0dffb02SXin Li
787*f0dffb02SXin Li auto& data = dex_->debug_info;
788*f0dffb02SXin Li dex::u4 offset = data.AddItem();
789*f0dffb02SXin Li
790*f0dffb02SXin Li // debug info "header"
791*f0dffb02SXin Li data.PushULeb128(ir_debug_info->line_start);
792*f0dffb02SXin Li data.PushULeb128(ir_debug_info->param_names.size());
793*f0dffb02SXin Li for (auto ir_string : ir_debug_info->param_names) {
794*f0dffb02SXin Li data.PushULeb128(OptIndex(ir_string) + 1);
795*f0dffb02SXin Li }
796*f0dffb02SXin Li
797*f0dffb02SXin Li // debug info "state machine bytecodes"
798*f0dffb02SXin Li const dex::u1* src = ir_debug_info->data.ptr<dex::u1>();
799*f0dffb02SXin Li dex::u1 opcode = 0;
800*f0dffb02SXin Li while ((opcode = *src++) != dex::DBG_END_SEQUENCE) {
801*f0dffb02SXin Li data.Push<dex::u1>(opcode);
802*f0dffb02SXin Li
803*f0dffb02SXin Li switch (opcode) {
804*f0dffb02SXin Li case dex::DBG_ADVANCE_PC:
805*f0dffb02SXin Li // addr_diff
806*f0dffb02SXin Li data.PushULeb128(dex::ReadULeb128(&src));
807*f0dffb02SXin Li break;
808*f0dffb02SXin Li
809*f0dffb02SXin Li case dex::DBG_ADVANCE_LINE:
810*f0dffb02SXin Li // line_diff
811*f0dffb02SXin Li data.PushSLeb128(dex::ReadSLeb128(&src));
812*f0dffb02SXin Li break;
813*f0dffb02SXin Li
814*f0dffb02SXin Li case dex::DBG_START_LOCAL: {
815*f0dffb02SXin Li // register_num
816*f0dffb02SXin Li data.PushULeb128(dex::ReadULeb128(&src));
817*f0dffb02SXin Li
818*f0dffb02SXin Li dex::u4 name_index = dex::ReadULeb128(&src) - 1;
819*f0dffb02SXin Li data.PushULeb128(MapStringIndex(name_index) + 1);
820*f0dffb02SXin Li
821*f0dffb02SXin Li dex::u4 type_index = dex::ReadULeb128(&src) - 1;
822*f0dffb02SXin Li data.PushULeb128(MapTypeIndex(type_index) + 1);
823*f0dffb02SXin Li } break;
824*f0dffb02SXin Li
825*f0dffb02SXin Li case dex::DBG_START_LOCAL_EXTENDED: {
826*f0dffb02SXin Li // register_num
827*f0dffb02SXin Li data.PushULeb128(dex::ReadULeb128(&src));
828*f0dffb02SXin Li
829*f0dffb02SXin Li dex::u4 name_index = dex::ReadULeb128(&src) - 1;
830*f0dffb02SXin Li data.PushULeb128(MapStringIndex(name_index) + 1);
831*f0dffb02SXin Li
832*f0dffb02SXin Li dex::u4 type_index = dex::ReadULeb128(&src) - 1;
833*f0dffb02SXin Li data.PushULeb128(MapTypeIndex(type_index) + 1);
834*f0dffb02SXin Li
835*f0dffb02SXin Li dex::u4 sig_index = dex::ReadULeb128(&src) - 1;
836*f0dffb02SXin Li data.PushULeb128(MapStringIndex(sig_index) + 1);
837*f0dffb02SXin Li } break;
838*f0dffb02SXin Li
839*f0dffb02SXin Li case dex::DBG_END_LOCAL:
840*f0dffb02SXin Li case dex::DBG_RESTART_LOCAL:
841*f0dffb02SXin Li // register_num
842*f0dffb02SXin Li data.PushULeb128(dex::ReadULeb128(&src));
843*f0dffb02SXin Li break;
844*f0dffb02SXin Li
845*f0dffb02SXin Li case dex::DBG_SET_FILE: {
846*f0dffb02SXin Li dex::u4 name_index = dex::ReadULeb128(&src) - 1;
847*f0dffb02SXin Li data.PushULeb128(MapStringIndex(name_index) + 1);
848*f0dffb02SXin Li } break;
849*f0dffb02SXin Li }
850*f0dffb02SXin Li }
851*f0dffb02SXin Li data.Push<dex::u1>(dex::DBG_END_SEQUENCE);
852*f0dffb02SXin Li
853*f0dffb02SXin Li return data.AbsoluteOffset(offset);
854*f0dffb02SXin Li }
855*f0dffb02SXin Li
856*f0dffb02SXin Li // instruction[] array
WriteInstructions(slicer::ArrayView<const dex::u2> instructions)857*f0dffb02SXin Li void Writer::WriteInstructions(slicer::ArrayView<const dex::u2> instructions) {
858*f0dffb02SXin Li SLICER_CHECK(!instructions.empty());
859*f0dffb02SXin Li
860*f0dffb02SXin Li auto offset = dex_->code.Push(instructions);
861*f0dffb02SXin Li dex::u2* ptr = dex_->code.ptr<dex::u2>(offset);
862*f0dffb02SXin Li dex::u2* const end = ptr + instructions.size();
863*f0dffb02SXin Li
864*f0dffb02SXin Li // relocate the instructions
865*f0dffb02SXin Li while (ptr < end) {
866*f0dffb02SXin Li auto opcode = dex::OpcodeFromBytecode(*ptr);
867*f0dffb02SXin Li dex::u2* idx = &ptr[1];
868*f0dffb02SXin Li dex::u2* idx2 = nullptr;
869*f0dffb02SXin Li
870*f0dffb02SXin Li size_t idx_size = 0;
871*f0dffb02SXin Li switch (dex::GetFormatFromOpcode(opcode)) {
872*f0dffb02SXin Li case dex::k20bc:
873*f0dffb02SXin Li case dex::k21c:
874*f0dffb02SXin Li case dex::k35c:
875*f0dffb02SXin Li case dex::k3rc:
876*f0dffb02SXin Li case dex::k22c:
877*f0dffb02SXin Li idx_size = 2;
878*f0dffb02SXin Li break;
879*f0dffb02SXin Li
880*f0dffb02SXin Li case dex::k31c:
881*f0dffb02SXin Li idx_size = 4;
882*f0dffb02SXin Li break;
883*f0dffb02SXin Li
884*f0dffb02SXin Li case dex::k45cc:
885*f0dffb02SXin Li case dex::k4rcc:
886*f0dffb02SXin Li idx_size = 2;
887*f0dffb02SXin Li idx2 = &ptr[3];
888*f0dffb02SXin Li break;
889*f0dffb02SXin Li
890*f0dffb02SXin Li default:
891*f0dffb02SXin Li break;
892*f0dffb02SXin Li }
893*f0dffb02SXin Li
894*f0dffb02SXin Li switch (dex::GetIndexTypeFromOpcode(opcode)) {
895*f0dffb02SXin Li case dex::kIndexStringRef:
896*f0dffb02SXin Li if (idx_size == 4) {
897*f0dffb02SXin Li dex::u4 new_index = MapStringIndex(ReadU4(idx));
898*f0dffb02SXin Li SLICER_CHECK_NE(new_index, dex::kNoIndex);
899*f0dffb02SXin Li WriteU4(idx, new_index);
900*f0dffb02SXin Li } else {
901*f0dffb02SXin Li SLICER_CHECK_EQ(idx_size, 2);
902*f0dffb02SXin Li dex::u4 new_index = MapStringIndex(*idx);
903*f0dffb02SXin Li SLICER_CHECK_NE(new_index, dex::kNoIndex);
904*f0dffb02SXin Li SLICER_CHECK_EQ(dex::u2(new_index), new_index);
905*f0dffb02SXin Li *idx = dex::u2(new_index);
906*f0dffb02SXin Li }
907*f0dffb02SXin Li break;
908*f0dffb02SXin Li
909*f0dffb02SXin Li case dex::kIndexTypeRef: {
910*f0dffb02SXin Li SLICER_CHECK_EQ(idx_size, 2);
911*f0dffb02SXin Li dex::u4 new_index = MapTypeIndex(*idx);
912*f0dffb02SXin Li SLICER_CHECK_NE(new_index, dex::kNoIndex);
913*f0dffb02SXin Li SLICER_CHECK_EQ(dex::u2(new_index), new_index);
914*f0dffb02SXin Li *idx = dex::u2(new_index);
915*f0dffb02SXin Li } break;
916*f0dffb02SXin Li
917*f0dffb02SXin Li case dex::kIndexFieldRef: {
918*f0dffb02SXin Li SLICER_CHECK_EQ(idx_size, 2);
919*f0dffb02SXin Li dex::u4 new_index = MapFieldIndex(*idx);
920*f0dffb02SXin Li SLICER_CHECK_NE(new_index, dex::kNoIndex);
921*f0dffb02SXin Li SLICER_CHECK_EQ(dex::u2(new_index), new_index);
922*f0dffb02SXin Li *idx = dex::u2(new_index);
923*f0dffb02SXin Li } break;
924*f0dffb02SXin Li
925*f0dffb02SXin Li case dex::kIndexMethodRef: {
926*f0dffb02SXin Li SLICER_CHECK_EQ(idx_size, 2);
927*f0dffb02SXin Li dex::u4 new_index = MapMethodIndex(*idx);
928*f0dffb02SXin Li SLICER_CHECK_NE(new_index, dex::kNoIndex);
929*f0dffb02SXin Li SLICER_CHECK_EQ(dex::u2(new_index), new_index);
930*f0dffb02SXin Li *idx = dex::u2(new_index);
931*f0dffb02SXin Li } break;
932*f0dffb02SXin Li
933*f0dffb02SXin Li case dex::kIndexMethodAndProtoRef: {
934*f0dffb02SXin Li SLICER_CHECK_EQ(idx_size, 2);
935*f0dffb02SXin Li dex::u4 new_index = MapMethodIndex(*idx);
936*f0dffb02SXin Li SLICER_CHECK_NE(new_index, dex::kNoIndex);
937*f0dffb02SXin Li SLICER_CHECK_EQ(dex::u2(new_index), new_index);
938*f0dffb02SXin Li *idx = dex::u2(new_index);
939*f0dffb02SXin Li dex::u4 new_index2 = MapProtoIndex(*idx2);
940*f0dffb02SXin Li SLICER_CHECK_NE(new_index2, dex::kNoIndex);
941*f0dffb02SXin Li SLICER_CHECK_EQ(dex::u2(new_index2), new_index2);
942*f0dffb02SXin Li *idx2 = dex::u2(new_index2);
943*f0dffb02SXin Li } break;
944*f0dffb02SXin Li
945*f0dffb02SXin Li case dex::kIndexMethodHandleRef: {
946*f0dffb02SXin Li SLICER_CHECK_EQ(idx_size, 2);
947*f0dffb02SXin Li dex::u4 new_index = MapMethodHandleIndex(*idx);
948*f0dffb02SXin Li SLICER_CHECK_NE(new_index, dex::kNoIndex);
949*f0dffb02SXin Li SLICER_CHECK_EQ(dex::u2(new_index), new_index);
950*f0dffb02SXin Li *idx = dex::u2(new_index);
951*f0dffb02SXin Li } break;
952*f0dffb02SXin Li
953*f0dffb02SXin Li default:
954*f0dffb02SXin Li break;
955*f0dffb02SXin Li }
956*f0dffb02SXin Li
957*f0dffb02SXin Li auto isize = dex::GetWidthFromBytecode(ptr);
958*f0dffb02SXin Li SLICER_CHECK_GT(isize, 0);
959*f0dffb02SXin Li ptr += isize;
960*f0dffb02SXin Li }
961*f0dffb02SXin Li SLICER_CHECK_EQ(ptr, end);
962*f0dffb02SXin Li }
963*f0dffb02SXin Li
964*f0dffb02SXin Li // "try_item[] + encoded_catch_handler_list"
WriteTryBlocks(const ir::Code * irCode)965*f0dffb02SXin Li void Writer::WriteTryBlocks(const ir::Code* irCode) {
966*f0dffb02SXin Li SLICER_CHECK(!irCode->try_blocks.empty());
967*f0dffb02SXin Li
968*f0dffb02SXin Li // use a temporary buffer to build the "encoded_catch_handler_list"
969*f0dffb02SXin Li slicer::Buffer handlers_list;
970*f0dffb02SXin Li auto original_list = irCode->catch_handlers.ptr<dex::u1>();
971*f0dffb02SXin Li auto ptr = original_list;
972*f0dffb02SXin Li std::map<dex::u2, dex::u2> handlers_offset_map;
973*f0dffb02SXin Li
974*f0dffb02SXin Li dex::u4 handlers_count = dex::ReadULeb128(&ptr);
975*f0dffb02SXin Li handlers_list.PushULeb128(handlers_count);
976*f0dffb02SXin Li
977*f0dffb02SXin Li for (dex::u4 handler_index = 0; handler_index < handlers_count; ++handler_index) {
978*f0dffb02SXin Li // track the oldOffset/newOffset mapping
979*f0dffb02SXin Li handlers_offset_map[ptr - original_list] = handlers_list.size();
980*f0dffb02SXin Li
981*f0dffb02SXin Li // parse each "encoded_catch_handler"
982*f0dffb02SXin Li int catch_count = dex::ReadSLeb128(&ptr);
983*f0dffb02SXin Li handlers_list.PushSLeb128(catch_count);
984*f0dffb02SXin Li
985*f0dffb02SXin Li for (int catch_index = 0; catch_index < std::abs(catch_count); ++catch_index) {
986*f0dffb02SXin Li // type_idx
987*f0dffb02SXin Li dex::u4 type_index = dex::ReadULeb128(&ptr);
988*f0dffb02SXin Li handlers_list.PushULeb128(MapTypeIndex(type_index));
989*f0dffb02SXin Li
990*f0dffb02SXin Li // address
991*f0dffb02SXin Li handlers_list.PushULeb128(dex::ReadULeb128(&ptr));
992*f0dffb02SXin Li }
993*f0dffb02SXin Li
994*f0dffb02SXin Li if (catch_count < 1) {
995*f0dffb02SXin Li // catch_all_addr
996*f0dffb02SXin Li handlers_list.PushULeb128(dex::ReadULeb128(&ptr));
997*f0dffb02SXin Li }
998*f0dffb02SXin Li }
999*f0dffb02SXin Li
1000*f0dffb02SXin Li handlers_list.Seal(1);
1001*f0dffb02SXin Li
1002*f0dffb02SXin Li // now write everything (try_item[] and encoded_catch_handler_list)
1003*f0dffb02SXin Li auto& data = dex_->code;
1004*f0dffb02SXin Li dex::u4 tries_offset = data.size();
1005*f0dffb02SXin Li data.Push(irCode->try_blocks);
1006*f0dffb02SXin Li data.Push(handlers_list);
1007*f0dffb02SXin Li
1008*f0dffb02SXin Li // finally relocate the offsets to handlers
1009*f0dffb02SXin Li for (dex::TryBlock& dex_try : slicer::ArrayView<dex::TryBlock>(
1010*f0dffb02SXin Li data.ptr<dex::TryBlock>(tries_offset), irCode->try_blocks.size())) {
1011*f0dffb02SXin Li dex::u2 new_Handler_offset = handlers_offset_map[dex_try.handler_off];
1012*f0dffb02SXin Li SLICER_CHECK_NE(new_Handler_offset, 0);
1013*f0dffb02SXin Li dex_try.handler_off = new_Handler_offset;
1014*f0dffb02SXin Li }
1015*f0dffb02SXin Li }
1016*f0dffb02SXin Li
1017*f0dffb02SXin Li // "code_item"
WriteCode(const ir::Code * irCode)1018*f0dffb02SXin Li dex::u4 Writer::WriteCode(const ir::Code* irCode) {
1019*f0dffb02SXin Li SLICER_CHECK_NE(irCode, nullptr);
1020*f0dffb02SXin Li
1021*f0dffb02SXin Li dex::Code dex_code = {};
1022*f0dffb02SXin Li dex_code.registers_size = irCode->registers;
1023*f0dffb02SXin Li dex_code.ins_size = irCode->ins_count;
1024*f0dffb02SXin Li dex_code.outs_size = irCode->outs_count;
1025*f0dffb02SXin Li dex_code.tries_size = irCode->try_blocks.size();
1026*f0dffb02SXin Li dex_code.debug_info_off = FilePointer(irCode->debug_info);
1027*f0dffb02SXin Li dex_code.insns_size = irCode->instructions.size();
1028*f0dffb02SXin Li
1029*f0dffb02SXin Li auto& data = dex_->code;
1030*f0dffb02SXin Li dex::u4 offset = data.AddItem(4);
1031*f0dffb02SXin Li data.Push(&dex_code, offsetof(dex::Code, insns));
1032*f0dffb02SXin Li WriteInstructions(irCode->instructions);
1033*f0dffb02SXin Li if (!irCode->try_blocks.empty()) {
1034*f0dffb02SXin Li data.Align(4);
1035*f0dffb02SXin Li WriteTryBlocks(irCode);
1036*f0dffb02SXin Li }
1037*f0dffb02SXin Li return data.AbsoluteOffset(offset);
1038*f0dffb02SXin Li }
1039*f0dffb02SXin Li
1040*f0dffb02SXin Li // "encoded_field"
WriteEncodedField(const ir::EncodedField * ir_encoded_field,dex::u4 * base_index)1041*f0dffb02SXin Li void Writer::WriteEncodedField(const ir::EncodedField* ir_encoded_field,
1042*f0dffb02SXin Li dex::u4* base_index) {
1043*f0dffb02SXin Li dex::u4 index_delta = ir_encoded_field->decl->index;
1044*f0dffb02SXin Li SLICER_CHECK_NE(index_delta, dex::kNoIndex);
1045*f0dffb02SXin Li if (*base_index != dex::kNoIndex) {
1046*f0dffb02SXin Li SLICER_CHECK_GT(index_delta, *base_index);
1047*f0dffb02SXin Li index_delta = index_delta - *base_index;
1048*f0dffb02SXin Li }
1049*f0dffb02SXin Li *base_index = ir_encoded_field->decl->index;
1050*f0dffb02SXin Li
1051*f0dffb02SXin Li auto& data = dex_->class_data;
1052*f0dffb02SXin Li data.PushULeb128(index_delta);
1053*f0dffb02SXin Li data.PushULeb128(ir_encoded_field->access_flags);
1054*f0dffb02SXin Li }
1055*f0dffb02SXin Li
1056*f0dffb02SXin Li // "encoded_method"
WriteEncodedMethod(const ir::EncodedMethod * ir_encoded_method,dex::u4 * base_index)1057*f0dffb02SXin Li void Writer::WriteEncodedMethod(const ir::EncodedMethod* ir_encoded_method,
1058*f0dffb02SXin Li dex::u4* base_index) {
1059*f0dffb02SXin Li dex::u4 index_delta = ir_encoded_method->decl->index;
1060*f0dffb02SXin Li SLICER_CHECK_NE(index_delta, dex::kNoIndex);
1061*f0dffb02SXin Li if (*base_index != dex::kNoIndex) {
1062*f0dffb02SXin Li SLICER_CHECK_GT(index_delta, *base_index);
1063*f0dffb02SXin Li index_delta = index_delta - *base_index;
1064*f0dffb02SXin Li }
1065*f0dffb02SXin Li *base_index = ir_encoded_method->decl->index;
1066*f0dffb02SXin Li
1067*f0dffb02SXin Li dex::u4 code_offset = FilePointer(ir_encoded_method->code);
1068*f0dffb02SXin Li
1069*f0dffb02SXin Li auto& data = dex_->class_data;
1070*f0dffb02SXin Li data.PushULeb128(index_delta);
1071*f0dffb02SXin Li data.PushULeb128(ir_encoded_method->access_flags);
1072*f0dffb02SXin Li data.PushULeb128(code_offset);
1073*f0dffb02SXin Li }
1074*f0dffb02SXin Li
1075*f0dffb02SXin Li // "class_data_item"
WriteClassData(const ir::Class * ir_class)1076*f0dffb02SXin Li dex::u4 Writer::WriteClassData(const ir::Class* ir_class) {
1077*f0dffb02SXin Li if (ir_class->static_fields.empty() && ir_class->instance_fields.empty() &&
1078*f0dffb02SXin Li ir_class->direct_methods.empty() && ir_class->virtual_methods.empty()) {
1079*f0dffb02SXin Li return 0;
1080*f0dffb02SXin Li }
1081*f0dffb02SXin Li
1082*f0dffb02SXin Li auto& data = dex_->class_data;
1083*f0dffb02SXin Li dex::u4 offset = data.AddItem();
1084*f0dffb02SXin Li
1085*f0dffb02SXin Li data.PushULeb128(ir_class->static_fields.size());
1086*f0dffb02SXin Li data.PushULeb128(ir_class->instance_fields.size());
1087*f0dffb02SXin Li data.PushULeb128(ir_class->direct_methods.size());
1088*f0dffb02SXin Li data.PushULeb128(ir_class->virtual_methods.size());
1089*f0dffb02SXin Li
1090*f0dffb02SXin Li dex::u4 base_index = dex::kNoIndex;
1091*f0dffb02SXin Li for (auto ir_encoded_field : ir_class->static_fields) {
1092*f0dffb02SXin Li WriteEncodedField(ir_encoded_field, &base_index);
1093*f0dffb02SXin Li }
1094*f0dffb02SXin Li
1095*f0dffb02SXin Li base_index = dex::kNoIndex;
1096*f0dffb02SXin Li for (auto ir_encoded_field : ir_class->instance_fields) {
1097*f0dffb02SXin Li WriteEncodedField(ir_encoded_field, &base_index);
1098*f0dffb02SXin Li }
1099*f0dffb02SXin Li
1100*f0dffb02SXin Li base_index = dex::kNoIndex;
1101*f0dffb02SXin Li for (auto ir_encoded_method : ir_class->direct_methods) {
1102*f0dffb02SXin Li WriteEncodedMethod(ir_encoded_method, &base_index);
1103*f0dffb02SXin Li }
1104*f0dffb02SXin Li
1105*f0dffb02SXin Li base_index = dex::kNoIndex;
1106*f0dffb02SXin Li for (auto ir_encoded_method : ir_class->virtual_methods) {
1107*f0dffb02SXin Li WriteEncodedMethod(ir_encoded_method, &base_index);
1108*f0dffb02SXin Li }
1109*f0dffb02SXin Li
1110*f0dffb02SXin Li return data.AbsoluteOffset(offset);
1111*f0dffb02SXin Li }
1112*f0dffb02SXin Li
1113*f0dffb02SXin Li // "encoded_array_item"
WriteClassStaticValues(const ir::Class * ir_class)1114*f0dffb02SXin Li dex::u4 Writer::WriteClassStaticValues(const ir::Class* ir_class) {
1115*f0dffb02SXin Li if (ir_class->static_init == nullptr) {
1116*f0dffb02SXin Li return 0;
1117*f0dffb02SXin Li }
1118*f0dffb02SXin Li
1119*f0dffb02SXin Li dex::u4& offset = node_offset_[ir_class->static_init];
1120*f0dffb02SXin Li if (offset == 0) {
1121*f0dffb02SXin Li auto& data = dex_->encoded_arrays;
1122*f0dffb02SXin Li offset = data.AddItem();
1123*f0dffb02SXin Li WriteEncodedArray(ir_class->static_init, data);
1124*f0dffb02SXin Li offset = data.AbsoluteOffset(offset);
1125*f0dffb02SXin Li }
1126*f0dffb02SXin Li return offset;
1127*f0dffb02SXin Li }
1128*f0dffb02SXin Li
1129*f0dffb02SXin Li // Map an index from the original .dex to the new index
MapStringIndex(dex::u4 index) const1130*f0dffb02SXin Li dex::u4 Writer::MapStringIndex(dex::u4 index) const {
1131*f0dffb02SXin Li if (index != dex::kNoIndex) {
1132*f0dffb02SXin Li index = dex_ir_->strings_map.at(index)->index;
1133*f0dffb02SXin Li SLICER_CHECK_NE(index, dex::kNoIndex);
1134*f0dffb02SXin Li }
1135*f0dffb02SXin Li return index;
1136*f0dffb02SXin Li }
1137*f0dffb02SXin Li
1138*f0dffb02SXin Li // Map an index from the original .dex to the new index
MapTypeIndex(dex::u4 index) const1139*f0dffb02SXin Li dex::u4 Writer::MapTypeIndex(dex::u4 index) const {
1140*f0dffb02SXin Li if (index != dex::kNoIndex) {
1141*f0dffb02SXin Li index = dex_ir_->types_map.at(index)->index;
1142*f0dffb02SXin Li SLICER_CHECK_NE(index, dex::kNoIndex);
1143*f0dffb02SXin Li }
1144*f0dffb02SXin Li return index;
1145*f0dffb02SXin Li }
1146*f0dffb02SXin Li
1147*f0dffb02SXin Li // Map an index from the original .dex to the new index
MapFieldIndex(dex::u4 index) const1148*f0dffb02SXin Li dex::u4 Writer::MapFieldIndex(dex::u4 index) const {
1149*f0dffb02SXin Li if (index != dex::kNoIndex) {
1150*f0dffb02SXin Li index = dex_ir_->fields_map.at(index)->index;
1151*f0dffb02SXin Li SLICER_CHECK_NE(index, dex::kNoIndex);
1152*f0dffb02SXin Li }
1153*f0dffb02SXin Li return index;
1154*f0dffb02SXin Li }
1155*f0dffb02SXin Li
1156*f0dffb02SXin Li // Map an index from the original .dex to the new index
MapMethodIndex(dex::u4 index) const1157*f0dffb02SXin Li dex::u4 Writer::MapMethodIndex(dex::u4 index) const {
1158*f0dffb02SXin Li if (index != dex::kNoIndex) {
1159*f0dffb02SXin Li index = dex_ir_->methods_map.at(index)->index;
1160*f0dffb02SXin Li SLICER_CHECK_NE(index, dex::kNoIndex);
1161*f0dffb02SXin Li }
1162*f0dffb02SXin Li return index;
1163*f0dffb02SXin Li }
1164*f0dffb02SXin Li
1165*f0dffb02SXin Li // Map an index from the original .dex to the new index
MapMethodHandleIndex(dex::u4 index) const1166*f0dffb02SXin Li dex::u4 Writer::MapMethodHandleIndex(dex::u4 index) const {
1167*f0dffb02SXin Li if (index != dex::kNoIndex) {
1168*f0dffb02SXin Li index = dex_ir_->method_handles_map.at(index)->index;
1169*f0dffb02SXin Li SLICER_CHECK_NE(index, dex::kNoIndex);
1170*f0dffb02SXin Li }
1171*f0dffb02SXin Li return index;
1172*f0dffb02SXin Li }
1173*f0dffb02SXin Li
1174*f0dffb02SXin Li // Map an index from the original .dex to the new index
MapProtoIndex(dex::u4 index) const1175*f0dffb02SXin Li dex::u4 Writer::MapProtoIndex(dex::u4 index) const {
1176*f0dffb02SXin Li if (index != dex::kNoIndex) {
1177*f0dffb02SXin Li index = dex_ir_->protos_map.at(index)->index;
1178*f0dffb02SXin Li SLICER_CHECK_NE(index, dex::kNoIndex);
1179*f0dffb02SXin Li }
1180*f0dffb02SXin Li return index;
1181*f0dffb02SXin Li }
1182*f0dffb02SXin Li
1183*f0dffb02SXin Li // .dex IR node to file pointer (absolute offset)
FilePointer(const ir::Node * ir_node) const1184*f0dffb02SXin Li dex::u4 Writer::FilePointer(const ir::Node* ir_node) const {
1185*f0dffb02SXin Li if (ir_node == nullptr) {
1186*f0dffb02SXin Li return 0;
1187*f0dffb02SXin Li }
1188*f0dffb02SXin Li auto it = node_offset_.find(ir_node);
1189*f0dffb02SXin Li SLICER_CHECK(it != node_offset_.end());
1190*f0dffb02SXin Li dex::u4 offset = it->second;
1191*f0dffb02SXin Li SLICER_CHECK_GT(offset, 0);
1192*f0dffb02SXin Li return offset;
1193*f0dffb02SXin Li }
1194*f0dffb02SXin Li
1195*f0dffb02SXin Li } // namespace dex
1196