1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <getopt.h> 18#include <stdio.h> 19#include <stdlib.h> 20#include <string.h> 21#include <unistd.h> 22 23#include <string> 24 25#include <demangle.h> 26 27extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*); 28 29void usage(const char* prog_name) { 30 printf("Usage: %s [-c] <NAME_TO_DEMANGLE>\n", prog_name); 31 printf(" -c\n"); 32 printf(" Compare the results of __cxa_demangle against the current\n"); 33 printf(" demangler.\n"); 34} 35 36std::string DemangleWithCxa(const char* name) { 37 const char* cxa_demangle = __cxa_demangle(name, nullptr, nullptr, nullptr); 38 39 if (cxa_demangle == nullptr) { 40 return name; 41 } 42 43 // The format of our demangler is slightly different from the cxa demangler 44 // so modify the cxa demangler output. Specifically, for templates, remove 45 // the spaces between '>' and '>'. 46 std::string demangled_str; 47 for (size_t i = 0; i < strlen(cxa_demangle); i++) { 48 if (i > 2 && cxa_demangle[i] == '>' && std::isspace(cxa_demangle[i - 1]) && 49 cxa_demangle[i - 2] == '>') { 50 demangled_str.resize(demangled_str.size() - 1); 51 } 52 demangled_str += cxa_demangle[i]; 53 } 54 return demangled_str; 55} 56 57int main(int argc, char** argv) { 58#ifdef __BIONIC__ 59 const char* prog_name = getprogname(); 60#else 61 const char* prog_name = argv[0]; 62#endif 63 64 bool compare = false; 65 int opt_char; 66 while ((opt_char = getopt(argc, argv, "c")) != -1) { 67 if (opt_char == 'c') { 68 compare = true; 69 } else { 70 usage(prog_name); 71 return 1; 72 } 73 } 74 if (optind >= argc || argc - optind != 1) { 75 printf("Must supply a single argument.\n\n"); 76 usage(prog_name); 77 return 1; 78 } 79 const char* name = argv[optind]; 80 81 std::string demangled_name = demangle(name); 82 83 printf("%s\n", demangled_name.c_str()); 84 85 if (compare) { 86 std::string cxa_demangle_str(DemangleWithCxa(name)); 87 88 if (cxa_demangle_str != demangled_name) { 89 printf("Mismatch\n"); 90 printf("cxa demangle: %s\n", cxa_demangle_str.c_str()); 91 return 1; 92 } else { 93 printf("Match\n"); 94 } 95 } 96 return 0; 97} 98