1 use core::fmt::Debug; 2 use core::mem; 3 4 use crate::elf; 5 use crate::endian; 6 use crate::pod::{Bytes, Pod}; 7 use crate::read::util; 8 use crate::read::{self, Error, ReadError}; 9 10 use super::FileHeader; 11 12 /// An iterator over the notes in an ELF section or segment. 13 #[derive(Debug)] 14 pub struct NoteIterator<'data, Elf> 15 where 16 Elf: FileHeader, 17 { 18 endian: Elf::Endian, 19 align: usize, 20 data: Bytes<'data>, 21 } 22 23 impl<'data, Elf> NoteIterator<'data, Elf> 24 where 25 Elf: FileHeader, 26 { 27 /// Returns `Err` if `align` is invalid. new( endian: Elf::Endian, align: Elf::Word, data: &'data [u8], ) -> read::Result<Self>28 pub(super) fn new( 29 endian: Elf::Endian, 30 align: Elf::Word, 31 data: &'data [u8], 32 ) -> read::Result<Self> { 33 let align = match align.into() { 34 0u64..=4 => 4, 35 8 => 8, 36 _ => return Err(Error("Invalid ELF note alignment")), 37 }; 38 // TODO: check data alignment? 39 Ok(NoteIterator { 40 endian, 41 align, 42 data: Bytes(data), 43 }) 44 } 45 46 /// Returns the next note. next(&mut self) -> read::Result<Option<Note<'data, Elf>>>47 pub fn next(&mut self) -> read::Result<Option<Note<'data, Elf>>> { 48 let mut data = self.data; 49 if data.is_empty() { 50 return Ok(None); 51 } 52 53 let header = data 54 .read_at::<Elf::NoteHeader>(0) 55 .read_error("ELF note is too short")?; 56 57 // The name has no alignment requirement. 58 let offset = mem::size_of::<Elf::NoteHeader>(); 59 let namesz = header.n_namesz(self.endian) as usize; 60 let name = data 61 .read_bytes_at(offset, namesz) 62 .read_error("Invalid ELF note namesz")? 63 .0; 64 65 // The descriptor must be aligned. 66 let offset = util::align(offset + namesz, self.align); 67 let descsz = header.n_descsz(self.endian) as usize; 68 let desc = data 69 .read_bytes_at(offset, descsz) 70 .read_error("Invalid ELF note descsz")? 71 .0; 72 73 // The next note (if any) must be aligned. 74 let offset = util::align(offset + descsz, self.align); 75 if data.skip(offset).is_err() { 76 data = Bytes(&[]); 77 } 78 self.data = data; 79 80 Ok(Some(Note { header, name, desc })) 81 } 82 } 83 84 /// A parsed `NoteHeader`. 85 #[derive(Debug)] 86 pub struct Note<'data, Elf> 87 where 88 Elf: FileHeader, 89 { 90 header: &'data Elf::NoteHeader, 91 name: &'data [u8], 92 desc: &'data [u8], 93 } 94 95 impl<'data, Elf: FileHeader> Note<'data, Elf> { 96 /// Return the `n_type` field of the `NoteHeader`. 97 /// 98 /// The meaning of this field is determined by `name`. n_type(&self, endian: Elf::Endian) -> u3299 pub fn n_type(&self, endian: Elf::Endian) -> u32 { 100 self.header.n_type(endian) 101 } 102 103 /// Return the `n_namesz` field of the `NoteHeader`. n_namesz(&self, endian: Elf::Endian) -> u32104 pub fn n_namesz(&self, endian: Elf::Endian) -> u32 { 105 self.header.n_namesz(endian) 106 } 107 108 /// Return the `n_descsz` field of the `NoteHeader`. n_descsz(&self, endian: Elf::Endian) -> u32109 pub fn n_descsz(&self, endian: Elf::Endian) -> u32 { 110 self.header.n_descsz(endian) 111 } 112 113 /// Return the bytes for the name field following the `NoteHeader`, 114 /// excluding any null terminator. 115 /// 116 /// This field is usually a string including a null terminator 117 /// (but it is not required to be). 118 /// 119 /// The length of this field (including any null terminator) is given by 120 /// `n_namesz`. name(&self) -> &'data [u8]121 pub fn name(&self) -> &'data [u8] { 122 if let Some((last, name)) = self.name.split_last() { 123 if *last == 0 { 124 return name; 125 } 126 } 127 self.name 128 } 129 130 /// Return the bytes for the desc field following the `NoteHeader`. 131 /// 132 /// The length of this field is given by `n_descsz`. The meaning 133 /// of this field is determined by `name` and `n_type`. desc(&self) -> &'data [u8]134 pub fn desc(&self) -> &'data [u8] { 135 self.desc 136 } 137 } 138 139 /// A trait for generic access to `NoteHeader32` and `NoteHeader64`. 140 #[allow(missing_docs)] 141 pub trait NoteHeader: Debug + Pod { 142 type Endian: endian::Endian; 143 n_namesz(&self, endian: Self::Endian) -> u32144 fn n_namesz(&self, endian: Self::Endian) -> u32; n_descsz(&self, endian: Self::Endian) -> u32145 fn n_descsz(&self, endian: Self::Endian) -> u32; n_type(&self, endian: Self::Endian) -> u32146 fn n_type(&self, endian: Self::Endian) -> u32; 147 } 148 149 impl<Endian: endian::Endian> NoteHeader for elf::NoteHeader32<Endian> { 150 type Endian = Endian; 151 152 #[inline] n_namesz(&self, endian: Self::Endian) -> u32153 fn n_namesz(&self, endian: Self::Endian) -> u32 { 154 self.n_namesz.get(endian) 155 } 156 157 #[inline] n_descsz(&self, endian: Self::Endian) -> u32158 fn n_descsz(&self, endian: Self::Endian) -> u32 { 159 self.n_descsz.get(endian) 160 } 161 162 #[inline] n_type(&self, endian: Self::Endian) -> u32163 fn n_type(&self, endian: Self::Endian) -> u32 { 164 self.n_type.get(endian) 165 } 166 } 167 168 impl<Endian: endian::Endian> NoteHeader for elf::NoteHeader64<Endian> { 169 type Endian = Endian; 170 171 #[inline] n_namesz(&self, endian: Self::Endian) -> u32172 fn n_namesz(&self, endian: Self::Endian) -> u32 { 173 self.n_namesz.get(endian) 174 } 175 176 #[inline] n_descsz(&self, endian: Self::Endian) -> u32177 fn n_descsz(&self, endian: Self::Endian) -> u32 { 178 self.n_descsz.get(endian) 179 } 180 181 #[inline] n_type(&self, endian: Self::Endian) -> u32182 fn n_type(&self, endian: Self::Endian) -> u32 { 183 self.n_type.get(endian) 184 } 185 } 186