add instruction using pseudo-instruction format
This commit is contained in:
parent
95f4686f3f
commit
2d164362a7
2 changed files with 209 additions and 8 deletions
|
|
@ -4,6 +4,7 @@
|
|||
use crate::{Error, ReadSeek, Result, Serializable};
|
||||
//use log::debug;
|
||||
use std::io::{SeekFrom, Write};
|
||||
use std::iter::zip;
|
||||
|
||||
/// An instruction, following the formats described at
|
||||
/// <https://source.android.com/docs/core/runtime/dalvik-bytecode>
|
||||
|
|
@ -208,6 +209,17 @@ pub enum Instruction {
|
|||
op: u8,
|
||||
b: i64,
|
||||
},
|
||||
FormatPackedSwitchPayload {
|
||||
first_key: i32,
|
||||
targets: Vec<i32>,
|
||||
},
|
||||
FormatSparseSwitchPayload {
|
||||
key_targets: Vec<(i32, i32)>,
|
||||
},
|
||||
FormatFillArrayDataPayload {
|
||||
elt_width: u16,
|
||||
data: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
|
|
@ -595,6 +607,48 @@ impl Instruction {
|
|||
let b = i64::deserialize(input)?;
|
||||
Ok(Self::Format51L { va, op, b })
|
||||
}
|
||||
|
||||
pub fn deserialize_packed_switch(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||
let _ = u16::deserialize(input)?;
|
||||
let size = u16::deserialize(input)?;
|
||||
let first_key = i32::deserialize(input)?;
|
||||
let mut targets = vec![];
|
||||
for _ in 0..size {
|
||||
targets.push(i32::deserialize(input)?);
|
||||
}
|
||||
Ok(Self::FormatPackedSwitchPayload { first_key, targets })
|
||||
}
|
||||
|
||||
pub fn deserialize_sparse_switch(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||
let _ = u16::deserialize(input)?;
|
||||
let size = u16::deserialize(input)?;
|
||||
let mut keys = vec![];
|
||||
let mut targets = vec![];
|
||||
for _ in 0..size {
|
||||
keys.push(i32::deserialize(input)?);
|
||||
}
|
||||
for _ in 0..size {
|
||||
targets.push(i32::deserialize(input)?);
|
||||
}
|
||||
let key_targets = zip(keys, targets).collect();
|
||||
Ok(Self::FormatSparseSwitchPayload { key_targets })
|
||||
}
|
||||
|
||||
pub fn deserialize_fill_array_data(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||
let _ = u16::deserialize(input)?;
|
||||
let elt_width = u16::deserialize(input)?;
|
||||
let size = u32::deserialize(input)?;
|
||||
let len = size * elt_width as u32;
|
||||
let mut data = vec![];
|
||||
for _ in 0..len {
|
||||
data.push(u8::deserialize(input)?);
|
||||
}
|
||||
if len % 2 != 0 {
|
||||
let _ = u8::deserialize(input)?;
|
||||
}
|
||||
|
||||
Ok(Self::FormatFillArrayDataPayload { elt_width, data })
|
||||
}
|
||||
}
|
||||
|
||||
impl Serializable for Instruction {
|
||||
|
|
@ -771,7 +825,6 @@ impl Serializable for Instruction {
|
|||
op.serialize(output)?;
|
||||
0u8.serialize(output)?;
|
||||
let [a_h0, a_h1, a_l0, a_l1] = a.to_be_bytes();
|
||||
// TODO: check the bytes order
|
||||
u32::from_be_bytes([a_l0, a_l1, a_h0, a_h1]).serialize(output)
|
||||
}
|
||||
Self::Format32X { op, va, vb } => {
|
||||
|
|
@ -784,21 +837,18 @@ impl Serializable for Instruction {
|
|||
op.serialize(output)?;
|
||||
va.serialize(output)?;
|
||||
let [b_h0, b_h1, b_l0, b_l1] = b.to_be_bytes();
|
||||
// TODO: check the bytes order
|
||||
u32::from_be_bytes([b_l0, b_l1, b_h0, b_h1]).serialize(output)
|
||||
}
|
||||
Self::Format31T { va, op, b } => {
|
||||
op.serialize(output)?;
|
||||
va.serialize(output)?;
|
||||
let [b_h0, b_h1, b_l0, b_l1] = b.to_be_bytes();
|
||||
// TODO: check the bytes order
|
||||
u32::from_be_bytes([b_l0, b_l1, b_h0, b_h1]).serialize(output)
|
||||
}
|
||||
Self::Format31C { va, op, b } => {
|
||||
op.serialize(output)?;
|
||||
va.serialize(output)?;
|
||||
let [b_h0, b_h1, b_l0, b_l1] = b.to_be_bytes();
|
||||
// TODO: check the bytes order
|
||||
u32::from_be_bytes([b_l0, b_l1, b_h0, b_h1]).serialize(output)
|
||||
}
|
||||
Self::Format35C {
|
||||
|
|
@ -1053,6 +1103,41 @@ impl Serializable for Instruction {
|
|||
va.serialize(output)?;
|
||||
b.serialize(output)
|
||||
}
|
||||
Self::FormatPackedSwitchPayload { first_key, targets } => {
|
||||
0x0100u16.serialize(output)?;
|
||||
let size = targets.len() as u16;
|
||||
size.serialize(output)?;
|
||||
first_key.serialize(output)?;
|
||||
for target in targets {
|
||||
target.serialize(output)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Self::FormatSparseSwitchPayload { key_targets } => {
|
||||
0x0200u16.serialize(output)?;
|
||||
let size = key_targets.len() as u16;
|
||||
size.serialize(output)?;
|
||||
for (key, _) in key_targets {
|
||||
key.serialize(output)?;
|
||||
}
|
||||
for (_, target) in key_targets {
|
||||
target.serialize(output)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Self::FormatFillArrayDataPayload { elt_width, data } => {
|
||||
0x0300u16.serialize(output)?;
|
||||
elt_width.serialize(output)?;
|
||||
let size = (data.len() / *elt_width as usize) as u32;
|
||||
size.serialize(output)?;
|
||||
for d in data {
|
||||
d.serialize(output)?;
|
||||
}
|
||||
if data.len() % 2 != 0 {
|
||||
0u8.serialize(output)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1061,13 +1146,18 @@ impl Serializable for Instruction {
|
|||
Error::SerializationError(format!("Failled to get position in steam: {err}"))
|
||||
})?;
|
||||
let op = u8::deserialize(input)?;
|
||||
let _ = u8::deserialize(input)?;
|
||||
let id = u8::deserialize(input)?;
|
||||
input.seek(SeekFrom::Start(pos)).map_err(|err| {
|
||||
Error::SerializationError(format!("Failled to get to position in steam: {err}"))
|
||||
})?;
|
||||
|
||||
match op {
|
||||
0x00 => Self::deserialize_10x(input),
|
||||
0x00 => match id {
|
||||
0x01 => Self::deserialize_packed_switch(input),
|
||||
0x02 => Self::deserialize_sparse_switch(input),
|
||||
0x03 => Self::deserialize_fill_array_data(input),
|
||||
_ => Self::deserialize_10x(input),
|
||||
},
|
||||
0x01 => Self::deserialize_12x(input),
|
||||
0x02 => Self::deserialize_22x(input),
|
||||
0x03 => Self::deserialize_32x(input),
|
||||
|
|
@ -1172,6 +1262,11 @@ impl Serializable for Instruction {
|
|||
Self::Format45CC { .. } => 8,
|
||||
Self::Format4RCC { .. } => 8,
|
||||
Self::Format51L { .. } => 10,
|
||||
Self::FormatPackedSwitchPayload { targets, .. } => 2 + 2 + 4 + targets.len() * 4,
|
||||
Self::FormatSparseSwitchPayload { key_targets } => 2 + 2 + key_targets.len() * 8,
|
||||
Self::FormatFillArrayDataPayload { data, .. } => {
|
||||
2 + 2 + 4 + data.len() + (data.len() % 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue