1use alloc::vec;
2use alloc::vec::Vec;
3use core::ffi::CStr;
4
5use crate::ByteOrder;
6use crate::Class;
7use crate::Error;
8
9use ByteOrder::*;
10use Class::*;
11
12macro_rules! define_read {
13 ($func: ident, $uint: ident) => {
14 #[doc = concat!("Read `", stringify!($uint), "`.")]
15 fn $func(&mut self, byte_order: ByteOrder) -> Result<$uint, crate::Error> {
16 let mut bytes = [0_u8; ::core::mem::size_of::<$uint>()];
17 self.read_bytes(&mut bytes[..])?;
18 let ret = match byte_order {
19 LittleEndian => $uint::from_le_bytes(bytes),
20 BigEndian => $uint::from_be_bytes(bytes),
21 };
22 Ok(ret)
23 }
24 };
25}
26
27pub trait ElfRead {
29 fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), crate::Error>;
33
34 fn read_u8(&mut self) -> Result<u8, crate::Error> {
36 let mut bytes = [0_u8; 1];
37 self.read_bytes(&mut bytes[..])?;
38 Ok(bytes[0])
39 }
40
41 fn read_i8(&mut self) -> Result<i8, crate::Error> {
43 let mut bytes = [0_u8; 1];
44 self.read_bytes(&mut bytes[..])?;
45 Ok(bytes[0] as i8)
46 }
47
48 define_read!(read_i16, i16);
49 define_read!(read_i32, i32);
50 define_read!(read_i64, i64);
51
52 define_read!(read_u16, u16);
53 define_read!(read_u32, u32);
54 define_read!(read_u64, u64);
55
56 fn read_word(&mut self, class: Class, byte_order: ByteOrder) -> Result<u64, crate::Error> {
60 match class {
61 Elf32 => self.read_u32(byte_order).map(Into::into),
62 Elf64 => self.read_u64(byte_order),
63 }
64 }
65}
66
67#[cfg(feature = "std")]
68impl<R: std::io::Read + ?Sized> ElfRead for R {
69 fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), crate::Error> {
70 Ok(self.read_exact(buf)?)
71 }
72}
73
74#[cfg(not(feature = "std"))]
75impl ElfRead for &[u8] {
76 fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), crate::Error> {
77 let n = buf.len();
78 if n > self.len() {
79 return Err(Error::UnexpectedEof);
80 }
81 buf.copy_from_slice(self[..n]);
82 *self = &self[n..];
83 Ok(())
84 }
85}
86
87macro_rules! define_write {
88 ($func: ident, $uint: ident) => {
89 #[doc = concat!("Write `", stringify!($uint), "`.")]
90 fn $func(&mut self, byte_order: ByteOrder, value: $uint) -> Result<(), Error> {
91 let bytes = match byte_order {
92 LittleEndian => value.to_le_bytes(),
93 BigEndian => value.to_be_bytes(),
94 };
95 self.write_bytes(&bytes)
96 }
97 };
98}
99
100pub trait ElfWrite {
102 fn write_u8(&mut self, value: u8) -> Result<(), Error> {
104 self.write_bytes(&[value])
105 }
106
107 fn write_i8(&mut self, value: i8) -> Result<(), Error> {
109 self.write_bytes(&value.to_ne_bytes())
110 }
111
112 define_write!(write_u16, u16);
113 define_write!(write_u32, u32);
114 define_write!(write_u64, u64);
115
116 define_write!(write_i16, i16);
117 define_write!(write_i32, i32);
118 define_write!(write_i64, i64);
119
120 fn write_word(&mut self, class: Class, byte_order: ByteOrder, value: u64) -> Result<(), Error> {
124 match class {
125 Elf32 => {
126 let value: u32 = value.try_into().map_err(|_| Error::TooBigWord(value))?;
127 self.write_u32(byte_order, value)?;
128 }
129 Elf64 => self.write_u64(byte_order, value)?,
130 }
131 Ok(())
132 }
133
134 fn write_word_as_u32(
136 &mut self,
137 class: Class,
138 byte_order: ByteOrder,
139 value: u32,
140 ) -> Result<(), Error> {
141 match class {
142 Elf32 => self.write_u32(byte_order, value),
143 Elf64 => self.write_u64(byte_order, value.into()),
144 }
145 }
146
147 fn write_u32_as_u64(&mut self, byte_order: ByteOrder, value: u64) -> Result<(), Error> {
149 self.write_u32(
150 byte_order,
151 value.try_into().map_err(|_| Error::TooBigWord(value))?,
152 )
153 }
154
155 fn write_i32_as_i64(&mut self, byte_order: ByteOrder, value: i64) -> Result<(), Error> {
157 self.write_i32(
158 byte_order,
159 value
160 .try_into()
161 .map_err(|_| Error::TooBigSignedWord(value))?,
162 )
163 }
164
165 fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), Error>;
169}
170
171#[cfg(feature = "std")]
172impl<W: std::io::Write + ?Sized> ElfWrite for W {
173 fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
174 Ok(self.write_all(bytes)?)
175 }
176}
177
178pub trait ElfSeek {
180 fn seek(&mut self, offset: u64) -> Result<(), Error>;
182}
183
184#[cfg(feature = "std")]
185impl<S: std::io::Seek + ?Sized> ElfSeek for S {
186 fn seek(&mut self, offset: u64) -> Result<(), Error> {
187 self.seek(std::io::SeekFrom::Start(offset))?;
188 Ok(())
189 }
190}
191
192pub trait EntityIo {
196 fn read<R: ElfRead>(reader: &mut R, class: Class, byte_order: ByteOrder) -> Result<Self, Error>
198 where
199 Self: Sized;
200
201 fn write<W: ElfWrite>(
203 &self,
204 writer: &mut W,
205 class: Class,
206 byte_order: ByteOrder,
207 ) -> Result<(), Error>;
208}
209
210pub trait BlockRead {
214 fn read<R: ElfRead>(
216 reader: &mut R,
217 class: Class,
218 byte_order: ByteOrder,
219 len: u64,
220 ) -> Result<Self, Error>
221 where
222 Self: Sized;
223}
224
225pub trait BlockWrite {
229 fn write<W: ElfWrite>(
231 &self,
232 writer: &mut W,
233 class: Class,
234 byte_order: ByteOrder,
235 ) -> Result<(), Error>;
236}
237
238impl BlockRead for Vec<u8> {
239 fn read<R: ElfRead>(
240 reader: &mut R,
241 _class: Class,
242 _byte_order: ByteOrder,
243 len: u64,
244 ) -> Result<Self, Error> {
245 let n: usize = len.try_into().map_err(|_| Error::TooBig("Block size"))?;
246 let mut buf = vec![0_u8; n];
247 reader.read_bytes(&mut buf[..])?;
248 Ok(buf)
249 }
250}
251
252impl<T: AsRef<[u8]>> BlockWrite for T {
253 fn write<W: ElfWrite>(
254 &self,
255 writer: &mut W,
256 _class: Class,
257 _byte_order: ByteOrder,
258 ) -> Result<(), Error> {
259 writer.write_bytes(self.as_ref())?;
260 Ok(())
261 }
262}
263
264impl BlockWrite for CStr {
265 fn write<W: ElfWrite>(
266 &self,
267 writer: &mut W,
268 _class: Class,
269 _byte_order: ByteOrder,
270 ) -> Result<(), Error> {
271 writer.write_bytes(self.to_bytes_with_nul())?;
272 Ok(())
273 }
274}
275
276pub(crate) fn zero<W: ElfWrite + ElfSeek>(
277 writer: &mut W,
278 offset: u64,
279 size: u64,
280) -> Result<(), Error> {
281 writer.seek(offset)?;
282 write_zeroes(writer, size)?;
283 Ok(())
284}
285
286pub(crate) fn write_zeroes<W: ElfWrite + ElfSeek>(writer: &mut W, size: u64) -> Result<(), Error> {
287 const BUF_LEN: usize = 4096;
288 let buf = [0_u8; BUF_LEN];
289 for offset in (0..size).step_by(BUF_LEN) {
290 let n = (offset + BUF_LEN as u64).min(size) - offset;
291 writer.write_bytes(&buf[..n as usize])?;
292 }
293 Ok(())
294}