ud_emulator/pe/
sections.rs1use super::header::{Parsed, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE};
6use super::PeError;
7use crate::emulator::mmu::{Mmu, Perm};
8
9#[derive(Debug, Clone)]
13pub struct Section {
14 pub name: String,
15 pub va_start: u32,
17 pub mapped_size: u32,
19 pub perm: Perm,
21}
22
23const PAGE_SIZE: u32 = 0x1000;
24
25pub fn map_sections(mmu: &mut Mmu, parsed: &Parsed, bytes: &[u8]) -> Result<Vec<Section>, PeError> {
29 map_sections_at(mmu, parsed, bytes, parsed.optional.image_base)
30}
31
32pub fn map_sections_at(
37 mmu: &mut Mmu,
38 parsed: &Parsed,
39 bytes: &[u8],
40 image_base: u32,
41) -> Result<Vec<Section>, PeError> {
42 let mut out = Vec::with_capacity(parsed.sections.len());
43
44 let hdrs_size = round_up(parsed.optional.size_of_headers, PAGE_SIZE);
47 if hdrs_size > 0 {
48 mmu.map(image_base, hdrs_size, Perm::R | Perm::W);
49 let n = (parsed.optional.size_of_headers as usize).min(bytes.len());
50 mmu.write_initializer(image_base, &bytes[..n])?;
51 }
52
53 for sh in &parsed.sections {
54 let va = image_base.wrapping_add(sh.virtual_address);
55 let virt = sh.virtual_size.max(sh.size_of_raw_data);
56 let mapped = round_up(virt, PAGE_SIZE);
57
58 mmu.map(va, mapped, Perm::R | Perm::W);
60
61 let copy_n = (sh.size_of_raw_data.min(virt)) as usize;
66 let raw_off = sh.pointer_to_raw_data as usize;
67 if copy_n > 0 {
68 let src = bytes
69 .get(raw_off..raw_off + copy_n)
70 .ok_or(PeError::SectionOutOfRange {
71 name: sh.name.clone(),
72 raw_off: sh.pointer_to_raw_data,
73 raw_size: sh.size_of_raw_data,
74 })?;
75 mmu.write_initializer(va, src)?;
76 }
77 let mut perm = Perm::from_bits(0);
82 if (sh.characteristics & IMAGE_SCN_MEM_READ) != 0 {
83 perm = perm | Perm::R;
84 }
85 if (sh.characteristics & IMAGE_SCN_MEM_WRITE) != 0 {
86 perm = perm | Perm::W;
87 }
88 if (sh.characteristics & IMAGE_SCN_MEM_EXECUTE) != 0 {
89 perm = perm | Perm::X;
90 }
91 if perm.bits() == 0 {
96 perm = Perm::R;
97 }
98 out.push(Section {
99 name: sh.name.clone(),
100 va_start: va,
101 mapped_size: mapped,
102 perm,
103 });
104 }
105 Ok(out)
106}
107
108pub fn apply_section_permissions(mmu: &mut Mmu, section: &Section) {
112 mmu.map(section.va_start, section.mapped_size, section.perm);
113}
114
115fn round_up(v: u32, align: u32) -> u32 {
116 if align == 0 {
117 v
118 } else {
119 v.div_ceil(align).wrapping_mul(align)
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn round_up_helper() {
129 assert_eq!(round_up(0, 0x1000), 0);
130 assert_eq!(round_up(1, 0x1000), 0x1000);
131 assert_eq!(round_up(0x1000, 0x1000), 0x1000);
132 assert_eq!(round_up(0x1001, 0x1000), 0x2000);
133 }
134}