add class data to generated dex

This commit is contained in:
Jean-Marie Mineau 2023-12-05 00:14:27 +01:00
parent 409663ca19
commit bb9f5a94aa
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
12 changed files with 474 additions and 41 deletions

View file

@ -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<IdMethod> {
self.annotation.get_all_method_ids()
}
/// Return all method handles referenced in the annotation.
pub fn get_all_method_handles(&self) -> HashSet<MethodHandle> {
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<MethodHandle> {
let mut methods = HashSet::new();
for value in self.elements.values() {
methods.extend(value.get_all_method_handles());
}
methods
}
}

View file

@ -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<MethodHandle> {
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
}
}

View file

@ -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<MethodHandle> {
// TODO
HashSet::new()
}
}

View file

@ -39,7 +39,7 @@ pub struct DexWriter {
/// index in the `class_defs` section.
class_defs: HashMap<IdType, (Class, usize)>,
// 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",
@ -329,12 +320,121 @@ impl DexWriter {
NO_INDEX.0
},
annotations_off: 0, // TODO
class_data_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<IdField> =
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<IdField> =
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<IdMethod> =
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<IdMethod> =
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<MethodHandleItem> = 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)?;

View file

@ -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<IdMethod> {
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<MethodHandle> {
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
}
}

View file

@ -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<MethodHandle> {
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
}
}

View file

@ -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<IdMethod> {
HashSet::new()
}
/// Return all method handles referenced in the handle.
pub fn get_all_method_handles(&self) -> HashSet<MethodHandle> {
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<IdMethod> {
HashSet::new()
}
/// Return all method handles referenced in the handle.
pub fn get_all_method_handles(&self) -> HashSet<MethodHandle> {
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<IdMethod> {
HashSet::new()
}
/// Return all method handles referenced in the handle.
pub fn get_all_method_handles(&self) -> HashSet<MethodHandle> {
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<IdMethod> {
HashSet::new()
}
/// Return all method handles referenced in the handle.
pub fn get_all_method_handles(&self) -> HashSet<MethodHandle> {
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<MethodHandle> {
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<MethodHandle> {
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<MethodHandle> {
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<MethodHandle> {
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<MethodHandle> {
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<MethodHandle> {
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(),
}
}
}

View file

@ -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<MethodHandle> {
let mut methods = HashSet::new();
for val in &self.0 {
methods.extend(val.get_all_method_handles());
}
methods
}
}

View file

@ -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<DexString> {
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<IdType> {
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<IdMethodType> {
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<IdField> {
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<IdMethod> {
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<MethodHandle> {
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<PyObject> for DexValue {

View file

@ -74,7 +74,7 @@ pub enum MethodHandleType {
}
/// <https://source.android.com/docs/core/runtime/dex-format#class-data-item>
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct ClassDataItem {
// pub static_fields_size: Uleb128,
// pub instance_fields_size: Uleb128,

View file

@ -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::*;