From 43d478cf39f8faef9cf9d16ca47d3edd8152f4cb Mon Sep 17 00:00:00 2001 From: Josh Ferrell Date: Sun, 9 Jun 2024 12:17:54 -0400 Subject: Large PDB parsing performance improvements --- rust/examples/pdb-ng/src/symbol_parser.rs | 95 ++++++++++++++++--------------- 1 file changed, 48 insertions(+), 47 deletions(-) (limited to 'rust/examples/pdb-ng/src/symbol_parser.rs') diff --git a/rust/examples/pdb-ng/src/symbol_parser.rs b/rust/examples/pdb-ng/src/symbol_parser.rs index 5a1d8761..a80f4841 100644 --- a/rust/examples/pdb-ng/src/symbol_parser.rs +++ b/rust/examples/pdb-ng/src/symbol_parser.rs @@ -14,6 +14,7 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::mem; +use std::sync::OnceLock; use anyhow::{anyhow, Result}; use itertools::Itertools; @@ -515,7 +516,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { self.log(|| format!("Symbol {:?} ", sym.index())); let (name, address) = - if let Some(parsed) = self.handle_symbol_index(sym.index(), sym)? { + if let Some(parsed) = self.handle_symbol_index(sym.index(), &sym)? { final_symbols.insert(sym.index()); match parsed { ParsedSymbol::Data(ParsedDataSymbol { name, address, .. }) => { @@ -617,17 +618,14 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { fn handle_symbol_index( &mut self, idx: SymbolIndex, - sym: Symbol, + sym: &Symbol, ) -> Result> { if let None = self.indexed_symbols.get(&idx) { match sym.parse() { Ok(data) => match self.handle_symbol(idx, &data) { Ok(Some(parsed)) => { self.log(|| format!("Symbol {} parsed into: {:?}", idx, parsed)); - match &parsed { - _ => {} - } - self.indexed_symbols.insert(idx, parsed.clone()); + self.indexed_symbols.insert(idx, parsed); } Ok(None) => {} e => { @@ -1786,7 +1784,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { raw_name: &String, rva: Rva, ) -> Result<(Option>>, Option)> { - let (mut t, mut name) = match demangle_ms(&self.arch, raw_name.clone(), true) { + let (mut t, mut name) = match demangle_ms(&self.arch, raw_name, true) { Ok((Some(t), name)) => (Some(Conf::new(t, DEMANGLE_CONFIDENCE)), name), Ok((_, name)) => (None, name), _ => (None, vec![raw_name.clone()]), @@ -1818,48 +1816,51 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { // These have types but they aren't actually set anywhere. So it's the demangler's // job to take care of them, apparently? - let name_to_type: HashMap> = HashMap::from_iter([ - ( - "`RTTI Complete Object Locator'".to_string(), - vec![ - "_s_RTTICompleteObjectLocator".to_string(), - "_s__RTTICompleteObjectLocator".to_string(), - "_s__RTTICompleteObjectLocator2".to_string(), - ], - ), - ( - "`RTTI Class Hierarchy Descriptor'".to_string(), - vec![ - "_s_RTTIClassHierarchyDescriptor".to_string(), - "_s__RTTIClassHierarchyDescriptor".to_string(), - "_s__RTTIClassHierarchyDescriptor2".to_string(), - ], - ), - ( - // TODO: This type is dynamic - "`RTTI Base Class Array'".to_string(), - vec![ - "_s_RTTIBaseClassArray".to_string(), - "_s__RTTIBaseClassArray".to_string(), - "_s__RTTIBaseClassArray2".to_string(), - ], - ), - ( - "`RTTI Base Class Descriptor at (".to_string(), - vec![ - "_s_RTTIBaseClassDescriptor".to_string(), - "_s__RTTIBaseClassDescriptor".to_string(), - "_s__RTTICBaseClassDescriptor2".to_string(), - ], - ), - ( - "`RTTI Type Descriptor'".to_string(), - vec!["_TypeDescriptor".to_string()], - ), - ]); + static MEM: OnceLock)>> = OnceLock::new(); + let name_to_type = MEM.get_or_init(|| { + vec![ + ( + "`RTTI Complete Object Locator'".to_string(), + vec![ + "_s_RTTICompleteObjectLocator".to_string(), + "_s__RTTICompleteObjectLocator".to_string(), + "_s__RTTICompleteObjectLocator2".to_string(), + ], + ), + ( + "`RTTI Class Hierarchy Descriptor'".to_string(), + vec![ + "_s_RTTIClassHierarchyDescriptor".to_string(), + "_s__RTTIClassHierarchyDescriptor".to_string(), + "_s__RTTIClassHierarchyDescriptor2".to_string(), + ], + ), + ( + // TODO: This type is dynamic + "`RTTI Base Class Array'".to_string(), + vec![ + "_s_RTTIBaseClassArray".to_string(), + "_s__RTTIBaseClassArray".to_string(), + "_s__RTTIBaseClassArray2".to_string(), + ], + ), + ( + "`RTTI Base Class Descriptor at (".to_string(), + vec![ + "_s_RTTIBaseClassDescriptor".to_string(), + "_s__RTTIBaseClassDescriptor".to_string(), + "_s__RTTICBaseClassDescriptor2".to_string(), + ], + ), + ( + "`RTTI Type Descriptor'".to_string(), + vec!["_TypeDescriptor".to_string()], + ), + ] + }); if let Some(last_name) = name.last() { - for (search_name, search_types) in &name_to_type { + for (search_name, search_types) in name_to_type.iter() { if last_name.contains(search_name) { for search_type in search_types { if let Some(ty) = self.named_types.get(search_type) { -- cgit v1.3.1