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")]
68#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
69impl<R: std::io::Read + ?Sized> ElfRead for R {
70 fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), crate::Error> {
71 Ok(self.read_exact(buf)?)
72 }
73}
74
75#[cfg(not(feature = "std"))]
76#[cfg_attr(docsrs, doc(cfg(not(feature = "std"))))]
77impl ElfRead for &[u8] {
78 fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), crate::Error> {
79 let n = buf.len();
80 if n > self.len() {
81 return Err(Error::UnexpectedEof);
82 }
83 buf.copy_from_slice(&self[..n]);
84 *self = &self[n..];
85 Ok(())
86 }
87}
88
89macro_rules! define_write {
90 ($func: ident, $uint: ident) => {
91 #[doc = concat!("Write `", stringify!($uint), "`.")]
92 fn $func(&mut self, byte_order: ByteOrder, value: $uint) -> Result<(), Error> {
93 let bytes = match byte_order {
94 LittleEndian => value.to_le_bytes(),
95 BigEndian => value.to_be_bytes(),
96 };
97 self.write_bytes(&bytes)
98 }
99 };
100}
101
102pub trait ElfWrite {
104 fn write_u8(&mut self, value: u8) -> Result<(), Error> {
106 self.write_bytes(&[value])
107 }
108
109 fn write_i8(&mut self, value: i8) -> Result<(), Error> {
111 self.write_bytes(&value.to_ne_bytes())
112 }
113
114 define_write!(write_u16, u16);
115 define_write!(write_u32, u32);
116 define_write!(write_u64, u64);
117
118 define_write!(write_i16, i16);
119 define_write!(write_i32, i32);
120 define_write!(write_i64, i64);
121
122 fn write_word(&mut self, class: Class, byte_order: ByteOrder, value: u64) -> Result<(), Error> {
126 match class {
127 Elf32 => {
128 let value: u32 = value.try_into().map_err(|_| Error::TooBigWord(value))?;
129 self.write_u32(byte_order, value)?;
130 }
131 Elf64 => self.write_u64(byte_order, value)?,
132 }
133 Ok(())
134 }
135
136 fn write_word_as_u32(
138 &mut self,
139 class: Class,
140 byte_order: ByteOrder,
141 value: u32,
142 ) -> Result<(), Error> {
143 match class {
144 Elf32 => self.write_u32(byte_order, value),
145 Elf64 => self.write_u64(byte_order, value.into()),
146 }
147 }
148
149 fn write_u32_as_u64(&mut self, byte_order: ByteOrder, value: u64) -> Result<(), Error> {
151 self.write_u32(
152 byte_order,
153 value.try_into().map_err(|_| Error::TooBigWord(value))?,
154 )
155 }
156
157 fn write_i32_as_i64(&mut self, byte_order: ByteOrder, value: i64) -> Result<(), Error> {
159 self.write_i32(
160 byte_order,
161 value
162 .try_into()
163 .map_err(|_| Error::TooBigSignedWord(value))?,
164 )
165 }
166
167 fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), Error>;
171}
172
173#[cfg(feature = "std")]
174#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
175impl<W: std::io::Write + ?Sized> ElfWrite for W {
176 fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
177 Ok(self.write_all(bytes)?)
178 }
179}
180
181pub trait ElfSeek {
183 fn seek(&mut self, offset: u64) -> Result<(), Error>;
185}
186
187#[cfg(feature = "std")]
188#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
189impl<S: std::io::Seek + ?Sized> ElfSeek for S {
190 fn seek(&mut self, offset: u64) -> Result<(), Error> {
191 self.seek(std::io::SeekFrom::Start(offset))?;
192 Ok(())
193 }
194}
195
196pub trait EntityIo {
200 fn read<R: ElfRead>(reader: &mut R, class: Class, byte_order: ByteOrder) -> Result<Self, Error>
202 where
203 Self: Sized;
204
205 fn write<W: ElfWrite>(
207 &self,
208 writer: &mut W,
209 class: Class,
210 byte_order: ByteOrder,
211 ) -> Result<(), Error>;
212}
213
214pub trait BlockRead {
218 fn read<R: ElfRead>(
220 reader: &mut R,
221 class: Class,
222 byte_order: ByteOrder,
223 len: u64,
224 ) -> Result<Self, Error>
225 where
226 Self: Sized;
227}
228
229pub trait BlockWrite {
233 fn write<W: ElfWrite>(
235 &self,
236 writer: &mut W,
237 class: Class,
238 byte_order: ByteOrder,
239 ) -> Result<(), Error>;
240}
241
242impl BlockRead for Vec<u8> {
243 fn read<R: ElfRead>(
244 reader: &mut R,
245 _class: Class,
246 _byte_order: ByteOrder,
247 len: u64,
248 ) -> Result<Self, Error> {
249 let n: usize = len.try_into().map_err(|_| Error::TooBig("Block size"))?;
250 let mut buf = vec![0_u8; n];
251 reader.read_bytes(&mut buf[..])?;
252 Ok(buf)
253 }
254}
255
256impl<T: AsRef<[u8]>> BlockWrite for T {
257 fn write<W: ElfWrite>(
258 &self,
259 writer: &mut W,
260 _class: Class,
261 _byte_order: ByteOrder,
262 ) -> Result<(), Error> {
263 writer.write_bytes(self.as_ref())?;
264 Ok(())
265 }
266}
267
268impl BlockWrite for CStr {
269 fn write<W: ElfWrite>(
270 &self,
271 writer: &mut W,
272 _class: Class,
273 _byte_order: ByteOrder,
274 ) -> Result<(), Error> {
275 writer.write_bytes(self.to_bytes_with_nul())?;
276 Ok(())
277 }
278}
279
280pub(crate) fn zero<W: ElfWrite + ElfSeek>(
281 writer: &mut W,
282 offset: u64,
283 size: u64,
284) -> Result<(), Error> {
285 writer.seek(offset)?;
286 write_zeroes(writer, size)?;
287 Ok(())
288}
289
290pub(crate) fn write_zeroes<W: ElfWrite + ElfSeek>(writer: &mut W, size: u64) -> Result<(), Error> {
291 const BUF_LEN: usize = 4096;
292 let buf = [0_u8; BUF_LEN];
293 for offset in (0..size).step_by(BUF_LEN) {
294 let n = (offset + BUF_LEN as u64).min(size) - offset;
295 writer.write_bytes(&buf[..n as usize])?;
296 }
297 Ok(())
298}