Skip to main content

macho2/command/
note.rs

1use nom::number::complete::{le_u32, le_u64};
2
3use crate::{helpers::string_upto_null_terminator, macho::MachOResult};
4
5use super::{pad_to_size, LCLoadCommand, LoadCommandBase, LoadCommandParser};
6
7#[derive(Debug, PartialEq, Eq)]
8pub struct NoteCommand {
9    pub cmd: LCLoadCommand,
10    pub cmdsize: u32,
11    pub data_owner: String,
12    pub offset: u64,
13    pub size: u64,
14}
15
16impl LoadCommandParser for NoteCommand {
17    fn parse(ldcmd: &[u8]) -> MachOResult<Self> {
18        let (cursor, base) = LoadCommandBase::parse(ldcmd)?;
19        let (cursor, data_owner_offset) = le_u32(cursor)?;
20        let (cursor, offset) = le_u64(cursor)?;
21        let (_, size) = le_u64(cursor)?;
22
23        let (_, data_owner) =
24            string_upto_null_terminator(&ldcmd[data_owner_offset as usize..])?;
25
26        Ok(
27            NoteCommand {
28                cmd: base.cmd,
29                cmdsize: base.cmdsize,
30                data_owner,
31                offset,
32                size,
33            },
34        )
35    }
36
37    fn serialize(&self) -> Vec<u8> {
38        let mut buf = Vec::new();
39        buf.extend(self.cmd.serialize());
40        buf.extend(self.cmdsize.to_le_bytes());
41        buf.extend((0x1C as u32).to_le_bytes()); // data_owner offset
42        buf.extend(self.offset.to_le_bytes());
43        buf.extend(self.size.to_le_bytes());
44        buf.extend(self.data_owner.as_bytes());
45        buf.push(0);
46        pad_to_size(&mut buf, self.cmdsize as usize);
47        buf
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54    use crate::command::LCLoadCommand;
55
56    #[test]
57    fn test_note_serialise() {
58        let cmd = NoteCommand {
59            cmd: LCLoadCommand::LcNote,
60            cmdsize: 47,
61            data_owner: "com.apple.dt.Xcode".to_string(),
62            offset: 0,
63            size: 0,
64        };
65
66        let serialized = cmd.serialize();
67        let deserialized = NoteCommand::parse(&serialized).unwrap();
68        assert_eq!(cmd, deserialized);
69    }
70}