diff --git a/androscalpel_serializer/src/debug.rs b/androscalpel_serializer/src/debug.rs new file mode 100644 index 0000000..7ee8c0d --- /dev/null +++ b/androscalpel_serializer/src/debug.rs @@ -0,0 +1,94 @@ +//! Debug structs + +use crate as androscalpel_serializer; +use crate::{ReadSeek, Result, Serializable, SerializableUntil, Sleb128, Uleb128, Uleb128p1}; +use std::io::Write; + +/// https://source.android.com/docs/core/runtime/dex-format#debug-info-item +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct DebugInfoItem { + pub line_start: Uleb128, + //pub parameters_size: Uleb128, + pub parameter_names: Vec, + /// List of opcode. Notice that the trailling [`DbgBytecode::EndSequence`] + /// is not stored in this vec. + pub bytecode: Vec, +} + +#[derive(Serializable, Debug, PartialEq, Eq, Copy, Clone)] +#[prefix_type(u8)] +pub enum DbgBytecode { + #[prefix(0x00)] + EndSequence, + #[prefix(0x01)] + AdvancePC { addr_diff: Uleb128 }, + #[prefix(0x02)] + AdvanceLine { line_diff: Sleb128 }, + #[prefix(0x03)] + StartLocal { + register_num: Uleb128, + name_idx: Uleb128p1, + type_idx: Uleb128p1, + }, + #[prefix(0x04)] + StartLocalExtended { + register_num: Uleb128, + name_idx: Uleb128p1, + type_idx: Uleb128p1, + sig_idx: Uleb128p1, + }, + #[prefix(0x05)] + EndLocal { register_num: Uleb128 }, + #[prefix(0x06)] + RestartLocal { register_num: Uleb128 }, + #[prefix(0x07)] + SetPrologueEnd, + #[prefix(0x08)] + SetEpilogueBegin, + #[prefix(0x09)] + SetFile { name_idx: Uleb128p1 }, + #[default_variant] + SpecialOpcode(u8), +} + +impl DebugInfoItem { + pub fn parameters_size_field(&self) -> Uleb128 { + Uleb128(self.parameter_names.len() as u32) + } +} + +impl Serializable for DebugInfoItem { + fn serialize(&self, output: &mut dyn Write) -> Result<()> { + self.line_start.serialize(output)?; + self.parameters_size_field().serialize(output)?; + for item in &self.parameter_names { + item.serialize(output)?; + } + self.bytecode.serialize(output, DbgBytecode::EndSequence)?; + Ok(()) + } + fn deserialize(input: &mut dyn ReadSeek) -> Result { + let line_start = Uleb128::deserialize(input)?; + let Uleb128(parameters_size) = Uleb128::deserialize(input)?; + let mut parameter_names = vec![]; + for _ in 0..parameters_size { + parameter_names.push(Uleb128p1::deserialize(input)?); + } + let bytecode = Vec::::deserialize(input, DbgBytecode::EndSequence)?; + Ok(Self { + line_start, + parameter_names, + bytecode, + }) + } + fn size(&self) -> usize { + self.line_start.size() + + self.parameters_size_field().size() + + self + .parameter_names + .iter() + .map(|param| param.size()) + .sum::() + + self.bytecode.size(DbgBytecode::EndSequence) + } +} diff --git a/androscalpel_serializer/src/lib.rs b/androscalpel_serializer/src/lib.rs index 0ec4bef..44a449e 100644 --- a/androscalpel_serializer/src/lib.rs +++ b/androscalpel_serializer/src/lib.rs @@ -2,6 +2,7 @@ pub mod annotation; pub mod array; pub mod constant; pub mod core; +pub mod debug; pub mod items; pub mod value; @@ -11,5 +12,6 @@ pub use crate::core::*; pub use annotation::*; pub use array::*; pub use constant::*; +pub use debug::*; pub use items::*; pub use value::*; diff --git a/androscalpel_serializer_derive/src/lib.rs b/androscalpel_serializer_derive/src/lib.rs index 76be5c0..a182d31 100644 --- a/androscalpel_serializer_derive/src/lib.rs +++ b/androscalpel_serializer_derive/src/lib.rs @@ -131,11 +131,12 @@ pub fn derive_serializable(input: proc_macro::TokenStream) -> proc_macro::TokenS #implem_serialize } - #[allow(clippy::single_element_loop, clippy::let_and_return)] + #[allow(clippy::single_element_loop, clippy::let_and_return, clippy::needless_return)] fn deserialize(input: &mut dyn androscalpel_serializer::ReadSeek) -> androscalpel_serializer::Result { #implem_deserialize } + #[allow(clippy::identity_op)] fn size(&self) -> usize { #implem_size }