elf/
dynamic.rs

1//! Parsing `.dynamic` section or [PT_DYNAMIC](crate::abi::PT_DYNAMIC) segment contents
2use crate::endian::EndianParse;
3use crate::file::Class;
4use crate::parse::{ParseAt, ParseError, ParsingTable};
5
6pub type DynamicTable<'data, E> = ParsingTable<'data, E, Dyn>;
7
8/// C-style 32-bit ELF Dynamic section entry definition
9///
10/// These C-style definitions are for users who want to implement their own ELF manipulation logic.
11#[derive(Debug)]
12#[repr(C)]
13pub struct Elf32_Dyn {
14    pub d_tag: i32,
15    // union of both {d_val, d_ptr}
16    pub d_un: u32,
17}
18
19/// C-style 64-bit ELF Dynamic section entry definition
20///
21/// These C-style definitions are for users who want to implement their own ELF manipulation logic.
22#[derive(Debug)]
23#[repr(C)]
24pub struct Elf64_Dyn {
25    pub d_tag: i64,
26    // union of both {d_val, d_ptr}
27    pub d_un: u64,
28}
29
30#[derive(Debug, Clone, PartialEq, Eq)]
31pub struct Dyn {
32    pub d_tag: i64,
33    pub(super) d_un: u64,
34}
35
36impl Dyn {
37    pub fn d_val(self) -> u64 {
38        self.d_un
39    }
40
41    pub fn d_ptr(self) -> u64 {
42        self.d_un
43    }
44}
45
46impl ParseAt for Dyn {
47    fn parse_at<E: EndianParse>(
48        endian: E,
49        class: Class,
50        offset: &mut usize,
51        data: &[u8],
52    ) -> Result<Self, ParseError> {
53        match class {
54            Class::ELF32 => Ok(Dyn {
55                d_tag: endian.parse_i32_at(offset, data)? as i64,
56                d_un: endian.parse_u32_at(offset, data)? as u64,
57            }),
58            Class::ELF64 => Ok(Dyn {
59                d_tag: endian.parse_i64_at(offset, data)?,
60                d_un: endian.parse_u64_at(offset, data)?,
61            }),
62        }
63    }
64
65    #[inline]
66    fn size_for(class: Class) -> usize {
67        match class {
68            Class::ELF32 => 8,
69            Class::ELF64 => 16,
70        }
71    }
72}
73
74#[cfg(test)]
75mod parse_tests {
76    use super::*;
77    use crate::endian::{BigEndian, LittleEndian};
78    use crate::parse::{test_parse_for, test_parse_fuzz_too_short};
79
80    #[test]
81    fn parse_dyn32_lsb() {
82        test_parse_for(
83            LittleEndian,
84            Class::ELF32,
85            Dyn {
86                d_tag: 0x03020100,
87                d_un: 0x07060504,
88            },
89        );
90    }
91
92    #[test]
93    fn parse_dyn32_msb() {
94        test_parse_for(
95            BigEndian,
96            Class::ELF32,
97            Dyn {
98                d_tag: 0x00010203,
99                d_un: 0x04050607,
100            },
101        );
102    }
103
104    #[test]
105    fn parse_dyn64_lsb() {
106        test_parse_for(
107            LittleEndian,
108            Class::ELF64,
109            Dyn {
110                d_tag: 0x0706050403020100,
111                d_un: 0x0F0E0D0C0B0A0908,
112            },
113        );
114    }
115
116    #[test]
117    fn parse_dyn64_msb() {
118        test_parse_for(
119            BigEndian,
120            Class::ELF64,
121            Dyn {
122                d_tag: 0x0001020304050607,
123                d_un: 0x08090A0B0C0D0E0F,
124            },
125        );
126    }
127
128    #[test]
129    fn parse_dyn32_lsb_fuzz_too_short() {
130        test_parse_fuzz_too_short::<_, Dyn>(LittleEndian, Class::ELF32);
131    }
132
133    #[test]
134    fn parse_dyn32_msb_fuzz_too_short() {
135        test_parse_fuzz_too_short::<_, Dyn>(BigEndian, Class::ELF32);
136    }
137
138    #[test]
139    fn parse_dyn64_lsb_fuzz_too_short() {
140        test_parse_fuzz_too_short::<_, Dyn>(LittleEndian, Class::ELF64);
141    }
142
143    #[test]
144    fn parse_dyn64_msb_fuzz_too_short() {
145        test_parse_fuzz_too_short::<_, Dyn>(BigEndian, Class::ELF64);
146    }
147}