1use ElfFile;
2use sections;
3
4use zero::Pod;
5
6use core::fmt;
7
8#[derive(Debug)]
9#[repr(C)]
10struct Entry32_ {
11 name: u32,
12 value: u32,
13 size: u32,
14 info: u8,
15 other: Visibility_,
16 shndx: u16,
17}
18
19#[derive(Debug)]
20#[repr(C)]
21struct Entry64_ {
22 name: u32,
23 info: u8,
24 other: Visibility_,
25 shndx: u16,
26 value: u64,
27 size: u64,
28}
29
30unsafe impl Pod for Entry32_ {}
31unsafe impl Pod for Entry64_ {}
32
33#[derive(Debug)]
34#[repr(C)]
35pub struct Entry32(Entry32_);
36
37#[derive(Debug)]
38#[repr(C)]
39pub struct Entry64(Entry64_);
40
41unsafe impl Pod for Entry32 {}
42unsafe impl Pod for Entry64 {}
43
44#[derive(Debug)]
45#[repr(C)]
46pub struct DynEntry32(Entry32_);
47
48#[derive(Debug)]
49#[repr(C)]
50pub struct DynEntry64(Entry64_);
51
52unsafe impl Pod for DynEntry32 {}
53unsafe impl Pod for DynEntry64 {}
54
55pub trait Entry {
56 fn name(&self) -> u32;
57 fn info(&self) -> u8;
58 fn other(&self) -> Visibility_;
59 fn shndx(&self) -> u16;
60 fn value(&self) -> u64;
61 fn size(&self) -> u64;
62
63 fn get_name<'a>(&'a self, elf_file: &ElfFile<'a>) -> Result<&'a str, &'static str>;
64
65 fn get_other(&self) -> Visibility {
66 self.other().as_visibility()
67 }
68
69 fn get_binding(&self) -> Result<Binding, &'static str> {
70 Binding_(self.info() >> 4).as_binding()
71 }
72
73 fn get_type(&self) -> Result<Type, &'static str> {
74 Type_(self.info() & 0xf).as_type()
75 }
76
77 fn get_section_header<'a>(&'a self,
78 elf_file: &ElfFile<'a>,
79 self_index: usize)
80 -> Result<sections::SectionHeader<'a>, &'static str> {
81 match self.shndx() {
82 sections::SHN_XINDEX => {
83 let header = elf_file.find_section_by_name(".symtab_shndx");
85 if let Some(header) = header {
86 assert_eq!(header.get_type()?, sections::ShType::SymTabShIndex);
87 if let sections::SectionData::SymTabShIndex(data) =
88 header.get_data(elf_file)? {
89 let index = data[self_index] as u16;
92 assert_ne!(index, sections::SHN_UNDEF);
93 elf_file.section_header(index)
94 } else {
95 Err("Expected SymTabShIndex")
96 }
97 } else {
98 Err("no .symtab_shndx section")
99 }
100 }
101 sections::SHN_UNDEF |
102 sections::SHN_ABS |
103 sections::SHN_COMMON => Err("Reserved section header index"),
104 i => elf_file.section_header(i),
105 }
106 }
107}
108
109impl fmt::Display for dyn Entry {
110 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
111 writeln!(f, "Symbol table entry:")?;
112 writeln!(f, " name: {:?}", self.name())?;
113 writeln!(f, " binding: {:?}", self.get_binding())?;
114 writeln!(f, " type: {:?}", self.get_type())?;
115 writeln!(f, " other: {:?}", self.get_other())?;
116 writeln!(f, " shndx: {:?}", self.shndx())?;
117 writeln!(f, " value: {:?}", self.value())?;
118 writeln!(f, " size: {:?}", self.size())?;
119 Ok(())
120 }
121}
122
123macro_rules! impl_entry {
124 ($name: ident with ElfFile::$strfunc: ident) => {
125 impl Entry for $name {
126 fn get_name<'a>(&'a self, elf_file: &ElfFile<'a>) -> Result<&'a str, &'static str> {
127 elf_file.$strfunc(self.name())
128 }
129
130 fn name(&self) -> u32 { self.0.name }
131 fn info(&self) -> u8 { self.0.info }
132 fn other(&self) -> Visibility_ { self.0.other }
133 fn shndx(&self) -> u16 { self.0.shndx }
134 fn value(&self) -> u64 { self.0.value as u64 }
135 fn size(&self) -> u64 { self.0.size as u64 }
136 }
137 }
138}
139impl_entry!(Entry32 with ElfFile::get_string);
140impl_entry!(Entry64 with ElfFile::get_string);
141impl_entry!(DynEntry32 with ElfFile::get_dyn_string);
142impl_entry!(DynEntry64 with ElfFile::get_dyn_string);
143
144#[derive(Copy, Clone, Debug)]
145pub struct Visibility_(u8);
146
147#[derive(Copy, Clone, Debug)]
148#[repr(u8)]
149pub enum Visibility {
150 Default = 0,
151 Internal = 1,
152 Hidden = 2,
153 Protected = 3,
154}
155
156impl Visibility_ {
157 pub fn as_visibility(self) -> Visibility {
158 match self.0 & 0x3 {
159 x if x == Visibility::Default as _ => Visibility::Default,
160 x if x == Visibility::Internal as _ => Visibility::Internal,
161 x if x == Visibility::Hidden as _ => Visibility::Hidden,
162 x if x == Visibility::Protected as _ => Visibility::Protected,
163 _ => unreachable!(),
164 }
165 }
166}
167
168#[derive(Copy, Clone, Debug)]
169pub struct Binding_(u8);
170
171#[derive(Copy, Clone, Debug, PartialEq, Eq)]
172pub enum Binding {
173 Local,
174 Global,
175 Weak,
176 OsSpecific(u8),
177 ProcessorSpecific(u8),
178}
179
180impl Binding_ {
181 pub fn as_binding(self) -> Result<Binding, &'static str> {
182 match self.0 {
183 0 => Ok(Binding::Local),
184 1 => Ok(Binding::Global),
185 2 => Ok(Binding::Weak),
186 b if (10..=12).contains(&b) => Ok(Binding::OsSpecific(b)),
187 b if (13..=15).contains(&b) => Ok(Binding::ProcessorSpecific(b)),
188 _ => Err("Invalid value for binding"),
189 }
190 }
191}
192
193#[derive(Copy, Clone, Debug)]
195pub struct Type_(u8);
196
197#[derive(Copy, Clone, Debug, PartialEq, Eq)]
198pub enum Type {
199 NoType,
200 Object,
201 Func,
202 Section,
203 File,
204 Common,
205 Tls,
206 OsSpecific(u8),
207 ProcessorSpecific(u8),
208}
209
210impl Type_ {
211 pub fn as_type(self) -> Result<Type, &'static str> {
212 match self.0 {
213 0 => Ok(Type::NoType),
214 1 => Ok(Type::Object),
215 2 => Ok(Type::Func),
216 3 => Ok(Type::Section),
217 4 => Ok(Type::File),
218 5 => Ok(Type::Common),
219 6 => Ok(Type::Tls),
220 b if (10..=12).contains(&b) => Ok(Type::OsSpecific(b)),
221 b if (13..=15).contains(&b) => Ok(Type::ProcessorSpecific(b)),
222 _ => Err("Invalid value for type"),
223 }
224 }
225}