memflow_win32_defs/offsets/
pdb.rs1mod data;
2
3use std::convert::TryInto;
4use std::prelude::v1::*;
5
6use data::TypeSet;
7use std::collections::HashMap;
8use std::{fmt, io, result};
9
10use pdb::{FallibleIterator, Result, Source, SourceSlice, SourceView, TypeData, PDB};
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct PdbSymbols {
14 symbol_map: HashMap<String, u32>,
15}
16
17impl PdbSymbols {
18 pub fn new(pdb_slice: &[u8]) -> Result<Self> {
19 let pdb_buffer = PdbSourceBuffer::new(pdb_slice);
20 let mut pdb = PDB::open(pdb_buffer)?;
21
22 let symbol_table = pdb.global_symbols()?;
23 let address_map = pdb.address_map()?;
24
25 let mut symbol_map = HashMap::new();
26
27 let mut symbols = symbol_table.iter();
28 while let Some(symbol) = symbols.next()? {
29 if let Ok(pdb::SymbolData::Public(data)) = symbol.parse() {
30 let rva = data.offset.to_rva(&address_map).unwrap_or_default();
31 symbol_map.insert(data.name.to_string().into(), rva.0);
32 }
33 }
34
35 Ok(Self { symbol_map })
36 }
37
38 pub fn find_symbol(&self, name: &str) -> Option<&u32> {
39 self.symbol_map.get(name)
40 }
41}
42
43#[derive(Debug, Clone, PartialEq, Eq)]
44pub struct PdbField {
45 pub type_name: String,
46 pub offset: usize,
47 pub bit_offset: usize,
48}
49
50#[derive(Debug, Clone, PartialEq, Eq)]
51pub struct PdbStruct {
52 field_map: HashMap<String, PdbField>,
53}
54
55impl PdbStruct {
56 pub fn new(pdb_slice: &[u8], class_name: &str) -> Result<Self> {
57 let pdb_buffer = PdbSourceBuffer::new(pdb_slice);
58 let mut pdb = PDB::open(pdb_buffer)?;
59
60 let type_information = pdb.type_information()?;
61 let mut type_finder = type_information.finder();
62
63 let mut needed_types = TypeSet::new();
64 let mut data = data::Data::new();
65
66 let mut type_iter = type_information.iter();
67 while let Some(typ) = type_iter.next()? {
68 type_finder.update(&type_iter);
70
71 if let Ok(TypeData::Class(class)) = typ.parse() {
72 if class.name.as_bytes() == class_name.as_bytes()
73 && !class.properties.forward_reference()
74 {
75 data.add(&type_finder, typ.index(), &mut needed_types)?;
76 break;
77 }
78 }
79 }
80
81 loop {
83 let last = needed_types.iter().next_back().copied();
85
86 if let Some(type_index) = last {
87 needed_types.remove(&type_index);
89
90 data.add(&type_finder, type_index, &mut needed_types)?;
92 } else {
93 break;
94 }
95 }
96
97 let mut field_map = HashMap::new();
98 for class in &data.classes {
99 class.fields.iter().for_each(|f| {
100 field_map.insert(
101 f.name.to_string().into_owned(),
102 PdbField {
103 type_name: f.type_name.clone(),
104 offset: f.offset as usize, bit_offset: f.bit_offset as usize, },
107 );
108 });
109 }
110
111 Ok(Self { field_map })
112 }
113
114 pub fn find_field(&self, name: &str) -> Option<&PdbField> {
115 self.field_map.get(name)
116 }
117}
118
119pub struct PdbSourceBuffer<'a> {
120 bytes: &'a [u8],
121}
122
123impl<'a> PdbSourceBuffer<'a> {
124 pub fn new(bytes: &'a [u8]) -> Self {
125 Self { bytes }
126 }
127}
128
129impl<'a> fmt::Debug for PdbSourceBuffer<'a> {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 write!(f, "PdbSourceBuffer({} bytes)", self.bytes.len())
132 }
133}
134
135impl<'a, 's> Source<'s> for PdbSourceBuffer<'a> {
136 fn view(
137 &mut self,
138 slices: &[SourceSlice],
139 ) -> result::Result<Box<dyn SourceView<'s>>, io::Error> {
140 let len = slices.iter().fold(0_usize, |acc, s| acc + s.size);
141
142 let mut v = PdbSourceBufferView {
143 bytes: Vec::with_capacity(len),
144 };
145 v.bytes.resize(len, 0);
146
147 let bytes = v.bytes.as_mut_slice();
148 let mut output_offset: usize = 0;
149 for slice in slices {
150 let offset = slice.offset.try_into().unwrap();
151 bytes[output_offset..(output_offset + slice.size)]
152 .copy_from_slice(&self.bytes[offset..(offset + slice.size)]);
153 output_offset += slice.size;
154 }
155
156 Ok(Box::new(v))
157 }
158}
159
160#[derive(Clone)]
161struct PdbSourceBufferView {
162 bytes: Vec<u8>,
163}
164
165impl fmt::Debug for PdbSourceBufferView {
166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167 write!(f, "PdbSourceBufferView({} bytes)", self.bytes.len())
168 }
169}
170
171impl SourceView<'_> for PdbSourceBufferView {
172 fn as_slice(&self) -> &[u8] {
173 self.bytes.as_slice()
174 }
175}
176
177impl Drop for PdbSourceBufferView {
178 fn drop(&mut self) {
179 }
181}