File indexing completed on 2024-05-05 05:44:03

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 
0020 // workarounds for conflicting declaration in libiberty.h
0021 #define HAVE_DECL_BASENAME 1
0022 #define HAVE_DECL_ASPRINTF 1
0023 #define HAVE_DECL_VASPRINTF 1
0024 
0025 #include <demangle.h>
0026 
0027 #include <QByteArray>
0028 
0029 #include <iostream>
0030 
0031 using namespace std;
0032 
0033 // not in a public binutils header, but needed anyway
0034 struct demangle_operator_info
0035 {
0036     const char *type;
0037     const char *name;
0038     int len;
0039     int args;
0040 };
0041 
0042 struct demangle_builtin_type_info {
0043     const char *name;
0044     int len;
0045     const char *java_name;
0046     int java_len;
0047     /*enum d_builtin_type_print*/ int print;
0048 };
0049 
0050 static int nodeCount = 0;
0051 
0052 static void writeNode(const char* name)
0053 {
0054     cout << "    node" << nodeCount << "[label = \"" << name << "\"];" << endl;
0055 }
0056 
0057 static void writeLink(int source, int target)
0058 {
0059     if (source == 0 || target == 0)
0060         return;
0061     cout << "    node" << source << " -> node" << target << ";" << endl;
0062 }
0063 
0064 static int handleNameComponent(demangle_component* component)
0065 {
0066     if (!component)
0067         return 0;
0068 
0069     ++nodeCount;
0070     const int sourceNode = nodeCount;
0071     switch (component->type) {
0072         case DEMANGLE_COMPONENT_NAME:
0073             writeNode(QByteArray(component->u.s_name.s, component->u.s_name.len));
0074             break;
0075         case DEMANGLE_COMPONENT_QUAL_NAME:
0076             writeNode("QUAL_NAME");
0077             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0078             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0079             break;
0080         case DEMANGLE_COMPONENT_LOCAL_NAME:
0081             writeNode("LOCAL_NAME");
0082             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0083             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0084             break;
0085         case DEMANGLE_COMPONENT_TYPED_NAME:
0086             writeNode("TYPED_NAME");
0087             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0088             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0089             break;
0090         case DEMANGLE_COMPONENT_TEMPLATE:
0091             writeNode("TEMPLATE");
0092             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0093             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0094             break;
0095         case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
0096             writeNode(QByteArray("TEMPLATE_PARAM: ") + QByteArray::number((int)component->u.s_number.number));
0097             // ???
0098             break;
0099         case DEMANGLE_COMPONENT_FUNCTION_PARAM:
0100             writeNode(QByteArray("FUNCTION_PARAM: ") + QByteArray::number((int)component->u.s_number.number));
0101             // ??? "This holds a number, which is the  parameter index."
0102             break;
0103         case DEMANGLE_COMPONENT_CTOR:
0104             writeNode("CTOR");
0105             // TODO: do we need to consider u.s_ctor.kind?
0106             writeLink(sourceNode, handleNameComponent(component->u.s_ctor.name));
0107             break;
0108         case DEMANGLE_COMPONENT_DTOR:
0109             writeNode("DTOR");
0110             // TODO: do we need to consider u.s_dtor.kind?
0111             writeLink(sourceNode, handleNameComponent(component->u.s_dtor.name));
0112             break;
0113         case DEMANGLE_COMPONENT_VTABLE:
0114             writeNode("VTABLE");
0115             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0116             break;
0117         case DEMANGLE_COMPONENT_VTT:
0118             writeNode("VTT");
0119             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0120             break;
0121         case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
0122             writeNode("CONSTRUCTION_VTABLE");
0123             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0124             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0125             break;
0126         case DEMANGLE_COMPONENT_TYPEINFO:
0127             writeNode("TYPEINFO");
0128             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0129             break;
0130         case DEMANGLE_COMPONENT_TYPEINFO_NAME:
0131             writeNode("TYPEINFO_NAME");
0132             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0133             break;
0134         case DEMANGLE_COMPONENT_TYPEINFO_FN:
0135             writeNode("TYPEINFO_FN");
0136             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0137             break;
0138         case DEMANGLE_COMPONENT_THUNK:
0139             writeNode("THUNK");
0140             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0141             break;
0142         case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
0143             writeNode("VIRTUAL_THUNK");
0144             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0145             break;
0146         case DEMANGLE_COMPONENT_COVARIANT_THUNK:
0147             writeNode("COVARIANT_THUNK");
0148             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0149             break;
0150         case DEMANGLE_COMPONENT_JAVA_CLASS:
0151             writeNode("JAVA_CLASS");
0152             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0153             break;
0154         case DEMANGLE_COMPONENT_GUARD:
0155             writeNode("GUARD");
0156             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0157             break;
0158 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 24)
0159         case DEMANGLE_COMPONENT_TLS_INIT:
0160             writeNode("TLS_INIT");
0161             // content?
0162             break;
0163         case DEMANGLE_COMPONENT_TLS_WRAPPER:
0164             writeNode("TLS_WRAPPER");
0165             // content ??
0166             break;
0167 #endif
0168         case DEMANGLE_COMPONENT_REFTEMP:
0169             writeNode("REFTEMP");
0170             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0171             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0172             break;
0173         case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
0174             writeNode("HIDDEN_ALIAS");
0175             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0176             break;
0177         case DEMANGLE_COMPONENT_SUB_STD:
0178             writeNode(QByteArray("SUB_STD: ") + QByteArray(component->u.s_name.s, component->u.s_name.len));
0179             break;
0180         case DEMANGLE_COMPONENT_RESTRICT:
0181             writeNode("RESTRICT");
0182             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0183             break;
0184         case DEMANGLE_COMPONENT_VOLATILE:
0185             writeNode("VOLATILE");
0186             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0187             break;
0188         case DEMANGLE_COMPONENT_CONST:
0189             writeNode("CONST");
0190             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0191             break;
0192         case DEMANGLE_COMPONENT_RESTRICT_THIS:
0193             writeNode("RESTRICT_THIS");
0194             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0195             break;
0196         case DEMANGLE_COMPONENT_VOLATILE_THIS:
0197             writeNode("VOLATILE_THIS");
0198             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0199             break;
0200         case DEMANGLE_COMPONENT_CONST_THIS:
0201             writeNode("CONST_THIS");
0202             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0203             break;
0204 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 24)
0205         case DEMANGLE_COMPONENT_REFERENCE_THIS:
0206             writeNode("REFERENCE_THIS");
0207             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0208             break;
0209         case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
0210             writeNode("RVALUE_REFERENCE_THIS");
0211             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0212             break;
0213 #endif
0214         case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
0215             writeNode("VENDOR_TYPE_QUAL");
0216             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0217             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0218             break;
0219         case DEMANGLE_COMPONENT_POINTER:
0220             writeNode("POINTER");
0221             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0222             break;
0223         case DEMANGLE_COMPONENT_REFERENCE:
0224             writeNode("REFERENCE");
0225             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0226             break;
0227         case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
0228             writeNode("RVALUE_REFERENCE");
0229             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0230             break;
0231         case DEMANGLE_COMPONENT_COMPLEX:
0232             writeNode("COMPLEX");
0233             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0234             break;
0235         case DEMANGLE_COMPONENT_IMAGINARY:
0236             writeNode("IMAGINARY");
0237             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0238             break;
0239         case DEMANGLE_COMPONENT_BUILTIN_TYPE:
0240             writeNode(QByteArray("BUILTIN_TYPE: ") + QByteArray(component->u.s_builtin.type->name, component->u.s_builtin.type->len));
0241             break;
0242         case DEMANGLE_COMPONENT_VENDOR_TYPE:
0243             writeNode("VENDOR_TYPE");
0244             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0245             break;
0246         case DEMANGLE_COMPONENT_FUNCTION_TYPE:
0247             writeNode("FUNCTION_TYPE");
0248             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0249             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0250             break;
0251         case DEMANGLE_COMPONENT_ARRAY_TYPE:
0252             writeNode("ARRAY_TYPE");
0253             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0254             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0255             break;
0256         case DEMANGLE_COMPONENT_PTRMEM_TYPE:
0257             writeNode("PTRMEM_TYPE");
0258             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0259             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0260             break;
0261         case DEMANGLE_COMPONENT_FIXED_TYPE:
0262             writeNode("FIXED_TYPE");
0263             // TODO ???
0264             break;
0265         case DEMANGLE_COMPONENT_VECTOR_TYPE:
0266             writeNode("VECTOR_TYPE");
0267             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0268             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0269             break;
0270         case DEMANGLE_COMPONENT_ARGLIST:
0271             writeNode("ARGLIST");
0272             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0273             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0274             break;
0275         case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
0276             writeNode("TEMPLATE_ARGLIST");
0277             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0278             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0279             break;
0280 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 32)
0281         case DEMANGLE_COMPONENT_TPARM_OBJ:
0282             writeNode("TPARM_OBJ");
0283             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0284         break;
0285 #endif
0286 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 23)
0287         case DEMANGLE_COMPONENT_INITIALIZER_LIST:
0288             writeNode("INITIALIZER_LIST");
0289             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0290             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0291             break;
0292 #endif
0293         case DEMANGLE_COMPONENT_OPERATOR:
0294             writeNode(QByteArray("OPERATOR ") + QByteArray(component->u.s_operator.op->name, component->u.s_operator.op->len));
0295             break;
0296         case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
0297             writeNode("EXTENDED_OPERATOR");
0298             // TODO
0299   /* An extended operator.  This holds the number of arguments, and
0300      the name of the extended operator.  */
0301             break;
0302         case DEMANGLE_COMPONENT_CAST:
0303             writeNode("CAST");
0304             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0305             break;
0306 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 26)
0307         case DEMANGLE_COMPONENT_CONVERSION:
0308             writeNode("CONVERSION");
0309             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0310             break;
0311 #endif
0312 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 23)
0313         case DEMANGLE_COMPONENT_NULLARY:
0314             writeNode("NULLARY");
0315             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0316             break;
0317 #endif
0318         case DEMANGLE_COMPONENT_UNARY:
0319             writeNode("UNARY");
0320             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0321             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0322             break;
0323         case DEMANGLE_COMPONENT_BINARY:
0324             writeNode("BINARY");
0325             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0326             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0327             break;
0328         case DEMANGLE_COMPONENT_BINARY_ARGS:
0329             writeNode("BINARY_ARGS");
0330             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0331             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0332             break;
0333         case DEMANGLE_COMPONENT_TRINARY:
0334             writeNode("TRINARY");
0335             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0336             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0337             break;
0338         case DEMANGLE_COMPONENT_TRINARY_ARG1:
0339             writeNode("TRINARY_ARG1");
0340             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0341             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0342             break;
0343         case DEMANGLE_COMPONENT_TRINARY_ARG2:
0344             writeNode("TRINARY_ARG2");
0345             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0346             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0347             break;
0348         case DEMANGLE_COMPONENT_LITERAL:
0349             writeNode("LITERAL");
0350             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0351             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0352             break;
0353         case DEMANGLE_COMPONENT_LITERAL_NEG:
0354             writeNode("LITERAL_NEG");
0355             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0356             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0357             break;
0358         case DEMANGLE_COMPONENT_JAVA_RESOURCE:
0359             writeNode("JAVA_RESOURCE");
0360             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0361             break;
0362         case DEMANGLE_COMPONENT_COMPOUND_NAME:
0363             writeNode("COMPOUND_NAME");
0364             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0365             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0366             break;
0367         case DEMANGLE_COMPONENT_CHARACTER:
0368             writeNode("CHARACTER");
0369             // TODO: content?
0370             break;
0371         case DEMANGLE_COMPONENT_NUMBER:
0372             writeNode(QByteArray("NUMBER: ") + QByteArray::number((int)component->u.s_number.number));
0373             break;
0374         case DEMANGLE_COMPONENT_DECLTYPE:
0375             writeNode("DECLTYPE");
0376             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0377             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0378             // TODO: content?
0379             break;
0380         case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
0381             writeNode("GLOBAL_CONSTRUCTORS");
0382             // TODO: content?
0383             break;
0384         case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
0385             writeNode("GLOBAL_DESTRUCTORS");
0386             // TODO: content?
0387             break;
0388         case DEMANGLE_COMPONENT_LAMBDA:
0389             writeNode(QByteArray("LAMBDA: ") + QByteArray::number(component->u.s_unary_num.num));
0390             writeLink(sourceNode, handleNameComponent(component->u.s_unary_num.sub));
0391             break;
0392         case DEMANGLE_COMPONENT_DEFAULT_ARG:
0393             writeNode(QByteArray("DEFAULT_ARG: ") + QByteArray::number((int)component->u.s_unary_num.num));
0394             writeLink(sourceNode, handleNameComponent(component->u.s_unary_num.sub));
0395             break;
0396         case DEMANGLE_COMPONENT_UNNAMED_TYPE:
0397             writeNode(QByteArray("UNNAMED_TYPE: ") + QByteArray::number((int)component->u.s_number.number));
0398             break;
0399 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 23)
0400         case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
0401             writeNode("TRANSACTION_CLONE");
0402             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0403             break;
0404         case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
0405             writeNode("NONTRANSACTION_CLONE");
0406             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0407             break;
0408 #endif
0409         case DEMANGLE_COMPONENT_PACK_EXPANSION:
0410             writeNode("PACK_EXPANSION");
0411             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0412             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0413             break;
0414 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 24)
0415         case DEMANGLE_COMPONENT_TAGGED_NAME:
0416             writeNode("TAGGED_NAME");
0417             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0418             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0419             break;
0420 #endif
0421 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 27)
0422         case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
0423             writeNode("TRANSACTION_SAFE");
0424             // ??
0425             break;
0426 #endif
0427 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 23)
0428         case DEMANGLE_COMPONENT_CLONE:
0429             writeNode("COMPONENT_CLONE");
0430             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0431             writeLink(sourceNode, handleNameComponent(component->u.s_binary.right));
0432             break;
0433 #endif
0434 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 28)
0435         case DEMANGLE_COMPONENT_NOEXCEPT:
0436             writeNode("NOEXCEPT");
0437             writeLink(sourceNode, handleNameComponent(component->u.s_binary.left));
0438             break;
0439         case DEMANGLE_COMPONENT_THROW_SPEC:
0440             writeNode("THROW_SPEC");
0441             // ??
0442             break;
0443 #endif
0444     }
0445     return sourceNode;
0446 }
0447 
0448 int main(int argc, char** argv)
0449 {
0450     if (argc < 2)
0451         return 1;
0452 
0453     void *memory = nullptr;
0454     demangle_component *component = cplus_demangle_v3_components(argv[1], DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES | DMGL_VERBOSE, &memory);
0455 
0456     cout << "digraph ast {" << endl;
0457 
0458     handleNameComponent(component);
0459 
0460     cout << "}" << endl;
0461 
0462     size_t size;
0463     char * fullName = cplus_demangle_print(DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES | DMGL_VERBOSE, component, strlen(argv[1]), &size);
0464     cerr << fullName << endl;
0465     free(fullName);
0466 
0467     free(memory);
0468     return 0;
0469 }