elf_utilities/segment/
elf64.rs

1//! Type definitions for 64-bit ELF binaries.
2
3use std::collections::HashSet;
4
5use crate::*;
6
7use crate::segment::*;
8use serde::{Deserialize, Serialize};
9
10#[derive(
11    Default, Debug, Clone, Copy, Hash, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize,
12)]
13pub struct Segment64 {
14    pub header: Phdr64,
15}
16
17#[repr(C)]
18#[derive(Debug, Clone, Copy, Hash, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize)]
19pub struct Phdr64 {
20    /// Segment type
21    pub p_type: Elf64Word,
22
23    /// Segment flags
24    pub p_flags: Elf64Word,
25
26    /// Segment file offset
27    pub p_offset: Elf64Off,
28
29    /// Segment virtual address
30    pub p_vaddr: Elf64Addr,
31
32    /// Segment physical address
33    pub p_paddr: Elf64Addr,
34
35    /// Segment size in file
36    pub p_filesz: Elf64Xword,
37
38    /// Segment size in memory
39    pub p_memsz: Elf64Xword,
40
41    /// Segment alignment
42    pub p_align: Elf64Xword,
43}
44
45impl Default for Phdr64 {
46    fn default() -> Self {
47        Self {
48            p_type: 0,
49            p_flags: 0,
50            p_offset: 0,
51            p_vaddr: 0,
52            p_paddr: 0,
53            p_filesz: 0,
54            p_memsz: 0,
55            p_align: 0,
56        }
57    }
58}
59
60impl Phdr64 {
61    pub const SIZE: usize = 0x38;
62
63    // getter
64    pub fn get_type(&self) -> segment_type::Type {
65        segment_type::Type::from(self.p_type)
66    }
67    pub fn get_flags(&self) -> HashSet<segment::Flag> {
68        let mut mask: Elf64Word = 0b1;
69        let mut flags = HashSet::new();
70        loop {
71            if mask == 0 {
72                break;
73            }
74            if self.p_flags & mask != 0 {
75                flags.insert(segment::Flag::from(mask));
76            }
77            mask <<= 1;
78        }
79
80        flags
81    }
82
83    // setter
84    /// # Examples
85    ///
86    /// ```
87    /// use elf_utilities::segment;
88    ///
89    /// let mut phdr : segment::Phdr64 = Default::default();
90    /// phdr.set_type(segment::Type::Load);
91    ///
92    /// assert_eq!(phdr.get_type(), segment::Type::Load);
93    /// ```
94    pub fn set_type(&mut self, ptype: segment_type::Type) {
95        self.p_type = ptype.to_bytes();
96    }
97
98    pub fn set_flags<'a, I>(&mut self, flags: I)
99    where
100        I: Iterator<Item = &'a segment::Flag>,
101    {
102        for flag in flags {
103            self.p_flags = self.p_flags | Into::<Elf64Word>::into(*flag);
104        }
105    }
106
107    /// Create Vec<u8> from this.
108    ///
109    /// # Examples
110    ///
111    /// ```
112    /// use elf_utilities::segment::Phdr64;
113    /// let null_phdr : Phdr64 = Default::default();
114    ///
115    /// assert_eq!([0].repeat(Phdr64::SIZE), null_phdr.to_le_bytes());
116    /// ```
117    pub fn to_le_bytes(&self) -> Vec<u8> {
118        bincode::serialize(self).unwrap()
119    }
120
121    pub fn deserialize(buf: &[u8], start: usize) -> Result<Self, Box<dyn std::error::Error>> {
122        // bincode::ErrorKindをトレイトオブジェクトとするため,この冗長な書き方が必要
123        match bincode::deserialize(&buf[start..]) {
124            Ok(header) => Ok(header),
125            Err(e) => Err(e),
126        }
127    }
128}