diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..913e264 --- /dev/null +++ b/TODO.md @@ -0,0 +1,5 @@ +- edditable format +- python binding +- sanity checks +- tests +- https://source.android.com/docs/core/runtime/dex-format#system-annotation diff --git a/androscalpel_serializer/src/annotation/encoded_annotation.rs b/androscalpel_serializer/src/annotation/encoded_annotation.rs index b37303f..cc25d07 100644 --- a/androscalpel_serializer/src/annotation/encoded_annotation.rs +++ b/androscalpel_serializer/src/annotation/encoded_annotation.rs @@ -4,7 +4,7 @@ use std::io::Write; // To derive Serializable use crate as androscalpel_serializer; -/// Encoded Annotation https://source.android.com/docs/core/runtime/dex-format#encoded-annotation +/// #[derive(Debug, Clone, PartialEq, Eq)] pub struct EncodedAnnotation { /// Type of the annotation. This must be a class (not array or primitive) type. @@ -20,7 +20,7 @@ impl EncodedAnnotation { } } -/// Annotation: https://source.android.com/docs/core/runtime/dex-format#annotation-element +/// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct AnnotationElement { pub name_idx: Uleb128, diff --git a/androscalpel_serializer/src/annotation/mod.rs b/androscalpel_serializer/src/annotation/mod.rs index 56afde3..578a57a 100644 --- a/androscalpel_serializer/src/annotation/mod.rs +++ b/androscalpel_serializer/src/annotation/mod.rs @@ -7,23 +7,23 @@ use crate as androscalpel_serializer; use crate::{ReadSeek, Result, Serializable}; use std::io::Write; -/// https://source.android.com/docs/core/runtime/dex-format#referenced-from-class_def_item_1 +/// /// alignment: 4 bytes #[derive(Debug, Clone, PartialEq, Eq)] pub struct AnnotationDirectoryItem { - /// 0 if they are no annotation, else offset of an [`AnnotationSetItem`]. + /// 0 if they are no annotation, else offset of an [`crate::AnnotationSetItem`]. pub class_annotations_off: u32, // pub fields_size: u32, // pub annotated_methods_size: u32, // pub annotated_parameters_size: u32, /// List of field annotation. The field annotations must be sorted by - /// increasing order of [`FieldAnnotation.field_idx`]. + /// increasing order of [`crate::FieldAnnotation.field_idx`]. pub field_annotations: Vec, /// List of method annotation. The method annotations must be sorted by - /// increasing order of [`MethodAnnotation.method_idx`]. + /// increasing order of [`crate::MethodAnnotation.method_idx`]. pub method_annotation: Vec, /// List of associated method parameter annotation. The parameter annotations - /// must be sorted by increasing order of [`ParameterAnnotation.parameter_size`]. + /// must be sorted by increasing order of [`crate::ParameterAnnotation.parameter_size`]. pub parameter_annotations: Vec, } @@ -105,7 +105,7 @@ impl Serializable for AnnotationDirectoryItem { } } -/// https://source.android.com/docs/core/runtime/dex-format#field-annotation +/// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct FieldAnnotation { pub field_idx: u32, @@ -113,7 +113,7 @@ pub struct FieldAnnotation { pub annotation_off: u32, } -/// https://source.android.com/docs/core/runtime/dex-format#method-annotation +/// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct MethodAnnotation { pub method_idx: u32, @@ -121,7 +121,7 @@ pub struct MethodAnnotation { pub annotation_off: u32, } -/// https://source.android.com/docs/core/runtime/dex-format#parameter-annotation +/// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct ParameterAnnotation { pub field_idx: u32, @@ -129,7 +129,7 @@ pub struct ParameterAnnotation { pub annotation_off: u32, } -/// https://source.android.com/docs/core/runtime/dex-format#set-ref-list +/// /// alignment: 4 bytes #[derive(Debug, Clone, PartialEq, Eq)] pub struct AnnotationSetRefList { @@ -164,14 +164,14 @@ impl Serializable for AnnotationSetRefList { } } -/// https://source.android.com/docs/core/runtime/dex-format#set-ref-item +/// #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct AnnotationSetRefItem { /// 0 if there are no annotation, offset to a [`AnnotationSetItem`] else. pub annotations_off: u32, } -/// https://source.android.com/docs/core/runtime/dex-format#annotation-set-item +/// /// alignment: 4 #[derive(Debug, Clone, PartialEq, Eq)] pub struct AnnotationSetItem { @@ -207,14 +207,14 @@ impl Serializable for AnnotationSetItem { } } -/// https://source.android.com/docs/core/runtime/dex-format#off-item +/// #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct AnnotationOffItem { - /// Offset to a [`AnnotationItem`] + /// Offset to a [`crate::AnnotationItem`] pub annotation_off: u32, } -/// https://source.android.com/docs/core/runtime/dex-format#annotation-item +/// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct AnnotationItem { pub visibility: AnnotationVisibility, @@ -222,7 +222,7 @@ pub struct AnnotationItem { } // TODO: Enum or flags ? -/// https://source.android.com/docs/core/runtime/dex-format#annotation-item +/// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] #[prefix_type(u8)] pub enum AnnotationVisibility { diff --git a/androscalpel_serializer/src/array.rs b/androscalpel_serializer/src/array.rs index 52582f8..7e56a35 100644 --- a/androscalpel_serializer/src/array.rs +++ b/androscalpel_serializer/src/array.rs @@ -2,7 +2,7 @@ use crate::{EncodedValue, Uleb128}; use crate::{ReadSeek, Result, Serializable}; use std::io::Write; -/// Encoded Array: https://source.android.com/docs/core/runtime/dex-format#encoded-array +/// #[derive(Debug, Clone, PartialEq, Eq)] pub struct EncodedArray { // pub size: Uleb128, diff --git a/androscalpel_serializer/src/core/string.rs b/androscalpel_serializer/src/core/string.rs index 85ebf83..a506373 100644 --- a/androscalpel_serializer/src/core/string.rs +++ b/androscalpel_serializer/src/core/string.rs @@ -1,5 +1,5 @@ //! The string representation, encoded in MUTF-8 -//! https://source.android.com/docs/core/runtime/dex-format#mutf-8 +//! //! //! The encoding of codepoint in MUTF-8 is as following (table from //! ): @@ -16,7 +16,7 @@ use crate as androscalpel_serializer; use crate::core::*; pub use androscalpel_serializer_derive::*; -/// [string-data-item](https://source.android.com/docs/core/runtime/dex-format#string-data-item) +/// #[derive(Serializable, PartialEq, Eq, Debug)] pub struct StringDataItem { pub utf16_size: Uleb128, @@ -251,8 +251,8 @@ impl StringDataItem { mod test { use super::*; - /// Test for bug found in https://github.com/TkTech/mutf8/tree/master: - /// https://github.com/TkTech/mutf8/blob/master/tests/test_bugs.py + /// Test for bug found in : + /// #[test] fn bug_tktech_mutf8() { let string_issue_1 = "[가 나 다 라 마 바 사 아 자 차 카 타 파 하]"; @@ -285,8 +285,8 @@ mod test { assert_eq!(&decoded, string_issue_3); } - /// Test from https://github.com/TkTech/mutf8/tree/master, test for bad encoding - /// Test for bug found in https://github.com/TkTech/mutf8/tree/master: + /// Test from , test for bad encoding + /// Test for bug found in : #[test] fn test_tktech_bad_mutf8() { assert!(TryInto::::try_into(StringDataItem { @@ -311,8 +311,8 @@ mod test { .is_err()); } - /// Test from https://github.com/TkTech/mutf8/tree/master, test 2 bytes - /// Test for bug found in https://github.com/TkTech/mutf8/tree/master: + /// Test from , test 2 bytes + /// Test for bug found in : #[test] fn test_tktech_2_bytes_mutf8() { let tests = vec![ @@ -350,8 +350,8 @@ mod test { } } - /// Test from https://github.com/TkTech/mutf8/tree/master, test 3 bytes - /// Test for bug found in https://github.com/TkTech/mutf8/tree/master: + /// Test from , test 3 bytes + /// Test for bug found in : #[test] fn test_tktech_3_bytes_mutf8() { let tests = vec![ @@ -411,8 +411,8 @@ mod test { } } - /// Test from https://github.com/TkTech/mutf8/tree/master, test 6 bytes - /// Test for bug found in https://github.com/TkTech/mutf8/tree/master: + /// Test from , test 6 bytes + /// Test for bug found in : #[test] fn test_tktech_6_bytes_mutf8() { let tests = vec![ diff --git a/androscalpel_serializer/src/debug.rs b/androscalpel_serializer/src/debug.rs index 7ee8c0d..4b4cec6 100644 --- a/androscalpel_serializer/src/debug.rs +++ b/androscalpel_serializer/src/debug.rs @@ -4,7 +4,7 @@ use crate as androscalpel_serializer; use crate::{ReadSeek, Result, Serializable, SerializableUntil, Sleb128, Uleb128, Uleb128p1}; use std::io::Write; -/// https://source.android.com/docs/core/runtime/dex-format#debug-info-item +/// #[derive(Debug, PartialEq, Eq, Clone)] pub struct DebugInfoItem { pub line_start: Uleb128, diff --git a/androscalpel_serializer/src/items/class.rs b/androscalpel_serializer/src/items/class.rs index 79e24a1..2d85389 100644 --- a/androscalpel_serializer/src/items/class.rs +++ b/androscalpel_serializer/src/items/class.rs @@ -4,25 +4,25 @@ use crate as androscalpel_serializer; use crate::{ReadSeek, Result, Serializable, Uleb128}; use std::io::Write; -/// https://source.android.com/docs/core/runtime/dex-format#class-def-item +/// /// alignment: 4 bytes #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct ClassDefItem { - /// Index of a [`TypeIdItem`] in `type_ids`, must be a class. + /// Index of a [`crate::TypeIdItem`] in `type_ids`, must be a class. pub class_idx: u32, - /// See [access-flags](https://source.android.com/docs/core/runtime/dex-format#access-flags) + /// See pub access_flags: u32, - /// Either index of a [`TypeIdItem`] in `type_ids`, must be a class or NO_INDEX + /// Either index of a [`crate::TypeIdItem`] in `type_ids`, must be a class or NO_INDEX pub superclass_idx: u32, - /// 0 if no interfaces, else offset to a [`TypeList`]. + /// 0 if no interfaces, else offset to a [`crate::TypeList`]. pub interfaces_off: u32, - /// Index of a [`StringIdItem`] in `string_ids` or NO_INDEX. + /// Index of a [`crate::StringIdItem`] in `string_ids` or [`crate::NO_INDEX`]. pub source_file_idx: u32, - /// 0 if no annotation, else offset to a [`AnnotationDirectoryItem`]. + /// 0 if no annotation, else offset to a [`crate::AnnotationDirectoryItem`]. pub annotations_off: u32, - /// 0 if no data for this class, else offset to a [`ClassDataItem`]. + /// 0 if no data for this class, else offset to a [`crate::ClassDataItem`]. pub class_data_off: u32, - /// 0 if no static fields, else offset to an [`EncodedArrayItem`]. + /// 0 if no static fields, else offset to an [`crate::EncodedArrayItem`]. /// /// Notes: /// @@ -36,7 +36,7 @@ pub struct ClassDefItem { pub static_values_off: u32, } -/// https://source.android.com/docs/core/runtime/dex-format#method-handle-item +/// /// alignment: 4 bytes #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct MethodHandleItem { @@ -46,7 +46,7 @@ pub struct MethodHandleItem { pub unused2: u16, } -/// https://source.android.com/docs/core/runtime/dex-format#method-handle-type-codes +/// #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] #[prefix_type(u16)] pub enum MethodHandleType { @@ -70,7 +70,7 @@ pub enum MethodHandleType { InvokeInterface, } -/// https://source.android.com/docs/core/runtime/dex-format#class-data-item +/// #[derive(Debug, Clone, PartialEq, Eq)] pub struct ClassDataItem { // pub static_fields_size: Uleb128, @@ -180,7 +180,7 @@ impl Serializable for ClassDataItem { } } -/// https://source.android.com/docs/core/runtime/dex-format#encoded-field-format +/// #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct EncodedField { /// Index into the `field_ids` list for the identity of this field @@ -191,7 +191,7 @@ pub struct EncodedField { pub access_flags: Uleb128, } -/// https://source.android.com/docs/core/runtime/dex-format#encoded-method +/// #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct EncodedMethod { /// Index into the `method_ids list` for the identity of this method @@ -200,11 +200,11 @@ pub struct EncodedMethod { /// first element in a list is represented directly. pub method_idx_diff: Uleb128, pub access_flags: Uleb128, - /// 0 if abstract or native, else offset to a [`CodeItem`]. + /// 0 if abstract or native, else offset to a [`crate::CodeItem`]. pub code_off: Uleb128, } -/// https://source.android.com/docs/core/runtime/dex-format#type-list +/// /// alignment: 4 bytes #[derive(Debug, Clone, PartialEq, Eq)] pub struct TypeList { @@ -244,7 +244,7 @@ impl Serializable for TypeList { } } -/// https://source.android.com/docs/core/runtime/dex-format#type-item-format +/// #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct TypeItem { /// Index into the `type_ids` list. diff --git a/androscalpel_serializer/src/items/code.rs b/androscalpel_serializer/src/items/code.rs index e944223..87c697e 100644 --- a/androscalpel_serializer/src/items/code.rs +++ b/androscalpel_serializer/src/items/code.rs @@ -4,7 +4,7 @@ use crate as androscalpel_serializer; use crate::{Error, ReadSeek, Result, Serializable, Sleb128, Uleb128}; use std::io::Write; -/// https://source.android.com/docs/core/runtime/dex-format#code-item +/// /// alignment: 4 bytes #[derive(Clone, Debug, PartialEq, Eq)] pub struct CodeItem { @@ -12,7 +12,7 @@ pub struct CodeItem { pub ins_size: u16, pub outs_size: u16, // pub tries_size: u16, - /// 0 if no debug info, else offset to a [`DebugInfoItem`]. + /// 0 if no debug info, else offset to a [`crate::DebugInfoItem`]. pub debug_info_off: u32, // pub insns_size: u32, pub insns: Vec, @@ -166,7 +166,7 @@ impl Serializable for CodeItem { } } -/// https://source.android.com/docs/core/runtime/dex-format#type-item +/// #[derive(Serializable, Clone, Copy, Debug, PartialEq, Eq)] pub struct TryItem { /// Start address of the block of code covered. It's a count of 16-bit code unit to the @@ -179,7 +179,7 @@ pub struct TryItem { pub handler_off: u16, } -/// https://source.android.com/docs/core/runtime/dex-format#encoded-catch-handlerlist +/// #[derive(Clone, Debug, PartialEq, Eq)] pub struct EncodedCatchHandlerList { // pub size: Uleb128, @@ -191,9 +191,9 @@ impl EncodedCatchHandlerList { Uleb128(self.list.len() as u32) } - /// Return a reference to the [`EncodedCatchHandler`] located at `offset` bytes after - /// the begining of the [`EncodedCatchHandlerList`]. Expected to be used to lookup - /// the value refered to by [`TryItem.handler_off`]. + /// Return a reference to the [`crate::EncodedCatchHandler`] located at `offset` bytes after + /// the begining of the [`crate::EncodedCatchHandlerList`]. Expected to be used to lookup + /// the value refered to by [`crate::TryItem.handler_off`]. pub fn get_handler_at_offset(&self, offset: u16) -> Result<&EncodedCatchHandler> { let offset = offset as usize; let mut current_offset = 0; @@ -238,7 +238,7 @@ impl Serializable for EncodedCatchHandlerList { } } -/// https://source.android.com/docs/core/runtime/dex-format#encoded-catch-handler +/// #[derive(Clone, Debug, PartialEq, Eq)] pub struct EncodedCatchHandler { // pub size: Sleb128, @@ -313,10 +313,10 @@ impl Serializable for EncodedCatchHandler { } } -/// https://source.android.com/docs/core/runtime/dex-format#encoded-type-addr-pair +/// #[derive(Serializable, Clone, Copy, Debug, PartialEq, Eq)] pub struct EncodedTypeAddrPair { - /// Index of the [`TypeId`] in `type_ids` + /// Index of the [`crate::TypeIdItem`] in `type_ids` pub type_idx: Uleb128, /// Bytecode address of the exception handler pub addr: Uleb128, diff --git a/androscalpel_serializer/src/items/header.rs b/androscalpel_serializer/src/items/header.rs index 9b31915..8cf2699 100644 --- a/androscalpel_serializer/src/items/header.rs +++ b/androscalpel_serializer/src/items/header.rs @@ -1,13 +1,12 @@ -//! The header item: https://source.android.com/docs/core/runtime/dex-format#header-item +//! The header item: use crate as androscalpel_serializer; use crate::{DexFileMagic, EndianConstant, Serializable}; -/// The header item: https://source.android.com/docs/core/runtime/dex-format#header-item -/// +/// /// alignment: 4 bytes #[derive(Serializable, PartialEq, Eq, Debug)] -pub struct UserItem { +pub struct HeaderItem { pub magic: DexFileMagic, pub checksum: u32, pub signature: [u8; 20], diff --git a/androscalpel_serializer/src/items/hiddenapi.rs b/androscalpel_serializer/src/items/hiddenapi.rs index a918a5a..d43213b 100644 --- a/androscalpel_serializer/src/items/hiddenapi.rs +++ b/androscalpel_serializer/src/items/hiddenapi.rs @@ -4,7 +4,7 @@ use crate as androscalpel_serializer; use crate::{Error, ReadSeek, Result, Serializable, Uleb128}; use std::io::{Cursor, Write}; -/// https://source.android.com/docs/core/runtime/dex-format#hiddenapi-class-data-item +/// /// Hard to serialize/deserialize without additional data like the number of classes /// or the method/field of the classes. #[derive(Clone, PartialEq, Eq)] diff --git a/androscalpel_serializer/src/items/map.rs b/androscalpel_serializer/src/items/map.rs index c119311..ba71ac8 100644 --- a/androscalpel_serializer/src/items/map.rs +++ b/androscalpel_serializer/src/items/map.rs @@ -1,10 +1,10 @@ -//! The map item: https://source.android.com/docs/core/runtime/dex-format#map-list +//! The map item: use crate as androscalpel_serializer; use crate::core::{ReadSeek, Result, Serializable}; use std::io::Write; -/// The map item: https://source.android.com/docs/core/runtime/dex-format#map-list +/// /// alignment: 4 bytes #[derive(Clone, PartialEq, Eq, Debug)] pub struct MapList { @@ -12,7 +12,7 @@ pub struct MapList { pub list: Vec, } -/// The location and size of an item: https://source.android.com/docs/core/runtime/dex-format#map-item +/// The location and size of an item: #[derive(Serializable, Clone, PartialEq, Eq, Debug)] pub struct MapItem { pub type_: MapItemType, @@ -21,7 +21,7 @@ pub struct MapItem { pub offset: u32, } -/// The type of the items refered by a [`MapItem`]: https://source.android.com/docs/core/runtime/dex-format#type-codes +/// The type of the items refered by a [`MapItem`]: #[derive(Serializable, Clone, Copy, PartialEq, Eq, Debug)] #[prefix_type(u16)] pub enum MapItemType { diff --git a/androscalpel_serializer/src/items/mod.rs b/androscalpel_serializer/src/items/mod.rs index 99abac7..15d60f1 100644 --- a/androscalpel_serializer/src/items/mod.rs +++ b/androscalpel_serializer/src/items/mod.rs @@ -15,7 +15,7 @@ pub use header::*; pub use hiddenapi::*; pub use map::*; -/// https://source.android.com/docs/core/runtime/dex-format#string-item +/// /// alignment: 4 bytes #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct StringIdItem { @@ -24,7 +24,7 @@ pub struct StringIdItem { pub use crate::StringDataItem; -/// https://source.android.com/docs/core/runtime/dex-format#type-id-item +/// /// alignment: 4 bytes #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct TypeIdItem { @@ -32,7 +32,7 @@ pub struct TypeIdItem { pub descriptor_idx: u32, } -/// https://source.android.com/docs/core/runtime/dex-format#proto-id-item +/// /// alignment: 4 bytes #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct ProtoIdItem { @@ -44,7 +44,7 @@ pub struct ProtoIdItem { pub parameters_off: u32, } -/// https://source.android.com/docs/core/runtime/dex-format#field-id-item +/// /// alignment: 4 bytes #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct FieldIdItem { @@ -56,7 +56,7 @@ pub struct FieldIdItem { pub name_idx: u32, } -/// https://source.android.com/docs/core/runtime/dex-format#method-id-item +/// /// alignment: 4 bytes #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct MethodIdItem { @@ -68,7 +68,7 @@ pub struct MethodIdItem { pub name_idx: u32, } -/// https://source.android.com/docs/core/runtime/dex-format#call-site-id-item +/// /// alignment: 4 bytes #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct CallSiteIdItem { @@ -76,23 +76,23 @@ pub struct CallSiteIdItem { pub call_site_off: u32, } -/// https://source.android.com/docs/core/runtime/dex-format#encoded-array-item +/// /// alignment: none #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct EncodedArrayItem { pub value: EncodedArray, } -/// https://source.android.com/docs/core/runtime/dex-format#call-site-item +/// /// /// The call_site_item is an encoded_array_item whose elements correspond to /// the arguments provided to a bootstrap linker method. /// /// The first three arguments are: -/// - A method handle representing the bootstrap linker method ([`EncodedValue::MethodHandle`]) -/// - A method name that the bootstrap linker should resolve ([`EncodedValue::String`]) +/// - A method handle representing the bootstrap linker method ([`crate::EncodedValue::MethodHandle`]) +/// - A method name that the bootstrap linker should resolve ([`crate::EncodedValue::String`]) /// - A method type corresponding to the type of the method name to be resolved -/// ([`EncodedValue::MethodType`]) +/// ([`crate::EncodedValue::MethodType`]) /// /// Any additional arguments are constant values passed to the bootstrap linker method. /// These arguments are passed in order and without any type conversions. diff --git a/androscalpel_serializer/src/value.rs b/androscalpel_serializer/src/value.rs index c76a59a..3a89b8f 100644 --- a/androscalpel_serializer/src/value.rs +++ b/androscalpel_serializer/src/value.rs @@ -1,10 +1,10 @@ -//! The encoded value format: https://source.android.com/docs/core/runtime/dex-format#encoding +//! The encoded value format: use crate::{EncodedAnnotation, EncodedArray, Error, ReadSeek, Result, Serializable}; use std::io::Write; /// An encoded value of arbitrary hierachically structured data: -/// https://source.android.com/docs/core/runtime/dex-format#encoding +/// #[derive(Debug, Clone)] pub enum EncodedValue { Byte(i8),