blob: 77a247deff5c74e9754c8aa6c40c0dccad089bc0 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdint.h>
#include <string>
// Definitions for .dex file format structures and helpers.
//
// The names for the structures and fields follows the specification:
// https://source.android.com/devices/tech/dalvik/dex-format.html
namespace dex {
// These match the definitions in the VM specification
typedef uint8_t u1;
typedef uint16_t u2;
typedef uint32_t u4;
typedef uint64_t u8;
typedef int8_t s1;
typedef int16_t s2;
typedef int32_t s4;
typedef int64_t s8;
// General constants
constexpr u4 kEndianConstant = 0x12345678;
constexpr u4 kNoIndex = 0xffffffff;
constexpr u4 kSHA1DigestLen = 20;
// Annotation visibility
constexpr u1 kVisibilityBuild = 0x00;
constexpr u1 kVisibilityRuntime = 0x01;
constexpr u1 kVisibilitySystem = 0x02;
// Special visibility: encoded_annotation, not annotation_item
constexpr u1 kVisibilityEncoded = 0xff;
// encoded_value types
constexpr u1 kEncodedByte = 0x00;
constexpr u1 kEncodedShort = 0x02;
constexpr u1 kEncodedChar = 0x03;
constexpr u1 kEncodedInt = 0x04;
constexpr u1 kEncodedLong = 0x06;
constexpr u1 kEncodedFloat = 0x10;
constexpr u1 kEncodedDouble = 0x11;
constexpr u1 kEncodedString = 0x17;
constexpr u1 kEncodedType = 0x18;
constexpr u1 kEncodedField = 0x19;
constexpr u1 kEncodedMethod = 0x1a;
constexpr u1 kEncodedEnum = 0x1b;
constexpr u1 kEncodedArray = 0x1c;
constexpr u1 kEncodedAnnotation = 0x1d;
constexpr u1 kEncodedNull = 0x1e;
constexpr u1 kEncodedBoolean = 0x1f;
// encoded_value header
constexpr u1 kEncodedValueTypeMask = 0x1f;
constexpr u1 kEncodedValueArgShift = 5;
// access_flags
constexpr u4 kAccPublic = 0x0001; // class, field, method, ic
constexpr u4 kAccPrivate = 0x0002; // field, method, ic
constexpr u4 kAccProtected = 0x0004; // field, method, ic
constexpr u4 kAccStatic = 0x0008; // field, method, ic
constexpr u4 kAccFinal = 0x0010; // class, field, method, ic
constexpr u4 kAccSynchronized = 0x0020; // method (only allowed on natives)
constexpr u4 kAccSuper = 0x0020; // class (not used in dex)
constexpr u4 kAccVolatile = 0x0040; // field
constexpr u4 kAccBridge = 0x0040; // method
constexpr u4 kAccTransient = 0x0080; // field
constexpr u4 kAccVarargs = 0x0080; // method
constexpr u4 kAccNative = 0x0100; // method
constexpr u4 kAccInterface = 0x0200; // class, ic
constexpr u4 kAccAbstract = 0x0400; // class, method, ic
constexpr u4 kAccStrict = 0x0800; // method
constexpr u4 kAccSynthetic = 0x1000; // class, field, method, ic
constexpr u4 kAccAnnotation = 0x2000; // class, ic
constexpr u4 kAccEnum = 0x4000; // class, field, ic
constexpr u4 kAccConstructor = 0x00010000; // method (dex only) <(cl)init>
constexpr u4 kAccDeclaredSynchronized = 0x00020000; // method (dex only)
// map_item type codes
constexpr u2 kHeaderItem = 0x0000;
constexpr u2 kStringIdItem = 0x0001;
constexpr u2 kTypeIdItem = 0x0002;
constexpr u2 kProtoIdItem = 0x0003;
constexpr u2 kFieldIdItem = 0x0004;
constexpr u2 kMethodIdItem = 0x0005;
constexpr u2 kClassDefItem = 0x0006;
constexpr u2 kMapList = 0x1000;
constexpr u2 kTypeList = 0x1001;
constexpr u2 kAnnotationSetRefList = 0x1002;
constexpr u2 kAnnotationSetItem = 0x1003;
constexpr u2 kClassDataItem = 0x2000;
constexpr u2 kCodeItem = 0x2001;
constexpr u2 kStringDataItem = 0x2002;
constexpr u2 kDebugInfoItem = 0x2003;
constexpr u2 kAnnotationItem = 0x2004;
constexpr u2 kEncodedArrayItem = 0x2005;
constexpr u2 kAnnotationsDirectoryItem = 0x2006;
// debug info opcodes
constexpr u1 DBG_END_SEQUENCE = 0x00;
constexpr u1 DBG_ADVANCE_PC = 0x01;
constexpr u1 DBG_ADVANCE_LINE = 0x02;
constexpr u1 DBG_START_LOCAL = 0x03;
constexpr u1 DBG_START_LOCAL_EXTENDED = 0x04;
constexpr u1 DBG_END_LOCAL = 0x05;
constexpr u1 DBG_RESTART_LOCAL = 0x06;
constexpr u1 DBG_SET_PROLOGUE_END = 0x07;
constexpr u1 DBG_SET_EPILOGUE_BEGIN = 0x08;
constexpr u1 DBG_SET_FILE = 0x09;
constexpr u1 DBG_FIRST_SPECIAL = 0x0a;
// special debug info values
constexpr int DBG_LINE_BASE = -4;
constexpr int DBG_LINE_RANGE = 15;
// "header_item"
struct Header {
u1 magic[8];
u4 checksum;
u1 signature[kSHA1DigestLen];
u4 file_size;
u4 header_size;
u4 endian_tag;
u4 link_size;
u4 link_off;
u4 map_off;
u4 string_ids_size;
u4 string_ids_off;
u4 type_ids_size;
u4 type_ids_off;
u4 proto_ids_size;
u4 proto_ids_off;
u4 field_ids_size;
u4 field_ids_off;
u4 method_ids_size;
u4 method_ids_off;
u4 class_defs_size;
u4 class_defs_off;
u4 data_size;
u4 data_off;
};
// "map_item"
struct MapItem {
u2 type;
u2 unused;
u4 size;
u4 offset;
};
// "map_list"
struct MapList {
u4 size;
MapItem list[];
};
// "string_id_item"
struct StringId {
u4 string_data_off;
};
// "type_id_item"
struct TypeId {
u4 descriptor_idx;
};
// "field_id_item"
struct FieldId {
u2 class_idx;
u2 type_idx;
u4 name_idx;
};
// "method_id_item"
struct MethodId {
u2 class_idx;
u2 proto_idx;
u4 name_idx;
};
// "proto_id_item"
struct ProtoId {
u4 shorty_idx;
u4 return_type_idx;
u4 parameters_off;
};
// "class_def_item"
struct ClassDef {
u4 class_idx;
u4 access_flags;
u4 superclass_idx;
u4 interfaces_off;
u4 source_file_idx;
u4 annotations_off;
u4 class_data_off;
u4 static_values_off;
};
// "type_item"
struct TypeItem {
u2 type_idx;
};
// "type_list"
struct TypeList {
u4 size;
TypeItem list[];
};
// "code_item"
struct Code {
u2 registers_size;
u2 ins_size;
u2 outs_size;
u2 tries_size;
u4 debug_info_off;
u4 insns_size;
u2 insns[];
// followed by optional u2 padding
// followed by try_item[tries_size]
// followed by uleb128 handlersSize
// followed by catch_handler_item[handlersSize]
};
// "try_item"
struct TryBlock {
u4 start_addr;
u2 insn_count;
u2 handler_off;
};
// "annotations_directory_item"
struct AnnotationsDirectoryItem {
u4 class_annotations_off;
u4 fields_size;
u4 methods_size;
u4 parameters_size;
// followed by FieldAnnotationsItem[fields_size]
// followed by MethodAnnotationsItem[methods_size]
// followed by ParameterAnnotationsItem[parameters_size]
};
// "field_annotations_item"
struct FieldAnnotationsItem {
u4 field_idx;
u4 annotations_off;
};
// "method_annotations_item"
struct MethodAnnotationsItem {
u4 method_idx;
u4 annotations_off;
};
// "parameter_annotations_item"
struct ParameterAnnotationsItem {
u4 method_idx;
u4 annotations_off;
};
// "annotation_set_ref_item"
struct AnnotationSetRefItem {
u4 annotations_off;
};
// "annotation_set_ref_list"
struct AnnotationSetRefList {
u4 size;
AnnotationSetRefItem list[];
};
// "annotation_set_item"
struct AnnotationSetItem {
u4 size;
u4 entries[];
};
// "annotation_item"
struct AnnotationItem {
u1 visibility;
u1 annotation[];
};
// Compute DEX checksum
u4 ComputeChecksum(const Header* header);
// Converts a type descriptor to a human-readable declaration
std::string DescriptorToDecl(const char* descriptor);
// Converts a type descriptor to the equivalent shorty type descriptor
char DescriptorToShorty(const char* descriptor);
} // namespace dex