add annotations for methods and parameters

This commit is contained in:
Jean-Marie Mineau 2023-11-29 12:12:41 +01:00
parent cf55766653
commit 224d1efdba
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
4 changed files with 160 additions and 14 deletions

View file

@ -92,7 +92,7 @@ impl Apk {
Some(dex.get_struct_at_offset::<AnnotationDirectoryItem>(class_item.annotations_off)?) Some(dex.get_struct_at_offset::<AnnotationDirectoryItem>(class_item.annotations_off)?)
}; };
let mut annotations = vec![]; let mut annotations = vec![];
if let Some(annotations_directory) = annotations_directory { if let Some(annotations_directory) = &annotations_directory {
if annotations_directory.class_annotations_off != 0 { if annotations_directory.class_annotations_off != 0 {
annotations = Self::get_annotation_items_from_annotation_set_off( annotations = Self::get_annotation_items_from_annotation_set_off(
annotations_directory.class_annotations_off, annotations_directory.class_annotations_off,
@ -137,6 +137,134 @@ impl Apk {
field.value = None; field.value = None;
} }
} }
if let Some(annotations_directory) = annotations_directory {
for field_annotation in annotations_directory.field_annotations {
let field_id =
Self::get_id_field_from_idx(field_annotation.field_idx as usize, dex)?;
let annotations = if field_annotation.annotations_off != 0 {
Self::get_annotation_items_from_annotation_set_off(
field_annotation.annotations_off,
dex,
)?
} else {
vec![]
};
if field_id.class_.get_name() != name {
info!(
"Annotation for field {} found in class {}, dropping it",
field_id.__str__(),
name.__str__(),
);
}
let mut found = false;
for field in &mut instance_fields {
if field.descriptor == field_id {
field.annotations.append(&mut (annotations.clone())); // the clone is prob
// unnecessary
found = true;
}
}
for field in &mut static_fields {
if field.descriptor == field_id {
field.annotations.append(&mut (annotations.clone())); // the clone is prob
// unnecessary
found = true;
}
}
if !found {
info!(
"Annotation found for field {} but could not find the field definition, dropping it",
field_id.__str__(),
);
}
}
for method_annotation in annotations_directory.method_annotations {
let method_id =
Self::get_id_method_from_idx(method_annotation.method_idx as usize, dex)?;
let annotations = if method_annotation.annotations_off != 0 {
Self::get_annotation_items_from_annotation_set_off(
method_annotation.annotations_off,
dex,
)?
} else {
vec![]
};
if method_id.class_.get_name() != name {
info!(
"Annotation for method {} found in class {}, dropping it",
method_id.__str__(),
name.__str__(),
);
}
let mut found = false;
for method in &mut direct_methods {
if method.descriptor == method_id {
method.annotations.append(&mut (annotations.clone())); // the clone is prob
// unnecessary
found = true;
}
}
for method in &mut virtual_methods {
if method.descriptor == method_id {
method.annotations.append(&mut (annotations.clone())); // the clone is prob
// unnecessary
found = true;
}
}
if !found {
info!(
"Annotation found for method {} but could not find the method definition, dropping it",
method_id.__str__(),
);
}
}
for parameter_annotation in annotations_directory.parameter_annotations {
let method_id =
Self::get_id_method_from_idx(parameter_annotation.method_idx as usize, dex)?;
let annotation_set_ref_list = dex.get_struct_at_offset::<AnnotationSetRefList>(
parameter_annotation.annotations_off,
)?;
let mut annotations_list = vec![];
for annotation_set in annotation_set_ref_list.list {
if annotation_set.annotations_off != 0 {
annotations_list.push(Self::get_annotation_items_from_annotation_set_off(
annotation_set.annotations_off,
dex,
)?);
} else {
annotations_list.push(vec![]);
}
}
if method_id.class_.get_name() != name {
info!(
"Annotation for parameter of method {} found in class {}, dropping it",
method_id.__str__(),
name.__str__(),
);
}
let mut found = false;
for method in &mut direct_methods {
if method.descriptor == method_id {
method.parameters_annotations = annotations_list.clone(); // the clone is prob
// unnecessary
found = true;
}
}
for method in &mut virtual_methods {
if method.descriptor == method_id {
method.parameters_annotations = annotations_list.clone(); // the clone is prob
// unnecessary
found = true;
}
}
if !found {
info!(
"Annotation found for parameter of method {} but could not find the method definition, dropping it",
method_id.__str__(),
);
}
}
}
Ok(Class { Ok(Class {
name, name,
superclass, superclass,
@ -427,6 +555,7 @@ impl Apk {
is_synthetic, is_synthetic,
is_enum, is_enum,
value: None, value: None,
annotations: vec![],
}) })
} }
@ -546,6 +675,8 @@ impl Apk {
is_synthetic, is_synthetic,
is_constructor, is_constructor,
is_declared_syncrhonized, is_declared_syncrhonized,
annotations: vec![],
parameters_annotations: vec![],
code: (), code: (),
}) })
} }

