Skip to main content

macho2/command/
linkedit_data.rs

1use nom::{number::complete::le_u32, IResult};
2
3use super::{pad_to_size, LCLoadCommand, LoadCommandBase};
4
5#[derive(Debug, PartialEq, Eq)]
6pub struct LinkeditDataCommand {
7    pub cmd: LCLoadCommand,
8    pub cmdsize: u32,
9    pub dataoff: u32,
10    pub datasize: u32,
11}
12
13impl LinkeditDataCommand {
14    pub fn parse<'a>(ldcmd: &'a [u8]) -> IResult<&'a [u8], Self> {
15        let (cursor, base) = LoadCommandBase::parse(ldcmd)?;
16        let (cursor, dataoff) = le_u32(cursor)?;
17        let (cursor, datasize) = le_u32(cursor)?;
18
19        Ok((
20            cursor,
21            LinkeditDataCommand {
22                cmd: base.cmd,
23                cmdsize: base.cmdsize,
24                dataoff,
25                datasize,
26            },
27        ))
28    }
29
30    pub fn serialize(&self) -> Vec<u8> {
31        let mut buf = Vec::new();
32        buf.extend(self.cmd.serialize());
33        buf.extend(self.cmdsize.to_le_bytes());
34        buf.extend(self.dataoff.to_le_bytes());
35        buf.extend(self.datasize.to_le_bytes());
36        pad_to_size(&mut buf, self.cmdsize as usize);
37        buf
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44    use crate::command::LCLoadCommand;
45
46    #[test]
47    fn test_linkedit_serialise() {
48        let cmd = LinkeditDataCommand {
49            cmd: LCLoadCommand::LcDyldInfo,
50            cmdsize: 16,
51            dataoff: 0,
52            datasize: 0,
53        };
54
55        let serialized = cmd.serialize();
56        let deserialized = LinkeditDataCommand::parse(&serialized).unwrap().1;
57        assert_eq!(cmd, deserialized);
58    }
59}