bug fix bug fix bug fix WIP

This commit is contained in:
Jean-Marie Mineau 2024-01-03 18:00:36 +01:00
parent b30e91b86a
commit b17a84212f
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
5 changed files with 153 additions and 151 deletions

View file

@ -742,7 +742,7 @@ impl Apk {
addr: usize, addr: usize,
insns_ref: &HashMap<usize, &InsFormat>, insns_ref: &HashMap<usize, &InsFormat>,
dex: &DexFileReader, dex: &DexFileReader,
) -> Result<(instructions::Instruction, HashMap<usize, String>)> { ) -> Result<Option<(instructions::Instruction, HashMap<usize, String>)>> {
use crate::instructions::*; use crate::instructions::*;
use InsFormat::*; use InsFormat::*;
let mut labels = HashMap::new(); let mut labels = HashMap::new();
@ -867,7 +867,7 @@ impl Apk {
} else { } else {
bail!( bail!(
"Found fill-array-data-payload v{va} +{b} at 0x{addr:x}, \ "Found fill-array-data-payload v{va} +{b} at 0x{addr:x}, \
no instruction found at {data_addr:x}" no instruction found at 0x{data_addr:x}"
) )
} }
} }
@ -881,11 +881,11 @@ impl Apk {
} else { } else {
addr - (-a as usize) addr - (-a as usize)
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::Goto(Goto::new(label)) Instruction::Goto(Goto::new(label))
@ -899,11 +899,11 @@ impl Apk {
} else { } else {
addr - (-a as usize) addr - (-a as usize)
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::Goto(Goto::new(label)) Instruction::Goto(Goto::new(label))
@ -917,11 +917,11 @@ impl Apk {
} else { } else {
addr - (-a as usize) addr - (-a as usize)
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::Goto(Goto::new(label)) Instruction::Goto(Goto::new(label))
@ -954,12 +954,12 @@ impl Apk {
} else { } else {
addr - (-target as usize) addr - (-target as usize)
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!( bail!(
"There is already a label at 0x{dest_addr:80X} with \ "There is already a label at 0x{dest_addr:08X} with \
an invalid name" an invalid name"
); );
} }
@ -1008,12 +1008,12 @@ impl Apk {
} else { } else {
addr - (-target as usize) addr - (-target as usize)
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!( bail!(
"There is already a label at 0x{dest_addr:80X} with \ "There is already a label at 0x{dest_addr:08X} with \
an invalid name" an invalid name"
); );
} }
@ -1079,13 +1079,13 @@ impl Apk {
let dest_addr = if c > 0 { let dest_addr = if c > 0 {
addr + c as usize addr + c as usize
} else { } else {
addr - c as usize addr - (-c) as usize
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::IfEq(IfEq::new(va, vb, label)?) Instruction::IfEq(IfEq::new(va, vb, label)?)
@ -1105,13 +1105,13 @@ impl Apk {
let dest_addr = if c > 0 { let dest_addr = if c > 0 {
addr + c as usize addr + c as usize
} else { } else {
addr - c as usize addr - (-c) as usize
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::IfNe(IfNe::new(va, vb, label)?) Instruction::IfNe(IfNe::new(va, vb, label)?)
@ -1131,13 +1131,13 @@ impl Apk {
let dest_addr = if c > 0 { let dest_addr = if c > 0 {
addr + c as usize addr + c as usize
} else { } else {
addr - c as usize addr - (-c) as usize
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::IfLt(IfLt::new(va, vb, label)?) Instruction::IfLt(IfLt::new(va, vb, label)?)
@ -1157,13 +1157,13 @@ impl Apk {
let dest_addr = if c > 0 { let dest_addr = if c > 0 {
addr + c as usize addr + c as usize
} else { } else {
addr - c as usize addr - (-c) as usize
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::IfGe(IfGe::new(va, vb, label)?) Instruction::IfGe(IfGe::new(va, vb, label)?)
@ -1183,13 +1183,13 @@ impl Apk {
let dest_addr = if c > 0 { let dest_addr = if c > 0 {
addr + c as usize addr + c as usize
} else { } else {
addr - c as usize addr - (-c) as usize
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::IfGt(IfGt::new(va, vb, label)?) Instruction::IfGt(IfGt::new(va, vb, label)?)
@ -1209,13 +1209,13 @@ impl Apk {
let dest_addr = if c > 0 { let dest_addr = if c > 0 {
addr + c as usize addr + c as usize
} else { } else {
addr - c as usize addr - (-c) as usize
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::IfLe(IfLe::new(va, vb, label)?) Instruction::IfLe(IfLe::new(va, vb, label)?)
@ -1230,13 +1230,13 @@ impl Apk {
let dest_addr = if b > 0 { let dest_addr = if b > 0 {
addr + b as usize addr + b as usize
} else { } else {
addr - b as usize addr - (-b) as usize
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::IfEqZ(IfEqZ::new(va, label)?) Instruction::IfEqZ(IfEqZ::new(va, label)?)
@ -1251,13 +1251,13 @@ impl Apk {
let dest_addr = if b > 0 { let dest_addr = if b > 0 {
addr + b as usize addr + b as usize
} else { } else {
addr - b as usize addr - (-b) as usize
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::IfNeZ(IfNeZ::new(va, label)?) Instruction::IfNeZ(IfNeZ::new(va, label)?)
@ -1272,13 +1272,13 @@ impl Apk {
let dest_addr = if b > 0 { let dest_addr = if b > 0 {
addr + b as usize addr + b as usize
} else { } else {
addr - b as usize addr - (-b) as usize
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::IfLtZ(IfLtZ::new(va, label)?) Instruction::IfLtZ(IfLtZ::new(va, label)?)
@ -1293,13 +1293,13 @@ impl Apk {
let dest_addr = if b > 0 { let dest_addr = if b > 0 {
addr + b as usize addr + b as usize
} else { } else {
addr - b as usize addr - (-b) as usize
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::IfGeZ(IfGeZ::new(va, label)?) Instruction::IfGeZ(IfGeZ::new(va, label)?)
@ -1314,13 +1314,13 @@ impl Apk {
let dest_addr = if b > 0 { let dest_addr = if b > 0 {
addr + b as usize addr + b as usize
} else { } else {
addr - b as usize addr - (-b) as usize
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::IfGtZ(IfGtZ::new(va, label)?) Instruction::IfGtZ(IfGtZ::new(va, label)?)
@ -1335,13 +1335,13 @@ impl Apk {
let dest_addr = if b > 0 { let dest_addr = if b > 0 {
addr + b as usize addr + b as usize
} else { } else {
addr - b as usize addr - (-b) as usize
}; };
let label = format!("label_{dest_addr:80X}"); let label = format!("label_{dest_addr:08X}");
if let Some(old_label) = labels.insert(dest_addr, label.clone()) { if let Some(old_label) = labels.insert(dest_addr, label.clone()) {
if old_label != label { if old_label != label {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("There is already a label at 0x{dest_addr:80X} with an invalid name"); bail!("There is already a label at 0x{dest_addr:08X} with an invalid name");
} }
} }
Instruction::IfLeZ(IfLeZ::new(va, label)?) Instruction::IfLeZ(IfLeZ::new(va, label)?)
@ -2154,12 +2154,15 @@ impl Apk {
let proto = Self::get_id_method_type_from_idx(b as usize, dex)?; let proto = Self::get_id_method_type_from_idx(b as usize, dex)?;
Instruction::ConstMethodType(ConstMethodType::new(va, proto)) Instruction::ConstMethodType(ConstMethodType::new(va, proto))
} }
FormatPackedSwitchPayload { .. } => bail!("{format:?} is a pseudo instruction"), FormatPackedSwitchPayload { .. } => return Ok(None),
FormatSparseSwitchPayload { .. } => bail!("{format:?} is a pseudo instruction"), //bail!("{format:?} is a pseudo instruction"),
FormatFillArrayDataPayload { .. } => bail!("{format:?} is a pseudo instruction"), FormatSparseSwitchPayload { .. } => return Ok(None),
//bail!("{format:?} is a pseudo instruction"),
FormatFillArrayDataPayload { .. } => return Ok(None),
//bail!("{format:?} is a pseudo instruction"),
_ => bail!("Unknwon instruction found at {addr}: {format:?}"), _ => bail!("Unknwon instruction found at {addr}: {format:?}"),
}; };
Ok((ins, labels)) Ok(Some((ins, labels)))
} }
/// Return a [`Code`] from it's offset in the dex file. /// Return a [`Code`] from it's offset in the dex file.
@ -2192,10 +2195,11 @@ impl Apk {
))? ))?
.get_handler_at_offset(handler_off)?; .get_handler_at_offset(handler_off)?;
let default_handler = if let Some(Uleb128(addr)) = *catch_all_addr { let default_handler = if let Some(Uleb128(addr)) = *catch_all_addr {
let label = format!("label_{addr:80X}"); let label = format!("label_{addr:08X}");
if let Some(label_) = labels.insert(addr as usize, label.clone()) { if let Some(label_) = labels.insert(addr as usize, label.clone()) {
if label_ != label { if label_ != label {
bail!("Label collision at 0x{addr:80X}: {label_} and {label}"); // TODO: that's an internal error
bail!("Label collision at 0x{addr:08X}: {label_} and {label}");
} }
} }
Some(label) Some(label)
@ -2208,20 +2212,27 @@ impl Apk {
addr: Uleb128(addr), addr: Uleb128(addr),
} in handlers.iter().cloned() } in handlers.iter().cloned()
{ {
let label = format!("label_{addr:80X}"); let label = format!("label_{addr:08X}");
if let Some(label_) = labels.insert(addr as usize, label.clone()) { if let Some(label_) = labels.insert(addr as usize, label.clone()) {
if label_ != label { if label_ != label {
bail!("Label collision at 0x{addr:80X}: {label_} and {label}"); // TODO: that's an internal error
bail!("Label collision at 0x{addr:08X}: {label_} and {label}");
} }
} }
handlers_.push((Self::get_id_type_from_idx(type_idx as usize, dex)?, label)) handlers_.push((Self::get_id_type_from_idx(type_idx as usize, dex)?, label))
} }
let dest_addr = start_addr + insn_count as u32; let dest_addr = start_addr + insn_count as u32;
let end_label = format!("label_{dest_addr:80X}"); let end_label = format!("label_{dest_addr:08X}");
if let Some(label_) = labels.insert(dest_addr as usize, end_label.clone()) {
if label_ != end_label {
// TODO: that's an internal error
bail!("Label collision at 0x{dest_addr:08X}: {label_} and {end_label}");
}
}
let try_ = Instruction::Try(Try::new(end_label, handlers_, default_handler)); let try_ = Instruction::Try(Try::new(end_label, handlers_, default_handler));
if let Some(try__) = tries.insert(start_addr as usize, try_.clone()) { if let Some(try__) = tries.insert(start_addr as usize, try_.clone()) {
bail!( bail!(
"Found two try blocks at the same address 0x{start_addr:80X}: \ "Found two try blocks at the same address 0x{start_addr:08X}: \
{try__:?}, {try_:?}" {try__:?}, {try_:?}"
); );
} }
@ -2231,25 +2242,27 @@ impl Apk {
let mut addr = 0; let mut addr = 0;
for ins_f in &code_item.insns { for ins_f in &code_item.insns {
instructions_raw.insert(addr, ins_f); instructions_raw.insert(addr, ins_f);
addr += ins_f.size(); addr += ins_f.size() / 2;
} }
let mut instructions = vec![]; let mut instructions = vec![];
addr = 0; addr = 0;
for ins_f in &code_item.insns { for ins_f in &code_item.insns {
let (ins, ins_labels) = if let Some((ins, ins_labels)) =
Self::instruction_format_to_instruction(ins_f, addr, &instructions_raw, dex)?; Self::instruction_format_to_instruction(ins_f, addr, &instructions_raw, dex)?
{
instructions.push((addr, ins)); instructions.push((addr, ins));
addr += ins_f.size() / 2; addr += ins_f.size() / 2;
for (key, val) in &ins_labels { for (key, val) in &ins_labels {
if let Some(val_) = ins_labels.get(key) { if let Some(val_) = ins_labels.get(key) {
if val_ != val { if val_ != val {
// TODO: internal error, panic? // TODO: internal error, panic?
bail!("Label collision at 0x{key:80X}: {val_} and {val}"); bail!("Label collision at 0x{key:08X}: {val_} and {val}");
} }
} }
} }
labels.extend(ins_labels); labels.extend(ins_labels);
} }
}
let mut insns = vec![]; let mut insns = vec![];
for (addr, ins) in instructions { for (addr, ins) in instructions {
if let Some(try_) = tries.remove(&addr) { if let Some(try_) = tries.remove(&addr) {
@ -2260,6 +2273,20 @@ impl Apk {
} }
insns.push(ins); insns.push(ins);
} }
// notice: addr is not the same as the one in the loop, this one is computed previously
// and is the addr after the last ins.
if let Some(try_) = tries.remove(&addr) {
insns.push(try_);
}
if let Some(label) = labels.remove(&addr) {
insns.push(Instruction::Label(Label::new(label)));
}
if !labels.is_empty() {
bail!("Could not put all label as instructions (label out of insns?)");
}
if !tries.is_empty() {
bail!("Could not put all try block as instructions (addr not aligned with ins?)");
}
Ok(Code { Ok(Code {
registers_size: code_item.registers_size, registers_size: code_item.registers_size,
ins_size: code_item.ins_size, ins_size: code_item.ins_size,

View file

@ -377,7 +377,6 @@ impl DexWriter {
.unwrap() .unwrap()
.clone() .clone()
}; };
// Estimate instructions addresses // Estimate instructions addresses
let mut min_addr = 0; let mut min_addr = 0;
let mut max_addr = 0; let mut max_addr = 0;
@ -1226,7 +1225,8 @@ impl DexWriter {
let try_item = TryItem { let try_item = TryItem {
start_addr: addr as u32, start_addr: addr as u32,
insn_count: (end_block_addr - addr) as u16, insn_count: (end_block_addr - addr) as u16,
handler_off: handler_off as u16, handler_off: handler_off as u16, // will be ajusted once the size of the
// handler list object is known
}; };
tries.push(try_item); tries.push(try_item);
let mut catches = EncodedCatchHandler { let mut catches = EncodedCatchHandler {
@ -1279,6 +1279,10 @@ impl DexWriter {
} }
insns.extend(payloads); insns.extend(payloads);
for try_ in &mut tries {
try_.handler_off += handlers.size_field().size() as u16;
}
let debug_info_off = if code.debug_info.is_empty() { let debug_info_off = if code.debug_info.is_empty() {
0 0
} else { } else {

View file

@ -8009,21 +8009,9 @@ impl IfEqZ {
#[new] #[new]
pub fn new(a: u8, label: String) -> Result<Self> { pub fn new(a: u8, label: String) -> Result<Self> {
let ins = Self { a, label }; let ins = Self { a, label };
ins.sanity_check()?;
Ok(ins) Ok(ins)
} }
pub fn sanity_check(&self) -> Result<()> {
if self.a & 0b1111_0000 != 0 {
Err(anyhow!(
"if-eqz uses registers indexed on 4 bits, found {}",
self.a
))
} else {
Ok(())
}
}
pub fn __str__(&self) -> String { pub fn __str__(&self) -> String {
format!("if-eqz {} {}", self.a, self.label) format!("if-eqz {} {}", self.a, self.label)
} }
@ -8122,21 +8110,9 @@ impl IfNeZ {
#[new] #[new]
pub fn new(a: u8, label: String) -> Result<Self> { pub fn new(a: u8, label: String) -> Result<Self> {
let ins = Self { a, label }; let ins = Self { a, label };
ins.sanity_check()?;
Ok(ins) Ok(ins)
} }
pub fn sanity_check(&self) -> Result<()> {
if self.a & 0b1111_0000 != 0 {
Err(anyhow!(
"if-neq uses registers indexed on 4 bits, found {}",
self.a
))
} else {
Ok(())
}
}
pub fn __str__(&self) -> String { pub fn __str__(&self) -> String {
format!("if-neq {} {}", self.a, self.label) format!("if-neq {} {}", self.a, self.label)
} }
@ -8235,21 +8211,9 @@ impl IfLtZ {
#[new] #[new]
pub fn new(a: u8, label: String) -> Result<Self> { pub fn new(a: u8, label: String) -> Result<Self> {
let ins = Self { a, label }; let ins = Self { a, label };
ins.sanity_check()?;
Ok(ins) Ok(ins)
} }
pub fn sanity_check(&self) -> Result<()> {
if self.a & 0b1111_0000 != 0 {
Err(anyhow!(
"if-lt uses registers indexed on 4 bits, found {}",
self.a
))
} else {
Ok(())
}
}
pub fn __str__(&self) -> String { pub fn __str__(&self) -> String {
format!("if-lt {} {}", self.a, self.label) format!("if-lt {} {}", self.a, self.label)
} }
@ -8348,21 +8312,9 @@ impl IfGeZ {
#[new] #[new]
pub fn new(a: u8, label: String) -> Result<Self> { pub fn new(a: u8, label: String) -> Result<Self> {
let ins = Self { a, label }; let ins = Self { a, label };
ins.sanity_check()?;
Ok(ins) Ok(ins)
} }
pub fn sanity_check(&self) -> Result<()> {
if self.a & 0b1111_0000 != 0 {
Err(anyhow!(
"if-ge uses registers indexed on 4 bits, found {}",
self.a
))
} else {
Ok(())
}
}
pub fn __str__(&self) -> String { pub fn __str__(&self) -> String {
format!("if-ge {} {}", self.a, self.label) format!("if-ge {} {}", self.a, self.label)
} }
@ -8461,21 +8413,9 @@ impl IfGtZ {
#[new] #[new]
pub fn new(a: u8, label: String) -> Result<Self> { pub fn new(a: u8, label: String) -> Result<Self> {
let ins = Self { a, label }; let ins = Self { a, label };
ins.sanity_check()?;
Ok(ins) Ok(ins)
} }
pub fn sanity_check(&self) -> Result<()> {
if self.a & 0b1111_0000 != 0 {
Err(anyhow!(
"if-gt uses registers indexed on 4 bits, found {}",
self.a
))
} else {
Ok(())
}
}
pub fn __str__(&self) -> String { pub fn __str__(&self) -> String {
format!("if-gt {} {}", self.a, self.label) format!("if-gt {} {}", self.a, self.label)
} }
@ -8574,21 +8514,9 @@ impl IfLeZ {
#[new] #[new]
pub fn new(a: u8, label: String) -> Result<Self> { pub fn new(a: u8, label: String) -> Result<Self> {
let ins = Self { a, label }; let ins = Self { a, label };
ins.sanity_check()?;
Ok(ins) Ok(ins)
} }
pub fn sanity_check(&self) -> Result<()> {
if self.a & 0b1111_0000 != 0 {
Err(anyhow!(
"if-le uses registers indexed on 4 bits, found {}",
self.a
))
} else {
Ok(())
}
}
pub fn __str__(&self) -> String { pub fn __str__(&self) -> String {
format!("if-le {} {}", self.a, self.label) format!("if-le {} {}", self.a, self.label)
} }

View file

@ -35,12 +35,16 @@ impl CodeItem {
pub fn sanity_check(&self) -> Result<()> { pub fn sanity_check(&self) -> Result<()> {
if self.tries.is_empty() && self.handlers.is_some() { if self.tries.is_empty() && self.handlers.is_some() {
return Err(Error::InconsistantStruct( return Err(Error::InconsistantStruct(
"CodeItem cannot have a `handlers` value if `tries_size` is 0 (CodeItem.tries is empty)".into() "CodeItem cannot have a `handlers` value if `tries_size` \
is 0 (CodeItem.tries is empty)"
.into(),
)); ));
} }
if !self.tries.is_empty() && self.handlers.is_none() { if !self.tries.is_empty() && self.handlers.is_none() {
return Err(Error::InconsistantStruct( return Err(Error::InconsistantStruct(
"CodeItem must have a `handlers` value if `tries_size` is not 0 (CodeItem.tries not empty)".into() "CodeItem must have a `handlers` value if `tries_size` \
is not 0 (CodeItem.tries not empty)"
.into(),
)); ));
} }
let mut max_addr = 0; let mut max_addr = 0;
@ -48,7 +52,9 @@ impl CodeItem {
let addr = item.start_addr; let addr = item.start_addr;
if addr < max_addr { if addr < max_addr {
return Err(Error::InconsistantStruct( return Err(Error::InconsistantStruct(
"try_item in a code_item must be non overlapping and sorted from low to high address".into() "try_item in a code_item must be non overlapping and \
sorted from low to high address"
.into(),
)); ));
} }
max_addr = addr + (item.insn_count as u32); max_addr = addr + (item.insn_count as u32);
@ -121,8 +127,10 @@ impl CodeItem {
} }
} }
if i < addresses.len() && addresses[i] < addr { if i < addresses.len() && addresses[i] < addr {
println!("{addresses:x?}");
return Err(Error::InconsistantStruct(format!( return Err(Error::InconsistantStruct(format!(
"Found an address in try block (0x{addr:x}) that does not align with an instruction" "Found an address in try block (0x{:x}) that does not align with an instruction",
addresses[i]
))); )));
} }
@ -170,11 +178,21 @@ impl Serializable for CodeItem {
let mut insns = vec![]; let mut insns = vec![];
let mut serialized_insns_size = 0; let mut serialized_insns_size = 0;
while serialized_insns_size != insns_size { while serialized_insns_size < insns_size {
let ins = Instruction::deserialize(input)?; let ins = Instruction::deserialize(input).map_err(|err| {
serialized_insns_size += ins.size() as u32; Error::DeserializationError(format!(
"Failed to deserialize instruction at 0x{serialized_insns_size:x}: {err}"
))
})?;
serialized_insns_size += ins.size() as u32 / 2;
insns.push(ins); insns.push(ins);
} }
if serialized_insns_size != insns_size {
return Err(Error::DeserializationError(format!(
"Failed to deserialize instructions, expected size of {insns_size} code \
units (16 bits), found at least {serialized_insns_size}"
)));
}
if tries_size != 0 && insns_size % 2 == 1 { if tries_size != 0 && insns_size % 2 == 1 {
let _ = u16::deserialize(input)?; let _ = u16::deserialize(input)?;
} }
@ -265,7 +283,8 @@ impl EncodedCatchHandlerList {
current_offset += handler.size(); current_offset += handler.size();
} }
Err(Error::InconsistantStruct(format!( Err(Error::InconsistantStruct(format!(
"Offset 0x{offset:x} does not match with the begining of a EncodedCatchHandler in this EncodedCatchHandlerList" "Offset 0x{offset:x} does not match with the begining of a \
EncodedCatchHandler in this EncodedCatchHandlerList"
))) )))
} }
} }

View file

@ -389,8 +389,11 @@ impl Instruction {
requires the first byte to be 0 found {v}" requires the first byte to be 0 found {v}"
))); )));
} }
/*
let [a_l0, a_l1, a_h0, a_h1] = i32::deserialize(input)?.to_be_bytes(); let [a_l0, a_l1, a_h0, a_h1] = i32::deserialize(input)?.to_be_bytes();
let a = i32::from_be_bytes([a_h0, a_h1, a_l0, a_l1]); let a = i32::from_be_bytes([a_h0, a_h1, a_l0, a_l1]);
*/
let a = i32::deserialize(input)?;
Ok(Self::Format30T { op, a }) Ok(Self::Format30T { op, a })
} }
@ -412,24 +415,33 @@ impl Instruction {
pub fn deserialize_31i(input: &mut dyn ReadSeek) -> Result<Self> { pub fn deserialize_31i(input: &mut dyn ReadSeek) -> Result<Self> {
let op = u8::deserialize(input)?; let op = u8::deserialize(input)?;
let va = u8::deserialize(input)?; let va = u8::deserialize(input)?;
let b = i32::deserialize(input)?;
/*
let [b_l0, b_l1, b_h0, b_h1] = i32::deserialize(input)?.to_be_bytes(); let [b_l0, b_l1, b_h0, b_h1] = i32::deserialize(input)?.to_be_bytes();
let b = i32::from_be_bytes([b_h0, b_h1, b_l0, b_l1]); let b = i32::from_be_bytes([b_h0, b_h1, b_l0, b_l1]);
*/
Ok(Self::Format31I { va, op, b }) Ok(Self::Format31I { va, op, b })
} }
pub fn deserialize_31t(input: &mut dyn ReadSeek) -> Result<Self> { pub fn deserialize_31t(input: &mut dyn ReadSeek) -> Result<Self> {
let op = u8::deserialize(input)?; let op = u8::deserialize(input)?;
let va = u8::deserialize(input)?; let va = u8::deserialize(input)?;
let b = i32::deserialize(input)?;
/*
let [b_l0, b_l1, b_h0, b_h1] = i32::deserialize(input)?.to_be_bytes(); let [b_l0, b_l1, b_h0, b_h1] = i32::deserialize(input)?.to_be_bytes();
let b = i32::from_be_bytes([b_h0, b_h1, b_l0, b_l1]); let b = i32::from_be_bytes([b_h0, b_h1, b_l0, b_l1]);
*/
Ok(Self::Format31T { va, op, b }) Ok(Self::Format31T { va, op, b })
} }
pub fn deserialize_31c(input: &mut dyn ReadSeek) -> Result<Self> { pub fn deserialize_31c(input: &mut dyn ReadSeek) -> Result<Self> {
let op = u8::deserialize(input)?; let op = u8::deserialize(input)?;
let va = u8::deserialize(input)?; let va = u8::deserialize(input)?;
let b = u32::deserialize(input)?;
/*
let [b_l0, b_l1, b_h0, b_h1] = u32::deserialize(input)?.to_be_bytes(); let [b_l0, b_l1, b_h0, b_h1] = u32::deserialize(input)?.to_be_bytes();
let b = u32::from_be_bytes([b_h0, b_h1, b_l0, b_l1]); let b = u32::from_be_bytes([b_h0, b_h1, b_l0, b_l1]);
*/
Ok(Self::Format31C { va, op, b }) Ok(Self::Format31C { va, op, b })
} }
@ -824,8 +836,11 @@ impl Serializable for Instruction {
Self::Format30T { op, a } => { Self::Format30T { op, a } => {
op.serialize(output)?; op.serialize(output)?;
0u8.serialize(output)?; 0u8.serialize(output)?;
/*
let [a_h0, a_h1, a_l0, a_l1] = a.to_be_bytes(); let [a_h0, a_h1, a_l0, a_l1] = a.to_be_bytes();
u32::from_be_bytes([a_l0, a_l1, a_h0, a_h1]).serialize(output) u32::from_be_bytes([a_l0, a_l1, a_h0, a_h1]).serialize(output)
*/
a.serialize(output)
} }
Self::Format32X { op, va, vb } => { Self::Format32X { op, va, vb } => {
op.serialize(output)?; op.serialize(output)?;
@ -836,20 +851,29 @@ impl Serializable for Instruction {
Self::Format31I { va, op, b } => { Self::Format31I { va, op, b } => {
op.serialize(output)?; op.serialize(output)?;
va.serialize(output)?; va.serialize(output)?;
/*
let [b_h0, b_h1, b_l0, b_l1] = b.to_be_bytes(); let [b_h0, b_h1, b_l0, b_l1] = b.to_be_bytes();
u32::from_be_bytes([b_l0, b_l1, b_h0, b_h1]).serialize(output) u32::from_be_bytes([b_l0, b_l1, b_h0, b_h1]).serialize(output)
*/
b.serialize(output)
} }
Self::Format31T { va, op, b } => { Self::Format31T { va, op, b } => {
op.serialize(output)?; op.serialize(output)?;
va.serialize(output)?; va.serialize(output)?;
/*
let [b_h0, b_h1, b_l0, b_l1] = b.to_be_bytes(); let [b_h0, b_h1, b_l0, b_l1] = b.to_be_bytes();
u32::from_be_bytes([b_l0, b_l1, b_h0, b_h1]).serialize(output) u32::from_be_bytes([b_l0, b_l1, b_h0, b_h1]).serialize(output)
*/
b.serialize(output)
} }
Self::Format31C { va, op, b } => { Self::Format31C { va, op, b } => {
op.serialize(output)?; op.serialize(output)?;
va.serialize(output)?; va.serialize(output)?;
/*
let [b_h0, b_h1, b_l0, b_l1] = b.to_be_bytes(); let [b_h0, b_h1, b_l0, b_l1] = b.to_be_bytes();
u32::from_be_bytes([b_l0, b_l1, b_h0, b_h1]).serialize(output) u32::from_be_bytes([b_l0, b_l1, b_h0, b_h1]).serialize(output)
*/
b.serialize(output)
} }
Self::Format35C { Self::Format35C {
a, a,