diff --git a/androscalpel/src/apk.rs b/androscalpel/src/apk.rs index 5b5c192..cd492f0 100644 --- a/androscalpel/src/apk.rs +++ b/androscalpel/src/apk.rs @@ -490,37 +490,33 @@ impl Apk { pub fn get_method_handle_from_idx(idx: usize, dex: &DexFileReader) -> Result { let handle = dex.get_method_handle(idx)?; match handle.method_handle_type { - MethodHandleType::StaticPut => Ok(MethodHandle::StaticPut(StaticPut( - Self::get_id_field_from_idx(handle.field_or_method_id as usize, dex)?, - ))), - MethodHandleType::StaticGet => Ok(MethodHandle::StaticGet(StaticGet( - Self::get_id_field_from_idx(handle.field_or_method_id as usize, dex)?, - ))), - MethodHandleType::InstancePut => Ok(MethodHandle::InstancePut(InstancePut( - Self::get_id_field_from_idx(handle.field_or_method_id as usize, dex)?, - ))), - MethodHandleType::InstanceGet => Ok(MethodHandle::InstanceGet(InstanceGet( - Self::get_id_field_from_idx(handle.field_or_method_id as usize, dex)?, - ))), - MethodHandleType::InvokeStatic => Ok(MethodHandle::InvokeStatic(InvokeStatic( - Self::get_id_method_from_idx(handle.field_or_method_id as usize, dex)?, - ))), - MethodHandleType::InvokeInstance => Ok(MethodHandle::InvokeInstance(InvokeInstance( - Self::get_id_method_from_idx(handle.field_or_method_id as usize, dex)?, - ))), - MethodHandleType::InvokeConstructor => { - Ok(MethodHandle::InvokeConstructor(InvokeConstructor( - Self::get_id_method_from_idx(handle.field_or_method_id as usize, dex)?, - ))) - } - MethodHandleType::InvokeDirect => Ok(MethodHandle::InvokeDirect(InvokeDirect( - Self::get_id_method_from_idx(handle.field_or_method_id as usize, dex)?, - ))), - MethodHandleType::InvokeInterface => { - Ok(MethodHandle::InvokeInterface(InvokeInterface( - Self::get_id_method_from_idx(handle.field_or_method_id as usize, dex)?, - ))) - } + MethodHandleType::StaticPut => Ok(MethodHandle::StaticPut { + field: Self::get_id_field_from_idx(handle.field_or_method_id as usize, dex)?, + }), + MethodHandleType::StaticGet => Ok(MethodHandle::StaticGet { + field: Self::get_id_field_from_idx(handle.field_or_method_id as usize, dex)?, + }), + MethodHandleType::InstancePut => Ok(MethodHandle::InstancePut { + field: Self::get_id_field_from_idx(handle.field_or_method_id as usize, dex)?, + }), + MethodHandleType::InstanceGet => Ok(MethodHandle::InstanceGet { + field: Self::get_id_field_from_idx(handle.field_or_method_id as usize, dex)?, + }), + MethodHandleType::InvokeStatic => Ok(MethodHandle::InvokeStatic { + method: Self::get_id_method_from_idx(handle.field_or_method_id as usize, dex)?, + }), + MethodHandleType::InvokeInstance => Ok(MethodHandle::InvokeInstance { + method: Self::get_id_method_from_idx(handle.field_or_method_id as usize, dex)?, + }), + MethodHandleType::InvokeConstructor => Ok(MethodHandle::InvokeConstructor { + method: Self::get_id_method_from_idx(handle.field_or_method_id as usize, dex)?, + }), + MethodHandleType::InvokeDirect => Ok(MethodHandle::InvokeDirect { + method: Self::get_id_method_from_idx(handle.field_or_method_id as usize, dex)?, + }), + MethodHandleType::InvokeInterface => Ok(MethodHandle::InvokeInterface { + method: Self::get_id_method_from_idx(handle.field_or_method_id as usize, dex)?, + }), } } @@ -793,7 +789,7 @@ impl Apk { labels.insert(addr, label.clone()); } let ins = match format.clone() { - Format10X { op: 0x00 } => Instruction::Nop(Nop::new()), + Format10X { op: 0x00 } => Instruction::Nop {}, Format12X { op: 0x01, va, vb } => Instruction::Move(Move::new(va as u16, vb as u16)), Format22X { op: 0x02, va, vb } => Instruction::Move(Move::new(va as u16, vb)), Format32X { op: 0x03, va, vb } => Instruction::Move(Move::new(va, vb)), diff --git a/androscalpel/src/code.rs b/androscalpel/src/code.rs index 72456f9..42a8972 100644 --- a/androscalpel/src/code.rs +++ b/androscalpel/src/code.rs @@ -472,7 +472,7 @@ impl Code { } last_ins_was_a_label = true; } - Instruction::Nop(_) => (), + Instruction::Nop {} => (), instr => { last_ins_was_a_label = false; new_insns.push(instr); diff --git a/androscalpel/src/dex_id.rs b/androscalpel/src/dex_id.rs index a48215f..454727a 100644 --- a/androscalpel/src/dex_id.rs +++ b/androscalpel/src/dex_id.rs @@ -10,7 +10,7 @@ use anyhow::{anyhow, bail, Context}; use pyo3::class::basic::CompareOp; use pyo3::prelude::*; -use crate::{scalar::*, DexString, DexValue, Result}; +use crate::{scalar::*, DexString, DexValue, Result, Visitable, VisitableMut, Visitor, VisitorMut}; use androscalpel_serializer::{StringDataItem, Uleb128}; /// The type of a method. The shorty is formated as described in @@ -25,6 +25,30 @@ pub struct IdMethodType { pub(crate) parameters: Vec, } +impl Visitable for IdMethodType { + fn default_visit(&self, v: &mut V) -> Result<()> { + v.visit_string(&self.shorty)?; + v.visit_type(&self.return_type)?; + for ty in &self.parameters { + v.visit_type(&ty)?; + } + Ok(()) + } +} + +impl VisitableMut for IdMethodType { + fn default_visit_mut(mut self, v: &mut V) -> Result { + self.shorty = v.visit_string(self.shorty)?; + self.return_type = v.visit_type(self.return_type)?; + self.parameters = self + .parameters + .into_iter() + .map(|ty| v.visit_type(ty)) + .collect::>()?; + Ok(self) + } +} + impl Ord for IdMethodType { fn cmp(&self, other: &Self) -> Ordering { self.return_type @@ -220,6 +244,18 @@ impl IdMethodType { #[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct IdType(pub(crate) DexString); + +impl Visitable for IdType { + fn default_visit(&self, v: &mut V) -> Result<()> { + v.visit_string(&self.0) + } +} + +impl VisitableMut for IdType { + fn default_visit_mut(self, v: &mut V) -> Result { + Ok(Self(v.visit_string(self.0)?)) + } +} #[pymethods] impl IdType { pub fn to_json(&self) -> Result { @@ -637,6 +673,24 @@ pub struct IdField { pub class_: IdType, } +impl Visitable for IdField { + fn default_visit(&self, v: &mut V) -> Result<()> { + v.visit_string(&self.name)?; + v.visit_type(&self.type_)?; + v.visit_type(&self.class_)?; + Ok(()) + } +} + +impl VisitableMut for IdField { + fn default_visit_mut(mut self, v: &mut V) -> Result { + self.name = v.visit_string(self.name)?; + self.type_ = v.visit_type(self.type_)?; + self.class_ = v.visit_type(self.class_)?; + Ok(self) + } +} + #[pymethods] impl IdField { pub fn to_json(&self) -> Result { @@ -795,6 +849,24 @@ pub struct IdMethod { pub name: DexString, } +impl Visitable for IdMethod { + fn default_visit(&self, v: &mut V) -> Result<()> { + v.visit_string(&self.name)?; + v.visit_method_type(&self.proto)?; + v.visit_type(&self.class_)?; + Ok(()) + } +} + +impl VisitableMut for IdMethod { + fn default_visit_mut(mut self, v: &mut V) -> Result { + self.name = v.visit_string(self.name)?; + self.proto = v.visit_method_type(self.proto)?; + self.class_ = v.visit_type(self.class_)?; + Ok(self) + } +} + #[pymethods] impl IdMethod { pub fn to_json(&self) -> Result { @@ -972,6 +1044,18 @@ impl SmaliName for IdMethod { #[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd)] pub struct IdEnum(pub IdField); +impl Visitable for IdEnum { + fn default_visit(&self, v: &mut V) -> Result<()> { + v.visit_field_id(&self.0) + } +} + +impl VisitableMut for IdEnum { + fn default_visit_mut(self, v: &mut V) -> Result { + Ok(Self(v.visit_field_id(self.0)?)) + } +} + #[pymethods] impl IdEnum { pub fn to_json(&self) -> Result { diff --git a/androscalpel/src/dex_string.rs b/androscalpel/src/dex_string.rs index cd0ef28..b9f0016 100644 --- a/androscalpel/src/dex_string.rs +++ b/androscalpel/src/dex_string.rs @@ -1,4 +1,4 @@ -use crate::Result; +use crate::{Result, Visitable, VisitableMut, Visitor, VisitorMut}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::cmp::{Ord, PartialOrd}; use std::collections::hash_map::DefaultHasher; @@ -13,6 +13,19 @@ use pyo3::prelude::*; #[derive(Clone, PartialEq, Eq, Ord, PartialOrd)] pub struct DexString(pub androscalpel_serializer::StringDataItem); +// Kinda useless +impl Visitable for DexString { + fn default_visit(&self, _: &mut V) -> Result<()> { + Ok(()) + } +} + +impl VisitableMut for DexString { + fn default_visit_mut(self, _: &mut V) -> Result { + Ok(self) + } +} + impl std::fmt::Debug for DexString { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { if let Ok(string) = TryInto::::try_into(self) { diff --git a/androscalpel/src/dex_writer.rs b/androscalpel/src/dex_writer.rs index 253fa60..f11464f 100644 --- a/androscalpel/src/dex_writer.rs +++ b/androscalpel/src/dex_writer.rs @@ -581,7 +581,7 @@ impl DexWriter { // https://cs.android.com/android/platform/superproject/main/+/main:art/runtime/verifier/method_verifier.cc;drc=e8c3e7be783937a340cd4f3280b69962d6f1ea0c;l=1347 // The ART check if the array data table is 4 bytes aligned (= 2 ins alligned) // TODO: check how it is donne in android and other dex generation code. - let nop = Instruction::Nop(Nop).get_raw_ins()?; + let nop = (Instruction::Nop {}).get_raw_ins()?; payload_addr += nop.size() / 2; payloads.push(nop); } @@ -632,7 +632,7 @@ impl DexWriter { // https://cs.android.com/android/platform/superproject/main/+/main:art/runtime/verifier/method_verifier.cc;drc=e8c3e7be783937a340cd4f3280b69962d6f1ea0c;l=1464 // The ART check if the switch table is 4 bytes aligned (= 2 ins alligned) // TODO: check how it is donne in android and other dex generation code. - let nop = Instruction::Nop(Nop).get_raw_ins()?; + let nop = (Instruction::Nop {}).get_raw_ins()?; payload_addr += nop.size() / 2; payloads.push(nop); } @@ -1388,7 +1388,7 @@ impl DexWriter { } if addr % 2 != 0 { // make sure the payload section is 4 bytes aligned - let nop = Instruction::Nop(Nop).get_raw_ins()?; + let nop = (Instruction::Nop {}).get_raw_ins()?; //addr += nop.size() / 2; insns.push(nop); } @@ -1582,66 +1582,66 @@ impl DexWriter { /// Insert a [`MethodHandle`]. pub fn insert_method_handle(&mut self, handle: &MethodHandle) -> Result<()> { let (field_or_method_id, method_handle_type) = match handle { - MethodHandle::StaticPut(StaticPut(field)) => ( + MethodHandle::StaticPut { field } => ( *self.field_ids.get(field).ok_or(anyhow!( "Field {} not found in dex writer", field.__repr__() ))? as u16, MethodHandleType::StaticPut, ), - MethodHandle::StaticGet(StaticGet(field)) => ( + MethodHandle::StaticGet { field } => ( *self.field_ids.get(field).ok_or(anyhow!( "Field {} not found in dex writer", field.__repr__() ))? as u16, MethodHandleType::StaticGet, ), - MethodHandle::InstancePut(InstancePut(field)) => ( + MethodHandle::InstancePut { field } => ( *self.field_ids.get(field).ok_or(anyhow!( "Field {} not found in dex writer", field.__repr__() ))? as u16, MethodHandleType::InstancePut, ), - MethodHandle::InstanceGet(InstanceGet(field)) => ( + MethodHandle::InstanceGet { field } => ( *self.field_ids.get(field).ok_or(anyhow!( "Field {} not found in dex writer", field.__repr__() ))? as u16, MethodHandleType::InstanceGet, ), - MethodHandle::InvokeStatic(InvokeStatic(meth)) => ( - *self.method_ids.get(meth).ok_or(anyhow!( + MethodHandle::InvokeStatic { method } => ( + *self.method_ids.get(method).ok_or(anyhow!( "Method {} not found in dex writer", - meth.__repr__() + method.__repr__() ))? as u16, MethodHandleType::InvokeStatic, ), - MethodHandle::InvokeInstance(InvokeInstance(meth)) => ( - *self.method_ids.get(meth).ok_or(anyhow!( + MethodHandle::InvokeInstance { method } => ( + *self.method_ids.get(method).ok_or(anyhow!( "Method {} not found in dex writer", - meth.__repr__() + method.__repr__() ))? as u16, MethodHandleType::InvokeInstance, ), - MethodHandle::InvokeConstructor(InvokeConstructor(meth)) => ( - *self.method_ids.get(meth).ok_or(anyhow!( + MethodHandle::InvokeConstructor { method } => ( + *self.method_ids.get(method).ok_or(anyhow!( "Method {} not found in dex writer", - meth.__repr__() + method.__repr__() ))? as u16, MethodHandleType::InvokeConstructor, ), - MethodHandle::InvokeDirect(InvokeDirect(meth)) => ( - *self.method_ids.get(meth).ok_or(anyhow!( + MethodHandle::InvokeDirect { method } => ( + *self.method_ids.get(method).ok_or(anyhow!( "Method {} not found in dex writer", - meth.__repr__() + method.__repr__() ))? as u16, MethodHandleType::InvokeDirect, ), - MethodHandle::InvokeInterface(InvokeInterface(meth)) => ( - *self.method_ids.get(meth).ok_or(anyhow!( + MethodHandle::InvokeInterface { method } => ( + *self.method_ids.get(method).ok_or(anyhow!( "Method {} not found in dex writer", - meth.__repr__() + method.__repr__() ))? as u16, MethodHandleType::InvokeInterface, ), diff --git a/androscalpel/src/instructions.rs b/androscalpel/src/instructions.rs index f7f044c..d1f7e75 100644 --- a/androscalpel/src/instructions.rs +++ b/androscalpel/src/instructions.rs @@ -6,7 +6,11 @@ use serde::{Deserialize, Serialize}; use crate::hashmap_vectorize; -use crate::{DexString, DexValue, IdField, IdMethod, IdMethodType, IdType, MethodHandle, Result}; +use crate::{ + DexString, DexValue, FieldIdCollector, IdField, IdMethod, IdMethodType, IdType, MethodHandle, + MethodHandleCollector, MethodIdCollector, MethodTypeCollector, Result, StringCollector, + TypeCollector, Visitable, VisitableMut, Visitor, VisitorMut, +}; use androscalpel_serializer::Instruction as InsFormat; use androscalpel_serializer::Serializable; @@ -31,7 +35,8 @@ const U16_MAX_AS_USIZE: usize = u16::MAX as usize; // TODO: impl PartialEq and Eq for call site to derive them here #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub enum Instruction { - Nop(Nop), + /// Waste a cycle. + Nop {}, Move(Move), MoveWide(MoveWide), MoveObject(MoveObject), @@ -227,10 +232,412 @@ pub enum Instruction { Label(Label), } +impl Visitable for Instruction { + fn default_visit(&self, _visitor: &mut V) -> Result<()> { + match self { + Self::Nop {} => Ok(()), + Self::Move(_ins) => todo!(), + Self::MoveWide(_ins) => todo!(), + Self::MoveObject(_ins) => todo!(), + Self::MoveResult(_ins) => todo!(), + Self::MoveResultWide(_ins) => todo!(), + Self::MoveException(_ins) => todo!(), + Self::MoveResultObject(_ins) => todo!(), + Self::ReturnVoid(_ins) => todo!(), + Self::Return(_ins) => todo!(), + Self::ReturnWide(_ins) => todo!(), + Self::ReturnObject(_ins) => todo!(), + Self::Const(_ins) => todo!(), + Self::ConstWide(_ins) => todo!(), + Self::ConstString(_ins) => todo!(), + Self::ConstClass(_ins) => todo!(), + Self::MonitorEnter(_ins) => todo!(), + Self::MonitorExit(_ins) => todo!(), + Self::CheckCast(_ins) => todo!(), + Self::InstanceOf(_ins) => todo!(), + Self::ArrayLength(_ins) => todo!(), + Self::NewInstance(_ins) => todo!(), + Self::NewArray(_ins) => todo!(), + Self::FilledNewArray(_ins) => todo!(), + Self::FillArrayData(_ins) => todo!(), + Self::Throw(_ins) => todo!(), + Self::Goto(_ins) => todo!(), + Self::Switch(_ins) => todo!(), + Self::CmpLFloat(_ins) => todo!(), + Self::CmpGFloat(_ins) => todo!(), + Self::CmpLDouble(_ins) => todo!(), + Self::CmpGDouble(_ins) => todo!(), + Self::CmpLong(_ins) => todo!(), + Self::IfEq(_ins) => todo!(), + Self::IfNe(_ins) => todo!(), + Self::IfLt(_ins) => todo!(), + Self::IfGe(_ins) => todo!(), + Self::IfGt(_ins) => todo!(), + Self::IfLe(_ins) => todo!(), + Self::IfEqZ(_ins) => todo!(), + Self::IfNeZ(_ins) => todo!(), + Self::IfLtZ(_ins) => todo!(), + Self::IfGeZ(_ins) => todo!(), + Self::IfGtZ(_ins) => todo!(), + Self::IfLeZ(_ins) => todo!(), + Self::AGet(_ins) => todo!(), + Self::AGetWide(_ins) => todo!(), + Self::AGetObject(_ins) => todo!(), + Self::AGetBoolean(_ins) => todo!(), + Self::AGetByte(_ins) => todo!(), + Self::AGetChar(_ins) => todo!(), + Self::AGetShort(_ins) => todo!(), + Self::APut(_ins) => todo!(), + Self::APutWide(_ins) => todo!(), + Self::APutObject(_ins) => todo!(), + Self::APutBoolean(_ins) => todo!(), + Self::APutByte(_ins) => todo!(), + Self::APutChar(_ins) => todo!(), + Self::APutShort(_ins) => todo!(), + Self::IGet(_ins) => todo!(), + Self::IGetWide(_ins) => todo!(), + Self::IGetObject(_ins) => todo!(), + Self::IGetBoolean(_ins) => todo!(), + Self::IGetByte(_ins) => todo!(), + Self::IGetChar(_ins) => todo!(), + Self::IGetShort(_ins) => todo!(), + Self::IPut(_ins) => todo!(), + Self::IPutWide(_ins) => todo!(), + Self::IPutObject(_ins) => todo!(), + Self::IPutBoolean(_ins) => todo!(), + Self::IPutByte(_ins) => todo!(), + Self::IPutChar(_ins) => todo!(), + Self::IPutShort(_ins) => todo!(), + Self::SGet(_ins) => todo!(), + Self::SGetWide(_ins) => todo!(), + Self::SGetObject(_ins) => todo!(), + Self::SGetBoolean(_ins) => todo!(), + Self::SGetByte(_ins) => todo!(), + Self::SGetChar(_ins) => todo!(), + Self::SGetShort(_ins) => todo!(), + Self::SPut(_ins) => todo!(), + Self::SPutWide(_ins) => todo!(), + Self::SPutObject(_ins) => todo!(), + Self::SPutBoolean(_ins) => todo!(), + Self::SPutByte(_ins) => todo!(), + Self::SPutChar(_ins) => todo!(), + Self::SPutShort(_ins) => todo!(), + Self::InvokeVirtual(_ins) => todo!(), + Self::InvokeSuper(_ins) => todo!(), + Self::InvokeDirect(_ins) => todo!(), + Self::InvokeStatic(_ins) => todo!(), + Self::InvokeInterface(_ins) => todo!(), + Self::NegInt(_ins) => todo!(), + Self::NotInt(_ins) => todo!(), + Self::NegLong(_ins) => todo!(), + Self::NotLong(_ins) => todo!(), + Self::NegFloat(_ins) => todo!(), + Self::NegDouble(_ins) => todo!(), + Self::IntToLong(_ins) => todo!(), + Self::IntToFloat(_ins) => todo!(), + Self::IntToDouble(_ins) => todo!(), + Self::LongToInt(_ins) => todo!(), + Self::LongToFloat(_ins) => todo!(), + Self::LongToDouble(_ins) => todo!(), + Self::FloatToInt(_ins) => todo!(), + Self::FloatToLong(_ins) => todo!(), + Self::FloatToDouble(_ins) => todo!(), + Self::DoubleToInt(_ins) => todo!(), + Self::DoubleToLong(_ins) => todo!(), + Self::DoubleToFloat(_ins) => todo!(), + Self::IntToByte(_ins) => todo!(), + Self::IntToChar(_ins) => todo!(), + Self::IntToShort(_ins) => todo!(), + Self::AddInt(_ins) => todo!(), + Self::SubInt(_ins) => todo!(), + Self::MulInt(_ins) => todo!(), + Self::DivInt(_ins) => todo!(), + Self::RemInt(_ins) => todo!(), + Self::AndInt(_ins) => todo!(), + Self::OrInt(_ins) => todo!(), + Self::XorInt(_ins) => todo!(), + Self::ShlInt(_ins) => todo!(), + Self::ShrInt(_ins) => todo!(), + Self::UshrInt(_ins) => todo!(), + Self::AddLong(_ins) => todo!(), + Self::SubLong(_ins) => todo!(), + Self::MulLong(_ins) => todo!(), + Self::DivLong(_ins) => todo!(), + Self::RemLong(_ins) => todo!(), + Self::AndLong(_ins) => todo!(), + Self::OrLong(_ins) => todo!(), + Self::XorLong(_ins) => todo!(), + Self::ShlLong(_ins) => todo!(), + Self::ShrLong(_ins) => todo!(), + Self::UshrLong(_ins) => todo!(), + Self::AddFloat(_ins) => todo!(), + Self::SubFloat(_ins) => todo!(), + Self::MulFloat(_ins) => todo!(), + Self::DivFloat(_ins) => todo!(), + Self::RemFloat(_ins) => todo!(), + Self::AddDouble(_ins) => todo!(), + Self::SubDouble(_ins) => todo!(), + Self::MulDouble(_ins) => todo!(), + Self::DivDouble(_ins) => todo!(), + Self::RemDouble(_ins) => todo!(), + Self::AddInt2Addr(_ins) => todo!(), + Self::SubInt2Addr(_ins) => todo!(), + Self::MulInt2Addr(_ins) => todo!(), + Self::DivInt2Addr(_ins) => todo!(), + Self::RemInt2Addr(_ins) => todo!(), + Self::AndInt2Addr(_ins) => todo!(), + Self::OrInt2Addr(_ins) => todo!(), + Self::XorInt2Addr(_ins) => todo!(), + Self::ShlInt2Addr(_ins) => todo!(), + Self::ShrInt2Addr(_ins) => todo!(), + Self::UshrInt2Addr(_ins) => todo!(), + Self::AddLong2Addr(_ins) => todo!(), + Self::SubLong2Addr(_ins) => todo!(), + Self::MulLong2Addr(_ins) => todo!(), + Self::DivLong2Addr(_ins) => todo!(), + Self::RemLong2Addr(_ins) => todo!(), + Self::AndLong2Addr(_ins) => todo!(), + Self::OrLong2Addr(_ins) => todo!(), + Self::XorLong2Addr(_ins) => todo!(), + Self::ShlLong2Addr(_ins) => todo!(), + Self::ShrLong2Addr(_ins) => todo!(), + Self::UshrLong2Addr(_ins) => todo!(), + Self::AddFloat2Addr(_ins) => todo!(), + Self::SubFloat2Addr(_ins) => todo!(), + Self::MulFloat2Addr(_ins) => todo!(), + Self::DivFloat2Addr(_ins) => todo!(), + Self::RemFloat2Addr(_ins) => todo!(), + Self::AddDouble2Addr(_ins) => todo!(), + Self::SubDouble2Addr(_ins) => todo!(), + Self::MulDouble2Addr(_ins) => todo!(), + Self::DivDouble2Addr(_ins) => todo!(), + Self::RemDouble2Addr(_ins) => todo!(), + Self::AddIntLit(_ins) => todo!(), + Self::RsubIntLit(_ins) => todo!(), + Self::MulIntLit(_ins) => todo!(), + Self::DivIntLit(_ins) => todo!(), + Self::RemIntLit(_ins) => todo!(), + Self::AndIntLit(_ins) => todo!(), + Self::OrIntLit(_ins) => todo!(), + Self::XorIntLit(_ins) => todo!(), + Self::ShlIntLit(_ins) => todo!(), + Self::ShrIntLit(_ins) => todo!(), + Self::UshrIntLit(_ins) => todo!(), + Self::InvokePolymorphic(_ins) => todo!(), + Self::InvokeCustom(_ins) => todo!(), + Self::ConstMethodHandle(_ins) => todo!(), + Self::ConstMethodType(_ins) => todo!(), + Self::Try(_ins) => todo!(), + Self::Label(_ins) => todo!(), + } + } +} + +impl VisitableMut for Instruction { + fn default_visit_mut(self, _visitor: &mut V) -> Result { + match self { + Self::Nop {} => Ok(self), + Self::Move(_ins) => todo!(), + Self::MoveWide(_ins) => todo!(), + Self::MoveObject(_ins) => todo!(), + Self::MoveResult(_ins) => todo!(), + Self::MoveResultWide(_ins) => todo!(), + Self::MoveException(_ins) => todo!(), + Self::MoveResultObject(_ins) => todo!(), + Self::ReturnVoid(_ins) => todo!(), + Self::Return(_ins) => todo!(), + Self::ReturnWide(_ins) => todo!(), + Self::ReturnObject(_ins) => todo!(), + Self::Const(_ins) => todo!(), + Self::ConstWide(_ins) => todo!(), + Self::ConstString(_ins) => todo!(), + Self::ConstClass(_ins) => todo!(), + Self::MonitorEnter(_ins) => todo!(), + Self::MonitorExit(_ins) => todo!(), + Self::CheckCast(_ins) => todo!(), + Self::InstanceOf(_ins) => todo!(), + Self::ArrayLength(_ins) => todo!(), + Self::NewInstance(_ins) => todo!(), + Self::NewArray(_ins) => todo!(), + Self::FilledNewArray(_ins) => todo!(), + Self::FillArrayData(_ins) => todo!(), + Self::Throw(_ins) => todo!(), + Self::Goto(_ins) => todo!(), + Self::Switch(_ins) => todo!(), + Self::CmpLFloat(_ins) => todo!(), + Self::CmpGFloat(_ins) => todo!(), + Self::CmpLDouble(_ins) => todo!(), + Self::CmpGDouble(_ins) => todo!(), + Self::CmpLong(_ins) => todo!(), + Self::IfEq(_ins) => todo!(), + Self::IfNe(_ins) => todo!(), + Self::IfLt(_ins) => todo!(), + Self::IfGe(_ins) => todo!(), + Self::IfGt(_ins) => todo!(), + Self::IfLe(_ins) => todo!(), + Self::IfEqZ(_ins) => todo!(), + Self::IfNeZ(_ins) => todo!(), + Self::IfLtZ(_ins) => todo!(), + Self::IfGeZ(_ins) => todo!(), + Self::IfGtZ(_ins) => todo!(), + Self::IfLeZ(_ins) => todo!(), + Self::AGet(_ins) => todo!(), + Self::AGetWide(_ins) => todo!(), + Self::AGetObject(_ins) => todo!(), + Self::AGetBoolean(_ins) => todo!(), + Self::AGetByte(_ins) => todo!(), + Self::AGetChar(_ins) => todo!(), + Self::AGetShort(_ins) => todo!(), + Self::APut(_ins) => todo!(), + Self::APutWide(_ins) => todo!(), + Self::APutObject(_ins) => todo!(), + Self::APutBoolean(_ins) => todo!(), + Self::APutByte(_ins) => todo!(), + Self::APutChar(_ins) => todo!(), + Self::APutShort(_ins) => todo!(), + Self::IGet(_ins) => todo!(), + Self::IGetWide(_ins) => todo!(), + Self::IGetObject(_ins) => todo!(), + Self::IGetBoolean(_ins) => todo!(), + Self::IGetByte(_ins) => todo!(), + Self::IGetChar(_ins) => todo!(), + Self::IGetShort(_ins) => todo!(), + Self::IPut(_ins) => todo!(), + Self::IPutWide(_ins) => todo!(), + Self::IPutObject(_ins) => todo!(), + Self::IPutBoolean(_ins) => todo!(), + Self::IPutByte(_ins) => todo!(), + Self::IPutChar(_ins) => todo!(), + Self::IPutShort(_ins) => todo!(), + Self::SGet(_ins) => todo!(), + Self::SGetWide(_ins) => todo!(), + Self::SGetObject(_ins) => todo!(), + Self::SGetBoolean(_ins) => todo!(), + Self::SGetByte(_ins) => todo!(), + Self::SGetChar(_ins) => todo!(), + Self::SGetShort(_ins) => todo!(), + Self::SPut(_ins) => todo!(), + Self::SPutWide(_ins) => todo!(), + Self::SPutObject(_ins) => todo!(), + Self::SPutBoolean(_ins) => todo!(), + Self::SPutByte(_ins) => todo!(), + Self::SPutChar(_ins) => todo!(), + Self::SPutShort(_ins) => todo!(), + Self::InvokeVirtual(_ins) => todo!(), + Self::InvokeSuper(_ins) => todo!(), + Self::InvokeDirect(_ins) => todo!(), + Self::InvokeStatic(_ins) => todo!(), + Self::InvokeInterface(_ins) => todo!(), + Self::NegInt(_ins) => todo!(), + Self::NotInt(_ins) => todo!(), + Self::NegLong(_ins) => todo!(), + Self::NotLong(_ins) => todo!(), + Self::NegFloat(_ins) => todo!(), + Self::NegDouble(_ins) => todo!(), + Self::IntToLong(_ins) => todo!(), + Self::IntToFloat(_ins) => todo!(), + Self::IntToDouble(_ins) => todo!(), + Self::LongToInt(_ins) => todo!(), + Self::LongToFloat(_ins) => todo!(), + Self::LongToDouble(_ins) => todo!(), + Self::FloatToInt(_ins) => todo!(), + Self::FloatToLong(_ins) => todo!(), + Self::FloatToDouble(_ins) => todo!(), + Self::DoubleToInt(_ins) => todo!(), + Self::DoubleToLong(_ins) => todo!(), + Self::DoubleToFloat(_ins) => todo!(), + Self::IntToByte(_ins) => todo!(), + Self::IntToChar(_ins) => todo!(), + Self::IntToShort(_ins) => todo!(), + Self::AddInt(_ins) => todo!(), + Self::SubInt(_ins) => todo!(), + Self::MulInt(_ins) => todo!(), + Self::DivInt(_ins) => todo!(), + Self::RemInt(_ins) => todo!(), + Self::AndInt(_ins) => todo!(), + Self::OrInt(_ins) => todo!(), + Self::XorInt(_ins) => todo!(), + Self::ShlInt(_ins) => todo!(), + Self::ShrInt(_ins) => todo!(), + Self::UshrInt(_ins) => todo!(), + Self::AddLong(_ins) => todo!(), + Self::SubLong(_ins) => todo!(), + Self::MulLong(_ins) => todo!(), + Self::DivLong(_ins) => todo!(), + Self::RemLong(_ins) => todo!(), + Self::AndLong(_ins) => todo!(), + Self::OrLong(_ins) => todo!(), + Self::XorLong(_ins) => todo!(), + Self::ShlLong(_ins) => todo!(), + Self::ShrLong(_ins) => todo!(), + Self::UshrLong(_ins) => todo!(), + Self::AddFloat(_ins) => todo!(), + Self::SubFloat(_ins) => todo!(), + Self::MulFloat(_ins) => todo!(), + Self::DivFloat(_ins) => todo!(), + Self::RemFloat(_ins) => todo!(), + Self::AddDouble(_ins) => todo!(), + Self::SubDouble(_ins) => todo!(), + Self::MulDouble(_ins) => todo!(), + Self::DivDouble(_ins) => todo!(), + Self::RemDouble(_ins) => todo!(), + Self::AddInt2Addr(_ins) => todo!(), + Self::SubInt2Addr(_ins) => todo!(), + Self::MulInt2Addr(_ins) => todo!(), + Self::DivInt2Addr(_ins) => todo!(), + Self::RemInt2Addr(_ins) => todo!(), + Self::AndInt2Addr(_ins) => todo!(), + Self::OrInt2Addr(_ins) => todo!(), + Self::XorInt2Addr(_ins) => todo!(), + Self::ShlInt2Addr(_ins) => todo!(), + Self::ShrInt2Addr(_ins) => todo!(), + Self::UshrInt2Addr(_ins) => todo!(), + Self::AddLong2Addr(_ins) => todo!(), + Self::SubLong2Addr(_ins) => todo!(), + Self::MulLong2Addr(_ins) => todo!(), + Self::DivLong2Addr(_ins) => todo!(), + Self::RemLong2Addr(_ins) => todo!(), + Self::AndLong2Addr(_ins) => todo!(), + Self::OrLong2Addr(_ins) => todo!(), + Self::XorLong2Addr(_ins) => todo!(), + Self::ShlLong2Addr(_ins) => todo!(), + Self::ShrLong2Addr(_ins) => todo!(), + Self::UshrLong2Addr(_ins) => todo!(), + Self::AddFloat2Addr(_ins) => todo!(), + Self::SubFloat2Addr(_ins) => todo!(), + Self::MulFloat2Addr(_ins) => todo!(), + Self::DivFloat2Addr(_ins) => todo!(), + Self::RemFloat2Addr(_ins) => todo!(), + Self::AddDouble2Addr(_ins) => todo!(), + Self::SubDouble2Addr(_ins) => todo!(), + Self::MulDouble2Addr(_ins) => todo!(), + Self::DivDouble2Addr(_ins) => todo!(), + Self::RemDouble2Addr(_ins) => todo!(), + Self::AddIntLit(_ins) => todo!(), + Self::RsubIntLit(_ins) => todo!(), + Self::MulIntLit(_ins) => todo!(), + Self::DivIntLit(_ins) => todo!(), + Self::RemIntLit(_ins) => todo!(), + Self::AndIntLit(_ins) => todo!(), + Self::OrIntLit(_ins) => todo!(), + Self::XorIntLit(_ins) => todo!(), + Self::ShlIntLit(_ins) => todo!(), + Self::ShrIntLit(_ins) => todo!(), + Self::UshrIntLit(_ins) => todo!(), + Self::InvokePolymorphic(_ins) => todo!(), + Self::InvokeCustom(_ins) => todo!(), + Self::ConstMethodHandle(_ins) => todo!(), + Self::ConstMethodType(_ins) => todo!(), + Self::Try(_ins) => todo!(), + Self::Label(_ins) => todo!(), + } + } +} + impl Instruction { pub fn __str__(&self) -> String { match self { - Self::Nop(ins) => ins.__str__(), + Self::Nop {} => "nop".into(), Self::Move(ins) => ins.__str__(), Self::MoveWide(ins) => ins.__str__(), Self::MoveObject(ins) => ins.__str__(), @@ -429,7 +836,7 @@ impl Instruction { pub fn __repr__(&self) -> String { match self { - Self::Nop(ins) => ins.__repr__(), + Self::Nop {} => "Instruction(Nop)".into(), Self::Move(ins) => ins.__repr__(), Self::MoveWide(ins) => ins.__repr__(), Self::MoveObject(ins) => ins.__repr__(), @@ -635,7 +1042,7 @@ impl Instruction { /// count addresses by unit of `u16`. pub fn min_ins_size(&self) -> usize { match self { - Self::Nop(ins) => ins.min_ins_size(), + Self::Nop {} => self.get_raw_ins().unwrap().size(), Self::Move(ins) => ins.min_ins_size(), Self::MoveWide(ins) => ins.min_ins_size(), Self::MoveObject(ins) => ins.min_ins_size(), @@ -841,7 +1248,7 @@ impl Instruction { /// count addresses by unit of `u16`. pub fn max_ins_size(&self) -> usize { match self { - Self::Nop(ins) => ins.max_ins_size(), + Self::Nop {} => self.get_raw_ins().unwrap().size(), Self::Move(ins) => ins.max_ins_size(), Self::MoveWide(ins) => ins.max_ins_size(), Self::MoveObject(ins) => ins.max_ins_size(), @@ -1047,7 +1454,7 @@ impl Instruction { /// count addresses by unit of `u16`. pub fn ins_size(&self) -> Result { match self { - Self::Nop(ins) => Ok(ins.ins_size()), + Self::Nop {} => Ok(self.get_raw_ins().unwrap().size()), Self::Move(ins) => Ok(ins.ins_size()), Self::MoveWide(ins) => Ok(ins.ins_size()), Self::MoveObject(ins) => Ok(ins.ins_size()), @@ -1322,7 +1729,7 @@ impl Instruction { /// - `Label` pub fn get_raw_ins(&self) -> Result { match self { - Self::Nop(ins) => Ok(ins.get_raw_ins()), + Self::Nop {} => Ok(InsFormat::Format10X { op: 0x00 }), Self::Move(ins) => Ok(ins.get_raw_ins()), Self::MoveWide(ins) => Ok(ins.get_raw_ins()), Self::MoveObject(ins) => Ok(ins.get_raw_ins()), @@ -1664,1209 +2071,51 @@ impl Instruction { /// Return all strings referenced in the instruction. pub fn get_all_strings(&self) -> HashSet { - match self { - Self::Nop(ins) => ins.get_all_strings(), - Self::Move(ins) => ins.get_all_strings(), - Self::MoveWide(ins) => ins.get_all_strings(), - Self::MoveObject(ins) => ins.get_all_strings(), - Self::MoveResult(ins) => ins.get_all_strings(), - Self::MoveResultWide(ins) => ins.get_all_strings(), - Self::MoveException(ins) => ins.get_all_strings(), - Self::MoveResultObject(ins) => ins.get_all_strings(), - Self::ReturnVoid(ins) => ins.get_all_strings(), - Self::Return(ins) => ins.get_all_strings(), - Self::ReturnWide(ins) => ins.get_all_strings(), - Self::ReturnObject(ins) => ins.get_all_strings(), - Self::Const(ins) => ins.get_all_strings(), - Self::ConstWide(ins) => ins.get_all_strings(), - Self::ConstString(ins) => ins.get_all_strings(), - Self::ConstClass(ins) => ins.get_all_strings(), - Self::MonitorEnter(ins) => ins.get_all_strings(), - Self::MonitorExit(ins) => ins.get_all_strings(), - Self::CheckCast(ins) => ins.get_all_strings(), - Self::InstanceOf(ins) => ins.get_all_strings(), - Self::ArrayLength(ins) => ins.get_all_strings(), - Self::NewInstance(ins) => ins.get_all_strings(), - Self::NewArray(ins) => ins.get_all_strings(), - Self::FilledNewArray(ins) => ins.get_all_strings(), - Self::FillArrayData(ins) => ins.get_all_strings(), - Self::Throw(ins) => ins.get_all_strings(), - Self::Goto(ins) => ins.get_all_strings(), - Self::Switch(ins) => ins.get_all_strings(), - Self::CmpLFloat(ins) => ins.get_all_strings(), - Self::CmpGFloat(ins) => ins.get_all_strings(), - Self::CmpLDouble(ins) => ins.get_all_strings(), - Self::CmpGDouble(ins) => ins.get_all_strings(), - Self::CmpLong(ins) => ins.get_all_strings(), - Self::IfEq(ins) => ins.get_all_strings(), - Self::IfNe(ins) => ins.get_all_strings(), - Self::IfLt(ins) => ins.get_all_strings(), - Self::IfGe(ins) => ins.get_all_strings(), - Self::IfGt(ins) => ins.get_all_strings(), - Self::IfLe(ins) => ins.get_all_strings(), - Self::IfEqZ(ins) => ins.get_all_strings(), - Self::IfNeZ(ins) => ins.get_all_strings(), - Self::IfLtZ(ins) => ins.get_all_strings(), - Self::IfGeZ(ins) => ins.get_all_strings(), - Self::IfGtZ(ins) => ins.get_all_strings(), - Self::IfLeZ(ins) => ins.get_all_strings(), - Self::AGet(ins) => ins.get_all_strings(), - Self::AGetWide(ins) => ins.get_all_strings(), - Self::AGetObject(ins) => ins.get_all_strings(), - Self::AGetBoolean(ins) => ins.get_all_strings(), - Self::AGetByte(ins) => ins.get_all_strings(), - Self::AGetChar(ins) => ins.get_all_strings(), - Self::AGetShort(ins) => ins.get_all_strings(), - Self::APut(ins) => ins.get_all_strings(), - Self::APutWide(ins) => ins.get_all_strings(), - Self::APutObject(ins) => ins.get_all_strings(), - Self::APutBoolean(ins) => ins.get_all_strings(), - Self::APutByte(ins) => ins.get_all_strings(), - Self::APutChar(ins) => ins.get_all_strings(), - Self::APutShort(ins) => ins.get_all_strings(), - Self::IGet(ins) => ins.get_all_strings(), - Self::IGetWide(ins) => ins.get_all_strings(), - Self::IGetObject(ins) => ins.get_all_strings(), - Self::IGetBoolean(ins) => ins.get_all_strings(), - Self::IGetByte(ins) => ins.get_all_strings(), - Self::IGetChar(ins) => ins.get_all_strings(), - Self::IGetShort(ins) => ins.get_all_strings(), - Self::IPut(ins) => ins.get_all_strings(), - Self::IPutWide(ins) => ins.get_all_strings(), - Self::IPutObject(ins) => ins.get_all_strings(), - Self::IPutBoolean(ins) => ins.get_all_strings(), - Self::IPutByte(ins) => ins.get_all_strings(), - Self::IPutChar(ins) => ins.get_all_strings(), - Self::IPutShort(ins) => ins.get_all_strings(), - Self::SGet(ins) => ins.get_all_strings(), - Self::SGetWide(ins) => ins.get_all_strings(), - Self::SGetObject(ins) => ins.get_all_strings(), - Self::SGetBoolean(ins) => ins.get_all_strings(), - Self::SGetByte(ins) => ins.get_all_strings(), - Self::SGetChar(ins) => ins.get_all_strings(), - Self::SGetShort(ins) => ins.get_all_strings(), - Self::SPut(ins) => ins.get_all_strings(), - Self::SPutWide(ins) => ins.get_all_strings(), - Self::SPutObject(ins) => ins.get_all_strings(), - Self::SPutBoolean(ins) => ins.get_all_strings(), - Self::SPutByte(ins) => ins.get_all_strings(), - Self::SPutChar(ins) => ins.get_all_strings(), - Self::SPutShort(ins) => ins.get_all_strings(), - Self::InvokeVirtual(ins) => ins.get_all_strings(), - Self::InvokeSuper(ins) => ins.get_all_strings(), - Self::InvokeDirect(ins) => ins.get_all_strings(), - Self::InvokeStatic(ins) => ins.get_all_strings(), - Self::InvokeInterface(ins) => ins.get_all_strings(), - Self::NegInt(ins) => ins.get_all_strings(), - Self::NotInt(ins) => ins.get_all_strings(), - Self::NegLong(ins) => ins.get_all_strings(), - Self::NotLong(ins) => ins.get_all_strings(), - Self::NegFloat(ins) => ins.get_all_strings(), - Self::NegDouble(ins) => ins.get_all_strings(), - Self::IntToLong(ins) => ins.get_all_strings(), - Self::IntToFloat(ins) => ins.get_all_strings(), - Self::IntToDouble(ins) => ins.get_all_strings(), - Self::LongToInt(ins) => ins.get_all_strings(), - Self::LongToFloat(ins) => ins.get_all_strings(), - Self::LongToDouble(ins) => ins.get_all_strings(), - Self::FloatToInt(ins) => ins.get_all_strings(), - Self::FloatToLong(ins) => ins.get_all_strings(), - Self::FloatToDouble(ins) => ins.get_all_strings(), - Self::DoubleToInt(ins) => ins.get_all_strings(), - Self::DoubleToLong(ins) => ins.get_all_strings(), - Self::DoubleToFloat(ins) => ins.get_all_strings(), - Self::IntToByte(ins) => ins.get_all_strings(), - Self::IntToChar(ins) => ins.get_all_strings(), - Self::IntToShort(ins) => ins.get_all_strings(), - Self::AddInt(ins) => ins.get_all_strings(), - Self::SubInt(ins) => ins.get_all_strings(), - Self::MulInt(ins) => ins.get_all_strings(), - Self::DivInt(ins) => ins.get_all_strings(), - Self::RemInt(ins) => ins.get_all_strings(), - Self::AndInt(ins) => ins.get_all_strings(), - Self::OrInt(ins) => ins.get_all_strings(), - Self::XorInt(ins) => ins.get_all_strings(), - Self::ShlInt(ins) => ins.get_all_strings(), - Self::ShrInt(ins) => ins.get_all_strings(), - Self::UshrInt(ins) => ins.get_all_strings(), - Self::AddLong(ins) => ins.get_all_strings(), - Self::SubLong(ins) => ins.get_all_strings(), - Self::MulLong(ins) => ins.get_all_strings(), - Self::DivLong(ins) => ins.get_all_strings(), - Self::RemLong(ins) => ins.get_all_strings(), - Self::AndLong(ins) => ins.get_all_strings(), - Self::OrLong(ins) => ins.get_all_strings(), - Self::XorLong(ins) => ins.get_all_strings(), - Self::ShlLong(ins) => ins.get_all_strings(), - Self::ShrLong(ins) => ins.get_all_strings(), - Self::UshrLong(ins) => ins.get_all_strings(), - Self::AddFloat(ins) => ins.get_all_strings(), - Self::SubFloat(ins) => ins.get_all_strings(), - Self::MulFloat(ins) => ins.get_all_strings(), - Self::DivFloat(ins) => ins.get_all_strings(), - Self::RemFloat(ins) => ins.get_all_strings(), - Self::AddDouble(ins) => ins.get_all_strings(), - Self::SubDouble(ins) => ins.get_all_strings(), - Self::MulDouble(ins) => ins.get_all_strings(), - Self::DivDouble(ins) => ins.get_all_strings(), - Self::RemDouble(ins) => ins.get_all_strings(), - Self::AddInt2Addr(ins) => ins.get_all_strings(), - Self::SubInt2Addr(ins) => ins.get_all_strings(), - Self::MulInt2Addr(ins) => ins.get_all_strings(), - Self::DivInt2Addr(ins) => ins.get_all_strings(), - Self::RemInt2Addr(ins) => ins.get_all_strings(), - Self::AndInt2Addr(ins) => ins.get_all_strings(), - Self::OrInt2Addr(ins) => ins.get_all_strings(), - Self::XorInt2Addr(ins) => ins.get_all_strings(), - Self::ShlInt2Addr(ins) => ins.get_all_strings(), - Self::ShrInt2Addr(ins) => ins.get_all_strings(), - Self::UshrInt2Addr(ins) => ins.get_all_strings(), - Self::AddLong2Addr(ins) => ins.get_all_strings(), - Self::SubLong2Addr(ins) => ins.get_all_strings(), - Self::MulLong2Addr(ins) => ins.get_all_strings(), - Self::DivLong2Addr(ins) => ins.get_all_strings(), - Self::RemLong2Addr(ins) => ins.get_all_strings(), - Self::AndLong2Addr(ins) => ins.get_all_strings(), - Self::OrLong2Addr(ins) => ins.get_all_strings(), - Self::XorLong2Addr(ins) => ins.get_all_strings(), - Self::ShlLong2Addr(ins) => ins.get_all_strings(), - Self::ShrLong2Addr(ins) => ins.get_all_strings(), - Self::UshrLong2Addr(ins) => ins.get_all_strings(), - Self::AddFloat2Addr(ins) => ins.get_all_strings(), - Self::SubFloat2Addr(ins) => ins.get_all_strings(), - Self::MulFloat2Addr(ins) => ins.get_all_strings(), - Self::DivFloat2Addr(ins) => ins.get_all_strings(), - Self::RemFloat2Addr(ins) => ins.get_all_strings(), - Self::AddDouble2Addr(ins) => ins.get_all_strings(), - Self::SubDouble2Addr(ins) => ins.get_all_strings(), - Self::MulDouble2Addr(ins) => ins.get_all_strings(), - Self::DivDouble2Addr(ins) => ins.get_all_strings(), - Self::RemDouble2Addr(ins) => ins.get_all_strings(), - Self::AddIntLit(ins) => ins.get_all_strings(), - Self::RsubIntLit(ins) => ins.get_all_strings(), - Self::MulIntLit(ins) => ins.get_all_strings(), - Self::DivIntLit(ins) => ins.get_all_strings(), - Self::RemIntLit(ins) => ins.get_all_strings(), - Self::AndIntLit(ins) => ins.get_all_strings(), - Self::OrIntLit(ins) => ins.get_all_strings(), - Self::XorIntLit(ins) => ins.get_all_strings(), - Self::ShlIntLit(ins) => ins.get_all_strings(), - Self::ShrIntLit(ins) => ins.get_all_strings(), - Self::UshrIntLit(ins) => ins.get_all_strings(), - Self::InvokePolymorphic(ins) => ins.get_all_strings(), - Self::InvokeCustom(ins) => ins.get_all_strings(), - Self::ConstMethodHandle(ins) => ins.get_all_strings(), - Self::ConstMethodType(ins) => ins.get_all_strings(), - Self::Try(ins) => ins.get_all_strings(), - Self::Label(ins) => ins.get_all_strings(), - } + let mut visitor = StringCollector::default(); + visitor.visit_instruction(self).unwrap(); + visitor.result() } /// Return all types referenced in the instruction. pub fn get_all_types(&self) -> HashSet { - match self { - Self::Nop(ins) => ins.get_all_types(), - Self::Move(ins) => ins.get_all_types(), - Self::MoveWide(ins) => ins.get_all_types(), - Self::MoveObject(ins) => ins.get_all_types(), - Self::MoveResult(ins) => ins.get_all_types(), - Self::MoveResultWide(ins) => ins.get_all_types(), - Self::MoveException(ins) => ins.get_all_types(), - Self::MoveResultObject(ins) => ins.get_all_types(), - Self::ReturnVoid(ins) => ins.get_all_types(), - Self::Return(ins) => ins.get_all_types(), - Self::ReturnWide(ins) => ins.get_all_types(), - Self::ReturnObject(ins) => ins.get_all_types(), - Self::Const(ins) => ins.get_all_types(), - Self::ConstWide(ins) => ins.get_all_types(), - Self::ConstString(ins) => ins.get_all_types(), - Self::ConstClass(ins) => ins.get_all_types(), - Self::MonitorEnter(ins) => ins.get_all_types(), - Self::MonitorExit(ins) => ins.get_all_types(), - Self::CheckCast(ins) => ins.get_all_types(), - Self::InstanceOf(ins) => ins.get_all_types(), - Self::ArrayLength(ins) => ins.get_all_types(), - Self::NewInstance(ins) => ins.get_all_types(), - Self::NewArray(ins) => ins.get_all_types(), - Self::FilledNewArray(ins) => ins.get_all_types(), - Self::FillArrayData(ins) => ins.get_all_types(), - Self::Throw(ins) => ins.get_all_types(), - Self::Goto(ins) => ins.get_all_types(), - Self::Switch(ins) => ins.get_all_types(), - Self::CmpLFloat(ins) => ins.get_all_types(), - Self::CmpGFloat(ins) => ins.get_all_types(), - Self::CmpLDouble(ins) => ins.get_all_types(), - Self::CmpGDouble(ins) => ins.get_all_types(), - Self::CmpLong(ins) => ins.get_all_types(), - Self::IfEq(ins) => ins.get_all_types(), - Self::IfNe(ins) => ins.get_all_types(), - Self::IfLt(ins) => ins.get_all_types(), - Self::IfGe(ins) => ins.get_all_types(), - Self::IfGt(ins) => ins.get_all_types(), - Self::IfLe(ins) => ins.get_all_types(), - Self::IfEqZ(ins) => ins.get_all_types(), - Self::IfNeZ(ins) => ins.get_all_types(), - Self::IfLtZ(ins) => ins.get_all_types(), - Self::IfGeZ(ins) => ins.get_all_types(), - Self::IfGtZ(ins) => ins.get_all_types(), - Self::IfLeZ(ins) => ins.get_all_types(), - Self::AGet(ins) => ins.get_all_types(), - Self::AGetWide(ins) => ins.get_all_types(), - Self::AGetObject(ins) => ins.get_all_types(), - Self::AGetBoolean(ins) => ins.get_all_types(), - Self::AGetByte(ins) => ins.get_all_types(), - Self::AGetChar(ins) => ins.get_all_types(), - Self::AGetShort(ins) => ins.get_all_types(), - Self::APut(ins) => ins.get_all_types(), - Self::APutWide(ins) => ins.get_all_types(), - Self::APutObject(ins) => ins.get_all_types(), - Self::APutBoolean(ins) => ins.get_all_types(), - Self::APutByte(ins) => ins.get_all_types(), - Self::APutChar(ins) => ins.get_all_types(), - Self::APutShort(ins) => ins.get_all_types(), - Self::IGet(ins) => ins.get_all_types(), - Self::IGetWide(ins) => ins.get_all_types(), - Self::IGetObject(ins) => ins.get_all_types(), - Self::IGetBoolean(ins) => ins.get_all_types(), - Self::IGetByte(ins) => ins.get_all_types(), - Self::IGetChar(ins) => ins.get_all_types(), - Self::IGetShort(ins) => ins.get_all_types(), - Self::IPut(ins) => ins.get_all_types(), - Self::IPutWide(ins) => ins.get_all_types(), - Self::IPutObject(ins) => ins.get_all_types(), - Self::IPutBoolean(ins) => ins.get_all_types(), - Self::IPutByte(ins) => ins.get_all_types(), - Self::IPutChar(ins) => ins.get_all_types(), - Self::IPutShort(ins) => ins.get_all_types(), - Self::SGet(ins) => ins.get_all_types(), - Self::SGetWide(ins) => ins.get_all_types(), - Self::SGetObject(ins) => ins.get_all_types(), - Self::SGetBoolean(ins) => ins.get_all_types(), - Self::SGetByte(ins) => ins.get_all_types(), - Self::SGetChar(ins) => ins.get_all_types(), - Self::SGetShort(ins) => ins.get_all_types(), - Self::SPut(ins) => ins.get_all_types(), - Self::SPutWide(ins) => ins.get_all_types(), - Self::SPutObject(ins) => ins.get_all_types(), - Self::SPutBoolean(ins) => ins.get_all_types(), - Self::SPutByte(ins) => ins.get_all_types(), - Self::SPutChar(ins) => ins.get_all_types(), - Self::SPutShort(ins) => ins.get_all_types(), - Self::InvokeVirtual(ins) => ins.get_all_types(), - Self::InvokeSuper(ins) => ins.get_all_types(), - Self::InvokeDirect(ins) => ins.get_all_types(), - Self::InvokeStatic(ins) => ins.get_all_types(), - Self::InvokeInterface(ins) => ins.get_all_types(), - Self::NegInt(ins) => ins.get_all_types(), - Self::NotInt(ins) => ins.get_all_types(), - Self::NegLong(ins) => ins.get_all_types(), - Self::NotLong(ins) => ins.get_all_types(), - Self::NegFloat(ins) => ins.get_all_types(), - Self::NegDouble(ins) => ins.get_all_types(), - Self::IntToLong(ins) => ins.get_all_types(), - Self::IntToFloat(ins) => ins.get_all_types(), - Self::IntToDouble(ins) => ins.get_all_types(), - Self::LongToInt(ins) => ins.get_all_types(), - Self::LongToFloat(ins) => ins.get_all_types(), - Self::LongToDouble(ins) => ins.get_all_types(), - Self::FloatToInt(ins) => ins.get_all_types(), - Self::FloatToLong(ins) => ins.get_all_types(), - Self::FloatToDouble(ins) => ins.get_all_types(), - Self::DoubleToInt(ins) => ins.get_all_types(), - Self::DoubleToLong(ins) => ins.get_all_types(), - Self::DoubleToFloat(ins) => ins.get_all_types(), - Self::IntToByte(ins) => ins.get_all_types(), - Self::IntToChar(ins) => ins.get_all_types(), - Self::IntToShort(ins) => ins.get_all_types(), - Self::AddInt(ins) => ins.get_all_types(), - Self::SubInt(ins) => ins.get_all_types(), - Self::MulInt(ins) => ins.get_all_types(), - Self::DivInt(ins) => ins.get_all_types(), - Self::RemInt(ins) => ins.get_all_types(), - Self::AndInt(ins) => ins.get_all_types(), - Self::OrInt(ins) => ins.get_all_types(), - Self::XorInt(ins) => ins.get_all_types(), - Self::ShlInt(ins) => ins.get_all_types(), - Self::ShrInt(ins) => ins.get_all_types(), - Self::UshrInt(ins) => ins.get_all_types(), - Self::AddLong(ins) => ins.get_all_types(), - Self::SubLong(ins) => ins.get_all_types(), - Self::MulLong(ins) => ins.get_all_types(), - Self::DivLong(ins) => ins.get_all_types(), - Self::RemLong(ins) => ins.get_all_types(), - Self::AndLong(ins) => ins.get_all_types(), - Self::OrLong(ins) => ins.get_all_types(), - Self::XorLong(ins) => ins.get_all_types(), - Self::ShlLong(ins) => ins.get_all_types(), - Self::ShrLong(ins) => ins.get_all_types(), - Self::UshrLong(ins) => ins.get_all_types(), - Self::AddFloat(ins) => ins.get_all_types(), - Self::SubFloat(ins) => ins.get_all_types(), - Self::MulFloat(ins) => ins.get_all_types(), - Self::DivFloat(ins) => ins.get_all_types(), - Self::RemFloat(ins) => ins.get_all_types(), - Self::AddDouble(ins) => ins.get_all_types(), - Self::SubDouble(ins) => ins.get_all_types(), - Self::MulDouble(ins) => ins.get_all_types(), - Self::DivDouble(ins) => ins.get_all_types(), - Self::RemDouble(ins) => ins.get_all_types(), - Self::AddInt2Addr(ins) => ins.get_all_types(), - Self::SubInt2Addr(ins) => ins.get_all_types(), - Self::MulInt2Addr(ins) => ins.get_all_types(), - Self::DivInt2Addr(ins) => ins.get_all_types(), - Self::RemInt2Addr(ins) => ins.get_all_types(), - Self::AndInt2Addr(ins) => ins.get_all_types(), - Self::OrInt2Addr(ins) => ins.get_all_types(), - Self::XorInt2Addr(ins) => ins.get_all_types(), - Self::ShlInt2Addr(ins) => ins.get_all_types(), - Self::ShrInt2Addr(ins) => ins.get_all_types(), - Self::UshrInt2Addr(ins) => ins.get_all_types(), - Self::AddLong2Addr(ins) => ins.get_all_types(), - Self::SubLong2Addr(ins) => ins.get_all_types(), - Self::MulLong2Addr(ins) => ins.get_all_types(), - Self::DivLong2Addr(ins) => ins.get_all_types(), - Self::RemLong2Addr(ins) => ins.get_all_types(), - Self::AndLong2Addr(ins) => ins.get_all_types(), - Self::OrLong2Addr(ins) => ins.get_all_types(), - Self::XorLong2Addr(ins) => ins.get_all_types(), - Self::ShlLong2Addr(ins) => ins.get_all_types(), - Self::ShrLong2Addr(ins) => ins.get_all_types(), - Self::UshrLong2Addr(ins) => ins.get_all_types(), - Self::AddFloat2Addr(ins) => ins.get_all_types(), - Self::SubFloat2Addr(ins) => ins.get_all_types(), - Self::MulFloat2Addr(ins) => ins.get_all_types(), - Self::DivFloat2Addr(ins) => ins.get_all_types(), - Self::RemFloat2Addr(ins) => ins.get_all_types(), - Self::AddDouble2Addr(ins) => ins.get_all_types(), - Self::SubDouble2Addr(ins) => ins.get_all_types(), - Self::MulDouble2Addr(ins) => ins.get_all_types(), - Self::DivDouble2Addr(ins) => ins.get_all_types(), - Self::RemDouble2Addr(ins) => ins.get_all_types(), - Self::AddIntLit(ins) => ins.get_all_types(), - Self::RsubIntLit(ins) => ins.get_all_types(), - Self::MulIntLit(ins) => ins.get_all_types(), - Self::DivIntLit(ins) => ins.get_all_types(), - Self::RemIntLit(ins) => ins.get_all_types(), - Self::AndIntLit(ins) => ins.get_all_types(), - Self::OrIntLit(ins) => ins.get_all_types(), - Self::XorIntLit(ins) => ins.get_all_types(), - Self::ShlIntLit(ins) => ins.get_all_types(), - Self::ShrIntLit(ins) => ins.get_all_types(), - Self::UshrIntLit(ins) => ins.get_all_types(), - Self::InvokePolymorphic(ins) => ins.get_all_types(), - Self::InvokeCustom(ins) => ins.get_all_types(), - Self::ConstMethodHandle(ins) => ins.get_all_types(), - Self::ConstMethodType(ins) => ins.get_all_types(), - Self::Try(ins) => ins.get_all_types(), - Self::Label(ins) => ins.get_all_types(), - } + let mut visitor = TypeCollector::default(); + visitor.visit_instruction(self).unwrap(); + visitor.result() } /// Return all prototypes referenced in the instruction. pub fn get_all_protos(&self) -> HashSet { - match self { - Self::Nop(ins) => ins.get_all_protos(), - Self::Move(ins) => ins.get_all_protos(), - Self::MoveWide(ins) => ins.get_all_protos(), - Self::MoveObject(ins) => ins.get_all_protos(), - Self::MoveResult(ins) => ins.get_all_protos(), - Self::MoveResultWide(ins) => ins.get_all_protos(), - Self::MoveException(ins) => ins.get_all_protos(), - Self::MoveResultObject(ins) => ins.get_all_protos(), - Self::ReturnVoid(ins) => ins.get_all_protos(), - Self::Return(ins) => ins.get_all_protos(), - Self::ReturnWide(ins) => ins.get_all_protos(), - Self::ReturnObject(ins) => ins.get_all_protos(), - Self::Const(ins) => ins.get_all_protos(), - Self::ConstWide(ins) => ins.get_all_protos(), - Self::ConstString(ins) => ins.get_all_protos(), - Self::ConstClass(ins) => ins.get_all_protos(), - Self::MonitorEnter(ins) => ins.get_all_protos(), - Self::MonitorExit(ins) => ins.get_all_protos(), - Self::CheckCast(ins) => ins.get_all_protos(), - Self::InstanceOf(ins) => ins.get_all_protos(), - Self::ArrayLength(ins) => ins.get_all_protos(), - Self::NewInstance(ins) => ins.get_all_protos(), - Self::NewArray(ins) => ins.get_all_protos(), - Self::FilledNewArray(ins) => ins.get_all_protos(), - Self::FillArrayData(ins) => ins.get_all_protos(), - Self::Throw(ins) => ins.get_all_protos(), - Self::Goto(ins) => ins.get_all_protos(), - Self::Switch(ins) => ins.get_all_protos(), - Self::CmpLFloat(ins) => ins.get_all_protos(), - Self::CmpGFloat(ins) => ins.get_all_protos(), - Self::CmpLDouble(ins) => ins.get_all_protos(), - Self::CmpGDouble(ins) => ins.get_all_protos(), - Self::CmpLong(ins) => ins.get_all_protos(), - Self::IfEq(ins) => ins.get_all_protos(), - Self::IfNe(ins) => ins.get_all_protos(), - Self::IfLt(ins) => ins.get_all_protos(), - Self::IfGe(ins) => ins.get_all_protos(), - Self::IfGt(ins) => ins.get_all_protos(), - Self::IfLe(ins) => ins.get_all_protos(), - Self::IfEqZ(ins) => ins.get_all_protos(), - Self::IfNeZ(ins) => ins.get_all_protos(), - Self::IfLtZ(ins) => ins.get_all_protos(), - Self::IfGeZ(ins) => ins.get_all_protos(), - Self::IfGtZ(ins) => ins.get_all_protos(), - Self::IfLeZ(ins) => ins.get_all_protos(), - Self::AGet(ins) => ins.get_all_protos(), - Self::AGetWide(ins) => ins.get_all_protos(), - Self::AGetObject(ins) => ins.get_all_protos(), - Self::AGetBoolean(ins) => ins.get_all_protos(), - Self::AGetByte(ins) => ins.get_all_protos(), - Self::AGetChar(ins) => ins.get_all_protos(), - Self::AGetShort(ins) => ins.get_all_protos(), - Self::APut(ins) => ins.get_all_protos(), - Self::APutWide(ins) => ins.get_all_protos(), - Self::APutObject(ins) => ins.get_all_protos(), - Self::APutBoolean(ins) => ins.get_all_protos(), - Self::APutByte(ins) => ins.get_all_protos(), - Self::APutChar(ins) => ins.get_all_protos(), - Self::APutShort(ins) => ins.get_all_protos(), - Self::IGet(ins) => ins.get_all_protos(), - Self::IGetWide(ins) => ins.get_all_protos(), - Self::IGetObject(ins) => ins.get_all_protos(), - Self::IGetBoolean(ins) => ins.get_all_protos(), - Self::IGetByte(ins) => ins.get_all_protos(), - Self::IGetChar(ins) => ins.get_all_protos(), - Self::IGetShort(ins) => ins.get_all_protos(), - Self::IPut(ins) => ins.get_all_protos(), - Self::IPutWide(ins) => ins.get_all_protos(), - Self::IPutObject(ins) => ins.get_all_protos(), - Self::IPutBoolean(ins) => ins.get_all_protos(), - Self::IPutByte(ins) => ins.get_all_protos(), - Self::IPutChar(ins) => ins.get_all_protos(), - Self::IPutShort(ins) => ins.get_all_protos(), - Self::SGet(ins) => ins.get_all_protos(), - Self::SGetWide(ins) => ins.get_all_protos(), - Self::SGetObject(ins) => ins.get_all_protos(), - Self::SGetBoolean(ins) => ins.get_all_protos(), - Self::SGetByte(ins) => ins.get_all_protos(), - Self::SGetChar(ins) => ins.get_all_protos(), - Self::SGetShort(ins) => ins.get_all_protos(), - Self::SPut(ins) => ins.get_all_protos(), - Self::SPutWide(ins) => ins.get_all_protos(), - Self::SPutObject(ins) => ins.get_all_protos(), - Self::SPutBoolean(ins) => ins.get_all_protos(), - Self::SPutByte(ins) => ins.get_all_protos(), - Self::SPutChar(ins) => ins.get_all_protos(), - Self::SPutShort(ins) => ins.get_all_protos(), - Self::InvokeVirtual(ins) => ins.get_all_protos(), - Self::InvokeSuper(ins) => ins.get_all_protos(), - Self::InvokeDirect(ins) => ins.get_all_protos(), - Self::InvokeStatic(ins) => ins.get_all_protos(), - Self::InvokeInterface(ins) => ins.get_all_protos(), - Self::NegInt(ins) => ins.get_all_protos(), - Self::NotInt(ins) => ins.get_all_protos(), - Self::NegLong(ins) => ins.get_all_protos(), - Self::NotLong(ins) => ins.get_all_protos(), - Self::NegFloat(ins) => ins.get_all_protos(), - Self::NegDouble(ins) => ins.get_all_protos(), - Self::IntToLong(ins) => ins.get_all_protos(), - Self::IntToFloat(ins) => ins.get_all_protos(), - Self::IntToDouble(ins) => ins.get_all_protos(), - Self::LongToInt(ins) => ins.get_all_protos(), - Self::LongToFloat(ins) => ins.get_all_protos(), - Self::LongToDouble(ins) => ins.get_all_protos(), - Self::FloatToInt(ins) => ins.get_all_protos(), - Self::FloatToLong(ins) => ins.get_all_protos(), - Self::FloatToDouble(ins) => ins.get_all_protos(), - Self::DoubleToInt(ins) => ins.get_all_protos(), - Self::DoubleToLong(ins) => ins.get_all_protos(), - Self::DoubleToFloat(ins) => ins.get_all_protos(), - Self::IntToByte(ins) => ins.get_all_protos(), - Self::IntToChar(ins) => ins.get_all_protos(), - Self::IntToShort(ins) => ins.get_all_protos(), - Self::AddInt(ins) => ins.get_all_protos(), - Self::SubInt(ins) => ins.get_all_protos(), - Self::MulInt(ins) => ins.get_all_protos(), - Self::DivInt(ins) => ins.get_all_protos(), - Self::RemInt(ins) => ins.get_all_protos(), - Self::AndInt(ins) => ins.get_all_protos(), - Self::OrInt(ins) => ins.get_all_protos(), - Self::XorInt(ins) => ins.get_all_protos(), - Self::ShlInt(ins) => ins.get_all_protos(), - Self::ShrInt(ins) => ins.get_all_protos(), - Self::UshrInt(ins) => ins.get_all_protos(), - Self::AddLong(ins) => ins.get_all_protos(), - Self::SubLong(ins) => ins.get_all_protos(), - Self::MulLong(ins) => ins.get_all_protos(), - Self::DivLong(ins) => ins.get_all_protos(), - Self::RemLong(ins) => ins.get_all_protos(), - Self::AndLong(ins) => ins.get_all_protos(), - Self::OrLong(ins) => ins.get_all_protos(), - Self::XorLong(ins) => ins.get_all_protos(), - Self::ShlLong(ins) => ins.get_all_protos(), - Self::ShrLong(ins) => ins.get_all_protos(), - Self::UshrLong(ins) => ins.get_all_protos(), - Self::AddFloat(ins) => ins.get_all_protos(), - Self::SubFloat(ins) => ins.get_all_protos(), - Self::MulFloat(ins) => ins.get_all_protos(), - Self::DivFloat(ins) => ins.get_all_protos(), - Self::RemFloat(ins) => ins.get_all_protos(), - Self::AddDouble(ins) => ins.get_all_protos(), - Self::SubDouble(ins) => ins.get_all_protos(), - Self::MulDouble(ins) => ins.get_all_protos(), - Self::DivDouble(ins) => ins.get_all_protos(), - Self::RemDouble(ins) => ins.get_all_protos(), - Self::AddInt2Addr(ins) => ins.get_all_protos(), - Self::SubInt2Addr(ins) => ins.get_all_protos(), - Self::MulInt2Addr(ins) => ins.get_all_protos(), - Self::DivInt2Addr(ins) => ins.get_all_protos(), - Self::RemInt2Addr(ins) => ins.get_all_protos(), - Self::AndInt2Addr(ins) => ins.get_all_protos(), - Self::OrInt2Addr(ins) => ins.get_all_protos(), - Self::XorInt2Addr(ins) => ins.get_all_protos(), - Self::ShlInt2Addr(ins) => ins.get_all_protos(), - Self::ShrInt2Addr(ins) => ins.get_all_protos(), - Self::UshrInt2Addr(ins) => ins.get_all_protos(), - Self::AddLong2Addr(ins) => ins.get_all_protos(), - Self::SubLong2Addr(ins) => ins.get_all_protos(), - Self::MulLong2Addr(ins) => ins.get_all_protos(), - Self::DivLong2Addr(ins) => ins.get_all_protos(), - Self::RemLong2Addr(ins) => ins.get_all_protos(), - Self::AndLong2Addr(ins) => ins.get_all_protos(), - Self::OrLong2Addr(ins) => ins.get_all_protos(), - Self::XorLong2Addr(ins) => ins.get_all_protos(), - Self::ShlLong2Addr(ins) => ins.get_all_protos(), - Self::ShrLong2Addr(ins) => ins.get_all_protos(), - Self::UshrLong2Addr(ins) => ins.get_all_protos(), - Self::AddFloat2Addr(ins) => ins.get_all_protos(), - Self::SubFloat2Addr(ins) => ins.get_all_protos(), - Self::MulFloat2Addr(ins) => ins.get_all_protos(), - Self::DivFloat2Addr(ins) => ins.get_all_protos(), - Self::RemFloat2Addr(ins) => ins.get_all_protos(), - Self::AddDouble2Addr(ins) => ins.get_all_protos(), - Self::SubDouble2Addr(ins) => ins.get_all_protos(), - Self::MulDouble2Addr(ins) => ins.get_all_protos(), - Self::DivDouble2Addr(ins) => ins.get_all_protos(), - Self::RemDouble2Addr(ins) => ins.get_all_protos(), - Self::AddIntLit(ins) => ins.get_all_protos(), - Self::RsubIntLit(ins) => ins.get_all_protos(), - Self::MulIntLit(ins) => ins.get_all_protos(), - Self::DivIntLit(ins) => ins.get_all_protos(), - Self::RemIntLit(ins) => ins.get_all_protos(), - Self::AndIntLit(ins) => ins.get_all_protos(), - Self::OrIntLit(ins) => ins.get_all_protos(), - Self::XorIntLit(ins) => ins.get_all_protos(), - Self::ShlIntLit(ins) => ins.get_all_protos(), - Self::ShrIntLit(ins) => ins.get_all_protos(), - Self::UshrIntLit(ins) => ins.get_all_protos(), - Self::InvokePolymorphic(ins) => ins.get_all_protos(), - Self::InvokeCustom(ins) => ins.get_all_protos(), - Self::ConstMethodHandle(ins) => ins.get_all_protos(), - Self::ConstMethodType(ins) => ins.get_all_protos(), - Self::Try(ins) => ins.get_all_protos(), - Self::Label(ins) => ins.get_all_protos(), - } + let mut visitor = MethodTypeCollector::default(); + visitor.visit_instruction(self).unwrap(); + visitor.result() } /// Return all field ids referenced in the instruction. pub fn get_all_field_ids(&self) -> HashSet { - match self { - Self::Nop(ins) => ins.get_all_field_ids(), - Self::Move(ins) => ins.get_all_field_ids(), - Self::MoveWide(ins) => ins.get_all_field_ids(), - Self::MoveObject(ins) => ins.get_all_field_ids(), - Self::MoveResult(ins) => ins.get_all_field_ids(), - Self::MoveResultWide(ins) => ins.get_all_field_ids(), - Self::MoveException(ins) => ins.get_all_field_ids(), - Self::MoveResultObject(ins) => ins.get_all_field_ids(), - Self::ReturnVoid(ins) => ins.get_all_field_ids(), - Self::Return(ins) => ins.get_all_field_ids(), - Self::ReturnWide(ins) => ins.get_all_field_ids(), - Self::ReturnObject(ins) => ins.get_all_field_ids(), - Self::Const(ins) => ins.get_all_field_ids(), - Self::ConstWide(ins) => ins.get_all_field_ids(), - Self::ConstString(ins) => ins.get_all_field_ids(), - Self::ConstClass(ins) => ins.get_all_field_ids(), - Self::MonitorEnter(ins) => ins.get_all_field_ids(), - Self::MonitorExit(ins) => ins.get_all_field_ids(), - Self::CheckCast(ins) => ins.get_all_field_ids(), - Self::InstanceOf(ins) => ins.get_all_field_ids(), - Self::ArrayLength(ins) => ins.get_all_field_ids(), - Self::NewInstance(ins) => ins.get_all_field_ids(), - Self::NewArray(ins) => ins.get_all_field_ids(), - Self::FilledNewArray(ins) => ins.get_all_field_ids(), - Self::FillArrayData(ins) => ins.get_all_field_ids(), - Self::Throw(ins) => ins.get_all_field_ids(), - Self::Goto(ins) => ins.get_all_field_ids(), - Self::Switch(ins) => ins.get_all_field_ids(), - Self::CmpLFloat(ins) => ins.get_all_field_ids(), - Self::CmpGFloat(ins) => ins.get_all_field_ids(), - Self::CmpLDouble(ins) => ins.get_all_field_ids(), - Self::CmpGDouble(ins) => ins.get_all_field_ids(), - Self::CmpLong(ins) => ins.get_all_field_ids(), - Self::IfEq(ins) => ins.get_all_field_ids(), - Self::IfNe(ins) => ins.get_all_field_ids(), - Self::IfLt(ins) => ins.get_all_field_ids(), - Self::IfGe(ins) => ins.get_all_field_ids(), - Self::IfGt(ins) => ins.get_all_field_ids(), - Self::IfLe(ins) => ins.get_all_field_ids(), - Self::IfEqZ(ins) => ins.get_all_field_ids(), - Self::IfNeZ(ins) => ins.get_all_field_ids(), - Self::IfLtZ(ins) => ins.get_all_field_ids(), - Self::IfGeZ(ins) => ins.get_all_field_ids(), - Self::IfGtZ(ins) => ins.get_all_field_ids(), - Self::IfLeZ(ins) => ins.get_all_field_ids(), - Self::AGet(ins) => ins.get_all_field_ids(), - Self::AGetWide(ins) => ins.get_all_field_ids(), - Self::AGetObject(ins) => ins.get_all_field_ids(), - Self::AGetBoolean(ins) => ins.get_all_field_ids(), - Self::AGetByte(ins) => ins.get_all_field_ids(), - Self::AGetChar(ins) => ins.get_all_field_ids(), - Self::AGetShort(ins) => ins.get_all_field_ids(), - Self::APut(ins) => ins.get_all_field_ids(), - Self::APutWide(ins) => ins.get_all_field_ids(), - Self::APutObject(ins) => ins.get_all_field_ids(), - Self::APutBoolean(ins) => ins.get_all_field_ids(), - Self::APutByte(ins) => ins.get_all_field_ids(), - Self::APutChar(ins) => ins.get_all_field_ids(), - Self::APutShort(ins) => ins.get_all_field_ids(), - Self::IGet(ins) => ins.get_all_field_ids(), - Self::IGetWide(ins) => ins.get_all_field_ids(), - Self::IGetObject(ins) => ins.get_all_field_ids(), - Self::IGetBoolean(ins) => ins.get_all_field_ids(), - Self::IGetByte(ins) => ins.get_all_field_ids(), - Self::IGetChar(ins) => ins.get_all_field_ids(), - Self::IGetShort(ins) => ins.get_all_field_ids(), - Self::IPut(ins) => ins.get_all_field_ids(), - Self::IPutWide(ins) => ins.get_all_field_ids(), - Self::IPutObject(ins) => ins.get_all_field_ids(), - Self::IPutBoolean(ins) => ins.get_all_field_ids(), - Self::IPutByte(ins) => ins.get_all_field_ids(), - Self::IPutChar(ins) => ins.get_all_field_ids(), - Self::IPutShort(ins) => ins.get_all_field_ids(), - Self::SGet(ins) => ins.get_all_field_ids(), - Self::SGetWide(ins) => ins.get_all_field_ids(), - Self::SGetObject(ins) => ins.get_all_field_ids(), - Self::SGetBoolean(ins) => ins.get_all_field_ids(), - Self::SGetByte(ins) => ins.get_all_field_ids(), - Self::SGetChar(ins) => ins.get_all_field_ids(), - Self::SGetShort(ins) => ins.get_all_field_ids(), - Self::SPut(ins) => ins.get_all_field_ids(), - Self::SPutWide(ins) => ins.get_all_field_ids(), - Self::SPutObject(ins) => ins.get_all_field_ids(), - Self::SPutBoolean(ins) => ins.get_all_field_ids(), - Self::SPutByte(ins) => ins.get_all_field_ids(), - Self::SPutChar(ins) => ins.get_all_field_ids(), - Self::SPutShort(ins) => ins.get_all_field_ids(), - Self::InvokeVirtual(ins) => ins.get_all_field_ids(), - Self::InvokeSuper(ins) => ins.get_all_field_ids(), - Self::InvokeDirect(ins) => ins.get_all_field_ids(), - Self::InvokeStatic(ins) => ins.get_all_field_ids(), - Self::InvokeInterface(ins) => ins.get_all_field_ids(), - Self::NegInt(ins) => ins.get_all_field_ids(), - Self::NotInt(ins) => ins.get_all_field_ids(), - Self::NegLong(ins) => ins.get_all_field_ids(), - Self::NotLong(ins) => ins.get_all_field_ids(), - Self::NegFloat(ins) => ins.get_all_field_ids(), - Self::NegDouble(ins) => ins.get_all_field_ids(), - Self::IntToLong(ins) => ins.get_all_field_ids(), - Self::IntToFloat(ins) => ins.get_all_field_ids(), - Self::IntToDouble(ins) => ins.get_all_field_ids(), - Self::LongToInt(ins) => ins.get_all_field_ids(), - Self::LongToFloat(ins) => ins.get_all_field_ids(), - Self::LongToDouble(ins) => ins.get_all_field_ids(), - Self::FloatToInt(ins) => ins.get_all_field_ids(), - Self::FloatToLong(ins) => ins.get_all_field_ids(), - Self::FloatToDouble(ins) => ins.get_all_field_ids(), - Self::DoubleToInt(ins) => ins.get_all_field_ids(), - Self::DoubleToLong(ins) => ins.get_all_field_ids(), - Self::DoubleToFloat(ins) => ins.get_all_field_ids(), - Self::IntToByte(ins) => ins.get_all_field_ids(), - Self::IntToChar(ins) => ins.get_all_field_ids(), - Self::IntToShort(ins) => ins.get_all_field_ids(), - Self::AddInt(ins) => ins.get_all_field_ids(), - Self::SubInt(ins) => ins.get_all_field_ids(), - Self::MulInt(ins) => ins.get_all_field_ids(), - Self::DivInt(ins) => ins.get_all_field_ids(), - Self::RemInt(ins) => ins.get_all_field_ids(), - Self::AndInt(ins) => ins.get_all_field_ids(), - Self::OrInt(ins) => ins.get_all_field_ids(), - Self::XorInt(ins) => ins.get_all_field_ids(), - Self::ShlInt(ins) => ins.get_all_field_ids(), - Self::ShrInt(ins) => ins.get_all_field_ids(), - Self::UshrInt(ins) => ins.get_all_field_ids(), - Self::AddLong(ins) => ins.get_all_field_ids(), - Self::SubLong(ins) => ins.get_all_field_ids(), - Self::MulLong(ins) => ins.get_all_field_ids(), - Self::DivLong(ins) => ins.get_all_field_ids(), - Self::RemLong(ins) => ins.get_all_field_ids(), - Self::AndLong(ins) => ins.get_all_field_ids(), - Self::OrLong(ins) => ins.get_all_field_ids(), - Self::XorLong(ins) => ins.get_all_field_ids(), - Self::ShlLong(ins) => ins.get_all_field_ids(), - Self::ShrLong(ins) => ins.get_all_field_ids(), - Self::UshrLong(ins) => ins.get_all_field_ids(), - Self::AddFloat(ins) => ins.get_all_field_ids(), - Self::SubFloat(ins) => ins.get_all_field_ids(), - Self::MulFloat(ins) => ins.get_all_field_ids(), - Self::DivFloat(ins) => ins.get_all_field_ids(), - Self::RemFloat(ins) => ins.get_all_field_ids(), - Self::AddDouble(ins) => ins.get_all_field_ids(), - Self::SubDouble(ins) => ins.get_all_field_ids(), - Self::MulDouble(ins) => ins.get_all_field_ids(), - Self::DivDouble(ins) => ins.get_all_field_ids(), - Self::RemDouble(ins) => ins.get_all_field_ids(), - Self::AddInt2Addr(ins) => ins.get_all_field_ids(), - Self::SubInt2Addr(ins) => ins.get_all_field_ids(), - Self::MulInt2Addr(ins) => ins.get_all_field_ids(), - Self::DivInt2Addr(ins) => ins.get_all_field_ids(), - Self::RemInt2Addr(ins) => ins.get_all_field_ids(), - Self::AndInt2Addr(ins) => ins.get_all_field_ids(), - Self::OrInt2Addr(ins) => ins.get_all_field_ids(), - Self::XorInt2Addr(ins) => ins.get_all_field_ids(), - Self::ShlInt2Addr(ins) => ins.get_all_field_ids(), - Self::ShrInt2Addr(ins) => ins.get_all_field_ids(), - Self::UshrInt2Addr(ins) => ins.get_all_field_ids(), - Self::AddLong2Addr(ins) => ins.get_all_field_ids(), - Self::SubLong2Addr(ins) => ins.get_all_field_ids(), - Self::MulLong2Addr(ins) => ins.get_all_field_ids(), - Self::DivLong2Addr(ins) => ins.get_all_field_ids(), - Self::RemLong2Addr(ins) => ins.get_all_field_ids(), - Self::AndLong2Addr(ins) => ins.get_all_field_ids(), - Self::OrLong2Addr(ins) => ins.get_all_field_ids(), - Self::XorLong2Addr(ins) => ins.get_all_field_ids(), - Self::ShlLong2Addr(ins) => ins.get_all_field_ids(), - Self::ShrLong2Addr(ins) => ins.get_all_field_ids(), - Self::UshrLong2Addr(ins) => ins.get_all_field_ids(), - Self::AddFloat2Addr(ins) => ins.get_all_field_ids(), - Self::SubFloat2Addr(ins) => ins.get_all_field_ids(), - Self::MulFloat2Addr(ins) => ins.get_all_field_ids(), - Self::DivFloat2Addr(ins) => ins.get_all_field_ids(), - Self::RemFloat2Addr(ins) => ins.get_all_field_ids(), - Self::AddDouble2Addr(ins) => ins.get_all_field_ids(), - Self::SubDouble2Addr(ins) => ins.get_all_field_ids(), - Self::MulDouble2Addr(ins) => ins.get_all_field_ids(), - Self::DivDouble2Addr(ins) => ins.get_all_field_ids(), - Self::RemDouble2Addr(ins) => ins.get_all_field_ids(), - Self::AddIntLit(ins) => ins.get_all_field_ids(), - Self::RsubIntLit(ins) => ins.get_all_field_ids(), - Self::MulIntLit(ins) => ins.get_all_field_ids(), - Self::DivIntLit(ins) => ins.get_all_field_ids(), - Self::RemIntLit(ins) => ins.get_all_field_ids(), - Self::AndIntLit(ins) => ins.get_all_field_ids(), - Self::OrIntLit(ins) => ins.get_all_field_ids(), - Self::XorIntLit(ins) => ins.get_all_field_ids(), - Self::ShlIntLit(ins) => ins.get_all_field_ids(), - Self::ShrIntLit(ins) => ins.get_all_field_ids(), - Self::UshrIntLit(ins) => ins.get_all_field_ids(), - Self::InvokePolymorphic(ins) => ins.get_all_field_ids(), - Self::InvokeCustom(ins) => ins.get_all_field_ids(), - Self::ConstMethodHandle(ins) => ins.get_all_field_ids(), - Self::ConstMethodType(ins) => ins.get_all_field_ids(), - Self::Try(ins) => ins.get_all_field_ids(), - Self::Label(ins) => ins.get_all_field_ids(), - } + let mut visitor = FieldIdCollector::default(); + visitor.visit_instruction(self).unwrap(); + visitor.result() } /// Return all method ids referenced in the instruction. pub fn get_all_method_ids(&self) -> HashSet { - match self { - Self::Nop(ins) => ins.get_all_method_ids(), - Self::Move(ins) => ins.get_all_method_ids(), - Self::MoveWide(ins) => ins.get_all_method_ids(), - Self::MoveObject(ins) => ins.get_all_method_ids(), - Self::MoveResult(ins) => ins.get_all_method_ids(), - Self::MoveResultWide(ins) => ins.get_all_method_ids(), - Self::MoveException(ins) => ins.get_all_method_ids(), - Self::MoveResultObject(ins) => ins.get_all_method_ids(), - Self::ReturnVoid(ins) => ins.get_all_method_ids(), - Self::Return(ins) => ins.get_all_method_ids(), - Self::ReturnWide(ins) => ins.get_all_method_ids(), - Self::ReturnObject(ins) => ins.get_all_method_ids(), - Self::Const(ins) => ins.get_all_method_ids(), - Self::ConstWide(ins) => ins.get_all_method_ids(), - Self::ConstString(ins) => ins.get_all_method_ids(), - Self::ConstClass(ins) => ins.get_all_method_ids(), - Self::MonitorEnter(ins) => ins.get_all_method_ids(), - Self::MonitorExit(ins) => ins.get_all_method_ids(), - Self::CheckCast(ins) => ins.get_all_method_ids(), - Self::InstanceOf(ins) => ins.get_all_method_ids(), - Self::ArrayLength(ins) => ins.get_all_method_ids(), - Self::NewInstance(ins) => ins.get_all_method_ids(), - Self::NewArray(ins) => ins.get_all_method_ids(), - Self::FilledNewArray(ins) => ins.get_all_method_ids(), - Self::FillArrayData(ins) => ins.get_all_method_ids(), - Self::Throw(ins) => ins.get_all_method_ids(), - Self::Goto(ins) => ins.get_all_method_ids(), - Self::Switch(ins) => ins.get_all_method_ids(), - Self::CmpLFloat(ins) => ins.get_all_method_ids(), - Self::CmpGFloat(ins) => ins.get_all_method_ids(), - Self::CmpLDouble(ins) => ins.get_all_method_ids(), - Self::CmpGDouble(ins) => ins.get_all_method_ids(), - Self::CmpLong(ins) => ins.get_all_method_ids(), - Self::IfEq(ins) => ins.get_all_method_ids(), - Self::IfNe(ins) => ins.get_all_method_ids(), - Self::IfLt(ins) => ins.get_all_method_ids(), - Self::IfGe(ins) => ins.get_all_method_ids(), - Self::IfGt(ins) => ins.get_all_method_ids(), - Self::IfLe(ins) => ins.get_all_method_ids(), - Self::IfEqZ(ins) => ins.get_all_method_ids(), - Self::IfNeZ(ins) => ins.get_all_method_ids(), - Self::IfLtZ(ins) => ins.get_all_method_ids(), - Self::IfGeZ(ins) => ins.get_all_method_ids(), - Self::IfGtZ(ins) => ins.get_all_method_ids(), - Self::IfLeZ(ins) => ins.get_all_method_ids(), - Self::AGet(ins) => ins.get_all_method_ids(), - Self::AGetWide(ins) => ins.get_all_method_ids(), - Self::AGetObject(ins) => ins.get_all_method_ids(), - Self::AGetBoolean(ins) => ins.get_all_method_ids(), - Self::AGetByte(ins) => ins.get_all_method_ids(), - Self::AGetChar(ins) => ins.get_all_method_ids(), - Self::AGetShort(ins) => ins.get_all_method_ids(), - Self::APut(ins) => ins.get_all_method_ids(), - Self::APutWide(ins) => ins.get_all_method_ids(), - Self::APutObject(ins) => ins.get_all_method_ids(), - Self::APutBoolean(ins) => ins.get_all_method_ids(), - Self::APutByte(ins) => ins.get_all_method_ids(), - Self::APutChar(ins) => ins.get_all_method_ids(), - Self::APutShort(ins) => ins.get_all_method_ids(), - Self::IGet(ins) => ins.get_all_method_ids(), - Self::IGetWide(ins) => ins.get_all_method_ids(), - Self::IGetObject(ins) => ins.get_all_method_ids(), - Self::IGetBoolean(ins) => ins.get_all_method_ids(), - Self::IGetByte(ins) => ins.get_all_method_ids(), - Self::IGetChar(ins) => ins.get_all_method_ids(), - Self::IGetShort(ins) => ins.get_all_method_ids(), - Self::IPut(ins) => ins.get_all_method_ids(), - Self::IPutWide(ins) => ins.get_all_method_ids(), - Self::IPutObject(ins) => ins.get_all_method_ids(), - Self::IPutBoolean(ins) => ins.get_all_method_ids(), - Self::IPutByte(ins) => ins.get_all_method_ids(), - Self::IPutChar(ins) => ins.get_all_method_ids(), - Self::IPutShort(ins) => ins.get_all_method_ids(), - Self::SGet(ins) => ins.get_all_method_ids(), - Self::SGetWide(ins) => ins.get_all_method_ids(), - Self::SGetObject(ins) => ins.get_all_method_ids(), - Self::SGetBoolean(ins) => ins.get_all_method_ids(), - Self::SGetByte(ins) => ins.get_all_method_ids(), - Self::SGetChar(ins) => ins.get_all_method_ids(), - Self::SGetShort(ins) => ins.get_all_method_ids(), - Self::SPut(ins) => ins.get_all_method_ids(), - Self::SPutWide(ins) => ins.get_all_method_ids(), - Self::SPutObject(ins) => ins.get_all_method_ids(), - Self::SPutBoolean(ins) => ins.get_all_method_ids(), - Self::SPutByte(ins) => ins.get_all_method_ids(), - Self::SPutChar(ins) => ins.get_all_method_ids(), - Self::SPutShort(ins) => ins.get_all_method_ids(), - Self::InvokeVirtual(ins) => ins.get_all_method_ids(), - Self::InvokeSuper(ins) => ins.get_all_method_ids(), - Self::InvokeDirect(ins) => ins.get_all_method_ids(), - Self::InvokeStatic(ins) => ins.get_all_method_ids(), - Self::InvokeInterface(ins) => ins.get_all_method_ids(), - Self::NegInt(ins) => ins.get_all_method_ids(), - Self::NotInt(ins) => ins.get_all_method_ids(), - Self::NegLong(ins) => ins.get_all_method_ids(), - Self::NotLong(ins) => ins.get_all_method_ids(), - Self::NegFloat(ins) => ins.get_all_method_ids(), - Self::NegDouble(ins) => ins.get_all_method_ids(), - Self::IntToLong(ins) => ins.get_all_method_ids(), - Self::IntToFloat(ins) => ins.get_all_method_ids(), - Self::IntToDouble(ins) => ins.get_all_method_ids(), - Self::LongToInt(ins) => ins.get_all_method_ids(), - Self::LongToFloat(ins) => ins.get_all_method_ids(), - Self::LongToDouble(ins) => ins.get_all_method_ids(), - Self::FloatToInt(ins) => ins.get_all_method_ids(), - Self::FloatToLong(ins) => ins.get_all_method_ids(), - Self::FloatToDouble(ins) => ins.get_all_method_ids(), - Self::DoubleToInt(ins) => ins.get_all_method_ids(), - Self::DoubleToLong(ins) => ins.get_all_method_ids(), - Self::DoubleToFloat(ins) => ins.get_all_method_ids(), - Self::IntToByte(ins) => ins.get_all_method_ids(), - Self::IntToChar(ins) => ins.get_all_method_ids(), - Self::IntToShort(ins) => ins.get_all_method_ids(), - Self::AddInt(ins) => ins.get_all_method_ids(), - Self::SubInt(ins) => ins.get_all_method_ids(), - Self::MulInt(ins) => ins.get_all_method_ids(), - Self::DivInt(ins) => ins.get_all_method_ids(), - Self::RemInt(ins) => ins.get_all_method_ids(), - Self::AndInt(ins) => ins.get_all_method_ids(), - Self::OrInt(ins) => ins.get_all_method_ids(), - Self::XorInt(ins) => ins.get_all_method_ids(), - Self::ShlInt(ins) => ins.get_all_method_ids(), - Self::ShrInt(ins) => ins.get_all_method_ids(), - Self::UshrInt(ins) => ins.get_all_method_ids(), - Self::AddLong(ins) => ins.get_all_method_ids(), - Self::SubLong(ins) => ins.get_all_method_ids(), - Self::MulLong(ins) => ins.get_all_method_ids(), - Self::DivLong(ins) => ins.get_all_method_ids(), - Self::RemLong(ins) => ins.get_all_method_ids(), - Self::AndLong(ins) => ins.get_all_method_ids(), - Self::OrLong(ins) => ins.get_all_method_ids(), - Self::XorLong(ins) => ins.get_all_method_ids(), - Self::ShlLong(ins) => ins.get_all_method_ids(), - Self::ShrLong(ins) => ins.get_all_method_ids(), - Self::UshrLong(ins) => ins.get_all_method_ids(), - Self::AddFloat(ins) => ins.get_all_method_ids(), - Self::SubFloat(ins) => ins.get_all_method_ids(), - Self::MulFloat(ins) => ins.get_all_method_ids(), - Self::DivFloat(ins) => ins.get_all_method_ids(), - Self::RemFloat(ins) => ins.get_all_method_ids(), - Self::AddDouble(ins) => ins.get_all_method_ids(), - Self::SubDouble(ins) => ins.get_all_method_ids(), - Self::MulDouble(ins) => ins.get_all_method_ids(), - Self::DivDouble(ins) => ins.get_all_method_ids(), - Self::RemDouble(ins) => ins.get_all_method_ids(), - Self::AddInt2Addr(ins) => ins.get_all_method_ids(), - Self::SubInt2Addr(ins) => ins.get_all_method_ids(), - Self::MulInt2Addr(ins) => ins.get_all_method_ids(), - Self::DivInt2Addr(ins) => ins.get_all_method_ids(), - Self::RemInt2Addr(ins) => ins.get_all_method_ids(), - Self::AndInt2Addr(ins) => ins.get_all_method_ids(), - Self::OrInt2Addr(ins) => ins.get_all_method_ids(), - Self::XorInt2Addr(ins) => ins.get_all_method_ids(), - Self::ShlInt2Addr(ins) => ins.get_all_method_ids(), - Self::ShrInt2Addr(ins) => ins.get_all_method_ids(), - Self::UshrInt2Addr(ins) => ins.get_all_method_ids(), - Self::AddLong2Addr(ins) => ins.get_all_method_ids(), - Self::SubLong2Addr(ins) => ins.get_all_method_ids(), - Self::MulLong2Addr(ins) => ins.get_all_method_ids(), - Self::DivLong2Addr(ins) => ins.get_all_method_ids(), - Self::RemLong2Addr(ins) => ins.get_all_method_ids(), - Self::AndLong2Addr(ins) => ins.get_all_method_ids(), - Self::OrLong2Addr(ins) => ins.get_all_method_ids(), - Self::XorLong2Addr(ins) => ins.get_all_method_ids(), - Self::ShlLong2Addr(ins) => ins.get_all_method_ids(), - Self::ShrLong2Addr(ins) => ins.get_all_method_ids(), - Self::UshrLong2Addr(ins) => ins.get_all_method_ids(), - Self::AddFloat2Addr(ins) => ins.get_all_method_ids(), - Self::SubFloat2Addr(ins) => ins.get_all_method_ids(), - Self::MulFloat2Addr(ins) => ins.get_all_method_ids(), - Self::DivFloat2Addr(ins) => ins.get_all_method_ids(), - Self::RemFloat2Addr(ins) => ins.get_all_method_ids(), - Self::AddDouble2Addr(ins) => ins.get_all_method_ids(), - Self::SubDouble2Addr(ins) => ins.get_all_method_ids(), - Self::MulDouble2Addr(ins) => ins.get_all_method_ids(), - Self::DivDouble2Addr(ins) => ins.get_all_method_ids(), - Self::RemDouble2Addr(ins) => ins.get_all_method_ids(), - Self::AddIntLit(ins) => ins.get_all_method_ids(), - Self::RsubIntLit(ins) => ins.get_all_method_ids(), - Self::MulIntLit(ins) => ins.get_all_method_ids(), - Self::DivIntLit(ins) => ins.get_all_method_ids(), - Self::RemIntLit(ins) => ins.get_all_method_ids(), - Self::AndIntLit(ins) => ins.get_all_method_ids(), - Self::OrIntLit(ins) => ins.get_all_method_ids(), - Self::XorIntLit(ins) => ins.get_all_method_ids(), - Self::ShlIntLit(ins) => ins.get_all_method_ids(), - Self::ShrIntLit(ins) => ins.get_all_method_ids(), - Self::UshrIntLit(ins) => ins.get_all_method_ids(), - Self::InvokePolymorphic(ins) => ins.get_all_method_ids(), - Self::InvokeCustom(ins) => ins.get_all_method_ids(), - Self::ConstMethodHandle(ins) => ins.get_all_method_ids(), - Self::ConstMethodType(ins) => ins.get_all_method_ids(), - Self::Try(ins) => ins.get_all_method_ids(), - Self::Label(ins) => ins.get_all_method_ids(), - } + let mut visitor = MethodIdCollector::default(); + visitor.visit_instruction(self).unwrap(); + visitor.result() } /// Return all method handles referenced in the instruction. pub fn get_all_method_handles(&self) -> HashSet { - match self { - Self::Nop(ins) => ins.get_all_method_handles(), - Self::Move(ins) => ins.get_all_method_handles(), - Self::MoveWide(ins) => ins.get_all_method_handles(), - Self::MoveObject(ins) => ins.get_all_method_handles(), - Self::MoveResult(ins) => ins.get_all_method_handles(), - Self::MoveResultWide(ins) => ins.get_all_method_handles(), - Self::MoveException(ins) => ins.get_all_method_handles(), - Self::MoveResultObject(ins) => ins.get_all_method_handles(), - Self::ReturnVoid(ins) => ins.get_all_method_handles(), - Self::Return(ins) => ins.get_all_method_handles(), - Self::ReturnWide(ins) => ins.get_all_method_handles(), - Self::ReturnObject(ins) => ins.get_all_method_handles(), - Self::Const(ins) => ins.get_all_method_handles(), - Self::ConstWide(ins) => ins.get_all_method_handles(), - Self::ConstString(ins) => ins.get_all_method_handles(), - Self::ConstClass(ins) => ins.get_all_method_handles(), - Self::MonitorEnter(ins) => ins.get_all_method_handles(), - Self::MonitorExit(ins) => ins.get_all_method_handles(), - Self::CheckCast(ins) => ins.get_all_method_handles(), - Self::InstanceOf(ins) => ins.get_all_method_handles(), - Self::ArrayLength(ins) => ins.get_all_method_handles(), - Self::NewInstance(ins) => ins.get_all_method_handles(), - Self::NewArray(ins) => ins.get_all_method_handles(), - Self::FilledNewArray(ins) => ins.get_all_method_handles(), - Self::FillArrayData(ins) => ins.get_all_method_handles(), - Self::Throw(ins) => ins.get_all_method_handles(), - Self::Goto(ins) => ins.get_all_method_handles(), - Self::Switch(ins) => ins.get_all_method_handles(), - Self::CmpLFloat(ins) => ins.get_all_method_handles(), - Self::CmpGFloat(ins) => ins.get_all_method_handles(), - Self::CmpLDouble(ins) => ins.get_all_method_handles(), - Self::CmpGDouble(ins) => ins.get_all_method_handles(), - Self::CmpLong(ins) => ins.get_all_method_handles(), - Self::IfEq(ins) => ins.get_all_method_handles(), - Self::IfNe(ins) => ins.get_all_method_handles(), - Self::IfLt(ins) => ins.get_all_method_handles(), - Self::IfGe(ins) => ins.get_all_method_handles(), - Self::IfGt(ins) => ins.get_all_method_handles(), - Self::IfLe(ins) => ins.get_all_method_handles(), - Self::IfEqZ(ins) => ins.get_all_method_handles(), - Self::IfNeZ(ins) => ins.get_all_method_handles(), - Self::IfLtZ(ins) => ins.get_all_method_handles(), - Self::IfGeZ(ins) => ins.get_all_method_handles(), - Self::IfGtZ(ins) => ins.get_all_method_handles(), - Self::IfLeZ(ins) => ins.get_all_method_handles(), - Self::AGet(ins) => ins.get_all_method_handles(), - Self::AGetWide(ins) => ins.get_all_method_handles(), - Self::AGetObject(ins) => ins.get_all_method_handles(), - Self::AGetBoolean(ins) => ins.get_all_method_handles(), - Self::AGetByte(ins) => ins.get_all_method_handles(), - Self::AGetChar(ins) => ins.get_all_method_handles(), - Self::AGetShort(ins) => ins.get_all_method_handles(), - Self::APut(ins) => ins.get_all_method_handles(), - Self::APutWide(ins) => ins.get_all_method_handles(), - Self::APutObject(ins) => ins.get_all_method_handles(), - Self::APutBoolean(ins) => ins.get_all_method_handles(), - Self::APutByte(ins) => ins.get_all_method_handles(), - Self::APutChar(ins) => ins.get_all_method_handles(), - Self::APutShort(ins) => ins.get_all_method_handles(), - Self::IGet(ins) => ins.get_all_method_handles(), - Self::IGetWide(ins) => ins.get_all_method_handles(), - Self::IGetObject(ins) => ins.get_all_method_handles(), - Self::IGetBoolean(ins) => ins.get_all_method_handles(), - Self::IGetByte(ins) => ins.get_all_method_handles(), - Self::IGetChar(ins) => ins.get_all_method_handles(), - Self::IGetShort(ins) => ins.get_all_method_handles(), - Self::IPut(ins) => ins.get_all_method_handles(), - Self::IPutWide(ins) => ins.get_all_method_handles(), - Self::IPutObject(ins) => ins.get_all_method_handles(), - Self::IPutBoolean(ins) => ins.get_all_method_handles(), - Self::IPutByte(ins) => ins.get_all_method_handles(), - Self::IPutChar(ins) => ins.get_all_method_handles(), - Self::IPutShort(ins) => ins.get_all_method_handles(), - Self::SGet(ins) => ins.get_all_method_handles(), - Self::SGetWide(ins) => ins.get_all_method_handles(), - Self::SGetObject(ins) => ins.get_all_method_handles(), - Self::SGetBoolean(ins) => ins.get_all_method_handles(), - Self::SGetByte(ins) => ins.get_all_method_handles(), - Self::SGetChar(ins) => ins.get_all_method_handles(), - Self::SGetShort(ins) => ins.get_all_method_handles(), - Self::SPut(ins) => ins.get_all_method_handles(), - Self::SPutWide(ins) => ins.get_all_method_handles(), - Self::SPutObject(ins) => ins.get_all_method_handles(), - Self::SPutBoolean(ins) => ins.get_all_method_handles(), - Self::SPutByte(ins) => ins.get_all_method_handles(), - Self::SPutChar(ins) => ins.get_all_method_handles(), - Self::SPutShort(ins) => ins.get_all_method_handles(), - Self::InvokeVirtual(ins) => ins.get_all_method_handles(), - Self::InvokeSuper(ins) => ins.get_all_method_handles(), - Self::InvokeDirect(ins) => ins.get_all_method_handles(), - Self::InvokeStatic(ins) => ins.get_all_method_handles(), - Self::InvokeInterface(ins) => ins.get_all_method_handles(), - Self::NegInt(ins) => ins.get_all_method_handles(), - Self::NotInt(ins) => ins.get_all_method_handles(), - Self::NegLong(ins) => ins.get_all_method_handles(), - Self::NotLong(ins) => ins.get_all_method_handles(), - Self::NegFloat(ins) => ins.get_all_method_handles(), - Self::NegDouble(ins) => ins.get_all_method_handles(), - Self::IntToLong(ins) => ins.get_all_method_handles(), - Self::IntToFloat(ins) => ins.get_all_method_handles(), - Self::IntToDouble(ins) => ins.get_all_method_handles(), - Self::LongToInt(ins) => ins.get_all_method_handles(), - Self::LongToFloat(ins) => ins.get_all_method_handles(), - Self::LongToDouble(ins) => ins.get_all_method_handles(), - Self::FloatToInt(ins) => ins.get_all_method_handles(), - Self::FloatToLong(ins) => ins.get_all_method_handles(), - Self::FloatToDouble(ins) => ins.get_all_method_handles(), - Self::DoubleToInt(ins) => ins.get_all_method_handles(), - Self::DoubleToLong(ins) => ins.get_all_method_handles(), - Self::DoubleToFloat(ins) => ins.get_all_method_handles(), - Self::IntToByte(ins) => ins.get_all_method_handles(), - Self::IntToChar(ins) => ins.get_all_method_handles(), - Self::IntToShort(ins) => ins.get_all_method_handles(), - Self::AddInt(ins) => ins.get_all_method_handles(), - Self::SubInt(ins) => ins.get_all_method_handles(), - Self::MulInt(ins) => ins.get_all_method_handles(), - Self::DivInt(ins) => ins.get_all_method_handles(), - Self::RemInt(ins) => ins.get_all_method_handles(), - Self::AndInt(ins) => ins.get_all_method_handles(), - Self::OrInt(ins) => ins.get_all_method_handles(), - Self::XorInt(ins) => ins.get_all_method_handles(), - Self::ShlInt(ins) => ins.get_all_method_handles(), - Self::ShrInt(ins) => ins.get_all_method_handles(), - Self::UshrInt(ins) => ins.get_all_method_handles(), - Self::AddLong(ins) => ins.get_all_method_handles(), - Self::SubLong(ins) => ins.get_all_method_handles(), - Self::MulLong(ins) => ins.get_all_method_handles(), - Self::DivLong(ins) => ins.get_all_method_handles(), - Self::RemLong(ins) => ins.get_all_method_handles(), - Self::AndLong(ins) => ins.get_all_method_handles(), - Self::OrLong(ins) => ins.get_all_method_handles(), - Self::XorLong(ins) => ins.get_all_method_handles(), - Self::ShlLong(ins) => ins.get_all_method_handles(), - Self::ShrLong(ins) => ins.get_all_method_handles(), - Self::UshrLong(ins) => ins.get_all_method_handles(), - Self::AddFloat(ins) => ins.get_all_method_handles(), - Self::SubFloat(ins) => ins.get_all_method_handles(), - Self::MulFloat(ins) => ins.get_all_method_handles(), - Self::DivFloat(ins) => ins.get_all_method_handles(), - Self::RemFloat(ins) => ins.get_all_method_handles(), - Self::AddDouble(ins) => ins.get_all_method_handles(), - Self::SubDouble(ins) => ins.get_all_method_handles(), - Self::MulDouble(ins) => ins.get_all_method_handles(), - Self::DivDouble(ins) => ins.get_all_method_handles(), - Self::RemDouble(ins) => ins.get_all_method_handles(), - Self::AddInt2Addr(ins) => ins.get_all_method_handles(), - Self::SubInt2Addr(ins) => ins.get_all_method_handles(), - Self::MulInt2Addr(ins) => ins.get_all_method_handles(), - Self::DivInt2Addr(ins) => ins.get_all_method_handles(), - Self::RemInt2Addr(ins) => ins.get_all_method_handles(), - Self::AndInt2Addr(ins) => ins.get_all_method_handles(), - Self::OrInt2Addr(ins) => ins.get_all_method_handles(), - Self::XorInt2Addr(ins) => ins.get_all_method_handles(), - Self::ShlInt2Addr(ins) => ins.get_all_method_handles(), - Self::ShrInt2Addr(ins) => ins.get_all_method_handles(), - Self::UshrInt2Addr(ins) => ins.get_all_method_handles(), - Self::AddLong2Addr(ins) => ins.get_all_method_handles(), - Self::SubLong2Addr(ins) => ins.get_all_method_handles(), - Self::MulLong2Addr(ins) => ins.get_all_method_handles(), - Self::DivLong2Addr(ins) => ins.get_all_method_handles(), - Self::RemLong2Addr(ins) => ins.get_all_method_handles(), - Self::AndLong2Addr(ins) => ins.get_all_method_handles(), - Self::OrLong2Addr(ins) => ins.get_all_method_handles(), - Self::XorLong2Addr(ins) => ins.get_all_method_handles(), - Self::ShlLong2Addr(ins) => ins.get_all_method_handles(), - Self::ShrLong2Addr(ins) => ins.get_all_method_handles(), - Self::UshrLong2Addr(ins) => ins.get_all_method_handles(), - Self::AddFloat2Addr(ins) => ins.get_all_method_handles(), - Self::SubFloat2Addr(ins) => ins.get_all_method_handles(), - Self::MulFloat2Addr(ins) => ins.get_all_method_handles(), - Self::DivFloat2Addr(ins) => ins.get_all_method_handles(), - Self::RemFloat2Addr(ins) => ins.get_all_method_handles(), - Self::AddDouble2Addr(ins) => ins.get_all_method_handles(), - Self::SubDouble2Addr(ins) => ins.get_all_method_handles(), - Self::MulDouble2Addr(ins) => ins.get_all_method_handles(), - Self::DivDouble2Addr(ins) => ins.get_all_method_handles(), - Self::RemDouble2Addr(ins) => ins.get_all_method_handles(), - Self::AddIntLit(ins) => ins.get_all_method_handles(), - Self::RsubIntLit(ins) => ins.get_all_method_handles(), - Self::MulIntLit(ins) => ins.get_all_method_handles(), - Self::DivIntLit(ins) => ins.get_all_method_handles(), - Self::RemIntLit(ins) => ins.get_all_method_handles(), - Self::AndIntLit(ins) => ins.get_all_method_handles(), - Self::OrIntLit(ins) => ins.get_all_method_handles(), - Self::XorIntLit(ins) => ins.get_all_method_handles(), - Self::ShlIntLit(ins) => ins.get_all_method_handles(), - Self::ShrIntLit(ins) => ins.get_all_method_handles(), - Self::UshrIntLit(ins) => ins.get_all_method_handles(), - Self::InvokePolymorphic(ins) => ins.get_all_method_handles(), - Self::InvokeCustom(ins) => ins.get_all_method_handles(), - Self::ConstMethodHandle(ins) => ins.get_all_method_handles(), - Self::ConstMethodType(ins) => ins.get_all_method_handles(), - Self::Try(ins) => ins.get_all_method_handles(), - Self::Label(ins) => ins.get_all_method_handles(), - } + let mut visitor = MethodHandleCollector::default(); + visitor.visit_instruction(self).unwrap(); + visitor.result() } } impl<'source> FromPyObject<'source> for Instruction { fn extract(ob: &'source PyAny) -> PyResult { if let Ok(ins) = Nop::extract(ob) { - Ok(Self::Nop(ins)) + Ok(Self::Nop {}) } else if let Ok(ins) = Move::extract(ob) { Ok(Self::Move(ins)) } else if let Ok(ins) = MoveWide::extract(ob) { @@ -3265,7 +2514,7 @@ impl<'source> FromPyObject<'source> for Instruction { impl IntoPy for Instruction { fn into_py(self, py: Python<'_>) -> PyObject { match self { - Self::Nop(ins) => ins.into_py(py), + Self::Nop {} => todo!(), Self::Move(ins) => ins.into_py(py), Self::MoveWide(ins) => ins.into_py(py), Self::MoveObject(ins) => ins.into_py(py), @@ -3604,7 +2853,6 @@ impl CallSite { } } -/// Waste a cycle. #[pyclass] #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] pub struct Nop; diff --git a/androscalpel/src/lib.rs b/androscalpel/src/lib.rs index 22a21da..0d8b614 100644 --- a/androscalpel/src/lib.rs +++ b/androscalpel/src/lib.rs @@ -21,6 +21,7 @@ pub mod method_handle; pub mod py_utils; pub mod scalar; pub mod value; +pub mod visitor; pub use annotation::*; pub use apk::*; @@ -36,6 +37,7 @@ pub use method::*; pub use method_handle::*; pub use scalar::*; pub use value::*; +pub use visitor::*; #[cfg(test)] mod tests; @@ -61,16 +63,6 @@ fn androscalpel(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; m.add_class::()?; m.add_class::()?; diff --git a/androscalpel/src/method_handle.rs b/androscalpel/src/method_handle.rs index fdb4774..12ca574 100644 --- a/androscalpel/src/method_handle.rs +++ b/androscalpel/src/method_handle.rs @@ -4,790 +4,150 @@ use serde::{Deserialize, Serialize}; use std::collections::HashSet; use std::hash::Hash; -use pyo3::exceptions::PyTypeError; use pyo3::prelude::*; use crate::dex_id::*; -use crate::DexString; -use crate::Result; +use crate::{ + DexString, FieldIdCollector, MethodHandleCollector, MethodIdCollector, MethodTypeCollector, + Result, StringCollector, TypeCollector, Visitable, VisitableMut, Visitor, VisitorMut, +}; /// The structure use to reference a method invocation. #[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] +#[pyclass] pub enum MethodHandle { - StaticPut(StaticPut), - StaticGet(StaticGet), - InstancePut(InstancePut), - InstanceGet(InstanceGet), - InvokeStatic(InvokeStatic), - InvokeInstance(InvokeInstance), - InvokeConstructor(InvokeConstructor), - InvokeDirect(InvokeDirect), - InvokeInterface(InvokeInterface), + StaticPut { field: IdField }, + StaticGet { field: IdField }, + InstancePut { field: IdField }, + InstanceGet { field: IdField }, + InvokeStatic { method: IdMethod }, + InvokeInstance { method: IdMethod }, + InvokeConstructor { method: IdMethod }, + InvokeDirect { method: IdMethod }, + InvokeInterface { method: IdMethod }, } -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] -pub struct StaticPut(pub IdField); - -#[pymethods] -impl StaticPut { - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(val: IdField) -> Self { - Self(val) - } - - pub fn get_field(&self) -> IdField { - self.0.clone() - } - - pub fn __str__(&self) -> String { - self.__repr__() - } - - pub fn __repr__(&self) -> String { - format!("StaticPut({})", self.0.__str__()) - } - - /// Return all strings referenced in the handle. - pub fn get_all_strings(&self) -> HashSet { - self.0.get_all_strings() - } - - /// Return all types referenced in the handle. - pub fn get_all_types(&self) -> HashSet { - self.0.get_all_types() - } - - /// Return all prototypes referenced in the handle. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the handle. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.0.clone()); - fields - } - - /// Return all method ids referenced in the handle. - 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, Hash, Deserialize, Serialize)] -pub struct StaticGet(pub IdField); - -#[pymethods] -impl StaticGet { - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(val: IdField) -> Self { - Self(val) - } - - pub fn get_field(&self) -> IdField { - self.0.clone() - } - - pub fn __str__(&self) -> String { - self.__repr__() - } - - pub fn __repr__(&self) -> String { - format!("StaticGet({})", self.0.__str__()) - } - - /// Return all strings referenced in the handle. - pub fn get_all_strings(&self) -> HashSet { - self.0.get_all_strings() - } - - /// Return all types referenced in the handle. - pub fn get_all_types(&self) -> HashSet { - self.0.get_all_types() - } - - /// Return all prototypes referenced in the handle. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the handle. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.0.clone()); - fields - } - - /// Return all method ids referenced in the handle. - 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, Hash, Deserialize, Serialize)] -pub struct InstancePut(pub IdField); - -#[pymethods] -impl InstancePut { - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(val: IdField) -> Self { - Self(val) - } - - pub fn get_field(&self) -> IdField { - self.0.clone() - } - - pub fn __str__(&self) -> String { - self.__repr__() - } - - pub fn __repr__(&self) -> String { - format!("InstancePut({})", self.0.__str__()) - } - - /// Return all strings referenced in the handle. - pub fn get_all_strings(&self) -> HashSet { - self.0.get_all_strings() - } - - /// Return all types referenced in the handle. - pub fn get_all_types(&self) -> HashSet { - self.0.get_all_types() - } - - /// Return all prototypes referenced in the handle. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the handle. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.0.clone()); - fields - } - - /// Return all method ids referenced in the handle. - 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, Hash, Deserialize, Serialize)] -pub struct InstanceGet(pub IdField); - -#[pymethods] -impl InstanceGet { - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(val: IdField) -> Self { - Self(val) - } - - pub fn get_field(&self) -> IdField { - self.0.clone() - } - - pub fn __str__(&self) -> String { - self.__repr__() - } - - pub fn __repr__(&self) -> String { - format!("InstanceGet({})", self.0.__str__()) - } - - /// Return all strings referenced in the handle. - pub fn get_all_strings(&self) -> HashSet { - self.0.get_all_strings() - } - - /// Return all types referenced in the handle. - pub fn get_all_types(&self) -> HashSet { - self.0.get_all_types() - } - - /// Return all prototypes referenced in the handle. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the handle. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.0.clone()); - fields - } - - /// Return all method ids referenced in the handle. - 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, Hash, Deserialize, Serialize)] -pub struct InvokeStatic(pub IdMethod); - -#[pymethods] -impl InvokeStatic { - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(val: IdMethod) -> Self { - Self(val) - } - - pub fn get_method(&self) -> IdMethod { - self.0.clone() - } - - pub fn __str__(&self) -> String { - self.__repr__() - } - - pub fn __repr__(&self) -> String { - format!("InvokeStatic({})", self.0.__str__()) - } - - /// Return all strings referenced in the handle. - pub fn get_all_strings(&self) -> HashSet { - self.0.get_all_strings() - } - - /// Return all types referenced in the handle. - pub fn get_all_types(&self) -> HashSet { - self.0.get_all_types() - } - - /// Return all prototypes referenced in the handle. - pub fn get_all_protos(&self) -> HashSet { - self.0.get_all_protos() - } - - /// Return all field ids referenced in the handle. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the handle. - pub fn get_all_method_ids(&self) -> HashSet { - let mut methods = HashSet::new(); - 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, Hash, Deserialize, Serialize)] -pub struct InvokeInstance(pub IdMethod); - -#[pymethods] -impl InvokeInstance { - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(val: IdMethod) -> Self { - Self(val) - } - - pub fn get_method(&self) -> IdMethod { - self.0.clone() - } - - pub fn __str__(&self) -> String { - self.__repr__() - } - - pub fn __repr__(&self) -> String { - format!("InvokeInstance({})", self.0.__str__()) - } - - /// Return all strings referenced in the handle. - pub fn get_all_strings(&self) -> HashSet { - self.0.get_all_strings() - } - - /// Return all types referenced in the handle. - pub fn get_all_types(&self) -> HashSet { - self.0.get_all_types() - } - - /// Return all prototypes referenced in the handle. - pub fn get_all_protos(&self) -> HashSet { - self.0.get_all_protos() - } - - /// Return all field ids referenced in the handle. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the handle. - pub fn get_all_method_ids(&self) -> HashSet { - let mut methods = HashSet::new(); - 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, Hash, Deserialize, Serialize)] -pub struct InvokeConstructor(pub IdMethod); - -#[pymethods] -impl InvokeConstructor { - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(val: IdMethod) -> Self { - Self(val) - } - - pub fn get_method(&self) -> IdMethod { - self.0.clone() - } - - pub fn __str__(&self) -> String { - self.__repr__() - } - - pub fn __repr__(&self) -> String { - format!("InvokeConstructor({})", self.0.__str__()) - } - - /// Return all strings referenced in the handle. - pub fn get_all_strings(&self) -> HashSet { - self.0.get_all_strings() - } - - /// Return all types referenced in the handle. - pub fn get_all_types(&self) -> HashSet { - self.0.get_all_types() - } - - /// Return all prototypes referenced in the handle. - pub fn get_all_protos(&self) -> HashSet { - self.0.get_all_protos() - } - - /// Return all field ids referenced in the handle. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the handle. - pub fn get_all_method_ids(&self) -> HashSet { - let mut methods = HashSet::new(); - 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, Hash, Deserialize, Serialize)] -pub struct InvokeDirect(pub IdMethod); - -#[pymethods] -impl InvokeDirect { - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(val: IdMethod) -> Self { - Self(val) - } - - pub fn get_method(&self) -> IdMethod { - self.0.clone() - } - - pub fn __str__(&self) -> String { - self.__repr__() - } - - pub fn __repr__(&self) -> String { - format!("InvokeDirect({})", self.0.__str__()) - } - - /// Return all strings referenced in the handle. - pub fn get_all_strings(&self) -> HashSet { - self.0.get_all_strings() - } - - /// Return all types referenced in the handle. - pub fn get_all_types(&self) -> HashSet { - self.0.get_all_types() - } - - /// Return all prototypes referenced in the handle. - pub fn get_all_protos(&self) -> HashSet { - self.0.get_all_protos() - } - - /// Return all field ids referenced in the handle. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the handle. - pub fn get_all_method_ids(&self) -> HashSet { - let mut methods = HashSet::new(); - 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, Hash, Deserialize, Serialize)] -pub struct InvokeInterface(pub IdMethod); - -#[pymethods] -impl InvokeInterface { - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(val: IdMethod) -> Self { - Self(val) - } - - pub fn get_method(&self) -> IdMethod { - self.0.clone() - } - - pub fn __str__(&self) -> String { - self.__repr__() - } - - pub fn __repr__(&self) -> String { - format!("InvokeInterface({})", self.0.__str__()) - } - - /// Return all strings referenced in the handle. - pub fn get_all_strings(&self) -> HashSet { - self.0.get_all_strings() - } - - /// Return all types referenced in the handle. - pub fn get_all_types(&self) -> HashSet { - self.0.get_all_types() - } - - /// Return all prototypes referenced in the handle. - pub fn get_all_protos(&self) -> HashSet { - self.0.get_all_protos() - } - - /// Return all field ids referenced in the handle. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the handle. - pub fn get_all_method_ids(&self) -> HashSet { - let mut methods = HashSet::new(); - 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 { - fn extract(ob: &'source PyAny) -> PyResult { - if let Ok(val) = StaticPut::extract(ob) { - Ok(Self::StaticPut(val)) - } else if let Ok(val) = StaticGet::extract(ob) { - Ok(Self::StaticGet(val)) - } else if let Ok(val) = InstancePut::extract(ob) { - Ok(Self::InstancePut(val)) - } else if let Ok(val) = InstanceGet::extract(ob) { - Ok(Self::InstanceGet(val)) - } else if let Ok(val) = InvokeStatic::extract(ob) { - Ok(Self::InvokeStatic(val)) - } else if let Ok(val) = InvokeInstance::extract(ob) { - Ok(Self::InvokeInstance(val)) - } else if let Ok(val) = InvokeConstructor::extract(ob) { - Ok(Self::InvokeConstructor(val)) - } else if let Ok(val) = InvokeDirect::extract(ob) { - Ok(Self::InvokeDirect(val)) - } else if let Ok(val) = InvokeInterface::extract(ob) { - Ok(Self::InvokeInterface(val)) - } else { - Err(PyErr::new::(format!( - "{} is not a castable as a MethodHandle", - ob.repr()? - ))) - } - } -} - -impl IntoPy for MethodHandle { - fn into_py(self, py: Python<'_>) -> PyObject { +impl Visitable for MethodHandle { + fn default_visit(&self, v: &mut V) -> Result<()> { match self { - Self::StaticPut(val) => val.into_py(py), - Self::StaticGet(val) => val.into_py(py), - Self::InstancePut(val) => val.into_py(py), - Self::InstanceGet(val) => val.into_py(py), - Self::InvokeStatic(val) => val.into_py(py), - Self::InvokeInstance(val) => val.into_py(py), - Self::InvokeConstructor(val) => val.into_py(py), - Self::InvokeDirect(val) => val.into_py(py), - Self::InvokeInterface(val) => val.into_py(py), + Self::StaticPut { field } => v.visit_field_id(field)?, + Self::StaticGet { field } => v.visit_field_id(field)?, + Self::InstancePut { field } => v.visit_field_id(field)?, + Self::InstanceGet { field } => v.visit_field_id(field)?, + Self::InvokeStatic { method } => v.visit_method_id(method)?, + Self::InvokeInstance { method } => v.visit_method_id(method)?, + Self::InvokeConstructor { method } => v.visit_method_id(method)?, + Self::InvokeDirect { method } => v.visit_method_id(method)?, + Self::InvokeInterface { method } => v.visit_method_id(method)?, + } + Ok(()) + } +} + +impl VisitableMut for MethodHandle { + fn default_visit_mut(self, v: &mut V) -> Result { + match self { + Self::StaticPut { field } => Ok(Self::StaticPut { + field: v.visit_field_id(field)?, + }), + Self::StaticGet { field } => Ok(Self::StaticGet { + field: v.visit_field_id(field)?, + }), + Self::InstancePut { field } => Ok(Self::InstancePut { + field: v.visit_field_id(field)?, + }), + Self::InstanceGet { field } => Ok(Self::InstanceGet { + field: v.visit_field_id(field)?, + }), + Self::InvokeStatic { method } => Ok(Self::InvokeStatic { + method: v.visit_method_id(method)?, + }), + Self::InvokeInstance { method } => Ok(Self::InvokeInstance { + method: v.visit_method_id(method)?, + }), + Self::InvokeConstructor { method } => Ok(Self::InvokeConstructor { + method: v.visit_method_id(method)?, + }), + Self::InvokeDirect { method } => Ok(Self::InvokeDirect { + method: v.visit_method_id(method)?, + }), + Self::InvokeInterface { method } => Ok(Self::InvokeInterface { + method: v.visit_method_id(method)?, + }), } } } +#[pymethods] impl MethodHandle { - // Not exposed to python, but meh, let's keep it coherent - pub fn __str__(&self) -> String { - match self { - Self::StaticPut(val) => val.__str__(), - Self::StaticGet(val) => val.__str__(), - Self::InstancePut(val) => val.__str__(), - Self::InstanceGet(val) => val.__str__(), - Self::InvokeStatic(val) => val.__str__(), - Self::InvokeInstance(val) => val.__str__(), - Self::InvokeConstructor(val) => val.__str__(), - Self::InvokeDirect(val) => val.__str__(), - Self::InvokeInterface(val) => val.__str__(), - } + pub fn to_json(&self) -> Result { + Ok(serde_json::to_string(self)?) + } + + #[staticmethod] + pub fn from_json(json: &str) -> Result { + Ok(serde_json::from_str(json)?) + } + + pub fn __str__(&self) -> String { + self.__repr__() } - // Not exposed to python, but meh, let's keep it coherent pub fn __repr__(&self) -> String { match self { - Self::StaticPut(val) => val.__repr__(), - Self::StaticGet(val) => val.__repr__(), - Self::InstancePut(val) => val.__repr__(), - Self::InstanceGet(val) => val.__repr__(), - Self::InvokeStatic(val) => val.__repr__(), - Self::InvokeInstance(val) => val.__repr__(), - Self::InvokeConstructor(val) => val.__str__(), - Self::InvokeDirect(val) => val.__repr__(), - Self::InvokeInterface(val) => val.__repr__(), + Self::StaticPut { field } => format!("StaticPut({})", field.__str__()), + Self::StaticGet { field } => format!("StaticGet({})", field.__str__()), + Self::InstancePut { field } => format!("InstancePut({})", field.__str__()), + Self::InstanceGet { field } => format!("InstanceGet({})", field.__str__()), + Self::InvokeStatic { method } => format!("InvokeStatic({})", method.__str__()), + Self::InvokeInstance { method } => format!("InvokeInstance({})", method.__str__()), + Self::InvokeConstructor { method } => { + format!("InvokeConstructor({})", method.__str__()) + } + Self::InvokeDirect { method } => format!("InvokeDirect({})", method.__str__()), + Self::InvokeInterface { method } => format!("InvokeInterface({})", method.__str__()), } } /// Return all strings referenced in the Handle. pub fn get_all_strings(&self) -> HashSet { - match self { - Self::StaticPut(val) => val.get_all_strings(), - Self::StaticGet(val) => val.get_all_strings(), - Self::InstancePut(val) => val.get_all_strings(), - Self::InstanceGet(val) => val.get_all_strings(), - Self::InvokeStatic(val) => val.get_all_strings(), - Self::InvokeInstance(val) => val.get_all_strings(), - Self::InvokeConstructor(val) => val.get_all_strings(), - Self::InvokeDirect(val) => val.get_all_strings(), - Self::InvokeInterface(val) => val.get_all_strings(), - } + let mut visitor = StringCollector::default(); + visitor.visit_method_handle(self).unwrap(); + visitor.result() } /// Return all types referenced in the Handle. pub fn get_all_types(&self) -> HashSet { - match self { - Self::StaticPut(val) => val.get_all_types(), - Self::StaticGet(val) => val.get_all_types(), - Self::InstancePut(val) => val.get_all_types(), - Self::InstanceGet(val) => val.get_all_types(), - Self::InvokeStatic(val) => val.get_all_types(), - Self::InvokeInstance(val) => val.get_all_types(), - Self::InvokeConstructor(val) => val.get_all_types(), - Self::InvokeDirect(val) => val.get_all_types(), - Self::InvokeInterface(val) => val.get_all_types(), - } + let mut visitor = TypeCollector::default(); + visitor.visit_method_handle(self).unwrap(); + visitor.result() } /// Return all prototypes referenced in the handle. pub fn get_all_protos(&self) -> HashSet { - match self { - Self::StaticPut(val) => val.get_all_protos(), - Self::StaticGet(val) => val.get_all_protos(), - Self::InstancePut(val) => val.get_all_protos(), - Self::InstanceGet(val) => val.get_all_protos(), - Self::InvokeStatic(val) => val.get_all_protos(), - Self::InvokeInstance(val) => val.get_all_protos(), - Self::InvokeConstructor(val) => val.get_all_protos(), - Self::InvokeDirect(val) => val.get_all_protos(), - Self::InvokeInterface(val) => val.get_all_protos(), - } + let mut visitor = MethodTypeCollector::default(); + visitor.visit_method_handle(self).unwrap(); + visitor.result() } /// Return all field ids referenced in the handle. pub fn get_all_field_ids(&self) -> HashSet { - match self { - Self::StaticPut(val) => val.get_all_field_ids(), - Self::StaticGet(val) => val.get_all_field_ids(), - Self::InstancePut(val) => val.get_all_field_ids(), - Self::InstanceGet(val) => val.get_all_field_ids(), - Self::InvokeStatic(val) => val.get_all_field_ids(), - Self::InvokeInstance(val) => val.get_all_field_ids(), - Self::InvokeConstructor(val) => val.get_all_field_ids(), - Self::InvokeDirect(val) => val.get_all_field_ids(), - Self::InvokeInterface(val) => val.get_all_field_ids(), - } + let mut visitor = FieldIdCollector::default(); + visitor.visit_method_handle(self).unwrap(); + visitor.result() } /// Return all method ids referenced in the handle. pub fn get_all_method_ids(&self) -> HashSet { - match self { - Self::StaticPut(val) => val.get_all_method_ids(), - Self::StaticGet(val) => val.get_all_method_ids(), - Self::InstancePut(val) => val.get_all_method_ids(), - Self::InstanceGet(val) => val.get_all_method_ids(), - Self::InvokeStatic(val) => val.get_all_method_ids(), - Self::InvokeInstance(val) => val.get_all_method_ids(), - Self::InvokeConstructor(val) => val.get_all_method_ids(), - Self::InvokeDirect(val) => val.get_all_method_ids(), - Self::InvokeInterface(val) => val.get_all_method_ids(), - } + let mut visitor = MethodIdCollector::default(); + visitor.visit_method_handle(self).unwrap(); + visitor.result() } /// 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(), - } + let mut visitor = MethodHandleCollector::default(); + visitor.visit_method_handle(self).unwrap(); + visitor.result() } } diff --git a/androscalpel/src/visitor.rs b/androscalpel/src/visitor.rs new file mode 100644 index 0000000..e58110c --- /dev/null +++ b/androscalpel/src/visitor.rs @@ -0,0 +1,189 @@ +//! The visitor trait and common implementations. + +use crate::{ + ins::Instruction, DexString, IdEnum, IdField, IdMethod, IdMethodType, IdType, MethodHandle, + Result, +}; +use std::collections::HashSet; + +pub trait Visitor: Sized { + fn visit_instruction(&mut self, ins: &Instruction) -> Result<()> { + ins.default_visit(self) + } + fn visit_string(&mut self, string: &DexString) -> Result<()> { + string.default_visit(self) + } + fn visit_type(&mut self, ty: &IdType) -> Result<()> { + ty.default_visit(self) + } + fn visit_method_type(&mut self, mty: &IdMethodType) -> Result<()> { + mty.default_visit(self) + } + fn visit_field_id(&mut self, id: &IdField) -> Result<()> { + id.default_visit(self) + } + fn visit_method_id(&mut self, id: &IdMethod) -> Result<()> { + id.default_visit(self) + } + fn visit_enum_id(&mut self, id: &IdEnum) -> Result<()> { + id.default_visit(self) + } + fn visit_method_handle(&mut self, handle: &MethodHandle) -> Result<()> { + handle.default_visit(self) + } +} + +pub trait VisitorMut: Sized { + fn visit_instruction(&mut self, ins: Instruction) -> Result { + ins.default_visit_mut(self) + } + fn visit_string(&mut self, string: DexString) -> Result { + string.default_visit_mut(self) + } + fn visit_type(&mut self, ty: IdType) -> Result { + ty.default_visit_mut(self) + } + fn visit_method_type(&mut self, mty: IdMethodType) -> Result { + mty.default_visit_mut(self) + } + fn visit_field_id(&mut self, id: IdField) -> Result { + id.default_visit_mut(self) + } + fn visit_method_id(&mut self, id: IdMethod) -> Result { + id.default_visit_mut(self) + } + fn visit_enum_id(&mut self, id: IdEnum) -> Result { + id.default_visit_mut(self) + } + fn visit_method_handle(&mut self, handle: MethodHandle) -> Result { + handle.default_visit_mut(self) + } +} + +/// Trait for structures that can be visited. +/// In theorie, this is not required, as the [`Visitor`] trait implement +/// all tree traversal, however if the visitor do not do a complex +/// operation it can be usefull to have a default tree traversal accessible +/// to re-implemented trait methods. +pub trait Visitable { + fn default_visit(&self, visitor: &mut V) -> Result<()>; +} + +/// Trait for structures that can be modified by a visitor. +/// In theorie, this is not required, as the [`VisitorMut`] trait implement +/// all tree traversal, however if the visitor do not do a complex +/// operation it can be usefull to have a default tree traversal accessible +/// to re-implemented trait methods. +pub trait VisitableMut { + fn default_visit_mut(self, visitor: &mut V) -> Result + where + Self: Sized; +} + +#[derive(Debug, Default)] +pub struct StringCollector { + pub strings: HashSet, +} + +impl StringCollector { + pub fn result(self) -> HashSet { + self.strings + } +} + +impl Visitor for StringCollector { + fn visit_string(&mut self, string: &DexString) -> Result<()> { + self.strings.insert(string.clone()); + Ok(()) + } +} + +#[derive(Debug, Default)] +pub struct TypeCollector { + pub types: HashSet, +} + +impl TypeCollector { + pub fn result(self) -> HashSet { + self.types + } +} + +impl Visitor for TypeCollector { + fn visit_type(&mut self, ty: &IdType) -> Result<()> { + self.types.insert(ty.clone()); + Ok(()) + } +} + +#[derive(Debug, Default)] +pub struct MethodTypeCollector { + pub method_types: HashSet, +} + +impl MethodTypeCollector { + pub fn result(self) -> HashSet { + self.method_types + } +} + +impl Visitor for MethodTypeCollector { + fn visit_method_type(&mut self, mty: &IdMethodType) -> Result<()> { + self.method_types.insert(mty.clone()); + Ok(()) + } +} + +#[derive(Debug, Default)] +pub struct FieldIdCollector { + pub field_ids: HashSet, +} + +impl FieldIdCollector { + pub fn result(self) -> HashSet { + self.field_ids + } +} + +impl Visitor for FieldIdCollector { + fn visit_field_id(&mut self, id: &IdField) -> Result<()> { + self.field_ids.insert(id.clone()); + Ok(()) + } +} + +#[derive(Debug, Default)] +pub struct MethodIdCollector { + pub method_ids: HashSet, +} + +impl MethodIdCollector { + pub fn result(self) -> HashSet { + self.method_ids + } +} + +impl Visitor for MethodIdCollector { + fn visit_method_id(&mut self, id: &IdMethod) -> Result<()> { + self.method_ids.insert(id.clone()); + Ok(()) + } +} + +#[derive(Debug, Default)] +pub struct MethodHandleCollector { + pub handles: HashSet, +} + +impl MethodHandleCollector { + pub fn result(self) -> HashSet { + self.handles + } +} + +impl Visitor for MethodHandleCollector { + fn visit_method_handle(&mut self, handle: &MethodHandle) -> Result<()> { + self.handles.insert(handle.clone()); + Ok(()) + } +} diff --git a/androscalpel_serializer/src/core/mod.rs b/androscalpel_serializer/src/core/mod.rs index 7e1f74a..66f1d56 100644 --- a/androscalpel_serializer/src/core/mod.rs +++ b/androscalpel_serializer/src/core/mod.rs @@ -33,6 +33,7 @@ impl std::fmt::Display for Error { Self::DeserializationError(msg) => write!(f, "{}", msg), Self::InvalidStringEncoding(msg) => write!(f, "{}", msg), Self::InconsistantStruct(msg) => write!(f, "{}", msg), + Self::OutOfBound(msg) => write!(f, "{}", msg), } } } diff --git a/androscalpel_serializer/src/debug.rs b/androscalpel_serializer/src/debug.rs index 38065fb..ad1006f 100644 --- a/androscalpel_serializer/src/debug.rs +++ b/androscalpel_serializer/src/debug.rs @@ -351,25 +351,29 @@ impl<'a> DebugStateMachine<'a> { Ok(self.debug_info.bytecode[self.pc]) } - pub fn tick(&mut self) -> Result> { - let ins = self.get_ins()?; + pub fn tick(&mut self) -> Option { + let ins = if let Ok(ins) = self.get_ins() { + ins + } else { + return Some(DebugInfo::EndOfData); + }; self.pc += 1; match ins { DbgBytecode::EndSequence => { self.pc = self.debug_info.bytecode.len(); - Ok(Some(DebugInfo::EndOfData)) + Some(DebugInfo::EndOfData) } DbgBytecode::AdvancePC { addr_diff: Uleb128(addr_diff), } => { self.address += addr_diff; - Ok(None) + None } DbgBytecode::AdvanceLine { line_diff: Sleb128(line_diff), } => { self.line = (self.line as i32 + line_diff) as u32; - Ok(None) + None } DbgBytecode::StartLocal { register_num: Uleb128(register_num), @@ -398,11 +402,11 @@ impl<'a> DebugStateMachine<'a> { sig_idx: None, in_scope: true, }; - Ok(Some(DebugInfo::DefLocal { + Some(DebugInfo::DefLocal { addr: self.address, reg: register_num, val: self.register_states[register_num as usize], - })) + }) } DbgBytecode::StartLocalExtended { register_num: Uleb128(register_num), @@ -436,20 +440,20 @@ impl<'a> DebugStateMachine<'a> { }, in_scope: true, }; - Ok(Some(DebugInfo::DefLocal { + Some(DebugInfo::DefLocal { addr: self.address, reg: register_num, val: self.register_states[register_num as usize], - })) + }) } DbgBytecode::EndLocal { register_num: Uleb128(register_num), } => { self.register_states[register_num as usize].in_scope = false; - Ok(Some(DebugInfo::EndLocal { + Some(DebugInfo::EndLocal { addr: self.address, reg: register_num, - })) + }) } DbgBytecode::RestartLocal { register_num: Uleb128(register_num), @@ -463,35 +467,35 @@ impl<'a> DebugStateMachine<'a> { }) } self.register_states[register_num as usize].in_scope = true; - Ok(Some(DebugInfo::DefLocal { + Some(DebugInfo::DefLocal { addr: self.address, reg: register_num, val: self.register_states[register_num as usize], - })) + }) } DbgBytecode::SetPrologueEnd => { //self.prologue_end = true; - Ok(Some(DebugInfo::PrologueEnd { addr: self.address })) + Some(DebugInfo::PrologueEnd { addr: self.address }) } DbgBytecode::SetEpilogueBegin => { //self.epilogue_begin = true; - Ok(Some(DebugInfo::EpilogueBegin { addr: self.address })) + Some(DebugInfo::EpilogueBegin { addr: self.address }) } DbgBytecode::SetFile { name_idx: NO_INDEX } => { //self.source_file_idx = None; - Ok(Some(DebugInfo::SetSourceFile { + Some(DebugInfo::SetSourceFile { addr: self.address, source_file_idx: None, - })) + }) } DbgBytecode::SetFile { name_idx: Uleb128p1(name_idx), } => { //self.source_file_idx = Some(name_idx); - Ok(Some(DebugInfo::SetSourceFile { + Some(DebugInfo::SetSourceFile { addr: self.address, source_file_idx: Some(name_idx), - })) + }) } DbgBytecode::SpecialOpcode(op) => { //if op >= 0x0a { @@ -502,10 +506,10 @@ impl<'a> DebugStateMachine<'a> { let adjusted_opcode = op as u32 - 0x0a; self.line = (self.line as i32 + (adjusted_opcode as i32 % 15) - 4) as u32; self.address += adjusted_opcode / 15; - Ok(Some(DebugInfo::SetLineNumber { + Some(DebugInfo::SetLineNumber { addr: self.address, line_num: self.line, - })) + }) } } }