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::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 match self.parse_type_index(function_type_index)? {
285 TypeData::MemberFunction(t) => {
286 if t.this_pointer_type.is_none() {
287 self.maybe_emit_static(w)?;
288 }
289 self.maybe_emit_return_type(w, Some(t.return_type), t.attributes)?;
290 self.emit_name_str(w, name)?;
291 self.emit_method_args(w, t, true)?;
292 }
293 TypeData::Procedure(t) => {
294 self.maybe_emit_return_type(w, t.return_type, t.attributes)?;
295 self.emit_name_str(w, name)?;
296
297 if !self.has_flags(TypeFormatterFlags::NO_ARGUMENTS) {
298 write!(w, "(")?;
299 self.emit_type_index(w, t.argument_list)?;
300 write!(w, ")")?;
301 }
302 }
303 _ => {
304 write!(w, "{}", name)?;
305 }
306 }
307 Ok(())
308 }
309
310 pub fn emit_id(&mut self, w: &mut impl Write, id_index: IdIndex) -> Result<()> {
314 let id_data = match self.parse_id_index(id_index) {
315 Ok(id_data) => id_data,
316 Err(Error::PdbError(pdb::Error::UnimplementedTypeKind(t))) => {
317 write!(w, "<unimplemented type kind 0x{:x}>", t)?;
318 return Ok(());
319 }
320 Err(Error::PdbError(pdb::Error::TypeNotFound(type_index))) => {
321 write!(w, "<missing type 0x{:x}>", type_index)?;
322 return Ok(());
323 }
324 Err(e) => return Err(e),
325 };
326 match id_data {
327 IdData::MemberFunction(m) => {
328 let t = match self.parse_type_index(m.function_type)? {
329 TypeData::MemberFunction(t) => t,
330 _ => return Err(Error::MemberFunctionIdIsNotMemberFunctionType),
331 };
332
333 if t.this_pointer_type.is_none() {
334 self.maybe_emit_static(w)?;
335 }
336 self.maybe_emit_return_type(w, Some(t.return_type), t.attributes)?;
337 self.emit_type_index(w, m.parent)?;
338 write!(w, "::")?;
339 self.emit_name_str(w, &m.name.to_string())?;
340 self.emit_method_args(w, t, true)?;
341 }
342 IdData::Function(f) => {
343 let t = match self.parse_type_index(f.function_type)? {
344 TypeData::Procedure(t) => t,
345 _ => return Err(Error::FunctionIdIsNotProcedureType),
346 };
347
348 self.maybe_emit_return_type(w, t.return_type, t.attributes)?;
349 if let Some(scope) = f.scope {
350 self.emit_id(w, scope)?;
351 write!(w, "::")?;
352 }
353
354 self.emit_name_str(w, &f.name.to_string())?;
355
356 if !self.has_flags(TypeFormatterFlags::NO_ARGUMENTS) {
357 write!(w, "(")?;
358 self.emit_type_index(w, t.argument_list)?;
359 write!(w, ")")?;
360 }
361 }
362 IdData::String(s) => {
363 let name = s.name.to_string();
364
365 if Self::is_anonymous_namespace(&name) {
366 write!(w, "`anonymous namespace'")?;
367 } else {
368 write!(w, "{}", name)?;
369 }
370 }
371 IdData::StringList(s) => {
372 write!(w, "\"")?;
373 for (i, type_index) in s.substrings.iter().enumerate() {
374 if i > 0 {
375 write!(w, "\" \"")?;
376 }
377 self.emit_type_index(w, *type_index)?;
378 }
379 write!(w, "\"")?;
380 }
381 other => write!(w, "<unhandled id scope {:?}>::", other)?,
382 }
383 Ok(())
384 }
385
386 fn is_anonymous_namespace(name: &str) -> bool {
391 name.strip_prefix("?A0x")
392 .is_some_and(|rest| u32::from_str_radix(rest, 16).is_ok())
393 }
394
395 fn resolve_index<I>(&mut self, index: I) -> Result<I>
396 where
397 I: ItemIndex,
398 {
399 if !index.is_cross_module() {
400 return Ok(index);
401 }
402
403 let string_table = self
407 .string_table
408 .ok_or(Error::CantResolveCrossModuleRefWithoutStringTable)?;
409
410 let TypeFormatterCache {
411 module_name_map,
412 module_imports,
413 module_exports,
414 ..
415 } = self.cache;
416 let modules = self.modules;
417 let module_provider = self.module_provider;
418 let self_module_index = self.module_index;
419
420 let get_module = |module_index: usize| -> Result<&'a ModuleInfo<'s>> {
421 let module = modules
422 .get(module_index)
423 .ok_or(Error::OutOfRangeModuleIndex(module_index))?;
424 let module_info = module_provider
425 .get_module_info(module_index, module)?
426 .ok_or(Error::ModuleInfoNotFound(module_index))?;
427 Ok(module_info)
428 };
429
430 let module_name_map = module_name_map.get_or_insert_with(|| {
431 modules
432 .iter()
433 .enumerate()
434 .map(|(module_index, module)| {
435 let name = module.module_name().to_ascii_lowercase();
436 (name, module_index)
437 })
438 .collect()
439 });
440
441 let imports = module_imports
446 .entry(self_module_index)
447 .or_insert_with(|| Ok(get_module(self_module_index)?.imports()?))
448 .as_mut()
449 .map_err(|err| mem::replace(err, Error::ModuleImportsUnsuccessful))?;
450
451 let CrossModuleRef(module_ref, local_index) = imports.resolve_import(index)?;
452
453 let ref_module_name = module_ref
455 .0
456 .to_string_lossy(string_table)?
457 .to_ascii_lowercase();
458
459 let ref_module_index = *module_name_map
462 .get(&ref_module_name)
463 .ok_or(Error::ModuleNameNotFound(ref_module_name))?;
464
465 let module_exports = module_exports
466 .entry(ref_module_index)
467 .or_insert_with(|| Ok(get_module(ref_module_index)?.exports()?))
468 .as_mut()
469 .map_err(|err| mem::replace(err, Error::ModuleExportsUnsuccessful))?;
470
471 let index = module_exports
474 .resolve_import(local_index)?
475 .ok_or_else(|| Error::LocalIndexNotInExports(local_index.0.into()))?;
476
477 Ok(index)
478 }
479
480 fn parse_type_index(&mut self, index: TypeIndex) -> Result<TypeData<'a>> {
481 let index = self.resolve_index(index)?;
482 let item = self.cache.type_map.try_get(index)?;
483 Ok(item.parse()?)
484 }
485
486 fn parse_id_index(&mut self, index: IdIndex) -> Result<IdData<'a>> {
487 let index = self.resolve_index(index)?;
488 let item = self.cache.id_map.try_get(index)?;
489 Ok(item.parse()?)
490 }
491
492 fn get_class_size(&mut self, index: TypeIndex, class_type: &ClassType<'a>) -> u64 {
493 if class_type.properties.forward_reference() {
494 let name = class_type.unique_name.unwrap_or(class_type.name);
495 let size = self.cache.type_size_cache.get_size_for_forward_reference(
496 index,
497 name,
498 &mut self.cache.type_map,
499 );
500
501 size.unwrap_or(class_type.size)
504 } else {
505 class_type.size
506 }
507 }
508
509 fn get_union_size(&mut self, index: TypeIndex, union_type: &UnionType<'a>) -> u64 {
510 if union_type.properties.forward_reference() {
511 let name = union_type.unique_name.unwrap_or(union_type.name);
512 let size = self.cache.type_size_cache.get_size_for_forward_reference(
513 index,
514 name,
515 &mut self.cache.type_map,
516 );
517
518 size.unwrap_or(union_type.size)
519 } else {
520 union_type.size
521 }
522 }
523
524 fn get_data_size(&mut self, type_index: TypeIndex, type_data: &TypeData<'a>) -> u64 {
525 match type_data {
526 TypeData::Primitive(t) => {
527 if t.indirection.is_some() {
528 return self.ptr_size;
529 }
530 match t.kind {
531 PrimitiveKind::NoType | PrimitiveKind::Void => 0,
532 PrimitiveKind::Char
533 | PrimitiveKind::UChar
534 | PrimitiveKind::RChar
535 | PrimitiveKind::Char8
536 | PrimitiveKind::I8
537 | PrimitiveKind::U8
538 | PrimitiveKind::Bool8 => 1,
539 PrimitiveKind::WChar
540 | PrimitiveKind::RChar16
541 | PrimitiveKind::Short
542 | PrimitiveKind::UShort
543 | PrimitiveKind::I16
544 | PrimitiveKind::U16
545 | PrimitiveKind::F16
546 | PrimitiveKind::Bool16 => 2,
547 PrimitiveKind::RChar32
548 | PrimitiveKind::Long
549 | PrimitiveKind::ULong
550 | PrimitiveKind::I32
551 | PrimitiveKind::U32
552 | PrimitiveKind::F32
553 | PrimitiveKind::F32PP
554 | PrimitiveKind::Bool32
555 | PrimitiveKind::HRESULT => 4,
556 PrimitiveKind::I64
557 | PrimitiveKind::U64
558 | PrimitiveKind::Quad
559 | PrimitiveKind::UQuad
560 | PrimitiveKind::F64
561 | PrimitiveKind::Complex32
562 | PrimitiveKind::Bool64 => 8,
563 PrimitiveKind::I128
564 | PrimitiveKind::U128
565 | PrimitiveKind::Octa
566 | PrimitiveKind::UOcta
567 | PrimitiveKind::F128
568 | PrimitiveKind::Complex64 => 16,
569 PrimitiveKind::F48 => 6,
570 PrimitiveKind::F80 => 10,
571 PrimitiveKind::Complex80 => 20,
572 PrimitiveKind::Complex128 => 32,
573 _ => panic!("Unknown PrimitiveKind {:?} in get_data_size", t.kind),
574 }
575 }
576 TypeData::Class(t) => self.get_class_size(type_index, t),
577 TypeData::MemberFunction(_) => self.ptr_size,
578 TypeData::Procedure(_) => self.ptr_size,
579 TypeData::Pointer(t) => t.attributes.size().into(),
580 TypeData::Array(t) => (*t.dimensions.last().unwrap()).into(),
581 TypeData::Union(t) => self.get_union_size(type_index, t),
582 TypeData::Enumeration(t) => self.get_type_size(t.underlying_type),
583 TypeData::Enumerate(t) => match t.value {
584 Variant::I8(_) | Variant::U8(_) => 1,
585 Variant::I16(_) | Variant::U16(_) => 2,
586 Variant::I32(_) | Variant::U32(_) => 4,
587 Variant::I64(_) | Variant::U64(_) => 8,
588 },
589 TypeData::Modifier(t) => self.get_type_size(t.underlying_type),
590 _ => 0,
591 }
592 }
593
594 fn has_flags(&self, flags: TypeFormatterFlags) -> bool {
595 self.flags.intersects(flags)
596 }
597
598 fn maybe_emit_static(&self, w: &mut impl Write) -> Result<()> {
599 if self.has_flags(TypeFormatterFlags::NO_MEMBER_FUNCTION_STATIC) {
600 return Ok(());
601 }
602
603 w.write_str("static ")?;
604 Ok(())
605 }
606
607 fn maybe_emit_return_type(
608 &mut self,
609 w: &mut impl Write,
610 type_index: Option<TypeIndex>,
611 attrs: FunctionAttributes,
612 ) -> Result<()> {
613 if self.has_flags(TypeFormatterFlags::NO_FUNCTION_RETURN) {
614 return Ok(());
615 }
616
617 self.emit_return_type(w, type_index, attrs)?;
618 Ok(())
619 }
620
621 fn emit_name_str(&mut self, w: &mut impl Write, name: &str) -> Result<()> {
622 if name.is_empty() {
623 write!(w, "<name omitted>")?;
624 } else {
625 write!(w, "{}", name)?;
626 }
627 Ok(())
628 }
629
630 fn emit_return_type(
631 &mut self,
632 w: &mut impl Write,
633 type_index: Option<TypeIndex>,
634 attrs: FunctionAttributes,
635 ) -> Result<()> {
636 if !attrs.is_constructor() {
637 if let Some(index) = type_index {
638 self.emit_type_index(w, index)?;
639 write!(w, " ")?;
640 }
641 }
642 Ok(())
643 }
644
645 fn check_ptr_class(&mut self, ptr: TypeIndex, class: TypeIndex) -> Result<PtrToClassKind> {
648 if let TypeData::Pointer(ptr_type) = self.parse_type_index(ptr)? {
649 let underlying_type = ptr_type.underlying_type;
650 if underlying_type == class {
651 return Ok(PtrToClassKind::PtrToGivenClass { constant: false });
652 }
653 let underlying_type_data = self.parse_type_index(underlying_type)?;
654 if let TypeData::Modifier(modifier) = underlying_type_data {
655 if modifier.underlying_type == class {
656 return Ok(PtrToClassKind::PtrToGivenClass {
657 constant: modifier.constant,
658 });
659 }
660 }
661 };
662 Ok(PtrToClassKind::OtherType)
663 }
664
665 fn get_class_constness_and_extra_arguments(
667 &mut self,
668 this: TypeIndex,
669 class: TypeIndex,
670 ) -> Result<(bool, Option<TypeIndex>)> {
671 match self.check_ptr_class(this, class)? {
672 PtrToClassKind::PtrToGivenClass { constant } => {
673 Ok((constant, None))
675 }
676 PtrToClassKind::OtherType => {
677 Ok((false, Some(this)))
688 }
689 }
690 }
691
692 fn emit_method_args(
693 &mut self,
694 w: &mut impl Write,
695 method_type: MemberFunctionType,
696 allow_emit_const: bool,
697 ) -> Result<()> {
698 if self.has_flags(TypeFormatterFlags::NO_ARGUMENTS) {
699 return Ok(());
700 }
701
702 let args_list = match self.parse_type_index(method_type.argument_list)? {
703 TypeData::ArgumentList(t) => t,
704 _ => {
705 return Err(Error::ArgumentTypeNotArgumentList);
706 }
707 };
708
709 let (is_const_method, extra_first_arg) = match method_type.this_pointer_type {
710 None => {
711 (false, None)
714 }
715 Some(this_type) => {
716 self.get_class_constness_and_extra_arguments(this_type, method_type.class_type)?
719 }
720 };
721
722 write!(w, "(")?;
723 if let Some(first_arg) = extra_first_arg {
724 self.emit_type_index(w, first_arg)?;
725 self.emit_arg_list(w, args_list, true)?;
726 } else {
727 self.emit_arg_list(w, args_list, false)?;
728 }
729 write!(w, ")")?;
730
731 if is_const_method && allow_emit_const {
732 write!(w, " const")?;
733 }
734
735 Ok(())
736 }
737
738 fn emit_attributes(
749 &mut self,
750 w: &mut impl Write,
751 attrs: Vec<PtrAttributes>,
752 allow_space_at_beginning: bool,
753 mut previous_byte_was_pointer_sigil: bool,
754 ) -> Result<()> {
755 let mut is_at_beginning = true;
756 for attr in attrs.iter().rev() {
757 if attr.is_pointee_const {
758 if !is_at_beginning || allow_space_at_beginning {
759 write!(w, " ")?;
760 }
761 write!(w, "const")?;
762 is_at_beginning = false;
763 previous_byte_was_pointer_sigil = false;
764 }
765
766 if self.has_flags(TypeFormatterFlags::SPACE_BEFORE_POINTER)
767 && !previous_byte_was_pointer_sigil
768 && (!is_at_beginning || allow_space_at_beginning)
769 {
770 write!(w, " ")?;
771 }
772 is_at_beginning = false;
773 match attr.mode {
774 PointerMode::Pointer => write!(w, "*")?,
775 PointerMode::LValueReference => write!(w, "&")?,
776 PointerMode::Member => write!(w, "::*")?,
777 PointerMode::MemberFunction => write!(w, "::*")?,
778 PointerMode::RValueReference => write!(w, "&&")?,
779 }
780 previous_byte_was_pointer_sigil = true;
781 if attr.is_pointer_const {
782 write!(w, " const")?;
783 previous_byte_was_pointer_sigil = false;
784 }
785 }
786 Ok(())
787 }
788
789 fn emit_member_ptr(
790 &mut self,
791 w: &mut impl Write,
792 fun: MemberFunctionType,
793 attributes: Vec<PtrAttributes>,
794 ) -> Result<()> {
795 self.emit_return_type(w, Some(fun.return_type), fun.attributes)?;
796 write!(w, "(")?;
797 self.emit_type_index(w, fun.class_type)?;
798 self.emit_attributes(w, attributes, false, false)?;
799 write!(w, ")")?;
800 self.emit_method_args(w, fun, false)?;
801 Ok(())
802 }
803
804 fn emit_proc_ptr(
805 &mut self,
806 w: &mut impl Write,
807 fun: ProcedureType,
808 attributes: Vec<PtrAttributes>,
809 ) -> Result<()> {
810 self.emit_return_type(w, fun.return_type, fun.attributes)?;
811
812 write!(w, "(")?;
813 self.emit_attributes(w, attributes, false, false)?;
814 write!(w, ")")?;
815 write!(w, "(")?;
816 self.emit_type_index(w, fun.argument_list)?;
817 write!(w, ")")?;
818 Ok(())
819 }
820
821 fn emit_other_ptr(
822 &mut self,
823 w: &mut impl Write,
824 type_data: TypeData,
825 attributes: Vec<PtrAttributes>,
826 ) -> Result<()> {
827 let mut buf = String::new();
828 self.emit_type(&mut buf, type_data)?;
829 let previous_byte_was_pointer_sigil = buf
830 .as_bytes()
831 .last()
832 .map(|&b| b == b'*' || b == b'&')
833 .unwrap_or(false);
834 w.write_str(&buf)?;
835 self.emit_attributes(w, attributes, true, previous_byte_was_pointer_sigil)?;
836
837 Ok(())
838 }
839
840 fn emit_ptr_helper(
841 &mut self,
842 w: &mut impl Write,
843 attributes: Vec<PtrAttributes>,
844 type_data: TypeData,
845 ) -> Result<()> {
846 match type_data {
847 TypeData::MemberFunction(t) => self.emit_member_ptr(w, t, attributes)?,
848 TypeData::Procedure(t) => self.emit_proc_ptr(w, t, attributes)?,
849 _ => self.emit_other_ptr(w, type_data, attributes)?,
850 };
851 Ok(())
852 }
853
854 fn emit_ptr(&mut self, w: &mut impl Write, ptr: PointerType, is_const: bool) -> Result<()> {
855 let mut attributes = vec![PtrAttributes {
856 is_pointer_const: ptr.attributes.is_const() || is_const,
857 is_pointee_const: false,
858 mode: ptr.attributes.pointer_mode(),
859 }];
860 let mut ptr = ptr;
861 loop {
862 let type_data = self.parse_type_index(ptr.underlying_type)?;
863 match type_data {
864 TypeData::Pointer(t) => {
865 attributes.push(PtrAttributes {
866 is_pointer_const: t.attributes.is_const(),
867 is_pointee_const: false,
868 mode: t.attributes.pointer_mode(),
869 });
870 ptr = t;
871 }
872 TypeData::Modifier(t) => {
873 attributes.last_mut().unwrap().is_pointee_const = t.constant;
875 let underlying_type_data = self.parse_type_index(t.underlying_type)?;
876 if let TypeData::Pointer(t) = underlying_type_data {
877 attributes.push(PtrAttributes {
878 is_pointer_const: t.attributes.is_const(),
879 is_pointee_const: false,
880 mode: t.attributes.pointer_mode(),
881 });
882 ptr = t;
883 } else {
884 self.emit_ptr_helper(w, attributes, underlying_type_data)?;
885 return Ok(());
886 }
887 }
888 _ => {
889 self.emit_ptr_helper(w, attributes, type_data)?;
890 return Ok(());
891 }
892 }
893 }
894 }
895
896 fn get_array_info(&mut self, array: ArrayType) -> Result<(Vec<u64>, TypeIndex, TypeData<'a>)> {
899 let mut base = array;
903 let mut dims = Vec::new();
904 dims.push(base.dimensions[0].into());
905
906 loop {
921 let type_index = base.element_type;
922 let type_data = self.parse_type_index(type_index)?;
923 match type_data {
924 TypeData::Array(a) => {
925 dims.push(a.dimensions[0].into());
926 base = a;
927 }
928 _ => {
929 return Ok((dims, type_index, type_data));
930 }
931 }
932 }
933 }
934
935 fn emit_array(&mut self, w: &mut impl Write, array: ArrayType) -> Result<()> {
936 let (dimensions_as_bytes, base_index, base) = self.get_array_info(array)?;
937 let base_size = self.get_data_size(base_index, &base);
938 self.emit_type(w, base)?;
939
940 let mut iter = dimensions_as_bytes.into_iter().peekable();
941 while let Some(current_level_byte_size) = iter.next() {
942 let next_level_byte_size = *iter.peek().unwrap_or(&base_size);
943 if next_level_byte_size != 0 {
944 let element_count = current_level_byte_size / next_level_byte_size;
945 write!(w, "[{}]", element_count)?;
946 } else {
947 write!(w, "[]")?;
950 };
951 }
952
953 Ok(())
954 }
955
956 fn emit_modifier(&mut self, w: &mut impl Write, modifier: ModifierType) -> Result<()> {
957 let type_data = self.parse_type_index(modifier.underlying_type)?;
958 match type_data {
959 TypeData::Pointer(ptr) => self.emit_ptr(w, ptr, modifier.constant)?,
960 TypeData::Primitive(prim) => self.emit_primitive(w, prim, modifier.constant)?,
961 _ => {
962 if modifier.constant {
963 write!(w, "const ")?
964 }
965 self.emit_type(w, type_data)?;
966 }
967 }
968 Ok(())
969 }
970
971 fn emit_class(&mut self, w: &mut impl Write, class: ClassType) -> Result<()> {
972 if self.has_flags(TypeFormatterFlags::NAME_ONLY) {
973 write!(w, "{}", class.name)?;
974 } else {
975 let name = match class.kind {
976 ClassKind::Class => "class",
977 ClassKind::Interface => "interface",
978 ClassKind::Struct => "struct",
979 };
980 write!(w, "{} {}", name, class.name)?
981 }
982 Ok(())
983 }
984
985 fn emit_arg_list(
986 &mut self,
987 w: &mut impl Write,
988 list: ArgumentList,
989 comma_before_first: bool,
990 ) -> Result<()> {
991 if let Some((first, args)) = list.arguments.split_first() {
992 if comma_before_first {
993 write!(w, ",")?;
994 if self.has_flags(TypeFormatterFlags::SPACE_AFTER_COMMA) {
995 write!(w, " ")?;
996 }
997 }
998 self.emit_type_index(w, *first)?;
999 for index in args.iter() {
1000 write!(w, ",")?;
1001 if self.has_flags(TypeFormatterFlags::SPACE_AFTER_COMMA) {
1002 write!(w, " ")?;
1003 }
1004 self.emit_type_index(w, *index)?;
1005 }
1006 }
1007 Ok(())
1008 }
1009
1010 fn emit_primitive(
1011 &mut self,
1012 w: &mut impl Write,
1013 prim: PrimitiveType,
1014 is_const: bool,
1015 ) -> Result<()> {
1016 let name = match prim.kind {
1018 PrimitiveKind::NoType => "<NoType>",
1019 PrimitiveKind::Void => "void",
1020 PrimitiveKind::Char => "signed char",
1021 PrimitiveKind::UChar => "unsigned char",
1022 PrimitiveKind::RChar => "char",
1023 PrimitiveKind::WChar => "wchar_t",
1024 PrimitiveKind::Char8 => "char8_t",
1025 PrimitiveKind::RChar16 => "char16_t",
1026 PrimitiveKind::RChar32 => "char32_t",
1027 PrimitiveKind::I8 => "int8_t",
1028 PrimitiveKind::U8 => "uint8_t",
1029 PrimitiveKind::Short => "short",
1030 PrimitiveKind::UShort => "unsigned short",
1031 PrimitiveKind::I16 => "int16_t",
1032 PrimitiveKind::U16 => "uint16_t",
1033 PrimitiveKind::Long => "long",
1034 PrimitiveKind::ULong => "unsigned long",
1035 PrimitiveKind::I32 => "int",
1036 PrimitiveKind::U32 => "unsigned int",
1037 PrimitiveKind::Quad => "long long",
1038 PrimitiveKind::UQuad => "unsigned long long",
1039 PrimitiveKind::I64 => "int64_t",
1040 PrimitiveKind::U64 => "uint64_t",
1041 PrimitiveKind::I128 | PrimitiveKind::Octa => "int128_t",
1042 PrimitiveKind::U128 | PrimitiveKind::UOcta => "uint128_t",
1043 PrimitiveKind::F16 => "float16_t",
1044 PrimitiveKind::F32 => "float",
1045 PrimitiveKind::F32PP => "float",
1046 PrimitiveKind::F48 => "float48_t",
1047 PrimitiveKind::F64 => "double",
1048 PrimitiveKind::F80 => "long double",
1049 PrimitiveKind::F128 => "long double",
1050 PrimitiveKind::Complex32 => "complex<float>",
1051 PrimitiveKind::Complex64 => "complex<double>",
1052 PrimitiveKind::Complex80 => "complex<long double>",
1053 PrimitiveKind::Complex128 => "complex<long double>",
1054 PrimitiveKind::Bool8 => "bool",
1055 PrimitiveKind::Bool16 => "bool16_t",
1056 PrimitiveKind::Bool32 => "bool32_t",
1057 PrimitiveKind::Bool64 => "bool64_t",
1058 PrimitiveKind::HRESULT => "HRESULT",
1059 _ => panic!("Unknown PrimitiveKind {:?} in emit_primitive", prim.kind),
1060 };
1061
1062 if prim.indirection.is_some() {
1063 if self.has_flags(TypeFormatterFlags::SPACE_BEFORE_POINTER) {
1064 if is_const {
1065 write!(w, "{} const *", name)?
1066 } else {
1067 write!(w, "{} *", name)?
1068 }
1069 } else if is_const {
1070 write!(w, "{} const*", name)?
1071 } else {
1072 write!(w, "{}*", name)?
1073 }
1074 } else if is_const {
1075 write!(w, "const {}", name)?
1076 } else {
1077 write!(w, "{}", name)?
1078 }
1079 Ok(())
1080 }
1081
1082 fn emit_named(&mut self, w: &mut impl Write, base: &str, name: RawString) -> Result<()> {
1083 if self.has_flags(TypeFormatterFlags::NAME_ONLY) {
1084 write!(w, "{}", name)?
1085 } else {
1086 write!(w, "{} {}", base, name)?
1087 }
1088
1089 Ok(())
1090 }
1091
1092 fn emit_type_index(&mut self, w: &mut impl Write, index: TypeIndex) -> Result<()> {
1093 match self.parse_type_index(index) {
1094 Ok(type_data) => self.emit_type(w, type_data),
1095 Err(Error::PdbError(pdb::Error::UnimplementedTypeKind(t))) => {
1096 write!(w, "<unimplemented type kind 0x{:x}>", t)?;
1097 Ok(())
1098 }
1099 Err(Error::PdbError(pdb::Error::TypeNotFound(type_index))) => {
1100 write!(w, "<missing type 0x{:x}>", type_index)?;
1101 Ok(())
1102 }
1103 Err(e) => Err(e),
1104 }
1105 }
1106
1107 fn emit_type(&mut self, w: &mut impl Write, type_data: TypeData) -> Result<()> {
1108 match self.emit_type_inner(w, type_data) {
1109 Ok(()) => Ok(()),
1110 Err(Error::PdbError(pdb::Error::TypeNotFound(type_index))) => {
1111 write!(w, "<missing type 0x{:x}>", type_index)?;
1112 Ok(())
1113 }
1114 Err(e) => Err(e),
1115 }
1116 }
1117
1118 fn emit_type_inner(&mut self, w: &mut impl Write, type_data: TypeData) -> Result<()> {
1119 match type_data {
1120 TypeData::Primitive(t) => self.emit_primitive(w, t, false)?,
1121 TypeData::Class(t) => self.emit_class(w, t)?,
1122 TypeData::MemberFunction(t) => {
1123 self.maybe_emit_return_type(w, Some(t.return_type), t.attributes)?;
1124 write!(w, "()")?;
1125 self.emit_method_args(w, t, false)?;
1126 }
1127 TypeData::Procedure(t) => {
1128 self.maybe_emit_return_type(w, t.return_type, t.attributes)?;
1129 write!(w, "()(")?;
1130 self.emit_type_index(w, t.argument_list)?;
1131 write!(w, "")?;
1132 }
1133 TypeData::ArgumentList(t) => self.emit_arg_list(w, t, false)?,
1134 TypeData::Pointer(t) => self.emit_ptr(w, t, false)?,
1135 TypeData::Array(t) => self.emit_array(w, t)?,
1136 TypeData::Union(t) => self.emit_named(w, "union", t.name)?,
1137 TypeData::Enumeration(t) => self.emit_named(w, "enum", t.name)?,
1138 TypeData::Enumerate(t) => self.emit_named(w, "enum class", t.name)?,
1139 TypeData::Modifier(t) => self.emit_modifier(w, t)?,
1140 _ => write!(w, "unhandled type /* {:?} */", type_data)?,
1141 }
1142
1143 Ok(())
1144 }
1145}
1146
1147#[derive(Eq, PartialEq)]
1148enum PtrToClassKind {
1149 PtrToGivenClass {
1150 constant: bool,
1152 },
1153 OtherType,
1154}
1155
1156#[derive(Debug)]
1157struct PtrAttributes {
1158 is_pointer_const: bool,
1159 is_pointee_const: bool,
1160 mode: PointerMode,
1161}
1162
1163struct ItemMap<'a, I: ItemIndex> {
1164 iter: ItemIter<'a, I>,
1165 finder: ItemFinder<'a, I>,
1166}
1167
1168impl<'a, I> ItemMap<'a, I>
1169where
1170 I: ItemIndex,
1171{
1172 pub fn try_get(&mut self, index: I) -> std::result::Result<Item<'a, I>, pdb::Error> {
1173 if index <= self.finder.max_index() {
1174 return self.finder.find(index);
1175 }
1176
1177 while let Some(item) = self.iter.next()? {
1178 self.finder.update(&self.iter);
1179 match item.index().partial_cmp(&index) {
1180 Some(Ordering::Equal) => return Ok(item),
1181 Some(Ordering::Greater) => break,
1182 _ => continue,
1183 }
1184 }
1185
1186 Err(pdb::Error::TypeNotFound(index.into()))
1187 }
1188}
1189
1190type IdMap<'a> = ItemMap<'a, IdIndex>;
1191type TypeMap<'a> = ItemMap<'a, TypeIndex>;
1192
1193struct TypeSizeCache<'a> {
1194 forward_ref_sizes: HashMap<RawString<'a>, u64>,
1208
1209 cached_ranges: RangeSet2<u32>,
1210}
1211
1212impl<'a> TypeSizeCache<'a> {
1213 pub fn get_size_for_forward_reference(
1214 &mut self,
1215 index: TypeIndex,
1216 name: RawString<'a>,
1217 type_map: &mut TypeMap<'a>,
1218 ) -> Option<u64> {
1219 if let Some(size) = self.forward_ref_sizes.get(&name) {
1220 return Some(*size);
1221 }
1222
1223 let start_index = index.0;
1224 let candidate_range = RangeSet::from((start_index + 1)..);
1225 let uncached_ranges = &candidate_range - &self.cached_ranges;
1226 for uncached_range in uncached_ranges.iter() {
1227 let (range_start, range_end) = match uncached_range {
1228 RangeSetRange::Range(r) => (*r.start, Some(*r.end)),
1229 RangeSetRange::RangeFrom(r) => (*r.start, None),
1230 };
1231 for index in range_start.. {
1232 if let Some(range_end) = range_end {
1233 if index >= range_end {
1234 break;
1235 }
1236 }
1237 if let Ok(item) = type_map.try_get(TypeIndex(index)) {
1238 let s = self.update_forward_ref_size_map(&item);
1239 if let Some((found_name, found_size)) = s {
1240 if found_name == name {
1241 self.cached_ranges |= RangeSet::from(start_index..(index + 1));
1242 return Some(found_size);
1243 }
1244 }
1245 } else {
1246 break;
1247 }
1248 }
1249 }
1250 self.cached_ranges |= RangeSet::from(start_index..);
1251
1252 None
1253 }
1254
1255 pub fn update_forward_ref_size_map(
1256 &mut self,
1257 item: &Item<'a, TypeIndex>,
1258 ) -> Option<(RawString<'a>, u64)> {
1259 if let Ok(type_data) = item.parse() {
1260 match type_data {
1261 TypeData::Class(t) => {
1262 if !t.properties.forward_reference() {
1263 let name = t.unique_name.unwrap_or(t.name);
1264 self.forward_ref_sizes.insert(name, t.size);
1265 return Some((name, t.size));
1266 }
1267 }
1268 TypeData::Union(t) => {
1269 if !t.properties.forward_reference() {
1270 let name = t.unique_name.unwrap_or(t.name);
1271 self.forward_ref_sizes.insert(name, t.size);
1272 return Some((name, t.size));
1273 }
1274 }
1275 _ => {}
1276 }
1277 }
1278 None
1279 }
1280}