Path: blob/main/contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c
39478 views
/*-1* Copyright (c) 2008 Hyogeol Lee <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer9* in this position and unchanged.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR15* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES16* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.17* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,18* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT19* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,20* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY21* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT22* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF23* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.24*/2526#include <sys/types.h>27#include <assert.h>28#include <ctype.h>29#include <errno.h>30#include <libelftc.h>31#include <limits.h>32#include <stdbool.h>33#include <stdio.h>34#include <stdlib.h>35#include <string.h>3637#include "_libelftc.h"3839ELFTC_VCSID("$Id: libelftc_dem_gnu2.c 3513 2016-12-29 07:04:22Z kaiwang27 $");4041/**42* @file cpp_demangle_gnu2.c43* @brief Decode function name encoding in GNU 2.44*45* Function name encoding in GNU 2 based on ARM style.46*/4748enum encode_type {49ENCODE_FUNC, ENCODE_OP, ENCODE_OP_CT, ENCODE_OP_DT, ENCODE_OP_USER,50ENCODE_OP_TF, ENCODE_OP_TI, ENCODE_OP_VT51};5253struct cstring {54char *buf;55size_t size;56};5758struct demangle_data {59bool ptr, ref, cnst, array, cnst_fn, class_name;60struct cstring array_str;61const char *p;62enum encode_type type;63struct vector_str vec;64struct vector_str arg;65};6667#define SIMPLE_HASH(x,y) (64 * x + y)68#define VEC_PUSH_STR(d,s) vector_str_push((d), (s), strlen((s)))69#define CPP_DEMANGLE_GNU2_TRY 1287071static void dest_cstring(struct cstring *);72static void dest_demangle_data(struct demangle_data *);73static bool init_cstring(struct cstring *, size_t);74static bool init_demangle_data(struct demangle_data *);75static bool push_CTDT(const char *, size_t, struct vector_str *);76static bool read_array(struct demangle_data *);77static bool read_class(struct demangle_data *);78static bool read_func(struct demangle_data *);79static bool read_func_name(struct demangle_data *);80static bool read_func_ptr(struct demangle_data *);81static bool read_memptr(struct demangle_data *);82static bool read_op(struct demangle_data *);83static bool read_op_user(struct demangle_data *);84static bool read_qual_name(struct demangle_data *);85static int read_subst(struct demangle_data *);86static int read_subst_iter(struct demangle_data *);87static bool read_type(struct demangle_data *);8889/**90* @brief Decode the input string by the GNU 2 style.91*92* @return New allocated demangled string or NULL if failed.93*/94char *95cpp_demangle_gnu2(const char *org)96{97struct demangle_data d;98size_t arg_begin, arg_len;99unsigned int try;100char *rtn, *arg;101102if (org == NULL)103return (NULL);104105if (init_demangle_data(&d) == false)106return (NULL);107108try = 0;109rtn = NULL;110111d.p = org;112if (read_func_name(&d) == false)113goto clean;114115switch (d.type) {116case ENCODE_FUNC :117case ENCODE_OP :118break;119120case ENCODE_OP_CT :121if (push_CTDT("::", 2, &d.vec) == false)122goto clean;123124break;125case ENCODE_OP_DT :126if (push_CTDT("::~", 3, &d.vec) == false)127goto clean;128129if (VEC_PUSH_STR(&d.vec, "(void)") == false)130goto clean;131132goto flat;133case ENCODE_OP_USER :134case ENCODE_OP_TF :135case ENCODE_OP_TI :136case ENCODE_OP_VT :137goto flat;138}139140if (*d.p == 'F')141++d.p;142else if (*d.p == '\0') {143if (d.class_name == true) {144if (VEC_PUSH_STR(&d.vec, "(void)") == false)145goto clean;146147goto flat;148} else149goto clean;150}151152/* start argument types */153if (VEC_PUSH_STR(&d.vec, "(") == false)154goto clean;155156for (;;) {157if (*d.p == 'T') {158const int rtn_subst = read_subst(&d);159160if (rtn_subst == -1)161goto clean;162else if (rtn_subst == 1)163break;164165continue;166}167168if (*d.p == 'N') {169const int rtn_subst_iter = read_subst_iter(&d);170171if (rtn_subst_iter == -1)172goto clean;173else if(rtn_subst_iter == 1)174break;175176continue;177}178179arg_begin = d.vec.size;180181if (read_type(&d) == false)182goto clean;183184if (d.ptr == true) {185if (VEC_PUSH_STR(&d.vec, "*") == false)186goto clean;187188d.ptr = false;189}190191if (d.ref == true) {192if (VEC_PUSH_STR(&d.vec, "&") == false)193goto clean;194195d.ref = false;196}197198if (d.cnst == true) {199if (VEC_PUSH_STR(&d.vec, " const") == false)200goto clean;201202d.cnst = false;203}204205if (d.array == true) {206if (vector_str_push(&d.vec, d.array_str.buf,207d.array_str.size) == false)208goto clean;209210dest_cstring(&d.array_str);211d.array = false;212}213214if (*d.p == '\0')215break;216217if ((arg = vector_str_substr(&d.vec, arg_begin, d.vec.size - 1,218&arg_len)) == NULL)219goto clean;220221if (vector_str_push(&d.arg, arg, arg_len) == false) {222free(arg);223goto clean;224}225226free(arg);227228if (VEC_PUSH_STR(&d.vec, ", ") == false)229goto clean;230231if (++try > CPP_DEMANGLE_GNU2_TRY)232goto clean;233}234235/* end argument types */236if (VEC_PUSH_STR(&d.vec, ")") == false)237goto clean;238flat:239if (d.cnst_fn == true && VEC_PUSH_STR(&d.vec, " const") == false)240goto clean;241242rtn = vector_str_get_flat(&d.vec, NULL);243clean:244dest_demangle_data(&d);245246return (rtn);247}248249/**250* @brief Test input string is encoded by the GNU 2 style.251*252* @return True if input string is encoded by the GNU 2 style.253*/254bool255is_cpp_mangled_gnu2(const char *org)256{257char *str;258bool rtn = false;259260if (org == NULL)261return (false);262263/* search valid text to end */264str = strstr(org, "__");265while (str != NULL) {266if (*(str + 2) != '\0') {267if (*(str + 2) == 'C' ||268*(str + 2) == 'F' ||269*(str + 2) == 'Q' ||270ELFTC_ISDIGIT(*(str + 2))) {271rtn |= true;272273break;274}275276if (*(str + 3) != '\0') {277switch (SIMPLE_HASH(*(str + 2), *(str + 3))) {278case SIMPLE_HASH('m', 'l') :279case SIMPLE_HASH('d', 'v') :280case SIMPLE_HASH('m', 'd') :281case SIMPLE_HASH('p', 'l') :282case SIMPLE_HASH('m', 'i') :283case SIMPLE_HASH('l', 's') :284case SIMPLE_HASH('r', 's') :285case SIMPLE_HASH('e', 'q') :286case SIMPLE_HASH('n', 'e') :287case SIMPLE_HASH('l', 't') :288case SIMPLE_HASH('g', 't') :289case SIMPLE_HASH('l', 'e') :290case SIMPLE_HASH('g', 'e') :291case SIMPLE_HASH('a', 'd') :292case SIMPLE_HASH('o', 'r') :293case SIMPLE_HASH('e', 'r') :294case SIMPLE_HASH('a', 'a') :295case SIMPLE_HASH('o', 'o') :296case SIMPLE_HASH('n', 't') :297case SIMPLE_HASH('c', 'o') :298case SIMPLE_HASH('p', 'p') :299case SIMPLE_HASH('m', 'm') :300case SIMPLE_HASH('a', 's') :301case SIMPLE_HASH('r', 'f') :302case SIMPLE_HASH('a', 'p') :303case SIMPLE_HASH('a', 'm') :304case SIMPLE_HASH('a', 'l') :305case SIMPLE_HASH('a', 'r') :306case SIMPLE_HASH('a', 'o') :307case SIMPLE_HASH('a', 'e') :308case SIMPLE_HASH('c', 'm') :309case SIMPLE_HASH('r', 'm') :310case SIMPLE_HASH('c', 'l') :311case SIMPLE_HASH('v', 'c') :312case SIMPLE_HASH('n', 'w') :313case SIMPLE_HASH('d', 'l') :314case SIMPLE_HASH('o', 'p') :315case SIMPLE_HASH('t', 'f') :316case SIMPLE_HASH('t', 'i') :317rtn |= true;318319break;320}321}322}323324str = strstr(str + 2, "__");325}326327rtn |= strstr(org, "_$_") != NULL;328rtn |= strstr(org, "_vt$") != NULL;329330return (rtn);331}332333static void334dest_cstring(struct cstring *s)335{336337if (s == NULL)338return;339340free(s->buf);341s->buf = NULL;342s->size = 0;343}344345static void346dest_demangle_data(struct demangle_data *d)347{348349if (d != NULL) {350vector_str_dest(&d->arg);351vector_str_dest(&d->vec);352353dest_cstring(&d->array_str);354}355}356357static bool358init_cstring(struct cstring *s, size_t len)359{360361if (s == NULL || len <= 1)362return (false);363364if ((s->buf = malloc(sizeof(char) * len)) == NULL)365return (false);366367s->size = len - 1;368369return (true);370}371372static bool373init_demangle_data(struct demangle_data *d)374{375376if (d == NULL)377return (false);378379d->ptr = false;380d->ref = false;381d->cnst = false;382d->array = false;383d->cnst_fn = false;384d->class_name = false;385386d->array_str.buf = NULL;387d->array_str.size = 0;388389d->type = ENCODE_FUNC;390391if (!vector_str_init(&d->vec))392return (false);393394if (!vector_str_init(&d->arg)) {395vector_str_dest(&d->vec);396return (false);397}398399return (true);400}401402static bool403push_CTDT(const char *s, size_t l, struct vector_str *v)404{405406if (s == NULL || l == 0 || v == NULL)407return (false);408409if (vector_str_push(v, s, l) == false)410return (false);411412assert(v->size > 1);413414return (VEC_PUSH_STR(v, v->container[v->size - 2]));415}416417static bool418read_array(struct demangle_data *d)419{420size_t len;421const char *end;422423if (d == NULL || d->p == NULL)424return (false);425426end = d->p;427assert(end != NULL);428429for (;;) {430if (*end == '\0')431return (false);432433if (ELFTC_ISDIGIT(*end) == 0)434break;435436++end;437}438439if (*end != '_')440return (false);441442len = end - d->p;443assert(len > 0);444445dest_cstring(&d->array_str);446if (init_cstring(&d->array_str, len + 3) == false)447return (false);448449strncpy(d->array_str.buf + 1, d->p, len);450*d->array_str.buf = '[';451*(d->array_str.buf + len + 1) = ']';452453d->array = true;454d->p = end + 1;455456return (true);457}458459static bool460read_class(struct demangle_data *d)461{462size_t len;463char *str;464465if (d == NULL)466return (false);467468len = strtol(d->p, &str, 10);469if (len == 0 && (errno == EINVAL || errno == ERANGE))470return (false);471472assert(len > 0);473assert(str != NULL);474475if (vector_str_push(&d->vec, str, len) == false)476return (false);477478d->p = str + len;479480d->class_name = true;481482return (true);483}484485static bool486read_func(struct demangle_data *d)487{488size_t len;489const char *name;490char *delim;491492if (d == NULL)493return (false);494495assert(d->p != NULL && "d->p (org str) is NULL");496if ((delim = strstr(d->p, "__")) == NULL)497return (false);498499len = delim - d->p;500assert(len != 0);501502name = d->p;503504d->p = delim + 2;505506if (*d->p == 'C') {507++d->p;508509d->cnst_fn = true;510}511512if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {513++d->p;514515if (read_qual_name(d) == false)516return (false);517} else if (ELFTC_ISDIGIT(*d->p)) {518if (read_class(d) == false)519return (false);520521if (VEC_PUSH_STR(&d->vec, "::") == false)522return (false);523}524525return (vector_str_push(&d->vec, name, len));526}527528static bool529read_func_name(struct demangle_data *d)530{531size_t len;532bool rtn;533char *op_name;534535if (d == NULL)536return (false);537538rtn = false;539op_name = NULL;540541assert(d->p != NULL && "d->p (org str) is NULL");542543if (*d->p == '_' && *(d->p + 1) == '_') {544d->p += 2;545546/* CTOR */547if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {548++d->p;549d->type = ENCODE_OP_CT;550551if (read_qual_name(d) == false)552return (false);553554return (vector_str_pop(&d->vec));555} else if (ELFTC_ISDIGIT(*d->p)) {556d->type = ENCODE_OP_CT;557558return (read_class(d));559}560561d->type = ENCODE_OP;562if (read_op(d) == false) {563/* not good condition, start function name with '__' */564d->type = ENCODE_FUNC;565566if (VEC_PUSH_STR(&d->vec, "__") == false)567return (false);568569return (read_func(d));570}571572if (d->type == ENCODE_OP_USER ||573d->type == ENCODE_OP_TF ||574d->type == ENCODE_OP_TI)575return (true);576577/* skip "__" */578d->p += 2;579580if (*d->p == 'C') {581++d->p;582583d->cnst_fn = true;584}585586/* assume delimiter is removed */587if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {588++d->p;589590assert(d->vec.size > 0);591592len = strlen(d->vec.container[d->vec.size - 1]);593if ((op_name = malloc(sizeof(char) * (len + 1)))594== NULL)595return (false);596597snprintf(op_name, len + 1, "%s",598d->vec.container[d->vec.size - 1]);599vector_str_pop(&d->vec);600601if (read_qual_name(d) == false)602goto clean;603604if (VEC_PUSH_STR(&d->vec, "::") == false)605goto clean;606607if (vector_str_push(&d->vec, op_name, len) == false)608goto clean;609610rtn = true;611} else if (ELFTC_ISDIGIT(*d->p)) {612assert(d->vec.size > 0);613614len = strlen(d->vec.container[d->vec.size - 1]);615if ((op_name = malloc(sizeof(char) * (len + 1)))616== NULL)617return (false);618619snprintf(op_name, len + 1, "%s",620d->vec.container[d->vec.size - 1]);621vector_str_pop(&d->vec);622623if (read_class(d) == false)624goto clean;625626if (VEC_PUSH_STR(&d->vec, "::") == false)627goto clean;628629if (vector_str_push(&d->vec, op_name, len) == false)630goto clean;631632rtn = true;633}634} else if (memcmp(d->p, "_$_", 3) == 0) {635/* DTOR */636d->p += 3;637d->type = ENCODE_OP_DT;638639if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {640++d->p;641642if (read_qual_name(d) == false)643return (false);644645return (vector_str_pop(&d->vec));646} else if (ELFTC_ISDIGIT(*d->p))647return (read_class(d));648649return (false);650} else if (memcmp(d->p, "_vt$", 4) == 0) {651/* vtable */652d->p += 4;653d->type = ENCODE_OP_VT;654655if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {656++d->p;657658if (read_qual_name(d) == false)659return (false);660661if (vector_str_pop(&d->vec) == false)662return (false);663} else if (ELFTC_ISDIGIT(*d->p)) {664if (read_class(d) == false)665return (false);666}667668return (VEC_PUSH_STR(&d->vec, " virtual table"));669} else670return (read_func(d));671clean:672free(op_name);673674return (rtn);675}676677/* Read function ptr type */678static bool679read_func_ptr(struct demangle_data *d)680{681struct demangle_data fptr;682size_t arg_len, rtn_len;683char *arg_type, *rtn_type;684int lim;685686if (d == NULL)687return (false);688689if (init_demangle_data(&fptr) == false)690return (false);691692fptr.p = d->p + 1;693lim = 0;694arg_type = NULL;695rtn_type = NULL;696697for (;;) {698if (read_type(&fptr) == false) {699dest_demangle_data(&fptr);700701return (false);702}703704if (fptr.ptr == true) {705if (VEC_PUSH_STR(&fptr.vec, "*") == false) {706dest_demangle_data(&fptr);707708return (false);709}710711fptr.ptr = false;712}713714if (fptr.ref == true) {715if (VEC_PUSH_STR(&fptr.vec, "&") == false) {716dest_demangle_data(&fptr);717718return (false);719}720721fptr.ref = false;722}723724if (fptr.cnst == true) {725if (VEC_PUSH_STR(&fptr.vec, " const") == false) {726dest_demangle_data(&fptr);727728return (false);729}730731fptr.cnst = false;732}733734if (*fptr.p == '_')735break;736737if (VEC_PUSH_STR(&fptr.vec, ", ") == false) {738dest_demangle_data(&fptr);739740return (false);741}742743if (++lim > CPP_DEMANGLE_GNU2_TRY) {744745dest_demangle_data(&fptr);746747return (false);748}749}750751arg_type = vector_str_get_flat(&fptr.vec, &arg_len);752/* skip '_' */753d->p = fptr.p + 1;754755dest_demangle_data(&fptr);756757if (init_demangle_data(&fptr) == false) {758free(arg_type);759760return (false);761}762763fptr.p = d->p;764lim = 0;765766if (read_type(&fptr) == false) {767free(arg_type);768dest_demangle_data(&fptr);769770return (false);771}772773rtn_type = vector_str_get_flat(&fptr.vec, &rtn_len);774d->p = fptr.p;775776777dest_demangle_data(&fptr);778779if (vector_str_push(&d->vec, rtn_type, rtn_len) == false) {780free(rtn_type);781free(arg_type);782783return (false);784}785786free(rtn_type);787788if (VEC_PUSH_STR(&d->vec, " (*)(") == false) {789free(arg_type);790791return (false);792}793794if (vector_str_push(&d->vec, arg_type, arg_len) == false) {795free(arg_type);796797return (false);798}799800free(arg_type);801802return (VEC_PUSH_STR(&d->vec, ")"));803}804805static bool806read_memptr(struct demangle_data *d)807{808struct demangle_data mptr;809size_t len;810bool rtn;811char *mptr_str;812813if (d == NULL || d->p == NULL)814return (false);815816if (init_demangle_data(&mptr) == false)817return (false);818819rtn = false;820mptr_str = NULL;821822mptr.p = d->p;823if (*mptr.p == 'Q') {824++mptr.p;825826if (read_qual_name(&mptr) == false)827goto clean;828} else if (read_class(&mptr) == false)829goto clean;830831d->p = mptr.p;832833if ((mptr_str = vector_str_get_flat(&mptr.vec, &len)) == NULL)834goto clean;835836if (vector_str_push(&d->vec, mptr_str, len) == false)837goto clean;838839if (VEC_PUSH_STR(&d->vec, "::*") == false)840goto clean;841842rtn = true;843clean:844free(mptr_str);845dest_demangle_data(&mptr);846847return (rtn);848}849850static bool851read_op(struct demangle_data *d)852{853854if (d == NULL)855return (false);856857assert(d->p != NULL && "d->p (org str) is NULL");858859switch (SIMPLE_HASH(*(d->p), *(d->p+1))) {860case SIMPLE_HASH('m', 'l') :861d->p += 2;862return (VEC_PUSH_STR(&d->vec, "operator*"));863case SIMPLE_HASH('d', 'v') :864d->p += 2;865return (VEC_PUSH_STR(&d->vec, "operator/"));866case SIMPLE_HASH('m', 'd') :867d->p += 2;868return (VEC_PUSH_STR(&d->vec, "operator%"));869case SIMPLE_HASH('p', 'l') :870d->p += 2;871return (VEC_PUSH_STR(&d->vec, "operator+"));872case SIMPLE_HASH('m', 'i') :873d->p += 2;874return (VEC_PUSH_STR(&d->vec, "operator-"));875case SIMPLE_HASH('l', 's') :876d->p += 2;877return (VEC_PUSH_STR(&d->vec, "operator<<"));878case SIMPLE_HASH('r', 's') :879d->p += 2;880return (VEC_PUSH_STR(&d->vec, "operator>>"));881case SIMPLE_HASH('e', 'q') :882d->p += 2;883return (VEC_PUSH_STR(&d->vec, "operator=="));884case SIMPLE_HASH('n', 'e') :885d->p += 2;886return (VEC_PUSH_STR(&d->vec, "operator!="));887case SIMPLE_HASH('l', 't') :888d->p += 2;889return (VEC_PUSH_STR(&d->vec, "operator<"));890case SIMPLE_HASH('g', 't') :891d->p += 2;892return (VEC_PUSH_STR(&d->vec, "operator>"));893case SIMPLE_HASH('l', 'e') :894d->p += 2;895return (VEC_PUSH_STR(&d->vec, "operator<="));896case SIMPLE_HASH('g', 'e') :897d->p += 2;898return (VEC_PUSH_STR(&d->vec, "operator>="));899case SIMPLE_HASH('a', 'd') :900d->p += 2;901if (*d->p == 'v') {902++d->p;903return (VEC_PUSH_STR(&d->vec, "operator/="));904} else905return (VEC_PUSH_STR(&d->vec, "operator&"));906case SIMPLE_HASH('o', 'r') :907d->p += 2;908return (VEC_PUSH_STR(&d->vec, "operator|"));909case SIMPLE_HASH('e', 'r') :910d->p += 2;911return (VEC_PUSH_STR(&d->vec, "operator^"));912case SIMPLE_HASH('a', 'a') :913d->p += 2;914if (*d->p == 'd') {915++d->p;916return (VEC_PUSH_STR(&d->vec, "operator&="));917} else918return (VEC_PUSH_STR(&d->vec, "operator&&"));919case SIMPLE_HASH('o', 'o') :920d->p += 2;921return (VEC_PUSH_STR(&d->vec, "operator||"));922case SIMPLE_HASH('n', 't') :923d->p += 2;924return (VEC_PUSH_STR(&d->vec, "operator!"));925case SIMPLE_HASH('c', 'o') :926d->p += 2;927return (VEC_PUSH_STR(&d->vec, "operator~"));928case SIMPLE_HASH('p', 'p') :929d->p += 2;930return (VEC_PUSH_STR(&d->vec, "operator++"));931case SIMPLE_HASH('m', 'm') :932d->p += 2;933return (VEC_PUSH_STR(&d->vec, "operator--"));934case SIMPLE_HASH('a', 's') :935d->p += 2;936return (VEC_PUSH_STR(&d->vec, "operator="));937case SIMPLE_HASH('r', 'f') :938d->p += 2;939return (VEC_PUSH_STR(&d->vec, "operator->"));940case SIMPLE_HASH('a', 'p') :941/* apl */942if (*(d->p + 2) != 'l')943return (false);944945d->p += 3;946return (VEC_PUSH_STR(&d->vec, "operator+="));947case SIMPLE_HASH('a', 'm') :948d->p += 2;949if (*d->p == 'i') {950++d->p;951return (VEC_PUSH_STR(&d->vec, "operator-="));952} else if (*d->p == 'u') {953++d->p;954return (VEC_PUSH_STR(&d->vec, "operator*="));955} else if (*d->p == 'd') {956++d->p;957return (VEC_PUSH_STR(&d->vec, "operator%="));958}959960return (false);961case SIMPLE_HASH('a', 'l') :962/* als */963if (*(d->p + 2) != 's')964return (false);965966d->p += 3;967return (VEC_PUSH_STR(&d->vec, "operator<<="));968case SIMPLE_HASH('a', 'r') :969/* ars */970if (*(d->p + 2) != 's')971return (false);972973d->p += 3;974return (VEC_PUSH_STR(&d->vec, "operator>>="));975case SIMPLE_HASH('a', 'o') :976/* aor */977if (*(d->p + 2) != 'r')978return (false);979980d->p += 3;981return (VEC_PUSH_STR(&d->vec, "operator|="));982case SIMPLE_HASH('a', 'e') :983/* aer */984if (*(d->p + 2) != 'r')985return (false);986987d->p += 3;988return (VEC_PUSH_STR(&d->vec, "operator^="));989case SIMPLE_HASH('c', 'm') :990d->p += 2;991return (VEC_PUSH_STR(&d->vec, "operator,"));992case SIMPLE_HASH('r', 'm') :993d->p += 2;994return (VEC_PUSH_STR(&d->vec, "operator->*"));995case SIMPLE_HASH('c', 'l') :996d->p += 2;997return (VEC_PUSH_STR(&d->vec, "()"));998case SIMPLE_HASH('v', 'c') :999d->p += 2;1000return (VEC_PUSH_STR(&d->vec, "[]"));1001case SIMPLE_HASH('n', 'w') :1002d->p += 2;1003return (VEC_PUSH_STR(&d->vec, "operator new()"));1004case SIMPLE_HASH('d', 'l') :1005d->p += 2;1006return (VEC_PUSH_STR(&d->vec, "operator delete()"));1007case SIMPLE_HASH('o', 'p') :1008/* __op<TO_TYPE>__<FROM_TYPE> */1009d->p += 2;10101011d->type = ENCODE_OP_USER;10121013return (read_op_user(d));1014case SIMPLE_HASH('t', 'f') :1015d->p += 2;1016d->type = ENCODE_OP_TF;10171018if (read_type(d) == false)1019return (false);10201021return (VEC_PUSH_STR(&d->vec, " type_info function"));1022case SIMPLE_HASH('t', 'i') :1023d->p += 2;1024d->type = ENCODE_OP_TI;10251026if (read_type(d) == false)1027return (false);10281029return (VEC_PUSH_STR(&d->vec, " type_info node"));1030default :1031return (false);1032};1033}10341035static bool1036read_op_user(struct demangle_data *d)1037{1038struct demangle_data from, to;1039size_t from_len, to_len;1040bool rtn;1041char *from_str, *to_str;10421043if (d == NULL)1044return (false);10451046if (init_demangle_data(&from) == false)1047return (false);10481049rtn = false;1050from_str = NULL;1051to_str = NULL;1052if (init_demangle_data(&to) == false)1053goto clean;10541055to.p = d->p;1056if (*to.p == 'Q') {1057++to.p;10581059if (read_qual_name(&to) == false)1060goto clean;10611062/* pop last '::' */1063if (vector_str_pop(&to.vec) == false)1064goto clean;1065} else {1066if (read_class(&to) == false)1067goto clean;10681069/* skip '__' */1070to.p += 2;1071}10721073if ((to_str = vector_str_get_flat(&to.vec, &to_len)) == NULL)1074goto clean;10751076from.p = to.p;1077if (*from.p == 'Q') {1078++from.p;10791080if (read_qual_name(&from) == false)1081goto clean;10821083/* pop last '::' */1084if (vector_str_pop(&from.vec) == false)1085goto clean;1086} else if (read_class(&from) == false)1087goto clean;10881089if ((from_str = vector_str_get_flat(&from.vec, &from_len)) == NULL)1090goto clean;10911092if (vector_str_push(&d->vec, from_str, from_len) == false)1093goto clean;10941095if (VEC_PUSH_STR(&d->vec, "::operator ") == false)1096goto clean;10971098if (vector_str_push(&d->vec, to_str, to_len) == false)1099goto clean;11001101rtn = VEC_PUSH_STR(&d->vec, "()");1102clean:1103free(to_str);1104free(from_str);1105dest_demangle_data(&to);1106dest_demangle_data(&from);11071108return (rtn);1109}11101111/* single digit + class names */1112static bool1113read_qual_name(struct demangle_data *d)1114{1115int i;1116char num;11171118if (d == NULL)1119return (false);11201121assert(d->p != NULL && "d->p (org str) is NULL");1122assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");11231124num = *d->p - 48;11251126assert(num > 0);11271128++d->p;1129for (i = 0; i < num ; ++i) {1130if (read_class(d) == false)1131return (false);11321133if (VEC_PUSH_STR(&d->vec, "::") == false)1134return (false);1135}11361137if (*d->p != '\0')1138d->p = d->p + 2;11391140return (true);1141}11421143/* Return -1 at fail, 0 at success, and 1 at end */1144static int1145read_subst(struct demangle_data *d)1146{1147size_t idx;1148char *str;11491150if (d == NULL)1151return (-1);11521153idx = strtol(d->p + 1, &str, 10);1154if (idx == 0 && (errno == EINVAL || errno == ERANGE))1155return (-1);11561157assert(idx > 0);1158assert(str != NULL);11591160d->p = str;11611162if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)1163return (-1);11641165if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)1166return (-1);11671168if (*d->p == '\0')1169return (1);11701171return (0);1172}11731174static int1175read_subst_iter(struct demangle_data *d)1176{1177int i;1178size_t idx;1179char repeat;1180char *str;11811182if (d == NULL)1183return (-1);11841185++d->p;1186assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");11871188repeat = *d->p - 48;11891190assert(repeat > 1);11911192++d->p;11931194idx = strtol(d->p, &str, 10);1195if (idx == 0 && (errno == EINVAL || errno == ERANGE))1196return (-1);11971198assert(idx > 0);1199assert(str != NULL);12001201d->p = str;12021203for (i = 0; i < repeat ; ++i) {1204if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)1205return (-1);12061207if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)1208return (-1);12091210if (i != repeat - 1 &&1211VEC_PUSH_STR(&d->vec, ", ") == false)1212return (-1);1213}12141215if (*d->p == '\0')1216return (1);12171218return (0);1219}12201221static bool1222read_type(struct demangle_data *d)1223{12241225if (d == NULL)1226return (false);12271228assert(d->p != NULL && "d->p (org str) is NULL");12291230while (*d->p == 'U' || *d->p == 'C' || *d->p == 'V' || *d->p == 'S' ||1231*d->p == 'P' || *d->p == 'R' || *d->p == 'A' || *d->p == 'F' ||1232*d->p == 'M') {1233switch (*d->p) {1234case 'U' :1235++d->p;12361237if (VEC_PUSH_STR(&d->vec, "unsigned ") == false)1238return (false);12391240break;1241case 'C' :1242++d->p;12431244if (*d->p == 'P')1245d->cnst = true;1246else {1247if (VEC_PUSH_STR(&d->vec, "const ") ==1248false)1249return (false);1250}12511252break;1253case 'V' :1254++d->p;12551256if (VEC_PUSH_STR(&d->vec, "volatile ") == false)1257return (false);12581259break;1260case 'S' :1261++d->p;12621263if (VEC_PUSH_STR(&d->vec, "signed ") == false)1264return (false);12651266break;1267case 'P' :1268++d->p;12691270if (*d->p == 'F')1271return (read_func_ptr(d));1272else1273d->ptr = true;12741275break;1276case 'R' :1277++d->p;12781279d->ref = true;12801281break;1282case 'F' :1283break;1284case 'A' :1285++d->p;12861287if (read_array(d) == false)1288return (false);12891290break;1291case 'M' :1292++d->p;12931294if (read_memptr(d) == false)1295return (false);12961297break;1298default :1299break;1300}1301}13021303if (ELFTC_ISDIGIT(*d->p))1304return (read_class(d));13051306switch (*d->p) {1307case 'Q' :1308++d->p;13091310return (read_qual_name(d));1311case 'v' :1312++d->p;13131314return (VEC_PUSH_STR(&d->vec, "void"));1315case 'b':1316++d->p;13171318return(VEC_PUSH_STR(&d->vec, "bool"));1319case 'c' :1320++d->p;13211322return (VEC_PUSH_STR(&d->vec, "char"));1323case 's' :1324++d->p;13251326return (VEC_PUSH_STR(&d->vec, "short"));1327case 'i' :1328++d->p;13291330return (VEC_PUSH_STR(&d->vec, "int"));1331case 'l' :1332++d->p;13331334return (VEC_PUSH_STR(&d->vec, "long"));1335case 'f' :1336++d->p;13371338return (VEC_PUSH_STR(&d->vec, "float"));1339case 'd':1340++d->p;13411342return (VEC_PUSH_STR(&d->vec, "double"));1343case 'r':1344++d->p;13451346return (VEC_PUSH_STR(&d->vec, "long double"));1347case 'e':1348++d->p;13491350return (VEC_PUSH_STR(&d->vec, "..."));1351case 'w':1352++d->p;13531354return (VEC_PUSH_STR(&d->vec, "wchar_t"));1355case 'x':1356++d->p;13571358return (VEC_PUSH_STR(&d->vec, "long long"));1359default:1360return (false);1361};13621363/* NOTREACHED */1364return (false);1365}136613671368