WIP
This commit is contained in:
parent
aad1fc862d
commit
483ac8637c
7 changed files with 320 additions and 5 deletions
|
|
@ -111,6 +111,20 @@ impl DexAnnotationItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: Visitor> Visitable<V> for DexAnnotationItem {
|
||||||
|
fn default_visit(&self, v: &mut V) -> Result<()> {
|
||||||
|
v.visit_annotation(&self.annotation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<V: VisitorMut> VisitableMut<V> for DexAnnotationItem {
|
||||||
|
fn default_visit_mut(self, v: &mut V) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
annotation: v.visit_annotation(self.annotation)?,
|
||||||
|
..self
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An annotation.
|
/// An annotation.
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use pyo3::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
DexAnnotationItem, DexString, Field, IdField, IdMethod, IdMethodType, IdType, Method,
|
DexAnnotationItem, DexString, Field, IdField, IdMethod, IdMethodType, IdType, Method,
|
||||||
MethodHandle, Result,
|
MethodHandle, Result, Visitable, VisitableMut, Visitor, VisitorMut,
|
||||||
};
|
};
|
||||||
use androscalpel_serializer::consts::*;
|
use androscalpel_serializer::consts::*;
|
||||||
|
|
||||||
|
|
@ -387,3 +387,92 @@ impl Class {
|
||||||
self == other
|
self == other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: Visitor> Visitable<V> for Class {
|
||||||
|
fn default_visit(&self, v: &mut V) -> Result<()> {
|
||||||
|
v.visit_type(&self.descriptor)?;
|
||||||
|
if let Some(superclass) = &self.superclass {
|
||||||
|
v.visit_type(&superclass)?;
|
||||||
|
}
|
||||||
|
for interface in &self.interfaces {
|
||||||
|
v.visit_type(&interface)?;
|
||||||
|
}
|
||||||
|
if let Some(source_file) = &self.source_file {
|
||||||
|
v.visit_string(&source_file)?;
|
||||||
|
}
|
||||||
|
for (id, field) in &self.static_fields {
|
||||||
|
v.visit_field_id(&id)?;
|
||||||
|
v.visit_field(&field)?;
|
||||||
|
}
|
||||||
|
for (id, field) in &self.instance_fields {
|
||||||
|
v.visit_field_id(&id)?;
|
||||||
|
v.visit_field(&field)?;
|
||||||
|
}
|
||||||
|
for (id, meth) in &self.direct_methods {
|
||||||
|
v.visit_method_id(&id)?;
|
||||||
|
v.visit_method(&meth)?;
|
||||||
|
}
|
||||||
|
for (id, meth) in &self.virtual_methods {
|
||||||
|
v.visit_method_id(&id)?;
|
||||||
|
v.visit_method(&meth)?;
|
||||||
|
}
|
||||||
|
for annot in &self.annotations {
|
||||||
|
v.visit_annotation_item(&annot)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<V: VisitorMut> VisitableMut<V> for Class {
|
||||||
|
fn default_visit_mut(self, v: &mut V) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
descriptor: v.visit_type(self.descriptor)?,
|
||||||
|
superclass: self
|
||||||
|
.superclass
|
||||||
|
.map(|superclass| v.visit_type(superclass))
|
||||||
|
.transpose()?,
|
||||||
|
interfaces: self
|
||||||
|
.interfaces
|
||||||
|
.into_iter()
|
||||||
|
.map(|interface| v.visit_type(interface))
|
||||||
|
.collect::<Result<_>>()?,
|
||||||
|
source_file: self
|
||||||
|
.source_file
|
||||||
|
.map(|source_file| v.visit_string(source_file))
|
||||||
|
.transpose()?,
|
||||||
|
static_fields: {
|
||||||
|
let mut static_fields = HashMap::new();
|
||||||
|
for (id, field) in self.static_fields.into_iter() {
|
||||||
|
static_fields.insert(v.visit_field_id(id)?, v.visit_field(field)?);
|
||||||
|
}
|
||||||
|
static_fields
|
||||||
|
},
|
||||||
|
instance_fields: {
|
||||||
|
let mut instance_fields = HashMap::new();
|
||||||
|
for (id, field) in self.instance_fields.into_iter() {
|
||||||
|
instance_fields.insert(v.visit_field_id(id)?, v.visit_field(field)?);
|
||||||
|
}
|
||||||
|
instance_fields
|
||||||
|
},
|
||||||
|
direct_methods: {
|
||||||
|
let mut direct_methods = HashMap::new();
|
||||||
|
for (id, meth) in self.direct_methods.into_iter() {
|
||||||
|
direct_methods.insert(v.visit_method_id(id)?, v.visit_method(meth)?);
|
||||||
|
}
|
||||||
|
direct_methods
|
||||||
|
},
|
||||||
|
virtual_methods: {
|
||||||
|
let mut virtual_methods = HashMap::new();
|
||||||
|
for (id, meth) in self.virtual_methods.into_iter() {
|
||||||
|
virtual_methods.insert(v.visit_method_id(id)?, v.visit_method(meth)?);
|
||||||
|
}
|
||||||
|
virtual_methods
|
||||||
|
},
|
||||||
|
annotations: self
|
||||||
|
.annotations
|
||||||
|
.into_iter()
|
||||||
|
.map(|annotation| v.visit_annotation_item(annotation))
|
||||||
|
.collect::<Result<_>>()?,
|
||||||
|
..self
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use pyo3::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ins::Instruction, DexString, IdField, IdMethod, IdMethodType, IdType, MethodHandle, Result,
|
ins::Instruction, DexString, IdField, IdMethod, IdMethodType, IdType, MethodHandle, Result,
|
||||||
|
Visitable, VisitableMut, Visitor, VisitorMut,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: make this easy to edit/manipulate, maybe move to Method
|
// TODO: make this easy to edit/manipulate, maybe move to Method
|
||||||
|
|
@ -493,3 +494,38 @@ impl Code {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: Visitor> Visitable<V> for Code {
|
||||||
|
fn default_visit(&self, v: &mut V) -> Result<()> {
|
||||||
|
for ins in &self.insns {
|
||||||
|
v.visit_instruction(&ins)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<V: VisitorMut> VisitableMut<V> for Code {
|
||||||
|
fn default_visit_mut(self, v: &mut V) -> Result<Self> {
|
||||||
|
let parameter_names = if let Some(parameter_names) = self.parameter_names {
|
||||||
|
let mut new_param = vec![];
|
||||||
|
for param in parameter_names {
|
||||||
|
if let Some(param) = param {
|
||||||
|
new_param.push(Some(v.visit_string(param)?));
|
||||||
|
} else {
|
||||||
|
new_param.push(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(new_param)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
Ok(Self {
|
||||||
|
parameter_names,
|
||||||
|
insns: self
|
||||||
|
.insns
|
||||||
|
.into_iter()
|
||||||
|
.map(|ins| v.visit_instruction(ins))
|
||||||
|
.collect::<Result<_>>()?,
|
||||||
|
..self
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use pyo3::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
DexAnnotationItem, DexString, DexValue, HiddenApiData, IdField, IdMethod, IdMethodType, IdType,
|
DexAnnotationItem, DexString, DexValue, HiddenApiData, IdField, IdMethod, IdMethodType, IdType,
|
||||||
MethodHandle, Result,
|
MethodHandle, Result, Visitable, VisitableMut, Visitor, VisitorMut,
|
||||||
};
|
};
|
||||||
use androscalpel_serializer::consts::*;
|
use androscalpel_serializer::consts::*;
|
||||||
|
|
||||||
|
|
@ -257,3 +257,40 @@ impl Field {
|
||||||
self == other
|
self == other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: Visitor> Visitable<V> for Field {
|
||||||
|
fn default_visit(&self, v: &mut V) -> Result<()> {
|
||||||
|
v.visit_field_id(&self.descriptor)?;
|
||||||
|
v.visit_field_visibility(&self.visibility)?;
|
||||||
|
if let Some(val) = &self.value {
|
||||||
|
v.visit_value(&val)?;
|
||||||
|
}
|
||||||
|
for annot in &self.annotations {
|
||||||
|
v.visit_annotation_item(&annot)?;
|
||||||
|
}
|
||||||
|
if let Some(hiddenapi) = &self.hiddenapi {
|
||||||
|
v.visit_hidden_api_data(&hiddenapi)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<V: VisitorMut> VisitableMut<V> for Field {
|
||||||
|
fn default_visit_mut(self, v: &mut V) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
descriptor: v.visit_field_id(self.descriptor)?,
|
||||||
|
visibility: v.visit_field_visibility(self.visibility)?,
|
||||||
|
value: self.value.map(|val| v.visit_value(val)).transpose()?,
|
||||||
|
annotations: self
|
||||||
|
.annotations
|
||||||
|
.into_iter()
|
||||||
|
.map(|annot| v.visit_annotation_item(annot))
|
||||||
|
.collect::<Result<_>>()?,
|
||||||
|
hiddenapi: self
|
||||||
|
.hiddenapi
|
||||||
|
.map(|hiddenapi| v.visit_hidden_api_data(hiddenapi))
|
||||||
|
.transpose()?,
|
||||||
|
..self
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
//! Representation of the hidden API data
|
//! Representation of the hidden API data
|
||||||
|
|
||||||
|
use crate::{Result, Visitable, VisitableMut, Visitor, VisitorMut};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
@ -39,6 +40,22 @@ impl From<HiddenApiData> for androscalpel_serializer::HiddenApiFlags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: Visitor> Visitable<V> for HiddenApiData {
|
||||||
|
fn default_visit(&self, v: &mut V) -> Result<()> {
|
||||||
|
v.visit_hidden_api_permission(&self.permission)?;
|
||||||
|
v.visit_hidden_api_domain(&self.domain)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<V: VisitorMut> VisitableMut<V> for HiddenApiData {
|
||||||
|
fn default_visit_mut(self, v: &mut V) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
permission: v.visit_hidden_api_permission(self.permission)?,
|
||||||
|
domain: v.visit_hidden_api_domain(self.domain)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize, Serialize)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize, Serialize)]
|
||||||
pub enum HiddenApiPermission {
|
pub enum HiddenApiPermission {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use pyo3::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Code, DexAnnotationItem, DexString, HiddenApiData, IdField, IdMethod, IdMethodType, IdType,
|
Code, DexAnnotationItem, DexString, HiddenApiData, IdField, IdMethod, IdMethodType, IdType,
|
||||||
MethodHandle, Result,
|
MethodHandle, Result, Visitable, VisitableMut, Visitor, VisitorMut,
|
||||||
};
|
};
|
||||||
use androscalpel_serializer::consts::*;
|
use androscalpel_serializer::consts::*;
|
||||||
|
|
||||||
|
|
@ -298,3 +298,54 @@ impl Method {
|
||||||
self == other
|
self == other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: Visitor> Visitable<V> for Method {
|
||||||
|
fn default_visit(&self, v: &mut V) -> Result<()> {
|
||||||
|
v.visit_method_id(&self.descriptor)?;
|
||||||
|
v.visit_method_visibility(&self.visibility)?;
|
||||||
|
for annot in &self.annotations {
|
||||||
|
v.visit_annotation_item(&annot)?;
|
||||||
|
}
|
||||||
|
for parameter_annotations in &self.parameters_annotations {
|
||||||
|
for annot in parameter_annotations {
|
||||||
|
v.visit_annotation_item(&annot)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(hiddenapi) = &self.hiddenapi {
|
||||||
|
v.visit_hidden_api_data(&hiddenapi)?;
|
||||||
|
}
|
||||||
|
if let Some(code) = &self.code {
|
||||||
|
v.visit_code(&code)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<V: VisitorMut> VisitableMut<V> for Method {
|
||||||
|
fn default_visit_mut(self, v: &mut V) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
descriptor: v.visit_method_id(self.descriptor)?,
|
||||||
|
visibility: v.visit_method_visibility(self.visibility)?,
|
||||||
|
annotations: self
|
||||||
|
.annotations
|
||||||
|
.into_iter()
|
||||||
|
.map(|annot| v.visit_annotation_item(annot))
|
||||||
|
.collect::<Result<_>>()?,
|
||||||
|
parameters_annotations: self
|
||||||
|
.parameters_annotations
|
||||||
|
.into_iter()
|
||||||
|
.map(|parameter_annotations| {
|
||||||
|
parameter_annotations
|
||||||
|
.into_iter()
|
||||||
|
.map(|annot| v.visit_annotation_item(annot))
|
||||||
|
.collect::<Result<_>>()
|
||||||
|
})
|
||||||
|
.collect::<Result<_>>()?,
|
||||||
|
hiddenapi: self
|
||||||
|
.hiddenapi
|
||||||
|
.map(|hiddenapi| v.visit_hidden_api_data(hiddenapi))
|
||||||
|
.transpose()?,
|
||||||
|
code: self.code.map(|code| v.visit_code(code)).transpose()?,
|
||||||
|
..self
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
//! The visitor trait and common implementations.
|
//! The visitor trait and common implementations.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ins::Instruction, scalar::*, CallSite, DexAnnotation, DexString, DexValue, IdEnum, IdField,
|
ins::Instruction, scalar::*, CallSite, Class, Code, DexAnnotation, DexAnnotationItem,
|
||||||
IdMethod, IdMethodType, IdType, MethodHandle, Result,
|
DexString, DexValue, Field, FieldVisibility, HiddenApiData, HiddenApiDomain,
|
||||||
|
HiddenApiPermission, IdEnum, IdField, IdMethod, IdMethodType, IdType, Method, MethodHandle,
|
||||||
|
MethodVisibility, Result,
|
||||||
};
|
};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
|
@ -70,6 +72,36 @@ pub trait Visitor: Sized {
|
||||||
fn visit_bool(&mut self, _: &DexBoolean) -> Result<()> {
|
fn visit_bool(&mut self, _: &DexBoolean) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
fn visit_class(&mut self, class: &Class) -> Result<()> {
|
||||||
|
class.default_visit(self)
|
||||||
|
}
|
||||||
|
fn visit_field(&mut self, field: &Field) -> Result<()> {
|
||||||
|
field.default_visit(self)
|
||||||
|
}
|
||||||
|
fn visit_method(&mut self, method: &Method) -> Result<()> {
|
||||||
|
method.default_visit(self)
|
||||||
|
}
|
||||||
|
fn visit_annotation_item(&mut self, annotation: &DexAnnotationItem) -> Result<()> {
|
||||||
|
annotation.default_visit(self)
|
||||||
|
}
|
||||||
|
fn visit_field_visibility(&mut self, _: &FieldVisibility) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn visit_method_visibility(&mut self, _: &MethodVisibility) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn visit_hidden_api_data(&mut self, hidden_api: &HiddenApiData) -> Result<()> {
|
||||||
|
hidden_api.default_visit(self)
|
||||||
|
}
|
||||||
|
fn visit_hidden_api_permission(&mut self, _: &HiddenApiPermission) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn visit_hidden_api_domain(&mut self, _: &HiddenApiDomain) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn visit_code(&mut self, code: &Code) -> Result<()> {
|
||||||
|
code.default_visit(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait VisitorMut: Sized {
|
pub trait VisitorMut: Sized {
|
||||||
|
|
@ -136,6 +168,45 @@ pub trait VisitorMut: Sized {
|
||||||
fn visit_bool(&mut self, val: DexBoolean) -> Result<DexBoolean> {
|
fn visit_bool(&mut self, val: DexBoolean) -> Result<DexBoolean> {
|
||||||
Ok(val)
|
Ok(val)
|
||||||
}
|
}
|
||||||
|
fn visit_class(&mut self, class: Class) -> Result<Class> {
|
||||||
|
class.default_visit_mut(self)
|
||||||
|
}
|
||||||
|
fn visit_field(&mut self, field: Field) -> Result<Field> {
|
||||||
|
field.default_visit_mut(self)
|
||||||
|
}
|
||||||
|
fn visit_method(&mut self, method: Method) -> Result<Method> {
|
||||||
|
method.default_visit_mut(self)
|
||||||
|
}
|
||||||
|
fn visit_annotation_item(
|
||||||
|
&mut self,
|
||||||
|
annotation: DexAnnotationItem,
|
||||||
|
) -> Result<DexAnnotationItem> {
|
||||||
|
annotation.default_visit_mut(self)
|
||||||
|
}
|
||||||
|
fn visit_field_visibility(&mut self, visibility: FieldVisibility) -> Result<FieldVisibility> {
|
||||||
|
Ok(visibility)
|
||||||
|
}
|
||||||
|
fn visit_method_visibility(
|
||||||
|
&mut self,
|
||||||
|
visibility: MethodVisibility,
|
||||||
|
) -> Result<MethodVisibility> {
|
||||||
|
Ok(visibility)
|
||||||
|
}
|
||||||
|
fn visit_hidden_api_data(&mut self, hidden_api: HiddenApiData) -> Result<HiddenApiData> {
|
||||||
|
hidden_api.default_visit_mut(self)
|
||||||
|
}
|
||||||
|
fn visit_hidden_api_permission(
|
||||||
|
&mut self,
|
||||||
|
perm: HiddenApiPermission,
|
||||||
|
) -> Result<HiddenApiPermission> {
|
||||||
|
Ok(perm)
|
||||||
|
}
|
||||||
|
fn visit_hidden_api_domain(&mut self, domain: HiddenApiDomain) -> Result<HiddenApiDomain> {
|
||||||
|
Ok(domain)
|
||||||
|
}
|
||||||
|
fn visit_code(&mut self, code: Code) -> Result<Code> {
|
||||||
|
code.default_visit_mut(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for structures that can be visited.
|
/// Trait for structures that can be visited.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue