pelite\wrap/
sections.rs

1use std::{fmt, mem, ops, slice};
2use crate::image::*;
3use crate::Pod;
4
5//----------------------------------------------------------------
6
7/// Section header.
8#[derive(Copy, Clone)]
9#[repr(transparent)]
10pub struct SectionHeader(IMAGE_SECTION_HEADER);
11
12impl SectionHeader {
13	/// Returns the name as a byte slice.
14	#[inline]
15	pub fn name_bytes(&self) -> &[u8] {
16		crate::util::trimn(&self.0.Name)
17	}
18	/// Returns the name.
19	pub fn name(&self) -> Result<&str, &[u8]> {
20		crate::util::parsen(&self.0.Name)
21	}
22	/// Returns the virtual range.
23	#[inline]
24	pub fn virtual_range(&self) -> std::ops::Range<u32> {
25		let start = self.0.VirtualAddress;
26		let end = u32::wrapping_add(self.0.VirtualAddress, self.0.VirtualSize);
27		start..end
28	}
29	/// Returns the file range.
30	#[inline]
31	pub fn file_range(&self) -> std::ops::Range<u32> {
32		let start = self.0.PointerToRawData;
33		let end = u32::wrapping_add(self.0.PointerToRawData, self.0.SizeOfRawData);
34		start..end
35	}
36}
37
38unsafe impl Pod for SectionHeader {}
39
40impl ops::Deref for SectionHeader {
41	type Target = IMAGE_SECTION_HEADER;
42	#[inline]
43	fn deref(&self) -> &IMAGE_SECTION_HEADER {
44		&self.0
45	}
46}
47
48impl fmt::Debug for SectionHeader {
49	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
50		let name = self.name();
51		let name = match &name {
52			Ok(name) => name as &dyn fmt::Debug,
53			Err(name) => name as &dyn fmt::Debug,
54		};
55		f.debug_struct("SectionHeader")
56			.field("Name", name)
57			.field("VirtualAddress", &format_args!("{:#x}", self.0.VirtualAddress))
58			.field("VirtualSize", &format_args!("{:#x}", self.0.VirtualSize))
59			.field("PointerToRawData", &format_args!("{:#x}", self.0.PointerToRawData))
60			.field("SizeOfRawData", &format_args!("{:#x}", self.0.SizeOfRawData))
61			.field("Characteristics", &format_args!("{:#x}", self.0.Characteristics))
62			.finish()
63	}
64}
65
66//----------------------------------------------------------------
67
68/// Section headers.
69#[repr(transparent)]
70pub struct SectionHeaders([IMAGE_SECTION_HEADER]);
71
72impl SectionHeaders {
73	pub(crate) fn new(image: &[IMAGE_SECTION_HEADER]) -> &SectionHeaders {
74		unsafe { mem::transmute(image) }
75	}
76	/// Returns the underlying slice of section headers.
77	#[inline]
78	pub fn image(&self) -> &[IMAGE_SECTION_HEADER] {
79		&self.0
80	}
81	/// Gets the section headers as a slice of `SectionHeader`.
82	#[inline]
83	pub fn as_slice(&self) -> &[SectionHeader] {
84		unsafe { mem::transmute(self) }
85	}
86	/// Returns an iterator over the `SectionHeader` elements.
87	#[inline]
88	pub fn iter(&self) -> slice::Iter<'_, SectionHeader> {
89		self.as_slice().iter()
90	}
91	/// Finds a section header by its name.
92	#[inline]
93	pub fn by_name<S: ?Sized + AsRef<[u8]>>(&self, name: &S) -> Option<&SectionHeader> {
94		// Names have a max length, if larger they will never match
95		let name = name.as_ref();
96		if name.len() > IMAGE_SIZEOF_SHORT_NAME {
97			return None;
98		}
99		// Copy the prefix into a new buffer for easy comparison
100		let mut name_buf = [0u8; IMAGE_SIZEOF_SHORT_NAME];
101		for i in 0..name.len() {
102			name_buf[i] = name[i];
103		}
104		for sect in self.iter() {
105			if sect.0.Name == name_buf {
106				return Some(sect);
107			}
108		}
109		None
110	}
111	/// Finds a section header by its RVA.
112	#[inline]
113	pub fn by_rva(&self, rva: u32) -> Option<&SectionHeader> {
114		for sect in self.iter() {
115			// FIXME! Should this round up the VirtualSize to the next virtual section alignment?
116			if rva >= sect.VirtualAddress && rva < u32::wrapping_add(sect.VirtualAddress, sect.VirtualSize) {
117				return Some(sect);
118			}
119		}
120		None
121	}
122}
123
124unsafe impl Pod for SectionHeaders {}
125
126impl<'a> IntoIterator for &'a SectionHeaders {
127	type Item = &'a SectionHeader;
128	type IntoIter = slice::Iter<'a, SectionHeader>;
129	fn into_iter(self) -> Self::IntoIter {
130		self.as_slice().into_iter()
131	}
132}
133
134impl fmt::Debug for SectionHeaders {
135	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136		self.as_slice().fmt(f)
137	}
138}
139
140//----------------------------------------------------------------
141
142#[cfg(feature = "serde")]
143pub(crate) fn serialize_name<S: ::serde::ser::Serializer>(name: &[u8; IMAGE_SIZEOF_SHORT_NAME], serializer: S) -> Result<S::Ok, S::Error> {
144	match crate::util::parsen(name) {
145		Ok(name) => serializer.serialize_str(name),
146		Err(name) => serializer.serialize_bytes(name),
147	}
148}
149
150#[cfg(feature = "serde")]
151mod serde {
152	use crate::util::serde_helper::*;
153	use super::{SectionHeader, SectionHeaders};
154
155	impl serde::Serialize for SectionHeaders {
156		fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
157			serializer.collect_seq(self.iter())
158		}
159	}
160
161	impl serde::Serialize for SectionHeader {
162		fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
163			self.0.serialize(serializer)
164		}
165	}
166}