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}