1 //! msvc-demangler is a crate for Rust that can demangle C++ symbols which use
2 //! the MSVC mangling scheme. These are emitted by the Microsoft C++ compiler
3 //! for Windows as well as some others.
4 //!
5 //! # Example
6 //!
7 //! ```
8 //! use msvc_demangler;
9 //! let flags = msvc_demangler::DemangleFlags::llvm();
10 //! let result = msvc_demangler::demangle("??_0klass@@QEAAHH@Z", flags).unwrap();
11 //! println!("{}", result);
12 //! ```
13 //!
14 //! # Behavior
15 //!
16 //! It's functionality is similar to `undname` on Windows and the underlying
17 //! `UnDecorateSymbolName` function. Since Microsoft does not document the
18 //! mangling scheme this is likely not to be entirely accurate. When unclear
19 //! the implementation tries to follow what LLVM does.
20 //!
21 //! # License
22 //!
23 //! This msvc-demangler is dual licensed under the MIT and the University of
24 //! Illinois Open Source Licenses.
25
26 #![deny(missing_debug_implementations)]
27 #![deny(unsafe_code)]
28
29 #[macro_use]
30 extern crate bitflags;
31
32 use std::borrow::Cow;
33 use std::cmp::min;
34 use std::error;
35 use std::fmt;
36 use std::io;
37 use std::io::Write;
38 use std::mem;
39 use std::result;
40 use std::str;
41 use std::str::Utf8Error;
42 use std::string::FromUtf8Error;
43
44 pub struct Error {
45 repr: ErrorRepr,
46 }
47
48 impl fmt::Debug for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result49 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
50 fmt::Debug::fmt(&self.repr, f)
51 }
52 }
53
54 #[derive(Debug)]
55 pub enum ErrorRepr {
56 FromUtf8(FromUtf8Error),
57 Utf8(Utf8Error),
58 Io(io::Error),
59 ParseError(Cow<'static, str>, String, usize),
60 Other(String),
61 }
62
63 impl Error {
64 /// Creates a simple error message.
new<S: Into<String>>(s: S) -> Error65 pub fn new<S: Into<String>>(s: S) -> Error {
66 Error {
67 repr: ErrorRepr::Other(s.into()),
68 }
69 }
70
new_parse_error(s: Cow<'static, str>, input: &str, offset: usize) -> Error71 fn new_parse_error(s: Cow<'static, str>, input: &str, offset: usize) -> Error {
72 let context = Cow::Borrowed(input.as_bytes().get(offset..).unwrap_or(&[]));
73 let context = if context.len() > 20 {
74 Cow::Owned(format!("{}...", String::from_utf8_lossy(&context[..20])))
75 } else {
76 String::from_utf8_lossy(&context)
77 };
78 Error {
79 repr: ErrorRepr::ParseError(s, context.to_string(), offset),
80 }
81 }
82
83 /// Returns the offset in the input where the error happened.
offset(&self) -> Option<usize>84 pub fn offset(&self) -> Option<usize> {
85 match self.repr {
86 ErrorRepr::ParseError(_, _, offset) => Some(offset),
87 _ => None,
88 }
89 }
90 }
91
92 impl From<Utf8Error> for Error {
from(err: Utf8Error) -> Error93 fn from(err: Utf8Error) -> Error {
94 Error {
95 repr: ErrorRepr::Utf8(err),
96 }
97 }
98 }
99
100 impl From<FromUtf8Error> for Error {
from(err: FromUtf8Error) -> Error101 fn from(err: FromUtf8Error) -> Error {
102 Error {
103 repr: ErrorRepr::FromUtf8(err),
104 }
105 }
106 }
107
108 impl From<std::io::Error> for Error {
from(err: std::io::Error) -> Error109 fn from(err: std::io::Error) -> Error {
110 Error {
111 repr: ErrorRepr::Io(err),
112 }
113 }
114 }
115
116 impl error::Error for Error {
source(&self) -> Option<&(dyn error::Error + 'static)>117 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
118 match self.repr {
119 ErrorRepr::FromUtf8(ref e) => Some(&*e),
120 ErrorRepr::Utf8(ref e) => Some(&*e),
121 ErrorRepr::Io(ref e) => Some(&*e),
122 ErrorRepr::ParseError(..) => None,
123 ErrorRepr::Other(_) => None,
124 }
125 }
126 }
127
128 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result129 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
130 match self.repr {
131 ErrorRepr::FromUtf8(ref e) => fmt::Display::fmt(e, f),
132 ErrorRepr::Utf8(ref e) => fmt::Display::fmt(e, f),
133 ErrorRepr::Io(ref e) => fmt::Display::fmt(e, f),
134 ErrorRepr::ParseError(ref msg, ref context, offset) => {
135 write!(f, "{} (offset: {}, remaining: {:?})", msg, offset, context)
136 }
137 ErrorRepr::Other(ref msg) => write!(f, "{}", msg),
138 }
139 }
140 }
141
142 type Result<T> = result::Result<T, Error>;
143
144 bitflags! {
145 pub struct StorageClass: u32 {
146 const CONST = 0b0_0000_0001;
147 const VOLATILE = 0b0_0000_0010;
148 const FAR = 0b0_0000_0100;
149 const HUGE = 0b0_0000_1000;
150 const UNALIGNED = 0b0_0001_0000;
151 const RESTRICT = 0b0_0010_0000;
152 const PTR64 = 0b0_0100_0000;
153 const LVALUE_QUAL = 0b0_1000_0000;
154 const RVALUE_QUAL = 0b1_0000_0000;
155 }
156 }
157
158 bitflags! {
159 pub struct DemangleFlags: u32 {
160 /// Undecorate 32-bit decorated names.
161 const DECODE_32_BIT = 0x0800;
162 /// Enable full undecoration.
163 const COMPLETE = 0x0000;
164 /// Undecorate only the name for primary declaration. Returns [scope::]name. Does expand template parameters.
165 const NAME_ONLY = 0x1000;
166 /// Disable expansion of access specifiers for members.
167 const NO_ACCESS_SPECIFIERS = 0x0080;
168 // /// Disable expansion of the declaration language specifier.
169 // const NO_ALLOCATION_LANGUAGE = 0x0010;
170 // /// Disable expansion of the declaration model.
171 // const NO_ALLOCATION_MODEL = 0x0008;
172 // /// Do not undecorate function arguments.
173 // const NO_ARGUMENTS = 0x2000;
174 /// Disable expansion of CodeView modifiers on the this type for primary declaration.
175 const NO_CV_THISTYPE = 0x0040;
176 /// Disable expansion of return types for primary declarations.
177 const NO_FUNCTION_RETURNS = 0x0004;
178 // /// Remove leading underscores from Microsoft keywords.
179 // const NO_LEADING_UNDERSCORES = 0x0001;
180 /// Disable expansion of the static or virtual attribute of members.
181 const NO_MEMBER_TYPE = 0x0200;
182 /// Disable expansion of Microsoft keywords.
183 const NO_MS_KEYWORDS = 0x0002;
184 /// Disable expansion of Microsoft keywords on the this type for primary declaration.
185 const NO_MS_THISTYPE = 0x0020;
186 /// Enable Microsoft type names.
187 const MS_TYPENAMES = 0x0400;
188 // /// Disable expansion of the Microsoft model for user-defined type returns.
189 // const NO_RETURN_UDT_MODEL = 0x0400;
190 // /// Do not undecorate special names, such as vtable, vcall, vector, metatype, and so on.
191 // const NO_SPECIAL_SYMS = 0x4000;
192 /// Disable all modifiers on the this type.
193 const NO_THISTYPE = Self::NO_MS_THISTYPE.bits | Self::NO_CV_THISTYPE.bits;
194 // /// Disable expansion of throw-signatures for functions and pointers to functions.
195 // const NO_THROW_SIGNATURES = 0x0100;
196 /// Disable output of struct/union/class/enum specifiers.
197 // (Not sure if this duplicates an existing flag)
198 const NO_CLASS_TYPE = 0x10_0000;
199 /// Insert a space after each comma.
200 const SPACE_AFTER_COMMA = 0x20_0000;
201 /// Make * and & hug the type name.
202 const HUG_TYPE = 0x40_0000;
203 /// Insert a space before pointers.
204 const SPACE_BEFORE_POINTER = 0x80_0000;
205 /// Add ptr64 to output. This is disabled by default because it's also not
206 /// added by LLVM. This is in a way the inverse of the DIA `UNDNAME_NO_PTR64`
207 const WITH_PTR64 = 0x100_0000;
208 }
209 }
210
211 impl DemangleFlags {
llvm() -> DemangleFlags212 pub fn llvm() -> DemangleFlags {
213 DemangleFlags::COMPLETE
214 | DemangleFlags::SPACE_AFTER_COMMA
215 | DemangleFlags::SPACE_BEFORE_POINTER
216 | DemangleFlags::MS_TYPENAMES
217 | DemangleFlags::HUG_TYPE
218 }
219 }
220
221 // Calling conventions
222 #[derive(Clone, Copy, Debug, PartialEq)]
223 pub enum CallingConv {
224 Cdecl,
225 Pascal,
226 Thiscall,
227 Stdcall,
228 Fastcall,
229 _Regcall,
230 }
231
232 bitflags! {
233 pub struct FuncClass: u32 {
234 const PUBLIC = 0b0000_0001;
235 const PROTECTED = 0b0000_0010;
236 const PRIVATE = 0b0000_0100;
237 const GLOBAL = 0b0000_1000;
238 const STATIC = 0b0001_0000;
239 const VIRTUAL = 0b0010_0000;
240 const FAR = 0b0100_0000;
241 const THUNK = 0b1000_0000;
242 }
243 }
244
245 // The kind of variable storage. In LLVM this is called storage class.
246 #[derive(Clone, Copy, Debug, PartialEq)]
247 pub enum VarStorageKind {
248 PrivateStatic,
249 ProtectedStatic,
250 PublicStatic,
251 Global,
252 FunctionLocalStatic,
253 }
254
255 // Represents an identifier which may be a template.
256 #[derive(Clone, PartialEq)]
257 pub enum Name<'a> {
258 Md5(&'a [u8]),
259 Operator(Operator<'a>),
260 NonTemplate(&'a [u8]),
261 AsInterface(&'a [u8]),
262 Template(Box<Name<'a>>, Params<'a>),
263 Discriminator(i32),
264 ParsedName(Box<ParseResult<'a>>),
265 AnonymousNamespace(Option<String>),
266 }
267
268 impl<'a> fmt::Debug for Name<'a> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270 match *self {
271 Name::Md5(s) => f
272 .debug_tuple("Md5")
273 .field(&String::from_utf8_lossy(s))
274 .finish(),
275 Name::Operator(ref op) => f.debug_tuple("Operator").field(&op).finish(),
276 Name::NonTemplate(s) => f
277 .debug_tuple("NonTemplate")
278 .field(&String::from_utf8_lossy(s))
279 .finish(),
280 Name::AsInterface(s) => f
281 .debug_tuple("AsInterface")
282 .field(&String::from_utf8_lossy(s))
283 .finish(),
284 Name::Template(ref name, ref params) => {
285 f.debug_tuple("Template").field(name).field(params).finish()
286 }
287 Name::Discriminator(i) => f.debug_tuple("Discriminator").field(&i).finish(),
288 Name::ParsedName(ref res) => f.debug_tuple("ParsedName").field(res).finish(),
289 Name::AnonymousNamespace(ref name) => {
290 f.debug_tuple("AnonymousNamespace").field(name).finish()
291 }
292 }
293 }
294 }
295
296 #[derive(Clone, Debug, PartialEq)]
297 pub enum Operator<'a> {
298 Ctor,
299 Dtor,
300 New,
301 Delete,
302 Equal,
303 RShift,
304 LShift,
305 Bang,
306 EqualEqual,
307 BangEqual,
308 Subscript,
309 Conversion, // TODO
310 Arrow,
311 Star,
312 PlusPlus,
313 MinusMinus,
314 Minus,
315 Plus,
316 Amp,
317 ArrowStar,
318 Slash,
319 Percent,
320 Less,
321 LessEqual,
322 Greater,
323 GreaterEqual,
324 Comma,
325 Call,
326 Tilde,
327 Caret,
328 Pipe,
329 AmpAmp,
330 PipePipe,
331 StarEqual,
332 PlusEqual,
333 MinusEqual,
334 SlashEqual,
335 PercentEqual,
336 GreaterGreaterEqual,
337 LessLessEqual,
338 AmpEqual,
339 PipeEqual,
340 CaretEqual,
341
342 VFTable,
343 VBTable,
344 VCall,
345 Typeof,
346 LocalStaticGuard(Option<u32>),
347 String,
348 VBaseDtor,
349 VectorDeletingDtor,
350 DefaultCtorClosure,
351 ScalarDeletingDtor,
352 VectorCtorIterator,
353 VectorDtorIterator,
354 VectorVBaseCtorIterator,
355 VirtualDisplacementMap,
356 EHVectorCtorIterator,
357 EHVectorDtorIterator,
358 EHVectorVBaseCtorIterator,
359 CopyCtorClosure,
360
361 LocalVFTable,
362 LocalVFTableCtorClosure,
363 ArrayNew,
364 ArrayDelete,
365 PlacementDeleteClosure,
366 PlacementArrayDeleteClosure,
367
368 CoroutineAwait,
369 LiteralOperatorName,
370
371 RTTITypeDescriptor(StorageClass, Box<Type<'a>>),
372 RTTIBaseClassDescriptor(i32, i32, i32, i32),
373 RTTIBaseClassArray,
374 RTTIClassHierarchyDescriptor,
375 RTTIClassCompleteObjectLocator,
376
377 DynamicInitializer,
378 DynamicAtexitDtor,
379 LocalStaticThreadGuard(Option<u32>),
380 }
381
382 #[derive(Clone, Debug, PartialEq)]
383 pub struct NameSequence<'a> {
384 pub names: Vec<Name<'a>>,
385 }
386
387 #[derive(Clone, Debug, PartialEq)]
388 pub struct Params<'a> {
389 pub types: Vec<Type<'a>>,
390 }
391
392 #[derive(Clone, Debug, PartialEq)]
393 pub struct Symbol<'a> {
394 pub name: Name<'a>,
395 pub scope: NameSequence<'a>,
396 }
397
398 // The type class. Mangled symbols are first parsed and converted to
399 // this type and then converted to string.
400 #[derive(Clone, Debug, PartialEq)]
401 pub enum Type<'a> {
402 None,
403 MemberFunction(
404 FuncClass,
405 CallingConv,
406 Params<'a>,
407 StorageClass,
408 Box<Type<'a>>,
409 ), // StorageClass is for the 'this' pointer
410 MemberFunctionPointer(
411 Symbol<'a>,
412 FuncClass,
413 CallingConv,
414 Params<'a>,
415 StorageClass,
416 Box<Type<'a>>,
417 ),
418 NonMemberFunction(CallingConv, Params<'a>, StorageClass, Box<Type<'a>>),
419 CXXVBTable(NameSequence<'a>, StorageClass),
420 CXXVFTable(NameSequence<'a>, StorageClass),
421 VCallThunk(i32, CallingConv),
422 TemplateParameterWithIndex(i32),
423 ThreadSafeStaticGuard(i32),
424 Constant(i32),
425 ConstantString(Vec<u8>),
426 Ptr(Box<Type<'a>>, StorageClass),
427 Ref(Box<Type<'a>>, StorageClass),
428 RValueRef(Box<Type<'a>>, StorageClass),
429 Array(i32, Box<Type<'a>>, StorageClass),
430 Var(Box<Type<'a>>, VarStorageKind, StorageClass),
431
432 Alias(Symbol<'a>, StorageClass),
433 Struct(Symbol<'a>, StorageClass),
434 Union(Symbol<'a>, StorageClass),
435 Class(Symbol<'a>, StorageClass),
436 Enum(Symbol<'a>, StorageClass),
437
438 Void(StorageClass),
439 Bool(StorageClass),
440 Char(StorageClass),
441 Schar(StorageClass),
442 Uchar(StorageClass),
443 Short(StorageClass),
444 Ushort(StorageClass),
445 Int(StorageClass),
446 Uint(StorageClass),
447 Long(StorageClass),
448 Ulong(StorageClass),
449 Int64(StorageClass),
450 Uint64(StorageClass),
451 Int128(StorageClass),
452 Uint128(StorageClass),
453 Wchar(StorageClass),
454 Char8(StorageClass),
455 Char16(StorageClass),
456 Char32(StorageClass),
457 Float(StorageClass),
458 Double(StorageClass),
459 Ldouble(StorageClass),
460 VarArgs,
461 EmptyParameterPack,
462 Nullptr,
463 RTTIType,
464 }
465
466 #[derive(Debug, Clone, PartialEq)]
467 pub struct ParseResult<'a> {
468 pub symbol: Symbol<'a>,
469 pub symbol_type: Type<'a>,
470 }
471
472 // Demangler class takes the main role in demangling symbols.
473 // It has a set of functions to parse mangled symbols into Type instnaces.
474 // It also has a set of functions to cnovert Type instances to strings.
475 struct ParserState<'a> {
476 // Mangled symbol. read_* functions shorten this string
477 // as they parse it.
478 remaining: &'a [u8],
479
480 // The original input
481 input: &'a str,
482
483 // how many bytes we advanced
484 offset: usize,
485
486 // The first 10 names in a mangled name can be back-referenced by
487 // special name @[0-9]. This is a storage for the first 10 names.
488 memorized_names: Vec<Name<'a>>,
489
490 memorized_types: Vec<Type<'a>>,
491 }
492
493 impl<'a> ParserState<'a> {
fail(&self, s: &'static str) -> Error494 fn fail(&self, s: &'static str) -> Error {
495 Error::new_parse_error(Cow::Borrowed(s), self.input, self.offset)
496 }
497
fail_args(&self, args: fmt::Arguments) -> Error498 fn fail_args(&self, args: fmt::Arguments) -> Error {
499 Error::new_parse_error(Cow::Owned(format!("{}", args)), self.input, self.offset)
500 }
501
parse(&mut self) -> Result<ParseResult<'a>>502 fn parse(&mut self) -> Result<ParseResult<'a>> {
503 // MSVC-style mangled symbols must start with b'?'.
504 if !self.consume(b"?") {
505 return Err(self.fail("does not start with b'?'"));
506 }
507
508 if self.consume(b"?@") {
509 let name = self.read_md5_name()?;
510 return Ok(ParseResult {
511 symbol: Symbol {
512 name,
513 scope: NameSequence { names: Vec::new() },
514 },
515 symbol_type: Type::None,
516 });
517 }
518
519 if self.consume(b"$") {
520 if self.consume(b"TSS") {
521 let mut guard_num: i32 = i32::from(
522 self.read_digit()
523 .ok_or_else(|| self.fail("missing digit"))?,
524 );
525 while !self.consume(b"@") {
526 guard_num = guard_num * 10
527 + i32::from(
528 self.read_digit()
529 .ok_or_else(|| self.fail("missing digit"))?,
530 );
531 }
532 let name = self.read_nested_name()?;
533 let scope = self.read_scope()?;
534 self.expect(b"4HA")?;
535 return Ok(ParseResult {
536 symbol: Symbol { name, scope },
537 symbol_type: Type::ThreadSafeStaticGuard(guard_num),
538 });
539 }
540 let name = self.read_template_name()?;
541 return Ok(ParseResult {
542 symbol: Symbol {
543 name,
544 scope: NameSequence { names: Vec::new() },
545 },
546 symbol_type: Type::None,
547 });
548 }
549
550 // What follows is a main symbol name. This may include
551 // namespaces or class names.
552 let mut symbol = self.read_name(true)?;
553
554 // Special case for some weird cases where extra data is tacked on
555 // after the main symbol but belongs into the symbol.
556 match symbol.name {
557 Name::Operator(Operator::LocalStaticGuard(ref mut scope_index))
558 | Name::Operator(Operator::LocalStaticThreadGuard(ref mut scope_index)) => {
559 let _is_visible = if self.consume(b"4IA") {
560 false
561 } else if self.consume(b"5") {
562 true
563 } else {
564 return Err(self.fail("unexpected local guard marker"));
565 };
566 if !self.remaining.is_empty() {
567 *scope_index = Some(self.read_unsigned()?);
568 };
569 }
570 _ => {}
571 }
572
573 if let Ok(c) = self.get() {
574 let symbol_type = match c {
575 b'0'..=b'4' => {
576 // Read a variable.
577 let kind = match c {
578 b'0' => VarStorageKind::PrivateStatic,
579 b'1' => VarStorageKind::ProtectedStatic,
580 b'2' => VarStorageKind::PublicStatic,
581 b'3' => VarStorageKind::Global,
582 b'4' => VarStorageKind::FunctionLocalStatic,
583 _ => unreachable!(),
584 };
585 let ty = self.read_var_type(StorageClass::empty())?;
586 let sc = self.read_storage_class();
587 Type::Var(Box::new(ty), kind, sc)
588 }
589 b'6' => {
590 let access_class = self.read_qualifier();
591 let scope = self.read_scope()?;
592 Type::CXXVFTable(scope, access_class)
593 }
594 b'7' => {
595 let access_class = self.read_qualifier();
596 let scope = self.read_scope()?;
597 Type::CXXVBTable(scope, access_class)
598 }
599 b'9' => {
600 // extern "C" names have their class and type omitted.
601 Type::None
602 }
603 b'Y' => {
604 // Read a non-member function.
605 let calling_conv = self.read_calling_conv()?;
606 let storage_class = self.read_storage_class_for_return()?;
607 let return_type = self.read_var_type(storage_class)?;
608 let params = self.read_func_params()?;
609 Type::NonMemberFunction(
610 calling_conv,
611 params,
612 StorageClass::empty(),
613 Box::new(return_type),
614 )
615 }
616 b'_' => {
617 // Read an encoded string.
618 let char_bytes = match self.get()? {
619 b'0' => 1, // char
620 b'1' => 2, // wchar_t
621 _ => {
622 return Err(self.fail("unknown string character type"));
623 }
624 };
625 self.read_encoded_string(char_bytes)?
626 }
627 b'$' => {
628 self.expect(b"B")?;
629 let vftable_offset = self.read_number()?;
630 self.expect(b"A")?;
631 let calling_conv = self.read_calling_conv()?;
632 Type::VCallThunk(vftable_offset, calling_conv)
633 }
634 b'8' => Type::RTTIType,
635 c => {
636 // Read a member function.
637 let func_class = self.read_func_class(c)?;
638 let access_class = if func_class.contains(FuncClass::STATIC) {
639 StorageClass::empty()
640 } else {
641 self.read_func_qualifiers()?
642 };
643
644 let calling_conv = self.read_calling_conv()?;
645 let storage_class_for_return = self.read_storage_class_for_return()?;
646 let return_type = self.read_func_return_type(storage_class_for_return)?;
647 let params = self.read_func_params()?;
648 Type::MemberFunction(
649 func_class,
650 calling_conv,
651 params,
652 access_class,
653 Box::new(return_type),
654 )
655 }
656 };
657 Ok(ParseResult {
658 symbol,
659 symbol_type,
660 })
661 } else {
662 Ok(ParseResult {
663 symbol,
664 symbol_type: Type::None,
665 })
666 }
667 }
668
peek(&self) -> Option<u8>669 fn peek(&self) -> Option<u8> {
670 self.remaining.first().cloned()
671 }
672
get(&mut self) -> Result<u8>673 fn get(&mut self) -> Result<u8> {
674 match self.peek() {
675 Some(first) => {
676 self.advance(1);
677 Ok(first)
678 }
679 None => Err(self.fail("unexpected end of input")),
680 }
681 }
682
consume(&mut self, s: &[u8]) -> bool683 fn consume(&mut self, s: &[u8]) -> bool {
684 if self.remaining.starts_with(s) {
685 self.advance(s.len());
686 true
687 } else {
688 false
689 }
690 }
691
advance(&mut self, len: usize)692 fn advance(&mut self, len: usize) {
693 let new_remaining = self.remaining.get(len..).unwrap_or(&[]);
694 self.offset += self.remaining.len() - new_remaining.len();
695 self.remaining = new_remaining;
696 }
697
expect(&mut self, s: &[u8]) -> Result<()>698 fn expect(&mut self, s: &[u8]) -> Result<()> {
699 if !self.consume(s) {
700 Err(self.fail_args(format_args!("{} expected", str::from_utf8(s)?,)))
701 } else {
702 Ok(())
703 }
704 }
705
706 /// An MD5 mangled name is `??@` followed by 32 characters and a terminating `@`.
707 ///
708 /// See https://github.com/llvm/llvm-project/blob/818cf30b83305fa4a2f75821349210b0f7aff4a4/llvm/lib/Demangle/MicrosoftDemangle.cpp#L754
read_md5_name(&mut self) -> Result<Name<'a>>709 fn read_md5_name(&mut self) -> Result<Name<'a>> {
710 let start_offset = self.offset;
711
712 while self.read_hex_digit().is_some() {}
713 let end_offset = self.offset;
714
715 if self.offset - start_offset != 32 || !self.consume(b"@") {
716 return Err(self.fail("expected MD5 mangled name of length 32"));
717 }
718 Ok(Name::Md5(&self.input.as_bytes()[start_offset..end_offset]))
719 }
720
read_digit(&mut self) -> Option<u8>721 fn read_digit(&mut self) -> Option<u8> {
722 match self.peek() {
723 Some(first) => {
724 if char::from(first).is_digit(10) {
725 self.advance(1);
726 Some(first - b'0')
727 } else {
728 None
729 }
730 }
731 None => None,
732 }
733 }
734
read_hex_digit(&mut self) -> Option<char>735 fn read_hex_digit(&mut self) -> Option<char> {
736 match self.peek() {
737 Some(first) => {
738 if char::from(first).is_digit(16) {
739 self.advance(1);
740 Some(first as char)
741 } else {
742 None
743 }
744 }
745 None => None,
746 }
747 }
748
read_encoded_string(&mut self, char_bytes: i32) -> Result<Type<'a>>749 fn read_encoded_string(&mut self, char_bytes: i32) -> Result<Type<'a>> {
750 let byte_length = self.read_number()?; // including null terminator
751 let _crc = self.read_number()?;
752 let bytes = min(byte_length, char_bytes * 32);
753
754 let mut collected = vec![];
755 for _i in 0..bytes {
756 let c = self.get()?;
757 let byte: u8 = match c {
758 b'0'..=b'9' | b'a'..=b'z' | b'A'..=b'Z' | b'_' | b'$' => c,
759 b'?' => {
760 let c = self.get()?;
761 match c {
762 b'A'..=b'Z' => c - b'A' + 0xe1,
763 b'a'..=b'z' => c - b'A' + 0xc1,
764 b'0'..=b'9' => {
765 let v = &[
766 b',', b'/', b'\\', b':', b'.', b' ', b'\n', b'\t', b'\'', b'-',
767 ];
768 v[(c - b'0') as usize]
769 }
770 b'$' => {
771 let high = self.get()? - b'A';
772 let low = self.get()? - b'A';
773 high << 4 | low
774 }
775 _ => {
776 return Err(self.fail_args(format_args!(
777 "unknown escaped encoded string character {}",
778 char::from(c)
779 )));
780 }
781 }
782 }
783 _ => {
784 return Err(self.fail_args(format_args!(
785 "unknown escaped encoded string character {}",
786 char::from(c)
787 )));
788 }
789 };
790 collected.push(byte);
791 }
792
793 Ok(Type::ConstantString(collected))
794 }
795
796 // Sometimes numbers are encoded in mangled symbols. For example,
797 // "int (*x)[20]" is a valid C type (x is a pointer to an array of
798 // length 20), so we need some way to embed numbers as part of symbols.
799 // This function parses it.
800 //
801 // <number> ::= [?] <non-negative integer>
802 //
803 // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10
804 // ::= <hex digit>+ @ # when Numbrer == 0 or >= 10
805 //
806 // <hex-digit> ::= [A-P] # A = 0, B = 1, ...
read_number(&mut self) -> Result<i32>807 fn read_number(&mut self) -> Result<i32> {
808 let neg = self.consume(b"?");
809
810 if let Some(digit) = self.read_digit() {
811 let ret = digit + 1;
812 return Ok(if neg { -i32::from(ret) } else { i32::from(ret) });
813 }
814
815 let mut i = 0;
816 let mut ret = 0;
817 for c in self.remaining {
818 match *c {
819 b'@' => {
820 self.advance(i + 1);
821 return Ok(if neg { -(ret as i32) } else { ret as i32 });
822 }
823 b'A'..=b'P' => {
824 ret = (ret << 4) + i32::from(c - b'A');
825 i += 1;
826 }
827 _ => {
828 return Err(self.fail("bad number"));
829 }
830 }
831 }
832 Err(self.fail("bad number"))
833 }
834
read_unsigned(&mut self) -> Result<u32>835 fn read_unsigned(&mut self) -> Result<u32> {
836 let num = self.read_number()?;
837 if num < 0 {
838 return Err(self.fail("expected unsigned"));
839 }
840 Ok(num as u32)
841 }
842
843 // Read until the next b'@'.
read_string(&mut self) -> Result<&'a [u8]>844 fn read_string(&mut self) -> Result<&'a [u8]> {
845 if let Some(pos) = self.remaining.iter().position(|&x| x == b'@') {
846 let ret = &self.remaining[0..pos];
847 self.advance(pos + 1);
848 Ok(ret)
849 } else {
850 Err(self.fail("read_string: missing b'@'"))
851 }
852 }
853
854 // First 10 strings can be referenced by special names ?0, ?1, ..., ?9.
855 // Memorize it.
memorize_name(&mut self, n: &Name<'a>)856 fn memorize_name(&mut self, n: &Name<'a>) {
857 // TODO: the contains check does an equality check on the Name enum, which
858 // might do unexpected things in subtle cases. It's not a pure string equality check.
859 if self.memorized_names.len() < 10 && !self.memorized_names.contains(n) {
860 self.memorized_names.push(n.clone());
861 }
862 }
memorize_type(&mut self, t: &Type<'a>)863 fn memorize_type(&mut self, t: &Type<'a>) {
864 // TODO: the contains check does an equality check on the Type enum, which
865 // might do unexpected things in subtle cases. It's not a pure string equality check.
866 if self.memorized_types.len() < 10 && !self.memorized_types.contains(t) {
867 self.memorized_types.push(t.clone());
868 }
869 }
870
read_template_name(&mut self) -> Result<Name<'a>>871 fn read_template_name(&mut self) -> Result<Name<'a>> {
872 // Templates have their own context for backreferences.
873 let saved_memorized_names = mem::take(&mut self.memorized_names);
874 let saved_memorized_types = mem::take(&mut self.memorized_types);
875 let name = self.read_unqualified_name(false)?; // how does wine deal with ??$?DM@std@@YA?AV?$complex@M@0@ABMABV10@@Z
876 let template_params = self.read_params()?;
877 let _ = mem::replace(&mut self.memorized_names, saved_memorized_names);
878 let _ = mem::replace(&mut self.memorized_types, saved_memorized_types);
879 Ok(Name::Template(Box::new(name), template_params))
880 }
881
read_nested_name(&mut self) -> Result<Name<'a>>882 fn read_nested_name(&mut self) -> Result<Name<'a>> {
883 let name = if let Some(i) = self.read_digit() {
884 let i = i as usize;
885 if i >= self.memorized_names.len() {
886 return Err(self.fail("name reference too large"));
887 }
888 self.memorized_names[i].clone()
889 } else if self.consume(b"?") {
890 match self.peek() {
891 Some(b'?') => Name::ParsedName(Box::new(self.parse()?)),
892 _ => {
893 if self.consume(b"$") {
894 let name = self.read_template_name()?;
895 self.memorize_name(&name);
896 name
897 } else if self.consume(b"A") {
898 let id = if self.consume(b"0x") {
899 let mut name = String::from("0x");
900 while let Some(c) = self.read_hex_digit() {
901 name.push(c);
902 }
903 Some(name)
904 } else {
905 None
906 };
907 self.expect(b"@")?;
908 let memorize = id.is_some();
909 let name = Name::AnonymousNamespace(id);
910 if memorize {
911 self.memorize_name(&name);
912 }
913 name
914 } else if self.consume(b"Q") {
915 let name = self.read_string()?;
916 self.expect(b"@")?;
917 let name = Name::AsInterface(name);
918 self.memorize_name(&name);
919 name
920 } else {
921 let discriminator = self.read_number()?;
922 Name::Discriminator(discriminator)
923 }
924 }
925 }
926 } else {
927 // Non-template functions or classes.
928 let name = self.read_string()?;
929 let name = Name::NonTemplate(name);
930 self.memorize_name(&name);
931 name
932 };
933 Ok(name)
934 }
935
read_unqualified_name(&mut self, function: bool) -> Result<Name<'a>>936 fn read_unqualified_name(&mut self, function: bool) -> Result<Name<'a>> {
937 let name = if let Some(i) = self.read_digit() {
938 let i = i as usize;
939 if i >= self.memorized_names.len() {
940 return Err(self.fail("name reference too large"));
941 }
942 self.memorized_names[i].clone()
943 } else if self.consume(b"?$") {
944 let name = self.read_template_name()?;
945 if !function {
946 self.memorize_name(&name);
947 }
948 name
949 } else if self.consume(b"?") {
950 self.read_special_name()?
951 } else {
952 // Non-template functions or classes.
953 let name = self.read_string()?;
954 let name = Name::NonTemplate(name);
955 self.memorize_name(&name);
956 name
957 };
958 Ok(name)
959 }
960
read_scope(&mut self) -> Result<NameSequence<'a>>961 fn read_scope(&mut self) -> Result<NameSequence<'a>> {
962 let mut names = Vec::new();
963 while !self.consume(b"@") {
964 let name = self.read_nested_name()?;
965 names.push(name);
966 }
967 Ok(NameSequence { names })
968 }
969
970 // Parses a name in the form of A@B@C@@ which represents C::B::A.
read_name(&mut self, function: bool) -> Result<Symbol<'a>>971 fn read_name(&mut self, function: bool) -> Result<Symbol<'a>> {
972 let name = self.read_unqualified_name(function)?;
973 let scope = self.read_scope()?;
974
975 Ok(Symbol { name, scope })
976 }
977
read_func_qualifiers(&mut self) -> Result<StorageClass>978 fn read_func_qualifiers(&mut self) -> Result<StorageClass> {
979 let ptr64 = if self.consume(b"E") {
980 StorageClass::PTR64
981 } else {
982 StorageClass::empty()
983 };
984 let restrict = if self.consume(b"I") {
985 StorageClass::RESTRICT
986 } else {
987 StorageClass::empty()
988 };
989 let unaligned = if self.consume(b"F") {
990 StorageClass::UNALIGNED
991 } else {
992 StorageClass::empty()
993 };
994 let ref_qualifiers = match self.peek() {
995 Some(b'G') => {
996 self.expect(b"G")?;
997 StorageClass::LVALUE_QUAL
998 }
999 Some(b'H') => {
1000 self.expect(b"H")?;
1001 StorageClass::RVALUE_QUAL
1002 }
1003 _ => StorageClass::empty(),
1004 };
1005 Ok(self.read_qualifier() | ptr64 | restrict | unaligned | ref_qualifiers)
1006 }
1007
read_func_type(&mut self, read_qualifiers: bool) -> Result<Type<'a>>1008 fn read_func_type(&mut self, read_qualifiers: bool) -> Result<Type<'a>> {
1009 let sc = if read_qualifiers {
1010 self.read_func_qualifiers()?
1011 } else {
1012 StorageClass::empty()
1013 };
1014 let calling_conv = self.read_calling_conv()?;
1015 // this might have to be conditional on template context. For now
1016 // this does not cause issues. For more information see
1017 // https://github.com/mstange/msvc-demangler-rust/issues/21
1018 let var_sc = if self.consume(b"?") {
1019 self.read_storage_class()
1020 } else {
1021 StorageClass::empty()
1022 };
1023 let return_type = self.read_var_type(var_sc)?;
1024 let params = self.read_func_params()?;
1025 Ok(Type::NonMemberFunction(
1026 calling_conv,
1027 params,
1028 sc,
1029 Box::new(return_type),
1030 ))
1031 }
1032
read_special_name(&mut self) -> Result<Name<'a>>1033 fn read_special_name(&mut self) -> Result<Name<'a>> {
1034 Ok(Name::Operator(match self.get()? {
1035 b'0' => Operator::Ctor,
1036 b'1' => Operator::Dtor,
1037 b'2' => Operator::New,
1038 b'3' => Operator::Delete,
1039 b'4' => Operator::Equal,
1040 b'5' => Operator::RShift,
1041 b'6' => Operator::LShift,
1042 b'7' => Operator::Bang,
1043 b'8' => Operator::EqualEqual,
1044 b'9' => Operator::BangEqual,
1045 b'A' => Operator::Subscript,
1046 b'B' => Operator::Conversion,
1047 b'C' => Operator::Arrow,
1048 b'D' => Operator::Star,
1049 b'E' => Operator::PlusPlus,
1050 b'F' => Operator::MinusMinus,
1051 b'G' => Operator::Minus,
1052 b'H' => Operator::Plus,
1053 b'I' => Operator::Amp,
1054 b'J' => Operator::ArrowStar,
1055 b'K' => Operator::Slash,
1056 b'L' => Operator::Percent,
1057 b'M' => Operator::Less,
1058 b'N' => Operator::LessEqual,
1059 b'O' => Operator::Greater,
1060 b'P' => Operator::GreaterEqual,
1061 b'Q' => Operator::Comma,
1062 b'R' => Operator::Call,
1063 b'S' => Operator::Tilde,
1064 b'T' => Operator::Caret,
1065 b'U' => Operator::Pipe,
1066 b'V' => Operator::AmpAmp,
1067 b'W' => Operator::PipePipe,
1068 b'X' => Operator::StarEqual,
1069 b'Y' => Operator::PlusEqual,
1070 b'Z' => Operator::MinusEqual,
1071 b'_' => match self.get()? {
1072 b'0' => Operator::SlashEqual,
1073 b'1' => Operator::PercentEqual,
1074 b'2' => Operator::GreaterGreaterEqual,
1075 b'3' => Operator::LessLessEqual,
1076 b'4' => Operator::AmpEqual,
1077 b'5' => Operator::PipeEqual,
1078 b'6' => Operator::CaretEqual,
1079 b'7' => Operator::VFTable,
1080 b'8' => Operator::VBTable,
1081 b'9' => Operator::VCall,
1082 b'A' => Operator::Typeof,
1083 b'B' => Operator::LocalStaticGuard(None),
1084 b'C' => Operator::String,
1085 b'D' => Operator::VBaseDtor,
1086 b'E' => Operator::VectorDeletingDtor,
1087 b'F' => Operator::DefaultCtorClosure,
1088 b'G' => Operator::ScalarDeletingDtor,
1089 b'H' => Operator::VectorCtorIterator,
1090 b'I' => Operator::VectorDtorIterator,
1091 b'J' => Operator::VectorVBaseCtorIterator,
1092 b'K' => Operator::VirtualDisplacementMap,
1093 b'L' => Operator::EHVectorCtorIterator,
1094 b'M' => Operator::EHVectorDtorIterator,
1095 b'N' => Operator::EHVectorVBaseCtorIterator,
1096 b'O' => Operator::CopyCtorClosure,
1097 b'R' => {
1098 let c = self.get()?;
1099 match c {
1100 b'0' => {
1101 self.expect(b"?")?;
1102 let storage_class = self.read_storage_class();
1103 let t = self.read_var_type(storage_class)?;
1104 Operator::RTTITypeDescriptor(storage_class, Box::new(t))
1105 }
1106 b'1' => {
1107 let nv_offset = self.read_number()?;
1108 let vbptr_offset = self.read_number()?;
1109 let vbtable_offset = self.read_number()?;
1110 let flags = self.read_number()?;
1111 Operator::RTTIBaseClassDescriptor(
1112 nv_offset,
1113 vbptr_offset,
1114 vbtable_offset,
1115 flags,
1116 )
1117 }
1118 b'2' => Operator::RTTIBaseClassArray,
1119 b'3' => Operator::RTTIClassHierarchyDescriptor,
1120 b'4' => Operator::RTTIClassCompleteObjectLocator,
1121 _ => {
1122 return Err(self.fail("unknown RTTI Operator name"));
1123 }
1124 }
1125 }
1126 b'S' => Operator::LocalVFTable,
1127 b'T' => Operator::LocalVFTableCtorClosure,
1128 b'U' => Operator::ArrayNew,
1129 b'V' => Operator::ArrayDelete,
1130 b'X' => Operator::PlacementDeleteClosure,
1131 b'Y' => Operator::PlacementArrayDeleteClosure,
1132 b'_' => {
1133 if self.consume(b"L") {
1134 Operator::CoroutineAwait
1135 } else if self.consume(b"E") {
1136 Operator::DynamicInitializer
1137 } else if self.consume(b"F") {
1138 Operator::DynamicAtexitDtor
1139 } else if self.consume(b"J") {
1140 Operator::LocalStaticThreadGuard(None)
1141 } else if self.consume(b"K") {
1142 Operator::LiteralOperatorName // TODO: read <source-name>, that's the operator name
1143 } else {
1144 return Err(self.fail("unknown operator name"));
1145 }
1146 }
1147 _ => {
1148 return Err(self.fail("unknown operator name"));
1149 }
1150 },
1151 _ => {
1152 return Err(self.fail("unknown operator name"));
1153 }
1154 }))
1155 }
1156
read_func_class(&mut self, c: u8) -> Result<FuncClass>1157 fn read_func_class(&mut self, c: u8) -> Result<FuncClass> {
1158 // TODO: need to figure out how to wrap up the adjustment.
1159 let mut read_thunk = |func_class| -> Result<FuncClass> {
1160 let _adjustment = self.read_number()?;
1161 Ok(func_class | FuncClass::THUNK)
1162 };
1163
1164 Ok(match c {
1165 b'A' => FuncClass::PRIVATE,
1166 b'B' => FuncClass::PRIVATE | FuncClass::FAR,
1167 b'C' => FuncClass::PRIVATE | FuncClass::STATIC,
1168 b'D' => FuncClass::PRIVATE | FuncClass::STATIC,
1169 b'E' => FuncClass::PRIVATE | FuncClass::VIRTUAL,
1170 b'F' => FuncClass::PRIVATE | FuncClass::VIRTUAL,
1171 // TODO(mitsuhiko): llvm uses adjustor here instead of virtual
1172 b'G' => read_thunk(FuncClass::PRIVATE | FuncClass::VIRTUAL)?,
1173 // TODO(mitsuhiko): llvm uses adjustor here instead of virtual
1174 b'H' => read_thunk(FuncClass::PRIVATE | FuncClass::VIRTUAL | FuncClass::FAR)?,
1175 b'I' => FuncClass::PROTECTED,
1176 b'J' => FuncClass::PROTECTED | FuncClass::FAR,
1177 b'K' => FuncClass::PROTECTED | FuncClass::STATIC,
1178 b'L' => FuncClass::PROTECTED | FuncClass::STATIC | FuncClass::FAR,
1179 b'M' => FuncClass::PROTECTED | FuncClass::VIRTUAL,
1180 b'N' => FuncClass::PROTECTED | FuncClass::VIRTUAL | FuncClass::FAR,
1181 // TODO(mitsuhiko): llvm uses adjustor here instead of virtual
1182 b'O' => read_thunk(FuncClass::PROTECTED | FuncClass::VIRTUAL)?,
1183 // TODO(mitsuhiko): llvm uses adjustor here instead of virtual
1184 b'P' => read_thunk(FuncClass::PROTECTED | FuncClass::VIRTUAL | FuncClass::FAR)?,
1185 b'Q' => FuncClass::PUBLIC,
1186 b'R' => FuncClass::PUBLIC | FuncClass::FAR,
1187 b'S' => FuncClass::PUBLIC | FuncClass::STATIC,
1188 b'T' => FuncClass::PUBLIC | FuncClass::STATIC | FuncClass::FAR,
1189 b'U' => FuncClass::PUBLIC | FuncClass::VIRTUAL,
1190 b'V' => FuncClass::PUBLIC | FuncClass::VIRTUAL | FuncClass::FAR,
1191 // TODO(mitsuhiko): llvm uses adjustor here instead of virtual
1192 b'W' => read_thunk(FuncClass::PUBLIC | FuncClass::VIRTUAL)?,
1193 // TODO(mitsuhiko): llvm uses adjustor here instead of virtual
1194 b'X' => read_thunk(FuncClass::PUBLIC | FuncClass::VIRTUAL | FuncClass::FAR)?,
1195 b'Y' => FuncClass::GLOBAL,
1196 b'Z' => FuncClass::GLOBAL | FuncClass::FAR,
1197 _ => {
1198 return Err(self.fail("unknown func class"));
1199 }
1200 })
1201 }
1202
read_qualifier(&mut self) -> StorageClass1203 fn read_qualifier(&mut self) -> StorageClass {
1204 let access_class = match self.peek() {
1205 Some(b'A') => StorageClass::empty(),
1206 Some(b'B') => StorageClass::CONST,
1207 Some(b'C') => StorageClass::VOLATILE,
1208 Some(b'D') => StorageClass::CONST | StorageClass::VOLATILE,
1209 Some(b'Q') => StorageClass::empty(),
1210 Some(b'R') => StorageClass::CONST,
1211 Some(b'S') => StorageClass::VOLATILE,
1212 Some(b'T') => StorageClass::CONST | StorageClass::VOLATILE,
1213 _ => return StorageClass::empty(),
1214 };
1215 self.advance(1);
1216 access_class
1217 }
1218
read_calling_conv(&mut self) -> Result<CallingConv>1219 fn read_calling_conv(&mut self) -> Result<CallingConv> {
1220 Ok(match self.get()? {
1221 b'A' => CallingConv::Cdecl,
1222 b'B' => CallingConv::Cdecl,
1223 b'C' => CallingConv::Pascal,
1224 b'E' => CallingConv::Thiscall,
1225 b'G' => CallingConv::Stdcall,
1226 b'I' => CallingConv::Fastcall,
1227 _ => {
1228 return Err(self.fail("unknown calling conv"));
1229 }
1230 })
1231 }
1232
1233 // <return-type> ::= <type>
1234 // ::= @ # structors (they have no declared return type)
read_func_return_type(&mut self, storage_class: StorageClass) -> Result<Type<'a>>1235 fn read_func_return_type(&mut self, storage_class: StorageClass) -> Result<Type<'a>> {
1236 if self.consume(b"@") {
1237 Ok(Type::None)
1238 } else {
1239 self.read_var_type(storage_class)
1240 }
1241 }
1242
read_storage_class(&mut self) -> StorageClass1243 fn read_storage_class(&mut self) -> StorageClass {
1244 let storage_class = match self.peek() {
1245 Some(b'A') => StorageClass::empty(),
1246 Some(b'B') => StorageClass::CONST,
1247 Some(b'C') => StorageClass::VOLATILE,
1248 Some(b'D') => StorageClass::CONST | StorageClass::VOLATILE,
1249 Some(b'E') => StorageClass::FAR,
1250 Some(b'F') => StorageClass::CONST | StorageClass::FAR,
1251 Some(b'G') => StorageClass::VOLATILE | StorageClass::FAR,
1252 Some(b'H') => StorageClass::CONST | StorageClass::VOLATILE | StorageClass::FAR,
1253 Some(b'Q') => StorageClass::empty(),
1254 Some(b'R') => StorageClass::CONST,
1255 Some(b'S') => StorageClass::VOLATILE,
1256 Some(b'T') => StorageClass::CONST | StorageClass::VOLATILE,
1257 _ => return StorageClass::empty(),
1258 };
1259 self.advance(1);
1260 storage_class
1261 }
1262
read_storage_class_for_return(&mut self) -> Result<StorageClass>1263 fn read_storage_class_for_return(&mut self) -> Result<StorageClass> {
1264 if !self.consume(b"?") {
1265 return Ok(StorageClass::empty());
1266 }
1267
1268 Ok(match self.get()? {
1269 b'A' => StorageClass::empty(),
1270 b'B' => StorageClass::CONST,
1271 b'C' => StorageClass::VOLATILE,
1272 b'D' => StorageClass::CONST | StorageClass::VOLATILE,
1273 _ => {
1274 return Err(self.fail("unknown storage class"));
1275 }
1276 })
1277 }
1278
read_member_function_pointer(&mut self, read_qualifiers: bool) -> Result<Type<'a>>1279 fn read_member_function_pointer(&mut self, read_qualifiers: bool) -> Result<Type<'a>> {
1280 let symbol = self.read_name(true)?;
1281 let ptr64 = if self.consume(b"E") {
1282 StorageClass::PTR64
1283 } else {
1284 StorageClass::empty()
1285 };
1286 let (access_class, func_class) = if read_qualifiers {
1287 (self.read_qualifier() | ptr64, FuncClass::empty())
1288 } else {
1289 let c = self.get()?;
1290 (ptr64, self.read_func_class(c)?)
1291 };
1292 let calling_conv = self.read_calling_conv()?;
1293 let storage_class_for_return = self.read_storage_class_for_return()?;
1294 let return_type = self.read_func_return_type(storage_class_for_return)?;
1295 let params = self.read_func_params()?;
1296 Ok(Type::MemberFunctionPointer(
1297 symbol,
1298 func_class,
1299 calling_conv,
1300 params,
1301 access_class,
1302 Box::new(return_type),
1303 ))
1304 }
1305
1306 // Reads a variable type.
read_var_type(&mut self, mut sc: StorageClass) -> Result<Type<'a>>1307 fn read_var_type(&mut self, mut sc: StorageClass) -> Result<Type<'a>> {
1308 if self.consume(b"W4") {
1309 let name = self.read_name(false)?;
1310 return Ok(Type::Enum(name, sc));
1311 }
1312
1313 if self.consume(b"A6") {
1314 let func_type = self.read_func_type(false)?;
1315 return Ok(Type::Ref(Box::new(func_type), sc));
1316 }
1317
1318 if self.consume(b"P6") {
1319 let func_type = self.read_func_type(false)?;
1320 return Ok(Type::Ptr(Box::new(func_type), sc));
1321 }
1322
1323 if self.consume(b"P8") {
1324 return self.read_member_function_pointer(true);
1325 }
1326
1327 if self.consume(b"$") {
1328 if self.consume(b"0") {
1329 let n = self.read_number()?;
1330 return Ok(Type::Constant(n));
1331 }
1332 if self.consume(b"D") {
1333 let n = self.read_number()?;
1334 return Ok(Type::TemplateParameterWithIndex(n));
1335 }
1336 if self.consume(b"$BY") {
1337 return self.read_array();
1338 }
1339 if self.consume(b"$Q") {
1340 return Ok(Type::RValueRef(Box::new(self.read_pointee()?), sc));
1341 }
1342 if self.consume(b"S")
1343 || self.consume(b"$V")
1344 || self.consume(b"$Z")
1345 || self.consume(b"$$V")
1346 {
1347 return Ok(Type::EmptyParameterPack);
1348 }
1349 if self.consume(b"$T") {
1350 return Ok(Type::Nullptr);
1351 }
1352 if self.consume(b"$A6") {
1353 return self.read_func_type(false);
1354 }
1355 if self.consume(b"$A8@@") {
1356 return self.read_func_type(true);
1357 }
1358 if self.consume(b"$Y") {
1359 let name = self.read_name(true)?;
1360 return Ok(Type::Alias(name, sc));
1361 }
1362 // These next cases can fallthrough, so be careful adding new ones!
1363 if self.consume(b"$C") {
1364 sc = self.read_qualifier();
1365 } else if let Some(x) = self.peek() {
1366 match x {
1367 // Inheritance specifiers, which we don't need to remember.
1368 b'1' | b'H' | b'I' | b'J' => {
1369 self.advance(1);
1370 self.expect(b"?")?;
1371 return self.read_member_function_pointer(false);
1372 }
1373 _ => {}
1374 };
1375 }
1376 }
1377
1378 if self.consume(b"?") {
1379 let n = self.read_number()?;
1380 return Ok(Type::TemplateParameterWithIndex(-n));
1381 }
1382
1383 if let Some(n) = self.read_digit() {
1384 if n as usize >= self.memorized_types.len() {
1385 return Err(self.fail_args(format_args!("invalid backreference: {}", n)));
1386 }
1387
1388 return Ok(self.memorized_types[n as usize].clone());
1389 }
1390
1391 Ok(match self.get()? {
1392 b'T' => Type::Union(self.read_name(false)?, sc),
1393 b'U' => Type::Struct(self.read_name(false)?, sc),
1394 b'V' => Type::Class(self.read_name(false)?, sc),
1395 b'A' => Type::Ref(Box::new(self.read_pointee()?), sc),
1396 b'B' => Type::Ref(Box::new(self.read_pointee()?), StorageClass::VOLATILE),
1397 b'P' => Type::Ptr(Box::new(self.read_pointee()?), sc),
1398 b'Q' => Type::Ptr(Box::new(self.read_pointee()?), StorageClass::CONST),
1399 b'R' => Type::Ptr(Box::new(self.read_pointee()?), StorageClass::VOLATILE),
1400 b'S' => Type::Ptr(
1401 Box::new(self.read_pointee()?),
1402 StorageClass::CONST | StorageClass::VOLATILE,
1403 ),
1404 b'Y' => self.read_array()?,
1405 b'X' => Type::Void(sc),
1406 b'D' => Type::Char(sc),
1407 b'C' => Type::Schar(sc),
1408 b'E' => Type::Uchar(sc),
1409 b'F' => Type::Short(sc),
1410 b'G' => Type::Ushort(sc),
1411 b'H' => Type::Int(sc),
1412 b'I' => Type::Uint(sc),
1413 b'J' => Type::Long(sc),
1414 b'K' => Type::Ulong(sc),
1415 b'M' => Type::Float(sc),
1416 b'N' => Type::Double(sc),
1417 b'O' => Type::Ldouble(sc),
1418 b'_' => match self.get()? {
1419 b'N' => Type::Bool(sc),
1420 b'J' => Type::Int64(sc),
1421 b'K' => Type::Uint64(sc),
1422 b'L' => Type::Int128(sc),
1423 b'M' => Type::Uint128(sc),
1424 b'W' => Type::Wchar(sc),
1425 b'Q' => Type::Char8(sc),
1426 b'S' => Type::Char16(sc),
1427 b'U' => Type::Char32(sc),
1428 _ => {
1429 return Err(self.fail("unknown primitive type"));
1430 }
1431 },
1432 _c => {
1433 return Err(self.fail("unknown primitive type"));
1434 }
1435 })
1436 }
1437
read_pointee(&mut self) -> Result<Type<'a>>1438 fn read_pointee(&mut self) -> Result<Type<'a>> {
1439 let ptr64 = if self.consume(b"E") {
1440 StorageClass::PTR64
1441 } else {
1442 StorageClass::empty()
1443 };
1444 let storage_class = self.read_storage_class();
1445 self.read_var_type(storage_class | ptr64)
1446 }
1447
read_array(&mut self) -> Result<Type<'a>>1448 fn read_array(&mut self) -> Result<Type<'a>> {
1449 let dimension = self.read_number()?;
1450 if dimension <= 0 {
1451 return Err(self.fail_args(format_args!("invalid array dimension: {}", dimension)));
1452 }
1453 let (array, _) = self.read_nested_array(dimension)?;
1454 Ok(array)
1455 }
1456
read_nested_array(&mut self, dimension: i32) -> Result<(Type<'a>, StorageClass)>1457 fn read_nested_array(&mut self, dimension: i32) -> Result<(Type<'a>, StorageClass)> {
1458 if dimension > 0 {
1459 let len = self.read_number()?;
1460 let (inner_array, storage_class) = self.read_nested_array(dimension - 1)?;
1461 Ok((
1462 Type::Array(len, Box::new(inner_array), storage_class),
1463 storage_class,
1464 ))
1465 } else {
1466 let storage_class = if self.consume(b"$$C") {
1467 if self.consume(b"B") {
1468 StorageClass::CONST
1469 } else if self.consume(b"C") || self.consume(b"D") {
1470 StorageClass::CONST | StorageClass::VOLATILE
1471 } else if !self.consume(b"A") {
1472 return Err(self.fail("unknown storage class"));
1473 } else {
1474 StorageClass::empty()
1475 }
1476 } else {
1477 StorageClass::empty()
1478 };
1479
1480 Ok((self.read_var_type(StorageClass::empty())?, storage_class))
1481 }
1482 }
1483
1484 // Reads a function or a template parameters.
read_params(&mut self) -> Result<Params<'a>>1485 fn read_params(&mut self) -> Result<Params<'a>> {
1486 // println!("read_params on {}", str::from_utf8(self.input)?);
1487 // Within the same parameter list, you can backreference the first 10 types.
1488 // let mut backref: Vec<Type<'a>> = Vec::with_capacity(10);
1489
1490 let mut params: Vec<Type<'a>> = Vec::new();
1491
1492 while !self.remaining.starts_with(b"@")
1493 && !self.remaining.starts_with(b"Z")
1494 && !self.remaining.is_empty()
1495 {
1496 if let Some(n) = self.read_digit() {
1497 if n as usize >= self.memorized_types.len() {
1498 return Err(self.fail_args(format_args!("invalid backreference: {}", n)));
1499 }
1500 // println!("reading a type from memorized_types[{}]. full list: {:#?}", n, self.memorized_types);
1501 params.push(self.memorized_types[n as usize].clone());
1502 continue;
1503 }
1504
1505 let len = self.remaining.len();
1506
1507 let param_type = self.read_var_type(StorageClass::empty())?;
1508
1509 // Single-letter types are ignored for backreferences because
1510 // memorizing them doesn't save anything.
1511 if len - self.remaining.len() > 1 {
1512 self.memorize_type(¶m_type);
1513 }
1514 params.push(param_type);
1515 }
1516
1517 if self.consume(b"Z") {
1518 params.push(Type::VarArgs);
1519 } else if self.remaining.is_empty() {
1520 // this is needed to handle the weird standalone template manglings
1521 } else {
1522 self.expect(b"@")?;
1523 }
1524 Ok(Params { types: params })
1525 }
1526
1527 // Reads a function parameters.
read_func_params(&mut self) -> Result<Params<'a>>1528 fn read_func_params(&mut self) -> Result<Params<'a>> {
1529 let params = if self.consume(b"X") {
1530 Params {
1531 types: vec![Type::Void(StorageClass::empty())],
1532 }
1533 } else {
1534 self.read_params()?
1535 };
1536
1537 self.expect(b"Z")?;
1538
1539 Ok(params)
1540 }
1541 }
1542
demangle(input: &str, flags: DemangleFlags) -> Result<String>1543 pub fn demangle(input: &str, flags: DemangleFlags) -> Result<String> {
1544 serialize(&parse(input)?, flags)
1545 }
1546
parse(input: &str) -> Result<ParseResult>1547 pub fn parse(input: &str) -> Result<ParseResult> {
1548 let mut state = ParserState {
1549 remaining: input.as_bytes(),
1550 input,
1551 offset: 0,
1552 memorized_names: Vec::with_capacity(10),
1553 memorized_types: Vec::with_capacity(10),
1554 };
1555 state.parse()
1556 }
1557
serialize(input: &ParseResult, flags: DemangleFlags) -> Result<String>1558 pub fn serialize(input: &ParseResult, flags: DemangleFlags) -> Result<String> {
1559 let mut s = Vec::new();
1560 {
1561 let mut serializer = Serializer { flags, w: &mut s };
1562 serializer.serialize(&input)?;
1563 }
1564 Ok(String::from_utf8(s)?)
1565 }
1566
1567 // Converts an AST to a string.
1568 //
1569 // Converting an AST representing a C++ type to a string is tricky due
1570 // to the bad grammar of the C++ declaration inherited from C. You have
1571 // to construct a string from inside to outside. For example, if a type
1572 // X is a pointer to a function returning int, the order you create a
1573 // string becomes something like this:
1574 //
1575 // (1) X is a pointer: *X
1576 // (2) (1) is a function returning int: int (*X)()
1577 //
1578 // So you cannot construct a result just by appending strings to a result.
1579 //
1580 // To deal with this, we split the function into two. write_pre() writes
1581 // the "first half" of type declaration, and write_post() writes the
1582 // "second half". For example, write_pre() writes a return type for a
1583 // function and write_post() writes an parameter list.
1584 struct Serializer<'a> {
1585 flags: DemangleFlags,
1586 w: &'a mut Vec<u8>,
1587 }
1588
1589 impl<'a> Serializer<'a> {
serialize(&mut self, parse_result: &ParseResult) -> Result<()>1590 fn serialize(&mut self, parse_result: &ParseResult) -> Result<()> {
1591 if !self
1592 .flags
1593 .intersects(DemangleFlags::NAME_ONLY | DemangleFlags::NO_FUNCTION_RETURNS)
1594 {
1595 self.write_pre(&parse_result.symbol_type)?;
1596 }
1597 self.write_name(&parse_result.symbol, Some(&parse_result.symbol_type))?;
1598 if !self.flags.contains(DemangleFlags::NAME_ONLY) {
1599 self.write_post(&parse_result.symbol_type)?;
1600 }
1601 Ok(())
1602 }
1603
write_calling_conv(&mut self, calling_conv: CallingConv) -> Result<()>1604 fn write_calling_conv(&mut self, calling_conv: CallingConv) -> Result<()> {
1605 match self.w.last() {
1606 Some(b' ') | Some(b'(') => {}
1607 _ => write!(self.w, " ")?,
1608 }
1609 if !self.flags.contains(DemangleFlags::NO_MS_KEYWORDS) {
1610 match calling_conv {
1611 CallingConv::Cdecl => {
1612 write!(self.w, "__cdecl ")?;
1613 }
1614 CallingConv::Pascal => {
1615 write!(self.w, "__pascal ")?;
1616 }
1617 CallingConv::Thiscall => {
1618 write!(self.w, "__thiscall ")?;
1619 }
1620 CallingConv::Stdcall => {
1621 write!(self.w, "__stdcall ")?;
1622 }
1623 CallingConv::Fastcall => {
1624 write!(self.w, "__fastcall ")?;
1625 }
1626 CallingConv::_Regcall => {
1627 write!(self.w, "__regcall ")?;
1628 }
1629 };
1630 }
1631
1632 Ok(())
1633 }
1634
1635 // Write the "first half" of a given type.
write_pre(&mut self, t: &Type) -> Result<()>1636 fn write_pre(&mut self, t: &Type) -> Result<()> {
1637 let storage_class = match *t {
1638 Type::None => return Ok(()),
1639 Type::MemberFunction(func_class, calling_conv, _, _, ref inner) => {
1640 if func_class.contains(FuncClass::THUNK) {
1641 write!(self.w, "[thunk]: ")?
1642 }
1643 if !self.flags.contains(DemangleFlags::NO_ACCESS_SPECIFIERS) {
1644 if func_class.contains(FuncClass::PRIVATE) {
1645 write!(self.w, "private: ")?
1646 }
1647 if func_class.contains(FuncClass::PROTECTED) {
1648 write!(self.w, "protected: ")?
1649 }
1650 if func_class.contains(FuncClass::PUBLIC) {
1651 write!(self.w, "public: ")?
1652 }
1653 }
1654 if !self.flags.contains(DemangleFlags::NO_MEMBER_TYPE) {
1655 if func_class.contains(FuncClass::STATIC) {
1656 write!(self.w, "static ")?
1657 }
1658 if func_class.contains(FuncClass::VIRTUAL) {
1659 write!(self.w, "virtual ")?;
1660 }
1661 }
1662 self.write_pre(inner)?;
1663 self.write_calling_conv(calling_conv)?;
1664 return Ok(());
1665 }
1666 Type::MemberFunctionPointer(ref symbol, _, calling_conv, _, _, ref inner) => {
1667 self.write_pre(inner)?;
1668 self.write_space()?;
1669 write!(self.w, "(")?;
1670 self.write_calling_conv(calling_conv)?;
1671 self.write_space()?;
1672 self.write_space()?;
1673 self.write_name(symbol, None)?;
1674 write!(self.w, "::*")?;
1675 return Ok(());
1676 }
1677 Type::NonMemberFunction(calling_conv, _, _, ref inner) => {
1678 self.write_pre(inner)?;
1679 self.write_calling_conv(calling_conv)?;
1680 return Ok(());
1681 }
1682 Type::VCallThunk(_, calling_conv) => {
1683 write!(self.w, "[thunk]: ")?;
1684 self.write_calling_conv(calling_conv)?;
1685 return Ok(());
1686 }
1687 Type::CXXVBTable(_, sc) => sc,
1688 Type::CXXVFTable(_, sc) => sc,
1689 Type::TemplateParameterWithIndex(n) => {
1690 write!(self.w, "`template-parameter{}'", n)?;
1691 return Ok(());
1692 }
1693 Type::ThreadSafeStaticGuard(num) => {
1694 write!(self.w, "TSS{}", num)?;
1695 return Ok(());
1696 }
1697 Type::Constant(n) => {
1698 write!(self.w, "{}", n)?;
1699 return Ok(());
1700 }
1701 Type::ConstantString(_) => {
1702 // We have no idea what the original encoding of the string is,
1703 // and undname doesn't even try to display anything.
1704 //match str::from_utf8(s).ok() {
1705 // Some(ref s) => write!(self.w, "{}", s)?,
1706 // None => {},
1707 //}
1708 return Ok(());
1709 }
1710 Type::VarArgs => {
1711 write!(self.w, "...")?;
1712 return Ok(());
1713 }
1714 Type::Ptr(ref inner, storage_class)
1715 | Type::Ref(ref inner, storage_class)
1716 | Type::RValueRef(ref inner, storage_class) => {
1717 // "[]" and "()" (for function parameters) take precedence over "*",
1718 // so "int *x(int)" means "x is a function returning int *". We need
1719 // parentheses to supercede the default precedence. (e.g. we want to
1720 // emit something like "int (*x)(int)".)
1721 match *inner.as_ref() {
1722 Type::MemberFunction(_, calling_conv, _, _, ref inner)
1723 | Type::NonMemberFunction(calling_conv, _, _, ref inner) => {
1724 self.write_pre(inner)?;
1725 self.write_space()?;
1726 write!(self.w, "(")?;
1727 self.write_calling_conv(calling_conv)?;
1728 }
1729 Type::Array(_, _, _) => {
1730 self.write_pre(inner)?;
1731 self.write_space()?;
1732 write!(self.w, "(")?;
1733 }
1734 _ => {
1735 self.write_pre(inner)?;
1736 }
1737 }
1738
1739 match *t {
1740 Type::Ptr(_, _) => {
1741 if !self.flags.contains(DemangleFlags::HUG_TYPE) {
1742 self.write_space()?;
1743 } else if self.flags.contains(DemangleFlags::SPACE_BEFORE_POINTER) {
1744 self.write_space_ptr()?;
1745 }
1746 write!(self.w, "*")?
1747 }
1748 Type::Ref(_, _) => {
1749 if !self.flags.contains(DemangleFlags::HUG_TYPE) {
1750 self.write_space()?;
1751 } else if self.flags.contains(DemangleFlags::SPACE_BEFORE_POINTER) {
1752 self.write_space_ptr()?;
1753 }
1754 write!(self.w, "&")?
1755 }
1756 Type::RValueRef(_, _) => {
1757 if !self.flags.contains(DemangleFlags::HUG_TYPE) {
1758 self.write_space()?;
1759 } else if self.flags.contains(DemangleFlags::SPACE_BEFORE_POINTER) {
1760 self.write_space_ptr()?;
1761 }
1762 write!(self.w, "&&")?
1763 }
1764 _ => {}
1765 }
1766
1767 storage_class
1768 }
1769 Type::Array(_len, ref inner, storage_class) => {
1770 self.write_pre(inner)?;
1771 storage_class
1772 }
1773 Type::Var(ref inner, kind, sc) => {
1774 match kind {
1775 VarStorageKind::PrivateStatic => write!(self.w, "private: static ")?,
1776 VarStorageKind::ProtectedStatic => write!(self.w, "protected: static ")?,
1777 VarStorageKind::PublicStatic => write!(self.w, "public: static ")?,
1778 VarStorageKind::Global | VarStorageKind::FunctionLocalStatic => {}
1779 }
1780 self.write_pre(inner)?;
1781 sc
1782 }
1783 Type::Alias(ref names, sc) => {
1784 self.write_name(names, None)?;
1785 sc
1786 }
1787 Type::Struct(ref names, sc) => {
1788 self.write_class(names, "struct")?;
1789 sc
1790 }
1791 Type::Union(ref names, sc) => {
1792 self.write_class(names, "union")?;
1793 sc
1794 }
1795 Type::Class(ref names, sc) => {
1796 self.write_class(names, "class")?;
1797 sc
1798 }
1799 Type::Enum(ref names, sc) => {
1800 self.write_class(names, "enum")?;
1801 sc
1802 }
1803 Type::Void(sc) => {
1804 write!(self.w, "void")?;
1805 sc
1806 }
1807 Type::Bool(sc) => {
1808 write!(self.w, "bool")?;
1809 sc
1810 }
1811 Type::Char(sc) => {
1812 write!(self.w, "char")?;
1813 sc
1814 }
1815 Type::Schar(sc) => {
1816 write!(self.w, "signed char")?;
1817 sc
1818 }
1819 Type::Uchar(sc) => {
1820 write!(self.w, "unsigned char")?;
1821 sc
1822 }
1823 Type::Short(sc) => {
1824 write!(self.w, "short")?;
1825 sc
1826 }
1827 Type::Ushort(sc) => {
1828 write!(self.w, "unsigned short")?;
1829 sc
1830 }
1831 Type::Int(sc) => {
1832 write!(self.w, "int")?;
1833 sc
1834 }
1835 Type::Uint(sc) => {
1836 write!(self.w, "unsigned int")?;
1837 sc
1838 }
1839 Type::Long(sc) => {
1840 write!(self.w, "long")?;
1841 sc
1842 }
1843 Type::Ulong(sc) => {
1844 write!(self.w, "unsigned long")?;
1845 sc
1846 }
1847 Type::Int64(sc) => {
1848 if self.flags.contains(DemangleFlags::MS_TYPENAMES) {
1849 write!(self.w, "__int64")?;
1850 } else {
1851 write!(self.w, "int64_t")?;
1852 }
1853 sc
1854 }
1855 Type::Uint64(sc) => {
1856 if self.flags.contains(DemangleFlags::MS_TYPENAMES) {
1857 write!(self.w, "unsigned __int64")?;
1858 } else {
1859 write!(self.w, "uint64_t")?;
1860 }
1861 sc
1862 }
1863 Type::Int128(sc) => {
1864 if self.flags.contains(DemangleFlags::MS_TYPENAMES) {
1865 write!(self.w, "__int128")?;
1866 } else {
1867 write!(self.w, "int128_t")?;
1868 }
1869 sc
1870 }
1871 Type::Uint128(sc) => {
1872 if self.flags.contains(DemangleFlags::MS_TYPENAMES) {
1873 write!(self.w, "unsigned __int128")?;
1874 } else {
1875 write!(self.w, "uint128_t")?;
1876 }
1877 sc
1878 }
1879 Type::Wchar(sc) => {
1880 write!(self.w, "wchar_t")?;
1881 sc
1882 }
1883 Type::Float(sc) => {
1884 write!(self.w, "float")?;
1885 sc
1886 }
1887 Type::Double(sc) => {
1888 write!(self.w, "double")?;
1889 sc
1890 }
1891 Type::Ldouble(sc) => {
1892 write!(self.w, "long double")?;
1893 sc
1894 }
1895 Type::Char8(sc) => {
1896 write!(self.w, "char8_t")?;
1897 sc
1898 }
1899 Type::Char16(sc) => {
1900 write!(self.w, "char16_t")?;
1901 sc
1902 }
1903 Type::Char32(sc) => {
1904 write!(self.w, "char32_t")?;
1905 sc
1906 }
1907 Type::Nullptr => {
1908 write!(self.w, "std::nullptr_t")?;
1909 return Ok(());
1910 }
1911 Type::EmptyParameterPack => return Ok(()),
1912 Type::RTTIType => return Ok(()),
1913 };
1914
1915 if storage_class.contains(StorageClass::CONST) {
1916 if self.flags.contains(DemangleFlags::SPACE_BEFORE_POINTER) {
1917 self.write_space_ptr()?;
1918 } else {
1919 self.write_space()?;
1920 }
1921 write!(self.w, "const")?;
1922 }
1923 if storage_class.contains(StorageClass::VOLATILE) {
1924 if self.flags.contains(DemangleFlags::SPACE_BEFORE_POINTER) {
1925 self.write_space_ptr()?;
1926 } else {
1927 self.write_space()?;
1928 }
1929 write!(self.w, "volatile")?;
1930 }
1931
1932 Ok(())
1933 }
1934
write_memfn_qualifiers(&mut self, sc: StorageClass) -> Result<()>1935 fn write_memfn_qualifiers(&mut self, sc: StorageClass) -> Result<()> {
1936 let with_ptr64 = self.flags.contains(DemangleFlags::WITH_PTR64);
1937 if self.flags.contains(DemangleFlags::NO_THISTYPE) {
1938 // TODO: should probably check for NO_CV_THISTYPE and NO_MS_THISTYPE
1939 // separately but I don't know what exactly those affect.
1940 return Ok(());
1941 }
1942 let mut write_one_qual = |flag, s| -> Result<()> {
1943 if sc.contains(flag) {
1944 self.write_space()?;
1945 self.w.write_all(s)?;
1946 }
1947
1948 Ok(())
1949 };
1950
1951 write_one_qual(StorageClass::CONST, b"const")?;
1952 write_one_qual(StorageClass::VOLATILE, b"volatile")?;
1953 if with_ptr64 {
1954 write_one_qual(StorageClass::PTR64, b"__ptr64")?;
1955 }
1956 // __restrict is different than `restrict`, keep the underscores!
1957 write_one_qual(StorageClass::RESTRICT, b"__restrict")?;
1958 // TODO: undname prints ref-qualifiers tightly to previous qualifiers.
1959 write_one_qual(StorageClass::LVALUE_QUAL, b"&")?;
1960 write_one_qual(StorageClass::RVALUE_QUAL, b"&&")?;
1961
1962 Ok(())
1963 }
1964
1965 // Write the "second half" of a given type.
write_post(&mut self, t: &Type) -> Result<()>1966 fn write_post(&mut self, t: &Type) -> Result<()> {
1967 match *t {
1968 Type::MemberFunction(_, _, ref params, sc, ref return_type)
1969 | Type::NonMemberFunction(_, ref params, sc, ref return_type) => {
1970 write!(self.w, "(")?;
1971 self.write_types(¶ms.types)?;
1972 write!(self.w, ")")?;
1973
1974 self.write_memfn_qualifiers(sc)?;
1975 self.write_post(return_type)?;
1976 }
1977 Type::MemberFunctionPointer(_, _, _, ref params, sc, ref return_type) => {
1978 write!(self.w, ")(")?;
1979 self.write_types(¶ms.types)?;
1980 write!(self.w, ")")?;
1981
1982 self.write_post(return_type)?;
1983
1984 if sc.contains(StorageClass::CONST) {
1985 self.write_space()?;
1986 write!(self.w, "const")?;
1987 }
1988 }
1989 Type::CXXVBTable(ref names, _sc) => {
1990 self.write_scope(names)?;
1991 write!(self.w, "\'}}")?; // the rest of the "operator"
1992 }
1993 Type::Ptr(ref inner, _sc) | Type::Ref(ref inner, _sc) => {
1994 match *inner.as_ref() {
1995 Type::MemberFunction(_, _, _, _, _)
1996 | Type::NonMemberFunction(_, _, _, _)
1997 | Type::Array(_, _, _) => {
1998 write!(self.w, ")")?;
1999 }
2000 _ => {}
2001 }
2002 self.write_post(inner)?;
2003 }
2004 Type::Array(len, ref inner, _sc) => {
2005 write!(self.w, "[{}]", len)?;
2006 self.write_post(inner)?;
2007 }
2008 Type::Var(ref inner, _kind, _sc) => {
2009 self.write_post(inner)?;
2010 }
2011 Type::CXXVFTable(ref names, _) => {
2012 if !names.names.is_empty() {
2013 write!(self.w, "{{for `")?;
2014 self.write_scope(names)?;
2015 self.w.write_all(b"'}")?;
2016 }
2017 }
2018 Type::VCallThunk(offset, _) => {
2019 write!(self.w, "{{{},", offset)?;
2020 if self.flags.contains(DemangleFlags::SPACE_AFTER_COMMA) {
2021 write!(self.w, " ")?;
2022 }
2023 write!(self.w, "{{flat}}}}")?;
2024 }
2025 _ => {}
2026 }
2027 Ok(())
2028 }
2029
2030 // Write a function or template parameter list.
write_types(&mut self, types: &[Type]) -> Result<()>2031 fn write_types(&mut self, types: &[Type]) -> Result<()> {
2032 for (idx, param) in types
2033 .iter()
2034 .filter(|x| **x != Type::EmptyParameterPack)
2035 .enumerate()
2036 {
2037 if idx > 0 {
2038 write!(self.w, ",")?;
2039 if self.flags.contains(DemangleFlags::SPACE_AFTER_COMMA) {
2040 write!(self.w, " ")?;
2041 }
2042 }
2043 self.write_pre(param)?;
2044 self.write_post(param)?;
2045 }
2046 Ok(())
2047 }
2048
write_class(&mut self, names: &Symbol, s: &str) -> Result<()>2049 fn write_class(&mut self, names: &Symbol, s: &str) -> Result<()> {
2050 if !self.flags.contains(DemangleFlags::NO_CLASS_TYPE) {
2051 write!(self.w, "{}", s)?;
2052 write!(self.w, " ")?;
2053 }
2054 self.write_name(names, None)?;
2055 Ok(())
2056 }
2057
write_space_pre(&mut self) -> Result<()>2058 fn write_space_pre(&mut self) -> Result<()> {
2059 if let Some(&c) = self.w.last() {
2060 if char::from(c).is_ascii_alphabetic() || c == b'&' || c == b'>' || c == b')' {
2061 write!(self.w, " ")?;
2062 }
2063 }
2064 Ok(())
2065 }
2066
write_space_ptr(&mut self) -> Result<()>2067 fn write_space_ptr(&mut self) -> Result<()> {
2068 if let Some(&c) = self.w.last() {
2069 if char::from(c).is_ascii_alphabetic() || c == b'>' || c == b')' {
2070 write!(self.w, " ")?;
2071 }
2072 }
2073 Ok(())
2074 }
2075
write_space(&mut self) -> Result<()>2076 fn write_space(&mut self) -> Result<()> {
2077 if let Some(&c) = self.w.last() {
2078 if char::from(c).is_ascii_alphabetic()
2079 || c == b'*'
2080 || c == b'&'
2081 || c == b'>'
2082 || c == b')'
2083 {
2084 write!(self.w, " ")?;
2085 }
2086 }
2087 Ok(())
2088 }
2089
write_operator_name(&mut self, op: &Operator) -> Result<()>2090 fn write_operator_name(&mut self, op: &Operator) -> Result<()> {
2091 let s = match *op {
2092 Operator::Ctor => "ctor",
2093 Operator::Dtor => "dtor",
2094 Operator::New => "operator new",
2095 Operator::Delete => "operator delete",
2096 Operator::Equal => "operator=",
2097 Operator::RShift => "operator>>",
2098 Operator::LShift => "operator<<",
2099 Operator::Bang => "operator!",
2100 Operator::EqualEqual => "operator==",
2101 Operator::BangEqual => "operator!=",
2102 Operator::Subscript => "operator[]",
2103
2104 // this is special cased for most situations unless demangling
2105 // produced something really wacky
2106 Operator::Conversion => "operatorcast",
2107 Operator::Arrow => "operator->",
2108 Operator::Star => "operator*",
2109 Operator::PlusPlus => "operator++",
2110 Operator::MinusMinus => "operator--",
2111 Operator::Minus => "operator-",
2112 Operator::Plus => "operator+",
2113 Operator::Amp => "operator&",
2114 Operator::ArrowStar => "operator->*",
2115 Operator::Slash => "operator/",
2116 Operator::Percent => "operator%",
2117 Operator::Less => "operator<",
2118 Operator::LessEqual => "operator<=",
2119 Operator::Greater => "operator>",
2120 Operator::GreaterEqual => "operator>=",
2121 Operator::Comma => "operator,",
2122 Operator::Call => "operator()",
2123 Operator::Tilde => "operator~",
2124 Operator::Caret => "operator^",
2125 Operator::Pipe => "operator|",
2126 Operator::AmpAmp => "operator&&",
2127 Operator::PipePipe => "operator||",
2128 Operator::StarEqual => "operator*=",
2129 Operator::PlusEqual => "operator+=",
2130 Operator::MinusEqual => "operator-=",
2131 Operator::SlashEqual => "operator/=",
2132 Operator::PercentEqual => "operator%=",
2133 Operator::GreaterGreaterEqual => "operator>>=",
2134 Operator::LessLessEqual => "operator<<=",
2135 Operator::AmpEqual => "operator&=",
2136 Operator::PipeEqual => "operator|=",
2137 Operator::CaretEqual => "operator^=",
2138
2139 Operator::VFTable => "`vftable'",
2140 Operator::VBTable => "`vbtable'",
2141 Operator::VCall => "`vcall'",
2142 Operator::Typeof => "`typeof'",
2143 Operator::LocalStaticGuard(scope) => {
2144 write!(self.w, "`local static guard'")?;
2145 if let Some(scope) = scope {
2146 write!(self.w, "{{{}}}", scope)?;
2147 }
2148 return Ok(());
2149 }
2150 Operator::String => "`string'",
2151 Operator::VBaseDtor => "`vbase destructor'",
2152 Operator::VectorDeletingDtor => "`vector deleting destructor'",
2153 Operator::DefaultCtorClosure => "`default constructor closure'",
2154 Operator::ScalarDeletingDtor => "`scalar deleting destructor'",
2155 Operator::VectorCtorIterator => "`vector constructor iterator'",
2156 Operator::VectorDtorIterator => "`vector destructor iterator'",
2157 Operator::VectorVBaseCtorIterator => "`vector vbase constructor iterator'",
2158 Operator::VirtualDisplacementMap => "`virtual displacement map'",
2159 Operator::EHVectorCtorIterator => "`eh vector constructor iterator'",
2160 Operator::EHVectorDtorIterator => "`eh vector destructor iterator'",
2161 Operator::EHVectorVBaseCtorIterator => "`eh vector vbase constructor iterator'",
2162 Operator::CopyCtorClosure => "`copy constructor closure'",
2163
2164 Operator::LocalVFTable => "`local vftable'",
2165 Operator::LocalVFTableCtorClosure => "`local vftable constructor closure'",
2166 Operator::ArrayNew => "operator new[]",
2167 Operator::ArrayDelete => "operator delete[]",
2168 Operator::PlacementDeleteClosure => "`placement delete closure'",
2169 Operator::PlacementArrayDeleteClosure => "`placement delete[] closure'",
2170
2171 Operator::CoroutineAwait => " co_await",
2172 Operator::LiteralOperatorName => "operator \"\"",
2173
2174 Operator::RTTITypeDescriptor(_, ref inner) => {
2175 self.write_pre(inner)?;
2176 // XXX(mitsuhiko): llvm uses a space here instead of `::`. No
2177 // idea why, seems inconsistent
2178 write!(self.w, "::`RTTI Type Descriptor'")?;
2179 return Ok(());
2180 }
2181 Operator::RTTIBaseClassDescriptor(nv_offset, vbptr_offset, vbtable_offset, flags) => {
2182 let sp = if self.flags.contains(DemangleFlags::SPACE_AFTER_COMMA) {
2183 " "
2184 } else {
2185 ""
2186 };
2187 write!(
2188 self.w,
2189 "`RTTI Base Class Descriptor at ({},{}{},{}{},{}{})'",
2190 nv_offset, sp, vbptr_offset, sp, vbtable_offset, sp, flags
2191 )?;
2192 return Ok(());
2193 }
2194 Operator::RTTIBaseClassArray => "`RTTI Base Class Array'",
2195 Operator::RTTIClassHierarchyDescriptor => "`RTTI Class Hierarchy Descriptor'",
2196 Operator::RTTIClassCompleteObjectLocator => "`RTTI Complete Object Locator'",
2197
2198 Operator::DynamicInitializer => "`dynamic initializer'",
2199 Operator::DynamicAtexitDtor => "`dynamic atexit destructor'",
2200 Operator::LocalStaticThreadGuard(scope) => {
2201 write!(self.w, "`local static thread guard'")?;
2202 if let Some(scope) = scope {
2203 write!(self.w, "{{{}}}", scope)?;
2204 }
2205 return Ok(());
2206 }
2207 };
2208 write!(self.w, "{}", s)?;
2209 Ok(())
2210 }
2211
write_one_name(&mut self, name: &Name) -> Result<()>2212 fn write_one_name(&mut self, name: &Name) -> Result<()> {
2213 match *name {
2214 Name::Md5(ref name) => {
2215 write!(self.w, "??@")?;
2216 self.w.write_all(name)?;
2217 write!(self.w, "@")?;
2218 }
2219 Name::Operator(ref op) => {
2220 self.write_space()?;
2221 self.write_operator_name(op)?;
2222 }
2223 Name::NonTemplate(ref name) => {
2224 self.w.write_all(name)?;
2225 }
2226 Name::AsInterface(ref name) => {
2227 write!(self.w, "[")?;
2228 self.w.write_all(name)?;
2229 write!(self.w, "]")?;
2230 }
2231 Name::Template(ref name, ref params) => {
2232 self.write_one_name(name)?;
2233 self.write_tmpl_params(¶ms)?;
2234 }
2235 Name::Discriminator(ref val) => {
2236 write!(self.w, "`{}'", val)?;
2237 }
2238 Name::ParsedName(ref val) => {
2239 write!(self.w, "`{}'", serialize(val, self.flags)?)?;
2240 }
2241 Name::AnonymousNamespace(_) => {
2242 write!(self.w, "`anonymous namespace'")?;
2243 }
2244 }
2245 Ok(())
2246 }
2247
write_scope(&mut self, names: &NameSequence) -> Result<()>2248 fn write_scope(&mut self, names: &NameSequence) -> Result<()> {
2249 // Print out namespaces or outer class names.
2250 let mut i = names.names.iter().rev();
2251 if let Some(name) = i.next() {
2252 self.write_one_name(&name)?;
2253 }
2254 for name in i {
2255 write!(self.w, "::")?;
2256 self.write_one_name(&name)?;
2257 }
2258 Ok(())
2259 }
2260
2261 // Write a name read by read_name().
write_name(&mut self, names: &Symbol, ty: Option<&Type<'_>>) -> Result<()>2262 fn write_name(&mut self, names: &Symbol, ty: Option<&Type<'_>>) -> Result<()> {
2263 if !self.flags.contains(DemangleFlags::SPACE_BEFORE_POINTER) {
2264 self.write_space_pre()?;
2265 } else {
2266 self.write_space_ptr()?;
2267 }
2268
2269 let mut was_literal_op = false;
2270 if let Name::Operator(Operator::LiteralOperatorName) = names.name {
2271 self.write_space()?;
2272 self.write_operator_name(&Operator::LiteralOperatorName)?;
2273 was_literal_op = true;
2274 }
2275
2276 self.write_scope(&names.scope)?;
2277
2278 if !names.scope.names.is_empty() && !was_literal_op {
2279 write!(self.w, "::")?;
2280 }
2281
2282 match names.name {
2283 Name::Md5(ref name) => {
2284 write!(self.w, "??@")?;
2285 self.w.write_all(name)?;
2286 write!(self.w, "@")?;
2287 }
2288 Name::Operator(ref op) => {
2289 match *op {
2290 Operator::Ctor => {
2291 let prev = names.scope.names.get(0).ok_or_else(|| {
2292 Error::new(
2293 "If there's a ctor, there should be another name in this sequence",
2294 )
2295 })?;
2296 self.write_one_name(prev)?;
2297 }
2298 Operator::Dtor => {
2299 let prev = names.scope.names.get(0).ok_or_else(|| {
2300 Error::new(
2301 "If there's a dtor, there should be another name in this sequence",
2302 )
2303 })?;
2304 write!(self.w, "~")?;
2305 self.write_one_name(prev)?;
2306 }
2307 Operator::VBTable => {
2308 write!(self.w, "`vbtable'{{for `")?;
2309 // The rest will be written by write_post of the
2310 // symbol type.
2311 }
2312 Operator::Conversion => {
2313 if let Some(Type::MemberFunction(_, _, _, _, ref rv)) = ty {
2314 write!(self.w, "operator ")?;
2315 self.write_pre(rv)?;
2316 self.write_post(rv)?;
2317 } else {
2318 self.write_space()?;
2319 self.write_operator_name(op)?;
2320 }
2321 }
2322 Operator::LiteralOperatorName => {}
2323 _ => {
2324 self.write_space()?;
2325 // Print out an overloaded operator.
2326 self.write_operator_name(op)?;
2327 }
2328 }
2329 }
2330 Name::NonTemplate(ref name) => {
2331 self.w.write_all(name)?;
2332 }
2333 Name::AsInterface(ref name) => {
2334 write!(self.w, "[")?;
2335 self.w.write_all(name)?;
2336 write!(self.w, "]")?;
2337 }
2338 Name::Template(ref name, ref params) => {
2339 self.write_one_name(name)?;
2340 self.write_tmpl_params(¶ms)?;
2341 }
2342 Name::Discriminator(ref val) => {
2343 write!(self.w, "`{}'", val)?;
2344 }
2345 Name::ParsedName(ref val) => {
2346 write!(self.w, "{}", serialize(val, self.flags)?)?;
2347 }
2348 Name::AnonymousNamespace(_) => {
2349 // this should never happen as they are handled elsewhere
2350 debug_assert!(false, "not supposed to be here");
2351 }
2352 }
2353 Ok(())
2354 }
2355
write_tmpl_params<'b>(&mut self, params: &Params<'b>) -> Result<()>2356 fn write_tmpl_params<'b>(&mut self, params: &Params<'b>) -> Result<()> {
2357 write!(self.w, "<")?;
2358 if !params.types.is_empty() {
2359 self.write_types(¶ms.types)?;
2360 if let Some(&b'>') = self.w.last() {
2361 write!(self.w, " ")?;
2362 }
2363 }
2364 write!(self.w, ">")?;
2365 Ok(())
2366 }
2367 }
2368
2369 // grammar from MicrosoftMangle.cpp:
2370
2371 // <mangled-name> ::= ? <name> <type-encoding>
2372 // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
2373 // <unqualified-name> ::= <operator-name>
2374 // ::= <ctor-dtor-name>
2375 // ::= <source-name>
2376 // ::= <template-name>
2377 // <operator-name> ::= ???
2378 // ::= ?B # cast, the target type is encoded as the return type.
2379 // <source-name> ::= <identifier> @
2380 //
2381 // mangleNestedName: calls into mangle, which is responsible for <mangled-name>, and into mangleUnqualifiedName
2382 // <postfix> ::= <unqualified-name> [<postfix>]
2383 // ::= <substitution> [<postfix>]
2384 //
2385 // <template-name> ::= <unscoped-template-name> <template-args>
2386 // ::= <substitution>
2387 // <unscoped-template-name> ::= ?$ <unqualified-name>
2388 // <type-encoding> ::= <function-class> <function-type>
2389 // ::= <storage-class> <variable-type>
2390 // <function-class> ::= <member-function> E? # E designates a 64-bit 'this'
2391 // # pointer. in 64-bit mode *all*
2392 // # 'this' pointers are 64-bit.
2393 // ::= <global-function>
2394 // <function-type> ::= <this-cvr-qualifiers> <calling-convention>
2395 // <return-type> <argument-list> <throw-spec>
2396 // <member-function> ::= A # private: near
2397 // ::= B # private: far
2398 // ::= C # private: static near
2399 // ::= D # private: static far
2400 // ::= E # private: near
2401 // ::= F # private: far
2402 // ::= I # near
2403 // ::= J # far
2404 // ::= K # static near
2405 // ::= L # static far
2406 // ::= M # near
2407 // ::= N # far
2408 // ::= Q # near
2409 // ::= R # far
2410 // ::= S # static near
2411 // ::= T # static far
2412 // ::= U # near
2413 // ::= V # far
2414 // <global-function> ::= Y # global near
2415 // ::= Z # global far
2416 // <storage-class> ::= 0 # private static member
2417 // ::= 1 # protected static member
2418 // ::= 2 # public static member
2419 // ::= 3 # global
2420 // ::= 4 # static local
2421