View file

@ -2,7 +2,7 @@
use pyo3::prelude::*; use pyo3::prelude::*;
use crate::{DexValue, IdField}; use crate::{DexAnnotationItem, DexValue, IdField};
/// Represent a field. /// Represent a field.
#[pyclass] #[pyclass]
@ -34,6 +34,9 @@ pub struct Field {
pub is_enum: bool, pub is_enum: bool,
/// The default value of this field /// The default value of this field
pub value: Option<DexValue>, pub value: Option<DexValue>,
/// The annotations for this field
#[pyo3(get, set)]
pub annotations: Vec<DexAnnotationItem>,
} }
/// Represent the visibility of a field /// Represent the visibility of a field
@ -60,6 +63,7 @@ impl Field {
is_synthetic: false, is_synthetic: false,
is_enum: false, is_enum: false,
value: None, value: None,
annotations: vec![],
} }
} }

View file

@ -2,7 +2,7 @@
use pyo3::prelude::*; use pyo3::prelude::*;
use crate::IdMethod; use crate::{DexAnnotationItem, IdMethod};
/// Represent a method. /// Represent a method.
#[pyclass] #[pyclass]
@ -49,6 +49,12 @@ pub struct Method {
/// If the method is declared as synchronize (just indicatif) /// If the method is declared as synchronize (just indicatif)
#[pyo3(get, set)] #[pyo3(get, set)]
pub is_declared_syncrhonized: bool, pub is_declared_syncrhonized: bool,
/// The annotations for this method
#[pyo3(get, set)]
pub annotations: Vec<DexAnnotationItem>,
/// The annotations for the parameters of this method method
#[pyo3(get, set)]
pub parameters_annotations: Vec<Vec<DexAnnotationItem>>,
/// The code of the method /// The code of the method
pub code: (), pub code: (),
@ -82,6 +88,8 @@ impl Method {
is_synthetic: false, is_synthetic: false,
is_constructor: false, is_constructor: false,
is_declared_syncrhonized: false, is_declared_syncrhonized: false,
annotations: vec![],
parameters_annotations: vec![],
code: (), code: (),
} }
} }

View file

