add annotation item

This commit is contained in:
Jean-Marie Mineau 2023-08-29 11:50:24 +02:00
parent 70e552339d
commit b670649ed0
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
2 changed files with 235 additions and 0 deletions

View 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,
}