Etienne Pierre-Doray | fff1ca3 | 2018-03-29 13:33:46 +0000 | [diff] [blame] | 1 | // Copyright 2018 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef COMPONENTS_ZUCCHINI_TYPE_DEX_H_ |
| 6 | #define COMPONENTS_ZUCCHINI_TYPE_DEX_H_ |
| 7 | |
| 8 | #include <stdint.h> |
| 9 | |
| 10 | namespace zucchini { |
| 11 | namespace dex { |
| 12 | // Contains types that models DEX executable format data structures. |
| 13 | // See https://source.android.com/devices/tech/dalvik/dex-format |
| 14 | |
ckitagawa | 1269b5c | 2021-09-07 21:12:21 +0000 | [diff] [blame] | 15 | // The supported versions are 035, 037, 038, and 039. |
Etienne Pierre-Doray | fff1ca3 | 2018-03-29 13:33:46 +0000 | [diff] [blame] | 16 | |
| 17 | enum class FormatId : uint8_t { |
| 18 | b, // 22b. |
ckitagawa | 26518ff | 2021-09-03 15:48:28 +0000 | [diff] [blame] | 19 | c, // 21c, 22c, 31c, 35c, 3rc, 45cc, 4rcc. |
Etienne Pierre-Doray | fff1ca3 | 2018-03-29 13:33:46 +0000 | [diff] [blame] | 20 | h, // 21h. |
| 21 | i, // 31i. |
| 22 | l, // 51l. |
| 23 | n, // 11n. |
| 24 | s, // 21s, 22s. |
| 25 | t, // 10t, 20t, 21t, 22t, 30t, 31t. |
| 26 | x, // 10x, 11x, 12x, 22x, 23x, 32x. |
| 27 | }; |
| 28 | |
| 29 | struct Instruction { |
| 30 | Instruction() = default; |
| 31 | constexpr Instruction(uint8_t opcode_in, |
| 32 | uint8_t layout_in, |
| 33 | FormatId format_in, |
| 34 | uint8_t variant_in = 1) |
| 35 | : opcode(opcode_in), |
| 36 | layout(layout_in), |
| 37 | format(format_in), |
| 38 | variant(variant_in) {} |
| 39 | |
| 40 | // The opcode that identifies the instruction. |
| 41 | uint8_t opcode; |
| 42 | // Number of uint16_t units for the instruction. |
| 43 | uint8_t layout; |
| 44 | // Identifier that groups similar instructions, as quick filter. |
| 45 | FormatId format; |
| 46 | // Number of successive opcodes that have the same format. |
| 47 | uint8_t variant = 1; |
| 48 | }; |
| 49 | |
| 50 | constexpr Instruction kByteCode[] = { |
| 51 | {0x00, 1, FormatId::x}, |
| 52 | {0x01, 1, FormatId::x}, |
| 53 | {0x02, 2, FormatId::x}, |
| 54 | {0x03, 3, FormatId::x}, |
| 55 | {0x04, 1, FormatId::x}, |
| 56 | {0x05, 2, FormatId::x}, |
| 57 | {0x06, 3, FormatId::x}, |
| 58 | {0x07, 1, FormatId::x}, |
| 59 | {0x08, 2, FormatId::x}, |
| 60 | {0x09, 3, FormatId::x}, |
| 61 | {0x0A, 1, FormatId::x}, |
| 62 | {0x0B, 1, FormatId::x}, |
| 63 | {0x0C, 1, FormatId::x}, |
| 64 | {0x0D, 1, FormatId::x}, |
| 65 | {0x0E, 1, FormatId::x}, |
| 66 | {0x0F, 1, FormatId::x}, |
| 67 | {0x10, 1, FormatId::x}, |
| 68 | {0x11, 1, FormatId::x}, |
| 69 | {0x12, 1, FormatId::n}, |
| 70 | {0x13, 2, FormatId::s}, |
| 71 | {0x14, 3, FormatId::i}, |
| 72 | {0x15, 2, FormatId::h}, |
| 73 | {0x16, 2, FormatId::s}, |
| 74 | {0x17, 3, FormatId::i}, |
| 75 | {0x18, 5, FormatId::l}, |
| 76 | {0x19, 2, FormatId::h}, |
| 77 | {0x1A, 2, FormatId::c}, |
| 78 | {0x1B, 3, FormatId::c}, |
| 79 | {0x1C, 2, FormatId::c}, |
| 80 | {0x1D, 1, FormatId::x}, |
| 81 | {0x1E, 1, FormatId::x}, |
| 82 | {0x1F, 2, FormatId::c}, |
| 83 | {0x20, 2, FormatId::c}, |
| 84 | {0x21, 1, FormatId::x}, |
| 85 | {0x22, 2, FormatId::c}, |
| 86 | {0x23, 2, FormatId::c}, |
| 87 | {0x24, 3, FormatId::c}, |
| 88 | {0x25, 3, FormatId::c}, |
| 89 | {0x26, 3, FormatId::t}, |
| 90 | {0x27, 1, FormatId::x}, |
| 91 | {0x28, 1, FormatId::t}, |
| 92 | {0x29, 2, FormatId::t}, |
| 93 | {0x2A, 3, FormatId::t}, |
| 94 | {0x2B, 3, FormatId::t}, |
| 95 | {0x2C, 3, FormatId::t}, |
| 96 | {0x2D, 2, FormatId::x, 5}, |
| 97 | {0x32, 2, FormatId::t, 6}, |
| 98 | {0x38, 2, FormatId::t, 6}, |
| 99 | // {0x3E, 1, FormatId::x, 6}, unused |
| 100 | {0x44, 2, FormatId::x, 14}, |
| 101 | {0x52, 2, FormatId::c, 14}, |
| 102 | {0x60, 2, FormatId::c, 14}, |
| 103 | {0x6E, 3, FormatId::c, 5}, |
| 104 | // {0x73, 1, FormatId::x}, unused |
| 105 | {0x74, 3, FormatId::c, 5}, |
| 106 | // {0x79, 1, FormatId::x, 2}, unused |
| 107 | {0x7B, 1, FormatId::x, 21}, |
| 108 | {0x90, 2, FormatId::x, 32}, |
| 109 | {0xB0, 1, FormatId::x, 32}, |
| 110 | {0xD0, 2, FormatId::s, 8}, |
| 111 | {0xD8, 2, FormatId::b, 11}, |
| 112 | // {0xE3, 1, FormatId::x, 29}, unused |
ckitagawa | 26518ff | 2021-09-03 15:48:28 +0000 | [diff] [blame] | 113 | {0xFA, 4, FormatId::c}, |
| 114 | {0xFB, 4, FormatId::c}, |
| 115 | {0xFC, 3, FormatId::c}, |
| 116 | {0xFD, 3, FormatId::c}, |
ckitagawa | 1269b5c | 2021-09-07 21:12:21 +0000 | [diff] [blame] | 117 | {0xFE, 2, FormatId::c}, |
| 118 | {0xFF, 2, FormatId::c}, |
Etienne Pierre-Doray | fff1ca3 | 2018-03-29 13:33:46 +0000 | [diff] [blame] | 119 | }; |
| 120 | |
| 121 | // Supported by MSVC, g++, and clang++. Ensures no gaps in packing. |
| 122 | #pragma pack(push, 1) |
| 123 | |
| 124 | // header_item: Appears in the header section. |
| 125 | struct HeaderItem { |
| 126 | uint8_t magic[8]; |
| 127 | uint32_t checksum; |
| 128 | uint8_t signature[20]; |
| 129 | uint32_t file_size; |
| 130 | uint32_t header_size; |
| 131 | uint32_t endian_tag; |
| 132 | uint32_t link_size; |
| 133 | uint32_t link_off; |
| 134 | uint32_t map_off; |
| 135 | uint32_t string_ids_size; |
| 136 | uint32_t string_ids_off; |
| 137 | uint32_t type_ids_size; |
| 138 | uint32_t type_ids_off; |
| 139 | uint32_t proto_ids_size; |
| 140 | uint32_t proto_ids_off; |
| 141 | uint32_t field_ids_size; |
| 142 | uint32_t field_ids_off; |
| 143 | uint32_t method_ids_size; |
| 144 | uint32_t method_ids_off; |
| 145 | uint32_t class_defs_size; |
| 146 | uint32_t class_defs_off; |
| 147 | uint32_t data_size; |
| 148 | uint32_t data_off; |
| 149 | }; |
| 150 | |
| 151 | // string_id_item: String identifiers list. |
| 152 | struct StringIdItem { |
| 153 | uint32_t string_data_off; |
| 154 | }; |
| 155 | |
| 156 | // type_id_item: Type identifiers list. |
| 157 | struct TypeIdItem { |
| 158 | uint32_t descriptor_idx; |
| 159 | }; |
| 160 | |
| 161 | // proto_id_item: Method prototype identifiers list. |
| 162 | struct ProtoIdItem { |
| 163 | uint32_t shorty_idx; |
| 164 | uint32_t return_type_idx; |
| 165 | uint32_t parameters_off; |
| 166 | }; |
| 167 | |
| 168 | // field_id_item: Field identifiers list. |
| 169 | struct FieldIdItem { |
| 170 | uint16_t class_idx; |
| 171 | uint16_t type_idx; |
| 172 | uint32_t name_idx; |
| 173 | }; |
| 174 | |
| 175 | // method_id_item: Method identifiers list. |
| 176 | struct MethodIdItem { |
| 177 | uint16_t class_idx; |
| 178 | uint16_t proto_idx; |
| 179 | uint32_t name_idx; |
| 180 | }; |
| 181 | |
| 182 | // class_def_item: Class definitions list. |
| 183 | struct ClassDefItem { |
| 184 | uint32_t class_idx; |
| 185 | uint32_t access_flags; |
| 186 | uint32_t superclass_idx; |
| 187 | uint32_t interfaces_off; |
| 188 | uint32_t source_file_idx; |
| 189 | uint32_t annotations_off; |
| 190 | uint32_t class_data_off; |
| 191 | uint32_t static_values_off; |
| 192 | }; |
| 193 | |
ckitagawa | 26518ff | 2021-09-03 15:48:28 +0000 | [diff] [blame] | 194 | // call_site_id_item: Call site identifiers list. |
| 195 | struct CallSiteIdItem { |
| 196 | uint32_t call_site_off; |
| 197 | }; |
| 198 | |
| 199 | // method_handle_type: Determines the behavior of the MethodHandleItem. |
| 200 | enum class MethodHandleType : uint16_t { |
| 201 | // FieldId |
| 202 | kStaticPut = 0x00, |
| 203 | kStaticGet = 0x01, |
| 204 | kInstancePut = 0x02, |
| 205 | kInstanceGet = 0x03, |
| 206 | // MethodId |
| 207 | kInvokeStatic = 0x04, |
| 208 | kInvokeInstance = 0x05, |
| 209 | kInvokeConstructor = 0x06, |
| 210 | kInvokeDirect = 0x07, |
| 211 | kInvokeInterface = 0x08, |
| 212 | // Sentinel. If new types are added put them before this and increment. |
| 213 | kMaxMethodHandleType = 0x09 |
| 214 | }; |
| 215 | |
| 216 | // method_handle_item: Method handles referred within the Dex file. |
| 217 | struct MethodHandleItem { |
| 218 | uint16_t method_handle_type; |
| 219 | uint16_t unused_1; |
| 220 | uint16_t field_or_method_id; |
| 221 | uint16_t unused_2; |
| 222 | }; |
| 223 | |
Etienne Pierre-Doray | fff1ca3 | 2018-03-29 13:33:46 +0000 | [diff] [blame] | 224 | // code_item: Header of a code item. |
| 225 | struct CodeItem { |
| 226 | uint16_t registers_size; |
| 227 | uint16_t ins_size; |
| 228 | uint16_t outs_size; |
| 229 | uint16_t tries_size; |
| 230 | uint32_t debug_info_off; |
| 231 | uint32_t insns_size; |
| 232 | // Variable length data follow for complete code item. |
| 233 | }; |
| 234 | |
ckitagawa | 26518ff | 2021-09-03 15:48:28 +0000 | [diff] [blame] | 235 | // Number of valid type codes for map_item elements in map_list. |
| 236 | // See: https://source.android.com/devices/tech/dalvik/dex-format#type-codes |
| 237 | constexpr uint32_t kMaxItemListSize = 21; |
| 238 | |
| 239 | constexpr uint16_t kTypeHeaderItem = 0x0000; |
| 240 | constexpr uint16_t kTypeStringIdItem = 0x0001; |
| 241 | constexpr uint16_t kTypeTypeIdItem = 0x0002; |
| 242 | constexpr uint16_t kTypeProtoIdItem = 0x0003; |
| 243 | constexpr uint16_t kTypeFieldIdItem = 0x0004; |
| 244 | constexpr uint16_t kTypeMethodIdItem = 0x0005; |
| 245 | constexpr uint16_t kTypeClassDefItem = 0x0006; |
| 246 | constexpr uint16_t kTypeCallSiteIdItem = 0x0007; |
| 247 | constexpr uint16_t kTypeMethodHandleItem = 0x0008; |
| 248 | constexpr uint16_t kTypeMapList = 0x1000; |
| 249 | constexpr uint16_t kTypeTypeList = 0x1001; |
| 250 | constexpr uint16_t kTypeAnnotationSetRefList = 0x1002; |
| 251 | constexpr uint16_t kTypeAnnotationSetItem = 0x1003; |
| 252 | constexpr uint16_t kTypeClassDataItem = 0x2000; |
| 253 | constexpr uint16_t kTypeCodeItem = 0x2001; |
| 254 | constexpr uint16_t kTypeStringDataItem = 0x2002; |
| 255 | constexpr uint16_t kTypeDebugInfoItem = 0x2003; |
| 256 | constexpr uint16_t kTypeAnnotationItem = 0x2004; |
| 257 | constexpr uint16_t kTypeEncodedArrayItem = 0x2005; |
| 258 | constexpr uint16_t kTypeAnnotationsDirectoryItem = 0x2006; |
| 259 | constexpr uint16_t kTypeHiddenApiClassDataItem = 0xF000; |
Etienne Pierre-Doray | fff1ca3 | 2018-03-29 13:33:46 +0000 | [diff] [blame] | 260 | |
| 261 | // map_item |
| 262 | struct MapItem { |
| 263 | uint16_t type; |
| 264 | uint16_t unused; |
| 265 | uint32_t size; |
| 266 | uint32_t offset; |
| 267 | }; |
| 268 | |
| 269 | // map_list |
| 270 | struct MapList { |
| 271 | uint32_t size; |
| 272 | MapItem list[kMaxItemListSize]; |
| 273 | }; |
| 274 | |
| 275 | // type_item |
| 276 | struct TypeItem { |
| 277 | uint16_t type_idx; |
| 278 | }; |
| 279 | |
| 280 | // annotation_set_ref_item |
| 281 | struct AnnotationSetRefItem { |
| 282 | uint32_t annotations_off; |
| 283 | }; |
| 284 | |
| 285 | // annotation_off_item |
| 286 | struct AnnotationOffItem { |
| 287 | uint32_t annotation_off; |
| 288 | }; |
| 289 | |
Calder Kitagawa | 1b25709 | 2018-06-12 14:37:39 +0000 | [diff] [blame] | 290 | // field_annotation |
| 291 | struct FieldAnnotation { |
| 292 | uint32_t field_idx; |
| 293 | uint32_t annotations_off; |
| 294 | }; |
| 295 | |
| 296 | // method_annotation |
| 297 | struct MethodAnnotation { |
| 298 | uint32_t method_idx; |
| 299 | uint32_t annotations_off; |
| 300 | }; |
| 301 | |
| 302 | // parameter_annotation |
| 303 | struct ParameterAnnotation { |
| 304 | uint32_t method_idx; |
| 305 | uint32_t annotations_off; |
| 306 | }; |
| 307 | |
| 308 | // annotations_directory_item |
| 309 | struct AnnotationsDirectoryItem { |
| 310 | uint32_t class_annotations_off; |
| 311 | uint32_t fields_size; |
| 312 | uint32_t annotated_methods_size; |
| 313 | uint32_t annotated_parameters_size; |
| 314 | // FieldAnnotation field_annotations[fields_size]; |
| 315 | // MethodAnnotation method_annotations[annotated_methods_size]; |
| 316 | // ParameterAnnotation parameter_annotations[annotated_parameters_size]; |
| 317 | // All *Annotation are 8 bytes each. |
| 318 | }; |
| 319 | |
Etienne Pierre-Doray | fff1ca3 | 2018-03-29 13:33:46 +0000 | [diff] [blame] | 320 | // try_item |
| 321 | struct TryItem { |
| 322 | uint32_t start_addr; |
| 323 | uint16_t insn_count; |
| 324 | uint16_t handler_off; |
| 325 | }; |
| 326 | |
Etienne Pierre-Doray | fff1ca3 | 2018-03-29 13:33:46 +0000 | [diff] [blame] | 327 | #pragma pack(pop) |
| 328 | |
| 329 | } // namespace dex |
| 330 | } // namespace zucchini |
| 331 | |
| 332 | #endif // COMPONENTS_ZUCCHINI_TYPE_DEX_H_ |