1use crate::endian::EndianParse;
3use crate::file::Class;
4use crate::parse::{ParseAt, ParseError, ParsingTable};
5
6pub type SectionHeaderTable<'data, E> = ParsingTable<'data, E, SectionHeader>;
7
8#[derive(Debug)]
12#[repr(C)]
13pub struct Elf32_Shdr {
14 pub sh_name: u32,
15 pub sh_type: u32,
16 pub sh_flags: u32,
17 pub sh_addr: u32,
18 pub sh_offset: u32,
19 pub sh_size: u32,
20 pub sh_link: u32,
21 pub sh_info: u32,
22 pub sh_addralign: u32,
23 pub sh_entsize: u32,
24}
25
26#[derive(Debug)]
30#[repr(C)]
31pub struct Elf64_Shdr {
32 pub sh_name: u32,
33 pub sh_type: u32,
34 pub sh_flags: u64,
35 pub sh_addr: u64,
36 pub sh_offset: u64,
37 pub sh_size: u64,
38 pub sh_link: u32,
39 pub sh_info: u32,
40 pub sh_addralign: u64,
41 pub sh_entsize: u64,
42}
43
44#[derive(Copy, Clone, Debug, PartialEq, Eq)]
48pub struct SectionHeader {
49 pub sh_name: u32,
51 pub sh_type: u32,
53 pub sh_flags: u64,
55 pub sh_addr: u64,
57 pub sh_offset: u64,
59 pub sh_size: u64,
61 pub sh_link: u32,
63 pub sh_info: u32,
65 pub sh_addralign: u64,
67 pub sh_entsize: u64,
69}
70
71impl ParseAt for SectionHeader {
72 fn parse_at<E: EndianParse>(
73 endian: E,
74 class: Class,
75 offset: &mut usize,
76 data: &[u8],
77 ) -> Result<Self, ParseError> {
78 match class {
79 Class::ELF32 => Ok(SectionHeader {
80 sh_name: endian.parse_u32_at(offset, data)?,
81 sh_type: endian.parse_u32_at(offset, data)?,
82 sh_flags: endian.parse_u32_at(offset, data)? as u64,
83 sh_addr: endian.parse_u32_at(offset, data)? as u64,
84 sh_offset: endian.parse_u32_at(offset, data)? as u64,
85 sh_size: endian.parse_u32_at(offset, data)? as u64,
86 sh_link: endian.parse_u32_at(offset, data)?,
87 sh_info: endian.parse_u32_at(offset, data)?,
88 sh_addralign: endian.parse_u32_at(offset, data)? as u64,
89 sh_entsize: endian.parse_u32_at(offset, data)? as u64,
90 }),
91 Class::ELF64 => Ok(SectionHeader {
92 sh_name: endian.parse_u32_at(offset, data)?,
93 sh_type: endian.parse_u32_at(offset, data)?,
94 sh_flags: endian.parse_u64_at(offset, data)?,
95 sh_addr: endian.parse_u64_at(offset, data)?,
96 sh_offset: endian.parse_u64_at(offset, data)?,
97 sh_size: endian.parse_u64_at(offset, data)?,
98 sh_link: endian.parse_u32_at(offset, data)?,
99 sh_info: endian.parse_u32_at(offset, data)?,
100 sh_addralign: endian.parse_u64_at(offset, data)?,
101 sh_entsize: endian.parse_u64_at(offset, data)?,
102 }),
103 }
104 }
105
106 #[inline]
107 fn size_for(class: Class) -> usize {
108 match class {
109 Class::ELF32 => 40,
110 Class::ELF64 => 64,
111 }
112 }
113}
114
115impl SectionHeader {
116 pub(crate) fn get_data_range(&self) -> Result<(usize, usize), ParseError> {
119 let start: usize = self.sh_offset.try_into()?;
120 let size: usize = self.sh_size.try_into()?;
121 let end = start.checked_add(size).ok_or(ParseError::IntegerOverflow)?;
122 Ok((start, end))
123 }
124}
125
126#[cfg(test)]
127mod parse_tests {
128 use super::*;
129 use crate::endian::{BigEndian, LittleEndian};
130 use crate::parse::{test_parse_for, test_parse_fuzz_too_short};
131
132 #[test]
133 fn parse_shdr32_lsb() {
134 test_parse_for(
135 LittleEndian,
136 Class::ELF32,
137 SectionHeader {
138 sh_name: 0x03020100,
139 sh_type: 0x07060504,
140 sh_flags: 0xB0A0908,
141 sh_addr: 0x0F0E0D0C,
142 sh_offset: 0x13121110,
143 sh_size: 0x17161514,
144 sh_link: 0x1B1A1918,
145 sh_info: 0x1F1E1D1C,
146 sh_addralign: 0x23222120,
147 sh_entsize: 0x27262524,
148 },
149 );
150 }
151
152 #[test]
153 fn parse_shdr32_msb() {
154 test_parse_for(
155 BigEndian,
156 Class::ELF32,
157 SectionHeader {
158 sh_name: 0x00010203,
159 sh_type: 0x04050607,
160 sh_flags: 0x08090A0B,
161 sh_addr: 0x0C0D0E0F,
162 sh_offset: 0x10111213,
163 sh_size: 0x14151617,
164 sh_link: 0x18191A1B,
165 sh_info: 0x1C1D1E1F,
166 sh_addralign: 0x20212223,
167 sh_entsize: 0x24252627,
168 },
169 );
170 }
171
172 #[test]
173 fn parse_shdr64_lsb() {
174 test_parse_for(
175 LittleEndian,
176 Class::ELF64,
177 SectionHeader {
178 sh_name: 0x03020100,
179 sh_type: 0x07060504,
180 sh_flags: 0x0F0E0D0C0B0A0908,
181 sh_addr: 0x1716151413121110,
182 sh_offset: 0x1F1E1D1C1B1A1918,
183 sh_size: 0x2726252423222120,
184 sh_link: 0x2B2A2928,
185 sh_info: 0x2F2E2D2C,
186 sh_addralign: 0x3736353433323130,
187 sh_entsize: 0x3F3E3D3C3B3A3938,
188 },
189 );
190 }
191
192 #[test]
193 fn parse_shdr64_msb() {
194 test_parse_for(
195 BigEndian,
196 Class::ELF64,
197 SectionHeader {
198 sh_name: 0x00010203,
199 sh_type: 0x04050607,
200 sh_flags: 0x08090A0B0C0D0E0F,
201 sh_addr: 0x1011121314151617,
202 sh_offset: 0x18191A1B1C1D1E1F,
203 sh_size: 0x2021222324252627,
204 sh_link: 0x28292A2B,
205 sh_info: 0x2C2D2E2F,
206 sh_addralign: 0x3031323334353637,
207 sh_entsize: 0x38393A3B3C3D3E3F,
208 },
209 );
210 }
211
212 #[test]
213 fn parse_shdr32_lsb_fuzz_too_short() {
214 test_parse_fuzz_too_short::<_, SectionHeader>(LittleEndian, Class::ELF32);
215 }
216
217 #[test]
218 fn parse_shdr32_msb_fuzz_too_short() {
219 test_parse_fuzz_too_short::<_, SectionHeader>(BigEndian, Class::ELF32);
220 }
221
222 #[test]
223 fn parse_shdr64_lsb_fuzz_too_short() {
224 test_parse_fuzz_too_short::<_, SectionHeader>(LittleEndian, Class::ELF64);
225 }
226
227 #[test]
228 fn parse_shdr64_msb_fuzz_too_short() {
229 test_parse_fuzz_too_short::<_, SectionHeader>(BigEndian, Class::ELF64);
230 }
231}