elb/
io.rs

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
27/// ELF-specific read functions.
28pub trait ElfRead {
29    /// Read enough bytes to fill the buffer `buf`.
30    ///
31    /// Similar to [`Read::read_exact`](std::io::Read::read_exact).
32    fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), crate::Error>;
33
34    /// Read one byte as `u8`.
35    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    /// Read one byte as `i8`.
42    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    /// Read one word.
57    ///
58    /// Reads `u32` when the class is [`Class::Elf32`], reads `u64` otherwise.
59    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
100/// ELF-specific write functions.
101pub trait ElfWrite {
102    /// Write one byte as `u8`.
103    fn write_u8(&mut self, value: u8) -> Result<(), Error> {
104        self.write_bytes(&[value])
105    }
106
107    /// Write one byte as `i8`.
108    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    /// Write one word.
121    ///
122    /// Writes `u32` when the class is [`Class::Elf32`], writes `u64` otherwise.
123    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    /// Write a word specified by `value`.
135    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    /// Write `value` as `u64`.
148    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    /// Write `value` as `i32`.
156    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    /// Write all bytes.
166    ///
167    /// Similar to [`Write::write_all`](std::io::Write::write_all).
168    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
178/// ELF-specific seek functions.
179pub trait ElfSeek {
180    /// Seek to the specified offset from the start of the file.
181    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
192/// Read an entity from a file or write an entity to a file.
193///
194/// Usually an entity doesn't occupy the whole section or segment.
195pub trait EntityIo {
196    /// Read the entity from the `reader`.
197    fn read<R: ElfRead>(reader: &mut R, class: Class, byte_order: ByteOrder) -> Result<Self, Error>
198    where
199        Self: Sized;
200
201    /// Write the entity to the `writer`.
202    fn write<W: ElfWrite>(
203        &self,
204        writer: &mut W,
205        class: Class,
206        byte_order: ByteOrder,
207    ) -> Result<(), Error>;
208}
209
210/// Read a block of data from a file.
211///
212/// Usually a block occupies the whole section or segment.
213pub trait BlockRead {
214    /// Read the table from the `reader`.
215    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
225/// Write a block of data to a file.
226///
227/// Usually a block occupies the whole section or segment.
228pub trait BlockWrite {
229    /// Write the table to the `writer`.
230    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}