File indexing completed on 2024-05-12 05:43:26
0001 /* 0002 Copyright (C) 2013-2014 Volker Krause <vkrause@kde.org> 0003 0004 This program is free software; you can redistribute it and/or modify it 0005 under the terms of the GNU Library General Public License as published by 0006 the Free Software Foundation; either version 2 of the License, or (at your 0007 option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, but WITHOUT 0010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 0012 License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program. If not, see <https://www.gnu.org/licenses/>. 0016 */ 0017 0018 #include <config-elf-dissector.h> 0019 #include "demangler.h" 0020 0021 #include <QDebug> 0022 #include <QScopedValueRollback> 0023 0024 // workarounds for conflicting declaration in libiberty.h 0025 #define HAVE_DECL_BASENAME 1 0026 #define HAVE_DECL_ASPRINTF 1 0027 #define HAVE_DECL_VASPRINTF 1 0028 0029 #include <demangle.h> 0030 0031 0032 QVector<QByteArray> Demangler::demangle(const char* name) 0033 { 0034 QScopedValueRollback<const char*> mangledName(m_mangledName, name); 0035 0036 void *memory = nullptr; 0037 demangle_component *component = cplus_demangle_v3_components(name, DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES | DMGL_VERBOSE, &memory); 0038 0039 QVector<QByteArray> result; 0040 if (!memory || !component) { // demangle failed, likely not mangled 0041 result.push_back(name); 0042 return result; 0043 } 0044 0045 reset(); 0046 handleNameComponent(component, result); 0047 free(memory); 0048 return result; 0049 } 0050 0051 QByteArray Demangler::demangleFull(const char* name) 0052 { 0053 void *memory = nullptr; 0054 demangle_component *component = cplus_demangle_v3_components(name, DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES | DMGL_VERBOSE, &memory); 0055 0056 size_t size; 0057 char * fullName = cplus_demangle_print(DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES | DMGL_VERBOSE, component, strlen(name), &size); 0058 const QByteArray b(fullName); 0059 0060 free(fullName); 0061 free(memory); 0062 0063 if (b.isEmpty()) 0064 return name; 0065 return b; 0066 } 0067 0068 void Demangler::reset() 0069 { 0070 m_inArgList = false; 0071 m_templateParamIndex = 0; 0072 m_templateParams.clear(); 0073 m_pendingPointer = false; 0074 m_pendingReference = false; 0075 } 0076 0077 // not in a public binutils header, but needed anyway 0078 struct demangle_operator_info 0079 { 0080 const char *type; 0081 const char *name; 0082 int len; 0083 int args; 0084 }; 0085 0086 struct demangle_builtin_type_info { 0087 const char *name; 0088 int len; 0089 const char *java_name; 0090 int java_len; 0091 /*enum d_builtin_type_print*/ int print; 0092 }; 0093 0094 static QByteArray join(const QVector<QByteArray> &v, const QByteArray &sep) 0095 { 0096 QByteArray res; 0097 for (auto it = v.begin(); it != v.end(); ++it) { 0098 if (it != v.begin()) 0099 res += sep; 0100 res += *it; 0101 } 0102 return res; 0103 } 0104 0105 void Demangler::handleNameComponent(demangle_component* component, QVector< QByteArray >& nameParts) 0106 { 0107 // TODO: complete the component types 0108 switch (component->type) { 0109 case DEMANGLE_COMPONENT_NAME: 0110 nameParts.push_back(QByteArray(component->u.s_name.s, component->u.s_name.len)); 0111 break; 0112 case DEMANGLE_COMPONENT_QUAL_NAME: 0113 handleNameComponent(component->u.s_binary.left, nameParts); 0114 handleNameComponent(component->u.s_binary.right, nameParts); 0115 if (m_inArgList) { 0116 const QByteArray name = nameParts.takeLast(); 0117 const QByteArray ns = nameParts.takeLast(); 0118 nameParts.push_back(ns + "::" + name); 0119 } 0120 break; 0121 case DEMANGLE_COMPONENT_LOCAL_NAME: 0122 handleNameComponent(component->u.s_binary.left, nameParts); 0123 handleNameComponent(component->u.s_binary.right, nameParts); 0124 if (m_inArgList) { 0125 const QByteArray name = nameParts.takeLast(); 0126 const QByteArray ns = nameParts.takeLast(); 0127 nameParts.push_back(ns + "::" + name); 0128 } 0129 break; 0130 case DEMANGLE_COMPONENT_TYPED_NAME: 0131 { 0132 // template parameters are indexed per enclosing type name, so push that on the stack here 0133 QScopedValueRollback<int> indexRestter(m_templateParamIndex, 0); 0134 QScopedValueRollback<QHash<int, QByteArray>> paramsResetter(m_templateParams); 0135 QScopedValueRollback<bool> shouldIndexResetter(m_indexTemplateArgs, true); 0136 QScopedValueRollback<QByteArray> modifierResetter(m_modifiers); 0137 m_templateParams.clear(); 0138 m_modifiers.clear(); 0139 0140 // left is the name of the function, right is the return type (ignored here) and arguments 0141 handleNameComponent(component->u.s_binary.left, nameParts); 0142 QVector<QByteArray> args; 0143 handleNameComponent(component->u.s_binary.right, args); 0144 if (!nameParts.isEmpty() && !args.isEmpty()) 0145 nameParts.last().append(args.last() + m_modifiers); 0146 break; 0147 } 0148 case DEMANGLE_COMPONENT_TEMPLATE: 0149 { 0150 { 0151 QScopedValueRollback<bool> indexRestter(m_indexTemplateArgs, false); 0152 handleNameComponent(component->u.s_binary.left, nameParts); 0153 } 0154 QVector<QByteArray> args; 0155 handleNameComponent(component->u.s_binary.right, args); 0156 const QByteArray fullTemplate = nameParts.last() + '<' + join(args, ", ") + '>'; 0157 if (m_inArgList) // we only want the template grouping on top-level 0158 nameParts.removeLast(); 0159 nameParts.push_back(fullTemplate); 0160 break; 0161 } 0162 case DEMANGLE_COMPONENT_TEMPLATE_PARAM: 0163 nameParts.push_back(m_templateParams.value(component->u.s_number.number)); 0164 break; 0165 case DEMANGLE_COMPONENT_FUNCTION_PARAM: 0166 // no idea what this means, but that's what c++filt is outputting for these... 0167 nameParts.push_back(QByteArray("{parm#") + QByteArray::number((int)component->u.s_number.number) + '}'); 0168 break; 0169 case DEMANGLE_COMPONENT_CTOR: 0170 // TODO: do we need to consider u.s_ctor.kind? 0171 handleNameComponent(component->u.s_ctor.name, nameParts); 0172 break; 0173 case DEMANGLE_COMPONENT_DTOR: 0174 // TODO: do we need to consider u.s_dtor.kind? 0175 handleNameComponent(component->u.s_dtor.name, nameParts); 0176 nameParts.last().prepend('~'); 0177 break; 0178 case DEMANGLE_COMPONENT_VTABLE: 0179 handleNameComponent(component->u.s_binary.left, nameParts); 0180 nameParts.push_back("vtable"); 0181 break; 0182 case DEMANGLE_COMPONENT_VTT: 0183 handleNameComponent(component->u.s_binary.left, nameParts); 0184 nameParts.push_back("vtt"); // what's this? 0185 break; 0186 case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: 0187 { 0188 handleNameComponent(component->u.s_binary.left, nameParts); 0189 QVector<QByteArray> tmp; 0190 handleNameComponent(component->u.s_binary.right, tmp); 0191 nameParts.push_back("construction vtable in " + join(tmp, "::")); 0192 break; 0193 } 0194 case DEMANGLE_COMPONENT_TYPEINFO: 0195 handleNameComponent(component->u.s_binary.left, nameParts); 0196 nameParts.push_back("typeinfo"); 0197 break; 0198 case DEMANGLE_COMPONENT_TYPEINFO_NAME: 0199 handleNameComponent(component->u.s_binary.left, nameParts); 0200 nameParts.push_back("typeinfo name"); 0201 break; 0202 case DEMANGLE_COMPONENT_TYPEINFO_FN: 0203 handleNameComponent(component->u.s_binary.left, nameParts); 0204 nameParts.push_back("typeinfo function"); 0205 break; 0206 case DEMANGLE_COMPONENT_THUNK: 0207 handleNameComponent(component->u.s_binary.left, nameParts); 0208 nameParts.push_back("thunk"); 0209 break; 0210 case DEMANGLE_COMPONENT_VIRTUAL_THUNK: 0211 handleNameComponent(component->u.s_binary.left, nameParts); 0212 nameParts.push_back("virtual thunk"); 0213 break; 0214 case DEMANGLE_COMPONENT_COVARIANT_THUNK: 0215 handleNameComponent(component->u.s_binary.left, nameParts); 0216 nameParts.push_back("covariant return thunk"); 0217 break; 0218 case DEMANGLE_COMPONENT_GUARD: 0219 handleNameComponent(component->u.s_binary.left, nameParts); 0220 nameParts.push_back("guard variable"); 0221 break; 0222 case DEMANGLE_COMPONENT_REFTEMP: 0223 { 0224 handleNameComponent(component->u.s_binary.left, nameParts); 0225 QVector<QByteArray> tmp; 0226 handleNameComponent(component->u.s_binary.right, tmp); 0227 nameParts.push_back("reference temporary #" + tmp.last()); 0228 break; 0229 } 0230 case DEMANGLE_COMPONENT_HIDDEN_ALIAS: 0231 handleNameComponent(component->u.s_binary.left, nameParts); 0232 nameParts.push_back("hidden alias"); 0233 break; 0234 case DEMANGLE_COMPONENT_SUB_STD: 0235 nameParts.push_back(QByteArray(component->u.s_name.s, component->u.s_name.len)); 0236 break; 0237 case DEMANGLE_COMPONENT_RESTRICT: 0238 handleNameComponent(component->u.s_binary.left, nameParts); 0239 nameParts.last().append(" restrict"); 0240 break; 0241 case DEMANGLE_COMPONENT_VOLATILE: 0242 handleNameComponent(component->u.s_binary.left, nameParts); 0243 nameParts.last().append(" volatile"); 0244 break; 0245 case DEMANGLE_COMPONENT_CONST: 0246 handleNameComponent(component->u.s_binary.left, nameParts); 0247 nameParts.last().append(" const"); 0248 break; 0249 case DEMANGLE_COMPONENT_RESTRICT_THIS: 0250 handleNameComponent(component->u.s_binary.left, nameParts); 0251 m_modifiers.append(" restrict"); 0252 break; 0253 case DEMANGLE_COMPONENT_VOLATILE_THIS: 0254 handleNameComponent(component->u.s_binary.left, nameParts); 0255 m_modifiers.append(" volatile"); 0256 break; 0257 case DEMANGLE_COMPONENT_CONST_THIS: 0258 handleNameComponent(component->u.s_binary.left, nameParts); 0259 m_modifiers.append(" const"); 0260 break; 0261 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 24) 0262 case DEMANGLE_COMPONENT_REFERENCE_THIS: 0263 handleNameComponent(component->u.s_binary.left, nameParts); 0264 m_modifiers.append(" &"); 0265 break; 0266 case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: 0267 handleNameComponent(component->u.s_binary.left, nameParts); 0268 m_modifiers.append(" &&"); 0269 break; 0270 #endif 0271 case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: 0272 { 0273 QVector<QByteArray> parts; 0274 handleNameComponent(component->u.s_binary.left, parts); 0275 handleNameComponent(component->u.s_binary.right, parts); 0276 nameParts.push_back(parts.first() + ' ' + parts.last()); 0277 break; 0278 } 0279 case DEMANGLE_COMPONENT_POINTER: 0280 { 0281 QScopedValueRollback<bool> resetter(m_pendingPointer, true); 0282 handleNameComponent(component->u.s_binary.left, nameParts); 0283 if (m_pendingPointer) // not consumed by a function pointer 0284 nameParts.last().append('*'); 0285 break; 0286 } 0287 case DEMANGLE_COMPONENT_REFERENCE: 0288 { 0289 QScopedValueRollback<bool> resetter(m_pendingReference, true); 0290 handleNameComponent(component->u.s_binary.left, nameParts); 0291 if (m_pendingReference && !nameParts.last().endsWith('&')) // not consumed by the array type, and primitive reference collapsing 0292 nameParts.last().append('&'); 0293 break; 0294 } 0295 case DEMANGLE_COMPONENT_RVALUE_REFERENCE: 0296 handleNameComponent(component->u.s_binary.left, nameParts); 0297 // skip appending && 0298 // - in case of reference collapsing (TODO: this should be done on the tree, not the string) 0299 // - if we have an empty template arg in a pack expansion 0300 if (!nameParts.last().endsWith('&') && !nameParts.last().isEmpty()) 0301 nameParts.last().append("&&"); 0302 break; 0303 case DEMANGLE_COMPONENT_BUILTIN_TYPE: 0304 nameParts.push_back(QByteArray(component->u.s_builtin.type->name, component->u.s_builtin.type->len)); 0305 break; 0306 case DEMANGLE_COMPONENT_FUNCTION_TYPE: 0307 { 0308 const bool previousPendingPointer = m_pendingPointer; 0309 m_pendingPointer = false; 0310 0311 // left is return type (only relevant in argument lists), right is the (optional) argument list 0312 QVector<QByteArray> returnType; 0313 handleOptionalNameComponent(component->u.s_binary.left, returnType); 0314 0315 QVector<QByteArray> args; 0316 handleOptionalNameComponent(component->u.s_binary.right, args); 0317 QByteArray fullName; 0318 if (m_inArgList && !returnType.isEmpty()) 0319 fullName.prepend(returnType.last() + ' '); 0320 if (previousPendingPointer) { // function pointer 0321 fullName.append("(*)"); 0322 } else if (!m_ptrmemType.isEmpty()) { 0323 fullName.append('(' + m_ptrmemType + "::*)"); 0324 } else { 0325 m_pendingPointer = previousPendingPointer; 0326 } 0327 fullName.append('(' + join(args, ", ") + ')'); 0328 nameParts.push_back(fullName); 0329 break; 0330 } 0331 case DEMANGLE_COMPONENT_ARRAY_TYPE: 0332 { 0333 const bool prevRef = m_pendingReference; 0334 m_pendingReference = false; 0335 // left is optional dimension, right is type 0336 handleNameComponent(component->u.s_binary.right, nameParts); 0337 QVector<QByteArray> dim; 0338 handleOptionalNameComponent(component->u.s_binary.left, dim); 0339 QByteArray suffix; 0340 if (prevRef) { 0341 suffix += " (&)"; // array references are special... 0342 } else { 0343 m_pendingReference = prevRef; 0344 } 0345 suffix += " ["; 0346 if (!dim.isEmpty()) 0347 suffix.append(dim.last()); 0348 suffix += ']'; 0349 nameParts.last().append(suffix); 0350 break; 0351 } 0352 case DEMANGLE_COMPONENT_PTRMEM_TYPE: 0353 { 0354 QScopedValueRollback<QByteArray> ptrmemTypeResetter(m_ptrmemType); 0355 m_ptrmemType.clear(); 0356 QVector<QByteArray> tmp; 0357 handleNameComponent(component->u.s_binary.left, tmp); 0358 m_ptrmemType = tmp.last(); 0359 handleNameComponent(component->u.s_binary.right, nameParts); 0360 break; 0361 } 0362 case DEMANGLE_COMPONENT_VECTOR_TYPE: 0363 { 0364 QVector<QByteArray> parts; 0365 // left is size, right is type 0366 handleNameComponent(component->u.s_binary.left, parts); 0367 handleNameComponent(component->u.s_binary.right, parts); 0368 nameParts.push_back(parts.last() + " __vector(" + parts.first() + ')'); 0369 break; 0370 } 0371 case DEMANGLE_COMPONENT_ARGLIST: 0372 { 0373 QScopedValueRollback<bool> resetter(m_inArgList, true); 0374 if (!component->u.s_binary.left && !component->u.s_binary.right) { 0375 nameParts.push_back(QByteArray("")); // empty arg list 0376 } else { 0377 handleOptionalNameComponent(component->u.s_binary.left, nameParts); 0378 handleOptionalNameComponent(component->u.s_binary.right, nameParts); 0379 } 0380 break; 0381 } 0382 case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: 0383 { 0384 QScopedValueRollback<bool> resetter(m_inArgList, true); 0385 0386 if (component->u.s_binary.left) { 0387 int currentIndex = -1; 0388 if (m_indexTemplateArgs) 0389 currentIndex = m_templateParamIndex++; 0390 QVector<QByteArray> left; 0391 { 0392 QScopedValueRollback<bool> resetter(m_indexTemplateArgs, false); 0393 handleNameComponent(component->u.s_binary.left, left); 0394 } 0395 nameParts += left; 0396 if (m_indexTemplateArgs) { 0397 Q_ASSERT(currentIndex >= 0); 0398 if (left.isEmpty()) 0399 m_templateParams.insert(currentIndex, QByteArray()); // empty template arg, might be referenced from elsewhere... 0400 else 0401 m_templateParams.insert(currentIndex, nameParts.last()); 0402 } 0403 } 0404 0405 handleOptionalNameComponent(component->u.s_binary.right, nameParts); 0406 break; 0407 } 0408 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 32) 0409 case DEMANGLE_COMPONENT_TPARM_OBJ: 0410 handleNameComponent(component->u.s_binary.left, nameParts); 0411 nameParts.last().prepend(QByteArray("template parameter object for ")); 0412 break; 0413 #endif 0414 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 23) 0415 case DEMANGLE_COMPONENT_INITIALIZER_LIST: 0416 { 0417 QVector<QByteArray> parts; 0418 handleNameComponent(component->u.s_binary.left, parts); 0419 handleNameComponent(component->u.s_binary.right, parts); 0420 nameParts.push_back(parts.at(0) + "{" + parts.at(1) + "}"); 0421 break; 0422 } 0423 #endif 0424 case DEMANGLE_COMPONENT_OPERATOR: 0425 nameParts.push_back(QByteArray("operator") + QByteArray(component->u.s_operator.op->name, component->u.s_operator.op->len)); 0426 break; 0427 case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: 0428 handleNameComponent(component->u.s_extended_operator.name, nameParts); 0429 break; 0430 case DEMANGLE_COMPONENT_CAST: 0431 handleNameComponent(component->u.s_binary.left, nameParts); 0432 nameParts.last().prepend("operator "); 0433 break; 0434 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 26) 0435 case DEMANGLE_COMPONENT_CONVERSION: 0436 handleNameComponent(component->u.s_binary.left, nameParts); 0437 nameParts.last().prepend("operator "); 0438 break; 0439 #endif 0440 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 23) 0441 case DEMANGLE_COMPONENT_NULLARY: 0442 handleNameComponent(component->u.s_binary.left, nameParts); 0443 break; 0444 #endif 0445 case DEMANGLE_COMPONENT_UNARY: 0446 { 0447 handleOperatorComponent(component->u.s_binary.left, nameParts); 0448 handleNameComponent(component->u.s_binary.right, nameParts); 0449 const QByteArray arg = nameParts.takeLast(); 0450 const QByteArray op = nameParts.takeLast(); 0451 nameParts.push_back(op + arg); 0452 break; 0453 } 0454 case DEMANGLE_COMPONENT_BINARY: 0455 { 0456 handleOperatorComponent(component->u.s_binary.left, nameParts); 0457 handleNameComponent(component->u.s_binary.right, nameParts); 0458 const QByteArray arg2 = nameParts.takeLast(); 0459 const QByteArray arg1 = nameParts.takeLast(); 0460 const QByteArray op = nameParts.takeLast(); 0461 nameParts.push_back(arg1 + op + arg2); 0462 break; 0463 } 0464 case DEMANGLE_COMPONENT_BINARY_ARGS: 0465 case DEMANGLE_COMPONENT_TRINARY: 0466 case DEMANGLE_COMPONENT_TRINARY_ARG1: 0467 case DEMANGLE_COMPONENT_TRINARY_ARG2: 0468 handleNameComponent(component->u.s_binary.left, nameParts); 0469 handleNameComponent(component->u.s_binary.right, nameParts); 0470 break; 0471 case DEMANGLE_COMPONENT_LITERAL: 0472 case DEMANGLE_COMPONENT_LITERAL_NEG: 0473 { 0474 // left is type, right is value 0475 QVector<QByteArray> type; 0476 handleNameComponent(component->u.s_binary.left, type); 0477 handleNameComponent(component->u.s_binary.right, type); 0478 if (component->type == DEMANGLE_COMPONENT_LITERAL_NEG) 0479 type.last().prepend('-'); 0480 QByteArray typeStr; 0481 // TODO add: unsigned, long, long long, unsigned long long 0482 if (type.first() == "bool") { 0483 typeStr = type.last() == "0" ? "false" : "true"; 0484 } else if (type.first() == "int") { 0485 typeStr = type.last(); 0486 } else if (type.first() == "unsigned long") { 0487 typeStr = type.last() + "ul"; 0488 } else { // custom type 0489 typeStr = '(' + type.first() + ')' + type.last(); 0490 } 0491 nameParts.push_back(typeStr); 0492 break; 0493 } 0494 case DEMANGLE_COMPONENT_NUMBER: 0495 nameParts.push_back(QByteArray::number((int)component->u.s_number.number)); 0496 break; 0497 case DEMANGLE_COMPONENT_DECLTYPE: 0498 // TODO: undocumented, but one seems to contain content at least 0499 handleOptionalNameComponent(component->u.s_binary.left, nameParts); 0500 handleOptionalNameComponent(component->u.s_binary.right, nameParts); 0501 break; 0502 case DEMANGLE_COMPONENT_LAMBDA: 0503 { 0504 QVector<QByteArray> args; 0505 handleNameComponent(component->u.s_unary_num.sub, args); 0506 nameParts.push_back("{lambda(" + join(args, ", ") + ")#" + QByteArray::number(component->u.s_unary_num.num + 1) + '}'); 0507 break; 0508 } 0509 case DEMANGLE_COMPONENT_DEFAULT_ARG: 0510 nameParts.push_back(QByteArray("{default arg#") + QByteArray::number((int)component->u.s_unary_num.num + 1) + '}'); 0511 handleOptionalNameComponent(component->u.s_unary_num.sub, nameParts); 0512 break; 0513 case DEMANGLE_COMPONENT_UNNAMED_TYPE: 0514 nameParts.push_back(QByteArray("{unnamed type#") + QByteArray::number((int)component->u.s_number.number + 1) + '}'); 0515 break; 0516 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 23) 0517 case DEMANGLE_COMPONENT_TRANSACTION_CLONE: 0518 handleNameComponent(component->u.s_binary.left, nameParts); 0519 nameParts.last().prepend("transaction clone for "); 0520 break; 0521 case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: 0522 handleNameComponent(component->u.s_binary.left, nameParts); 0523 nameParts.last().prepend("non-transaction clone for "); 0524 break; 0525 #endif 0526 case DEMANGLE_COMPONENT_PACK_EXPANSION: 0527 handleOptionalNameComponent(component->u.s_binary.left, nameParts); 0528 handleOptionalNameComponent(component->u.s_binary.right, nameParts); 0529 break; 0530 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 24) 0531 case DEMANGLE_COMPONENT_TAGGED_NAME: 0532 { 0533 QVector<QByteArray> args; 0534 handleNameComponent(component->u.s_binary.left, nameParts); 0535 handleNameComponent(component->u.s_binary.right, args); 0536 const auto n = nameParts.takeLast(); 0537 nameParts.push_back(n + "[abi:" + args.last() + ']'); 0538 break; 0539 } 0540 #endif 0541 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 23) 0542 case DEMANGLE_COMPONENT_CLONE: 0543 { 0544 QVector<QByteArray> args; 0545 handleNameComponent(component->u.s_binary.left, nameParts); 0546 handleNameComponent(component->u.s_binary.right, args); 0547 const auto n = nameParts.takeLast(); 0548 nameParts.push_back(n + " [clone " + args.last() + ']'); 0549 break; 0550 } 0551 #endif 0552 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 28) 0553 case DEMANGLE_COMPONENT_NOEXCEPT: 0554 { 0555 handleNameComponent(component->u.s_binary.left, nameParts); 0556 const auto n = nameParts.takeLast(); 0557 nameParts.push_back(n + " noexcept"); 0558 break; 0559 } 0560 #endif 0561 default: 0562 qDebug() << Q_FUNC_INFO << "unhandled component type" << component->type << m_mangledName; 0563 } 0564 } 0565 0566 void Demangler::handleOptionalNameComponent(demangle_component* component, QVector< QByteArray >& nameParts) 0567 { 0568 if (!component) 0569 return; 0570 handleNameComponent(component, nameParts); 0571 } 0572 0573 void Demangler::handleOperatorComponent(demangle_component* component, QVector< QByteArray >& nameParts) 0574 { 0575 if (component->type == DEMANGLE_COMPONENT_OPERATOR) { 0576 nameParts.push_back(QByteArray(component->u.s_operator.op->name, component->u.s_operator.op->len)); 0577 return; 0578 } 0579 handleNameComponent(component, nameParts); 0580 } 0581 0582 Demangler::SymbolType Demangler::symbolType(const char* name) 0583 { 0584 if (strlen(name) < 4) 0585 return SymbolType::Normal; 0586 if (name[0] != '_' || name[1] != 'Z' || name[2] != 'T') 0587 return SymbolType::Normal; 0588 0589 switch (name[3]) { 0590 case 'V': return SymbolType::VTable; 0591 case 'I': return SymbolType::TypeInfo; 0592 case 'S': return SymbolType::TypeInfoName; 0593 case 'T': return SymbolType::VTT; 0594 case 'C': return SymbolType::ConstructionVTable; 0595 } 0596 0597 return SymbolType::Normal; 0598 }