1use std::io::{Read, Write};
2use {types, Error, Header, SectionContent};
3use utils::hextab;
4use num_traits::{FromPrimitive, ToPrimitive};
5use strtab::Strtab;
6use section::{Section, SectionHeader};
7use std::fmt;
8
9#[derive(Debug, Clone, Eq, PartialEq)]
10pub enum SymbolSectionIndex {
11 Section(u16), Undefined, Absolute, Common, }
16impl Default for SymbolSectionIndex {
17 fn default() -> SymbolSectionIndex {
18 SymbolSectionIndex::Undefined
19 }
20}
21
22#[derive(Default, Clone)]
23pub struct Symbol {
24 pub shndx: SymbolSectionIndex,
25 pub value: u64,
26 pub size: u64,
27
28 pub name: Vec<u8>,
29 pub stype: types::SymbolType,
30 pub bind: types::SymbolBind,
31 pub vis: types::SymbolVis,
32
33 pub _name: u32,
34}
35
36impl fmt::Debug for Symbol {
37 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38 write!(f,
39 " {} {:>5.5} {:<7.7} {:<6.6} {:<8.8} {:<3.3} {} ",
40 hextab(16, self.value),
41 self.size,
42 format!("{:?}", self.stype),
43 format!("{:?}", self.bind),
44 format!("{:?}", self.vis),
45 match self.shndx {
46 SymbolSectionIndex::Undefined => String::from("UND"),
47 SymbolSectionIndex::Absolute => String::from("ABS"),
48 SymbolSectionIndex::Common => String::from("COM"),
49 SymbolSectionIndex::Section(i) => format!("{}", i),
50 },
51 String::from_utf8_lossy(&self.name)
52 )
53 }
54}
55
56impl Symbol {
57 fn from_val(
58 tab: Option<&Strtab>,
59 _name: u32,
60 info: u8,
61 other: u8,
62 shndx: u16,
63 value: u64,
64 size: u64,
65 ) -> Result<Symbol, Error> {
66 let name = match tab {
67 Some(tab) => tab.get(_name as usize),
68 None => Vec::default(),
69 };
70
71 let shndx = match shndx {
72 0 => SymbolSectionIndex::Undefined,
73 65521 => SymbolSectionIndex::Absolute,
74 65522 => SymbolSectionIndex::Common,
75 _ if shndx > 0 && shndx < 6552 => SymbolSectionIndex::Section(shndx),
76 _ => return Err(Error::InvalidSymbolShndx(String::from_utf8_lossy(&name).into_owned(), shndx)),
77 };
78
79 let reb = info & 0xf;
80 let stype = match types::SymbolType::from_u8(reb) {
81 Some(v) => v,
82 None => return Err(Error::InvalidSymbolType(reb)),
83 };
84
85 let reb = info >> 4;
86 let bind = match types::SymbolBind::from_u8(reb) {
87 Some(v) => v,
88 None => return Err(Error::InvalidSymbolBind(reb)),
89 };
90
91 let reb = other & 0x3;
92 let vis = match types::SymbolVis::from_u8(reb) {
93 Some(v) => v,
94 None => return Err(Error::InvalidSymbolVis(reb)),
95 };
96
97 Ok(Symbol {
98 shndx: shndx,
99 value: value,
100 size: size,
101
102 name: name,
103 stype: stype,
104 bind: bind,
105 vis: vis,
106
107 _name: _name,
108 })
109 }
110
111 pub fn entsize(eh: &Header) -> usize {
112 match eh.ident_class {
113 types::Class::Class64 => 24,
114 types::Class::Class32 => 16,
115 }
116 }
117
118 pub fn from_reader<R>(
119 mut io: R,
120 linked: Option<&SectionContent>,
121 eh: &Header,
122 ) -> Result<SectionContent, Error>
123 where
124 R: Read,
125 {
126 let tab = match linked {
127 None => None,
128 Some(&SectionContent::Strtab(ref s)) => Some(s),
129 any => return Err(Error::LinkedSectionIsNotStrtab{
130 during: "reading symbols",
131 link: any.map(|v|v.clone()),
132 }),
133 };
134
135 let mut r = Vec::new();
136 let mut b = vec![0; Self::entsize(eh)];
137 while io.read(&mut b)? > 0 {
138 let mut br = &b[..];
139 elf_dispatch_endianness!(eh => {
140 let _name = read_u32(&mut br)?;
141 r.push(match eh.ident_class {
142 types::Class::Class64 => {
143 let info = b[4];
144 let other = b[5];
145 br = &b[6..];
146 let shndx = read_u16(&mut br)?;
147 let value = read_u64(&mut br)?;
148 let size = read_u64(&mut br)?;
149
150 Symbol::from_val(tab, _name, info, other, shndx, value, size)?
151 }
152 types::Class::Class32 => {
153 let value = read_u32(&mut br)?;
154 let size = read_u32(&mut br)?;
155 let info = b[12];
156 let other = b[13];
157 br = &b[14..];
158 let shndx = read_u16(&mut br)?;
159
160 Symbol::from_val(tab, _name, info, other, shndx, value as u64, size as u64)?
161 }
162 })
163 })
164 }
165
166 Ok(SectionContent::Symbols(r))
167 }
168
169 pub fn to_writer<W>(
170 &self,
171 mut io: W,
172 eh: &Header,
173 ) -> Result<(usize), Error>
174 where
175 W: Write,
176 {
177 let info = (self.bind.to_u8().unwrap() << 4) + (self.stype.to_u8().unwrap() & 0xf);
178 let other = self.vis.to_u8().unwrap();
179
180 let shndx = match self.shndx {
181 SymbolSectionIndex::Section(i) => i,
182 SymbolSectionIndex::Undefined => 0,
183 SymbolSectionIndex::Absolute => 65521,
184 SymbolSectionIndex::Common => 65522,
185 };
186
187 elf_write_u32!(eh, io, self._name)?;
188
189 Ok(match eh.ident_class {
190 types::Class::Class64 => {
191 io.write(&[info, other])?;
192 elf_write_u16!(eh, io, shndx)?;
193 elf_write_u64!(eh, io, self.value)?;
194 elf_write_u64!(eh, io, self.size)?;
195
196 2+2+8+8
197 }
198 types::Class::Class32 => {
199 elf_write_u32!(eh, io, self.value as u32)?;
200 elf_write_u32!(eh, io, self.size as u32)?;
201 io.write(&[info, other])?;
202 elf_write_u16!(eh, io, shndx)?;
203
204 4+4+2+2
205 }
206 })
207 }
208
209 pub fn sync(&mut self, linked: Option<&mut SectionContent>, _: &Header) -> Result<(), Error> {
210 match linked {
211 Some(&mut SectionContent::Strtab(ref mut strtab)) => {
212 self._name = strtab.insert(&self.name) as u32;
213 }
214 any => return Err(Error::LinkedSectionIsNotStrtab{
215 during: "syncing symbols",
216 link: any.map(|v|v.clone()),
217 }),
218 }
219 Ok(())
220 }
221}
222
223pub fn sysv_hash(s: &String) -> u64 {
224 let mut h: u64 = 0;
225 let mut g: u64;
226
227 for byte in s.bytes() {
228 h = (h << 4) + byte as u64;
229 g = h & 0xf0000000;
230 if g > 0 {
231 h ^= g >> 24;
232 }
233 h &= !g;
234 }
235 return h;
236}
237
238
239pub fn symhash(eh: &Header, symbols: &Vec<Symbol>, link: u32) -> Result<Section, Error> {
240 assert!(symbols.len() > 0);
241 let mut b = Vec::new();
243 {
244 let io = &mut b;
245 elf_write_uclass!(eh, io, 1)?; elf_write_uclass!(eh, io, symbols.len() as u64)?; elf_write_uclass!(eh, io, 1)?; elf_write_uclass!(eh, io, 0)?; for i in 1..symbols.len() - 1 {
254 elf_write_uclass!(eh, io, i as u64 + 1)?;
255 }
256
257 elf_write_uclass!(eh, io, 0)?;
259 }
260
261 Ok(Section {
262 name: b".hash".to_vec(),
263 header: SectionHeader {
264 name: 0,
265 shtype: types::SectionType::HASH,
266 flags: types::SectionFlags::ALLOC,
267 addr: 0,
268 offset: 0,
269 size: b.len() as u64,
270 link: link,
271 info: 0,
272 addralign: 0,
273 entsize: 8, },
275 content: SectionContent::Raw(b),
276 addrlock: false,
277 })
278}