add item related to class
This commit is contained in:
parent
42698cc8d7
commit
9ed99594cc
4 changed files with 293 additions and 6 deletions
252
androscalpel_serializer/src/items/class.rs
Normal file
252
androscalpel_serializer/src/items/class.rs
Normal file
|
|
@ -0,0 +1,252 @@
|
||||||
|
//! Class definitions.
|
||||||
|
|
||||||
|
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.
|
||||||
|
pub class_idx: u32,
|
||||||
|
/// See [access-flags](https://source.android.com/docs/core/runtime/dex-format#access-flags)
|
||||||
|
pub access_flags: u32,
|
||||||
|
/// Either index of a [`TypeIdItem`] in `type_ids`, must be a class or NO_INDEX
|
||||||
|
pub superclass_idx: u32,
|
||||||
|
/// 0 if no interfaces, else offset to a [`TypeList`].
|
||||||
|
pub interfaces_off: u32,
|
||||||
|
/// Index of a [`StringIdItem`] in `string_ids` or NO_INDEX.
|
||||||
|
pub source_file_idx: u32,
|
||||||
|
/// 0 if no annotation, else offset to a [`AnnotationDirectoryItem`].
|
||||||
|
pub annotations_off: u32,
|
||||||
|
/// 0 if no data for this class, else offset to a [`ClassDataItem`].
|
||||||
|
pub class_data_off: u32,
|
||||||
|
/// 0 if no static fields, else offset to an [`EncodedArrayItem`].
|
||||||
|
///
|
||||||
|
/// Notes:
|
||||||
|
///
|
||||||
|
/// > The size of the array must be no larger than the number of static
|
||||||
|
/// > fields declared by this class, and the elements correspond to the
|
||||||
|
/// > static fields in the same order as declared in the corresponding
|
||||||
|
/// > field_list. The type of each array element must match the declared
|
||||||
|
/// > type of its corresponding field. If there are fewer elements in the
|
||||||
|
/// > array than there are static fields, then the leftover fields are
|
||||||
|
/// > initialized with a type-appropriate 0 or null.
|
||||||
|
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 {
|
||||||
|
pub method_handle_type: MethodHandleType,
|
||||||
|
pub unused1: u16,
|
||||||
|
pub field_or_method_id: u16,
|
||||||
|
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 {
|
||||||
|
#[prefix(0x00)]
|
||||||
|
StaticPut,
|
||||||
|
#[prefix(0x01)]
|
||||||
|
StaticGet,
|
||||||
|
#[prefix(0x02)]
|
||||||
|
InstancePut,
|
||||||
|
#[prefix(0x03)]
|
||||||
|
InstanceGet,
|
||||||
|
#[prefix(0x04)]
|
||||||
|
InvokeStatic,
|
||||||
|
#[prefix(0x05)]
|
||||||
|
InvokeInstance,
|
||||||
|
#[prefix(0x06)]
|
||||||
|
InvokeConstructor,
|
||||||
|
#[prefix(0x07)]
|
||||||
|
InvokeDirect,
|
||||||
|
#[prefix(0x08)]
|
||||||
|
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,
|
||||||
|
// pub instance_fields_size: Uleb128,
|
||||||
|
// pub direct_methods_size: Uleb128,
|
||||||
|
// pub virtual_methods_size: Uleb128,
|
||||||
|
pub static_fields: Vec<EncodedField>,
|
||||||
|
pub instance_fields: Vec<EncodedField>,
|
||||||
|
pub direct_methods: Vec<EncodedMethod>,
|
||||||
|
pub virtual_methods: Vec<EncodedMethod>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClassDataItem {
|
||||||
|
pub fn static_fields_size_field(&self) -> Uleb128 {
|
||||||
|
Uleb128(self.static_fields.len() as u32)
|
||||||
|
}
|
||||||
|
pub fn instance_fields_size_field(&self) -> Uleb128 {
|
||||||
|
Uleb128(self.instance_fields.len() as u32)
|
||||||
|
}
|
||||||
|
pub fn direct_methods_size_field(&self) -> Uleb128 {
|
||||||
|
Uleb128(self.direct_methods.len() as u32)
|
||||||
|
}
|
||||||
|
pub fn virtual_methods_size_field(&self) -> Uleb128 {
|
||||||
|
Uleb128(self.virtual_methods.len() as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serializable for ClassDataItem {
|
||||||
|
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
||||||
|
self.static_fields_size_field().serialize(output)?;
|
||||||
|
self.instance_fields_size_field().serialize(output)?;
|
||||||
|
self.direct_methods_size_field().serialize(output)?;
|
||||||
|
self.virtual_methods_size_field().serialize(output)?;
|
||||||
|
for field in &self.static_fields {
|
||||||
|
field.serialize(output)?;
|
||||||
|
}
|
||||||
|
for field in &self.instance_fields {
|
||||||
|
field.serialize(output)?;
|
||||||
|
}
|
||||||
|
for method in &self.direct_methods {
|
||||||
|
method.serialize(output)?;
|
||||||
|
}
|
||||||
|
for method in &self.virtual_methods {
|
||||||
|
method.serialize(output)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
|
let Uleb128(static_fields_size) = Uleb128::deserialize(input)?;
|
||||||
|
let Uleb128(instance_fields_size) = Uleb128::deserialize(input)?;
|
||||||
|
let Uleb128(direct_methods_size) = Uleb128::deserialize(input)?;
|
||||||
|
let Uleb128(virtual_methods_size) = Uleb128::deserialize(input)?;
|
||||||
|
let mut static_fields = vec![];
|
||||||
|
let mut instance_fields = vec![];
|
||||||
|
let mut direct_methods = vec![];
|
||||||
|
let mut virtual_methods = vec![];
|
||||||
|
for _ in 0..static_fields_size {
|
||||||
|
static_fields.push(EncodedField::deserialize(input)?);
|
||||||
|
}
|
||||||
|
for _ in 0..instance_fields_size {
|
||||||
|
instance_fields.push(EncodedField::deserialize(input)?);
|
||||||
|
}
|
||||||
|
for _ in 0..direct_methods_size {
|
||||||
|
direct_methods.push(EncodedMethod::deserialize(input)?);
|
||||||
|
}
|
||||||
|
for _ in 0..virtual_methods_size {
|
||||||
|
virtual_methods.push(EncodedMethod::deserialize(input)?);
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
// static_fields_size: Uleb128(static_fields_size),
|
||||||
|
// instance_fields_size: Uleb128(instance_fields_size),
|
||||||
|
// direct_methods_size: Uleb128(direct_methods_size),
|
||||||
|
// virtual_methods_size: Uleb128(virtual_methods_size),
|
||||||
|
static_fields,
|
||||||
|
instance_fields,
|
||||||
|
direct_methods,
|
||||||
|
virtual_methods,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
self.static_fields_size_field().size()
|
||||||
|
+ self.instance_fields_size_field().size()
|
||||||
|
+ self.direct_methods_size_field().size()
|
||||||
|
+ self.virtual_methods_size_field().size()
|
||||||
|
+ self
|
||||||
|
.static_fields
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.size())
|
||||||
|
.sum::<usize>()
|
||||||
|
+ self
|
||||||
|
.instance_fields
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.size())
|
||||||
|
.sum::<usize>()
|
||||||
|
+ self
|
||||||
|
.direct_methods
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.size())
|
||||||
|
.sum::<usize>()
|
||||||
|
+ self
|
||||||
|
.virtual_methods
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.size())
|
||||||
|
.sum::<usize>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// (includes the name and descriptor), represented as a difference
|
||||||
|
/// from the index of previous element in the list. The index of the
|
||||||
|
/// first element in a list is represented directly.
|
||||||
|
pub field_idx_diff: Uleb128,
|
||||||
|
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
|
||||||
|
/// (includes the name and descriptor), represented as a difference
|
||||||
|
/// from the index of previous element in the list. The index of the
|
||||||
|
/// 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`].
|
||||||
|
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 {
|
||||||
|
// pub size: u32,
|
||||||
|
pub list: Vec<TypeItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeList {
|
||||||
|
fn size_field(&self) -> u32 {
|
||||||
|
self.list.len() as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serializable for TypeList {
|
||||||
|
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
||||||
|
self.size_field().serialize(output)?;
|
||||||
|
for item in &self.list {
|
||||||
|
item.serialize(output)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
|
let size = i32::deserialize(input)?;
|
||||||
|
let mut list = vec![];
|
||||||
|
for _ in 0..size {
|
||||||
|
list.push(TypeItem::deserialize(input)?);
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
// size,
|
||||||
|
list,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
self.size_field().size() + self.list.iter().map(|val| val.size()).sum::<usize>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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.
|
||||||
|
pub type_idx: u16,
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
//! The header item: https://source.android.com/docs/core/runtime/dex-format#header-item
|
//! The header item: https://source.android.com/docs/core/runtime/dex-format#header-item
|
||||||
|
|
||||||
use crate::{DexFileMagic, EndianConstant};
|
use crate as androscalpel_serializer;
|
||||||
|
use crate::{DexFileMagic, EndianConstant, Serializable};
|
||||||
|
|
||||||
/// The header item: https://source.android.com/docs/core/runtime/dex-format#header-item
|
/// The header item: https://source.android.com/docs/core/runtime/dex-format#header-item
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ impl MapList {
|
||||||
impl Serializable for MapList {
|
impl Serializable for MapList {
|
||||||
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
||||||
self.size_field().serialize(output)?;
|
self.size_field().serialize(output)?;
|
||||||
for map_item in self.list {
|
for map_item in &self.list {
|
||||||
map_item.serialize(output)?;
|
map_item.serialize(output)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
//! The items structures.
|
//! The items structures.
|
||||||
|
|
||||||
use crate as androscalpel_serializer;
|
use crate as androscalpel_serializer;
|
||||||
use crate::Serializable;
|
use crate::{EncodedArray, Serializable};
|
||||||
|
|
||||||
|
pub mod class;
|
||||||
pub mod header;
|
pub mod header;
|
||||||
pub mod map;
|
pub mod map;
|
||||||
|
|
||||||
|
pub use class::*;
|
||||||
pub use header::*;
|
pub use header::*;
|
||||||
pub use map::*;
|
pub use map::*;
|
||||||
|
|
||||||
|
|
@ -34,7 +36,7 @@ pub struct ProtoIdItem {
|
||||||
pub shorty_idx: u32,
|
pub shorty_idx: u32,
|
||||||
/// Index of a [`TypeIdItem`] in `type_ids`.
|
/// Index of a [`TypeIdItem`] in `type_ids`.
|
||||||
pub return_type_idx: u32,
|
pub return_type_idx: u32,
|
||||||
/// 0 if no parameter, else offset to a [`TypeList`.
|
/// 0 if no parameter, else offset to a [`TypeList`].
|
||||||
pub parameters_off: u32,
|
pub parameters_off: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,7 +44,7 @@ pub struct ProtoIdItem {
|
||||||
/// alignment: 4 bytes
|
/// alignment: 4 bytes
|
||||||
#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct FieldIdItem {
|
pub struct FieldIdItem {
|
||||||
/// Index of a [`TypeIdItem`] in `type_ids`], must be a class.
|
/// Index of a [`TypeIdItem`] in `type_ids`, must be a class.
|
||||||
pub class_idx: u16,
|
pub class_idx: u16,
|
||||||
/// Index of a [`TypeIdItem`] in `type_ids`.
|
/// Index of a [`TypeIdItem`] in `type_ids`.
|
||||||
pub type_idx: u16,
|
pub type_idx: u16,
|
||||||
|
|
@ -54,10 +56,42 @@ pub struct FieldIdItem {
|
||||||
/// alignment: 4 bytes
|
/// alignment: 4 bytes
|
||||||
#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct MethodIdItem {
|
pub struct MethodIdItem {
|
||||||
/// Index of a [`TypeIdItem`] in `type_ids`], must be a class.
|
/// Index of a [`TypeIdItem`] in `type_ids`, must be a class.
|
||||||
pub class_idx: u16,
|
pub class_idx: u16,
|
||||||
/// Index of a [`ProtoIdItem`] in `proto_ids`.
|
/// Index of a [`ProtoIdItem`] in `proto_ids`.
|
||||||
pub proto_idx: u16,
|
pub proto_idx: u16,
|
||||||
/// Index of a [`StringIdItem`] in [`HeaderItem.string_ids`].
|
/// Index of a [`StringIdItem`] in [`HeaderItem.string_ids`].
|
||||||
pub name_idx: u32,
|
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 {
|
||||||
|
/// Offset to a [`CallSiteItem`].
|
||||||
|
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 type corresponding to the type of the method name to be resolved
|
||||||
|
/// ([`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.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
pub type CallSiteItem = EncodedArrayItem;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue