add instruction enum to code item
This commit is contained in:
parent
ee7cf4d325
commit
81c8d0a8ec
2 changed files with 122 additions and 39 deletions
|
|
@ -1,7 +1,7 @@
|
|||
//! Code items
|
||||
|
||||
use crate as androscalpel_serializer;
|
||||
use crate::{Error, ReadSeek, Result, Serializable, Sleb128, Uleb128};
|
||||
use crate::{Error, Instruction, ReadSeek, Result, Serializable, Sleb128, Uleb128};
|
||||
use log::debug;
|
||||
use std::io::Write;
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ pub struct CodeItem {
|
|||
/// 0 if no debug info, else offset to a [`crate::DebugInfoItem`].
|
||||
pub debug_info_off: u32,
|
||||
// pub insns_size: u32,
|
||||
pub insns: Vec<u16>,
|
||||
pub insns: Vec<Instruction>,
|
||||
// pub padding: Vec<u8>,
|
||||
/// try items must refere to non overlapping range an order from low to hight addresses.
|
||||
pub tries: Vec<TryItem>,
|
||||
|
|
@ -29,7 +29,7 @@ impl CodeItem {
|
|||
}
|
||||
|
||||
pub fn insns_size_field(&self) -> u32 {
|
||||
self.insns.len() as u32
|
||||
self.insns.iter().map(|ins| ins.size() as u32).sum::<u32>() / 2
|
||||
}
|
||||
|
||||
pub fn sanity_check(&self) -> Result<()> {
|
||||
|
|
@ -56,7 +56,7 @@ impl CodeItem {
|
|||
/*
|
||||
// Necessary? no in spec and apk in the wild seams to have try blocks spaming outside the
|
||||
// insns array.
|
||||
if max_addr > self.insns.len() as u32 {
|
||||
if max_addr > self.insns_size_field() {
|
||||
return Err(Error::InconsistantStruct(
|
||||
"found try_item whose block span outside of the insns array".into(),
|
||||
));
|
||||
|
|
@ -72,7 +72,7 @@ impl CodeItem {
|
|||
handler.sanity_check()?;
|
||||
for handler in &handler.handlers {
|
||||
// Necessary? no in spec
|
||||
if handler.addr.0 > self.insns.len() as u32 {
|
||||
if handler.addr.0 > self.insns_size_field() {
|
||||
return Err(Error::InconsistantStruct(
|
||||
"Found an handler whose address is outside of the insns array".into(),
|
||||
));
|
||||
|
|
@ -80,7 +80,7 @@ impl CodeItem {
|
|||
}
|
||||
if let Some(Uleb128(addr)) = handler.catch_all_addr {
|
||||
// Necessary? no in spec
|
||||
if addr > self.insns.len() as u32 {
|
||||
if addr > self.insns_size_field() {
|
||||
return Err(Error::InconsistantStruct(
|
||||
"Found a catch all handler whose address is outside of the insns array"
|
||||
.into(),
|
||||
|
|
@ -88,6 +88,46 @@ impl CodeItem {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut addresses = vec![];
|
||||
for try_ in &self.tries {
|
||||
addresses.push(try_.start_addr);
|
||||
addresses.push(try_.start_addr + try_.insn_count as u32);
|
||||
}
|
||||
for handler in &self.handlers {
|
||||
for catch in &handler.list {
|
||||
for EncodedTypeAddrPair {
|
||||
addr: Uleb128(addr),
|
||||
..
|
||||
} in &catch.handlers
|
||||
{
|
||||
addresses.push(*addr);
|
||||
}
|
||||
if let Some(Uleb128(addr)) = catch.catch_all_addr {
|
||||
addresses.push(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
addresses.sort();
|
||||
let mut addr = 0;
|
||||
let mut i = 0;
|
||||
while i < addresses.len() && addresses[i] == addr {
|
||||
i += 1;
|
||||
}
|
||||
for insn in &self.insns {
|
||||
addr += insn.size() as u32;
|
||||
while i < addresses.len() && addresses[i] == addr {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
if i < addresses.len() && addresses[i] < addr {
|
||||
return Err(Error::InconsistantStruct(format!(
|
||||
"Found an address in try block (0x{addr:x}) that does not align with an instruction"
|
||||
)));
|
||||
}
|
||||
|
||||
// TODO check goto addresses? pb: op code are not parsed so goto instruction are not known
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -127,9 +167,13 @@ impl Serializable for CodeItem {
|
|||
let tries_size = u16::deserialize(input)?;
|
||||
let debug_info_off = u32::deserialize(input)?;
|
||||
let insns_size = u32::deserialize(input)?;
|
||||
|
||||
let mut insns = vec![];
|
||||
for _ in 0..insns_size {
|
||||
insns.push(u16::deserialize(input)?);
|
||||
let mut serialized_insns_size = 0;
|
||||
while serialized_insns_size != insns_size {
|
||||
let ins = Instruction::deserialize(input)?;
|
||||
serialized_insns_size += ins.size() as u32;
|
||||
insns.push(ins);
|
||||
}
|
||||
if tries_size != 0 && insns_size % 2 == 1 {
|
||||
let _ = u16::deserialize(input)?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue