elfkit/
dynamic.rs

1use std::io::{Read, Write};
2use {Error, Header, SectionContent};
3use types;
4use num_traits::{FromPrimitive, ToPrimitive};
5
6#[derive(Debug, Clone)]
7pub enum DynamicContent {
8    None,
9    String((Vec<u8>,Option<u64>)),
10    Address(u64),
11    Flags1(types::DynamicFlags1),
12}
13
14impl Default for DynamicContent{
15    fn default() -> Self {
16        DynamicContent::None
17    }
18}
19
20#[derive(Debug, Clone, Default)]
21pub struct Dynamic {
22    pub dhtype: types::DynamicType,
23    pub content: DynamicContent,
24}
25
26impl Dynamic {
27    pub fn entsize(eh: &Header) -> usize {
28        match eh.ident_class {
29            types::Class::Class64 => 16,
30            types::Class::Class32 => 8,
31        }
32    }
33
34    pub fn from_reader<R>(
35        mut io: R,
36        linked: Option<&SectionContent>,
37        eh: &Header,
38    ) -> Result<SectionContent, Error>
39    where
40        R: Read,
41    {
42        let strtab = match linked {
43            None => None,
44            Some(&SectionContent::Strtab(ref s)) => Some(s),
45            any => return Err(Error::LinkedSectionIsNotStrtab{
46                during: "reading dynamic",
47                link: any.map(|v|v.clone()),
48            }),
49        };
50
51        let mut r = Vec::new();
52
53        while let Ok(tag) = elf_read_uclass!(eh, io) {
54            let val = elf_read_uclass!(eh, io)?;
55
56            match types::DynamicType::from_u64(tag) {
57                None => return Err(Error::InvalidDynamicType(tag)),
58                Some(types::DynamicType::NULL) => {
59                    r.push(Dynamic {
60                        dhtype: types::DynamicType::NULL,
61                        content: DynamicContent::None,
62                    });
63                    break;
64                },
65                Some(types::DynamicType::RPATH) => {
66                    r.push(Dynamic {
67                        dhtype: types::DynamicType::RPATH,
68                        content: DynamicContent::String(match strtab {
69                            None => (Vec::default(),None),
70                            Some(s) => (s.get(val as usize), Some(val)),
71                        }),
72                    });
73                },
74                Some(types::DynamicType::NEEDED) => {
75                    r.push(Dynamic {
76                        dhtype: types::DynamicType::NEEDED,
77                        content: DynamicContent::String(match strtab {
78                            None => (Vec::default(),None),
79                            Some(s) => (s.get(val as usize), Some(val)),
80                        }),
81                    });
82                },
83                Some(types::DynamicType::FLAGS_1) => {
84                    r.push(Dynamic {
85                        dhtype: types::DynamicType::FLAGS_1,
86                        content: DynamicContent::Flags1(
87                            match types::DynamicFlags1::from_bits(val) {
88                                Some(v) => v,
89                                None => return Err(Error::InvalidDynamicFlags1(val)),
90                            },
91                        ),
92                    });
93                },
94                Some(x) => {
95                    r.push(Dynamic {
96                        dhtype: x,
97                        content: DynamicContent::Address(val),
98                    });
99                }
100            };
101        }
102
103        Ok(SectionContent::Dynamic(r))
104    }
105    pub fn to_writer<W>(
106        &self,
107        mut io: W,
108        eh: &Header,
109    ) -> Result<(usize), Error>
110    where
111        W: Write,
112    {
113        elf_write_uclass!(eh, io, self.dhtype.to_u64().unwrap())?;
114
115        match self.content {
116            DynamicContent::None => {
117                elf_write_uclass!(eh, io, 0)?;
118            }
119            DynamicContent::String(ref s) => match s.1 {
120                Some(val) => elf_write_uclass!(eh, io, val)?,
121                None      => return Err(Error::WritingNotSynced),
122            },
123            DynamicContent::Address(ref v) => {
124                elf_write_uclass!(eh, io, *v)?;
125            }
126            DynamicContent::Flags1(ref v) => {
127                elf_write_uclass!(eh, io, v.bits())?;
128            }
129        }
130        Ok(Dynamic::entsize(eh))
131    }
132
133    pub fn sync(&mut self, linked: Option<&mut SectionContent>, _: &Header) -> Result<(), Error> {
134        match self.content {
135            DynamicContent::String(ref mut s) => match linked {
136                Some(&mut SectionContent::Strtab(ref mut strtab)) => {
137                    s.1 = Some(strtab.insert(&s.0) as u64);
138                }
139                any => return Err(Error::LinkedSectionIsNotStrtab{
140                    during: "syncing dynamic",
141                    link: any.map(|v|v.clone()),
142                }),
143            },
144            DynamicContent::None => {}
145            DynamicContent::Address(_) => {}
146            DynamicContent::Flags1(_) => {}
147        }
148        Ok(())
149    }
150}