@ -21,7 +21,7 @@ pub struct AnnotationDirectoryItem {
pub field_annotations: Vec<FieldAnnotation>, pub field_annotations: Vec<FieldAnnotation>,
/// List of method annotation. The method annotations must be sorted by /// List of method annotation. The method annotations must be sorted by
/// increasing order of [`crate::MethodAnnotation.method_idx`]. /// increasing order of [`crate::MethodAnnotation.method_idx`].
pub method_annotation: Vec<MethodAnnotation>, pub method_annotations: Vec<MethodAnnotation>,
/// List of associated method parameter annotation. The parameter annotations /// List of associated method parameter annotation. The parameter annotations
/// must be sorted by increasing order of [`crate::ParameterAnnotation.parameter_size`]. /// must be sorted by increasing order of [`crate::ParameterAnnotation.parameter_size`].
pub parameter_annotations: Vec<ParameterAnnotation>, pub parameter_annotations: Vec<ParameterAnnotation>,
@ -32,7 +32,7 @@ impl AnnotationDirectoryItem {
self.field_annotations.len() as u32 self.field_annotations.len() as u32
} }
pub fn annotated_methods_size_field(&self) -> u32 { pub fn annotated_methods_size_field(&self) -> u32 {
self.method_annotation.len() as u32 self.method_annotations.len() as u32
} }
pub fn parameter_annotations_field(&self) -> u32 { pub fn parameter_annotations_field(&self) -> u32 {
self.parameter_annotations.len() as u32 self.parameter_annotations.len() as u32
@ -49,7 +49,7 @@ impl Serializable for AnnotationDirectoryItem {
for item in &self.field_annotations { for item in &self.field_annotations {
item.serialize(output)?; item.serialize(output)?;
} }
for item in &self.method_annotation { for item in &self.method_annotations {
item.serialize(output)?; item.serialize(output)?;
} }
for item in &self.parameter_annotations { for item in &self.parameter_annotations {
@ -66,9 +66,9 @@ impl Serializable for AnnotationDirectoryItem {
for _ in 0..fields_size { for _ in 0..fields_size {
field_annotations.push(FieldAnnotation::deserialize(input)?); field_annotations.push(FieldAnnotation::deserialize(input)?);
} }
let mut method_annotation = vec![]; let mut method_annotations = vec![];
for _ in 0..annotated_methods_size { for _ in 0..annotated_methods_size {
method_annotation.push(MethodAnnotation::deserialize(input)?); method_annotations.push(MethodAnnotation::deserialize(input)?);
} }
let mut parameter_annotations = vec![]; let mut parameter_annotations = vec![];
for _ in 0..annotated_parameters_size { for _ in 0..annotated_parameters_size {
@ -78,7 +78,7 @@ impl Serializable for AnnotationDirectoryItem {
Ok(Self { Ok(Self {
class_annotations_off, class_annotations_off,
field_annotations, field_annotations,
method_annotation, method_annotations,
parameter_annotations, parameter_annotations,
}) })
} }
@ -93,7 +93,7 @@ impl Serializable for AnnotationDirectoryItem {
.map(|val| val.size()) .map(|val| val.size())
.sum::<usize>() .sum::<usize>()
+ self + self
.method_annotation .method_annotations
.iter() .iter()
.map(|val| val.size()) .map(|val| val.size())
.sum::<usize>() .sum::<usize>()
@ -108,25 +108,28 @@ impl Serializable for AnnotationDirectoryItem {
/// <https://source.android.com/docs/core/runtime/dex-format#field-annotation> /// <https://source.android.com/docs/core/runtime/dex-format#field-annotation>
#[derive(Serializable, Debug, Clone, PartialEq, Eq)] #[derive(Serializable, Debug, Clone, PartialEq, Eq)]
pub struct FieldAnnotation { pub struct FieldAnnotation {
/// Index of the field annotated in `field_ids`
pub field_idx: u32, pub field_idx: u32,
/// Offset to a [`AnnotationSetItem`] /// Offset to a [`AnnotationSetItem`]
pub annotation_off: u32, pub annotations_off: u32,
} }
/// <https://source.android.com/docs/core/runtime/dex-format#method-annotation> /// <https://source.android.com/docs/core/runtime/dex-format#method-annotation>
#[derive(Serializable, Debug, Clone, PartialEq, Eq)] #[derive(Serializable, Debug, Clone, PartialEq, Eq)]
pub struct MethodAnnotation { pub struct MethodAnnotation {
/// Index of the method annotated in `method_ids`
pub method_idx: u32, pub method_idx: u32,
/// Offset to a [`AnnotationSetItem`] /// Offset to a [`AnnotationSetItem`]
pub annotation_off: u32, pub annotations_off: u32,
} }
/// <https://source.android.com/docs/core/runtime/dex-format#parameter-annotation> /// <https://source.android.com/docs/core/runtime/dex-format#parameter-annotation>
#[derive(Serializable, Debug, Clone, PartialEq, Eq)] #[derive(Serializable, Debug, Clone, PartialEq, Eq)]
pub struct ParameterAnnotation { pub struct ParameterAnnotation {
pub field_idx: u32, /// Index of the method whose parameters are annotated in `method_ids`
pub method_idx: u32,
/// Offset of a [`AnnotationSetRefList`] /// Offset of a [`AnnotationSetRefList`]
pub annotation_off: u32, pub annotations_off: u32,
} }
/// <https://source.android.com/docs/core/runtime/dex-format#set-ref-list> /// <https://source.android.com/docs/core/runtime/dex-format#set-ref-list>