pelite\wrap/
debug.rs

1use crate::*;
2use super::Wrap;
3
4/// Debug directory.
5impl<'a, Pe32: pe32::Pe<'a>, Pe64: pe64::Pe<'a>> Wrap<pe32::debug::Debug<'a, Pe32>, pe64::debug::Debug<'a, Pe64>> {
6	/// Gets the PE instance.
7	#[inline]
8	pub fn pe(&self) -> Wrap<Pe32, Pe64> {
9		match self {
10			Wrap::T32(debug) => Wrap::T32(debug.pe()),
11			Wrap::T64(debug) => Wrap::T64(debug.pe()),
12		}
13	}
14	/// Returns the underlying debug directories image.
15	#[inline]
16	pub fn image(&self) -> &'a [image::IMAGE_DEBUG_DIRECTORY] {
17		match self {
18			Wrap::T32(debug) => debug.image(),
19			Wrap::T64(debug) => debug.image(),
20		}
21	}
22	/// Gets the CodeView PDB file name.
23	#[inline]
24	pub fn pdb_file_name(&self) -> Option<&'a util::CStr> {
25		match self {
26			Wrap::T32(debug) => debug.pdb_file_name(),
27			Wrap::T64(debug) => debug.pdb_file_name(),
28		}
29	}
30	/// Iterator over the debug directories.
31	#[inline]
32	pub fn iter(&self) -> Wrap<pe32::debug::Iter<'a, Pe32>, pe64::debug::Iter<'a, Pe64>> {
33		match self {
34			Wrap::T32(debug) => Wrap::T32(debug.iter()),
35			Wrap::T64(debug) => Wrap::T64(debug.iter()),
36		}
37	}
38}
39
40impl<'a, Pe32: pe32::Pe<'a>, Pe64: pe64::Pe<'a>> IntoIterator for Wrap<pe32::debug::Debug<'a, Pe32>, pe64::debug::Debug<'a, Pe64>> {
41	type Item = Wrap<pe32::debug::Dir<'a, Pe32>, pe64::debug::Dir<'a, Pe64>>;
42	type IntoIter = Wrap<pe32::debug::Iter<'a, Pe32>, pe64::debug::Iter<'a, Pe64>>;
43	#[inline]
44	fn into_iter(self) -> Self::IntoIter {
45		self.iter()
46	}
47}
48
49/// Debug directory entry.
50impl<'a, Pe32: pe32::Pe<'a>, Pe64: pe64::Pe<'a>> Wrap<pe32::debug::Dir<'a, Pe32>, pe64::debug::Dir<'a, Pe64>> {
51	/// Gets the PE instance.
52	#[inline]
53	pub fn pe(&self) -> Wrap<Pe32, Pe64> {
54		match self {
55			Wrap::T32(dir) => Wrap::T32(dir.pe()),
56			Wrap::T64(dir) => Wrap::T64(dir.pe()),
57		}
58	}
59	/// Gets the underlying debug directory image.
60	#[inline]
61	pub fn image(&self) -> &'a image::IMAGE_DEBUG_DIRECTORY {
62		match self {
63			Wrap::T32(dir) => dir.image(),
64			Wrap::T64(dir) => dir.image(),
65		}
66	}
67	/// Gets the raw data of this debug directory entry.
68	#[inline]
69	pub fn data(&self) -> Option<&'a [u8]> {
70		match self {
71			Wrap::T32(dir) => dir.data(),
72			Wrap::T64(dir) => dir.data(),
73		}
74	}
75	/// Interprets the directory entry.
76	#[inline]
77	pub fn entry(&self) -> Result<Entry<'a>> {
78		match self {
79			Wrap::T32(dir) => dir.entry(),
80			Wrap::T64(dir) => dir.entry(),
81		}
82	}
83}
84
85//----------------------------------------------------------------
86
87#[derive(Copy, Clone, Debug)]
88#[cfg_attr(feature = "serde", derive(::serde::Serialize), serde(untagged))]
89pub enum Entry<'a> {
90	CodeView(CodeView<'a>),
91	Dbg(Dbg<'a>),
92	Pgo(Pgo<'a>),
93	Unknown(Option<&'a [u8]>),
94}
95impl<'a> Entry<'a> {
96	/// As a CodeView debug information entry.
97	pub fn as_code_view(self) -> Option<CodeView<'a>> {
98		match self { Entry::CodeView(cv) => Some(cv), _ => None }
99	}
100	/// As a Dbg information entry.
101	pub fn as_dbg(self) -> Option<Dbg<'a>> {
102		match self { Entry::Dbg(dbg) => Some(dbg), _ => None }
103	}
104	/// As a PGO information entry.
105	pub fn as_pgo(self) -> Option<Pgo<'a>> {
106		match self { Entry::Pgo(pgo) => Some(pgo), _ => None }
107	}
108	/// Unknown format, return as bytes.
109	pub fn as_unknown(self) -> Option<&'a [u8]> {
110		match self { Entry::Unknown(data) => data, _ => None }
111	}
112}
113
114//----------------------------------------------------------------
115
116use std::{fmt, str};
117use crate::image::*;
118use crate::util::CStr;
119
120/// CodeView information.
121#[derive(Copy, Clone)]
122pub enum CodeView<'a> {
123	/// CodeView 2.0 debug information.
124	Cv20 { image: &'a IMAGE_DEBUG_CV_INFO_PDB20, pdb_file_name: &'a CStr },
125	/// CodeView 7.0 debug information.
126	Cv70 { image: &'a IMAGE_DEBUG_CV_INFO_PDB70, pdb_file_name: &'a CStr },
127}
128impl<'a> CodeView<'a> {
129	pub fn format(&self) -> &'a str {
130		let cv_signature = match self {
131			CodeView::Cv20 { image, .. } => &image.CvSignature,
132			CodeView::Cv70 { image, .. } => &image.CvSignature,
133		} as *const _ as *const [u8; 4];
134		unsafe { str::from_utf8_unchecked(&*cv_signature) }
135	}
136	pub fn age(&self) -> u32 {
137		match self {
138			CodeView::Cv20 { image, .. } => image.Age,
139			CodeView::Cv70 { image, .. } => image.Age,
140		}
141	}
142	pub fn pdb_file_name(&self) -> &'a CStr {
143		match self {
144			CodeView::Cv20 { pdb_file_name, .. } => pdb_file_name,
145			CodeView::Cv70 { pdb_file_name, .. } => pdb_file_name,
146		}
147	}
148}
149impl<'a> fmt::Debug for CodeView<'a> {
150	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151		let mut stru = f.debug_struct("CodeView");
152		stru.field("format", &self.format());
153		stru.field("pdb_file_name", &self.pdb_file_name());
154		match self {
155			CodeView::Cv20 { image, .. } => {
156				stru.field("time_date_stamp", &image.TimeDateStamp);
157				stru.field("age", &image.Age);
158			},
159			CodeView::Cv70 { image, .. } => {
160				stru.field("signature", &image.Signature);
161				stru.field("age", &image.Age);
162			},
163		}
164		stru.finish()
165	}
166}
167
168//----------------------------------------------------------------
169
170/// Debug information.
171#[derive(Copy, Clone)]
172pub struct Dbg<'a> {
173	pub image: &'a IMAGE_DEBUG_MISC,
174}
175impl<'a> Dbg<'a> {
176	/// Gets the underlying information image.
177	pub fn image(&self) -> &'a IMAGE_DEBUG_MISC {
178		self.image
179	}
180}
181impl<'a> fmt::Debug for Dbg<'a> {
182	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
183		f.debug_struct("Dbg").finish()
184	}
185}
186
187//----------------------------------------------------------------
188
189/// PGO information.
190#[derive(Copy, Clone)]
191pub struct Pgo<'a> {
192	pub image: &'a [u32],
193}
194impl<'a> Pgo<'a> {
195	/// Gets the underlying image.
196	pub fn image(&self) -> &'a [u32] {
197		self.image
198	}
199	/// Iterator over the PGO sections.
200	pub fn iter(&self) -> PgoIter<'a> {
201		let image = if self.image.len() >= 1 { &self.image[1..] } else { self.image };
202		PgoIter { image }
203	}
204}
205impl<'a> IntoIterator for Pgo<'a> {
206	type Item = PgoItem<'a>;
207	type IntoIter = PgoIter<'a>;
208	fn into_iter(self) -> PgoIter<'a> {
209		self.iter()
210	}
211}
212impl<'a> fmt::Debug for Pgo<'a> {
213	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
214		f.debug_list().entries(self.iter()).finish()
215	}
216}
217/// Iterator over PGO sections.
218#[derive(Clone)]
219pub struct PgoIter<'a> {
220	image: &'a [u32],
221}
222impl<'a> Iterator for PgoIter<'a> {
223	type Item = PgoItem<'a>;
224	fn next(&mut self) -> Option<PgoItem<'a>> {
225		if self.image.len() >= 3 {
226			let rva = self.image[0];
227			let size = self.image[1];
228			let name = CStr::from_bytes(dataview::bytes(&self.image[2..]))?;
229			let len = name.len() >> 2;
230			self.image = &self.image[2 + len + 1..];
231			Some(PgoItem { rva, size, name })
232		}
233		else {
234			None
235		}
236	}
237}
238/// Describes a PGO section.
239#[derive(Copy, Clone, Debug)]
240#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
241pub struct PgoItem<'a> {
242	pub rva: u32,
243	pub size: u32,
244	pub name: &'a CStr,
245}
246
247//----------------------------------------------------------------
248
249#[cfg(feature = "serde")]
250mod serde2 {
251	use crate::util::serde_helper::*;
252	use super::{CodeView, Dbg, Pgo};
253
254	impl<'a> Serialize for CodeView<'a> {
255		fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
256			let mut state = serializer.serialize_struct("CodeView", 4)?;
257			state.serialize_field("format", &self.format())?;
258			state.serialize_field("pdb_file_name", &self.pdb_file_name())?;
259			match self {
260				CodeView::Cv20 { image, .. } => {
261					state.serialize_field("time_date_stamp", &image.TimeDateStamp)?;
262					state.serialize_field("age", &image.Age)?;
263				},
264				CodeView::Cv70 { image, .. } => {
265					state.serialize_field("signature", &image.Signature)?;
266					state.serialize_field("age", &image.Age)?;
267				},
268			}
269			state.end()
270		}
271	}
272	impl<'a> Serialize for Dbg<'a> {
273		fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
274			serializer.serialize_struct("Dbg", 0)?.end()
275		}
276	}
277	impl<'a> Serialize for Pgo<'a> {
278		fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
279			serializer.collect_seq(self.iter())
280		}
281	}
282}