1use anyhow::{ensure, Result};
2use simics::ConfObject;
3
4use crate::os::windows::util::{
5 read_nul_terminated_string, read_nul_terminated_string_dtb, read_virtual, read_virtual_dtb,
6};
7
8#[derive(Debug, Clone)]
9#[repr(C)]
10pub struct Guid {
12 pub data0: u32,
13 pub data1: u16,
14 pub data2: u16,
15 pub data3: u64,
16}
17
18#[derive(Debug, Clone)]
19pub struct CvInfoPdb70 {
21 pub cv_signature: u32,
22 pub signature: Guid,
23 pub age: u32,
24 pub file_name: String,
25}
26
27impl CvInfoPdb70 {
28 pub fn new(processor: *mut ConfObject, address: u64) -> Result<Self> {
30 let cv_signature = read_virtual::<u32>(processor, address)?;
31 let signature =
32 read_virtual::<Guid>(processor, address + std::mem::size_of::<u32>() as u64)?;
33 let age = read_virtual::<u32>(
34 processor,
35 address + std::mem::size_of::<u32>() as u64 + std::mem::size_of::<Guid>() as u64,
36 )?;
37 let file_name = read_nul_terminated_string(
38 processor,
39 address
40 + std::mem::size_of::<u32>() as u64
41 + std::mem::size_of::<Guid>() as u64
42 + std::mem::size_of::<u32>() as u64,
43 )?;
44
45 ensure!(cv_signature == 0x53445352, "Invalid CV signature");
46
47 Ok(Self {
48 cv_signature,
49 signature,
50 age,
51 file_name,
52 })
53 }
54
55 pub fn new_dtb(
57 processor: *mut ConfObject,
58 directory_table_base: u64,
59 address: u64,
60 ) -> Result<Self> {
61 let cv_signature = read_virtual_dtb::<u32>(processor, directory_table_base, address)?;
62 let signature = read_virtual_dtb::<Guid>(
63 processor,
64 directory_table_base,
65 address + std::mem::size_of::<u32>() as u64,
66 )?;
67 let age = read_virtual_dtb::<u32>(
68 processor,
69 directory_table_base,
70 address + std::mem::size_of::<u32>() as u64 + std::mem::size_of::<Guid>() as u64,
71 )?;
72 let file_name = read_nul_terminated_string_dtb(
73 processor,
74 directory_table_base,
75 address
76 + std::mem::size_of::<u32>() as u64
77 + std::mem::size_of::<Guid>() as u64
78 + std::mem::size_of::<u32>() as u64,
79 )?;
80
81 ensure!(cv_signature == 0x53445352, "Invalid CV signature");
82
83 Ok(Self {
84 cv_signature,
85 signature,
86 age,
87 file_name,
88 })
89 }
90
91 pub fn guid(&self) -> String {
92 let data3 = u64::from_be_bytes(self.signature.data3.to_le_bytes());
94
95 format!(
96 "{:08X}{:04X}{:04X}{:016X}{:01X}",
97 self.signature.data0, self.signature.data1, self.signature.data2, data3, self.age
98 )
99 }
100
101 pub fn file_name(&self) -> &str {
102 &self.file_name
103 }
104}
105
106#[derive(Debug, Clone)]
107pub struct Export {
109 pub name: Option<String>,
110 pub offset: Option<usize>,
111 pub rva: usize,
112 pub size: usize,
113}
114
115impl From<goblin::pe::export::Export<'_>> for Export {
116 fn from(export: goblin::pe::export::Export) -> Self {
117 Self {
118 name: export.name.map(|s| s.to_string()),
119 offset: export.offset,
120 rva: export.rva,
121 size: export.size,
122 }
123 }
124}
125
126impl From<&goblin::pe::export::Export<'_>> for Export {
127 fn from(export: &goblin::pe::export::Export) -> Self {
128 Self {
129 name: export.name.map(|s| s.to_string()),
130 offset: export.offset,
131 rva: export.rva,
132 size: export.size,
133 }
134 }
135}