1use alloc::vec::Vec;
2use core::ops::Deref;
3use core::ops::DerefMut;
4
5use crate::BlockRead;
6use crate::BlockWrite;
7use crate::ByteOrder;
8use crate::Class;
9use crate::ElfRead;
10use crate::ElfWrite;
11use crate::EntityIo;
12use crate::Error;
13use crate::SymbolBinding;
14use crate::SymbolKind;
15use crate::SymbolVisibility;
16
17#[derive(Debug)]
19#[cfg_attr(test, derive(PartialEq, Eq))]
20pub struct Symbol {
21 pub address: u64,
23 pub size: u64,
25 pub name_offset: u32,
27 pub section_index: u16,
29 pub binding: SymbolBinding,
31 pub kind: SymbolKind,
33 pub visibility: SymbolVisibility,
35}
36
37impl Symbol {
38 const fn info(&self) -> u8 {
39 self.binding.to_info_bits() | self.kind.to_info_bits()
40 }
41}
42
43impl EntityIo for Symbol {
44 fn read<R: ElfRead>(
45 reader: &mut R,
46 class: Class,
47 byte_order: ByteOrder,
48 ) -> Result<Self, Error> {
49 let name_offset = reader.read_u32(byte_order)?;
50 match class {
51 Class::Elf32 => {
52 let address = reader.read_word(class, byte_order)?;
53 let size = reader.read_u32(byte_order)? as u64;
54 let info = reader.read_u8()?;
55 let other = reader.read_u8()?;
56 let section_index = reader.read_u16(byte_order)?;
57 Ok(Self {
58 name_offset,
59 address,
60 size,
61 section_index,
62 binding: SymbolBinding::from_info(info),
63 kind: SymbolKind::from_info(info),
64 visibility: SymbolVisibility::from_other(other),
65 })
66 }
67 Class::Elf64 => {
68 let info = reader.read_u8()?;
69 let other = reader.read_u8()?;
70 let section_index = reader.read_u16(byte_order)?;
71 let address = reader.read_word(class, byte_order)?;
72 let size = reader.read_u64(byte_order)?;
73 Ok(Self {
74 name_offset,
75 address,
76 size,
77 section_index,
78 binding: SymbolBinding::from_info(info),
79 kind: SymbolKind::from_info(info),
80 visibility: SymbolVisibility::from_other(other),
81 })
82 }
83 }
84 }
85
86 fn write<W: ElfWrite>(
87 &self,
88 writer: &mut W,
89 class: Class,
90 byte_order: ByteOrder,
91 ) -> Result<(), Error> {
92 writer.write_u32(byte_order, self.name_offset)?;
93 match class {
94 Class::Elf32 => {
95 writer.write_word(class, byte_order, self.address)?;
96 writer.write_u32_as_u64(byte_order, self.size)?;
97 writer.write_u8(self.info())?;
98 writer.write_u8(self.visibility as u8)?;
99 writer.write_u16(byte_order, self.section_index)?;
100 }
101 Class::Elf64 => {
102 writer.write_u8(self.info())?;
103 writer.write_u8(self.visibility as u8)?;
104 writer.write_u16(byte_order, self.section_index)?;
105 writer.write_word(class, byte_order, self.address)?;
106 writer.write_u64(byte_order, self.size)?;
107 }
108 }
109 Ok(())
110 }
111}
112
113#[derive(Default)]
115#[cfg_attr(test, derive(PartialEq, Eq, Debug))]
116pub struct SymbolTable {
117 entries: Vec<Symbol>,
118}
119
120impl SymbolTable {
121 pub fn new() -> Self {
123 Self::default()
124 }
125}
126
127impl BlockRead for SymbolTable {
128 fn read<R: ElfRead>(
129 reader: &mut R,
130 class: Class,
131 byte_order: ByteOrder,
132 len: u64,
133 ) -> Result<Self, Error> {
134 let mut entries = Vec::new();
135 let symbol_len = class.symbol_len();
136 for _ in 0..len / symbol_len as u64 {
137 let symbol = Symbol::read(reader, class, byte_order)?;
138 entries.push(symbol);
139 }
140 Ok(Self { entries })
141 }
142}
143
144impl BlockWrite for SymbolTable {
145 fn write<W: ElfWrite>(
146 &self,
147 writer: &mut W,
148 class: Class,
149 byte_order: ByteOrder,
150 ) -> Result<(), Error> {
151 for symbol in self.entries.iter() {
152 symbol.write(writer, class, byte_order)?;
153 }
154 Ok(())
155 }
156}
157
158impl Deref for SymbolTable {
159 type Target = Vec<Symbol>;
160 fn deref(&self) -> &Self::Target {
161 &self.entries
162 }
163}
164
165impl DerefMut for SymbolTable {
166 fn deref_mut(&mut self) -> &mut Self::Target {
167 &mut self.entries
168 }
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174
175 use arbitrary::Unstructured;
176
177 use crate::constants::*;
178 use crate::test::test_block_io;
179 use crate::test::test_entity_io;
180 use crate::test::ArbitraryWithClass;
181
182 #[test]
183 fn symbol_io() {
184 test_entity_io::<Symbol>();
185 }
186
187 #[test]
188 fn symbol_table_io() {
189 test_block_io::<SymbolTable>();
190 }
191
192 impl ArbitraryWithClass<'_> for Symbol {
193 fn arbitrary(u: &mut Unstructured<'_>, class: Class) -> arbitrary::Result<Self> {
194 let info = u.arbitrary()?;
195 Ok(match class {
196 Class::Elf32 => Self {
197 address: u.arbitrary::<u32>()?.into(),
198 size: u.arbitrary::<u32>()?.into(),
199 name_offset: u.arbitrary()?,
200 section_index: u.arbitrary()?,
201 binding: SymbolBinding::from_info(info),
202 kind: SymbolKind::from_info(info),
203 visibility: u.arbitrary()?,
204 },
205 Class::Elf64 => Self {
206 address: u.arbitrary()?,
207 size: u.arbitrary()?,
208 name_offset: u.arbitrary()?,
209 section_index: u.arbitrary()?,
210 binding: SymbolBinding::from_info(info),
211 kind: SymbolKind::from_info(info),
212 visibility: u.arbitrary()?,
213 },
214 })
215 }
216 }
217
218 impl ArbitraryWithClass<'_> for SymbolTable {
219 fn arbitrary(u: &mut Unstructured<'_>, class: Class) -> arbitrary::Result<Self> {
220 let num_entries = u.arbitrary_len::<[u8; SYMBOL_LEN_64]>()?;
221 let mut entries = Vec::with_capacity(num_entries);
222 for _ in 0..num_entries {
223 entries.push(Symbol::arbitrary(u, class)?);
224 }
225 Ok(Self { entries })
226 }
227 }
228}