diff --git a/androscalpel/src/annotation.rs b/androscalpel/src/annotation.rs index 12a0c66..d3cb821 100644 --- a/androscalpel/src/annotation.rs +++ b/androscalpel/src/annotation.rs @@ -3,7 +3,9 @@ use std::collections::{HashMap, HashSet}; use pyo3::prelude::*; -use crate::{dex_id::IdType, value::DexValue, DexString, IdField, IdMethod, IdMethodType}; +use crate::{ + dex_id::IdType, value::DexValue, DexString, IdField, IdMethod, IdMethodType, MethodHandle, +}; /// Annotation with a visibility #[pyclass] @@ -86,6 +88,11 @@ impl DexAnnotationItem { pub fn get_all_method_ids(&self) -> HashSet { self.annotation.get_all_method_ids() } + + /// Return all method handles referenced in the annotation. + pub fn get_all_method_handles(&self) -> HashSet { + self.annotation.get_all_method_handles() + } } /// An annotation. @@ -170,4 +177,13 @@ impl DexAnnotation { } methods } + + /// Return all method handles referenced in the annotation. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + for value in self.elements.values() { + methods.extend(value.get_all_method_handles()); + } + methods + } } diff --git a/androscalpel/src/class.rs b/androscalpel/src/class.rs index a2ed1c5..dc9bec4 100644 --- a/androscalpel/src/class.rs +++ b/androscalpel/src/class.rs @@ -5,8 +5,10 @@ use std::collections::{HashMap, HashSet}; use pyo3::prelude::*; use crate::{ - DexAnnotationItem, DexString, Field, IdField, IdMethod, IdMethodType, IdType, Method, Result, + DexAnnotationItem, DexString, Field, IdField, IdMethod, IdMethodType, IdType, Method, + MethodHandle, Result, }; +use androscalpel_serializer::consts::*; /// Represent an apk #[pyclass] @@ -242,7 +244,7 @@ impl Class { fields } - /// Return all methods id referenced in the class. + /// Return all method ids referenced in the class. /// This **not** the concatenation of the direct and virtual method attributs: /// this also contains reference to method in other classes used by methods/values /// in this class. @@ -267,4 +269,60 @@ impl Class { } methods } + + /// Return all method handles referenced in the class. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + for field in self.static_fields.values() { + methods.extend(field.get_all_method_handles()); + } + for field in self.instance_fields.values() { + methods.extend(field.get_all_method_handles()); + } + for method in self.direct_methods.values() { + methods.extend(method.get_all_method_handles()); + } + for method in self.virtual_methods.values() { + methods.extend(method.get_all_method_handles()); + } + for annot in &self.annotations { + methods.extend(annot.get_all_method_handles()); + } + methods + } + + /// If a data section is needed for this class. + pub fn has_data_section(&self) -> bool { + !self.static_fields.is_empty() + || !self.instance_fields.is_empty() + || !self.direct_methods.is_empty() + || !self.virtual_methods.is_empty() + } + + /// Return the binary representation of access flags. + pub fn get_raw_access_flags(&self) -> u32 { + let mut flags = 0u32; + if self.is_public { + flags |= ACC_PUBLIC; + } + if self.is_final { + flags |= ACC_FINAL; + } + if self.is_interface { + flags |= ACC_INTERFACE; + } + if self.is_abstract { + flags |= ACC_ABSTRACT; + } + if self.is_synthetic { + flags |= ACC_SYNTHETIC; + } + if self.is_annotation { + flags |= ACC_ANNOTATION; + } + if self.is_enum { + flags |= ACC_ENUM; + } + flags + } } diff --git a/androscalpel/src/code.rs b/androscalpel/src/code.rs index 82c2a71..3012944 100644 --- a/androscalpel/src/code.rs +++ b/androscalpel/src/code.rs @@ -4,7 +4,7 @@ use std::collections::HashSet; use pyo3::prelude::*; -use crate::{DexString, IdField, IdMethod, IdMethodType, IdType}; +use crate::{DexString, IdField, IdMethod, IdMethodType, IdType, MethodHandle}; // TODO: make this easy to edit/manipulate, maybe move to Method @@ -102,4 +102,10 @@ impl Code { // TODO HashSet::new() } + + /// Return all method handles referenced in the codes. + pub fn get_all_method_handles(&self) -> HashSet { + // TODO + HashSet::new() + } } diff --git a/androscalpel/src/dex_writer.rs b/androscalpel/src/dex_writer.rs index e3bd407..287995b 100644 --- a/androscalpel/src/dex_writer.rs +++ b/androscalpel/src/dex_writer.rs @@ -39,7 +39,7 @@ pub struct DexWriter { /// index in the `class_defs` section. class_defs: HashMap, // call_site_ids: // TODO: parsing code insns - // method_handles: + // method_handles are not deduplicated nor ordered, so they must be serialized on the fly. // TODO: other structs in data: // **map_list**, prbl generate on write // values @@ -285,8 +285,9 @@ impl DexWriter { method_ids_list_aux }; - debug!("Sort classes and generate the class_defs section"); + debug!("Sort classes and generate the class_defs and class_data section"); let mut class_defs_list = vec![]; + let mut class_data_list = vec![]; for (idx, class_id) in self.get_sorted_class_def()?.into_iter().enumerate() { self.class_defs .entry(class_id.clone()) @@ -298,17 +299,7 @@ impl DexWriter { class.descriptor.__repr__(), class.__repr__() ))? as u32, - access_flags: if class.is_public { ACC_PUBLIC } else { 0 } - | if class.is_final { ACC_FINAL } else { 0 } - | if class.is_interface { ACC_INTERFACE } else { 0 } - | if class.is_abstract { ACC_ABSTRACT } else { 0 } - | if class.is_synthetic { ACC_SYNTHETIC } else { 0 } - | if class.is_annotation { - ACC_ANNOTATION - } else { - 0 - } - | if class.is_enum { ACC_ENUM } else { 0 }, + access_flags: class.get_raw_access_flags(), superclass_idx: if let Some(sup) = &class.superclass { *self.type_ids.get(sup).ok_or(anyhow!( "Type {} (superclass of class {}) not found in dex builder", @@ -318,7 +309,7 @@ impl DexWriter { } else { NO_INDEX.0 }, - interfaces_off: 0, // TODO + interfaces_off: 0, source_file_idx: if let Some(file) = &class.source_file { *self.strings.get(file).ok_or(anyhow!( "String {} (source file of class {}) not found in dex builder", @@ -328,13 +319,122 @@ impl DexWriter { } else { NO_INDEX.0 }, - annotations_off: 0, // TODO - class_data_off: 0, // TODO + annotations_off: 0, // TODO + class_data_off: { + // need relinking once offset of class_data section is known + if class.has_data_section() { + let mut data = ClassDataItem::default(); + + let mut static_fields: Vec = + class.static_fields.keys().cloned().collect(); + static_fields.sort(); + let mut last_field_id = 0; + for id in &static_fields { + let idx = self.field_ids.get(id).ok_or(anyhow!( + "Field {} (field of class {}) not found in dex builder", + id.__repr__(), + class.__repr__() + ))?; + let field_idx_diff = Uleb128((idx - last_field_id) as u32); + last_field_id = *idx; + let access_flags = Uleb128( + class.static_fields.get(id).unwrap().get_raw_access_flags(), + ); + data.static_fields.push(EncodedField { + field_idx_diff, + access_flags, + }); + } + + let mut instance_fields: Vec = + class.instance_fields.keys().cloned().collect(); + instance_fields.sort(); + let mut last_field_id = 0; + for id in &instance_fields { + let idx = self.field_ids.get(id).ok_or(anyhow!( + "Field {} (field of class {}) not found in dex builder", + id.__repr__(), + class.__repr__() + ))?; + let field_idx_diff = Uleb128((idx - last_field_id) as u32); + last_field_id = *idx; + let access_flags = Uleb128( + class + .instance_fields + .get(id) + .unwrap() + .get_raw_access_flags(), + ); + data.instance_fields.push(EncodedField { + field_idx_diff, + access_flags, + }); + } + + let mut direct_methods: Vec = + class.direct_methods.keys().cloned().collect(); + direct_methods.sort(); + let mut last_method_id = 0; + for id in &direct_methods { + let idx = self.method_ids.get(id).ok_or(anyhow!( + "Method {} (method of class {}) not found in dex builder", + id.__repr__(), + class.__repr__() + ))?; + let method_idx_diff = Uleb128((idx - last_method_id) as u32); + last_method_id = *idx; + let access_flags = Uleb128( + class.direct_methods.get(id).unwrap().get_raw_access_flags(), + ); + data.direct_methods.push(EncodedMethod { + method_idx_diff, + access_flags, + code_off: Uleb128(0), // TODO + }); + } + + let mut virtual_methods: Vec = + class.virtual_methods.keys().cloned().collect(); + virtual_methods.sort(); + let mut last_method_id = 0; + for id in &virtual_methods { + let idx = self.method_ids.get(id).ok_or(anyhow!( + "Method {} (method of class {}) not found in dex builder", + id.__repr__(), + class.__repr__() + ))?; + let method_idx_diff = Uleb128((idx - last_method_id) as u32); + last_method_id = *idx; + let access_flags = Uleb128( + class + .virtual_methods + .get(id) + .unwrap() + .get_raw_access_flags(), + ); + data.virtual_methods.push(EncodedMethod { + method_idx_diff, + access_flags, + code_off: Uleb128(0), // TODO + }); + } + + let class_data_off = section_manager.get_size(Section::ClassDataItem); + section_manager.add_elt(Section::ClassDataItem, Some(data.size())); + class_data_list.push(data); + class_data_off + } else { + 0 + } + }, static_values_off: 0, // TODO }); section_manager.add_elt(Section::ClassDefItem, None); } + // Method handles are not ordered, nor deduplicated, so they are generated on the fly + let mut _method_handles: Vec = vec![]; + debug!("Generate the type_list section"); let mut type_lists_index = HashMap::new(); for proto in self.proto_ids.keys() { @@ -443,6 +543,14 @@ impl DexWriter { } } + debug!("Link the class_data_item entries in class_def_items"); + for (class, idx) in self.class_defs.values() { + if class.has_data_section() { + class_defs_list[*idx].class_data_off += + section_manager.get_offset(Section::ClassDataItem); + } + } + debug!("Serialize the dex file"); // TODO: compute checksum, hash, ect self.header.serialize(writer)?; @@ -476,9 +584,11 @@ impl DexWriter { class_def.serialize(writer)?; } // TODO: CallSiteIdItem, - // TODO: MethodHandleItem, - // TODO: Data, - // MapList, + // MethodHandleItem section + for handle in _method_handles { + handle.serialize(writer)?; + } + // MapList map_list.serialize(writer)?; // TypeList, let mut offset = 0; @@ -492,7 +602,10 @@ impl DexWriter { } // TODO: AnnotationSetRefList, // TODO: AnnotationSetItem, - // TODO: ClassDataItem, + // ClassDataItem section + for data in class_data_list { + data.serialize(writer)?; + } // TODO: CodeItem, for string in string_ids_list { string.serialize(writer)?; diff --git a/androscalpel/src/field.rs b/androscalpel/src/field.rs index fdb94ea..f9fd04a 100644 --- a/androscalpel/src/field.rs +++ b/androscalpel/src/field.rs @@ -4,7 +4,10 @@ use std::collections::HashSet; use pyo3::prelude::*; -use crate::{DexAnnotationItem, DexString, DexValue, IdField, IdMethod, IdMethodType, IdType}; +use crate::{ + DexAnnotationItem, DexString, DexValue, IdField, IdMethod, IdMethodType, IdType, MethodHandle, +}; +use androscalpel_serializer::consts::*; /// Represent a field. #[pyclass] @@ -171,7 +174,7 @@ impl Field { fields } - /// Return all method ids referenced in the method. + /// Return all method ids referenced in the field. pub fn get_all_method_ids(&self) -> HashSet { let mut methods = HashSet::new(); if let Some(value) = &self.value { @@ -182,4 +185,51 @@ impl Field { } methods } + + /// Return all method handles referenced in the field. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + if let Some(value) = &self.value { + methods.extend(value.get_all_method_handles()); + } + for annot in &self.annotations { + methods.extend(annot.get_all_method_handles()); + } + methods + } + + /// Return the binary representation of access flags. + /// + /// # Note + /// + /// The return value is a u32, not the Uleb128 + /// encoded value found in the dex file. + pub fn get_raw_access_flags(&self) -> u32 { + let mut flags = 0; + match self.visibility { + FieldVisibility::Public => flags |= ACC_PUBLIC, + FieldVisibility::Private => flags |= ACC_PRIVATE, + FieldVisibility::Protected => flags |= ACC_PROTECTED, + FieldVisibility::None_ => (), + } + if self.is_static { + flags |= ACC_STATIC + } + if self.is_final { + flags |= ACC_FINAL + } + if self.is_volatile { + flags |= ACC_VOLATILE + } + if self.is_transient { + flags |= ACC_TRANSIENT + } + if self.is_synthetic { + flags |= ACC_SYNTHETIC + } + if self.is_enum { + flags |= ACC_ENUM + } + flags + } } diff --git a/androscalpel/src/method.rs b/androscalpel/src/method.rs index 4e8ed9f..e575f1a 100644 --- a/androscalpel/src/method.rs +++ b/androscalpel/src/method.rs @@ -4,7 +4,10 @@ use std::collections::HashSet; use pyo3::prelude::*; -use crate::{Code, DexAnnotationItem, DexString, IdField, IdMethod, IdMethodType, IdType}; +use crate::{ + Code, DexAnnotationItem, DexString, IdField, IdMethod, IdMethodType, IdType, MethodHandle, +}; +use androscalpel_serializer::consts::*; /// Represent a method. #[pyclass] @@ -196,4 +199,73 @@ impl Method { } methods } + + /// Return all method handles referenced in the method. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + + for annot in &self.annotations { + methods.extend(annot.get_all_method_handles()); + } + for param_annots in &self.parameters_annotations { + for annot in param_annots { + methods.extend(annot.get_all_method_handles()); + } + } + if let Some(code) = &self.code { + methods.extend(code.get_all_method_handles()); + } + methods + } + + /// Return the binary representation of access flags. + /// + /// # Note + /// + /// The return value is a u32, not the Uleb128 + /// encoded value found in the dex file. + pub fn get_raw_access_flags(&self) -> u32 { + let mut flags = 0; + match self.visibility { + MethodVisibility::Public => flags |= ACC_PUBLIC, + MethodVisibility::Private => flags |= ACC_PRIVATE, + MethodVisibility::Protected => flags |= ACC_PROTECTED, + MethodVisibility::None_ => (), + } + if self.is_static { + flags |= ACC_STATIC; + } + if self.is_final { + flags |= ACC_FINAL; + } + if self.is_synchronized { + flags |= ACC_SYNCHRONIZED; + } + if self.is_bridge { + flags |= ACC_BRIDGE; + } + if self.is_varargs { + flags |= ACC_VARARGS; + } + if self.is_native { + flags |= ACC_NATIVE; + } + if self.is_abstract { + flags |= ACC_ABSTRACT; + } + if self.is_strictfp { + flags |= ACC_STRICT; + } + if self.is_synthetic { + flags |= ACC_SYNTHETIC; + } + if self.is_constructor { + flags |= ACC_CONSTRUCTOR; + } + if self.is_declared_syncrhonized { + flags |= ACC_DECLARED_SYNCHRONIZED; + } + + flags + } } diff --git a/androscalpel/src/method_handle.rs b/androscalpel/src/method_handle.rs index 8143688..29563b0 100644 --- a/androscalpel/src/method_handle.rs +++ b/androscalpel/src/method_handle.rs @@ -1,6 +1,7 @@ //! The structure use to reference a method invocation. use std::collections::HashSet; +use std::hash::Hash; use pyo3::exceptions::PyTypeError; use pyo3::prelude::*; @@ -9,7 +10,7 @@ use crate::dex_id::*; use crate::DexString; /// The structure use to reference a method invocation. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum MethodHandle { StaticPut(StaticPut), StaticGet(StaticGet), @@ -23,7 +24,7 @@ pub enum MethodHandle { } #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct StaticPut(pub IdField); #[pymethods] @@ -71,9 +72,16 @@ impl StaticPut { pub fn get_all_method_ids(&self) -> HashSet { HashSet::new() } + + /// Return all method handles referenced in the handle. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + methods.insert(MethodHandle::StaticPut(self.clone())); + methods + } } #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct StaticGet(pub IdField); #[pymethods] @@ -121,9 +129,16 @@ impl StaticGet { pub fn get_all_method_ids(&self) -> HashSet { HashSet::new() } + + /// Return all method handles referenced in the handle. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + methods.insert(MethodHandle::StaticGet(self.clone())); + methods + } } #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct InstancePut(pub IdField); #[pymethods] @@ -171,9 +186,16 @@ impl InstancePut { pub fn get_all_method_ids(&self) -> HashSet { HashSet::new() } + + /// Return all method handles referenced in the handle. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + methods.insert(MethodHandle::InstancePut(self.clone())); + methods + } } #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct InstanceGet(pub IdField); #[pymethods] @@ -221,10 +243,17 @@ impl InstanceGet { pub fn get_all_method_ids(&self) -> HashSet { HashSet::new() } + + /// Return all method handles referenced in the handle. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + methods.insert(MethodHandle::InstanceGet(self.clone())); + methods + } } #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct InvokeStatic(pub IdMethod); #[pymethods] @@ -272,10 +301,17 @@ impl InvokeStatic { methods.insert(self.0.clone()); methods } + + /// Return all method handles referenced in the handle. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + methods.insert(MethodHandle::InvokeStatic(self.clone())); + methods + } } #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct InvokeInstance(pub IdMethod); #[pymethods] @@ -323,10 +359,17 @@ impl InvokeInstance { methods.insert(self.0.clone()); methods } + + /// Return all method handles referenced in the handle. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + methods.insert(MethodHandle::InvokeInstance(self.clone())); + methods + } } #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct InvokeConstructor(pub IdMethod); #[pymethods] @@ -374,10 +417,17 @@ impl InvokeConstructor { methods.insert(self.0.clone()); methods } + + /// Return all method handles referenced in the handle. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + methods.insert(MethodHandle::InvokeConstructor(self.clone())); + methods + } } #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct InvokeDirect(pub IdMethod); #[pymethods] @@ -425,10 +475,17 @@ impl InvokeDirect { methods.insert(self.0.clone()); methods } + + /// Return all method handles referenced in the handle. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + methods.insert(MethodHandle::InvokeDirect(self.clone())); + methods + } } #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct InvokeInterface(pub IdMethod); #[pymethods] @@ -476,6 +533,13 @@ impl InvokeInterface { methods.insert(self.0.clone()); methods } + + /// Return all method handles referenced in the handle. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + methods.insert(MethodHandle::InvokeInterface(self.clone())); + methods + } } impl<'source> FromPyObject<'source> for MethodHandle { @@ -613,4 +677,19 @@ impl MethodHandle { Self::InvokeInterface(val) => val.get_all_method_ids(), } } + + /// Return all method handles referenced in the handle. + pub fn get_all_method_handles(&self) -> HashSet { + match self { + Self::StaticPut(val) => val.get_all_method_handles(), + Self::StaticGet(val) => val.get_all_method_handles(), + Self::InstancePut(val) => val.get_all_method_handles(), + Self::InstanceGet(val) => val.get_all_method_handles(), + Self::InvokeStatic(val) => val.get_all_method_handles(), + Self::InvokeInstance(val) => val.get_all_method_handles(), + Self::InvokeConstructor(val) => val.get_all_method_handles(), + Self::InvokeDirect(val) => val.get_all_method_handles(), + Self::InvokeInterface(val) => val.get_all_method_handles(), + } + } } diff --git a/androscalpel/src/scalar.rs b/androscalpel/src/scalar.rs index 6c6c62c..e7dd4da 100644 --- a/androscalpel/src/scalar.rs +++ b/androscalpel/src/scalar.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; -use crate::{DexString, DexValue, IdField, IdMethod, IdMethodType, IdType}; +use crate::{DexString, DexValue, IdField, IdMethod, IdMethodType, IdType, MethodHandle}; use pyo3::prelude::*; #[pyclass] @@ -306,4 +306,13 @@ impl DexArray { } methods } + + /// Return all method handles referenced in the value. + pub fn get_all_method_handles(&self) -> HashSet { + let mut methods = HashSet::new(); + for val in &self.0 { + methods.extend(val.get_all_method_handles()); + } + methods + } } diff --git a/androscalpel/src/value.rs b/androscalpel/src/value.rs index 46c499c..c8fe998 100644 --- a/androscalpel/src/value.rs +++ b/androscalpel/src/value.rs @@ -101,6 +101,7 @@ impl DexValue { } } + // TODO: implement for each variant struct for python binding /// Return all strings referenced in the value. pub fn get_all_strings(&self) -> HashSet { match self { @@ -125,6 +126,7 @@ impl DexValue { } } + // TODO: implement for each variant struct for python binding /// Return all types referenced in the value. pub fn get_all_types(&self) -> HashSet { match self { @@ -149,6 +151,7 @@ impl DexValue { } } + // TODO: implement for each variant struct for python binding /// Return all prototypes referenced in the value. pub fn get_all_protos(&self) -> HashSet { match self { @@ -173,6 +176,7 @@ impl DexValue { } } + // TODO: implement for each variant struct for python binding /// Return all field ids referenced in the value. pub fn get_all_field_ids(&self) -> HashSet { match self { @@ -197,6 +201,7 @@ impl DexValue { } } + // TODO: implement for each variant struct for python binding /// Return all method ids referenced in the value. pub fn get_all_method_ids(&self) -> HashSet { match self { @@ -220,6 +225,31 @@ impl DexValue { DexValue::Boolean(_) => HashSet::new(), } } + + // TODO: implement for each variant struct for python binding + /// Return all method handles referenced in the value. + pub fn get_all_method_handles(&self) -> HashSet { + match self { + DexValue::Byte(_) => HashSet::new(), + DexValue::Short(_) => HashSet::new(), + DexValue::Char(_) => HashSet::new(), + DexValue::Int(_) => HashSet::new(), + DexValue::Long(_) => HashSet::new(), + DexValue::Float(_) => HashSet::new(), + DexValue::Double(_) => HashSet::new(), + DexValue::MethodType(_) => HashSet::new(), + DexValue::MethodHandle(val) => val.get_all_method_handles(), + DexValue::String(_) => HashSet::new(), + DexValue::Type(_) => HashSet::new(), + DexValue::Field(_) => HashSet::new(), + DexValue::Method(_) => HashSet::new(), + DexValue::Enum(_) => HashSet::new(), + DexValue::Array(val) => val.get_all_method_handles(), + DexValue::Annotation(val) => val.get_all_method_handles(), + DexValue::Null(_) => HashSet::new(), + DexValue::Boolean(_) => HashSet::new(), + } + } } impl IntoPy for DexValue { diff --git a/androscalpel_serializer/src/constant.rs b/androscalpel_serializer/src/consts.rs similarity index 100% rename from androscalpel_serializer/src/constant.rs rename to androscalpel_serializer/src/consts.rs diff --git a/androscalpel_serializer/src/items/class.rs b/androscalpel_serializer/src/items/class.rs index c7a932a..b586284 100644 --- a/androscalpel_serializer/src/items/class.rs +++ b/androscalpel_serializer/src/items/class.rs @@ -74,7 +74,7 @@ pub enum MethodHandleType { } /// -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct ClassDataItem { // pub static_fields_size: Uleb128, // pub instance_fields_size: Uleb128, diff --git a/androscalpel_serializer/src/lib.rs b/androscalpel_serializer/src/lib.rs index 5778f9f..5100d14 100644 --- a/androscalpel_serializer/src/lib.rs +++ b/androscalpel_serializer/src/lib.rs @@ -1,6 +1,6 @@ pub mod annotation; pub mod array; -pub mod constant; +pub mod consts; pub mod core; pub mod debug; pub mod file_reader; @@ -12,7 +12,7 @@ pub use androscalpel_serializer_derive::*; pub use crate::core::*; pub use annotation::*; pub use array::*; -pub use constant::*; +pub use consts::*; pub use debug::*; pub use items::*; pub use value::*;