1use error::Error;
2use header::Header;
3use relocation::Relocation;
4use dynamic::Dynamic;
5use symbol::Symbol;
6use strtab::Strtab;
7use types;
8
9use std::io::{Read, Seek, SeekFrom, Write};
10use std::io::BufWriter;
11
12#[derive(Default, Debug, Clone)]
13pub struct SectionHeader {
14 pub name: u32,
15 pub shtype: types::SectionType,
16 pub flags: types::SectionFlags,
17 pub addr: u64,
18 pub offset: u64,
19 pub size: u64,
20 pub link: u32,
21 pub info: u32,
22 pub addralign: u64,
23 pub entsize: u64,
24}
25
26impl SectionHeader {
27 pub fn entsize(eh: &Header) -> usize {
28 4 + 4 + match eh.ident_class {
29 types::Class::Class64 => 6 * 8,
30 types::Class::Class32 => 6 * 4,
31 } + 4 + 4
32 }
33
34 pub fn from_reader<R>(io: &mut R, eh: &Header) -> Result<SectionHeader, Error>
35 where
36 R: Read,
37 {
38 elf_dispatch_endianness!(eh => {
39 let mut r = SectionHeader::default();
40 r.name = read_u32(io)?;
41 let reb = read_u32(io)?;
42 r.shtype = types::SectionType(reb);
43
44 elf_dispatch_uclass!(eh => {
45 let reb = read_uclass(io)?;
46 r.flags = match types::SectionFlags::from_bits(reb) {
47 Some(v) => v,
48 None => return Err(Error::InvalidSectionFlags(reb)),
49 };
50 r.addr = read_uclass(io)?;
51 r.offset = read_uclass(io)?;
52 r.size = read_uclass(io)?;
53 r.link = read_u32(io)?;
54 r.info = read_u32(io)?;
55 r.addralign = read_uclass(io)?;
56 r.entsize = read_uclass(io)?;
57 Ok(r)
58 })
59 })
60 }
61
62 pub fn to_writer<R>(&self, eh: &Header, io: &mut R) -> Result<(), Error>
63 where
64 R: Write,
65 {
66 let mut w = BufWriter::new(io);
67 elf_write_u32!(eh, w, self.name)?;
68 elf_write_u32!(eh, w, self.shtype.to_u32())?;
69 elf_write_uclass!(eh, w, self.flags.bits())?;
70
71 elf_write_uclass!(eh, w, self.addr)?;
72 elf_write_uclass!(eh, w, self.offset)?;
73 elf_write_uclass!(eh, w, self.size)?;
74 elf_write_u32!(eh, w, self.link)?;
75 elf_write_u32!(eh, w, self.info)?;
76 elf_write_uclass!(eh, w, self.addralign)?;
77 elf_write_uclass!(eh, w, self.entsize)?;
78 Ok(())
79 }
80}
81
82#[derive(Debug, Clone)]
83pub enum SectionContent {
84 None,
85 Unloaded,
86 Raw(Vec<u8>),
87 Relocations(Vec<Relocation>),
88 Symbols(Vec<Symbol>),
89 Dynamic(Vec<Dynamic>),
90 Strtab(Strtab),
91}
92
93impl Default for SectionContent {
94 fn default() -> Self {
95 SectionContent::None
96 }
97}
98impl SectionContent {
99 pub fn as_dynamic_mut(&mut self) -> Option<&mut Vec<Dynamic>> {
100 match self {
101 &mut SectionContent::Dynamic(ref mut v) => Some(v),
102 _ => None,
103 }
104 }
105 pub fn as_dynamic(&self) -> Option<&Vec<Dynamic>> {
106 match self {
107 &SectionContent::Dynamic(ref v) => Some(v),
108 _ => None,
109 }
110 }
111 pub fn into_dynamic(self) -> Option<Vec<Dynamic>> {
112 match self {
113 SectionContent::Dynamic(v) => Some(v),
114 _ => None,
115 }
116 }
117 pub fn as_strtab_mut(&mut self) -> Option<&mut Strtab> {
118 match self {
119 &mut SectionContent::Strtab(ref mut v) => Some(v),
120 _ => None,
121 }
122 }
123 pub fn as_symbols(&self) -> Option<&Vec<Symbol>> {
124 match self {
125 &SectionContent::Symbols(ref v) => Some(v),
126 _ => None,
127 }
128 }
129 pub fn as_symbols_mut(&mut self) -> Option<&mut Vec<Symbol>> {
130 match self {
131 &mut SectionContent::Symbols(ref mut v) => Some(v),
132 _ => None,
133 }
134 }
135 pub fn into_symbols(self) -> Option<Vec<Symbol>> {
136 match self {
137 SectionContent::Symbols(v) => Some(v),
138 _ => None,
139 }
140 }
141 pub fn as_relocations(&self) -> Option<&Vec<Relocation>> {
142 match self {
143 &SectionContent::Relocations(ref v) => Some(v),
144 _ => None,
145 }
146 }
147 pub fn as_relocations_mut(&mut self) -> Option<&mut Vec<Relocation>> {
148 match self {
149 &mut SectionContent::Relocations(ref mut v) => Some(v),
150 _ => None,
151 }
152 }
153 pub fn into_relocations(self) -> Option<Vec<Relocation>> {
154 match self {
155 SectionContent::Relocations(v) => Some(v),
156 _ => None,
157 }
158 }
159 pub fn as_raw(&self) -> Option<&Vec<u8>> {
160 match self {
161 &SectionContent::Raw(ref v) => Some(v),
162 _ => None,
163 }
164 }
165 pub fn as_raw_mut(&mut self) -> Option<&mut Vec<u8>> {
166 match self {
167 &mut SectionContent::Raw(ref mut v) => Some(v),
168 _ => None,
169 }
170 }
171 pub fn into_raw(self) -> Option<Vec<u8>> {
172 match self {
173 SectionContent::Raw(v) => Some(v),
174 _ => None,
175 }
176 }
177 pub fn size(&self, eh: &Header) -> usize {
178 match self {
179 &SectionContent::Unloaded => panic!("cannot size unloaded section"),
180 &SectionContent::None => 0,
181 &SectionContent::Raw(ref v) => v.len(),
182 &SectionContent::Dynamic(ref v) => v.len() * Dynamic::entsize(eh),
183 &SectionContent::Strtab(ref v) => v.len(eh),
184 &SectionContent::Symbols(ref v) => v.len() * Symbol::entsize(eh),
185 &SectionContent::Relocations(ref v) => v.len() * Relocation::entsize(eh),
186 }
187 }
188}
189
190#[derive(Debug, Default, Clone)]
191pub struct Section {
192 pub header: SectionHeader,
193 pub name: Vec<u8>,
194 pub content: SectionContent,
195 pub addrlock: bool,
196}
197
198
199impl Section {
200 pub fn size(&self, eh: &Header) -> usize {
201 self.content.size(eh)
202 }
203 pub fn new(
204 name: Vec<u8>,
205 shtype: types::SectionType,
206 flags: types::SectionFlags,
207 content: SectionContent,
208 link: u32,
209 info: u32,
210 ) -> Section {
211 Section {
212 name: name,
213 header: SectionHeader {
214 name: 0,
215 shtype: shtype,
216 flags: flags,
217 addr: 0,
218 offset: 0,
219 size: 0,
220 link: link,
221 info: info,
222 addralign: 0,
223 entsize: 0,
224 },
225 content: content,
226 addrlock: false,
227 }
228 }
229
230 pub fn sync(
231 &mut self,
232 eh: &Header,
233 mut linked: Option<&mut SectionContent>,
234 ) -> Result<(), Error> {
235 match self.content {
236 SectionContent::Unloaded => {
237 return Err(Error::SyncingUnloadedSection);
238 },
239 SectionContent::Relocations(_) => {
240 self.header.entsize = Relocation::entsize(eh) as u64;
241 }
242 SectionContent::Symbols(ref mut vv) => {
243 for (i, sym) in vv.iter().enumerate() {
244 if sym.bind == types::SymbolBind::GLOBAL {
245 self.header.info = i as u32;
246 break;
247 }
248 }
249 for v in vv {
250 v.sync(linked.as_mut().map(|r| &mut **r), eh)?;
251 }
252 self.header.entsize = Symbol::entsize(eh) as u64;
253 }
254 SectionContent::Dynamic(ref mut vv) => {
255 for v in vv {
256 v.sync(linked.as_mut().map(|r| &mut **r), eh)?;
257 }
258 self.header.entsize = Dynamic::entsize(eh) as u64;
259 }
260 SectionContent::Strtab(_) => {
261 self.header.entsize = Strtab::entsize(eh) as u64;
262 }
263 SectionContent::None | SectionContent::Raw(_) => {}
264 }
265 if self.header.shtype != types::SectionType::NOBITS {
266 self.header.size = self.size(eh) as u64;
267 }
268 Ok(())
269 }
270
271 pub fn from_reader<T>(
272 &mut self,
273 mut io: T,
274 linked: Option<&Section>,
275 eh: &Header,
276 ) -> Result<(), Error> where T: Read + Seek {
277 match self.content {
278 SectionContent::Unloaded => {},
279 _ => return Ok(()),
280 };
281 if self.header.shtype == types::SectionType::NOBITS {
282 self.content = SectionContent::None;
283 return Ok(());
284 };
285 io.seek(SeekFrom::Start(self.header.offset))?;
286 let mut bb = vec![0; self.header.size as usize];
287 io.read_exact(&mut bb)?;
288 let linked = linked.map(|s|&s.content);
289 self.content = match self.header.shtype {
290 types::SectionType::NOBITS => {
291 unreachable!();
292 },
293 types::SectionType::STRTAB => {
294 let io = bb.as_slice();
295 Strtab::from_reader(io, linked, eh)?
296 }
297 types::SectionType::RELA => {
298 let io = bb.as_slice();
299 Relocation::from_reader(io, linked, eh)?
300 }
301 types::SectionType::SYMTAB | types::SectionType::DYNSYM => {
302 let io = bb.as_slice();
303 Symbol::from_reader(io, linked, eh)?
304 }
305 types::SectionType::DYNAMIC => {
306 let io = bb.as_slice();
307 Dynamic::from_reader(io, linked, eh)?
308 }
309 _ => {
310 SectionContent::Raw(bb)
311 }
312 };
313 Ok(())
314 }
315
316
317 pub fn to_writer<R>(
318 &self,
319 mut io: R,
320 eh: &Header,
321 ) -> Result<(), Error> where R: Write + Seek {
322 match self.content {
323 SectionContent::Unloaded => return Ok(()),
324 _ => {},
325 };
326 io.seek(SeekFrom::Start(self.header.offset))?;
327
328 let rs = match &self.content {
329 &SectionContent::Unloaded => {
330 return Err(Error::WritingUnloadedSection);
331 },
332 &SectionContent::Relocations(ref vv) => {
333 let mut rs = 0;
334 for v in vv {
335 rs += v.to_writer(&mut io, eh)?;
336 }
337 rs
338 }
339 &SectionContent::Symbols(ref vv) => {
340 let mut rs = 0;
341 for v in vv {
342 rs += v.to_writer(&mut io, eh)?;
343 }
344 rs
345 }
346 &SectionContent::Dynamic(ref vv) => {
347 let mut rs = 0;
348 for v in vv {
349 rs += v.to_writer(&mut io, eh)?;
350 }
351 rs
352 }
353 &SectionContent::Strtab(ref v) => {
354 v.to_writer(&mut io, eh)?
355 }
356 &SectionContent::None => {
357 0
358 },
359 &SectionContent::Raw(ref raw) => {
360 io.write(&raw)?
361 }
362 };
363
364 assert_eq!(
365 io.seek(SeekFrom::Current(0))?,
366 self.header.offset + self.content.size(eh) as u64,
367 "writing {} with header.size {} and content.size {} returned a written size {}",
368 String::from_utf8_lossy(&self.name),
369 self.content.size(eh),
370 self.header.size,
371 rs
372 );
373
374 Ok(())
375 }
376
377}