memflow_win32_defs/offsets/
pdb.rs

1mod 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            // keep building the index
69            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        // add all the needed types iteratively until we're done
82        loop {
83            // get the last element in needed_types without holding an immutable borrow
84            let last = needed_types.iter().next_back().copied();
85
86            if let Some(type_index) = last {
87                // remove it
88                needed_types.remove(&type_index);
89
90                // add the type
91                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, // u16 can always be safely converted into usize
105                        bit_offset: f.bit_offset as usize, // u8 can always be safely converted into usize
106                    },
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        // no-op
180    }
181}