blob: aff03cd6ea4e42d161be9e5f9f74abf5ffd43109 [file] [log] [blame]
Jeff Hao3ab96b42016-09-09 18:35:01 -07001/*
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 * Implementation 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#include "dex_ir.h"
24#include "dex_ir_builder.h"
25
26namespace art {
27namespace dex_ir {
28
29static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) {
30 uint64_t value = 0;
31 for (uint32_t i = 0; i <= length; i++) {
32 value |= static_cast<uint64_t>(*(*data)++) << (i * 8);
33 }
34 if (sign_extend) {
35 int shift = (7 - length) * 8;
36 return (static_cast<int64_t>(value) << shift) >> shift;
37 }
38 return value;
39}
40
41static bool GetPositionsCb(void* context, const DexFile::PositionInfo& entry) {
42 DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
43 PositionInfoVector& positions = debug_info->GetPositionInfo();
44 positions.push_back(std::unique_ptr<PositionInfo>(new PositionInfo(entry.address_, entry.line_)));
45 return false;
46}
47
48static void GetLocalsCb(void* context, const DexFile::LocalInfo& entry) {
49 DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
50 LocalInfoVector& locals = debug_info->GetLocalInfo();
51 const char* name = entry.name_ != nullptr ? entry.name_ : "(null)";
52 const char* signature = entry.signature_ != nullptr ? entry.signature_ : "";
53 locals.push_back(std::unique_ptr<LocalInfo>(
54 new LocalInfo(name, entry.descriptor_, signature, entry.start_address_,
55 entry.end_address_, entry.reg_)));
56}
57
58EncodedValue* Collections::ReadEncodedValue(const uint8_t** data) {
59 const uint8_t encoded_value = *(*data)++;
60 const uint8_t type = encoded_value & 0x1f;
61 EncodedValue* item = new EncodedValue(type);
62 ReadEncodedValue(data, type, encoded_value >> 5, item);
63 return item;
64}
65
66EncodedValue* Collections::ReadEncodedValue(const uint8_t** data, uint8_t type, uint8_t length) {
67 EncodedValue* item = new EncodedValue(type);
68 ReadEncodedValue(data, type, length, item);
69 return item;
70}
71
72void Collections::ReadEncodedValue(
73 const uint8_t** data, uint8_t type, uint8_t length, EncodedValue* item) {
74 switch (type) {
75 case DexFile::kDexAnnotationByte:
76 item->SetByte(static_cast<int8_t>(ReadVarWidth(data, length, false)));
77 break;
78 case DexFile::kDexAnnotationShort:
79 item->SetShort(static_cast<int16_t>(ReadVarWidth(data, length, true)));
80 break;
81 case DexFile::kDexAnnotationChar:
82 item->SetChar(static_cast<uint16_t>(ReadVarWidth(data, length, false)));
83 break;
84 case DexFile::kDexAnnotationInt:
85 item->SetInt(static_cast<int32_t>(ReadVarWidth(data, length, true)));
86 break;
87 case DexFile::kDexAnnotationLong:
88 item->SetLong(static_cast<int64_t>(ReadVarWidth(data, length, true)));
89 break;
90 case DexFile::kDexAnnotationFloat: {
91 // Fill on right.
92 union {
93 float f;
94 uint32_t data;
95 } conv;
96 conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8;
97 item->SetFloat(conv.f);
98 break;
99 }
100 case DexFile::kDexAnnotationDouble: {
101 // Fill on right.
102 union {
103 double d;
104 uint64_t data;
105 } conv;
106 conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8;
107 item->SetDouble(conv.d);
108 break;
109 }
110 case DexFile::kDexAnnotationString: {
111 const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
112 item->SetStringId(GetStringId(string_index));
113 break;
114 }
115 case DexFile::kDexAnnotationType: {
116 const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
117 item->SetTypeId(GetTypeId(string_index));
118 break;
119 }
120 case DexFile::kDexAnnotationField:
121 case DexFile::kDexAnnotationEnum: {
122 const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
123 item->SetFieldId(GetFieldId(field_index));
124 break;
125 }
126 case DexFile::kDexAnnotationMethod: {
127 const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
128 item->SetMethodId(GetMethodId(method_index));
129 break;
130 }
131 case DexFile::kDexAnnotationArray: {
132 EncodedValueVector* values = new EncodedValueVector();
133 const uint32_t size = DecodeUnsignedLeb128(data);
134 // Decode all elements.
135 for (uint32_t i = 0; i < size; i++) {
136 values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(data)));
137 }
138 item->SetEncodedArray(new EncodedArrayItem(values));
139 break;
140 }
141 case DexFile::kDexAnnotationAnnotation: {
142 AnnotationElementVector* elements = new AnnotationElementVector();
143 const uint32_t type_idx = DecodeUnsignedLeb128(data);
144 const uint32_t size = DecodeUnsignedLeb128(data);
145 // Decode all name=value pairs.
146 for (uint32_t i = 0; i < size; i++) {
147 const uint32_t name_index = DecodeUnsignedLeb128(data);
148 elements->push_back(std::unique_ptr<AnnotationElement>(
149 new AnnotationElement(GetStringId(name_index), ReadEncodedValue(data))));
150 }
151 item->SetEncodedAnnotation(new EncodedAnnotation(GetTypeId(type_idx), elements));
152 break;
153 }
154 case DexFile::kDexAnnotationNull:
155 break;
156 case DexFile::kDexAnnotationBoolean:
157 item->SetBoolean(length != 0);
158 break;
159 default:
160 break;
161 }
162}
163
164void Collections::CreateStringId(const DexFile& dex_file, uint32_t i) {
165 const DexFile::StringId& disk_string_id = dex_file.GetStringId(i);
166 StringData* string_data = new StringData(dex_file.GetStringData(disk_string_id));
167 string_datas_.AddItem(string_data, disk_string_id.string_data_off_);
168
169 StringId* string_id = new StringId(string_data);
170 string_ids_.AddIndexedItem(string_id, StringIdsOffset() + i * StringId::ItemSize(), i);
171}
172
173void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) {
174 const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(i);
175 TypeId* type_id = new TypeId(GetStringId(disk_type_id.descriptor_idx_));
176 type_ids_.AddIndexedItem(type_id, TypeIdsOffset() + i * TypeId::ItemSize(), i);
177}
178
179void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) {
180 const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(i);
181 const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
182 TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_, true);
183
184 ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_),
185 GetTypeId(disk_proto_id.return_type_idx_),
186 parameter_type_list);
187 proto_ids_.AddIndexedItem(proto_id, ProtoIdsOffset() + i * ProtoId::ItemSize(), i);
188}
189
190void Collections::CreateFieldId(const DexFile& dex_file, uint32_t i) {
191 const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
192 FieldId* field_id = new FieldId(GetTypeId(disk_field_id.class_idx_),
193 GetTypeId(disk_field_id.type_idx_),
194 GetStringId(disk_field_id.name_idx_));
195 field_ids_.AddIndexedItem(field_id, FieldIdsOffset() + i * FieldId::ItemSize(), i);
196}
197
198void Collections::CreateMethodId(const DexFile& dex_file, uint32_t i) {
199 const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
200 MethodId* method_id = new MethodId(GetTypeId(disk_method_id.class_idx_),
201 GetProtoId(disk_method_id.proto_idx_),
202 GetStringId(disk_method_id.name_idx_));
203 method_ids_.AddIndexedItem(method_id, MethodIdsOffset() + i * MethodId::ItemSize(), i);
204}
205
206void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) {
207 const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i);
208 const TypeId* class_type = GetTypeId(disk_class_def.class_idx_);
209 uint32_t access_flags = disk_class_def.access_flags_;
210 const TypeId* superclass = GetTypeIdOrNullPtr(disk_class_def.superclass_idx_);
211
212 const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
213 TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_, false);
214
215 const StringId* source_file = GetStringIdOrNullPtr(disk_class_def.source_file_idx_);
216 // Annotations.
217 AnnotationsDirectoryItem* annotations = nullptr;
218 const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
219 dex_file.GetAnnotationsDirectory(disk_class_def);
220 if (disk_annotations_directory_item != nullptr) {
221 annotations = CreateAnnotationsDirectoryItem(
222 dex_file, disk_annotations_directory_item, disk_class_def.annotations_off_);
223 }
224 // Static field initializers.
225 const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def);
226 EncodedArrayItem* static_values =
227 CreateEncodedArrayItem(static_data, disk_class_def.static_values_off_);
228 ClassData* class_data = CreateClassData(
229 dex_file, dex_file.GetClassData(disk_class_def), disk_class_def.class_data_off_);
230 ClassDef* class_def = new ClassDef(class_type, access_flags, superclass, interfaces_type_list,
231 source_file, annotations, static_values, class_data);
232 class_defs_.AddIndexedItem(class_def, ClassDefsOffset() + i * ClassDef::ItemSize(), i);
233}
234
235TypeList* Collections::CreateTypeList(
236 const DexFile::TypeList* dex_type_list, uint32_t offset, bool allow_empty) {
237 if (dex_type_list == nullptr && !allow_empty) {
238 return nullptr;
239 }
240 // TODO: Create more efficient lookup for existing type lists.
241 for (std::unique_ptr<TypeList>& type_list : TypeLists()) {
242 if (type_list->GetOffset() == offset) {
243 return type_list.get();
244 }
245 }
246 TypeIdVector* type_vector = new TypeIdVector();
247 uint32_t size = dex_type_list == nullptr ? 0 : dex_type_list->Size();
248 for (uint32_t index = 0; index < size; ++index) {
249 type_vector->push_back(GetTypeId(dex_type_list->GetTypeItem(index).type_idx_));
250 }
251 TypeList* new_type_list = new TypeList(type_vector);
252 type_lists_.AddItem(new_type_list, offset);
253 return new_type_list;
254}
255
256EncodedArrayItem* Collections::CreateEncodedArrayItem(const uint8_t* static_data, uint32_t offset) {
257 if (static_data == nullptr) {
258 return nullptr;
259 }
260 uint32_t size = DecodeUnsignedLeb128(&static_data);
261 EncodedValueVector* values = new EncodedValueVector();
262 for (uint32_t i = 0; i < size; ++i) {
263 values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(&static_data)));
264 }
265 // TODO: Calculate the size of the encoded array.
266 EncodedArrayItem* encoded_array_item = new EncodedArrayItem(values);
267 encoded_array_items_.AddItem(encoded_array_item, offset);
268 return encoded_array_item;
269}
270
271AnnotationItem* Collections::CreateAnnotationItem(const DexFile::AnnotationItem* annotation,
272 uint32_t offset) {
273 uint8_t visibility = annotation->visibility_;
274 const uint8_t* annotation_data = annotation->annotation_;
275 EncodedValue* encoded_value =
276 ReadEncodedValue(&annotation_data, DexFile::kDexAnnotationAnnotation, 0);
277 // TODO: Calculate the size of the annotation.
278 AnnotationItem* annotation_item =
279 new AnnotationItem(visibility, encoded_value->ReleaseEncodedAnnotation());
280 annotation_items_.AddItem(annotation_item, offset);
281 return annotation_item;
282}
283
284
285AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file,
286 const DexFile::AnnotationSetItem& disk_annotations_item, uint32_t offset) {
287 if (disk_annotations_item.size_ == 0) {
288 return nullptr;
289 }
290 std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>();
291 for (uint32_t i = 0; i < disk_annotations_item.size_; ++i) {
292 const DexFile::AnnotationItem* annotation =
293 dex_file.GetAnnotationItem(&disk_annotations_item, i);
294 if (annotation == nullptr) {
295 continue;
296 }
297 AnnotationItem* annotation_item =
298 CreateAnnotationItem(annotation, disk_annotations_item.entries_[i]);
299 items->push_back(annotation_item);
300 }
301 AnnotationSetItem* annotation_set_item = new AnnotationSetItem(items);
302 annotation_set_items_.AddItem(annotation_set_item, offset);
303 return annotation_set_item;
304}
305
306AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexFile& dex_file,
307 const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) {
308 const DexFile::AnnotationSetItem* class_set_item =
309 dex_file.GetClassAnnotationSet(disk_annotations_item);
310 AnnotationSetItem* class_annotation = nullptr;
311 if (class_set_item != nullptr) {
312 uint32_t offset = disk_annotations_item->class_annotations_off_;
313 class_annotation = CreateAnnotationSetItem(dex_file, *class_set_item, offset);
314 }
315 const DexFile::FieldAnnotationsItem* fields =
316 dex_file.GetFieldAnnotations(disk_annotations_item);
317 FieldAnnotationVector* field_annotations = nullptr;
318 if (fields != nullptr) {
319 field_annotations = new FieldAnnotationVector();
320 for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) {
321 FieldId* field_id = GetFieldId(fields[i].field_idx_);
322 const DexFile::AnnotationSetItem* field_set_item =
323 dex_file.GetFieldAnnotationSetItem(fields[i]);
324 uint32_t annotation_set_offset = fields[i].annotations_off_;
325 AnnotationSetItem* annotation_set_item =
326 CreateAnnotationSetItem(dex_file, *field_set_item, annotation_set_offset);
327 field_annotations->push_back(std::unique_ptr<FieldAnnotation>(
328 new FieldAnnotation(field_id, annotation_set_item)));
329 }
330 }
331 const DexFile::MethodAnnotationsItem* methods =
332 dex_file.GetMethodAnnotations(disk_annotations_item);
333 MethodAnnotationVector* method_annotations = nullptr;
334 if (methods != nullptr) {
335 method_annotations = new MethodAnnotationVector();
336 for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) {
337 MethodId* method_id = GetMethodId(methods[i].method_idx_);
338 const DexFile::AnnotationSetItem* method_set_item =
339 dex_file.GetMethodAnnotationSetItem(methods[i]);
340 uint32_t annotation_set_offset = methods[i].annotations_off_;
341 AnnotationSetItem* annotation_set_item =
342 CreateAnnotationSetItem(dex_file, *method_set_item, annotation_set_offset);
343 method_annotations->push_back(std::unique_ptr<MethodAnnotation>(
344 new MethodAnnotation(method_id, annotation_set_item)));
345 }
346 }
347 const DexFile::ParameterAnnotationsItem* parameters =
348 dex_file.GetParameterAnnotations(disk_annotations_item);
349 ParameterAnnotationVector* parameter_annotations = nullptr;
350 if (parameters != nullptr) {
351 parameter_annotations = new ParameterAnnotationVector();
352 for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) {
353 MethodId* method_id = GetMethodId(parameters[i].method_idx_);
354 const DexFile::AnnotationSetRefList* list =
355 dex_file.GetParameterAnnotationSetRefList(&parameters[i]);
356 parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>(
357 GenerateParameterAnnotation(dex_file, method_id, list, parameters[i].annotations_off_)));
358 }
359 }
360 // TODO: Calculate the size of the annotations directory.
361 AnnotationsDirectoryItem* annotations_directory_item = new AnnotationsDirectoryItem(
362 class_annotation, field_annotations, method_annotations, parameter_annotations);
363 annotations_directory_items_.AddItem(annotations_directory_item, offset);
364 return annotations_directory_item;
365}
366
367ParameterAnnotation* Collections::GenerateParameterAnnotation(
368 const DexFile& dex_file, MethodId* method_id,
369 const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset) {
370 std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
371 for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
372 const DexFile::AnnotationSetItem* annotation_set_item =
373 dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
374 uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
375 annotations->push_back(CreateAnnotationSetItem(dex_file, *annotation_set_item, set_offset));
376 }
377 AnnotationSetRefList* new_ref_list = new AnnotationSetRefList(annotations);
378 annotation_set_ref_lists_.AddItem(new_ref_list, offset);
379 return new ParameterAnnotation(method_id, new_ref_list);
380}
381
382CodeItem* Collections::CreateCodeItem(const DexFile& dex_file,
383 const DexFile::CodeItem& disk_code_item, uint32_t offset) {
384 uint16_t registers_size = disk_code_item.registers_size_;
385 uint16_t ins_size = disk_code_item.ins_size_;
386 uint16_t outs_size = disk_code_item.outs_size_;
387 uint32_t tries_size = disk_code_item.tries_size_;
388
389 // TODO: Calculate the size of the debug info.
390 const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(&disk_code_item);
391 DebugInfoItem* debug_info = nullptr;
392 if (debug_info_stream != nullptr) {
393 debug_info = new DebugInfoItem();
394 debug_info_items_.AddItem(debug_info, disk_code_item.debug_info_off_);
395 }
396
397 uint32_t insns_size = disk_code_item.insns_size_in_code_units_;
398 uint16_t* insns = new uint16_t[insns_size];
399 memcpy(insns, disk_code_item.insns_, insns_size * sizeof(uint16_t));
400
401 TryItemVector* tries = nullptr;
402 if (tries_size > 0) {
403 tries = new TryItemVector();
404 for (uint32_t i = 0; i < tries_size; ++i) {
405 const DexFile::TryItem* disk_try_item = dex_file.GetTryItems(disk_code_item, i);
406 uint32_t start_addr = disk_try_item->start_addr_;
407 uint16_t insn_count = disk_try_item->insn_count_;
408 CatchHandlerVector* handlers = new CatchHandlerVector();
409 for (CatchHandlerIterator it(disk_code_item, *disk_try_item); it.HasNext(); it.Next()) {
410 const uint16_t type_index = it.GetHandlerTypeIndex();
411 const TypeId* type_id = GetTypeIdOrNullPtr(type_index);
412 handlers->push_back(std::unique_ptr<const CatchHandler>(
413 new CatchHandler(type_id, it.GetHandlerAddress())));
414 }
415 TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
416 tries->push_back(std::unique_ptr<const TryItem>(try_item));
417 }
418 }
419 // TODO: Calculate the size of the code item.
420 CodeItem* code_item =
421 new CodeItem(registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries);
422 code_items_.AddItem(code_item, offset);
423 return code_item;
424}
425
426MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
427 MethodId* method_item = GetMethodId(cdii.GetMemberIndex());
428 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
429 const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
430 CodeItem* code_item = nullptr;
431 DebugInfoItem* debug_info = nullptr;
432 if (disk_code_item != nullptr) {
433 code_item = CreateCodeItem(dex_file, *disk_code_item, cdii.GetMethodCodeItemOffset());
434 debug_info = code_item->DebugInfo();
435 }
436 if (debug_info != nullptr) {
437 bool is_static = (access_flags & kAccStatic) != 0;
438 dex_file.DecodeDebugLocalInfo(
439 disk_code_item, is_static, cdii.GetMemberIndex(), GetLocalsCb, debug_info);
440 dex_file.DecodeDebugPositionInfo(disk_code_item, GetPositionsCb, debug_info);
441 }
442 return new MethodItem(access_flags, method_item, code_item);
443}
444
445ClassData* Collections::CreateClassData(
446 const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
447 // Read the fields and methods defined by the class, resolving the circular reference from those
448 // to classes by setting class at the same time.
449 ClassData* class_data = nullptr;
450 if (encoded_data != nullptr) {
451 ClassDataItemIterator cdii(dex_file, encoded_data);
452 // Static fields.
453 FieldItemVector* static_fields = new FieldItemVector();
454 for (uint32_t i = 0; cdii.HasNextStaticField(); i++, cdii.Next()) {
455 FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
456 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
457 static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
458 }
459 // Instance fields.
460 FieldItemVector* instance_fields = new FieldItemVector();
461 for (uint32_t i = 0; cdii.HasNextInstanceField(); i++, cdii.Next()) {
462 FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
463 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
464 instance_fields->push_back(
465 std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
466 }
467 // Direct methods.
468 MethodItemVector* direct_methods = new MethodItemVector();
469 for (uint32_t i = 0; cdii.HasNextDirectMethod(); i++, cdii.Next()) {
470 direct_methods->push_back(
471 std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
472 }
473 // Virtual methods.
474 MethodItemVector* virtual_methods = new MethodItemVector();
475 for (uint32_t i = 0; cdii.HasNextVirtualMethod(); i++, cdii.Next()) {
476 virtual_methods->push_back(
477 std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
478 }
479 // TODO: Calculate the size of the class data.
480 class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods);
481 class_datas_.AddItem(class_data, offset);
482 }
483 return class_data;
484}
485
486} // namespace dex_ir
487} // namespace art