1 /*
2 Copyright (C) 2013-2014 Volker Krause <vkrause@kde.org>
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include <config-elf-dissector.h>
19 #include "demangler.h"
20
21 #include <QDebug>
22 #include <QScopedValueRollback>
23
24 // workarounds for conflicting declaration in libiberty.h
25 #define HAVE_DECL_BASENAME 1
26 #define HAVE_DECL_ASPRINTF 1
27 #define HAVE_DECL_VASPRINTF 1
28
29 #include <demangle.h>
30
31
demangle(const char * name)32 QVector<QByteArray> Demangler::demangle(const char* name)
33 {
34 QScopedValueRollback<const char*> mangledName(m_mangledName, name);
35
36 void *memory = nullptr;
37 demangle_component *component = cplus_demangle_v3_components(name, DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES | DMGL_VERBOSE, &memory);
38
39 QVector<QByteArray> result;
40 if (!memory || !component) { // demangle failed, likely not mangled
41 result.push_back(name);
42 return result;
43 }
44
45 reset();
46 handleNameComponent(component, result);
47 free(memory);
48 return result;
49 }
50
demangleFull(const char * name)51 QByteArray Demangler::demangleFull(const char* name)
52 {
53 void *memory = nullptr;
54 demangle_component *component = cplus_demangle_v3_components(name, DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES | DMGL_VERBOSE, &memory);
55
56 size_t size;
57 char * fullName = cplus_demangle_print(DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES | DMGL_VERBOSE, component, strlen(name), &size);
58 const QByteArray b(fullName);
59
60 free(fullName);
61 free(memory);
62
63 if (b.isEmpty())
64 return name;
65 return b;
66 }
67
reset()68 void Demangler::reset()
69 {
70 m_inArgList = false;
71 m_templateParamIndex = 0;
72 m_templateParams.clear();
73 m_pendingPointer = false;
74 m_pendingReference = false;
75 }
76
77 // not in a public binutils header, but needed anyway
78 struct demangle_operator_info
79 {
80 const char *type;
81 const char *name;
82 int len;
83 int args;
84 };
85
86 struct demangle_builtin_type_info {
87 const char *name;
88 int len;
89 const char *java_name;
90 int java_len;
91 /*enum d_builtin_type_print*/ int print;
92 };
93
join(const QVector<QByteArray> & v,const QByteArray & sep)94 static QByteArray join(const QVector<QByteArray> &v, const QByteArray &sep)
95 {
96 QByteArray res;
97 for (auto it = v.begin(); it != v.end(); ++it) {
98 if (it != v.begin())
99 res += sep;
100 res += *it;
101 }
102 return res;
103 }
104
handleNameComponent(demangle_component * component,QVector<QByteArray> & nameParts)105 void Demangler::handleNameComponent(demangle_component* component, QVector< QByteArray >& nameParts)
106 {
107 // TODO: complete the component types
108 switch (component->type) {
109 case DEMANGLE_COMPONENT_NAME:
110 nameParts.push_back(QByteArray(component->u.s_name.s, component->u.s_name.len));
111 break;
112 case DEMANGLE_COMPONENT_QUAL_NAME:
113 handleNameComponent(component->u.s_binary.left, nameParts);
114 handleNameComponent(component->u.s_binary.right, nameParts);
115 if (m_inArgList) {
116 const QByteArray name = nameParts.takeLast();
117 const QByteArray ns = nameParts.takeLast();
118 nameParts.push_back(ns + "::" + name);
119 }
120 break;
121 case DEMANGLE_COMPONENT_LOCAL_NAME:
122 handleNameComponent(component->u.s_binary.left, nameParts);
123 handleNameComponent(component->u.s_binary.right, nameParts);
124 if (m_inArgList) {
125 const QByteArray name = nameParts.takeLast();
126 const QByteArray ns = nameParts.takeLast();
127 nameParts.push_back(ns + "::" + name);
128 }
129 break;
130 case DEMANGLE_COMPONENT_TYPED_NAME:
131 {
132 // template parameters are indexed per enclosing type name, so push that on the stack here
133 QScopedValueRollback<int> indexRestter(m_templateParamIndex, 0);
134 QScopedValueRollback<QHash<int, QByteArray>> paramsResetter(m_templateParams);
135 QScopedValueRollback<bool> shouldIndexResetter(m_indexTemplateArgs, true);
136 QScopedValueRollback<QByteArray> modifierResetter(m_modifiers);
137 m_templateParams.clear();
138 m_modifiers.clear();
139
140 // left is the name of the function, right is the return type (ignored here) and arguments
141 handleNameComponent(component->u.s_binary.left, nameParts);
142 QVector<QByteArray> args;
143 handleNameComponent(component->u.s_binary.right, args);
144 if (!nameParts.isEmpty() && !args.isEmpty())
145 nameParts.last().append(args.last() + m_modifiers);
146 break;
147 }
148 case DEMANGLE_COMPONENT_TEMPLATE:
149 {
150 {
151 QScopedValueRollback<bool> indexRestter(m_indexTemplateArgs, false);
152 handleNameComponent(component->u.s_binary.left, nameParts);
153 }
154 QVector<QByteArray> args;
155 handleNameComponent(component->u.s_binary.right, args);
156 const QByteArray fullTemplate = nameParts.last() + '<' + join(args, ", ") + '>';
157 if (m_inArgList) // we only want the template grouping on top-level
158 nameParts.removeLast();
159 nameParts.push_back(fullTemplate);
160 break;
161 }
162 case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
163 nameParts.push_back(m_templateParams.value(component->u.s_number.number));
164 break;
165 case DEMANGLE_COMPONENT_FUNCTION_PARAM:
166 // no idea what this means, but that's what c++filt is outputting for these...
167 nameParts.push_back(QByteArray("{parm#") + QByteArray::number((int)component->u.s_number.number) + '}');
168 break;
169 case DEMANGLE_COMPONENT_CTOR:
170 // TODO: do we need to consider u.s_ctor.kind?
171 handleNameComponent(component->u.s_ctor.name, nameParts);
172 break;
173 case DEMANGLE_COMPONENT_DTOR:
174 // TODO: do we need to consider u.s_dtor.kind?
175 handleNameComponent(component->u.s_dtor.name, nameParts);
176 nameParts.last().prepend('~');
177 break;
178 case DEMANGLE_COMPONENT_VTABLE:
179 handleNameComponent(component->u.s_binary.left, nameParts);
180 nameParts.push_back("vtable");
181 break;
182 case DEMANGLE_COMPONENT_VTT:
183 handleNameComponent(component->u.s_binary.left, nameParts);
184 nameParts.push_back("vtt"); // what's this?
185 break;
186 case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
187 {
188 handleNameComponent(component->u.s_binary.left, nameParts);
189 QVector<QByteArray> tmp;
190 handleNameComponent(component->u.s_binary.right, tmp);
191 nameParts.push_back("construction vtable in " + join(tmp, "::"));
192 break;
193 }
194 case DEMANGLE_COMPONENT_TYPEINFO:
195 handleNameComponent(component->u.s_binary.left, nameParts);
196 nameParts.push_back("typeinfo");
197 break;
198 case DEMANGLE_COMPONENT_TYPEINFO_NAME:
199 handleNameComponent(component->u.s_binary.left, nameParts);
200 nameParts.push_back("typeinfo name");
201 break;
202 case DEMANGLE_COMPONENT_TYPEINFO_FN:
203 handleNameComponent(component->u.s_binary.left, nameParts);
204 nameParts.push_back("typeinfo function");
205 break;
206 case DEMANGLE_COMPONENT_THUNK:
207 handleNameComponent(component->u.s_binary.left, nameParts);
208 nameParts.push_back("thunk");
209 break;
210 case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
211 handleNameComponent(component->u.s_binary.left, nameParts);
212 nameParts.push_back("virtual thunk");
213 break;
214 case DEMANGLE_COMPONENT_COVARIANT_THUNK:
215 handleNameComponent(component->u.s_binary.left, nameParts);
216 nameParts.push_back("covariant return thunk");
217 break;
218 case DEMANGLE_COMPONENT_GUARD:
219 handleNameComponent(component->u.s_binary.left, nameParts);
220 nameParts.push_back("guard variable");
221 break;
222 case DEMANGLE_COMPONENT_REFTEMP:
223 {
224 handleNameComponent(component->u.s_binary.left, nameParts);
225 QVector<QByteArray> tmp;
226 handleNameComponent(component->u.s_binary.right, tmp);
227 nameParts.push_back("reference temporary #" + tmp.last());
228 break;
229 }
230 case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
231 handleNameComponent(component->u.s_binary.left, nameParts);
232 nameParts.push_back("hidden alias");
233 break;
234 case DEMANGLE_COMPONENT_SUB_STD:
235 nameParts.push_back(QByteArray(component->u.s_name.s, component->u.s_name.len));
236 break;
237 case DEMANGLE_COMPONENT_RESTRICT:
238 handleNameComponent(component->u.s_binary.left, nameParts);
239 nameParts.last().append(" restrict");
240 break;
241 case DEMANGLE_COMPONENT_VOLATILE:
242 handleNameComponent(component->u.s_binary.left, nameParts);
243 nameParts.last().append(" volatile");
244 break;
245 case DEMANGLE_COMPONENT_CONST:
246 handleNameComponent(component->u.s_binary.left, nameParts);
247 nameParts.last().append(" const");
248 break;
249 case DEMANGLE_COMPONENT_RESTRICT_THIS:
250 handleNameComponent(component->u.s_binary.left, nameParts);
251 m_modifiers.append(" restrict");
252 break;
253 case DEMANGLE_COMPONENT_VOLATILE_THIS:
254 handleNameComponent(component->u.s_binary.left, nameParts);
255 m_modifiers.append(" volatile");
256 break;
257 case DEMANGLE_COMPONENT_CONST_THIS:
258 handleNameComponent(component->u.s_binary.left, nameParts);
259 m_modifiers.append(" const");
260 break;
261 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 24)
262 case DEMANGLE_COMPONENT_REFERENCE_THIS:
263 handleNameComponent(component->u.s_binary.left, nameParts);
264 m_modifiers.append(" &");
265 break;
266 case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
267 handleNameComponent(component->u.s_binary.left, nameParts);
268 m_modifiers.append(" &&");
269 break;
270 #endif
271 case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
272 {
273 QVector<QByteArray> parts;
274 handleNameComponent(component->u.s_binary.left, parts);
275 handleNameComponent(component->u.s_binary.right, parts);
276 nameParts.push_back(parts.first() + ' ' + parts.last());
277 break;
278 }
279 case DEMANGLE_COMPONENT_POINTER:
280 {
281 QScopedValueRollback<bool> resetter(m_pendingPointer, true);
282 handleNameComponent(component->u.s_binary.left, nameParts);
283 if (m_pendingPointer) // not consumed by a function pointer
284 nameParts.last().append('*');
285 break;
286 }
287 case DEMANGLE_COMPONENT_REFERENCE:
288 {
289 QScopedValueRollback<bool> resetter(m_pendingReference, true);
290 handleNameComponent(component->u.s_binary.left, nameParts);
291 if (m_pendingReference && !nameParts.last().endsWith('&')) // not consumed by the array type, and primitive reference collapsing
292 nameParts.last().append('&');
293 break;
294 }
295 case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
296 handleNameComponent(component->u.s_binary.left, nameParts);
297 // skip appending &&
298 // - in case of reference collapsing (TODO: this should be done on the tree, not the string)
299 // - if we have an empty template arg in a pack expansion
300 if (!nameParts.last().endsWith('&') && !nameParts.last().isEmpty())
301 nameParts.last().append("&&");
302 break;
303 case DEMANGLE_COMPONENT_BUILTIN_TYPE:
304 nameParts.push_back(QByteArray(component->u.s_builtin.type->name, component->u.s_builtin.type->len));
305 break;
306 case DEMANGLE_COMPONENT_FUNCTION_TYPE:
307 {
308 const bool previousPendingPointer = m_pendingPointer;
309 m_pendingPointer = false;
310
311 // left is return type (only relevant in argument lists), right is the (optional) argument list
312 QVector<QByteArray> returnType;
313 handleOptionalNameComponent(component->u.s_binary.left, returnType);
314
315 QVector<QByteArray> args;
316 handleOptionalNameComponent(component->u.s_binary.right, args);
317 QByteArray fullName;
318 if (m_inArgList && !returnType.isEmpty())
319 fullName.prepend(returnType.last() + ' ');
320 if (previousPendingPointer) { // function pointer
321 fullName.append("(*)");
322 } else if (!m_ptrmemType.isEmpty()) {
323 fullName.append('(' + m_ptrmemType + "::*)");
324 } else {
325 m_pendingPointer = previousPendingPointer;
326 }
327 fullName.append('(' + join(args, ", ") + ')');
328 nameParts.push_back(fullName);
329 break;
330 }
331 case DEMANGLE_COMPONENT_ARRAY_TYPE:
332 {
333 const bool prevRef = m_pendingReference;
334 m_pendingReference = false;
335 // left is optional dimension, right is type
336 handleNameComponent(component->u.s_binary.right, nameParts);
337 QVector<QByteArray> dim;
338 handleOptionalNameComponent(component->u.s_binary.left, dim);
339 QByteArray suffix;
340 if (prevRef) {
341 suffix += " (&)"; // array references are special...
342 } else {
343 m_pendingReference = prevRef;
344 }
345 suffix += " [";
346 if (!dim.isEmpty())
347 suffix.append(dim.last());
348 suffix += ']';
349 nameParts.last().append(suffix);
350 break;
351 }
352 case DEMANGLE_COMPONENT_PTRMEM_TYPE:
353 {
354 QScopedValueRollback<QByteArray> ptrmemTypeResetter(m_ptrmemType);
355 m_ptrmemType.clear();
356 QVector<QByteArray> tmp;
357 handleNameComponent(component->u.s_binary.left, tmp);
358 m_ptrmemType = tmp.last();
359 handleNameComponent(component->u.s_binary.right, nameParts);
360 break;
361 }
362 case DEMANGLE_COMPONENT_VECTOR_TYPE:
363 {
364 QVector<QByteArray> parts;
365 // left is size, right is type
366 handleNameComponent(component->u.s_binary.left, parts);
367 handleNameComponent(component->u.s_binary.right, parts);
368 nameParts.push_back(parts.last() + " __vector(" + parts.first() + ')');
369 break;
370 }
371 case DEMANGLE_COMPONENT_ARGLIST:
372 {
373 QScopedValueRollback<bool> resetter(m_inArgList, true);
374 if (!component->u.s_binary.left && !component->u.s_binary.right) {
375 nameParts.push_back(QByteArray("")); // empty arg list
376 } else {
377 handleOptionalNameComponent(component->u.s_binary.left, nameParts);
378 handleOptionalNameComponent(component->u.s_binary.right, nameParts);
379 }
380 break;
381 }
382 case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
383 {
384 QScopedValueRollback<bool> resetter(m_inArgList, true);
385
386 if (component->u.s_binary.left) {
387 int currentIndex = -1;
388 if (m_indexTemplateArgs)
389 currentIndex = m_templateParamIndex++;
390 QVector<QByteArray> left;
391 {
392 QScopedValueRollback<bool> resetter(m_indexTemplateArgs, false);
393 handleNameComponent(component->u.s_binary.left, left);
394 }
395 nameParts += left;
396 if (m_indexTemplateArgs) {
397 Q_ASSERT(currentIndex >= 0);
398 if (left.isEmpty())
399 m_templateParams.insert(currentIndex, QByteArray()); // empty template arg, might be referenced from elsewhere...
400 else
401 m_templateParams.insert(currentIndex, nameParts.last());
402 }
403 }
404
405 handleOptionalNameComponent(component->u.s_binary.right, nameParts);
406 break;
407 }
408 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 32)
409 case DEMANGLE_COMPONENT_TPARM_OBJ:
410 handleNameComponent(component->u.s_binary.left, nameParts);
411 nameParts.last().prepend(QByteArray("template parameter object for "));
412 break;
413 #endif
414 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 23)
415 case DEMANGLE_COMPONENT_INITIALIZER_LIST:
416 {
417 QVector<QByteArray> parts;
418 handleNameComponent(component->u.s_binary.left, parts);
419 handleNameComponent(component->u.s_binary.right, parts);
420 nameParts.push_back(parts.at(0) + "{" + parts.at(1) + "}");
421 break;
422 }
423 #endif
424 case DEMANGLE_COMPONENT_OPERATOR:
425 nameParts.push_back(QByteArray("operator") + QByteArray(component->u.s_operator.op->name, component->u.s_operator.op->len));
426 break;
427 case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
428 handleNameComponent(component->u.s_extended_operator.name, nameParts);
429 break;
430 case DEMANGLE_COMPONENT_CAST:
431 handleNameComponent(component->u.s_binary.left, nameParts);
432 nameParts.last().prepend("operator ");
433 break;
434 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 26)
435 case DEMANGLE_COMPONENT_CONVERSION:
436 handleNameComponent(component->u.s_binary.left, nameParts);
437 nameParts.last().prepend("operator ");
438 break;
439 #endif
440 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 23)
441 case DEMANGLE_COMPONENT_NULLARY:
442 handleNameComponent(component->u.s_binary.left, nameParts);
443 break;
444 #endif
445 case DEMANGLE_COMPONENT_UNARY:
446 {
447 handleOperatorComponent(component->u.s_binary.left, nameParts);
448 handleNameComponent(component->u.s_binary.right, nameParts);
449 const QByteArray arg = nameParts.takeLast();
450 const QByteArray op = nameParts.takeLast();
451 nameParts.push_back(op + arg);
452 break;
453 }
454 case DEMANGLE_COMPONENT_BINARY:
455 {
456 handleOperatorComponent(component->u.s_binary.left, nameParts);
457 handleNameComponent(component->u.s_binary.right, nameParts);
458 const QByteArray arg2 = nameParts.takeLast();
459 const QByteArray arg1 = nameParts.takeLast();
460 const QByteArray op = nameParts.takeLast();
461 nameParts.push_back(arg1 + op + arg2);
462 break;
463 }
464 case DEMANGLE_COMPONENT_BINARY_ARGS:
465 case DEMANGLE_COMPONENT_TRINARY:
466 case DEMANGLE_COMPONENT_TRINARY_ARG1:
467 case DEMANGLE_COMPONENT_TRINARY_ARG2:
468 handleNameComponent(component->u.s_binary.left, nameParts);
469 handleNameComponent(component->u.s_binary.right, nameParts);
470 break;
471 case DEMANGLE_COMPONENT_LITERAL:
472 case DEMANGLE_COMPONENT_LITERAL_NEG:
473 {
474 // left is type, right is value
475 QVector<QByteArray> type;
476 handleNameComponent(component->u.s_binary.left, type);
477 handleNameComponent(component->u.s_binary.right, type);
478 if (component->type == DEMANGLE_COMPONENT_LITERAL_NEG)
479 type.last().prepend('-');
480 QByteArray typeStr;
481 // TODO add: unsigned, long, long long, unsigned long long
482 if (type.first() == "bool") {
483 typeStr = type.last() == "0" ? "false" : "true";
484 } else if (type.first() == "int") {
485 typeStr = type.last();
486 } else if (type.first() == "unsigned long") {
487 typeStr = type.last() + "ul";
488 } else { // custom type
489 typeStr = '(' + type.first() + ')' + type.last();
490 }
491 nameParts.push_back(typeStr);
492 break;
493 }
494 case DEMANGLE_COMPONENT_NUMBER:
495 nameParts.push_back(QByteArray::number((int)component->u.s_number.number));
496 break;
497 case DEMANGLE_COMPONENT_DECLTYPE:
498 // TODO: undocumented, but one seems to contain content at least
499 handleOptionalNameComponent(component->u.s_binary.left, nameParts);
500 handleOptionalNameComponent(component->u.s_binary.right, nameParts);
501 break;
502 case DEMANGLE_COMPONENT_LAMBDA:
503 {
504 QVector<QByteArray> args;
505 handleNameComponent(component->u.s_unary_num.sub, args);
506 nameParts.push_back("{lambda(" + join(args, ", ") + ")#" + QByteArray::number(component->u.s_unary_num.num + 1) + '}');
507 break;
508 }
509 case DEMANGLE_COMPONENT_DEFAULT_ARG:
510 nameParts.push_back(QByteArray("{default arg#") + QByteArray::number((int)component->u.s_unary_num.num + 1) + '}');
511 handleOptionalNameComponent(component->u.s_unary_num.sub, nameParts);
512 break;
513 case DEMANGLE_COMPONENT_UNNAMED_TYPE:
514 nameParts.push_back(QByteArray("{unnamed type#") + QByteArray::number((int)component->u.s_number.number + 1) + '}');
515 break;
516 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 23)
517 case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
518 handleNameComponent(component->u.s_binary.left, nameParts);
519 nameParts.last().prepend("transaction clone for ");
520 break;
521 case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
522 handleNameComponent(component->u.s_binary.left, nameParts);
523 nameParts.last().prepend("non-transaction clone for ");
524 break;
525 #endif
526 case DEMANGLE_COMPONENT_PACK_EXPANSION:
527 handleOptionalNameComponent(component->u.s_binary.left, nameParts);
528 handleOptionalNameComponent(component->u.s_binary.right, nameParts);
529 break;
530 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 24)
531 case DEMANGLE_COMPONENT_TAGGED_NAME:
532 {
533 QVector<QByteArray> args;
534 handleNameComponent(component->u.s_binary.left, nameParts);
535 handleNameComponent(component->u.s_binary.right, args);
536 const auto n = nameParts.takeLast();
537 nameParts.push_back(n + "[abi:" + args.last() + ']');
538 break;
539 }
540 #endif
541 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 23)
542 case DEMANGLE_COMPONENT_CLONE:
543 {
544 QVector<QByteArray> args;
545 handleNameComponent(component->u.s_binary.left, nameParts);
546 handleNameComponent(component->u.s_binary.right, args);
547 const auto n = nameParts.takeLast();
548 nameParts.push_back(n + " [clone " + args.last() + ']');
549 break;
550 }
551 #endif
552 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 28)
553 case DEMANGLE_COMPONENT_NOEXCEPT:
554 {
555 handleNameComponent(component->u.s_binary.left, nameParts);
556 const auto n = nameParts.takeLast();
557 nameParts.push_back(n + " noexcept");
558 break;
559 }
560 #endif
561 default:
562 qDebug() << Q_FUNC_INFO << "unhandled component type" << component->type << m_mangledName;
563 }
564 }
565
handleOptionalNameComponent(demangle_component * component,QVector<QByteArray> & nameParts)566 void Demangler::handleOptionalNameComponent(demangle_component* component, QVector< QByteArray >& nameParts)
567 {
568 if (!component)
569 return;
570 handleNameComponent(component, nameParts);
571 }
572
handleOperatorComponent(demangle_component * component,QVector<QByteArray> & nameParts)573 void Demangler::handleOperatorComponent(demangle_component* component, QVector< QByteArray >& nameParts)
574 {
575 if (component->type == DEMANGLE_COMPONENT_OPERATOR) {
576 nameParts.push_back(QByteArray(component->u.s_operator.op->name, component->u.s_operator.op->len));
577 return;
578 }
579 handleNameComponent(component, nameParts);
580 }
581
symbolType(const char * name)582 Demangler::SymbolType Demangler::symbolType(const char* name)
583 {
584 if (strlen(name) < 4)
585 return SymbolType::Normal;
586 if (name[0] != '_' || name[1] != 'Z' || name[2] != 'T')
587 return SymbolType::Normal;
588
589 switch (name[3]) {
590 case 'V': return SymbolType::VTable;
591 case 'I': return SymbolType::TypeInfo;
592 case 'S': return SymbolType::TypeInfoName;
593 case 'T': return SymbolType::VTT;
594 case 'C': return SymbolType::ConstructionVTable;
595 }
596
597 return SymbolType::Normal;
598 }
599