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 an in-memory representation of DEX files.
17 */
18
19#include <stdint.h>
20#include <vector>
21
22#include "dex_ir_builder.h"
23
24namespace art {
25namespace dex_ir {
26
27static void CheckAndSetRemainingOffsets(const DexFile& dex_file, Collections* collections);
28
29Header* DexIrBuilder(const DexFile& dex_file) {
30  const DexFile::Header& disk_header = dex_file.GetHeader();
31  Header* header = new Header(disk_header.magic_,
32                              disk_header.checksum_,
33                              disk_header.signature_,
34                              disk_header.endian_tag_,
35                              disk_header.file_size_,
36                              disk_header.header_size_,
37                              disk_header.link_size_,
38                              disk_header.link_off_,
39                              disk_header.data_size_,
40                              disk_header.data_off_);
41  Collections& collections = header->GetCollections();
42  // Walk the rest of the header fields.
43  // StringId table.
44  collections.SetStringIdsOffset(disk_header.string_ids_off_);
45  for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) {
46    collections.CreateStringId(dex_file, i);
47  }
48  // TypeId table.
49  collections.SetTypeIdsOffset(disk_header.type_ids_off_);
50  for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
51    collections.CreateTypeId(dex_file, i);
52  }
53  // ProtoId table.
54  collections.SetProtoIdsOffset(disk_header.proto_ids_off_);
55  for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) {
56    collections.CreateProtoId(dex_file, i);
57  }
58  // FieldId table.
59  collections.SetFieldIdsOffset(disk_header.field_ids_off_);
60  for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) {
61    collections.CreateFieldId(dex_file, i);
62  }
63  // MethodId table.
64  collections.SetMethodIdsOffset(disk_header.method_ids_off_);
65  for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) {
66    collections.CreateMethodId(dex_file, i);
67  }
68  // ClassDef table.
69  collections.SetClassDefsOffset(disk_header.class_defs_off_);
70  for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
71    collections.CreateClassDef(dex_file, i);
72  }
73  // MapItem.
74  collections.SetMapListOffset(disk_header.map_off_);
75  // CallSiteIds and MethodHandleItems.
76  collections.CreateCallSitesAndMethodHandles(dex_file);
77
78  CheckAndSetRemainingOffsets(dex_file, &collections);
79
80  return header;
81}
82
83static void CheckAndSetRemainingOffsets(const DexFile& dex_file, Collections* collections) {
84  const DexFile::Header& disk_header = dex_file.GetHeader();
85  // Read MapItems and validate/set remaining offsets.
86  const DexFile::MapList* map =
87      reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + disk_header.map_off_);
88  const uint32_t count = map->size_;
89  for (uint32_t i = 0; i < count; ++i) {
90    const DexFile::MapItem* item = map->list_ + i;
91    switch (item->type_) {
92      case DexFile::kDexTypeHeaderItem:
93        CHECK_EQ(item->size_, 1u);
94        CHECK_EQ(item->offset_, 0u);
95        break;
96      case DexFile::kDexTypeStringIdItem:
97        CHECK_EQ(item->size_, collections->StringIdsSize());
98        CHECK_EQ(item->offset_, collections->StringIdsOffset());
99        break;
100      case DexFile::kDexTypeTypeIdItem:
101        CHECK_EQ(item->size_, collections->TypeIdsSize());
102        CHECK_EQ(item->offset_, collections->TypeIdsOffset());
103        break;
104      case DexFile::kDexTypeProtoIdItem:
105        CHECK_EQ(item->size_, collections->ProtoIdsSize());
106        CHECK_EQ(item->offset_, collections->ProtoIdsOffset());
107        break;
108      case DexFile::kDexTypeFieldIdItem:
109        CHECK_EQ(item->size_, collections->FieldIdsSize());
110        CHECK_EQ(item->offset_, collections->FieldIdsOffset());
111        break;
112      case DexFile::kDexTypeMethodIdItem:
113        CHECK_EQ(item->size_, collections->MethodIdsSize());
114        CHECK_EQ(item->offset_, collections->MethodIdsOffset());
115        break;
116      case DexFile::kDexTypeClassDefItem:
117        CHECK_EQ(item->size_, collections->ClassDefsSize());
118        CHECK_EQ(item->offset_, collections->ClassDefsOffset());
119        break;
120      case DexFile::kDexTypeCallSiteIdItem:
121        CHECK_EQ(item->size_, collections->CallSiteIdsSize());
122        CHECK_EQ(item->offset_, collections->CallSiteIdsOffset());
123        break;
124      case DexFile::kDexTypeMethodHandleItem:
125        CHECK_EQ(item->size_, collections->MethodHandleItemsSize());
126        CHECK_EQ(item->offset_, collections->MethodHandleItemsOffset());
127        break;
128      case DexFile::kDexTypeMapList:
129        CHECK_EQ(item->size_, 1u);
130        CHECK_EQ(item->offset_, disk_header.map_off_);
131        break;
132      case DexFile::kDexTypeTypeList:
133        collections->SetTypeListsOffset(item->offset_);
134        break;
135      case DexFile::kDexTypeAnnotationSetRefList:
136        collections->SetAnnotationSetRefListsOffset(item->offset_);
137        break;
138      case DexFile::kDexTypeAnnotationSetItem:
139        collections->SetAnnotationSetItemsOffset(item->offset_);
140        break;
141      case DexFile::kDexTypeClassDataItem:
142        collections->SetClassDatasOffset(item->offset_);
143        break;
144      case DexFile::kDexTypeCodeItem:
145        collections->SetCodeItemsOffset(item->offset_);
146        break;
147      case DexFile::kDexTypeStringDataItem:
148        collections->SetStringDatasOffset(item->offset_);
149        break;
150      case DexFile::kDexTypeDebugInfoItem:
151        collections->SetDebugInfoItemsOffset(item->offset_);
152        break;
153      case DexFile::kDexTypeAnnotationItem:
154        collections->SetAnnotationItemsOffset(item->offset_);
155        break;
156      case DexFile::kDexTypeEncodedArrayItem:
157        collections->SetEncodedArrayItemsOffset(item->offset_);
158        break;
159      case DexFile::kDexTypeAnnotationsDirectoryItem:
160        collections->SetAnnotationsDirectoryItemsOffset(item->offset_);
161        break;
162      default:
163        LOG(ERROR) << "Unknown map list item type.";
164    }
165  }
166}
167
168}  // namespace dex_ir
169}  // namespace art
170