1use std::prelude::v1::*;
6
7use std::{cmp, slice};
8
9use crate::Result;
10
11use super::image::*;
12use super::pe::validate_headers;
13use super::{Align, Pe, PeObject};
14
15#[derive(Copy, Clone)]
17pub struct PeView<'a> {
18 image: &'a [u8],
19}
20
21current_target! {
22 impl PeView<'static> {
23 #[inline]
25 pub unsafe fn new() -> PeView<'static> {
26 Self::module(image_base() as *const _ as *const u8)
27 }
28 }
29}
30impl<'a> PeView<'a> {
31 pub fn from_bytes<T: AsRef<[u8]> + ?Sized>(image: &'a T) -> Result<PeView<'a>> {
50 let image = image.as_ref();
51 let _ = validate_headers(image)?;
52 Ok(PeView { image })
53 }
54 #[inline]
64 pub unsafe fn module(base: *const u8) -> PeView<'a> {
65 let dos = &*(base as *const IMAGE_DOS_HEADER);
66 let nt = &*(base.offset(dos.e_lfanew as isize) as *const IMAGE_NT_HEADERS);
67 PeView {
68 image: slice::from_raw_parts(base, nt.OptionalHeader.SizeOfImage as usize),
69 }
70 }
71 pub fn to_file(self) -> Vec<u8> {
73 let (sizeof_headers, sizeof_image) = {
74 let optional_header = self.optional_header();
75 (optional_header.SizeOfHeaders, optional_header.SizeOfImage)
76 };
77
78 let mut file_size = sizeof_headers;
80 for section in self.section_headers() {
81 file_size = cmp::max(file_size, u32::wrapping_add(section.PointerToRawData, section.SizeOfRawData));
82 }
83 file_size = cmp::min(file_size, sizeof_image);
85
86 let mut vec = vec![0u8; file_size as usize];
88
89 let image = self.image();
91 unsafe {
92 let dest_headers = vec.get_unchecked_mut(..sizeof_headers as usize);
94 let src_headers = image.get_unchecked(..sizeof_headers as usize);
95 dest_headers.copy_from_slice(src_headers);
96 }
97
98 for section in self.section_headers() {
100 let dest = vec.get_mut(section.PointerToRawData as usize..u32::wrapping_add(section.PointerToRawData, section.SizeOfRawData) as usize);
101 let src = image.get(section.VirtualAddress as usize..u32::wrapping_add(section.VirtualAddress, section.VirtualSize) as usize);
102 if let (Some(dest), Some(src)) = (dest, src) {
104 dest.copy_from_slice(src);
105 }
106 }
107
108 vec
109 }
110}
111
112unsafe impl<'a> Pe<'a> for PeView<'a> {}
115
116unsafe impl<'a> PeObject<'a> for PeView<'a> {
117 fn image(&self) -> &'a [u8] {
118 self.image
119 }
120 fn align(&self) -> Align {
121 Align::Section
122 }
123 #[cfg(feature = "serde")]
124 fn serde_name(&self) -> &'static str {
125 "PeView"
126 }
127}
128
129#[cfg(feature = "serde")]
132impl<'a> serde::Serialize for PeView<'a> {
133 fn serialize<S: serde::Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
134 super::pe::serialize_pe(*self, serializer)
135 }
136}
137
138#[cfg(test)]
141mod tests {
142 use crate::Error;
143 use super::PeView;
144
145 #[test]
146 fn from_byte_slice() {
147 assert!(match PeView::from_bytes(&[]) { Err(Error::Bounds) => true, _ => false });
148 }
149}