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)?)
};
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 {
annotations = Self::get_annotation_items_from_annotation_set_off(
annotations_directory.class_annotations_off,
@ -137,6 +137,134 @@ impl Apk {
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 {
name,
superclass,
@ -427,6 +555,7 @@ impl Apk {
is_synthetic,
is_enum,
value: None,
annotations: vec![],
})
}
@ -546,6 +675,8 @@ impl Apk {
is_synthetic,
is_constructor,
is_declared_syncrhonized,
annotations: vec![],
parameters_annotations: vec![],
code: (),
})
}

View file

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

View file

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

View file

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