1use crate::error::Error;
2use bitflags::bitflags;
3use pdb::{
4 ArgumentList, ArrayType, ClassKind, ClassType, CrossModuleExports, CrossModuleImports,
5 CrossModuleRef, DebugInformation, FallibleIterator, FunctionAttributes, IdData, IdIndex,
6 IdInformation, Item, ItemFinder, ItemIndex, ItemIter, MachineType, MemberFunctionType,
7 ModifierType, Module, ModuleInfo, PointerMode, PointerType, PrimitiveKind, PrimitiveType,
8 ProcedureType, RawString, StringTable, TypeData, TypeIndex, TypeInformation, UnionType,
9 Variant,
10};
11use range_collections::range_set::RangeSetRange;
12use range_collections::{RangeSet, RangeSet2};
13use std::cmp::Ordering;
14use std::collections::{BTreeSet, HashMap};
15use std::fmt::Write;
16use std::mem;
17use std::sync::Mutex;
18
19type Result<V> = std::result::Result<V, Error>;
20
21bitflags! {
22 #[derive(Clone, Copy)]
24 pub struct TypeFormatterFlags: u32 {
25 const NO_FUNCTION_RETURN = 0b1;
27
28 const NO_MEMBER_FUNCTION_STATIC = 0b10;
30
31 const SPACE_AFTER_COMMA = 0b100;
33
34 const SPACE_BEFORE_POINTER = 0b1000;
36
37 const NAME_ONLY = 0b10000;
39
40 const NO_ARGUMENTS = 0b100000;
42 }
43}
44
45impl Default for TypeFormatterFlags {
46 fn default() -> Self {
47 Self::NO_FUNCTION_RETURN
48 | Self::NO_MEMBER_FUNCTION_STATIC
49 | Self::SPACE_AFTER_COMMA
50 | Self::NAME_ONLY
51 }
52}
53
54pub trait ModuleProvider<'s> {
61 fn get_module_info(
63 &self,
64 module_index: usize,
65 module: &Module,
66 ) -> std::result::Result<Option<&ModuleInfo<'s>>, pdb::Error>;
67}
68
69pub struct TypeFormatter<'a, 's> {
82 module_provider: &'a (dyn ModuleProvider<'s> + Sync),
83 modules: Vec<Module<'a>>,
84 string_table: Option<&'a StringTable<'s>>,
85 cache: Mutex<TypeFormatterCache<'a>>,
86 ptr_size: u64,
87 flags: TypeFormatterFlags,
88}
89
90struct TypeFormatterCache<'a> {
91 type_map: TypeMap<'a>,
92 type_size_cache: TypeSizeCache<'a>,
93 id_map: IdMap<'a>,
94 module_name_map: Option<HashMap<String, usize>>,
96 module_imports: HashMap<usize, Result<CrossModuleImports<'a>>>,
97 module_exports: HashMap<usize, Result<CrossModuleExports>>,
98}
99
100struct TypeFormatterForModule<'cache, 'a, 's> {
105 module_index: usize,
106 module_provider: &'a (dyn ModuleProvider<'s> + Sync),
107 modules: &'cache [Module<'a>],
108 string_table: Option<&'a StringTable<'s>>,
109 cache: &'cache mut TypeFormatterCache<'a>,
110 ptr_size: u64,
111 flags: TypeFormatterFlags,
112}
113
114impl<'a, 's> TypeFormatter<'a, 's> {
115 pub fn new_from_parts(
122 module_provider: &'a (dyn ModuleProvider<'s> + Sync),
123 modules: Vec<Module<'a>>,
124 debug_info: &DebugInformation<'s>,
125 type_info: &'a TypeInformation<'s>,
126 id_info: &'a IdInformation<'s>,
127 string_table: Option<&'a StringTable<'s>>,
128 flags: TypeFormatterFlags,
129 ) -> std::result::Result<Self, pdb::Error> {
130 let type_map = TypeMap {
131 iter: type_info.iter(),
132 finder: type_info.finder(),
133 };
134 let type_size_cache = TypeSizeCache {
135 forward_ref_sizes: HashMap::new(),
136 cached_ranges: RangeSet::empty(),
137 };
138
139 let id_map = IdMap {
140 iter: id_info.iter(),
141 finder: id_info.finder(),
142 };
143
144 let ptr_size = match debug_info.machine_type()? {
145 MachineType::Amd64 | MachineType::Arm64 | MachineType::Ia64 | MachineType::RiscV64 => 8,
146 MachineType::RiscV128 => 16,
147 _ => 4,
148 };
149
150 Ok(Self {
151 module_provider,
152 modules,
153 string_table,
154 cache: Mutex::new(TypeFormatterCache {
155 type_map,
156 type_size_cache,
157 id_map,
158 module_name_map: None,
159 module_imports: HashMap::new(),
160 module_exports: HashMap::new(),
161 }),
162 ptr_size,
163 flags,
164 })
165 }
166
167 pub fn modules(&self) -> &[Module<'a>] {
169 &self.modules
170 }
171
172 fn for_module<F, R>(&self, module_index: usize, f: F) -> R
173 where
174 F: FnOnce(&mut TypeFormatterForModule<'_, 'a, 's>) -> R,
175 {
176 let mut cache = self.cache.lock().unwrap();
177 let mut for_module = TypeFormatterForModule {
178 module_index,
179 module_provider: self.module_provider,
180 modules: &self.modules,
181 string_table: self.string_table,
182 cache: &mut cache,
183 ptr_size: self.ptr_size,
184 flags: self.flags,
185 };
186 f(&mut for_module)
187 }
188
189 pub fn get_type_size(&self, module_index: usize, index: TypeIndex) -> u64 {
191 self.for_module(module_index, |tf| tf.get_type_size(index))
192 }
193
194 pub fn format_function(
203 &self,
204 name: &str,
205 module_index: usize,
206 function_type_index: TypeIndex,
207 ) -> Result<String> {
208 let mut s = String::new();
209 self.emit_function(&mut s, name, module_index, function_type_index)?;
210 Ok(s)
211 }
212
213 pub fn emit_function(
222 &self,
223 w: &mut impl Write,
224 name: &str,
225 module_index: usize,
226 function_type_index: TypeIndex,
227 ) -> Result<()> {
228 self.for_module(module_index, |tf| {
229 tf.emit_function(w, name, function_type_index)
230 })
231 }
232
233 pub fn format_id(&self, module_index: usize, id_index: IdIndex) -> Result<String> {
239 let mut s = String::new();
240 self.emit_id(&mut s, module_index, id_index)?;
241 Ok(s)
242 }
243
244 pub fn emit_id(
250 &self,
251 w: &mut impl Write,
252 module_index: usize,
253 id_index: IdIndex,
254 ) -> Result<()> {
255 self.for_module(module_index, |tf| tf.emit_id(w, id_index))
256 }
257}
258
259impl<'a, 's> TypeFormatterForModule<'_, 'a, 's> {
260 pub fn get_type_size(&mut self, index: TypeIndex) -> u64 {
262 if let Ok(type_data) = self.parse_type_index(index) {
263 self.get_data_size(index, &type_data)
264 } else {
265 0
266 }
267 }
268 pub fn emit_function(
275 &mut self,
276 w: &mut impl Write,
277 name: &str,
278 function_type_index: TypeIndex,
279 ) -> Result<()> {
280 if function_type_index == TypeIndex(0) {
281 return self.emit_name_str(w, name);
282 }
283
284 let mut seen = BTreeSet::from([function_type_index]);
285 let mut seen = Seen::new(&mut seen);
286 match self.parse_type_index(function_type_index)? {
287 TypeData::MemberFunction(t) => {
288 if t.this_pointer_type.is_none() {
289 self.maybe_emit_static(w)?;
290 }
291 self.maybe_emit_return_type(w, Some(t.return_type), t.attributes, &mut seen)?;
292 self.emit_name_str(w, name)?;
293 self.emit_method_args(w, t, true, &mut seen)?;
294 }
295 TypeData::Procedure(t) => {
296 self.maybe_emit_return_type(w, t.return_type, t.attributes, &mut seen)?;
297 self.emit_name_str(w, name)?;
298
299 if !self.has_flags(TypeFormatterFlags::NO_ARGUMENTS) {
300 write!(w, "(")?;
301 self.emit_type_index(w, t.argument_list, &mut seen)?;
302 write!(w, ")")?;
303 }
304 }
305 _ => {
306 write!(w, "{}", name)?;
307 }
308 }
309 Ok(())
310 }
311
312 pub fn emit_id(&mut self, w: &mut impl Write, id_index: IdIndex) -> Result<()> {
316 let id_data = match self.parse_id_index(id_index) {
317 Ok(id_data) => id_data,
318 Err(Error::PdbError(pdb::Error::UnimplementedTypeKind(t))) => {
319 write!(w, "<unimplemented type kind 0x{:x}>", t)?;
320 return Ok(());
321 }
322 Err(Error::PdbError(pdb::Error::TypeNotFound(type_index))) => {
323 write!(w, "<missing type 0x{:x}>", type_index)?;
324 return Ok(());
325 }
326 Err(e) => return Err(e),
327 };
328 match id_data {
329 IdData::MemberFunction(m) => {
330 let mut seen = BTreeSet::from([m.function_type]);
331 let mut seen = Seen::new(&mut seen);
332 let t = match self.parse_type_index(m.function_type)? {
333 TypeData::MemberFunction(t) => t,
334 _ => return Err(Error::MemberFunctionIdIsNotMemberFunctionType),
335 };
336
337 if t.this_pointer_type.is_none() {
338 self.maybe_emit_static(w)?;
339 }
340 self.maybe_emit_return_type(w, Some(t.return_type), t.attributes, &mut seen)?;
341 self.emit_type_index(w, m.parent, &mut seen)?;
342 write!(w, "::")?;
343 self.emit_name_str(w, &m.name.to_string())?;
344 self.emit_method_args(w, t, true, &mut seen)?;
345 }
346 IdData::Function(f) => {
347 let mut seen = BTreeSet::from([f.function_type]);
348 let mut seen = Seen::new(&mut seen);
349 let t = match self.parse_type_index(f.function_type)? {
350 TypeData::Procedure(t) => t,
351 _ => return Err(Error::FunctionIdIsNotProcedureType),
352 };
353
354 self.maybe_emit_return_type(w, t.return_type, t.attributes, &mut seen)?;
355 if let Some(scope) = f.scope {
356 self.emit_id(w, scope)?;
357 write!(w, "::")?;
358 }
359
360 self.emit_name_str(w, &f.name.to_string())?;
361
362 if !self.has_flags(TypeFormatterFlags::NO_ARGUMENTS) {
363 write!(w, "(")?;
364 self.emit_type_index(w, t.argument_list, &mut seen)?;
365 write!(w, ")")?;
366 }
367 }
368 IdData::String(s) => {
369 let name = s.name.to_string();
370
371 if Self::is_anonymous_namespace(&name) {
372 write!(w, "`anonymous namespace'")?;
373 } else {
374 write!(w, "{}", name)?;
375 }
376 }
377 IdData::StringList(s) => {
378 let mut seen = BTreeSet::new();
379 let mut seen = Seen::new(&mut seen);
380 write!(w, "\"")?;
381 for (i, type_index) in s.substrings.iter().enumerate() {
382 if i > 0 {
383 write!(w, "\" \"")?;
384 }
385 self.emit_type_index(w, *type_index, &mut seen)?;
386 }
387 write!(w, "\"")?;
388 }
389 other => write!(w, "<unhandled id scope {:?}>::", other)?,
390 }
391 Ok(())
392 }
393
394 fn is_anonymous_namespace(name: &str) -> bool {
399 name.strip_prefix("?A0x")
400 .is_some_and(|rest| u32::from_str_radix(rest, 16).is_ok())
401 }
402
403 fn resolve_index<I>(&mut self, index: I) -> Result<I>
404 where
405 I: ItemIndex,
406 {
407 if !index.is_cross_module() {
408 return Ok(index);
409 }
410
411 let string_table = self
415 .string_table
416 .ok_or(Error::CantResolveCrossModuleRefWithoutStringTable)?;
417
418 let TypeFormatterCache {
419 module_name_map,
420 module_imports,
421 module_exports,
422 ..
423 } = self.cache;
424 let modules = self.modules;
425 let module_provider = self.module_provider;
426 let self_module_index = self.module_index;
427
428 let get_module = |module_index: usize| -> Result<&'a ModuleInfo<'s>> {
429 let module = modules
430 .get(module_index)
431 .ok_or(Error::OutOfRangeModuleIndex(module_index))?;
432 let module_info = module_provider
433 .get_module_info(module_index, module)?
434 .ok_or(Error::ModuleInfoNotFound(module_index))?;
435 Ok(module_info)
436 };
437
438 let module_name_map = module_name_map.get_or_insert_with(|| {
439 modules
440 .iter()
441 .enumerate()
442 .map(|(module_index, module)| {
443 let name = module.module_name().to_ascii_lowercase();
444 (name, module_index)
445 })
446 .collect()
447 });
448
449 let imports = module_imports
454 .entry(self_module_index)
455 .or_insert_with(|| Ok(get_module(self_module_index)?.imports()?))
456 .as_mut()
457 .map_err(|err| mem::replace(err, Error::ModuleImportsUnsuccessful))?;
458
459 let CrossModuleRef(module_ref, local_index) = imports.resolve_import(index)?;
460
461 let ref_module_name = module_ref
463 .0
464 .to_string_lossy(string_table)?
465 .to_ascii_lowercase();
466
467 let ref_module_index = *module_name_map
470 .get(&ref_module_name)
471 .ok_or(Error::ModuleNameNotFound(ref_module_name))?;
472
473 let module_exports = module_exports
474 .entry(ref_module_index)
475 .or_insert_with(|| Ok(get_module(ref_module_index)?.exports()?))
476 .as_mut()
477 .map_err(|err| mem::replace(err, Error::ModuleExportsUnsuccessful))?;
478
479 let index = module_exports
482 .resolve_import(local_index)?
483 .ok_or_else(|| Error::LocalIndexNotInExports(local_index.0.into()))?;
484
485 Ok(index)
486 }
487
488 fn parse_type_index(&mut self, index: TypeIndex) -> Result<TypeData<'a>> {
489 let index = self.resolve_index(index)?;
490 let item = self.cache.type_map.try_get(index)?;
491 Ok(item.parse()?)
492 }
493
494 fn parse_id_index(&mut self, index: IdIndex) -> Result<IdData<'a>> {
495 let index = self.resolve_index(index)?;
496 let item = self.cache.id_map.try_get(index)?;
497 Ok(item.parse()?)
498 }
499
500 fn get_class_size(&mut self, index: TypeIndex, class_type: &ClassType<'a>) -> u64 {
501 if class_type.properties.forward_reference() {
502 let name = class_type.unique_name.unwrap_or(class_type.name);
503 let size = self.cache.type_size_cache.get_size_for_forward_reference(
504 index,
505 name,
506 &mut self.cache.type_map,
507 );
508
509 size.unwrap_or(class_type.size)
512 } else {
513 class_type.size
514 }
515 }
516
517 fn get_union_size(&mut self, index: TypeIndex, union_type: &UnionType<'a>) -> u64 {
518 if union_type.properties.forward_reference() {
519 let name = union_type.unique_name.unwrap_or(union_type.name);
520 let size = self.cache.type_size_cache.get_size_for_forward_reference(
521 index,
522 name,
523 &mut self.cache.type_map,
524 );
525
526 size.unwrap_or(union_type.size)
527 } else {
528 union_type.size
529 }
530 }
531
532 fn get_data_size(&mut self, type_index: TypeIndex, type_data: &TypeData<'a>) -> u64 {
533 match type_data {
534 TypeData::Primitive(t) => {
535 if t.indirection.is_some() {
536 return self.ptr_size;
537 }
538 match t.kind {
539 PrimitiveKind::NoType | PrimitiveKind::Void => 0,
540 PrimitiveKind::Char
541 | PrimitiveKind::UChar
542 | PrimitiveKind::RChar
543 | PrimitiveKind::Char8
544 | PrimitiveKind::I8
545 | PrimitiveKind::U8
546 | PrimitiveKind::Bool8 => 1,
547 PrimitiveKind::WChar
548 | PrimitiveKind::RChar16
549 | PrimitiveKind::Short
550 | PrimitiveKind::UShort
551 | PrimitiveKind::I16
552 | PrimitiveKind::U16
553 | PrimitiveKind::F16
554 | PrimitiveKind::Bool16 => 2,
555 PrimitiveKind::RChar32
556 | PrimitiveKind::Long
557 | PrimitiveKind::ULong
558 | PrimitiveKind::I32
559 | PrimitiveKind::U32
560 | PrimitiveKind::F32
561 | PrimitiveKind::F32PP
562 | PrimitiveKind::Bool32
563 | PrimitiveKind::HRESULT => 4,
564 PrimitiveKind::I64
565 | PrimitiveKind::U64
566 | PrimitiveKind::Quad
567 | PrimitiveKind::UQuad
568 | PrimitiveKind::F64
569 | PrimitiveKind::Complex32
570 | PrimitiveKind::Bool64 => 8,
571 PrimitiveKind::I128
572 | PrimitiveKind::U128
573 | PrimitiveKind::Octa
574 | PrimitiveKind::UOcta
575 | PrimitiveKind::F128
576 | PrimitiveKind::Complex64 => 16,
577 PrimitiveKind::F48 => 6,
578 PrimitiveKind::F80 => 10,
579 PrimitiveKind::Complex80 => 20,
580 PrimitiveKind::Complex128 => 32,
581 _ => panic!("Unknown PrimitiveKind {:?} in get_data_size", t.kind),
582 }
583 }
584 TypeData::Class(t) => self.get_class_size(type_index, t),
585 TypeData::MemberFunction(_) => self.ptr_size,
586 TypeData::Procedure(_) => self.ptr_size,
587 TypeData::Pointer(t) => t.attributes.size().into(),
588 TypeData::Array(t) => (*t.dimensions.last().unwrap()).into(),
589 TypeData::Union(t) => self.get_union_size(type_index, t),
590 TypeData::Enumeration(t) => self.get_type_size(t.underlying_type),
591 TypeData::Enumerate(t) => match t.value {
592 Variant::I8(_) | Variant::U8(_) => 1,
593 Variant::I16(_) | Variant::U16(_) => 2,
594 Variant::I32(_) | Variant::U32(_) => 4,
595 Variant::I64(_) | Variant::U64(_) => 8,
596 },
597 TypeData::Modifier(t) => self.get_type_size(t.underlying_type),
598 _ => 0,
599 }
600 }
601
602 fn has_flags(&self, flags: TypeFormatterFlags) -> bool {
603 self.flags.intersects(flags)
604 }
605
606 fn maybe_emit_static(&self, w: &mut impl Write) -> Result<()> {
607 if self.has_flags(TypeFormatterFlags::NO_MEMBER_FUNCTION_STATIC) {
608 return Ok(());
609 }
610
611 w.write_str("static ")?;
612 Ok(())
613 }
614
615 fn maybe_emit_return_type(
616 &mut self,
617 w: &mut impl Write,
618 type_index: Option<TypeIndex>,
619 attrs: FunctionAttributes,
620 seen: &mut Seen,
621 ) -> Result<()> {
622 if self.has_flags(TypeFormatterFlags::NO_FUNCTION_RETURN) {
623 return Ok(());
624 }
625
626 self.emit_return_type(w, type_index, attrs, seen)?;
627 Ok(())
628 }
629
630 fn emit_name_str(&mut self, w: &mut impl Write, name: &str) -> Result<()> {
631 if name.is_empty() {
632 write!(w, "<name omitted>")?;
633 } else {
634 write!(w, "{}", name)?;
635 }
636 Ok(())
637 }
638
639 fn emit_return_type(
640 &mut self,
641 w: &mut impl Write,
642 type_index: Option<TypeIndex>,
643 attrs: FunctionAttributes,
644 seen: &mut Seen,
645 ) -> Result<()> {
646 if !attrs.is_constructor() {
647 if let Some(index) = type_index {
648 self.emit_type_index(w, index, seen)?;
649 write!(w, " ")?;
650 }
651 }
652 Ok(())
653 }
654
655 fn check_ptr_class(&mut self, ptr: TypeIndex, class: TypeIndex) -> Result<PtrToClassKind> {
658 if let TypeData::Pointer(ptr_type) = self.parse_type_index(ptr)? {
659 let underlying_type = ptr_type.underlying_type;
660 if underlying_type == class {
661 return Ok(PtrToClassKind::PtrToGivenClass { constant: false });
662 }
663 let underlying_type_data = self.parse_type_index(underlying_type)?;
664 if let TypeData::Modifier(modifier) = underlying_type_data {
665 if modifier.underlying_type == class {
666 return Ok(PtrToClassKind::PtrToGivenClass {
667 constant: modifier.constant,
668 });
669 }
670 }
671 };
672 Ok(PtrToClassKind::OtherType)
673 }
674
675 fn get_class_constness_and_extra_arguments(
677 &mut self,
678 this: TypeIndex,
679 class: TypeIndex,
680 ) -> Result<(bool, Option<TypeIndex>)> {
681 match self.check_ptr_class(this, class)? {
682 PtrToClassKind::PtrToGivenClass { constant } => {
683 Ok((constant, None))
685 }
686 PtrToClassKind::OtherType => {
687 Ok((false, Some(this)))
698 }
699 }
700 }
701
702 fn emit_method_args(
703 &mut self,
704 w: &mut impl Write,
705 method_type: MemberFunctionType,
706 allow_emit_const: bool,
707 seen: &mut Seen,
708 ) -> Result<()> {
709 if self.has_flags(TypeFormatterFlags::NO_ARGUMENTS) {
710 return Ok(());
711 }
712
713 let mut seen = seen.insert_one(method_type.argument_list)?;
714
715 let args_list = match self.parse_type_index(method_type.argument_list)? {
716 TypeData::ArgumentList(t) => t,
717 _ => {
718 return Err(Error::ArgumentTypeNotArgumentList);
719 }
720 };
721
722 let (is_const_method, extra_first_arg) = match method_type.this_pointer_type {
723 None => {
724 (false, None)
727 }
728 Some(this_type) => {
729 self.get_class_constness_and_extra_arguments(this_type, method_type.class_type)?
732 }
733 };
734
735 write!(w, "(")?;
736 if let Some(first_arg) = extra_first_arg {
737 self.emit_type_index(w, first_arg, &mut seen)?;
738 self.emit_arg_list(w, args_list, true, &mut seen)?;
739 } else {
740 self.emit_arg_list(w, args_list, false, &mut seen)?;
741 }
742 write!(w, ")")?;
743
744 if is_const_method && allow_emit_const {
745 write!(w, " const")?;
746 }
747
748 Ok(())
749 }
750
751 fn emit_attributes(
762 &mut self,
763 w: &mut impl Write,
764 attrs: Vec<PtrAttributes>,
765 allow_space_at_beginning: bool,
766 mut previous_byte_was_pointer_sigil: bool,
767 ) -> Result<()> {
768 let mut is_at_beginning = true;
769 for attr in attrs.iter().rev() {
770 if attr.is_pointee_const {
771 if !is_at_beginning || allow_space_at_beginning {
772 write!(w, " ")?;
773 }
774 write!(w, "const")?;
775 is_at_beginning = false;
776 previous_byte_was_pointer_sigil = false;
777 }
778
779 if self.has_flags(TypeFormatterFlags::SPACE_BEFORE_POINTER)
780 && !previous_byte_was_pointer_sigil
781 && (!is_at_beginning || allow_space_at_beginning)
782 {
783 write!(w, " ")?;
784 }
785 is_at_beginning = false;
786 match attr.mode {
787 PointerMode::Pointer => write!(w, "*")?,
788 PointerMode::LValueReference => write!(w, "&")?,
789 PointerMode::Member => write!(w, "::*")?,
790 PointerMode::MemberFunction => write!(w, "::*")?,
791 PointerMode::RValueReference => write!(w, "&&")?,
792 }
793 previous_byte_was_pointer_sigil = true;
794 if attr.is_pointer_const {
795 write!(w, " const")?;
796 previous_byte_was_pointer_sigil = false;
797 }
798 }
799 Ok(())
800 }
801
802 fn emit_member_ptr(
803 &mut self,
804 w: &mut impl Write,
805 fun: MemberFunctionType,
806 attributes: Vec<PtrAttributes>,
807 seen: &mut Seen,
808 ) -> Result<()> {
809 self.emit_return_type(w, Some(fun.return_type), fun.attributes, seen)?;
810 write!(w, "(")?;
811 self.emit_type_index(w, fun.class_type, seen)?;
812 self.emit_attributes(w, attributes, false, false)?;
813 write!(w, ")")?;
814 self.emit_method_args(w, fun, false, seen)?;
815 Ok(())
816 }
817
818 fn emit_proc_ptr(
819 &mut self,
820 w: &mut impl Write,
821 fun: ProcedureType,
822 attributes: Vec<PtrAttributes>,
823 seen: &mut Seen,
824 ) -> Result<()> {
825 self.emit_return_type(w, fun.return_type, fun.attributes, seen)?;
826
827 write!(w, "(")?;
828 self.emit_attributes(w, attributes, false, false)?;
829 write!(w, ")")?;
830 write!(w, "(")?;
831 self.emit_type_index(w, fun.argument_list, seen)?;
832 write!(w, ")")?;
833 Ok(())
834 }
835
836 fn emit_other_ptr(
837 &mut self,
838 w: &mut impl Write,
839 type_data: TypeData,
840 attributes: Vec<PtrAttributes>,
841 seen: &mut Seen,
842 ) -> Result<()> {
843 let mut buf = String::new();
844 self.emit_type(&mut buf, type_data, seen)?;
845 let previous_byte_was_pointer_sigil = buf
846 .as_bytes()
847 .last()
848 .map(|&b| b == b'*' || b == b'&')
849 .unwrap_or(false);
850 w.write_str(&buf)?;
851 self.emit_attributes(w, attributes, true, previous_byte_was_pointer_sigil)?;
852
853 Ok(())
854 }
855
856 fn emit_ptr_helper(
857 &mut self,
858 w: &mut impl Write,
859 attributes: Vec<PtrAttributes>,
860 type_data: TypeData,
861 seen: &mut Seen,
862 ) -> Result<()> {
863 match type_data {
864 TypeData::MemberFunction(t) => self.emit_member_ptr(w, t, attributes, seen)?,
865 TypeData::Procedure(t) => self.emit_proc_ptr(w, t, attributes, seen)?,
866 _ => self.emit_other_ptr(w, type_data, attributes, seen)?,
867 };
868 Ok(())
869 }
870
871 fn emit_ptr(
872 &mut self,
873 w: &mut impl Write,
874 ptr: PointerType,
875 is_const: bool,
876 seen: &mut Seen,
877 ) -> Result<()> {
878 let mut attributes = vec![PtrAttributes {
879 is_pointer_const: ptr.attributes.is_const() || is_const,
880 is_pointee_const: false,
881 mode: ptr.attributes.pointer_mode(),
882 }];
883 let mut ptr = ptr;
884 let mut seen = seen.new_level();
885 loop {
886 seen.insert(ptr.underlying_type)?;
887
888 let type_data = self.parse_type_index(ptr.underlying_type)?;
889 match type_data {
890 TypeData::Pointer(t) => {
891 attributes.push(PtrAttributes {
892 is_pointer_const: t.attributes.is_const(),
893 is_pointee_const: false,
894 mode: t.attributes.pointer_mode(),
895 });
896 ptr = t;
897 }
898 TypeData::Modifier(t) => {
899 attributes.last_mut().unwrap().is_pointee_const = t.constant;
901
902 seen.insert(t.underlying_type)?;
903
904 let underlying_type_data = self.parse_type_index(t.underlying_type)?;
905 if let TypeData::Pointer(t) = underlying_type_data {
906 attributes.push(PtrAttributes {
907 is_pointer_const: t.attributes.is_const(),
908 is_pointee_const: false,
909 mode: t.attributes.pointer_mode(),
910 });
911 ptr = t;
912 } else {
913 self.emit_ptr_helper(w, attributes, underlying_type_data, &mut seen)?;
914 return Ok(());
915 }
916 }
917 _ => {
918 self.emit_ptr_helper(w, attributes, type_data, &mut seen)?;
919 return Ok(());
920 }
921 }
922 }
923 }
924
925 fn get_array_info(&mut self, array: ArrayType) -> Result<(Vec<u64>, TypeIndex, TypeData<'a>)> {
928 let mut base = array;
932 let mut dims = Vec::new();
933 dims.push(base.dimensions[0].into());
934
935 loop {
950 let type_index = base.element_type;
951 let type_data = self.parse_type_index(type_index)?;
952 match type_data {
953 TypeData::Array(a) => {
954 dims.push(a.dimensions[0].into());
955 base = a;
956 }
957 _ => {
958 return Ok((dims, type_index, type_data));
959 }
960 }
961 }
962 }
963
964 fn emit_array(&mut self, w: &mut impl Write, array: ArrayType, seen: &mut Seen) -> Result<()> {
965 let (dimensions_as_bytes, base_index, base) = self.get_array_info(array)?;
966 let base_size = self.get_data_size(base_index, &base);
967 self.emit_type(w, base, seen)?;
968
969 let mut iter = dimensions_as_bytes.into_iter().peekable();
970 while let Some(current_level_byte_size) = iter.next() {
971 let next_level_byte_size = *iter.peek().unwrap_or(&base_size);
972 if let Some(element_count) = current_level_byte_size.checked_div(next_level_byte_size) {
973 write!(w, "[{}]", element_count)?;
974 } else {
975 write!(w, "[]")?;
978 };
979 }
980
981 Ok(())
982 }
983
984 fn emit_modifier(
985 &mut self,
986 w: &mut impl Write,
987 modifier: ModifierType,
988 seen: &mut Seen,
989 ) -> Result<()> {
990 let mut seen = seen.insert_one(modifier.underlying_type)?;
991 let type_data = self.parse_type_index(modifier.underlying_type)?;
992 match type_data {
993 TypeData::Pointer(ptr) => self.emit_ptr(w, ptr, modifier.constant, &mut seen),
994 TypeData::Primitive(prim) => self.emit_primitive(w, prim, modifier.constant),
995 _ => {
996 if modifier.constant {
997 write!(w, "const ")?
998 }
999 self.emit_type(w, type_data, &mut seen)
1000 }
1001 }
1002 }
1003
1004 fn emit_class(&mut self, w: &mut impl Write, class: ClassType) -> Result<()> {
1005 if self.has_flags(TypeFormatterFlags::NAME_ONLY) {
1006 write!(w, "{}", class.name)?;
1007 } else {
1008 let name = match class.kind {
1009 ClassKind::Class => "class",
1010 ClassKind::Interface => "interface",
1011 ClassKind::Struct => "struct",
1012 };
1013 write!(w, "{} {}", name, class.name)?
1014 }
1015 Ok(())
1016 }
1017
1018 fn emit_arg_list(
1019 &mut self,
1020 w: &mut impl Write,
1021 list: ArgumentList,
1022 comma_before_first: bool,
1023 seen: &mut Seen,
1024 ) -> Result<()> {
1025 if let Some((first, args)) = list.arguments.split_first() {
1026 if comma_before_first {
1027 write!(w, ",")?;
1028 if self.has_flags(TypeFormatterFlags::SPACE_AFTER_COMMA) {
1029 write!(w, " ")?;
1030 }
1031 }
1032 self.emit_type_index(w, *first, seen)?;
1033 for index in args.iter() {
1034 write!(w, ",")?;
1035 if self.has_flags(TypeFormatterFlags::SPACE_AFTER_COMMA) {
1036 write!(w, " ")?;
1037 }
1038 self.emit_type_index(w, *index, seen)?;
1039 }
1040 }
1041 Ok(())
1042 }
1043
1044 fn emit_primitive(
1045 &mut self,
1046 w: &mut impl Write,
1047 prim: PrimitiveType,
1048 is_const: bool,
1049 ) -> Result<()> {
1050 let name = match prim.kind {
1052 PrimitiveKind::NoType => "<NoType>",
1053 PrimitiveKind::Void => "void",
1054 PrimitiveKind::Char => "signed char",
1055 PrimitiveKind::UChar => "unsigned char",
1056 PrimitiveKind::RChar => "char",
1057 PrimitiveKind::WChar => "wchar_t",
1058 PrimitiveKind::Char8 => "char8_t",
1059 PrimitiveKind::RChar16 => "char16_t",
1060 PrimitiveKind::RChar32 => "char32_t",
1061 PrimitiveKind::I8 => "int8_t",
1062 PrimitiveKind::U8 => "uint8_t",
1063 PrimitiveKind::Short => "short",
1064 PrimitiveKind::UShort => "unsigned short",
1065 PrimitiveKind::I16 => "int16_t",
1066 PrimitiveKind::U16 => "uint16_t",
1067 PrimitiveKind::Long => "long",
1068 PrimitiveKind::ULong => "unsigned long",
1069 PrimitiveKind::I32 => "int",
1070 PrimitiveKind::U32 => "unsigned int",
1071 PrimitiveKind::Quad => "long long",
1072 PrimitiveKind::UQuad => "unsigned long long",
1073 PrimitiveKind::I64 => "int64_t",
1074 PrimitiveKind::U64 => "uint64_t",
1075 PrimitiveKind::I128 | PrimitiveKind::Octa => "int128_t",
1076 PrimitiveKind::U128 | PrimitiveKind::UOcta => "uint128_t",
1077 PrimitiveKind::F16 => "float16_t",
1078 PrimitiveKind::F32 => "float",
1079 PrimitiveKind::F32PP => "float",
1080 PrimitiveKind::F48 => "float48_t",
1081 PrimitiveKind::F64 => "double",
1082 PrimitiveKind::F80 => "long double",
1083 PrimitiveKind::F128 => "long double",
1084 PrimitiveKind::Complex32 => "complex<float>",
1085 PrimitiveKind::Complex64 => "complex<double>",
1086 PrimitiveKind::Complex80 => "complex<long double>",
1087 PrimitiveKind::Complex128 => "complex<long double>",
1088 PrimitiveKind::Bool8 => "bool",
1089 PrimitiveKind::Bool16 => "bool16_t",
1090 PrimitiveKind::Bool32 => "bool32_t",
1091 PrimitiveKind::Bool64 => "bool64_t",
1092 PrimitiveKind::HRESULT => "HRESULT",
1093 _ => panic!("Unknown PrimitiveKind {:?} in emit_primitive", prim.kind),
1094 };
1095
1096 if prim.indirection.is_some() {
1097 if self.has_flags(TypeFormatterFlags::SPACE_BEFORE_POINTER) {
1098 if is_const {
1099 write!(w, "{} const *", name)?
1100 } else {
1101 write!(w, "{} *", name)?
1102 }
1103 } else if is_const {
1104 write!(w, "{} const*", name)?
1105 } else {
1106 write!(w, "{}*", name)?
1107 }
1108 } else if is_const {
1109 write!(w, "const {}", name)?
1110 } else {
1111 write!(w, "{}", name)?
1112 }
1113 Ok(())
1114 }
1115
1116 fn emit_named(&mut self, w: &mut impl Write, base: &str, name: RawString) -> Result<()> {
1117 if self.has_flags(TypeFormatterFlags::NAME_ONLY) {
1118 write!(w, "{}", name)?
1119 } else {
1120 write!(w, "{} {}", base, name)?
1121 }
1122
1123 Ok(())
1124 }
1125
1126 fn emit_type_index(
1127 &mut self,
1128 w: &mut impl Write,
1129 index: TypeIndex,
1130 seen: &mut Seen,
1131 ) -> Result<()> {
1132 match self.parse_type_index(index) {
1133 Ok(type_data) => self.emit_type(w, type_data, &mut seen.insert_one(index)?),
1134 Err(Error::PdbError(pdb::Error::UnimplementedTypeKind(t))) => {
1135 write!(w, "<unimplemented type kind 0x{:x}>", t)?;
1136 Ok(())
1137 }
1138 Err(Error::PdbError(pdb::Error::TypeNotFound(type_index))) => {
1139 write!(w, "<missing type 0x{:x}>", type_index)?;
1140 Ok(())
1141 }
1142 Err(e) => Err(e),
1143 }
1144 }
1145
1146 fn emit_type(
1147 &mut self,
1148 w: &mut impl Write,
1149 type_data: TypeData,
1150 seen: &mut Seen,
1151 ) -> Result<()> {
1152 match self.emit_type_inner(w, type_data, seen) {
1153 Ok(()) => Ok(()),
1154 Err(Error::PdbError(pdb::Error::TypeNotFound(type_index))) => {
1155 write!(w, "<missing type 0x{:x}>", type_index)?;
1156 Ok(())
1157 }
1158 Err(e) => Err(e),
1159 }
1160 }
1161
1162 fn emit_type_inner(
1163 &mut self,
1164 w: &mut impl Write,
1165 type_data: TypeData,
1166 seen: &mut Seen,
1167 ) -> Result<()> {
1168 match type_data {
1169 TypeData::Primitive(t) => self.emit_primitive(w, t, false)?,
1170 TypeData::Class(t) => self.emit_class(w, t)?,
1171 TypeData::MemberFunction(t) => {
1172 self.maybe_emit_return_type(w, Some(t.return_type), t.attributes, seen)?;
1173 write!(w, "()")?;
1174 self.emit_method_args(w, t, false, seen)?;
1175 }
1176 TypeData::Procedure(t) => {
1177 self.maybe_emit_return_type(w, t.return_type, t.attributes, seen)?;
1178 write!(w, "()(")?;
1179 self.emit_type_index(w, t.argument_list, seen)?;
1180 write!(w, "")?;
1181 }
1182 TypeData::ArgumentList(t) => self.emit_arg_list(w, t, false, seen)?,
1183 TypeData::Pointer(t) => self.emit_ptr(w, t, false, seen)?,
1184 TypeData::Array(t) => self.emit_array(w, t, seen)?,
1185 TypeData::Union(t) => self.emit_named(w, "union", t.name)?,
1186 TypeData::Enumeration(t) => self.emit_named(w, "enum", t.name)?,
1187 TypeData::Enumerate(t) => self.emit_named(w, "enum class", t.name)?,
1188 TypeData::Modifier(t) => self.emit_modifier(w, t, seen)?,
1189 _ => write!(w, "unhandled type /* {:?} */", type_data)?,
1190 }
1191
1192 Ok(())
1193 }
1194}
1195
1196#[derive(Eq, PartialEq)]
1197enum PtrToClassKind {
1198 PtrToGivenClass {
1199 constant: bool,
1201 },
1202 OtherType,
1203}
1204
1205#[derive(Debug)]
1206struct PtrAttributes {
1207 is_pointer_const: bool,
1208 is_pointee_const: bool,
1209 mode: PointerMode,
1210}
1211
1212struct ItemMap<'a, I: ItemIndex> {
1213 iter: ItemIter<'a, I>,
1214 finder: ItemFinder<'a, I>,
1215}
1216
1217impl<'a, I> ItemMap<'a, I>
1218where
1219 I: ItemIndex,
1220{
1221 pub fn try_get(&mut self, index: I) -> std::result::Result<Item<'a, I>, pdb::Error> {
1222 if index <= self.finder.max_index() {
1223 return self.finder.find(index);
1224 }
1225
1226 while let Some(item) = self.iter.next()? {
1227 self.finder.update(&self.iter);
1228 match item.index().partial_cmp(&index) {
1229 Some(Ordering::Equal) => return Ok(item),
1230 Some(Ordering::Greater) => break,
1231 _ => continue,
1232 }
1233 }
1234
1235 Err(pdb::Error::TypeNotFound(index.into()))
1236 }
1237}
1238
1239type IdMap<'a> = ItemMap<'a, IdIndex>;
1240type TypeMap<'a> = ItemMap<'a, TypeIndex>;
1241
1242struct TypeSizeCache<'a> {
1243 forward_ref_sizes: HashMap<RawString<'a>, u64>,
1257
1258 cached_ranges: RangeSet2<u32>,
1259}
1260
1261impl<'a> TypeSizeCache<'a> {
1262 pub fn get_size_for_forward_reference(
1263 &mut self,
1264 index: TypeIndex,
1265 name: RawString<'a>,
1266 type_map: &mut TypeMap<'a>,
1267 ) -> Option<u64> {
1268 if let Some(size) = self.forward_ref_sizes.get(&name) {
1269 return Some(*size);
1270 }
1271
1272 let start_index = index.0;
1273 let candidate_range = RangeSet::from((start_index + 1)..);
1274 let uncached_ranges = &candidate_range - &self.cached_ranges;
1275 for uncached_range in uncached_ranges.iter() {
1276 let (range_start, range_end) = match uncached_range {
1277 RangeSetRange::Range(r) => (*r.start, Some(*r.end)),
1278 RangeSetRange::RangeFrom(r) => (*r.start, None),
1279 };
1280 for index in range_start.. {
1281 if let Some(range_end) = range_end {
1282 if index >= range_end {
1283 break;
1284 }
1285 }
1286 if let Ok(item) = type_map.try_get(TypeIndex(index)) {
1287 let s = self.update_forward_ref_size_map(&item);
1288 if let Some((found_name, found_size)) = s {
1289 if found_name == name {
1290 self.cached_ranges |= RangeSet::from(start_index..(index + 1));
1291 return Some(found_size);
1292 }
1293 }
1294 } else {
1295 break;
1296 }
1297 }
1298 }
1299 self.cached_ranges |= RangeSet::from(start_index..);
1300
1301 None
1302 }
1303
1304 pub fn update_forward_ref_size_map(
1305 &mut self,
1306 item: &Item<'a, TypeIndex>,
1307 ) -> Option<(RawString<'a>, u64)> {
1308 if let Ok(type_data) = item.parse() {
1309 match type_data {
1310 TypeData::Class(t) => {
1311 if !t.properties.forward_reference() {
1312 let name = t.unique_name.unwrap_or(t.name);
1313 self.forward_ref_sizes.insert(name, t.size);
1314 return Some((name, t.size));
1315 }
1316 }
1317 TypeData::Union(t) if !t.properties.forward_reference() => {
1318 let name = t.unique_name.unwrap_or(t.name);
1319 self.forward_ref_sizes.insert(name, t.size);
1320 return Some((name, t.size));
1321 }
1322 _ => {}
1323 }
1324 }
1325 None
1326 }
1327}
1328
1329#[derive(Debug, Clone)]
1330pub(crate) struct AlreadySeenError(pub(crate) TypeIndex);
1331
1332#[derive(Debug, Clone)]
1334enum Inserted {
1335 Nothing,
1337 Single(TypeIndex),
1339 Multiple(BTreeSet<TypeIndex>),
1341}
1342
1343#[derive(Debug)]
1354struct Seen<'a> {
1355 set: &'a mut BTreeSet<TypeIndex>,
1356 inserted: Inserted,
1357}
1358
1359impl<'a> Seen<'a> {
1360 fn new(set: &'a mut BTreeSet<TypeIndex>) -> Self {
1363 Self {
1364 set,
1365 inserted: Inserted::Nothing,
1366 }
1367 }
1368
1369 fn new_level<'b>(&'b mut self) -> Seen<'b> {
1375 Seen {
1376 set: self.set,
1377 inserted: Inserted::Nothing,
1378 }
1379 }
1380
1381 fn insert(&mut self, idx: TypeIndex) -> std::result::Result<(), AlreadySeenError> {
1386 if !self.set.insert(idx) {
1387 return Err(AlreadySeenError(idx));
1388 }
1389
1390 match &mut self.inserted {
1391 Inserted::Nothing => self.inserted = Inserted::Single(idx),
1392 Inserted::Single(prev_idx) => {
1393 self.inserted = Inserted::Multiple(BTreeSet::from([*prev_idx, idx]))
1394 }
1395 Inserted::Multiple(ref mut multiple) => {
1396 multiple.insert(idx);
1397 }
1398 }
1399
1400 Ok(())
1401 }
1402
1403 fn insert_one<'b>(
1409 &'b mut self,
1410 idx: TypeIndex,
1411 ) -> std::result::Result<Seen<'b>, AlreadySeenError> {
1412 let mut out = self.new_level();
1413 out.insert(idx)?;
1414 Ok(out)
1415 }
1416}
1417
1418impl<'a> Drop for Seen<'a> {
1419 fn drop(&mut self) {
1420 match std::mem::replace(&mut self.inserted, Inserted::Nothing) {
1421 Inserted::Nothing => {}
1422 Inserted::Single(idx) => {
1423 self.set.remove(&idx);
1424 }
1425 Inserted::Multiple(idxs) => {
1426 for idx in idxs {
1427 self.set.remove(&idx);
1428 }
1429 }
1430 }
1431 }
1432}
1433
1434#[cfg(test)]
1435mod tests {
1436 use std::collections::BTreeSet;
1437
1438 use pdb::TypeIndex;
1439
1440 use crate::type_formatter::Seen;
1441
1442 macro_rules! assert_contents {
1443 ($seen:expr, $($el:expr),+) => {
1444 assert_eq!(
1445 $seen.set,
1446 &mut BTreeSet::from([$(TypeIndex($el)),+])
1447 );
1448 };
1449 }
1450
1451 #[test]
1452 fn test_seen() {
1453 let mut set = BTreeSet::from([TypeIndex(0)]);
1454 let mut level_0 = Seen::new(&mut set);
1455
1456 assert_contents!(level_0, 0);
1457
1458 let mut level_1 = level_0.insert_one(TypeIndex(1)).unwrap();
1459 level_1.insert(TypeIndex(0)).unwrap_err();
1460 level_1.insert(TypeIndex(2)).unwrap();
1461
1462 assert_contents!(level_1, 0, 1, 2);
1463
1464 let mut level_2 = level_1.insert_one(TypeIndex(3)).unwrap();
1465
1466 assert_contents!(level_2, 0, 1, 2, 3);
1467
1468 let mut level_3 = level_2.new_level();
1469 level_3.insert(TypeIndex(4)).unwrap();
1470 level_3.insert(TypeIndex(5)).unwrap();
1471
1472 assert_contents!(level_3, 0, 1, 2, 3, 4, 5);
1473
1474 std::mem::drop(level_3);
1475 assert_contents!(level_2, 0, 1, 2, 3);
1476
1477 std::mem::drop(level_2);
1478 assert_contents!(level_1, 0, 1, 2);
1479
1480 std::mem::drop(level_1);
1481 assert_contents!(level_0, 0);
1482
1483 std::mem::drop(level_0);
1484
1485 assert_eq!(set, BTreeSet::from([TypeIndex(0)]));
1486 }
1487}