| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_ZUCCHINI_TYPE_DEX_H_ |
| #define COMPONENTS_ZUCCHINI_TYPE_DEX_H_ |
| |
| #include <stdint.h> |
| |
| namespace zucchini { |
| namespace dex { |
| // Contains types that models DEX executable format data structures. |
| // See https://source.android.com/devices/tech/dalvik/dex-format |
| |
| // The supported versions are 035, 037, 038, and 039. |
| |
| enum class FormatId : uint8_t { |
| b, // 22b. |
| c, // 21c, 22c, 31c, 35c, 3rc, 45cc, 4rcc. |
| h, // 21h. |
| i, // 31i. |
| l, // 51l. |
| n, // 11n. |
| s, // 21s, 22s. |
| t, // 10t, 20t, 21t, 22t, 30t, 31t. |
| x, // 10x, 11x, 12x, 22x, 23x, 32x. |
| }; |
| |
| struct Instruction { |
| Instruction() = default; |
| constexpr Instruction(uint8_t opcode_in, |
| uint8_t layout_in, |
| FormatId format_in, |
| uint8_t variant_in = 1) |
| : opcode(opcode_in), |
| layout(layout_in), |
| format(format_in), |
| variant(variant_in) {} |
| |
| // The opcode that identifies the instruction. |
| uint8_t opcode; |
| // Number of uint16_t units for the instruction. |
| uint8_t layout; |
| // Identifier that groups similar instructions, as quick filter. |
| FormatId format; |
| // Number of successive opcodes that have the same format. |
| uint8_t variant = 1; |
| }; |
| |
| constexpr Instruction kByteCode[] = { |
| {0x00, 1, FormatId::x}, |
| {0x01, 1, FormatId::x}, |
| {0x02, 2, FormatId::x}, |
| {0x03, 3, FormatId::x}, |
| {0x04, 1, FormatId::x}, |
| {0x05, 2, FormatId::x}, |
| {0x06, 3, FormatId::x}, |
| {0x07, 1, FormatId::x}, |
| {0x08, 2, FormatId::x}, |
| {0x09, 3, FormatId::x}, |
| {0x0A, 1, FormatId::x}, |
| {0x0B, 1, FormatId::x}, |
| {0x0C, 1, FormatId::x}, |
| {0x0D, 1, FormatId::x}, |
| {0x0E, 1, FormatId::x}, |
| {0x0F, 1, FormatId::x}, |
| {0x10, 1, FormatId::x}, |
| {0x11, 1, FormatId::x}, |
| {0x12, 1, FormatId::n}, |
| {0x13, 2, FormatId::s}, |
| {0x14, 3, FormatId::i}, |
| {0x15, 2, FormatId::h}, |
| {0x16, 2, FormatId::s}, |
| {0x17, 3, FormatId::i}, |
| {0x18, 5, FormatId::l}, |
| {0x19, 2, FormatId::h}, |
| {0x1A, 2, FormatId::c}, |
| {0x1B, 3, FormatId::c}, |
| {0x1C, 2, FormatId::c}, |
| {0x1D, 1, FormatId::x}, |
| {0x1E, 1, FormatId::x}, |
| {0x1F, 2, FormatId::c}, |
| {0x20, 2, FormatId::c}, |
| {0x21, 1, FormatId::x}, |
| {0x22, 2, FormatId::c}, |
| {0x23, 2, FormatId::c}, |
| {0x24, 3, FormatId::c}, |
| {0x25, 3, FormatId::c}, |
| {0x26, 3, FormatId::t}, |
| {0x27, 1, FormatId::x}, |
| {0x28, 1, FormatId::t}, |
| {0x29, 2, FormatId::t}, |
| {0x2A, 3, FormatId::t}, |
| {0x2B, 3, FormatId::t}, |
| {0x2C, 3, FormatId::t}, |
| {0x2D, 2, FormatId::x, 5}, |
| {0x32, 2, FormatId::t, 6}, |
| {0x38, 2, FormatId::t, 6}, |
| // {0x3E, 1, FormatId::x, 6}, unused |
| {0x44, 2, FormatId::x, 14}, |
| {0x52, 2, FormatId::c, 14}, |
| {0x60, 2, FormatId::c, 14}, |
| {0x6E, 3, FormatId::c, 5}, |
| // {0x73, 1, FormatId::x}, unused |
| {0x74, 3, FormatId::c, 5}, |
| // {0x79, 1, FormatId::x, 2}, unused |
| {0x7B, 1, FormatId::x, 21}, |
| {0x90, 2, FormatId::x, 32}, |
| {0xB0, 1, FormatId::x, 32}, |
| {0xD0, 2, FormatId::s, 8}, |
| {0xD8, 2, FormatId::b, 11}, |
| // {0xE3, 1, FormatId::x, 29}, unused |
| {0xFA, 4, FormatId::c}, |
| {0xFB, 4, FormatId::c}, |
| {0xFC, 3, FormatId::c}, |
| {0xFD, 3, FormatId::c}, |
| {0xFE, 2, FormatId::c}, |
| {0xFF, 2, FormatId::c}, |
| }; |
| |
| // Supported by MSVC, g++, and clang++. Ensures no gaps in packing. |
| #pragma pack(push, 1) |
| |
| // header_item: Appears in the header section. |
| struct HeaderItem { |
| uint8_t magic[8]; |
| uint32_t checksum; |
| uint8_t signature[20]; |
| uint32_t file_size; |
| uint32_t header_size; |
| uint32_t endian_tag; |
| uint32_t link_size; |
| uint32_t link_off; |
| uint32_t map_off; |
| uint32_t string_ids_size; |
| uint32_t string_ids_off; |
| uint32_t type_ids_size; |
| uint32_t type_ids_off; |
| uint32_t proto_ids_size; |
| uint32_t proto_ids_off; |
| uint32_t field_ids_size; |
| uint32_t field_ids_off; |
| uint32_t method_ids_size; |
| uint32_t method_ids_off; |
| uint32_t class_defs_size; |
| uint32_t class_defs_off; |
| uint32_t data_size; |
| uint32_t data_off; |
| }; |
| |
| // string_id_item: String identifiers list. |
| struct StringIdItem { |
| uint32_t string_data_off; |
| }; |
| |
| // type_id_item: Type identifiers list. |
| struct TypeIdItem { |
| uint32_t descriptor_idx; |
| }; |
| |
| // proto_id_item: Method prototype identifiers list. |
| struct ProtoIdItem { |
| uint32_t shorty_idx; |
| uint32_t return_type_idx; |
| uint32_t parameters_off; |
| }; |
| |
| // field_id_item: Field identifiers list. |
| struct FieldIdItem { |
| uint16_t class_idx; |
| uint16_t type_idx; |
| uint32_t name_idx; |
| }; |
| |
| // method_id_item: Method identifiers list. |
| struct MethodIdItem { |
| uint16_t class_idx; |
| uint16_t proto_idx; |
| uint32_t name_idx; |
| }; |
| |
| // class_def_item: Class definitions list. |
| struct ClassDefItem { |
| uint32_t class_idx; |
| uint32_t access_flags; |
| uint32_t superclass_idx; |
| uint32_t interfaces_off; |
| uint32_t source_file_idx; |
| uint32_t annotations_off; |
| uint32_t class_data_off; |
| uint32_t static_values_off; |
| }; |
| |
| // call_site_id_item: Call site identifiers list. |
| struct CallSiteIdItem { |
| uint32_t call_site_off; |
| }; |
| |
| // method_handle_type: Determines the behavior of the MethodHandleItem. |
| enum class MethodHandleType : uint16_t { |
| // FieldId |
| kStaticPut = 0x00, |
| kStaticGet = 0x01, |
| kInstancePut = 0x02, |
| kInstanceGet = 0x03, |
| // MethodId |
| kInvokeStatic = 0x04, |
| kInvokeInstance = 0x05, |
| kInvokeConstructor = 0x06, |
| kInvokeDirect = 0x07, |
| kInvokeInterface = 0x08, |
| // Sentinel. If new types are added put them before this and increment. |
| kMaxMethodHandleType = 0x09 |
| }; |
| |
| // method_handle_item: Method handles referred within the Dex file. |
| struct MethodHandleItem { |
| uint16_t method_handle_type; |
| uint16_t unused_1; |
| uint16_t field_or_method_id; |
| uint16_t unused_2; |
| }; |
| |
| // code_item: Header of a code item. |
| struct CodeItem { |
| uint16_t registers_size; |
| uint16_t ins_size; |
| uint16_t outs_size; |
| uint16_t tries_size; |
| uint32_t debug_info_off; |
| uint32_t insns_size; |
| // Variable length data follow for complete code item. |
| }; |
| |
| // Number of valid type codes for map_item elements in map_list. |
| // See: https://source.android.com/devices/tech/dalvik/dex-format#type-codes |
| constexpr uint32_t kMaxItemListSize = 21; |
| |
| constexpr uint16_t kTypeHeaderItem = 0x0000; |
| constexpr uint16_t kTypeStringIdItem = 0x0001; |
| constexpr uint16_t kTypeTypeIdItem = 0x0002; |
| constexpr uint16_t kTypeProtoIdItem = 0x0003; |
| constexpr uint16_t kTypeFieldIdItem = 0x0004; |
| constexpr uint16_t kTypeMethodIdItem = 0x0005; |
| constexpr uint16_t kTypeClassDefItem = 0x0006; |
| constexpr uint16_t kTypeCallSiteIdItem = 0x0007; |
| constexpr uint16_t kTypeMethodHandleItem = 0x0008; |
| constexpr uint16_t kTypeMapList = 0x1000; |
| constexpr uint16_t kTypeTypeList = 0x1001; |
| constexpr uint16_t kTypeAnnotationSetRefList = 0x1002; |
| constexpr uint16_t kTypeAnnotationSetItem = 0x1003; |
| constexpr uint16_t kTypeClassDataItem = 0x2000; |
| constexpr uint16_t kTypeCodeItem = 0x2001; |
| constexpr uint16_t kTypeStringDataItem = 0x2002; |
| constexpr uint16_t kTypeDebugInfoItem = 0x2003; |
| constexpr uint16_t kTypeAnnotationItem = 0x2004; |
| constexpr uint16_t kTypeEncodedArrayItem = 0x2005; |
| constexpr uint16_t kTypeAnnotationsDirectoryItem = 0x2006; |
| constexpr uint16_t kTypeHiddenApiClassDataItem = 0xF000; |
| |
| // map_item |
| struct MapItem { |
| uint16_t type; |
| uint16_t unused; |
| uint32_t size; |
| uint32_t offset; |
| }; |
| |
| // map_list |
| struct MapList { |
| uint32_t size; |
| MapItem list[kMaxItemListSize]; |
| }; |
| |
| // type_item |
| struct TypeItem { |
| uint16_t type_idx; |
| }; |
| |
| // annotation_set_ref_item |
| struct AnnotationSetRefItem { |
| uint32_t annotations_off; |
| }; |
| |
| // annotation_off_item |
| struct AnnotationOffItem { |
| uint32_t annotation_off; |
| }; |
| |
| // field_annotation |
| struct FieldAnnotation { |
| uint32_t field_idx; |
| uint32_t annotations_off; |
| }; |
| |
| // method_annotation |
| struct MethodAnnotation { |
| uint32_t method_idx; |
| uint32_t annotations_off; |
| }; |
| |
| // parameter_annotation |
| struct ParameterAnnotation { |
| uint32_t method_idx; |
| uint32_t annotations_off; |
| }; |
| |
| // annotations_directory_item |
| struct AnnotationsDirectoryItem { |
| uint32_t class_annotations_off; |
| uint32_t fields_size; |
| uint32_t annotated_methods_size; |
| uint32_t annotated_parameters_size; |
| // FieldAnnotation field_annotations[fields_size]; |
| // MethodAnnotation method_annotations[annotated_methods_size]; |
| // ParameterAnnotation parameter_annotations[annotated_parameters_size]; |
| // All *Annotation are 8 bytes each. |
| }; |
| |
| // try_item |
| struct TryItem { |
| uint32_t start_addr; |
| uint16_t insn_count; |
| uint16_t handler_off; |
| }; |
| |
| #pragma pack(pop) |
| |
| } // namespace dex |
| } // namespace zucchini |
| |
| #endif // COMPONENTS_ZUCCHINI_TYPE_DEX_H_ |