1 use core::marker::PhantomData; 2 use core::{cmp, iter, result, slice, str}; 3 4 use crate::endian::LittleEndian as LE; 5 use crate::pe; 6 use crate::pod::Bytes; 7 use crate::read::{ 8 self, CompressedData, ObjectSection, ObjectSegment, ReadError, Relocation, Result, 9 SectionFlags, SectionIndex, SectionKind, 10 }; 11 12 use super::{ImageNtHeaders, PeFile}; 13 14 /// An iterator over the loadable sections of a `PeFile32`. 15 pub type PeSegmentIterator32<'data, 'file> = PeSegmentIterator<'data, 'file, pe::ImageNtHeaders32>; 16 /// An iterator over the loadable sections of a `PeFile64`. 17 pub type PeSegmentIterator64<'data, 'file> = PeSegmentIterator<'data, 'file, pe::ImageNtHeaders64>; 18 19 /// An iterator over the loadable sections of a `PeFile`. 20 #[derive(Debug)] 21 pub struct PeSegmentIterator<'data, 'file, Pe> 22 where 23 'data: 'file, 24 Pe: ImageNtHeaders, 25 { 26 pub(super) file: &'file PeFile<'data, Pe>, 27 pub(super) iter: slice::Iter<'file, pe::ImageSectionHeader>, 28 } 29 30 impl<'data, 'file, Pe: ImageNtHeaders> Iterator for PeSegmentIterator<'data, 'file, Pe> { 31 type Item = PeSegment<'data, 'file, Pe>; 32 next(&mut self) -> Option<Self::Item>33 fn next(&mut self) -> Option<Self::Item> { 34 self.iter.next().map(|section| PeSegment { 35 file: self.file, 36 section, 37 }) 38 } 39 } 40 41 /// A loadable section of a `PeFile32`. 42 pub type PeSegment32<'data, 'file> = PeSegment<'data, 'file, pe::ImageNtHeaders32>; 43 /// A loadable section of a `PeFile64`. 44 pub type PeSegment64<'data, 'file> = PeSegment<'data, 'file, pe::ImageNtHeaders64>; 45 46 /// A loadable section of a `PeFile`. 47 #[derive(Debug)] 48 pub struct PeSegment<'data, 'file, Pe> 49 where 50 'data: 'file, 51 Pe: ImageNtHeaders, 52 { 53 file: &'file PeFile<'data, Pe>, 54 section: &'file pe::ImageSectionHeader, 55 } 56 57 impl<'data, 'file, Pe: ImageNtHeaders> PeSegment<'data, 'file, Pe> { bytes(&self) -> Result<Bytes<'data>>58 fn bytes(&self) -> Result<Bytes<'data>> { 59 self.section 60 .pe_data(self.file.data) 61 .read_error("Invalid PE section offset or size") 62 } 63 } 64 65 impl<'data, 'file, Pe: ImageNtHeaders> read::private::Sealed for PeSegment<'data, 'file, Pe> {} 66 67 impl<'data, 'file, Pe: ImageNtHeaders> ObjectSegment<'data> for PeSegment<'data, 'file, Pe> { 68 #[inline] address(&self) -> u6469 fn address(&self) -> u64 { 70 u64::from(self.section.virtual_address.get(LE)) 71 } 72 73 #[inline] size(&self) -> u6474 fn size(&self) -> u64 { 75 u64::from(self.section.virtual_size.get(LE)) 76 } 77 78 #[inline] align(&self) -> u6479 fn align(&self) -> u64 { 80 self.file.section_alignment() 81 } 82 83 #[inline] file_range(&self) -> (u64, u64)84 fn file_range(&self) -> (u64, u64) { 85 let (offset, size) = self.section.pe_file_range(); 86 (u64::from(offset), u64::from(size)) 87 } 88 data(&self) -> Result<&'data [u8]>89 fn data(&self) -> Result<&'data [u8]> { 90 Ok(self.bytes()?.0) 91 } 92 data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>>93 fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> { 94 Ok(read::data_range( 95 self.bytes()?, 96 self.address(), 97 address, 98 size, 99 )) 100 } 101 102 #[inline] name(&self) -> Result<Option<&str>>103 fn name(&self) -> Result<Option<&str>> { 104 let name = self.section.name(self.file.symbols.strings())?; 105 Ok(Some( 106 str::from_utf8(name) 107 .ok() 108 .read_error("Non UTF-8 PE section name")?, 109 )) 110 } 111 } 112 113 /// An iterator over the sections of a `PeFile32`. 114 pub type PeSectionIterator32<'data, 'file> = PeSectionIterator<'data, 'file, pe::ImageNtHeaders32>; 115 /// An iterator over the sections of a `PeFile64`. 116 pub type PeSectionIterator64<'data, 'file> = PeSectionIterator<'data, 'file, pe::ImageNtHeaders64>; 117 118 /// An iterator over the sections of a `PeFile`. 119 #[derive(Debug)] 120 pub struct PeSectionIterator<'data, 'file, Pe> 121 where 122 'data: 'file, 123 Pe: ImageNtHeaders, 124 { 125 pub(super) file: &'file PeFile<'data, Pe>, 126 pub(super) iter: iter::Enumerate<slice::Iter<'file, pe::ImageSectionHeader>>, 127 } 128 129 impl<'data, 'file, Pe: ImageNtHeaders> Iterator for PeSectionIterator<'data, 'file, Pe> { 130 type Item = PeSection<'data, 'file, Pe>; 131 next(&mut self) -> Option<Self::Item>132 fn next(&mut self) -> Option<Self::Item> { 133 self.iter.next().map(|(index, section)| PeSection { 134 file: self.file, 135 index: SectionIndex(index + 1), 136 section, 137 }) 138 } 139 } 140 141 /// A section of a `PeFile32`. 142 pub type PeSection32<'data, 'file> = PeSection<'data, 'file, pe::ImageNtHeaders32>; 143 /// A section of a `PeFile64`. 144 pub type PeSection64<'data, 'file> = PeSection<'data, 'file, pe::ImageNtHeaders64>; 145 146 /// A section of a `PeFile`. 147 #[derive(Debug)] 148 pub struct PeSection<'data, 'file, Pe> 149 where 150 'data: 'file, 151 Pe: ImageNtHeaders, 152 { 153 pub(super) file: &'file PeFile<'data, Pe>, 154 pub(super) index: SectionIndex, 155 pub(super) section: &'file pe::ImageSectionHeader, 156 } 157 158 impl<'data, 'file, Pe: ImageNtHeaders> PeSection<'data, 'file, Pe> { bytes(&self) -> Result<Bytes<'data>>159 fn bytes(&self) -> Result<Bytes<'data>> { 160 self.section 161 .pe_data(self.file.data) 162 .read_error("Invalid PE section offset or size") 163 } 164 } 165 166 impl<'data, 'file, Pe: ImageNtHeaders> read::private::Sealed for PeSection<'data, 'file, Pe> {} 167 168 impl<'data, 'file, Pe: ImageNtHeaders> ObjectSection<'data> for PeSection<'data, 'file, Pe> { 169 type RelocationIterator = PeRelocationIterator<'data, 'file>; 170 171 #[inline] index(&self) -> SectionIndex172 fn index(&self) -> SectionIndex { 173 self.index 174 } 175 176 #[inline] address(&self) -> u64177 fn address(&self) -> u64 { 178 u64::from(self.section.virtual_address.get(LE)) 179 } 180 181 #[inline] size(&self) -> u64182 fn size(&self) -> u64 { 183 u64::from(self.section.virtual_size.get(LE)) 184 } 185 186 #[inline] align(&self) -> u64187 fn align(&self) -> u64 { 188 self.file.section_alignment() 189 } 190 191 #[inline] file_range(&self) -> Option<(u64, u64)>192 fn file_range(&self) -> Option<(u64, u64)> { 193 let (offset, size) = self.section.pe_file_range(); 194 if size == 0 { 195 None 196 } else { 197 Some((u64::from(offset), u64::from(size))) 198 } 199 } 200 data(&self) -> Result<&'data [u8]>201 fn data(&self) -> Result<&'data [u8]> { 202 Ok(self.bytes()?.0) 203 } 204 data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>>205 fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> { 206 Ok(read::data_range( 207 self.bytes()?, 208 self.address(), 209 address, 210 size, 211 )) 212 } 213 214 #[inline] compressed_data(&self) -> Result<CompressedData<'data>>215 fn compressed_data(&self) -> Result<CompressedData<'data>> { 216 self.data().map(CompressedData::none) 217 } 218 219 #[inline] name(&self) -> Result<&str>220 fn name(&self) -> Result<&str> { 221 let name = self.section.name(self.file.symbols.strings())?; 222 str::from_utf8(name) 223 .ok() 224 .read_error("Non UTF-8 PE section name") 225 } 226 227 #[inline] segment_name(&self) -> Result<Option<&str>>228 fn segment_name(&self) -> Result<Option<&str>> { 229 Ok(None) 230 } 231 232 #[inline] kind(&self) -> SectionKind233 fn kind(&self) -> SectionKind { 234 self.section.kind() 235 } 236 relocations(&self) -> PeRelocationIterator<'data, 'file>237 fn relocations(&self) -> PeRelocationIterator<'data, 'file> { 238 PeRelocationIterator::default() 239 } 240 flags(&self) -> SectionFlags241 fn flags(&self) -> SectionFlags { 242 SectionFlags::Coff { 243 characteristics: self.section.characteristics.get(LE), 244 } 245 } 246 } 247 248 impl pe::ImageSectionHeader { pe_file_range(&self) -> (u32, u32)249 fn pe_file_range(&self) -> (u32, u32) { 250 // Pointer and size will be zero for uninitialized data; we don't need to validate this. 251 let offset = self.pointer_to_raw_data.get(LE); 252 let size = cmp::min(self.virtual_size.get(LE), self.size_of_raw_data.get(LE)); 253 (offset, size) 254 } 255 256 /// Return the data for a PE section. pe_data<'data>(&self, data: Bytes<'data>) -> result::Result<Bytes<'data>, ()>257 pub fn pe_data<'data>(&self, data: Bytes<'data>) -> result::Result<Bytes<'data>, ()> { 258 let (offset, size) = self.pe_file_range(); 259 data.read_bytes_at(offset as usize, size as usize) 260 } 261 } 262 263 /// An iterator over the relocations in an `PeSection`. 264 #[derive(Debug, Default)] 265 pub struct PeRelocationIterator<'data, 'file>(PhantomData<(&'data (), &'file ())>); 266 267 impl<'data, 'file> Iterator for PeRelocationIterator<'data, 'file> { 268 type Item = (u64, Relocation); 269 next(&mut self) -> Option<Self::Item>270 fn next(&mut self) -> Option<Self::Item> { 271 None 272 } 273 } 274