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
|
||||
|
||||
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
|
||||
///
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ impl MapList {
|
|||
impl Serializable for MapList {
|
||||
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
||||
self.size_field().serialize(output)?;
|
||||
for map_item in self.list {
|
||||
for map_item in &self.list {
|
||||
map_item.serialize(output)?;
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
//! The items structures.
|
||||
|
||||
use crate as androscalpel_serializer;
|
||||
use crate::Serializable;
|
||||
use crate::{EncodedArray, Serializable};
|
||||
|
||||
pub mod class;
|
||||
pub mod header;
|
||||
pub mod map;
|
||||
|
||||
pub use class::*;
|
||||
pub use header::*;
|
||||
pub use map::*;
|
||||
|
||||
|
|
@ -34,7 +36,7 @@ pub struct ProtoIdItem {
|
|||
pub shorty_idx: u32,
|
||||
/// Index of a [`TypeIdItem`] in `type_ids`.
|
||||
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,
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +44,7 @@ pub struct ProtoIdItem {
|
|||
/// alignment: 4 bytes
|
||||
#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
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,
|
||||
/// Index of a [`TypeIdItem`] in `type_ids`.
|
||||
pub type_idx: u16,
|
||||
|
|
@ -54,10 +56,42 @@ pub struct FieldIdItem {
|
|||
/// alignment: 4 bytes
|
||||
#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
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,
|
||||
/// Index of a [`ProtoIdItem`] in `proto_ids`.
|
||||
pub proto_idx: u16,
|
||||
/// Index of a [`StringIdItem`] in [`HeaderItem.string_ids`].
|
||||
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