//! Debug structs use crate as androscalpel_serializer; use crate::{ReadSeek, Result, Serializable, SerializableUntil, Sleb128, Uleb128, Uleb128p1}; use std::io::Write; /// #[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) } } #[cfg(test)] mod test { use super::DbgBytecode::*; use super::*; #[test] fn test_debug_reserialize() { let debug = DebugInfoItem { line_start: Uleb128(2902), parameter_names: vec![], bytecode: vec![ SpecialOpcode(14), AdvanceLine { line_diff: Sleb128(-1551), }, AdvancePC { addr_diff: Uleb128(51), }, SpecialOpcode(14), ], }; assert_eq!( debug, DebugInfoItem::deserialize_from_slice(&debug.serialize_to_vec().unwrap()).unwrap() ); } #[test] fn test_advance_line_reserialize() { let advance_line = AdvanceLine { line_diff: Sleb128(-1551), }; assert_eq!( advance_line, DbgBytecode::deserialize_from_slice(&advance_line.serialize_to_vec().unwrap()).unwrap() ); } }