add annotation item
This commit is contained in:
parent
70e552339d
commit
b670649ed0
2 changed files with 235 additions and 0 deletions
235
androscalpel_serializer/src/annotation/mod.rs
Normal file
235
androscalpel_serializer/src/annotation/mod.rs
Normal file
|
|
@ -0,0 +1,235 @@
|
||||||
|
//! Annotation items.
|
||||||
|
|
||||||
|
pub mod encoded_annotation;
|
||||||
|
pub use encoded_annotation::*;
|
||||||
|
|
||||||
|
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`].
|
||||||
|
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`].
|
||||||
|
pub field_annotations: Vec<FieldAnnotation>,
|
||||||
|
/// List of method annotation. The method annotations must be sorted by
|
||||||
|
/// increasing order of [`MethodAnnotation.method_idx`].
|
||||||
|
pub method_annotation: Vec<MethodAnnotation>,
|
||||||
|
/// List of associated method parameter annotation. The parameter annotations
|
||||||
|
/// must be sorted by increasing order of [`ParameterAnnotation.parameter_size`].
|
||||||
|
pub parameter_annotations: Vec<ParameterAnnotation>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnnotationDirectoryItem {
|
||||||
|
pub fn fields_size_field(&self) -> u32 {
|
||||||
|
self.field_annotations.len() as u32
|
||||||
|
}
|
||||||
|
pub fn annotated_methods_size_field(&self) -> u32 {
|
||||||
|
self.method_annotation.len() as u32
|
||||||
|
}
|
||||||
|
pub fn parameter_annotations_field(&self) -> u32 {
|
||||||
|
self.parameter_annotations.len() as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serializable for AnnotationDirectoryItem {
|
||||||
|
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
||||||
|
self.class_annotations_off.serialize(output)?;
|
||||||
|
self.fields_size_field().serialize(output)?;
|
||||||
|
self.annotated_methods_size_field().serialize(output)?;
|
||||||
|
self.parameter_annotations_field().serialize(output)?;
|
||||||
|
|
||||||
|
for item in &self.field_annotations {
|
||||||
|
item.serialize(output)?;
|
||||||
|
}
|
||||||
|
for item in &self.method_annotation {
|
||||||
|
item.serialize(output)?;
|
||||||
|
}
|
||||||
|
for item in &self.parameter_annotations {
|
||||||
|
item.serialize(output)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
|
let class_annotations_off = u32::deserialize(input)?;
|
||||||
|
let fields_size = u32::deserialize(input)?;
|
||||||
|
let annotated_methods_size = u32::deserialize(input)?;
|
||||||
|
let annotated_parameters_size = u32::deserialize(input)?;
|
||||||
|
let mut field_annotations = vec![];
|
||||||
|
for _ in 0..fields_size {
|
||||||
|
field_annotations.push(FieldAnnotation::deserialize(input)?);
|
||||||
|
}
|
||||||
|
let mut method_annotation = vec![];
|
||||||
|
for _ in 0..annotated_methods_size {
|
||||||
|
method_annotation.push(MethodAnnotation::deserialize(input)?);
|
||||||
|
}
|
||||||
|
let mut parameter_annotations = vec![];
|
||||||
|
for _ in 0..annotated_parameters_size {
|
||||||
|
parameter_annotations.push(ParameterAnnotation::deserialize(input)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
class_annotations_off,
|
||||||
|
field_annotations,
|
||||||
|
method_annotation,
|
||||||
|
parameter_annotations,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
self.class_annotations_off.size()
|
||||||
|
+ self.fields_size_field().size()
|
||||||
|
+ self.annotated_methods_size_field().size()
|
||||||
|
+ self.parameter_annotations_field().size()
|
||||||
|
+ self
|
||||||
|
.field_annotations
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.size())
|
||||||
|
.sum::<usize>()
|
||||||
|
+ self
|
||||||
|
.method_annotation
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.size())
|
||||||
|
.sum::<usize>()
|
||||||
|
+ self
|
||||||
|
.parameter_annotations
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.size())
|
||||||
|
.sum::<usize>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://source.android.com/docs/core/runtime/dex-format#field-annotation
|
||||||
|
#[derive(Serializable, Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct FieldAnnotation {
|
||||||
|
pub field_idx: u32,
|
||||||
|
/// Offset to a [`AnnotationSetItem`]
|
||||||
|
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,
|
||||||
|
/// Offset to a [`AnnotationSetItem`]
|
||||||
|
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,
|
||||||
|
/// Offset of a [`AnnotationSetRefList`]
|
||||||
|
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 {
|
||||||
|
// pub size: u32,
|
||||||
|
pub list: Vec<AnnotationSetRefItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnnotationSetRefList {
|
||||||
|
pub fn size_field(&self) -> u32 {
|
||||||
|
self.list.len() as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serializable for AnnotationSetRefList {
|
||||||
|
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 = u32::deserialize(input)?;
|
||||||
|
let mut list = vec![];
|
||||||
|
for _ in 0..size {
|
||||||
|
list.push(AnnotationSetRefItem::deserialize(input)?);
|
||||||
|
}
|
||||||
|
Ok(Self { 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#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 {
|
||||||
|
// pub size: u32,
|
||||||
|
/// Must be sorted by increasing [`AnnotationOffItem.type_idx`].
|
||||||
|
pub entries: Vec<AnnotationOffItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnnotationSetItem {
|
||||||
|
pub fn size_field(&self) -> u32 {
|
||||||
|
self.entries.len() as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serializable for AnnotationSetItem {
|
||||||
|
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
||||||
|
self.size_field().serialize(output)?;
|
||||||
|
for item in &self.entries {
|
||||||
|
item.serialize(output)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
|
let size = u32::deserialize(input)?;
|
||||||
|
let mut entries = vec![];
|
||||||
|
for _ in 0..size {
|
||||||
|
entries.push(AnnotationOffItem::deserialize(input)?);
|
||||||
|
}
|
||||||
|
Ok(Self { entries })
|
||||||
|
}
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
self.size_field().size() + self.entries.iter().map(|val| val.size()).sum::<usize>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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`]
|
||||||
|
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,
|
||||||
|
pub annotation: EncodedAnnotation,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
#[prefix(0x00)]
|
||||||
|
Build,
|
||||||
|
#[prefix(0x01)]
|
||||||
|
Runtime,
|
||||||
|
#[prefix(0x02)]
|
||||||
|
System,
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue