diff --git a/androscalpel/src/apk.rs b/androscalpel/src/apk.rs index 7421f2a..e75b07f 100644 --- a/androscalpel/src/apk.rs +++ b/androscalpel/src/apk.rs @@ -1,13 +1,15 @@ //! Representation of an apk. -use anyhow::{anyhow, Context, Result}; +use anyhow::{anyhow, bail, Context, Result}; use std::collections::HashMap; use log::info; use pyo3::prelude::*; use pyo3::types::PyBytes; +use crate::instructions; use crate::*; +use androscalpel_serializer::Instruction as InsFormat; use androscalpel_serializer::*; /// Represent an apk. @@ -281,6 +283,58 @@ impl Apk { )) } + /// Return a [`CallSite`] from its idx. + pub fn get_call_site_from_idx(idx: usize, dex: &DexFileReader) -> Result { + let call_site_id = dex.get_call_site_id(idx)?; + let array = dex + .get_struct_at_offset::(call_site_id.call_site_off)? + .value + .values; + if array.len() < 3 { + bail!( + "Invalid CallSite {idx}: the encoded array must contains \ + at least 3 elements, found {}", + array.len() + ); + } + let array = { + let mut array_aux = vec![]; + for val in array { + array_aux.push(Self::encoded_value_to_dex_value(&val, dex)?); + } + array_aux + }; + let method_handle = if let DexValue::MethodHandle(handle) = array[0] { + handle + } else { + bail!( + "Invalid CallSite {idx}: the first value of \ + the encoded array must be a MethodHandle, found {:?}", + array[0] + ) + }; + let name = if let DexValue::String(string) = array[1] { + string + } else { + bail!( + "Invalid CallSite {idx}: the second value of \ + the encoded array must be a String, found {:?}", + array[1] + ) + }; + let proto = if let DexValue::MethodType(ty) = array[0] { + ty + } else { + bail!( + "Invalid CallSite {idx}: the third value of \ + the encoded array must be a MethodType, found {:?}", + array[1] + ) + }; + let args = array[3..].to_vec(); + Ok(CallSite::new(method_handle, name, proto, args)) + } + /// Return a [`Vec`] for the offset of an [`AnnotationSetItem`]. pub fn get_annotation_items_from_annotation_set_off( annotations_set_off: u32, @@ -677,6 +731,1299 @@ impl Apk { }) } + /// Convert an instruction format to an instruction. + fn instruction_format_to_instruction( + format: InsFormat, + addr: usize, + insns_ref: &HashMap, + dex: &DexFileReader, + ) -> Result<(instructions::Instruction, HashMap)> { + use crate::instructions::*; + use InsFormat::*; + let mut labels = HashMap::new(); + let ins = match format { + Format10X { op: 0x00 } => Instruction::Nop(Nop::new()), + 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)), + Format12X { op: 0x04, va, vb } => { + Instruction::MoveWide(MoveWide::new(va as u16, vb as u16)) + } + Format22X { op: 0x05, va, vb } => Instruction::MoveWide(MoveWide::new(va as u16, vb)), + Format32X { op: 0x06, va, vb } => Instruction::MoveWide(MoveWide::new(va, vb)), + Format12X { op: 0x07, va, vb } => { + Instruction::MoveObject(MoveObject::new(va as u16, vb as u16)) + } + Format22X { op: 0x08, va, vb } => { + Instruction::MoveObject(MoveObject::new(va as u16, vb)) + } + Format32X { op: 0x09, va, vb } => Instruction::MoveObject(MoveObject::new(va, vb)), + Format11X { op: 0x0a, va } => Instruction::MoveResult(MoveResult::new(va)), + Format11X { op: 0x0b, va } => Instruction::MoveResultWide(MoveResultWide::new(va)), + Format11X { op: 0x0c, va } => Instruction::MoveResultObject(MoveResultObject::new(va)), + Format11X { op: 0x0d, va } => Instruction::MoveException(MoveException::new(va)), + Format10X { op: 0x0e } => Instruction::ReturnVoid(ReturnVoid::new()), + Format11X { op: 0x0f, va } => Instruction::Return(Return::new(va)), + Format11X { op: 0x10, va } => Instruction::ReturnWide(ReturnWide::new(va)), + Format11X { op: 0x11, va } => Instruction::ReturnObject(ReturnObject::new(va)), + Format11N { op: 0x12, va, b } => Instruction::Const(Const::new(va, b as i32)), + Format21S { op: 0x13, va, b } => Instruction::Const(Const::new(va, b as i32)), + Format31I { op: 0x14, va, b } => Instruction::Const(Const::new(va, b)), + Format21H { op: 0x15, va, b } => Instruction::Const(Const::new(va, (b as i32) * 65536)), // *2**16 + Format21S { op: 0x16, va, b } => Instruction::ConstWide(ConstWide::new(va, b as i64)), + Format31I { op: 0x17, va, b } => Instruction::ConstWide(ConstWide::new(va, b as i64)), + Format51L { op: 0x18, va, b } => Instruction::ConstWide(ConstWide::new(va, b)), + Format21H { op: 0x19, va, b } => { + Instruction::ConstWide(ConstWide::new(va, (b as i64) * 281474976710656)) + // * 2**48 + } + Format21C { op: 0x1a, va, b } => { + Instruction::ConstString(ConstString::new(va, dex.get_string(b as u32)?.into())) + } + Format31C { op: 0x1b, va, b } => { + Instruction::ConstString(ConstString::new(va, dex.get_string(b)?.into())) + } + Format21C { op: 0x1c, va, b } => Instruction::ConstClass(ConstClass::new( + va, + Self::get_id_type_from_idx(b as usize, dex)?, + )), + Format11X { op: 0x1d, va } => Instruction::MonitorEnter(MonitorEnter::new(va)), + Format11X { op: 0x1e, va } => Instruction::MonitorExit(MonitorExit::new(va)), + Format21C { op: 0x1f, va, b } => Instruction::CheckCast(CheckCast::new( + va, + Self::get_id_type_from_idx(b as usize, dex)?, + )), + Format22C { + op: 0x20, + va, + vb, + c, + } => Instruction::InstanceOf(InstanceOf::new( + va, + vb, + Self::get_id_type_from_idx(c as usize, dex)?, + )), + Format12X { op: 0x21, va, vb } => Instruction::ArrayLength(ArrayLength::new(va, vb)), + Format21C { op: 0x22, va, b } => Instruction::NewInstance(NewInstance::new( + va, + Self::get_id_type_from_idx(b as usize, dex)?, + )), + Format22C { + op: 0x23, + va, + vb, + c, + } => Instruction::NewArray(NewArray::new( + va, + vb, + Self::get_id_type_from_idx(c as usize, dex)?, + )), + Format35C { + op: 0x24, + a, + vc, + vd, + ve, + vf, + vg, + b, + } => { + let type_ = Self::get_id_type_from_idx(b as usize, dex)?; + let reg_values: Vec<_> = + [vc as u16, vd as u16, ve as u16, vf as u16, vg as u16][..a as usize].into(); + Instruction::FilledNewArray(FilledNewArray::new(type_, reg_values)?) + } + Format3RC { op: 0x25, a, b, vc } => { + let type_ = Self::get_id_type_from_idx(b as usize, dex)?; + let reg_values = (vc..vc + a as u16).collect(); + Instruction::FilledNewArray(FilledNewArray::new(type_, reg_values)?) + } + Format31T { op: 0x26, va, b } => todo!(), // Fill Array Data + Format11X { op: 0x27, va } => Instruction::Throw(Throw::new(va)), + Format10T { op: 0x28, a } => { + if a < 0 && (-a) as usize > addr { + bail!("Found goto {a} at 0x{addr:0x}: the destination is invalid (negative addresse)"); + } + let dest_addr = if a > 0 { + addr + a as usize + } else { + addr - a as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::Goto(Goto::new(label)) + } + Format20T { op: 0x29, a } => { + if a < 0 && (-a) as usize > addr { + bail!("Found goto {a} at 0x{addr:0x}: the destination is invalid (negative addresse)"); + } + let dest_addr = if a > 0 { + addr + a as usize + } else { + addr - a as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::Goto(Goto::new(label)) + } + Format30T { op: 0x2a, a } => { + if a < 0 && (-a) as usize > addr { + bail!("Found goto {a} at 0x{addr:0x}: the destination is invalid (negative addresse)"); + } + let dest_addr = if a > 0 { + addr + a as usize + } else { + addr - a as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::Goto(Goto::new(label)) + } + Format31T { op: 0x2b, va, b } => todo!(), // Packed Switch + Format31T { op: 0x2c, va, b } => todo!(), // Sparsed Switch + Format23X { + op: 0x2d, + va, + vb, + vc, + } => Instruction::CmpLFloat(CmpLFloat::new(va, vb, vc)), + Format23X { + op: 0x2e, + va, + vb, + vc, + } => Instruction::CmpGFloat(CmpGFloat::new(va, vb, vc)), + Format23X { + op: 0x2f, + va, + vb, + vc, + } => Instruction::CmpLDouble(CmpLDouble::new(va, vb, vc)), + Format23X { + op: 0x30, + va, + vb, + vc, + } => Instruction::CmpGDouble(CmpGDouble::new(va, vb, vc)), + Format23X { + op: 0x31, + va, + vb, + vc, + } => Instruction::CmpLong(CmpLong::new(va, vb, vc)), + Format22T { + op: 0x32, + va, + vb, + c, + } => { + if c < 0 && (-c) as usize > addr { + bail!( + "Found if-eq vA vB {c} at 0x{addr:0x}: \ + the destination is invalid (negative addresse)" + ); + } + let dest_addr = if c > 0 { + addr + c as usize + } else { + addr - c as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::IfEq(IfEq::new(va, vb, label)?) + } + Format22T { + op: 0x33, + va, + vb, + c, + } => { + if c < 0 && (-c) as usize > addr { + bail!( + "Found if-ne vA vB {c} at 0x{addr:0x}: \ + the destination is invalid (negative addresse)" + ); + } + let dest_addr = if c > 0 { + addr + c as usize + } else { + addr - c as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::IfNe(IfNe::new(va, vb, label)?) + } + Format22T { + op: 0x34, + va, + vb, + c, + } => { + if c < 0 && (-c) as usize > addr { + bail!( + "Found if-lt vA vB {c} at 0x{addr:0x}: \ + the destination is invalid (negative addresse)" + ); + } + let dest_addr = if c > 0 { + addr + c as usize + } else { + addr - c as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::IfLt(IfLt::new(va, vb, label)?) + } + Format22T { + op: 0x35, + va, + vb, + c, + } => { + if c < 0 && (-c) as usize > addr { + bail!( + "Found if-ge vA vB {c} at 0x{addr:0x}: \ + the destination is invalid (negative addresse)" + ); + } + let dest_addr = if c > 0 { + addr + c as usize + } else { + addr - c as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::IfGe(IfGe::new(va, vb, label)?) + } + Format22T { + op: 0x36, + va, + vb, + c, + } => { + if c < 0 && (-c) as usize > addr { + bail!( + "Found if-gt vA vB {c} at 0x{addr:0x}: \ + the destination is invalid (negative addresse)" + ); + } + let dest_addr = if c > 0 { + addr + c as usize + } else { + addr - c as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::IfGt(IfGt::new(va, vb, label)?) + } + Format22T { + op: 0x37, + va, + vb, + c, + } => { + if c < 0 && (-c) as usize > addr { + bail!( + "Found if-le vA vB {c} at 0x{addr:0x}: \ + the destination is invalid (negative addresse)" + ); + } + let dest_addr = if c > 0 { + addr + c as usize + } else { + addr - c as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::IfLe(IfLe::new(va, vb, label)?) + } + Format21T { op: 0x38, va, b } => { + if b < 0 && (-b) as usize > addr { + bail!( + "Found if-eqz vA vB {b} at 0x{addr:0x}: \ + the destination is invalid (negative addresse)" + ); + } + let dest_addr = if b > 0 { + addr + b as usize + } else { + addr - b as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::IfEqZ(IfEqZ::new(va, label)?) + } + Format21T { op: 0x39, va, b } => { + if b < 0 && (-b) as usize > addr { + bail!( + "Found if-nez vA vB {b} at 0x{addr:0x}: \ + the destination is invalid (negative addresse)" + ); + } + let dest_addr = if b > 0 { + addr + b as usize + } else { + addr - b as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::IfNeZ(IfNeZ::new(va, label)?) + } + Format21T { op: 0x3a, va, b } => { + if b < 0 && (-b) as usize > addr { + bail!( + "Found if-ltz vA vB {b} at 0x{addr:0x}: \ + the destination is invalid (negative addresse)" + ); + } + let dest_addr = if b > 0 { + addr + b as usize + } else { + addr - b as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::IfLtZ(IfLtZ::new(va, label)?) + } + Format21T { op: 0x3b, va, b } => { + if b < 0 && (-b) as usize > addr { + bail!( + "Found if-gez vA vB {b} at 0x{addr:0x}: \ + the destination is invalid (negative addresse)" + ); + } + let dest_addr = if b > 0 { + addr + b as usize + } else { + addr - b as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::IfGeZ(IfGeZ::new(va, label)?) + } + Format21T { op: 0x3c, va, b } => { + if b < 0 && (-b) as usize > addr { + bail!( + "Found if-gtz vA vB {b} at 0x{addr:0x}: \ + the destination is invalid (negative addresse)" + ); + } + let dest_addr = if b > 0 { + addr + b as usize + } else { + addr - b as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::IfGtZ(IfGtZ::new(va, label)?) + } + Format21T { op: 0x3d, va, b } => { + if b < 0 && (-b) as usize > addr { + bail!( + "Found if-lez vA vB {b} at 0x{addr:0x}: \ + the destination is invalid (negative addresse)" + ); + } + let dest_addr = if b > 0 { + addr + b as usize + } else { + addr - b as usize + }; + let label = format!("label_{dest_addr:80X}"); + if let Some(old_label) = labels.insert(dest_addr, label) { + if old_label != label { + // TODO: internal error, panic? + bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); + } + } + Instruction::IfLeZ(IfLeZ::new(va, label)?) + } + Format23X { + op: 0x44, + va, + vb, + vc, + } => Instruction::AGet(AGet::new(va, vb, vc)), + Format23X { + op: 0x45, + va, + vb, + vc, + } => Instruction::AGetWide(AGetWide::new(va, vb, vc)), + Format23X { + op: 0x46, + va, + vb, + vc, + } => Instruction::AGetObject(AGetObject::new(va, vb, vc)), + Format23X { + op: 0x47, + va, + vb, + vc, + } => Instruction::AGetBoolean(AGetBoolean::new(va, vb, vc)), + Format23X { + op: 0x48, + va, + vb, + vc, + } => Instruction::AGetByte(AGetByte::new(va, vb, vc)), + Format23X { + op: 0x49, + va, + vb, + vc, + } => Instruction::AGetChar(AGetChar::new(va, vb, vc)), + Format23X { + op: 0x4a, + va, + vb, + vc, + } => Instruction::AGetShort(AGetShort::new(va, vb, vc)), + Format23X { + op: 0x4b, + va, + vb, + vc, + } => Instruction::APut(APut::new(va, vb, vc)), + Format23X { + op: 0x4c, + va, + vb, + vc, + } => Instruction::APutWide(APutWide::new(va, vb, vc)), + Format23X { + op: 0x4d, + va, + vb, + vc, + } => Instruction::APutObject(APutObject::new(va, vb, vc)), + Format23X { + op: 0x4e, + va, + vb, + vc, + } => Instruction::APutBoolean(APutBoolean::new(va, vb, vc)), + Format23X { + op: 0x4f, + va, + vb, + vc, + } => Instruction::APutByte(APutByte::new(va, vb, vc)), + Format23X { + op: 0x50, + va, + vb, + vc, + } => Instruction::APutChar(APutChar::new(va, vb, vc)), + Format23X { + op: 0x51, + va, + vb, + vc, + } => Instruction::APutShort(APutShort::new(va, vb, vc)), + Format22C { + op: 0x52, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IGet(IGet::new(va, vb, field)?) + } + Format22C { + op: 0x53, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IGetWide(IGetWide::new(va, vb, field)?) + } + Format22C { + op: 0x54, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IGetObject(IGetObject::new(va, vb, field)?) + } + Format22C { + op: 0x55, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IGetBoolean(IGetBoolean::new(va, vb, field)?) + } + Format22C { + op: 0x56, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IGetByte(IGetByte::new(va, vb, field)?) + } + Format22C { + op: 0x57, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IGetChar(IGetChar::new(va, vb, field)?) + } + Format22C { + op: 0x58, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IGetShort(IGetShort::new(va, vb, field)?) + } + Format22C { + op: 0x59, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IPut(IPut::new(va, vb, field)?) + } + Format22C { + op: 0x5a, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IPutWide(IPutWide::new(va, vb, field)?) + } + Format22C { + op: 0x5b, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IPutObject(IPutObject::new(va, vb, field)?) + } + Format22C { + op: 0x5c, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IPutBoolean(IPutBoolean::new(va, vb, field)?) + } + Format22C { + op: 0x5d, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IPutByte(IPutByte::new(va, vb, field)?) + } + Format22C { + op: 0x5e, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IPutChar(IPutChar::new(va, vb, field)?) + } + Format22C { + op: 0x5f, + va, + vb, + c, + } => { + let field = Self::get_id_field_from_idx(c as usize, dex)?; + Instruction::IPutShort(IPutShort::new(va, vb, field)?) + } + Format21C { op: 0x60, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SGet(SGet::new(va, field)) + } + Format21C { op: 0x61, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SGetWide(SGetWide::new(va, field)) + } + Format21C { op: 0x62, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SGetObject(SGetObject::new(va, field)) + } + Format21C { op: 0x63, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SGetBoolean(SGetBoolean::new(va, field)) + } + Format21C { op: 0x64, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SGetByte(SGetByte::new(va, field)) + } + Format21C { op: 0x65, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SGetChar(SGetChar::new(va, field)) + } + Format21C { op: 0x66, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SGetShort(SGetShort::new(va, field)) + } + Format21C { op: 0x67, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SPut(SPut::new(va, field)) + } + Format21C { op: 0x68, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SPutWide(SPutWide::new(va, field)) + } + Format21C { op: 0x69, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SPutObject(SPutObject::new(va, field)) + } + Format21C { op: 0x6a, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SPutBoolean(SPutBoolean::new(va, field)) + } + Format21C { op: 0x6b, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SPutByte(SPutByte::new(va, field)) + } + Format21C { op: 0x6c, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SPutChar(SPutChar::new(va, field)) + } + Format21C { op: 0x6d, va, b } => { + let field = Self::get_id_field_from_idx(b as usize, dex)?; + Instruction::SPutShort(SPutShort::new(va, field)) + } + Format35C { + op: 0x6e, + a, + vc, + vd, + ve, + vf, + vg, + b, + } => { + let meth = Self::get_id_method_from_idx(b as usize, dex)?; + let args: Vec<_> = + [vc as u16, vd as u16, ve as u16, vf as u16, vg as u16][..a as usize].into(); + Instruction::InvokeVirtual(InvokeVirtual::new(meth, args)?) + } + Format35C { + op: 0x6f, + a, + vc, + vd, + ve, + vf, + vg, + b, + } => { + let meth = Self::get_id_method_from_idx(b as usize, dex)?; + let args: Vec<_> = + [vc as u16, vd as u16, ve as u16, vf as u16, vg as u16][..a as usize].into(); + Instruction::InvokeSuper(InvokeSuper::new(meth, args)?) + } + Format35C { + op: 0x70, + a, + vc, + vd, + ve, + vf, + vg, + b, + } => { + let meth = Self::get_id_method_from_idx(b as usize, dex)?; + let args: Vec<_> = + [vc as u16, vd as u16, ve as u16, vf as u16, vg as u16][..a as usize].into(); + Instruction::InvokeDirect(InvokeDirect::new(meth, args)?) + } + Format35C { + op: 0x71, + a, + vc, + vd, + ve, + vf, + vg, + b, + } => { + let meth = Self::get_id_method_from_idx(b as usize, dex)?; + let args: Vec<_> = + [vc as u16, vd as u16, ve as u16, vf as u16, vg as u16][..a as usize].into(); + Instruction::InvokeStatic(InvokeStatic::new(meth, args)?) + } + Format35C { + op: 0x72, + a, + vc, + vd, + ve, + vf, + vg, + b, + } => { + let meth = Self::get_id_method_from_idx(b as usize, dex)?; + let args: Vec<_> = + [vc as u16, vd as u16, ve as u16, vf as u16, vg as u16][..a as usize].into(); + Instruction::InvokeInterface(InvokeInterface::new(meth, args)?) + } + Format3RC { op: 0x74, a, b, vc } => { + let meth = Self::get_id_method_from_idx(b as usize, dex)?; + let args = (vc..vc + a as u16).collect(); + Instruction::InvokeVirtual(InvokeVirtual::new(meth, args)?) + } + Format3RC { op: 0x75, a, b, vc } => { + let meth = Self::get_id_method_from_idx(b as usize, dex)?; + let args = (vc..vc + a as u16).collect(); + Instruction::InvokeSuper(InvokeSuper::new(meth, args)?) + } + Format3RC { op: 0x76, a, b, vc } => { + let meth = Self::get_id_method_from_idx(b as usize, dex)?; + let args = (vc..vc + a as u16).collect(); + Instruction::InvokeDirect(InvokeDirect::new(meth, args)?) + } + Format3RC { op: 0x77, a, b, vc } => { + let meth = Self::get_id_method_from_idx(b as usize, dex)?; + let args = (vc..vc + a as u16).collect(); + Instruction::InvokeStatic(InvokeStatic::new(meth, args)?) + } + Format3RC { op: 0x78, a, b, vc } => { + let meth = Self::get_id_method_from_idx(b as usize, dex)?; + let args = (vc..vc + a as u16).collect(); + Instruction::InvokeInterface(InvokeInterface::new(meth, args)?) + } + Format12X { op: 0x7b, va, vb } => Instruction::NegInt(NegInt::new(va, vb)?), + Format12X { op: 0x7c, va, vb } => Instruction::NotInt(NotInt::new(va, vb)?), + Format12X { op: 0x7d, va, vb } => Instruction::NegLong(NegLong::new(va, vb)?), + Format12X { op: 0x7e, va, vb } => Instruction::NotLong(NotLong::new(va, vb)?), + Format12X { op: 0x7f, va, vb } => Instruction::NegFloat(NegFloat::new(va, vb)?), + Format12X { op: 0x80, va, vb } => Instruction::NegDouble(NegDouble::new(va, vb)?), + Format12X { op: 0x81, va, vb } => Instruction::IntToLong(IntToLong::new(va, vb)?), + Format12X { op: 0x82, va, vb } => Instruction::IntToFloat(IntToFloat::new(va, vb)?), + Format12X { op: 0x83, va, vb } => Instruction::IntToDouble(IntToDouble::new(va, vb)?), + Format12X { op: 0x84, va, vb } => Instruction::LongToInt(LongToInt::new(va, vb)?), + Format12X { op: 0x85, va, vb } => Instruction::LongToFloat(LongToFloat::new(va, vb)?), + Format12X { op: 0x86, va, vb } => Instruction::LongToDouble(LongToDouble::new(va, vb)?), + Format12X { op: 0x87, va, vb } => Instruction::FloatToInt(FloatToInt::new(va, vb)?), + Format12X { op: 0x88, va, vb } => Instruction::FloatToLong(FloatToLong::new(va, vb)?), + Format12X { op: 0x89, va, vb } => { + Instruction::FloatToDouble(FloatToDouble::new(va, vb)?) + } + Format12X { op: 0x8a, va, vb } => Instruction::DoubleToInt(DoubleToInt::new(va, vb)?), + Format12X { op: 0x8b, va, vb } => Instruction::DoubleToLong(DoubleToLong::new(va, vb)?), + Format12X { op: 0x8c, va, vb } => { + Instruction::DoubleToFloat(DoubleToFloat::new(va, vb)?) + } + Format12X { op: 0x8d, va, vb } => Instruction::IntToByte(IntToByte::new(va, vb)?), + Format12X { op: 0x8e, va, vb } => Instruction::IntToChar(IntToChar::new(va, vb)?), + Format12X { op: 0x8f, va, vb } => Instruction::IntToShort(IntToShort::new(va, vb)?), + Format23X { + op: 0x90, + va, + vb, + vc, + } => Instruction::AddInt(AddInt::new(va, vb, vc)), + Format23X { + op: 0x91, + va, + vb, + vc, + } => Instruction::SubInt(SubInt::new(va, vb, vc)), + Format23X { + op: 0x92, + va, + vb, + vc, + } => Instruction::MulInt(MulInt::new(va, vb, vc)), + Format23X { + op: 0x93, + va, + vb, + vc, + } => Instruction::DivInt(DivInt::new(va, vb, vc)), + Format23X { + op: 0x94, + va, + vb, + vc, + } => Instruction::RemInt(RemInt::new(va, vb, vc)), + Format23X { + op: 0x95, + va, + vb, + vc, + } => Instruction::AndInt(AndInt::new(va, vb, vc)), + Format23X { + op: 0x96, + va, + vb, + vc, + } => Instruction::OrInt(OrInt::new(va, vb, vc)), + Format23X { + op: 0x97, + va, + vb, + vc, + } => Instruction::XorInt(XorInt::new(va, vb, vc)), + Format23X { + op: 0x98, + va, + vb, + vc, + } => Instruction::ShlInt(ShlInt::new(va, vb, vc)), + Format23X { + op: 0x99, + va, + vb, + vc, + } => Instruction::ShrInt(ShrInt::new(va, vb, vc)), + Format23X { + op: 0x9a, + va, + vb, + vc, + } => Instruction::UshrInt(UshrInt::new(va, vb, vc)), + Format23X { + op: 0x9b, + va, + vb, + vc, + } => Instruction::AddLong(AddLong::new(va, vb, vc)), + Format23X { + op: 0x9c, + va, + vb, + vc, + } => Instruction::SubLong(SubLong::new(va, vb, vc)), + Format23X { + op: 0x9d, + va, + vb, + vc, + } => Instruction::MulLong(MulLong::new(va, vb, vc)), + Format23X { + op: 0x9e, + va, + vb, + vc, + } => Instruction::DivLong(DivLong::new(va, vb, vc)), + Format23X { + op: 0x9f, + va, + vb, + vc, + } => Instruction::RemLong(RemLong::new(va, vb, vc)), + Format23X { + op: 0xa0, + va, + vb, + vc, + } => Instruction::AndLong(AndLong::new(va, vb, vc)), + Format23X { + op: 0xa1, + va, + vb, + vc, + } => Instruction::OrLong(OrLong::new(va, vb, vc)), + Format23X { + op: 0xa2, + va, + vb, + vc, + } => Instruction::XorLong(XorLong::new(va, vb, vc)), + Format23X { + op: 0xa3, + va, + vb, + vc, + } => Instruction::ShlLong(ShlLong::new(va, vb, vc)), + Format23X { + op: 0xa4, + va, + vb, + vc, + } => Instruction::ShrLong(ShrLong::new(va, vb, vc)), + Format23X { + op: 0xa5, + va, + vb, + vc, + } => Instruction::UshrLong(UshrLong::new(va, vb, vc)), + Format23X { + op: 0xa6, + va, + vb, + vc, + } => Instruction::AddFloat(AddFloat::new(va, vb, vc)), + Format23X { + op: 0xa7, + va, + vb, + vc, + } => Instruction::SubFloat(SubFloat::new(va, vb, vc)), + Format23X { + op: 0xa8, + va, + vb, + vc, + } => Instruction::MulFloat(MulFloat::new(va, vb, vc)), + Format23X { + op: 0xa9, + va, + vb, + vc, + } => Instruction::DivFloat(DivFloat::new(va, vb, vc)), + Format23X { + op: 0xaa, + va, + vb, + vc, + } => Instruction::RemFloat(RemFloat::new(va, vb, vc)), + Format23X { + op: 0xab, + va, + vb, + vc, + } => Instruction::AddDouble(AddDouble::new(va, vb, vc)), + Format23X { + op: 0xac, + va, + vb, + vc, + } => Instruction::SubDouble(SubDouble::new(va, vb, vc)), + Format23X { + op: 0xad, + va, + vb, + vc, + } => Instruction::MulDouble(MulDouble::new(va, vb, vc)), + Format23X { + op: 0xae, + va, + vb, + vc, + } => Instruction::DivDouble(DivDouble::new(va, vb, vc)), + Format23X { + op: 0xaf, + va, + vb, + vc, + } => Instruction::RemDouble(RemDouble::new(va, vb, vc)), + Format12X { op: 0xb0, va, vb } => Instruction::AddInt2Addr(AddInt2Addr::new(va, vb)?), + Format12X { op: 0xb1, va, vb } => Instruction::SubInt2Addr(SubInt2Addr::new(va, vb)?), + Format12X { op: 0xb2, va, vb } => Instruction::MulInt2Addr(MulInt2Addr::new(va, vb)?), + Format12X { op: 0xb3, va, vb } => Instruction::DivInt2Addr(DivInt2Addr::new(va, vb)?), + Format12X { op: 0xb4, va, vb } => Instruction::RemInt2Addr(RemInt2Addr::new(va, vb)?), + Format12X { op: 0xb5, va, vb } => Instruction::AndInt2Addr(AndInt2Addr::new(va, vb)?), + Format12X { op: 0xb6, va, vb } => Instruction::OrInt2Addr(OrInt2Addr::new(va, vb)?), + Format12X { op: 0xb7, va, vb } => Instruction::XorInt2Addr(XorInt2Addr::new(va, vb)?), + Format12X { op: 0xb8, va, vb } => Instruction::ShlInt2Addr(ShlInt2Addr::new(va, vb)?), + Format12X { op: 0xb9, va, vb } => Instruction::ShrInt2Addr(ShrInt2Addr::new(va, vb)?), + Format12X { op: 0xba, va, vb } => Instruction::UshrInt2Addr(UshrInt2Addr::new(va, vb)?), + Format12X { op: 0xbb, va, vb } => Instruction::AddLong2Addr(AddLong2Addr::new(va, vb)?), + Format12X { op: 0xbc, va, vb } => Instruction::SubLong2Addr(SubLong2Addr::new(va, vb)?), + Format12X { op: 0xbd, va, vb } => Instruction::MulLong2Addr(MulLong2Addr::new(va, vb)?), + Format12X { op: 0xbe, va, vb } => Instruction::DivLong2Addr(DivLong2Addr::new(va, vb)?), + Format12X { op: 0xbf, va, vb } => Instruction::RemLong2Addr(RemLong2Addr::new(va, vb)?), + Format12X { op: 0xc0, va, vb } => Instruction::AndLong2Addr(AndLong2Addr::new(va, vb)?), + Format12X { op: 0xc1, va, vb } => Instruction::OrLong2Addr(OrLong2Addr::new(va, vb)?), + Format12X { op: 0xc2, va, vb } => Instruction::XorLong2Addr(XorLong2Addr::new(va, vb)?), + Format12X { op: 0xc3, va, vb } => Instruction::ShlLong2Addr(ShlLong2Addr::new(va, vb)?), + Format12X { op: 0xc4, va, vb } => Instruction::ShrLong2Addr(ShrLong2Addr::new(va, vb)?), + Format12X { op: 0xc5, va, vb } => { + Instruction::UshrLong2Addr(UshrLong2Addr::new(va, vb)?) + } + Format12X { op: 0xc6, va, vb } => { + Instruction::AddFloat2Addr(AddFloat2Addr::new(va, vb)?) + } + Format12X { op: 0xc7, va, vb } => { + Instruction::SubFloat2Addr(SubFloat2Addr::new(va, vb)?) + } + Format12X { op: 0xc8, va, vb } => { + Instruction::MulFloat2Addr(MulFloat2Addr::new(va, vb)?) + } + Format12X { op: 0xc9, va, vb } => { + Instruction::DivFloat2Addr(DivFloat2Addr::new(va, vb)?) + } + Format12X { op: 0xca, va, vb } => { + Instruction::RemFloat2Addr(RemFloat2Addr::new(va, vb)?) + } + Format12X { op: 0xcb, va, vb } => { + Instruction::AddDouble2Addr(AddDouble2Addr::new(va, vb)?) + } + Format12X { op: 0xcc, va, vb } => { + Instruction::SubDouble2Addr(SubDouble2Addr::new(va, vb)?) + } + Format12X { op: 0xcd, va, vb } => { + Instruction::MulDouble2Addr(MulDouble2Addr::new(va, vb)?) + } + Format12X { op: 0xce, va, vb } => { + Instruction::DivDouble2Addr(DivDouble2Addr::new(va, vb)?) + } + Format12X { op: 0xcf, va, vb } => { + Instruction::RemDouble2Addr(RemDouble2Addr::new(va, vb)?) + } + Format22S { + op: 0xd0, + va, + vb, + c, + } => Instruction::AddIntLit(AddIntLit::new(va, vb, c)?), + Format22S { + op: 0xd1, + va, + vb, + c, + } => Instruction::RsubIntLit(RsubIntLit::new(va, vb, c)?), + Format22S { + op: 0xd2, + va, + vb, + c, + } => Instruction::MulIntLit(MulIntLit::new(va, vb, c)?), + Format22S { + op: 0xd3, + va, + vb, + c, + } => Instruction::DivIntLit(DivIntLit::new(va, vb, c)?), + Format22S { + op: 0xd4, + va, + vb, + c, + } => Instruction::RemIntLit(RemIntLit::new(va, vb, c)?), + Format22S { + op: 0xd5, + va, + vb, + c, + } => Instruction::AndIntLit(AndIntLit::new(va, vb, c)?), + Format22S { + op: 0xd6, + va, + vb, + c, + } => Instruction::OrIntLit(OrIntLit::new(va, vb, c)?), + Format22S { + op: 0xd7, + va, + vb, + c, + } => Instruction::XorIntLit(XorIntLit::new(va, vb, c)?), + Format22B { + op: 0xd8, + va, + vb, + c, + } => Instruction::AddIntLit(AddIntLit::new(va, vb, c as i16)?), + Format22B { + op: 0xd9, + va, + vb, + c, + } => Instruction::RsubIntLit(RsubIntLit::new(va, vb, c as i16)?), + Format22B { + op: 0xda, + va, + vb, + c, + } => Instruction::MulIntLit(MulIntLit::new(va, vb, c as i16)?), + Format22B { + op: 0xdb, + va, + vb, + c, + } => Instruction::DivIntLit(DivIntLit::new(va, vb, c as i16)?), + Format22B { + op: 0xdc, + va, + vb, + c, + } => Instruction::RemIntLit(RemIntLit::new(va, vb, c as i16)?), + Format22B { + op: 0xdd, + va, + vb, + c, + } => Instruction::AndIntLit(AndIntLit::new(va, vb, c as i16)?), + Format22B { + op: 0xde, + va, + vb, + c, + } => Instruction::OrIntLit(OrIntLit::new(va, vb, c as i16)?), + Format22B { + op: 0xdf, + va, + vb, + c, + } => Instruction::XorIntLit(XorIntLit::new(va, vb, c as i16)?), + Format22B { + op: 0xe0, + va, + vb, + c, + } => Instruction::ShlIntLit(ShlIntLit::new(va, vb, c)), + Format22B { + op: 0xe1, + va, + vb, + c, + } => Instruction::ShrIntLit(ShrIntLit::new(va, vb, c)), + Format22B { + op: 0xe2, + va, + vb, + c, + } => Instruction::UshrIntLit(UshrIntLit::new(va, vb, c)), + Format45CC { + op: 0xfa, + a, + vc, + vd, + ve, + vf, + vg, + b, + h, + } => { + let meth = Self::get_id_method_from_idx(b as usize, dex)?; + let proto = Self::get_id_method_type_from_idx(h as usize, dex)?; + let args: Vec<_> = + [vc as u16, vd as u16, ve as u16, vf as u16, vg as u16][..a as usize].into(); + Instruction::InvokePolymorphic(InvokePolymorphic::new(meth, proto, args)?) + } + Format4RCC { + op: 0xfb, + a, + b, + vc, + h, + } => { + let meth = Self::get_id_method_from_idx(b as usize, dex)?; + let proto = Self::get_id_method_type_from_idx(h as usize, dex)?; + let args = (vc..vc + a as u16).collect(); + Instruction::InvokePolymorphic(InvokePolymorphic::new(meth, proto, args)?) + } + Format35C { + op: 0xfc, + a, + vc, + vd, + ve, + vf, + vg, + b, + } => { + let call_site = Self::get_call_site_from_idx(b as usize, dex)?; + let args: Vec<_> = + [vc as u16, vd as u16, ve as u16, vf as u16, vg as u16][..a as usize].into(); + Instruction::InvokeCustom(InvokeCustom::new(call_site, args)?) + } + Format3RC { op: 0xfd, a, b, vc } => { + let call_site = Self::get_call_site_from_idx(b as usize, dex)?; + let args = (vc..vc + a as u16).collect(); + Instruction::InvokeCustom(InvokeCustom::new(call_site, args)?) + } + Format21C { op: 0xfe, va, b } => { + let meth_handle = Self::get_method_handle_from_idx(b as usize, dex)?; + Instruction::ConstMethodHandle(ConstMethodHandle::new(va, meth_handle)) + } + Format21C { op: 0xff, va, b } => { + let proto = Self::get_id_method_type_from_idx(b as usize, dex)?; + Instruction::ConstMethodType(ConstMethodType::new(va, proto)) + } + FormatPackedSwitchPayload { .. } => bail!("{format:?} is a pseudo instruction"), + FormatSparseSwitchPayload { .. } => bail!("{format:?} is a pseudo instruction"), + FormatFillArrayDataPayload { .. } => bail!("{format:?} is a pseudo instruction"), + _ => bail!("Unknwon instruction found at {addr}: {format:?}"), + }; + Ok((ins, labels)) + } + /// Return a [`Code`] from it's offset in the dex file. pub fn get_code_from_off(offset: u32, dex: &DexFileReader) -> Result { let code_item = dex.get_struct_at_offset::(offset)?; @@ -686,7 +2033,7 @@ impl Apk { dex.get_struct_at_offset::(code_item.debug_info_off)? .serialize_to_vec()? // no dealing with that right now }; - let mut tries = vec![]; + let mut _tries = vec![]; for TryItem { start_addr, insn_count, @@ -712,15 +2059,34 @@ impl Apk { { handlers_.push((Self::get_id_type_from_idx(*type_idx as usize, dex)?, *addr)) } - tries.push((start_addr, insn_count, (handlers_, catch_all_addr))); + _tries.push((start_addr, insn_count, (handlers_, catch_all_addr))); } + + let mut instructions_raw = HashMap::new(); + let mut addr = 0; + for ins_f in &code_item.insns { + instructions_raw.insert(addr, ins_f); + addr += ins_f.size(); + } + let mut instructions = vec![]; + addr = 0; + let mut labels = HashMap::new(); + for ins_f in code_item.insns { + let (ins, ins_labels) = + Self::instruction_format_to_instruction(ins_f, addr, &instructions_raw, dex)?; + instructions.push((addr, ins)); + addr += ins_f.size() / 2; + labels.extend(&mut ins_labels); // TODO: handle collisions + } + // TODO: add try blocks and labels + let insns = instructions.into_iter().map(|(_, ins)| ins).collect(); Ok(Code { registers_size: code_item.registers_size, ins_size: code_item.ins_size, outs_size: code_item.outs_size, debug_info, - insns: code_item.insns, - tries, + insns, + //tries, }) } diff --git a/androscalpel/src/code.rs b/androscalpel/src/code.rs index 112208d..32ee556 100644 --- a/androscalpel/src/code.rs +++ b/androscalpel/src/code.rs @@ -4,11 +4,11 @@ use std::collections::HashSet; use pyo3::prelude::*; -use crate::{DexString, IdField, IdMethod, IdMethodType, IdType, MethodHandle}; +use crate::{DexString, IdField, IdMethod, IdMethodType, IdType, Instruction, MethodHandle}; // TODO: make this easy to edit/manipulate, maybe move to Method -type TmpHandlerType = (Vec<(IdType, u32)>, Option); +// type TmpHandlerType = (Vec<(IdType, u32)>, Option); /// The code run by a method. #[pyclass] @@ -33,12 +33,12 @@ pub struct Code { // TODO: implement OPcode /// The instructions. #[pyo3(get, set)] - pub insns: Vec, + pub insns: Vec, // TODO: currently unusable, juste a mapping ty TryItem // TODO: maybe implement as custom OPcode to make me easy to modify? - /// Try blocks - #[pyo3(get, set)] - pub tries: Vec<(u32, u16, TmpHandlerType)>, + // /// Try blocks + // #[pyo3(get, set)] + // pub tries: Vec<(u32, u16, TmpHandlerType)>, // TODO: currently unusable, juste a mapping ty TryItem // TODO: maybe implement as custom OPcode to make me easy to modify? } @@ -62,6 +62,8 @@ impl Code { /// Return all strings referenced in the codes. pub fn get_all_strings(&self) -> HashSet { + todo!() + /* let mut strings = HashSet::new(); for (_, _, (list, _)) in &self.tries { for (ty, _) in list { @@ -69,10 +71,13 @@ impl Code { } } strings + */ } /// Return all types referenced in the codes. pub fn get_all_types(&self) -> HashSet { + todo!() + /* let mut types = HashSet::new(); for (_, _, (list, _)) in &self.tries { for (ty, _) in list { @@ -80,6 +85,7 @@ impl Code { } } types + */ } /// Return all prototypes referenced in the codes. diff --git a/androscalpel/src/instructions.rs b/androscalpel/src/instructions.rs index 5de54de..1d251ac 100644 --- a/androscalpel/src/instructions.rs +++ b/androscalpel/src/instructions.rs @@ -3,22 +3,1226 @@ //! Instruction at a sligthly higher level than //! -use crate::{DexString, IdField, IdMethod, IdMethodType, IdType, MethodHandle, Result}; +use crate::{DexString, DexValue, IdField, IdMethod, IdMethodType, IdType, MethodHandle, Result}; use anyhow::anyhow; +use pyo3::exceptions::PyTypeError; use pyo3::prelude::*; use std::collections::HashMap; +// TODO: impl PartialEq and Eq for call site to derive them here +#[derive(Debug, Clone)] +pub enum Instruction { + Nop(Nop), + Move(Move), + MoveWide(MoveWide), + MoveObject(MoveObject), + MoveResult(MoveResult), + MoveResultWide(MoveResultWide), + MoveException(MoveException), + MoveResultObject(MoveResultObject), + ReturnVoid(ReturnVoid), + Return(Return), + ReturnWide(ReturnWide), + ReturnObject(ReturnObject), + Const(Const), + ConstWide(ConstWide), + ConstString(ConstString), + ConstClass(ConstClass), + MonitorEnter(MonitorEnter), + MonitorExit(MonitorExit), + CheckCast(CheckCast), + InstanceOf(InstanceOf), + ArrayLength(ArrayLength), + NewInstance(NewInstance), + NewArray(NewArray), + FilledNewArray(FilledNewArray), + FillArrayData(FillArrayData), + Throw(Throw), + Goto(Goto), + Switch(Switch), + CmpLFloat(CmpLFloat), + CmpGFloat(CmpGFloat), + CmpLDouble(CmpLDouble), + CmpGDouble(CmpGDouble), + CmpLong(CmpLong), + IfEq(IfEq), + IfNe(IfNe), + IfLt(IfLt), + IfGe(IfGe), + IfGt(IfGt), + IfLe(IfLe), + IfEqZ(IfEqZ), + IfNeZ(IfNeZ), + IfLtZ(IfLtZ), + IfGeZ(IfGeZ), + IfGtZ(IfGtZ), + IfLeZ(IfLeZ), + AGet(AGet), + AGetWide(AGetWide), + AGetObject(AGetObject), + AGetBoolean(AGetBoolean), + AGetByte(AGetByte), + AGetChar(AGetChar), + AGetShort(AGetShort), + APut(APut), + APutWide(APutWide), + APutObject(APutObject), + APutBoolean(APutBoolean), + APutByte(APutByte), + APutChar(APutChar), + APutShort(APutShort), + IGet(IGet), + IGetWide(IGetWide), + IGetObject(IGetObject), + IGetBoolean(IGetBoolean), + IGetByte(IGetByte), + IGetChar(IGetChar), + IGetShort(IGetShort), + IPut(IPut), + IPutWide(IPutWide), + IPutObject(IPutObject), + IPutBoolean(IPutBoolean), + IPutByte(IPutByte), + IPutChar(IPutChar), + IPutShort(IPutShort), + SGet(SGet), + SGetWide(SGetWide), + SGetObject(SGetObject), + SGetBoolean(SGetBoolean), + SGetByte(SGetByte), + SGetChar(SGetChar), + SGetShort(SGetShort), + SPut(SPut), + SPutWide(SPutWide), + SPutObject(SPutObject), + SPutBoolean(SPutBoolean), + SPutByte(SPutByte), + SPutChar(SPutChar), + SPutShort(SPutShort), + InvokeVirtual(InvokeVirtual), + InvokeSuper(InvokeSuper), + InvokeDirect(InvokeDirect), + InvokeStatic(InvokeStatic), + InvokeInterface(InvokeInterface), + NegInt(NegInt), + NotInt(NotInt), + NegLong(NegLong), + NotLong(NotLong), + NegFloat(NegFloat), + NegDouble(NegDouble), + IntToLong(IntToLong), + IntToFloat(IntToFloat), + IntToDouble(IntToDouble), + LongToInt(LongToInt), + LongToFloat(LongToFloat), + LongToDouble(LongToDouble), + FloatToInt(FloatToInt), + FloatToLong(FloatToLong), + FloatToDouble(FloatToDouble), + DoubleToInt(DoubleToInt), + DoubleToLong(DoubleToLong), + DoubleToFloat(DoubleToFloat), + IntToByte(IntToByte), + IntToChar(IntToChar), + IntToShort(IntToShort), + AddInt(AddInt), + SubInt(SubInt), + MulInt(MulInt), + DivInt(DivInt), + RemInt(RemInt), + AndInt(AndInt), + OrInt(OrInt), + XorInt(XorInt), + ShlInt(ShlInt), + ShrInt(ShrInt), + UshrInt(UshrInt), + AddLong(AddLong), + SubLong(SubLong), + MulLong(MulLong), + DivLong(DivLong), + RemLong(RemLong), + AndLong(AndLong), + OrLong(OrLong), + XorLong(XorLong), + ShlLong(ShlLong), + ShrLong(ShrLong), + UshrLong(UshrLong), + AddFloat(AddFloat), + SubFloat(SubFloat), + MulFloat(MulFloat), + DivFloat(DivFloat), + RemFloat(RemFloat), + AddDouble(AddDouble), + SubDouble(SubDouble), + MulDouble(MulDouble), + DivDouble(DivDouble), + RemDouble(RemDouble), + AddInt2Addr(AddInt2Addr), + SubInt2Addr(SubInt2Addr), + MulInt2Addr(MulInt2Addr), + DivInt2Addr(DivInt2Addr), + RemInt2Addr(RemInt2Addr), + AndInt2Addr(AndInt2Addr), + OrInt2Addr(OrInt2Addr), + XorInt2Addr(XorInt2Addr), + ShlInt2Addr(ShlInt2Addr), + ShrInt2Addr(ShrInt2Addr), + UshrInt2Addr(UshrInt2Addr), + AddLong2Addr(AddLong2Addr), + SubLong2Addr(SubLong2Addr), + MulLong2Addr(MulLong2Addr), + DivLong2Addr(DivLong2Addr), + RemLong2Addr(RemLong2Addr), + AndLong2Addr(AndLong2Addr), + OrLong2Addr(OrLong2Addr), + XorLong2Addr(XorLong2Addr), + ShlLong2Addr(ShlLong2Addr), + ShrLong2Addr(ShrLong2Addr), + UshrLong2Addr(UshrLong2Addr), + AddFloat2Addr(AddFloat2Addr), + SubFloat2Addr(SubFloat2Addr), + MulFloat2Addr(MulFloat2Addr), + DivFloat2Addr(DivFloat2Addr), + RemFloat2Addr(RemFloat2Addr), + AddDouble2Addr(AddDouble2Addr), + SubDouble2Addr(SubDouble2Addr), + MulDouble2Addr(MulDouble2Addr), + DivDouble2Addr(DivDouble2Addr), + RemDouble2Addr(RemDouble2Addr), + AddIntLit(AddIntLit), + RsubIntLit(RsubIntLit), + MulIntLit(MulIntLit), + DivIntLit(DivIntLit), + RemIntLit(RemIntLit), + AndIntLit(AndIntLit), + OrIntLit(OrIntLit), + XorIntLit(XorIntLit), + ShlIntLit(ShlIntLit), + ShrIntLit(ShrIntLit), + UshrIntLit(UshrIntLit), + InvokePolymorphic(InvokePolymorphic), + InvokeCustom(InvokeCustom), + ConstMethodHandle(ConstMethodHandle), + ConstMethodType(ConstMethodType), +} + +impl Instruction { + pub fn __str__(&self) -> String { + match self { + Self::Nop(ins) => ins.__str__(), + Self::Move(ins) => ins.__str__(), + Self::MoveWide(ins) => ins.__str__(), + Self::MoveObject(ins) => ins.__str__(), + Self::MoveResult(ins) => ins.__str__(), + Self::MoveResultWide(ins) => ins.__str__(), + Self::MoveException(ins) => ins.__str__(), + Self::MoveResultObject(ins) => ins.__str__(), + Self::ReturnVoid(ins) => ins.__str__(), + Self::Return(ins) => ins.__str__(), + Self::ReturnWide(ins) => ins.__str__(), + Self::ReturnObject(ins) => ins.__str__(), + Self::Const(ins) => ins.__str__(), + Self::ConstWide(ins) => ins.__str__(), + Self::ConstString(ins) => ins.__str__(), + Self::ConstClass(ins) => ins.__str__(), + Self::MonitorEnter(ins) => ins.__str__(), + Self::MonitorExit(ins) => ins.__str__(), + Self::CheckCast(ins) => ins.__str__(), + Self::InstanceOf(ins) => ins.__str__(), + Self::ArrayLength(ins) => ins.__str__(), + Self::NewInstance(ins) => ins.__str__(), + Self::NewArray(ins) => ins.__str__(), + Self::FilledNewArray(ins) => ins.__str__(), + Self::FillArrayData(ins) => ins.__str__(), + Self::Throw(ins) => ins.__str__(), + Self::Goto(ins) => ins.__str__(), + Self::Switch(ins) => ins.__str__(), + Self::CmpLFloat(ins) => ins.__str__(), + Self::CmpGFloat(ins) => ins.__str__(), + Self::CmpLDouble(ins) => ins.__str__(), + Self::CmpGDouble(ins) => ins.__str__(), + Self::CmpLong(ins) => ins.__str__(), + Self::IfEq(ins) => ins.__str__(), + Self::IfNe(ins) => ins.__str__(), + Self::IfLt(ins) => ins.__str__(), + Self::IfGe(ins) => ins.__str__(), + Self::IfGt(ins) => ins.__str__(), + Self::IfLe(ins) => ins.__str__(), + Self::IfEqZ(ins) => ins.__str__(), + Self::IfNeZ(ins) => ins.__str__(), + Self::IfLtZ(ins) => ins.__str__(), + Self::IfGeZ(ins) => ins.__str__(), + Self::IfGtZ(ins) => ins.__str__(), + Self::IfLeZ(ins) => ins.__str__(), + Self::AGet(ins) => ins.__str__(), + Self::AGetWide(ins) => ins.__str__(), + Self::AGetObject(ins) => ins.__str__(), + Self::AGetBoolean(ins) => ins.__str__(), + Self::AGetByte(ins) => ins.__str__(), + Self::AGetChar(ins) => ins.__str__(), + Self::AGetShort(ins) => ins.__str__(), + Self::APut(ins) => ins.__str__(), + Self::APutWide(ins) => ins.__str__(), + Self::APutObject(ins) => ins.__str__(), + Self::APutBoolean(ins) => ins.__str__(), + Self::APutByte(ins) => ins.__str__(), + Self::APutChar(ins) => ins.__str__(), + Self::APutShort(ins) => ins.__str__(), + Self::IGet(ins) => ins.__str__(), + Self::IGetWide(ins) => ins.__str__(), + Self::IGetObject(ins) => ins.__str__(), + Self::IGetBoolean(ins) => ins.__str__(), + Self::IGetByte(ins) => ins.__str__(), + Self::IGetChar(ins) => ins.__str__(), + Self::IGetShort(ins) => ins.__str__(), + Self::IPut(ins) => ins.__str__(), + Self::IPutWide(ins) => ins.__str__(), + Self::IPutObject(ins) => ins.__str__(), + Self::IPutBoolean(ins) => ins.__str__(), + Self::IPutByte(ins) => ins.__str__(), + Self::IPutChar(ins) => ins.__str__(), + Self::IPutShort(ins) => ins.__str__(), + Self::SGet(ins) => ins.__str__(), + Self::SGetWide(ins) => ins.__str__(), + Self::SGetObject(ins) => ins.__str__(), + Self::SGetBoolean(ins) => ins.__str__(), + Self::SGetByte(ins) => ins.__str__(), + Self::SGetChar(ins) => ins.__str__(), + Self::SGetShort(ins) => ins.__str__(), + Self::SPut(ins) => ins.__str__(), + Self::SPutWide(ins) => ins.__str__(), + Self::SPutObject(ins) => ins.__str__(), + Self::SPutBoolean(ins) => ins.__str__(), + Self::SPutByte(ins) => ins.__str__(), + Self::SPutChar(ins) => ins.__str__(), + Self::SPutShort(ins) => ins.__str__(), + Self::InvokeVirtual(ins) => ins.__str__(), + Self::InvokeSuper(ins) => ins.__str__(), + Self::InvokeDirect(ins) => ins.__str__(), + Self::InvokeStatic(ins) => ins.__str__(), + Self::InvokeInterface(ins) => ins.__str__(), + Self::NegInt(ins) => ins.__str__(), + Self::NotInt(ins) => ins.__str__(), + Self::NegLong(ins) => ins.__str__(), + Self::NotLong(ins) => ins.__str__(), + Self::NegFloat(ins) => ins.__str__(), + Self::NegDouble(ins) => ins.__str__(), + Self::IntToLong(ins) => ins.__str__(), + Self::IntToFloat(ins) => ins.__str__(), + Self::IntToDouble(ins) => ins.__str__(), + Self::LongToInt(ins) => ins.__str__(), + Self::LongToFloat(ins) => ins.__str__(), + Self::LongToDouble(ins) => ins.__str__(), + Self::FloatToInt(ins) => ins.__str__(), + Self::FloatToLong(ins) => ins.__str__(), + Self::FloatToDouble(ins) => ins.__str__(), + Self::DoubleToInt(ins) => ins.__str__(), + Self::DoubleToLong(ins) => ins.__str__(), + Self::DoubleToFloat(ins) => ins.__str__(), + Self::IntToByte(ins) => ins.__str__(), + Self::IntToChar(ins) => ins.__str__(), + Self::IntToShort(ins) => ins.__str__(), + Self::AddInt(ins) => ins.__str__(), + Self::SubInt(ins) => ins.__str__(), + Self::MulInt(ins) => ins.__str__(), + Self::DivInt(ins) => ins.__str__(), + Self::RemInt(ins) => ins.__str__(), + Self::AndInt(ins) => ins.__str__(), + Self::OrInt(ins) => ins.__str__(), + Self::XorInt(ins) => ins.__str__(), + Self::ShlInt(ins) => ins.__str__(), + Self::ShrInt(ins) => ins.__str__(), + Self::UshrInt(ins) => ins.__str__(), + Self::AddLong(ins) => ins.__str__(), + Self::SubLong(ins) => ins.__str__(), + Self::MulLong(ins) => ins.__str__(), + Self::DivLong(ins) => ins.__str__(), + Self::RemLong(ins) => ins.__str__(), + Self::AndLong(ins) => ins.__str__(), + Self::OrLong(ins) => ins.__str__(), + Self::XorLong(ins) => ins.__str__(), + Self::ShlLong(ins) => ins.__str__(), + Self::ShrLong(ins) => ins.__str__(), + Self::UshrLong(ins) => ins.__str__(), + Self::AddFloat(ins) => ins.__str__(), + Self::SubFloat(ins) => ins.__str__(), + Self::MulFloat(ins) => ins.__str__(), + Self::DivFloat(ins) => ins.__str__(), + Self::RemFloat(ins) => ins.__str__(), + Self::AddDouble(ins) => ins.__str__(), + Self::SubDouble(ins) => ins.__str__(), + Self::MulDouble(ins) => ins.__str__(), + Self::DivDouble(ins) => ins.__str__(), + Self::RemDouble(ins) => ins.__str__(), + Self::AddInt2Addr(ins) => ins.__str__(), + Self::SubInt2Addr(ins) => ins.__str__(), + Self::MulInt2Addr(ins) => ins.__str__(), + Self::DivInt2Addr(ins) => ins.__str__(), + Self::RemInt2Addr(ins) => ins.__str__(), + Self::AndInt2Addr(ins) => ins.__str__(), + Self::OrInt2Addr(ins) => ins.__str__(), + Self::XorInt2Addr(ins) => ins.__str__(), + Self::ShlInt2Addr(ins) => ins.__str__(), + Self::ShrInt2Addr(ins) => ins.__str__(), + Self::UshrInt2Addr(ins) => ins.__str__(), + Self::AddLong2Addr(ins) => ins.__str__(), + Self::SubLong2Addr(ins) => ins.__str__(), + Self::MulLong2Addr(ins) => ins.__str__(), + Self::DivLong2Addr(ins) => ins.__str__(), + Self::RemLong2Addr(ins) => ins.__str__(), + Self::AndLong2Addr(ins) => ins.__str__(), + Self::OrLong2Addr(ins) => ins.__str__(), + Self::XorLong2Addr(ins) => ins.__str__(), + Self::ShlLong2Addr(ins) => ins.__str__(), + Self::ShrLong2Addr(ins) => ins.__str__(), + Self::UshrLong2Addr(ins) => ins.__str__(), + Self::AddFloat2Addr(ins) => ins.__str__(), + Self::SubFloat2Addr(ins) => ins.__str__(), + Self::MulFloat2Addr(ins) => ins.__str__(), + Self::DivFloat2Addr(ins) => ins.__str__(), + Self::RemFloat2Addr(ins) => ins.__str__(), + Self::AddDouble2Addr(ins) => ins.__str__(), + Self::SubDouble2Addr(ins) => ins.__str__(), + Self::MulDouble2Addr(ins) => ins.__str__(), + Self::DivDouble2Addr(ins) => ins.__str__(), + Self::RemDouble2Addr(ins) => ins.__str__(), + Self::AddIntLit(ins) => ins.__str__(), + Self::RsubIntLit(ins) => ins.__str__(), + Self::MulIntLit(ins) => ins.__str__(), + Self::DivIntLit(ins) => ins.__str__(), + Self::RemIntLit(ins) => ins.__str__(), + Self::AndIntLit(ins) => ins.__str__(), + Self::OrIntLit(ins) => ins.__str__(), + Self::XorIntLit(ins) => ins.__str__(), + Self::ShlIntLit(ins) => ins.__str__(), + Self::ShrIntLit(ins) => ins.__str__(), + Self::UshrIntLit(ins) => ins.__str__(), + Self::InvokePolymorphic(ins) => ins.__str__(), + Self::InvokeCustom(ins) => ins.__str__(), + Self::ConstMethodHandle(ins) => ins.__str__(), + Self::ConstMethodType(ins) => ins.__str__(), + } + } + + pub fn __repr__(&self) -> String { + match self { + Self::Nop(ins) => ins.__repr__(), + Self::Move(ins) => ins.__repr__(), + Self::MoveWide(ins) => ins.__repr__(), + Self::MoveObject(ins) => ins.__repr__(), + Self::MoveResult(ins) => ins.__repr__(), + Self::MoveResultWide(ins) => ins.__repr__(), + Self::MoveException(ins) => ins.__repr__(), + Self::MoveResultObject(ins) => ins.__repr__(), + Self::ReturnVoid(ins) => ins.__repr__(), + Self::Return(ins) => ins.__repr__(), + Self::ReturnWide(ins) => ins.__repr__(), + Self::ReturnObject(ins) => ins.__repr__(), + Self::Const(ins) => ins.__repr__(), + Self::ConstWide(ins) => ins.__repr__(), + Self::ConstString(ins) => ins.__repr__(), + Self::ConstClass(ins) => ins.__repr__(), + Self::MonitorEnter(ins) => ins.__repr__(), + Self::MonitorExit(ins) => ins.__repr__(), + Self::CheckCast(ins) => ins.__repr__(), + Self::InstanceOf(ins) => ins.__repr__(), + Self::ArrayLength(ins) => ins.__repr__(), + Self::NewInstance(ins) => ins.__repr__(), + Self::NewArray(ins) => ins.__repr__(), + Self::FilledNewArray(ins) => ins.__repr__(), + Self::FillArrayData(ins) => ins.__repr__(), + Self::Throw(ins) => ins.__repr__(), + Self::Goto(ins) => ins.__repr__(), + Self::Switch(ins) => ins.__repr__(), + Self::CmpLFloat(ins) => ins.__repr__(), + Self::CmpGFloat(ins) => ins.__repr__(), + Self::CmpLDouble(ins) => ins.__repr__(), + Self::CmpGDouble(ins) => ins.__repr__(), + Self::CmpLong(ins) => ins.__repr__(), + Self::IfEq(ins) => ins.__repr__(), + Self::IfNe(ins) => ins.__repr__(), + Self::IfLt(ins) => ins.__repr__(), + Self::IfGe(ins) => ins.__repr__(), + Self::IfGt(ins) => ins.__repr__(), + Self::IfLe(ins) => ins.__repr__(), + Self::IfEqZ(ins) => ins.__repr__(), + Self::IfNeZ(ins) => ins.__repr__(), + Self::IfLtZ(ins) => ins.__repr__(), + Self::IfGeZ(ins) => ins.__repr__(), + Self::IfGtZ(ins) => ins.__repr__(), + Self::IfLeZ(ins) => ins.__repr__(), + Self::AGet(ins) => ins.__repr__(), + Self::AGetWide(ins) => ins.__repr__(), + Self::AGetObject(ins) => ins.__repr__(), + Self::AGetBoolean(ins) => ins.__repr__(), + Self::AGetByte(ins) => ins.__repr__(), + Self::AGetChar(ins) => ins.__repr__(), + Self::AGetShort(ins) => ins.__repr__(), + Self::APut(ins) => ins.__repr__(), + Self::APutWide(ins) => ins.__repr__(), + Self::APutObject(ins) => ins.__repr__(), + Self::APutBoolean(ins) => ins.__repr__(), + Self::APutByte(ins) => ins.__repr__(), + Self::APutChar(ins) => ins.__repr__(), + Self::APutShort(ins) => ins.__repr__(), + Self::IGet(ins) => ins.__repr__(), + Self::IGetWide(ins) => ins.__repr__(), + Self::IGetObject(ins) => ins.__repr__(), + Self::IGetBoolean(ins) => ins.__repr__(), + Self::IGetByte(ins) => ins.__repr__(), + Self::IGetChar(ins) => ins.__repr__(), + Self::IGetShort(ins) => ins.__repr__(), + Self::IPut(ins) => ins.__repr__(), + Self::IPutWide(ins) => ins.__repr__(), + Self::IPutObject(ins) => ins.__repr__(), + Self::IPutBoolean(ins) => ins.__repr__(), + Self::IPutByte(ins) => ins.__repr__(), + Self::IPutChar(ins) => ins.__repr__(), + Self::IPutShort(ins) => ins.__repr__(), + Self::SGet(ins) => ins.__repr__(), + Self::SGetWide(ins) => ins.__repr__(), + Self::SGetObject(ins) => ins.__repr__(), + Self::SGetBoolean(ins) => ins.__repr__(), + Self::SGetByte(ins) => ins.__repr__(), + Self::SGetChar(ins) => ins.__repr__(), + Self::SGetShort(ins) => ins.__repr__(), + Self::SPut(ins) => ins.__repr__(), + Self::SPutWide(ins) => ins.__repr__(), + Self::SPutObject(ins) => ins.__repr__(), + Self::SPutBoolean(ins) => ins.__repr__(), + Self::SPutByte(ins) => ins.__repr__(), + Self::SPutChar(ins) => ins.__repr__(), + Self::SPutShort(ins) => ins.__repr__(), + Self::InvokeVirtual(ins) => ins.__repr__(), + Self::InvokeSuper(ins) => ins.__repr__(), + Self::InvokeDirect(ins) => ins.__repr__(), + Self::InvokeStatic(ins) => ins.__repr__(), + Self::InvokeInterface(ins) => ins.__repr__(), + Self::NegInt(ins) => ins.__repr__(), + Self::NotInt(ins) => ins.__repr__(), + Self::NegLong(ins) => ins.__repr__(), + Self::NotLong(ins) => ins.__repr__(), + Self::NegFloat(ins) => ins.__repr__(), + Self::NegDouble(ins) => ins.__repr__(), + Self::IntToLong(ins) => ins.__repr__(), + Self::IntToFloat(ins) => ins.__repr__(), + Self::IntToDouble(ins) => ins.__repr__(), + Self::LongToInt(ins) => ins.__repr__(), + Self::LongToFloat(ins) => ins.__repr__(), + Self::LongToDouble(ins) => ins.__repr__(), + Self::FloatToInt(ins) => ins.__repr__(), + Self::FloatToLong(ins) => ins.__repr__(), + Self::FloatToDouble(ins) => ins.__repr__(), + Self::DoubleToInt(ins) => ins.__repr__(), + Self::DoubleToLong(ins) => ins.__repr__(), + Self::DoubleToFloat(ins) => ins.__repr__(), + Self::IntToByte(ins) => ins.__repr__(), + Self::IntToChar(ins) => ins.__repr__(), + Self::IntToShort(ins) => ins.__repr__(), + Self::AddInt(ins) => ins.__repr__(), + Self::SubInt(ins) => ins.__repr__(), + Self::MulInt(ins) => ins.__repr__(), + Self::DivInt(ins) => ins.__repr__(), + Self::RemInt(ins) => ins.__repr__(), + Self::AndInt(ins) => ins.__repr__(), + Self::OrInt(ins) => ins.__repr__(), + Self::XorInt(ins) => ins.__repr__(), + Self::ShlInt(ins) => ins.__repr__(), + Self::ShrInt(ins) => ins.__repr__(), + Self::UshrInt(ins) => ins.__repr__(), + Self::AddLong(ins) => ins.__repr__(), + Self::SubLong(ins) => ins.__repr__(), + Self::MulLong(ins) => ins.__repr__(), + Self::DivLong(ins) => ins.__repr__(), + Self::RemLong(ins) => ins.__repr__(), + Self::AndLong(ins) => ins.__repr__(), + Self::OrLong(ins) => ins.__repr__(), + Self::XorLong(ins) => ins.__repr__(), + Self::ShlLong(ins) => ins.__repr__(), + Self::ShrLong(ins) => ins.__repr__(), + Self::UshrLong(ins) => ins.__repr__(), + Self::AddFloat(ins) => ins.__repr__(), + Self::SubFloat(ins) => ins.__repr__(), + Self::MulFloat(ins) => ins.__repr__(), + Self::DivFloat(ins) => ins.__repr__(), + Self::RemFloat(ins) => ins.__repr__(), + Self::AddDouble(ins) => ins.__repr__(), + Self::SubDouble(ins) => ins.__repr__(), + Self::MulDouble(ins) => ins.__repr__(), + Self::DivDouble(ins) => ins.__repr__(), + Self::RemDouble(ins) => ins.__repr__(), + Self::AddInt2Addr(ins) => ins.__repr__(), + Self::SubInt2Addr(ins) => ins.__repr__(), + Self::MulInt2Addr(ins) => ins.__repr__(), + Self::DivInt2Addr(ins) => ins.__repr__(), + Self::RemInt2Addr(ins) => ins.__repr__(), + Self::AndInt2Addr(ins) => ins.__repr__(), + Self::OrInt2Addr(ins) => ins.__repr__(), + Self::XorInt2Addr(ins) => ins.__repr__(), + Self::ShlInt2Addr(ins) => ins.__repr__(), + Self::ShrInt2Addr(ins) => ins.__repr__(), + Self::UshrInt2Addr(ins) => ins.__repr__(), + Self::AddLong2Addr(ins) => ins.__repr__(), + Self::SubLong2Addr(ins) => ins.__repr__(), + Self::MulLong2Addr(ins) => ins.__repr__(), + Self::DivLong2Addr(ins) => ins.__repr__(), + Self::RemLong2Addr(ins) => ins.__repr__(), + Self::AndLong2Addr(ins) => ins.__repr__(), + Self::OrLong2Addr(ins) => ins.__repr__(), + Self::XorLong2Addr(ins) => ins.__repr__(), + Self::ShlLong2Addr(ins) => ins.__repr__(), + Self::ShrLong2Addr(ins) => ins.__repr__(), + Self::UshrLong2Addr(ins) => ins.__repr__(), + Self::AddFloat2Addr(ins) => ins.__repr__(), + Self::SubFloat2Addr(ins) => ins.__repr__(), + Self::MulFloat2Addr(ins) => ins.__repr__(), + Self::DivFloat2Addr(ins) => ins.__repr__(), + Self::RemFloat2Addr(ins) => ins.__repr__(), + Self::AddDouble2Addr(ins) => ins.__repr__(), + Self::SubDouble2Addr(ins) => ins.__repr__(), + Self::MulDouble2Addr(ins) => ins.__repr__(), + Self::DivDouble2Addr(ins) => ins.__repr__(), + Self::RemDouble2Addr(ins) => ins.__repr__(), + Self::AddIntLit(ins) => ins.__repr__(), + Self::RsubIntLit(ins) => ins.__repr__(), + Self::MulIntLit(ins) => ins.__repr__(), + Self::DivIntLit(ins) => ins.__repr__(), + Self::RemIntLit(ins) => ins.__repr__(), + Self::AndIntLit(ins) => ins.__repr__(), + Self::OrIntLit(ins) => ins.__repr__(), + Self::XorIntLit(ins) => ins.__repr__(), + Self::ShlIntLit(ins) => ins.__repr__(), + Self::ShrIntLit(ins) => ins.__repr__(), + Self::UshrIntLit(ins) => ins.__repr__(), + Self::InvokePolymorphic(ins) => ins.__repr__(), + Self::InvokeCustom(ins) => ins.__repr__(), + Self::ConstMethodHandle(ins) => ins.__repr__(), + Self::ConstMethodType(ins) => ins.__repr__(), + } + } +} + +impl<'source> FromPyObject<'source> for Instruction { + fn extract(ob: &'source PyAny) -> PyResult { + if let Ok(ins) = Nop::extract(ob) { + Ok(Self::Nop(ins)) + } else if let Ok(ins) = Move::extract(ob) { + Ok(Self::Move(ins)) + } else if let Ok(ins) = MoveWide::extract(ob) { + Ok(Self::MoveWide(ins)) + } else if let Ok(ins) = MoveObject::extract(ob) { + Ok(Self::MoveObject(ins)) + } else if let Ok(ins) = MoveResult::extract(ob) { + Ok(Self::MoveResult(ins)) + } else if let Ok(ins) = MoveResultWide::extract(ob) { + Ok(Self::MoveResultWide(ins)) + } else if let Ok(ins) = MoveException::extract(ob) { + Ok(Self::MoveException(ins)) + } else if let Ok(ins) = MoveResultObject::extract(ob) { + Ok(Self::MoveResultObject(ins)) + } else if let Ok(ins) = ReturnVoid::extract(ob) { + Ok(Self::ReturnVoid(ins)) + } else if let Ok(ins) = Return::extract(ob) { + Ok(Self::Return(ins)) + } else if let Ok(ins) = ReturnWide::extract(ob) { + Ok(Self::ReturnWide(ins)) + } else if let Ok(ins) = ReturnObject::extract(ob) { + Ok(Self::ReturnObject(ins)) + } else if let Ok(ins) = Const::extract(ob) { + Ok(Self::Const(ins)) + } else if let Ok(ins) = ConstWide::extract(ob) { + Ok(Self::ConstWide(ins)) + } else if let Ok(ins) = ConstString::extract(ob) { + Ok(Self::ConstString(ins)) + } else if let Ok(ins) = ConstClass::extract(ob) { + Ok(Self::ConstClass(ins)) + } else if let Ok(ins) = MonitorEnter::extract(ob) { + Ok(Self::MonitorEnter(ins)) + } else if let Ok(ins) = MonitorExit::extract(ob) { + Ok(Self::MonitorExit(ins)) + } else if let Ok(ins) = CheckCast::extract(ob) { + Ok(Self::CheckCast(ins)) + } else if let Ok(ins) = InstanceOf::extract(ob) { + Ok(Self::InstanceOf(ins)) + } else if let Ok(ins) = ArrayLength::extract(ob) { + Ok(Self::ArrayLength(ins)) + } else if let Ok(ins) = NewInstance::extract(ob) { + Ok(Self::NewInstance(ins)) + } else if let Ok(ins) = NewArray::extract(ob) { + Ok(Self::NewArray(ins)) + } else if let Ok(ins) = FilledNewArray::extract(ob) { + Ok(Self::FilledNewArray(ins)) + } else if let Ok(ins) = FillArrayData::extract(ob) { + Ok(Self::FillArrayData(ins)) + } else if let Ok(ins) = Throw::extract(ob) { + Ok(Self::Throw(ins)) + } else if let Ok(ins) = Goto::extract(ob) { + Ok(Self::Goto(ins)) + } else if let Ok(ins) = Switch::extract(ob) { + Ok(Self::Switch(ins)) + } else if let Ok(ins) = CmpLFloat::extract(ob) { + Ok(Self::CmpLFloat(ins)) + } else if let Ok(ins) = CmpGFloat::extract(ob) { + Ok(Self::CmpGFloat(ins)) + } else if let Ok(ins) = CmpLDouble::extract(ob) { + Ok(Self::CmpLDouble(ins)) + } else if let Ok(ins) = CmpGDouble::extract(ob) { + Ok(Self::CmpGDouble(ins)) + } else if let Ok(ins) = CmpLong::extract(ob) { + Ok(Self::CmpLong(ins)) + } else if let Ok(ins) = IfEq::extract(ob) { + Ok(Self::IfEq(ins)) + } else if let Ok(ins) = IfNe::extract(ob) { + Ok(Self::IfNe(ins)) + } else if let Ok(ins) = IfLt::extract(ob) { + Ok(Self::IfLt(ins)) + } else if let Ok(ins) = IfGe::extract(ob) { + Ok(Self::IfGe(ins)) + } else if let Ok(ins) = IfGt::extract(ob) { + Ok(Self::IfGt(ins)) + } else if let Ok(ins) = IfLe::extract(ob) { + Ok(Self::IfLe(ins)) + } else if let Ok(ins) = IfEqZ::extract(ob) { + Ok(Self::IfEqZ(ins)) + } else if let Ok(ins) = IfNeZ::extract(ob) { + Ok(Self::IfNeZ(ins)) + } else if let Ok(ins) = IfLtZ::extract(ob) { + Ok(Self::IfLtZ(ins)) + } else if let Ok(ins) = IfGeZ::extract(ob) { + Ok(Self::IfGeZ(ins)) + } else if let Ok(ins) = IfGtZ::extract(ob) { + Ok(Self::IfGtZ(ins)) + } else if let Ok(ins) = IfLeZ::extract(ob) { + Ok(Self::IfLeZ(ins)) + } else if let Ok(ins) = AGet::extract(ob) { + Ok(Self::AGet(ins)) + } else if let Ok(ins) = AGetWide::extract(ob) { + Ok(Self::AGetWide(ins)) + } else if let Ok(ins) = AGetObject::extract(ob) { + Ok(Self::AGetObject(ins)) + } else if let Ok(ins) = AGetBoolean::extract(ob) { + Ok(Self::AGetBoolean(ins)) + } else if let Ok(ins) = AGetByte::extract(ob) { + Ok(Self::AGetByte(ins)) + } else if let Ok(ins) = AGetChar::extract(ob) { + Ok(Self::AGetChar(ins)) + } else if let Ok(ins) = AGetShort::extract(ob) { + Ok(Self::AGetShort(ins)) + } else if let Ok(ins) = APut::extract(ob) { + Ok(Self::APut(ins)) + } else if let Ok(ins) = APutWide::extract(ob) { + Ok(Self::APutWide(ins)) + } else if let Ok(ins) = APutObject::extract(ob) { + Ok(Self::APutObject(ins)) + } else if let Ok(ins) = APutBoolean::extract(ob) { + Ok(Self::APutBoolean(ins)) + } else if let Ok(ins) = APutByte::extract(ob) { + Ok(Self::APutByte(ins)) + } else if let Ok(ins) = APutChar::extract(ob) { + Ok(Self::APutChar(ins)) + } else if let Ok(ins) = APutShort::extract(ob) { + Ok(Self::APutShort(ins)) + } else if let Ok(ins) = IGet::extract(ob) { + Ok(Self::IGet(ins)) + } else if let Ok(ins) = IGetWide::extract(ob) { + Ok(Self::IGetWide(ins)) + } else if let Ok(ins) = IGetObject::extract(ob) { + Ok(Self::IGetObject(ins)) + } else if let Ok(ins) = IGetBoolean::extract(ob) { + Ok(Self::IGetBoolean(ins)) + } else if let Ok(ins) = IGetByte::extract(ob) { + Ok(Self::IGetByte(ins)) + } else if let Ok(ins) = IGetChar::extract(ob) { + Ok(Self::IGetChar(ins)) + } else if let Ok(ins) = IGetShort::extract(ob) { + Ok(Self::IGetShort(ins)) + } else if let Ok(ins) = IPut::extract(ob) { + Ok(Self::IPut(ins)) + } else if let Ok(ins) = IPutWide::extract(ob) { + Ok(Self::IPutWide(ins)) + } else if let Ok(ins) = IPutObject::extract(ob) { + Ok(Self::IPutObject(ins)) + } else if let Ok(ins) = IPutBoolean::extract(ob) { + Ok(Self::IPutBoolean(ins)) + } else if let Ok(ins) = IPutByte::extract(ob) { + Ok(Self::IPutByte(ins)) + } else if let Ok(ins) = IPutChar::extract(ob) { + Ok(Self::IPutChar(ins)) + } else if let Ok(ins) = IPutShort::extract(ob) { + Ok(Self::IPutShort(ins)) + } else if let Ok(ins) = SGet::extract(ob) { + Ok(Self::SGet(ins)) + } else if let Ok(ins) = SGetWide::extract(ob) { + Ok(Self::SGetWide(ins)) + } else if let Ok(ins) = SGetObject::extract(ob) { + Ok(Self::SGetObject(ins)) + } else if let Ok(ins) = SGetBoolean::extract(ob) { + Ok(Self::SGetBoolean(ins)) + } else if let Ok(ins) = SGetByte::extract(ob) { + Ok(Self::SGetByte(ins)) + } else if let Ok(ins) = SGetChar::extract(ob) { + Ok(Self::SGetChar(ins)) + } else if let Ok(ins) = SGetShort::extract(ob) { + Ok(Self::SGetShort(ins)) + } else if let Ok(ins) = SPut::extract(ob) { + Ok(Self::SPut(ins)) + } else if let Ok(ins) = SPutWide::extract(ob) { + Ok(Self::SPutWide(ins)) + } else if let Ok(ins) = SPutObject::extract(ob) { + Ok(Self::SPutObject(ins)) + } else if let Ok(ins) = SPutBoolean::extract(ob) { + Ok(Self::SPutBoolean(ins)) + } else if let Ok(ins) = SPutByte::extract(ob) { + Ok(Self::SPutByte(ins)) + } else if let Ok(ins) = SPutChar::extract(ob) { + Ok(Self::SPutChar(ins)) + } else if let Ok(ins) = SPutShort::extract(ob) { + Ok(Self::SPutShort(ins)) + } else if let Ok(ins) = InvokeVirtual::extract(ob) { + Ok(Self::InvokeVirtual(ins)) + } else if let Ok(ins) = InvokeSuper::extract(ob) { + Ok(Self::InvokeSuper(ins)) + } else if let Ok(ins) = InvokeDirect::extract(ob) { + Ok(Self::InvokeDirect(ins)) + } else if let Ok(ins) = InvokeStatic::extract(ob) { + Ok(Self::InvokeStatic(ins)) + } else if let Ok(ins) = InvokeInterface::extract(ob) { + Ok(Self::InvokeInterface(ins)) + } else if let Ok(ins) = NegInt::extract(ob) { + Ok(Self::NegInt(ins)) + } else if let Ok(ins) = NotInt::extract(ob) { + Ok(Self::NotInt(ins)) + } else if let Ok(ins) = NegLong::extract(ob) { + Ok(Self::NegLong(ins)) + } else if let Ok(ins) = NotLong::extract(ob) { + Ok(Self::NotLong(ins)) + } else if let Ok(ins) = NegFloat::extract(ob) { + Ok(Self::NegFloat(ins)) + } else if let Ok(ins) = NegDouble::extract(ob) { + Ok(Self::NegDouble(ins)) + } else if let Ok(ins) = IntToLong::extract(ob) { + Ok(Self::IntToLong(ins)) + } else if let Ok(ins) = IntToFloat::extract(ob) { + Ok(Self::IntToFloat(ins)) + } else if let Ok(ins) = IntToDouble::extract(ob) { + Ok(Self::IntToDouble(ins)) + } else if let Ok(ins) = LongToInt::extract(ob) { + Ok(Self::LongToInt(ins)) + } else if let Ok(ins) = LongToFloat::extract(ob) { + Ok(Self::LongToFloat(ins)) + } else if let Ok(ins) = LongToDouble::extract(ob) { + Ok(Self::LongToDouble(ins)) + } else if let Ok(ins) = FloatToInt::extract(ob) { + Ok(Self::FloatToInt(ins)) + } else if let Ok(ins) = FloatToLong::extract(ob) { + Ok(Self::FloatToLong(ins)) + } else if let Ok(ins) = FloatToDouble::extract(ob) { + Ok(Self::FloatToDouble(ins)) + } else if let Ok(ins) = DoubleToInt::extract(ob) { + Ok(Self::DoubleToInt(ins)) + } else if let Ok(ins) = DoubleToLong::extract(ob) { + Ok(Self::DoubleToLong(ins)) + } else if let Ok(ins) = DoubleToFloat::extract(ob) { + Ok(Self::DoubleToFloat(ins)) + } else if let Ok(ins) = IntToByte::extract(ob) { + Ok(Self::IntToByte(ins)) + } else if let Ok(ins) = IntToChar::extract(ob) { + Ok(Self::IntToChar(ins)) + } else if let Ok(ins) = IntToShort::extract(ob) { + Ok(Self::IntToShort(ins)) + } else if let Ok(ins) = AddInt::extract(ob) { + Ok(Self::AddInt(ins)) + } else if let Ok(ins) = SubInt::extract(ob) { + Ok(Self::SubInt(ins)) + } else if let Ok(ins) = MulInt::extract(ob) { + Ok(Self::MulInt(ins)) + } else if let Ok(ins) = DivInt::extract(ob) { + Ok(Self::DivInt(ins)) + } else if let Ok(ins) = RemInt::extract(ob) { + Ok(Self::RemInt(ins)) + } else if let Ok(ins) = AndInt::extract(ob) { + Ok(Self::AndInt(ins)) + } else if let Ok(ins) = OrInt::extract(ob) { + Ok(Self::OrInt(ins)) + } else if let Ok(ins) = XorInt::extract(ob) { + Ok(Self::XorInt(ins)) + } else if let Ok(ins) = ShlInt::extract(ob) { + Ok(Self::ShlInt(ins)) + } else if let Ok(ins) = ShrInt::extract(ob) { + Ok(Self::ShrInt(ins)) + } else if let Ok(ins) = UshrInt::extract(ob) { + Ok(Self::UshrInt(ins)) + } else if let Ok(ins) = AddLong::extract(ob) { + Ok(Self::AddLong(ins)) + } else if let Ok(ins) = SubLong::extract(ob) { + Ok(Self::SubLong(ins)) + } else if let Ok(ins) = MulLong::extract(ob) { + Ok(Self::MulLong(ins)) + } else if let Ok(ins) = DivLong::extract(ob) { + Ok(Self::DivLong(ins)) + } else if let Ok(ins) = RemLong::extract(ob) { + Ok(Self::RemLong(ins)) + } else if let Ok(ins) = AndLong::extract(ob) { + Ok(Self::AndLong(ins)) + } else if let Ok(ins) = OrLong::extract(ob) { + Ok(Self::OrLong(ins)) + } else if let Ok(ins) = XorLong::extract(ob) { + Ok(Self::XorLong(ins)) + } else if let Ok(ins) = ShlLong::extract(ob) { + Ok(Self::ShlLong(ins)) + } else if let Ok(ins) = ShrLong::extract(ob) { + Ok(Self::ShrLong(ins)) + } else if let Ok(ins) = UshrLong::extract(ob) { + Ok(Self::UshrLong(ins)) + } else if let Ok(ins) = AddFloat::extract(ob) { + Ok(Self::AddFloat(ins)) + } else if let Ok(ins) = SubFloat::extract(ob) { + Ok(Self::SubFloat(ins)) + } else if let Ok(ins) = MulFloat::extract(ob) { + Ok(Self::MulFloat(ins)) + } else if let Ok(ins) = DivFloat::extract(ob) { + Ok(Self::DivFloat(ins)) + } else if let Ok(ins) = RemFloat::extract(ob) { + Ok(Self::RemFloat(ins)) + } else if let Ok(ins) = AddDouble::extract(ob) { + Ok(Self::AddDouble(ins)) + } else if let Ok(ins) = SubDouble::extract(ob) { + Ok(Self::SubDouble(ins)) + } else if let Ok(ins) = MulDouble::extract(ob) { + Ok(Self::MulDouble(ins)) + } else if let Ok(ins) = DivDouble::extract(ob) { + Ok(Self::DivDouble(ins)) + } else if let Ok(ins) = RemDouble::extract(ob) { + Ok(Self::RemDouble(ins)) + } else if let Ok(ins) = AddInt2Addr::extract(ob) { + Ok(Self::AddInt2Addr(ins)) + } else if let Ok(ins) = SubInt2Addr::extract(ob) { + Ok(Self::SubInt2Addr(ins)) + } else if let Ok(ins) = MulInt2Addr::extract(ob) { + Ok(Self::MulInt2Addr(ins)) + } else if let Ok(ins) = DivInt2Addr::extract(ob) { + Ok(Self::DivInt2Addr(ins)) + } else if let Ok(ins) = RemInt2Addr::extract(ob) { + Ok(Self::RemInt2Addr(ins)) + } else if let Ok(ins) = AndInt2Addr::extract(ob) { + Ok(Self::AndInt2Addr(ins)) + } else if let Ok(ins) = OrInt2Addr::extract(ob) { + Ok(Self::OrInt2Addr(ins)) + } else if let Ok(ins) = XorInt2Addr::extract(ob) { + Ok(Self::XorInt2Addr(ins)) + } else if let Ok(ins) = ShlInt2Addr::extract(ob) { + Ok(Self::ShlInt2Addr(ins)) + } else if let Ok(ins) = ShrInt2Addr::extract(ob) { + Ok(Self::ShrInt2Addr(ins)) + } else if let Ok(ins) = UshrInt2Addr::extract(ob) { + Ok(Self::UshrInt2Addr(ins)) + } else if let Ok(ins) = AddLong2Addr::extract(ob) { + Ok(Self::AddLong2Addr(ins)) + } else if let Ok(ins) = SubLong2Addr::extract(ob) { + Ok(Self::SubLong2Addr(ins)) + } else if let Ok(ins) = MulLong2Addr::extract(ob) { + Ok(Self::MulLong2Addr(ins)) + } else if let Ok(ins) = DivLong2Addr::extract(ob) { + Ok(Self::DivLong2Addr(ins)) + } else if let Ok(ins) = RemLong2Addr::extract(ob) { + Ok(Self::RemLong2Addr(ins)) + } else if let Ok(ins) = AndLong2Addr::extract(ob) { + Ok(Self::AndLong2Addr(ins)) + } else if let Ok(ins) = OrLong2Addr::extract(ob) { + Ok(Self::OrLong2Addr(ins)) + } else if let Ok(ins) = XorLong2Addr::extract(ob) { + Ok(Self::XorLong2Addr(ins)) + } else if let Ok(ins) = ShlLong2Addr::extract(ob) { + Ok(Self::ShlLong2Addr(ins)) + } else if let Ok(ins) = ShrLong2Addr::extract(ob) { + Ok(Self::ShrLong2Addr(ins)) + } else if let Ok(ins) = UshrLong2Addr::extract(ob) { + Ok(Self::UshrLong2Addr(ins)) + } else if let Ok(ins) = AddFloat2Addr::extract(ob) { + Ok(Self::AddFloat2Addr(ins)) + } else if let Ok(ins) = SubFloat2Addr::extract(ob) { + Ok(Self::SubFloat2Addr(ins)) + } else if let Ok(ins) = MulFloat2Addr::extract(ob) { + Ok(Self::MulFloat2Addr(ins)) + } else if let Ok(ins) = DivFloat2Addr::extract(ob) { + Ok(Self::DivFloat2Addr(ins)) + } else if let Ok(ins) = RemFloat2Addr::extract(ob) { + Ok(Self::RemFloat2Addr(ins)) + } else if let Ok(ins) = AddDouble2Addr::extract(ob) { + Ok(Self::AddDouble2Addr(ins)) + } else if let Ok(ins) = SubDouble2Addr::extract(ob) { + Ok(Self::SubDouble2Addr(ins)) + } else if let Ok(ins) = MulDouble2Addr::extract(ob) { + Ok(Self::MulDouble2Addr(ins)) + } else if let Ok(ins) = DivDouble2Addr::extract(ob) { + Ok(Self::DivDouble2Addr(ins)) + } else if let Ok(ins) = RemDouble2Addr::extract(ob) { + Ok(Self::RemDouble2Addr(ins)) + } else if let Ok(ins) = AddIntLit::extract(ob) { + Ok(Self::AddIntLit(ins)) + } else if let Ok(ins) = RsubIntLit::extract(ob) { + Ok(Self::RsubIntLit(ins)) + } else if let Ok(ins) = MulIntLit::extract(ob) { + Ok(Self::MulIntLit(ins)) + } else if let Ok(ins) = DivIntLit::extract(ob) { + Ok(Self::DivIntLit(ins)) + } else if let Ok(ins) = RemIntLit::extract(ob) { + Ok(Self::RemIntLit(ins)) + } else if let Ok(ins) = AndIntLit::extract(ob) { + Ok(Self::AndIntLit(ins)) + } else if let Ok(ins) = OrIntLit::extract(ob) { + Ok(Self::OrIntLit(ins)) + } else if let Ok(ins) = XorIntLit::extract(ob) { + Ok(Self::XorIntLit(ins)) + } else if let Ok(ins) = ShlIntLit::extract(ob) { + Ok(Self::ShlIntLit(ins)) + } else if let Ok(ins) = ShrIntLit::extract(ob) { + Ok(Self::ShrIntLit(ins)) + } else if let Ok(ins) = UshrIntLit::extract(ob) { + Ok(Self::UshrIntLit(ins)) + } else if let Ok(ins) = InvokePolymorphic::extract(ob) { + Ok(Self::InvokePolymorphic(ins)) + } else if let Ok(ins) = InvokeCustom::extract(ob) { + Ok(Self::InvokeCustom(ins)) + } else if let Ok(ins) = ConstMethodHandle::extract(ob) { + Ok(Self::ConstMethodHandle(ins)) + } else if let Ok(ins) = ConstMethodType::extract(ob) { + Ok(Self::ConstMethodType(ins)) + } else { + Err(PyErr::new::(format!( + "{} is not a castable as an Instruction", + ob.repr()? + ))) + } + } +} + +impl IntoPy for Instruction { + fn into_py(self, py: Python<'_>) -> PyObject { + match self { + Self::Nop(ins) => ins.into_py(py), + Self::Move(ins) => ins.into_py(py), + Self::MoveWide(ins) => ins.into_py(py), + Self::MoveObject(ins) => ins.into_py(py), + Self::MoveResult(ins) => ins.into_py(py), + Self::MoveResultWide(ins) => ins.into_py(py), + Self::MoveException(ins) => ins.into_py(py), + Self::MoveResultObject(ins) => ins.into_py(py), + Self::ReturnVoid(ins) => ins.into_py(py), + Self::Return(ins) => ins.into_py(py), + Self::ReturnWide(ins) => ins.into_py(py), + Self::ReturnObject(ins) => ins.into_py(py), + Self::Const(ins) => ins.into_py(py), + Self::ConstWide(ins) => ins.into_py(py), + Self::ConstString(ins) => ins.into_py(py), + Self::ConstClass(ins) => ins.into_py(py), + Self::MonitorEnter(ins) => ins.into_py(py), + Self::MonitorExit(ins) => ins.into_py(py), + Self::CheckCast(ins) => ins.into_py(py), + Self::InstanceOf(ins) => ins.into_py(py), + Self::ArrayLength(ins) => ins.into_py(py), + Self::NewInstance(ins) => ins.into_py(py), + Self::NewArray(ins) => ins.into_py(py), + Self::FilledNewArray(ins) => ins.into_py(py), + Self::FillArrayData(ins) => ins.into_py(py), + Self::Throw(ins) => ins.into_py(py), + Self::Goto(ins) => ins.into_py(py), + Self::Switch(ins) => ins.into_py(py), + Self::CmpLFloat(ins) => ins.into_py(py), + Self::CmpGFloat(ins) => ins.into_py(py), + Self::CmpLDouble(ins) => ins.into_py(py), + Self::CmpGDouble(ins) => ins.into_py(py), + Self::CmpLong(ins) => ins.into_py(py), + Self::IfEq(ins) => ins.into_py(py), + Self::IfNe(ins) => ins.into_py(py), + Self::IfLt(ins) => ins.into_py(py), + Self::IfGe(ins) => ins.into_py(py), + Self::IfGt(ins) => ins.into_py(py), + Self::IfLe(ins) => ins.into_py(py), + Self::IfEqZ(ins) => ins.into_py(py), + Self::IfNeZ(ins) => ins.into_py(py), + Self::IfLtZ(ins) => ins.into_py(py), + Self::IfGeZ(ins) => ins.into_py(py), + Self::IfGtZ(ins) => ins.into_py(py), + Self::IfLeZ(ins) => ins.into_py(py), + Self::AGet(ins) => ins.into_py(py), + Self::AGetWide(ins) => ins.into_py(py), + Self::AGetObject(ins) => ins.into_py(py), + Self::AGetBoolean(ins) => ins.into_py(py), + Self::AGetByte(ins) => ins.into_py(py), + Self::AGetChar(ins) => ins.into_py(py), + Self::AGetShort(ins) => ins.into_py(py), + Self::APut(ins) => ins.into_py(py), + Self::APutWide(ins) => ins.into_py(py), + Self::APutObject(ins) => ins.into_py(py), + Self::APutBoolean(ins) => ins.into_py(py), + Self::APutByte(ins) => ins.into_py(py), + Self::APutChar(ins) => ins.into_py(py), + Self::APutShort(ins) => ins.into_py(py), + Self::IGet(ins) => ins.into_py(py), + Self::IGetWide(ins) => ins.into_py(py), + Self::IGetObject(ins) => ins.into_py(py), + Self::IGetBoolean(ins) => ins.into_py(py), + Self::IGetByte(ins) => ins.into_py(py), + Self::IGetChar(ins) => ins.into_py(py), + Self::IGetShort(ins) => ins.into_py(py), + Self::IPut(ins) => ins.into_py(py), + Self::IPutWide(ins) => ins.into_py(py), + Self::IPutObject(ins) => ins.into_py(py), + Self::IPutBoolean(ins) => ins.into_py(py), + Self::IPutByte(ins) => ins.into_py(py), + Self::IPutChar(ins) => ins.into_py(py), + Self::IPutShort(ins) => ins.into_py(py), + Self::SGet(ins) => ins.into_py(py), + Self::SGetWide(ins) => ins.into_py(py), + Self::SGetObject(ins) => ins.into_py(py), + Self::SGetBoolean(ins) => ins.into_py(py), + Self::SGetByte(ins) => ins.into_py(py), + Self::SGetChar(ins) => ins.into_py(py), + Self::SGetShort(ins) => ins.into_py(py), + Self::SPut(ins) => ins.into_py(py), + Self::SPutWide(ins) => ins.into_py(py), + Self::SPutObject(ins) => ins.into_py(py), + Self::SPutBoolean(ins) => ins.into_py(py), + Self::SPutByte(ins) => ins.into_py(py), + Self::SPutChar(ins) => ins.into_py(py), + Self::SPutShort(ins) => ins.into_py(py), + Self::InvokeVirtual(ins) => ins.into_py(py), + Self::InvokeSuper(ins) => ins.into_py(py), + Self::InvokeDirect(ins) => ins.into_py(py), + Self::InvokeStatic(ins) => ins.into_py(py), + Self::InvokeInterface(ins) => ins.into_py(py), + Self::NegInt(ins) => ins.into_py(py), + Self::NotInt(ins) => ins.into_py(py), + Self::NegLong(ins) => ins.into_py(py), + Self::NotLong(ins) => ins.into_py(py), + Self::NegFloat(ins) => ins.into_py(py), + Self::NegDouble(ins) => ins.into_py(py), + Self::IntToLong(ins) => ins.into_py(py), + Self::IntToFloat(ins) => ins.into_py(py), + Self::IntToDouble(ins) => ins.into_py(py), + Self::LongToInt(ins) => ins.into_py(py), + Self::LongToFloat(ins) => ins.into_py(py), + Self::LongToDouble(ins) => ins.into_py(py), + Self::FloatToInt(ins) => ins.into_py(py), + Self::FloatToLong(ins) => ins.into_py(py), + Self::FloatToDouble(ins) => ins.into_py(py), + Self::DoubleToInt(ins) => ins.into_py(py), + Self::DoubleToLong(ins) => ins.into_py(py), + Self::DoubleToFloat(ins) => ins.into_py(py), + Self::IntToByte(ins) => ins.into_py(py), + Self::IntToChar(ins) => ins.into_py(py), + Self::IntToShort(ins) => ins.into_py(py), + Self::AddInt(ins) => ins.into_py(py), + Self::SubInt(ins) => ins.into_py(py), + Self::MulInt(ins) => ins.into_py(py), + Self::DivInt(ins) => ins.into_py(py), + Self::RemInt(ins) => ins.into_py(py), + Self::AndInt(ins) => ins.into_py(py), + Self::OrInt(ins) => ins.into_py(py), + Self::XorInt(ins) => ins.into_py(py), + Self::ShlInt(ins) => ins.into_py(py), + Self::ShrInt(ins) => ins.into_py(py), + Self::UshrInt(ins) => ins.into_py(py), + Self::AddLong(ins) => ins.into_py(py), + Self::SubLong(ins) => ins.into_py(py), + Self::MulLong(ins) => ins.into_py(py), + Self::DivLong(ins) => ins.into_py(py), + Self::RemLong(ins) => ins.into_py(py), + Self::AndLong(ins) => ins.into_py(py), + Self::OrLong(ins) => ins.into_py(py), + Self::XorLong(ins) => ins.into_py(py), + Self::ShlLong(ins) => ins.into_py(py), + Self::ShrLong(ins) => ins.into_py(py), + Self::UshrLong(ins) => ins.into_py(py), + Self::AddFloat(ins) => ins.into_py(py), + Self::SubFloat(ins) => ins.into_py(py), + Self::MulFloat(ins) => ins.into_py(py), + Self::DivFloat(ins) => ins.into_py(py), + Self::RemFloat(ins) => ins.into_py(py), + Self::AddDouble(ins) => ins.into_py(py), + Self::SubDouble(ins) => ins.into_py(py), + Self::MulDouble(ins) => ins.into_py(py), + Self::DivDouble(ins) => ins.into_py(py), + Self::RemDouble(ins) => ins.into_py(py), + Self::AddInt2Addr(ins) => ins.into_py(py), + Self::SubInt2Addr(ins) => ins.into_py(py), + Self::MulInt2Addr(ins) => ins.into_py(py), + Self::DivInt2Addr(ins) => ins.into_py(py), + Self::RemInt2Addr(ins) => ins.into_py(py), + Self::AndInt2Addr(ins) => ins.into_py(py), + Self::OrInt2Addr(ins) => ins.into_py(py), + Self::XorInt2Addr(ins) => ins.into_py(py), + Self::ShlInt2Addr(ins) => ins.into_py(py), + Self::ShrInt2Addr(ins) => ins.into_py(py), + Self::UshrInt2Addr(ins) => ins.into_py(py), + Self::AddLong2Addr(ins) => ins.into_py(py), + Self::SubLong2Addr(ins) => ins.into_py(py), + Self::MulLong2Addr(ins) => ins.into_py(py), + Self::DivLong2Addr(ins) => ins.into_py(py), + Self::RemLong2Addr(ins) => ins.into_py(py), + Self::AndLong2Addr(ins) => ins.into_py(py), + Self::OrLong2Addr(ins) => ins.into_py(py), + Self::XorLong2Addr(ins) => ins.into_py(py), + Self::ShlLong2Addr(ins) => ins.into_py(py), + Self::ShrLong2Addr(ins) => ins.into_py(py), + Self::UshrLong2Addr(ins) => ins.into_py(py), + Self::AddFloat2Addr(ins) => ins.into_py(py), + Self::SubFloat2Addr(ins) => ins.into_py(py), + Self::MulFloat2Addr(ins) => ins.into_py(py), + Self::DivFloat2Addr(ins) => ins.into_py(py), + Self::RemFloat2Addr(ins) => ins.into_py(py), + Self::AddDouble2Addr(ins) => ins.into_py(py), + Self::SubDouble2Addr(ins) => ins.into_py(py), + Self::MulDouble2Addr(ins) => ins.into_py(py), + Self::DivDouble2Addr(ins) => ins.into_py(py), + Self::RemDouble2Addr(ins) => ins.into_py(py), + Self::AddIntLit(ins) => ins.into_py(py), + Self::RsubIntLit(ins) => ins.into_py(py), + Self::MulIntLit(ins) => ins.into_py(py), + Self::DivIntLit(ins) => ins.into_py(py), + Self::RemIntLit(ins) => ins.into_py(py), + Self::AndIntLit(ins) => ins.into_py(py), + Self::OrIntLit(ins) => ins.into_py(py), + Self::XorIntLit(ins) => ins.into_py(py), + Self::ShlIntLit(ins) => ins.into_py(py), + Self::ShrIntLit(ins) => ins.into_py(py), + Self::UshrIntLit(ins) => ins.into_py(py), + Self::InvokePolymorphic(ins) => ins.into_py(py), + Self::InvokeCustom(ins) => ins.into_py(py), + Self::ConstMethodHandle(ins) => ins.into_py(py), + Self::ConstMethodType(ins) => ins.into_py(py), + } + } +} + #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct CallSite; // TODO +#[derive(Debug, Clone)] +pub struct CallSite { + pub method_handle: MethodHandle, + pub name: DexString, + pub type_: IdMethodType, + pub args: Vec, +} #[pymethods] impl CallSite { #[new] - pub fn new() -> Self { - Self + pub fn new( + method_handle: MethodHandle, + name: DexString, + type_: IdMethodType, + args: Vec, + ) -> Self { + let args = args.iter().cloned().collect(); + Self { + method_handle, + name, + type_, + args, + } } pub fn __str__(&self) -> String { @@ -907,14 +2111,14 @@ impl Switch { /// - b == c == Nan: a = -1 #[pyclass] #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct CmpLFLoat { +pub struct CmpLFloat { pub dest: u8, pub b: u8, pub c: u8, } #[pymethods] -impl CmpLFLoat { +impl CmpLFloat { #[new] pub fn new(dest: u8, b: u8, c: u8) -> Self { Self { dest, b, c } @@ -926,7 +2130,7 @@ impl CmpLFLoat { pub fn __repr__(&self) -> String { format!( - "Instruction(CmpLFLoat({}, {}, {}))", + "Instruction(CmpLFloat({}, {}, {}))", self.dest, self.b, self.c ) } @@ -940,14 +2144,14 @@ impl CmpLFLoat { /// - b == c == Nan: a = 1 #[pyclass] #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct CmpGFLoat { +pub struct CmpGFloat { pub dest: u8, pub b: u8, pub c: u8, } #[pymethods] -impl CmpGFLoat { +impl CmpGFloat { #[new] pub fn new(dest: u8, b: u8, c: u8) -> Self { Self { dest, b, c } @@ -959,7 +2163,7 @@ impl CmpGFLoat { pub fn __repr__(&self) -> String { format!( - "Instruction(CmpGFLoat({}, {}, {}))", + "Instruction(CmpGFloat({}, {}, {}))", self.dest, self.b, self.c ) } @@ -1109,14 +2313,14 @@ impl IfEq { /// Jump to the label if a != b #[pyclass] #[derive(Debug, Clone, PartialEq, Eq)] -pub struct IfNeq { +pub struct IfNe { pub a: u8, pub b: u8, pub label: String, } #[pymethods] -impl IfNeq { +impl IfNe { #[new] pub fn new(a: u8, b: u8, label: String) -> Result { let ins = Self { a, b, label }; @@ -1145,7 +2349,7 @@ impl IfNeq { } pub fn __repr__(&self) -> String { - format!("Instruction(IfNeq({}, {}, {}))", self.a, self.b, self.label) + format!("Instruction(IfNe({}, {}, {}))", self.a, self.b, self.label) } } @@ -1361,13 +2565,13 @@ impl IfEqZ { /// Jump to the label if a != 0 #[pyclass] #[derive(Debug, Clone, PartialEq, Eq)] -pub struct IfNeqZ { +pub struct IfNeZ { pub a: u8, pub label: String, } #[pymethods] -impl IfNeqZ { +impl IfNeZ { #[new] pub fn new(a: u8, label: String) -> Result { let ins = Self { a, label }; @@ -1391,7 +2595,7 @@ impl IfNeqZ { } pub fn __repr__(&self) -> String { - format!("Instruction(IfNeq({}, {}))", self.a, self.label) + format!("Instruction(IfNe({}, {}))", self.a, self.label) } } @@ -2900,7 +4104,7 @@ pub struct SPut { #[pymethods] impl SPut { #[new] - pub fn new(from: u8, obj: u8, field: IdField) -> Self { + pub fn new(from: u8, field: IdField) -> Self { Self { from, field } } @@ -3091,13 +4295,13 @@ impl SPutShort { #[derive(Debug, Clone, PartialEq, Eq)] pub struct InvokeVirtual { pub method: IdMethod, - pub args: Vec, + pub args: Vec, } #[pymethods] impl InvokeVirtual { #[new] - pub fn new(method: IdMethod, args: Vec) -> Result { + pub fn new(method: IdMethod, args: Vec) -> Result { let invoke = Self { method, args }; invoke.sanity_check()?; Ok(invoke) @@ -3168,13 +4372,13 @@ impl InvokeVirtual { #[derive(Debug, Clone, PartialEq, Eq)] pub struct InvokeSuper { pub method: IdMethod, - pub args: Vec, + pub args: Vec, } #[pymethods] impl InvokeSuper { #[new] - pub fn new(method: IdMethod, args: Vec) -> Result { + pub fn new(method: IdMethod, args: Vec) -> Result { let invoke = Self { method, args }; invoke.sanity_check()?; Ok(invoke) @@ -3245,13 +4449,13 @@ impl InvokeSuper { #[derive(Debug, Clone, PartialEq, Eq)] pub struct InvokeDirect { pub method: IdMethod, - pub args: Vec, + pub args: Vec, } #[pymethods] impl InvokeDirect { #[new] - pub fn new(method: IdMethod, args: Vec) -> Result { + pub fn new(method: IdMethod, args: Vec) -> Result { let invoke = Self { method, args }; invoke.sanity_check()?; Ok(invoke) @@ -3322,13 +4526,13 @@ impl InvokeDirect { #[derive(Debug, Clone, PartialEq, Eq)] pub struct InvokeStatic { pub method: IdMethod, - pub args: Vec, + pub args: Vec, } #[pymethods] impl InvokeStatic { #[new] - pub fn new(method: IdMethod, args: Vec) -> Result { + pub fn new(method: IdMethod, args: Vec) -> Result { let invoke = Self { method, args }; invoke.sanity_check()?; Ok(invoke) @@ -3399,13 +4603,13 @@ impl InvokeStatic { #[derive(Debug, Clone, PartialEq, Eq)] pub struct InvokeInterface { pub method: IdMethod, - pub args: Vec, + pub args: Vec, } #[pymethods] impl InvokeInterface { #[new] - pub fn new(method: IdMethod, args: Vec) -> Result { + pub fn new(method: IdMethod, args: Vec) -> Result { let invoke = Self { method, args }; invoke.sanity_check()?; Ok(invoke) @@ -7320,13 +8524,13 @@ impl UshrIntLit { pub struct InvokePolymorphic { pub method: IdMethod, pub proto: IdMethodType, - pub args: Vec, + pub args: Vec, } #[pymethods] impl InvokePolymorphic { #[new] - pub fn new(method: IdMethod, proto: IdMethodType, args: Vec) -> Result { + pub fn new(method: IdMethod, proto: IdMethodType, args: Vec) -> Result { let invoke = Self { method, proto, @@ -7404,16 +8608,16 @@ impl InvokePolymorphic { /// Invoke a method from a call site. #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone)] pub struct InvokeCustom { pub call_site: CallSite, - pub args: Vec, + pub args: Vec, } #[pymethods] impl InvokeCustom { #[new] - pub fn new(call_site: CallSite, args: Vec) -> Result { + pub fn new(call_site: CallSite, args: Vec) -> Result { let invoke = Self { call_site, args }; invoke.sanity_check()?; Ok(invoke) diff --git a/androscalpel/src/lib.rs b/androscalpel/src/lib.rs index c999d53..a67b995 100644 --- a/androscalpel/src/lib.rs +++ b/androscalpel/src/lib.rs @@ -24,7 +24,7 @@ pub use dex_id::*; pub use dex_string::*; pub use dex_writer::*; pub use field::*; -//pub use instructions::*; +pub use instructions::{CallSite, Instruction}; pub use method::*; pub use method_handle::*; pub use scalar::*; diff --git a/androscalpel_serializer/src/file_reader.rs b/androscalpel_serializer/src/file_reader.rs index 6bdd453..ad1a3cb 100644 --- a/androscalpel_serializer/src/file_reader.rs +++ b/androscalpel_serializer/src/file_reader.rs @@ -194,6 +194,16 @@ impl<'a> DexFileReader<'a> { ))) } + /// Return a [`CallSiteIdItem`] reference from its idx. + pub fn get_call_site_id(&self, idx: usize) -> Result<&CallSiteIdItem> { + self.call_site_ids + .get(idx) + .ok_or(Error::InconsistantStruct(format!( + "call site {idx} is out of bound (|call_site_ids|={})", + self.call_site_ids.len() + ))) + } + fn sanity_check(&self) -> Result<()> { if self.header.magic.version != [0x30, 0x33, 0x39] { warn!(