Path: blob/main/contrib/elftoolchain/libelftc/libelftc_dem_arm.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_arm.c 3513 2016-12-29 07:04:22Z kaiwang27 $");4041/**42* @file cpp_demangle_arm.c43* @brief Decode function name encoding in ARM.44*45* Function name encoding in "The Annotated C++ Reference Manual".46*47* Ref : "The Annotated C++ Reference Manual", Margaet A.Ellis,48* Bjarne Stroustrup, AT&T Bell Laboratories 1990, pp 122-126.49*/5051enum encode_type {52ENCODE_FUNC, ENCODE_OP, ENCODE_OP_CT, ENCODE_OP_DT, ENCODE_OP_USER53};5455struct cstring {56char *buf;57size_t size;58};5960struct demangle_data {61bool ptr, ref, cnst, array;62struct cstring array_str;63const char *p;64enum encode_type type;65struct vector_str vec;66struct vector_str arg;67};6869#define SIMPLE_HASH(x,y) (64 * x + y)70#define VEC_PUSH_STR(d,s) vector_str_push((d), (s), strlen((s)))71#define CPP_DEMANGLE_ARM_TRY 1287273static void dest_cstring(struct cstring *);74static void dest_demangle_data(struct demangle_data *);75static bool init_cstring(struct cstring *, size_t);76static bool init_demangle_data(struct demangle_data *);77static bool push_CTDT(const char *, size_t, struct vector_str *);78static bool read_array(struct demangle_data *);79static bool read_class(struct demangle_data *);80static bool read_func(struct demangle_data *);81static bool read_func_name(struct demangle_data *);82static bool read_func_ptr(struct demangle_data *);83static bool read_memptr(struct demangle_data *);84static bool read_op(struct demangle_data *);85static bool read_op_user(struct demangle_data *);86static bool read_qual_name(struct demangle_data *);87static int read_subst(struct demangle_data *);88static int read_subst_iter(struct demangle_data *);89static bool read_type(struct demangle_data *);9091/**92* @brief Decode the input string by the ARM style.93*94* @return New allocated demangled string or NULL if failed.95*/96char *97cpp_demangle_ARM(const char *org)98{99struct demangle_data d;100size_t arg_begin, arg_len;101unsigned int try;102char *rtn, *arg;103104if (org == NULL)105return (NULL);106107if (init_demangle_data(&d) == false)108return (NULL);109110try = 0;111rtn = NULL;112113d.p = org;114if (read_func_name(&d) == false)115goto clean;116117if (d.type == ENCODE_OP_CT) {118if (push_CTDT("::", 2, &d.vec) == false)119goto clean;120121goto flat;122}123124if (d.type == ENCODE_OP_DT) {125if (push_CTDT("::~", 3, &d.vec) == false)126goto clean;127128goto flat;129}130131if (d.type == ENCODE_OP_USER)132goto flat;133134/* function type */135if (*d.p != 'F')136goto clean;137++d.p;138139/* start argument types */140if (VEC_PUSH_STR(&d.vec, "(") == false)141goto clean;142143for (;;) {144if (*d.p == 'T') {145const int rtn_subst = read_subst(&d);146147if (rtn_subst == -1)148goto clean;149else if (rtn_subst == 1)150break;151152continue;153}154155if (*d.p == 'N') {156const int rtn_subst_iter = read_subst_iter(&d);157158if (rtn_subst_iter == -1)159goto clean;160else if(rtn_subst_iter == 1)161break;162163continue;164}165166arg_begin = d.vec.size;167168if (read_type(&d) == false)169goto clean;170171if (d.ptr == true) {172if (VEC_PUSH_STR(&d.vec, "*") == false)173goto clean;174175d.ptr = false;176}177178if (d.ref == true) {179if (VEC_PUSH_STR(&d.vec, "&") == false)180goto clean;181182d.ref = false;183}184185if (d.cnst == true) {186if (VEC_PUSH_STR(&d.vec, " const") == false)187goto clean;188189d.cnst = false;190}191192if (d.array == true) {193if (vector_str_push(&d.vec, d.array_str.buf,194d.array_str.size) == false)195goto clean;196197dest_cstring(&d.array_str);198d.array = false;199}200201if (*d.p == '\0')202break;203204if ((arg = vector_str_substr(&d.vec, arg_begin, d.vec.size - 1,205&arg_len)) == NULL)206goto clean;207208if (vector_str_push(&d.arg, arg, arg_len) == false) {209free(arg);210goto clean;211}212213free(arg);214215if (VEC_PUSH_STR(&d.vec, ", ") == false)216goto clean;217218if (++try > CPP_DEMANGLE_ARM_TRY)219goto clean;220}221222/* end argument types */223if (VEC_PUSH_STR(&d.vec, ")") == false)224goto clean;225226flat:227rtn = vector_str_get_flat(&d.vec, NULL);228clean:229dest_demangle_data(&d);230231return (rtn);232}233234/**235* @brief Test input string is encoded by the ARM style.236*237* @return True if input string is encoded by the ARM style.238*/239bool240is_cpp_mangled_ARM(const char *org)241{242243if (org == NULL)244return (false);245246return (strstr(org, "__") != NULL);247}248249static void250dest_cstring(struct cstring *s)251{252253if (s == NULL)254return;255256free(s->buf);257s->buf = NULL;258s->size = 0;259}260261static void262dest_demangle_data(struct demangle_data *d)263{264265if (d != NULL) {266vector_str_dest(&d->arg);267vector_str_dest(&d->vec);268269dest_cstring(&d->array_str);270}271}272273static bool274init_cstring(struct cstring *s, size_t len)275{276277if (s == NULL || len <= 1)278return (false);279280if ((s->buf = malloc(sizeof(char) * len)) == NULL)281return (false);282283s->size = len - 1;284285return (true);286}287288static bool289init_demangle_data(struct demangle_data *d)290{291292if (d == NULL)293return (false);294295d->ptr = false;296d->ref = false;297d->cnst = false;298d->array = false;299300d->array_str.buf = NULL;301d->array_str.size = 0;302303d->type = ENCODE_FUNC;304305if (!vector_str_init(&d->vec))306return (false);307308if (!vector_str_init(&d->arg)) {309vector_str_dest(&d->vec);310return (false);311}312313return (true);314}315316static bool317push_CTDT(const char *s, size_t l, struct vector_str *v)318{319320if (s == NULL || l == 0 || v == NULL)321return (false);322323if (vector_str_push(v, s, l) == false)324return (false);325326assert(v->size > 1);327if (VEC_PUSH_STR(v, v->container[v->size - 2]) == false)328return (false);329330if (VEC_PUSH_STR(v, "()") == false)331return (false);332333return (true);334}335336static bool337read_array(struct demangle_data *d)338{339size_t len;340const char *end;341342if (d == NULL || d->p == NULL)343return (false);344345end = d->p;346assert(end != NULL);347348for (;;) {349if (*end == '\0')350return (false);351352if (ELFTC_ISDIGIT(*end) == 0)353break;354355++end;356}357358if (*end != '_')359return (false);360361len = end - d->p;362assert(len > 0);363364dest_cstring(&d->array_str);365if (init_cstring(&d->array_str, len + 3) == false)366return (false);367368strncpy(d->array_str.buf + 1, d->p, len);369*d->array_str.buf = '[';370*(d->array_str.buf + len + 1) = ']';371372d->array = true;373d->p = end + 1;374375return (true);376}377378static bool379read_class(struct demangle_data *d)380{381size_t len;382char *str;383384if (d == NULL)385return (false);386387len = strtol(d->p, &str, 10);388if (len == 0 && (errno == EINVAL || errno == ERANGE))389return (false);390391assert(len > 0);392assert(str != NULL);393394if (vector_str_push(&d->vec, str, len) == false)395return (false);396397d->p = str + len;398399return (true);400}401402static bool403read_func(struct demangle_data *d)404{405size_t len;406const char *name;407char *delim;408409if (d == NULL)410return (false);411412assert(d->p != NULL && "d->p (org str) is NULL");413if ((delim = strstr(d->p, "__")) == NULL)414return (false);415416len = delim - d->p;417assert(len != 0);418419name = d->p;420421d->p = delim + 2;422423if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {424++d->p;425426if (read_qual_name(d) == false)427return (false);428} else if (ELFTC_ISDIGIT(*d->p)) {429if (read_class(d) == false)430return (false);431432if (VEC_PUSH_STR(&d->vec, "::") == false)433return (false);434}435436if (vector_str_push(&d->vec, name, len) == false)437return (false);438439return (true);440}441442static bool443read_func_name(struct demangle_data *d)444{445size_t len;446bool rtn;447char *op_name;448449if (d == NULL)450return (false);451452rtn = false;453op_name = NULL;454455assert(d->p != NULL && "d->p (org str) is NULL");456457if (*d->p == '_' && *(d->p + 1) == '_') {458d->p += 2;459460d->type = ENCODE_OP;461if (read_op(d) == false)462return (false);463464if (d->type == ENCODE_OP_CT || d->type == ENCODE_OP_DT ||465d->type == ENCODE_OP_USER)466return (true);467468/* skip "__" */469d->p += 2;470471/* assume delimiter is removed */472if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {473++d->p;474475assert(d->vec.size > 0);476477len = strlen(d->vec.container[d->vec.size - 1]);478if ((op_name = malloc(sizeof(char) * (len + 1)))479== NULL)480return (false);481482snprintf(op_name, len + 1, "%s",483d->vec.container[d->vec.size - 1]);484vector_str_pop(&d->vec);485486if (read_qual_name(d) == false)487goto clean;488489if (VEC_PUSH_STR(&d->vec, "::") == false)490goto clean;491492if (vector_str_push(&d->vec, op_name, len) == false)493goto clean;494495rtn = true;496} else if (ELFTC_ISDIGIT(*d->p)) {497assert(d->vec.size > 0);498499len = strlen(d->vec.container[d->vec.size - 1]);500if ((op_name = malloc(sizeof(char) * (len + 1)))501== NULL)502return (false);503504snprintf(op_name, len + 1, "%s",505d->vec.container[d->vec.size - 1]);506vector_str_pop(&d->vec);507508if (read_class(d) == false)509goto clean;510511if (VEC_PUSH_STR(&d->vec, "::") == false)512goto clean;513514if (vector_str_push(&d->vec, op_name, len) == false)515goto clean;516517rtn = true;518}519} else520return (read_func(d));521522clean:523free(op_name);524525return (rtn);526}527528/* Read function ptr type */529static bool530read_func_ptr(struct demangle_data *d)531{532struct demangle_data fptr;533size_t arg_len, rtn_len;534char *arg_type, *rtn_type;535int lim;536537if (d == NULL)538return (false);539540if (init_demangle_data(&fptr) == false)541return (false);542543fptr.p = d->p + 1;544lim = 0;545arg_type = NULL;546rtn_type = NULL;547548for (;;) {549if (read_type(&fptr) == false) {550dest_demangle_data(&fptr);551552return (false);553}554555if (fptr.ptr == true) {556if (VEC_PUSH_STR(&fptr.vec, "*") == false) {557dest_demangle_data(&fptr);558559return (false);560}561562fptr.ptr = false;563}564565if (fptr.ref == true) {566if (VEC_PUSH_STR(&fptr.vec, "&") == false) {567dest_demangle_data(&fptr);568569return (false);570}571572fptr.ref = false;573}574575if (fptr.cnst == true) {576if (VEC_PUSH_STR(&fptr.vec, " const") == false) {577dest_demangle_data(&fptr);578579return (false);580}581582fptr.cnst = false;583}584585if (*fptr.p == '_')586break;587588if (VEC_PUSH_STR(&fptr.vec, ", ") == false) {589dest_demangle_data(&fptr);590591return (false);592}593594if (++lim > CPP_DEMANGLE_ARM_TRY) {595596dest_demangle_data(&fptr);597598return (false);599}600}601602arg_type = vector_str_get_flat(&fptr.vec, &arg_len);603/* skip '_' */604d->p = fptr.p + 1;605606dest_demangle_data(&fptr);607608if (init_demangle_data(&fptr) == false) {609free(arg_type);610611return (false);612}613614fptr.p = d->p;615lim = 0;616617if (read_type(&fptr) == false) {618free(arg_type);619dest_demangle_data(&fptr);620621return (false);622}623624rtn_type = vector_str_get_flat(&fptr.vec, &rtn_len);625d->p = fptr.p;626627628dest_demangle_data(&fptr);629630if (vector_str_push(&d->vec, rtn_type, rtn_len) == false) {631free(rtn_type);632free(arg_type);633634return (false);635}636637free(rtn_type);638639if (VEC_PUSH_STR(&d->vec, " (*)(") == false) {640free(arg_type);641642return (false);643}644645if (vector_str_push(&d->vec, arg_type, arg_len) == false) {646free(arg_type);647648return (false);649}650651free(arg_type);652653return (VEC_PUSH_STR(&d->vec, ")"));654}655656static bool657read_memptr(struct demangle_data *d)658{659struct demangle_data mptr;660size_t len;661bool rtn;662char *mptr_str;663664if (d == NULL || d->p == NULL)665return (false);666667if (init_demangle_data(&mptr) == false)668return (false);669670rtn = false;671mptr_str = NULL;672673mptr.p = d->p;674if (*mptr.p == 'Q') {675++mptr.p;676677if (read_qual_name(&mptr) == false)678goto clean;679} else {680if (read_class(&mptr) == false)681goto clean;682}683684d->p = mptr.p;685686if ((mptr_str = vector_str_get_flat(&mptr.vec, &len)) == NULL)687goto clean;688689if (vector_str_push(&d->vec, mptr_str, len) == false)690goto clean;691692if (VEC_PUSH_STR(&d->vec, "::*") == false)693goto clean;694695rtn = true;696clean:697free(mptr_str);698dest_demangle_data(&mptr);699700return (rtn);701}702703static bool704read_op(struct demangle_data *d)705{706707if (d == NULL)708return (false);709710assert(d->p != NULL && "d->p (org str) is NULL");711712switch (SIMPLE_HASH(*(d->p), *(d->p+1))) {713case SIMPLE_HASH('m', 'l') :714d->p += 2;715return (VEC_PUSH_STR(&d->vec, "operator*"));716case SIMPLE_HASH('d', 'v') :717d->p += 2;718return (VEC_PUSH_STR(&d->vec, "operator/"));719case SIMPLE_HASH('m', 'd') :720d->p += 2;721return (VEC_PUSH_STR(&d->vec, "operator%"));722case SIMPLE_HASH('p', 'l') :723d->p += 2;724return (VEC_PUSH_STR(&d->vec, "operator+"));725case SIMPLE_HASH('m', 'i') :726d->p += 2;727return (VEC_PUSH_STR(&d->vec, "operator-"));728case SIMPLE_HASH('l', 's') :729d->p += 2;730return (VEC_PUSH_STR(&d->vec, "operator<<"));731case SIMPLE_HASH('r', 's') :732d->p += 2;733return (VEC_PUSH_STR(&d->vec, "operator>>"));734case SIMPLE_HASH('e', 'q') :735d->p += 2;736return (VEC_PUSH_STR(&d->vec, "operator=="));737case SIMPLE_HASH('n', 'e') :738d->p += 2;739return (VEC_PUSH_STR(&d->vec, "operator!="));740case SIMPLE_HASH('l', 't') :741d->p += 2;742return (VEC_PUSH_STR(&d->vec, "operator<"));743case SIMPLE_HASH('g', 't') :744d->p += 2;745return (VEC_PUSH_STR(&d->vec, "operator>"));746case SIMPLE_HASH('l', 'e') :747d->p += 2;748return (VEC_PUSH_STR(&d->vec, "operator<="));749case SIMPLE_HASH('g', 'e') :750d->p += 2;751return (VEC_PUSH_STR(&d->vec, "operator>="));752case SIMPLE_HASH('a', 'd') :753d->p += 2;754if (*d->p == 'v') {755++d->p;756return (VEC_PUSH_STR(&d->vec, "operator/="));757} else758return (VEC_PUSH_STR(&d->vec, "operator&"));759case SIMPLE_HASH('o', 'r') :760d->p += 2;761return (VEC_PUSH_STR(&d->vec, "operator|"));762case SIMPLE_HASH('e', 'r') :763d->p += 2;764return (VEC_PUSH_STR(&d->vec, "operator^"));765case SIMPLE_HASH('a', 'a') :766d->p += 2;767if (*d->p == 'd') {768++d->p;769return (VEC_PUSH_STR(&d->vec, "operator&="));770} else771return (VEC_PUSH_STR(&d->vec, "operator&&"));772case SIMPLE_HASH('o', 'o') :773d->p += 2;774return (VEC_PUSH_STR(&d->vec, "operator||"));775case SIMPLE_HASH('n', 't') :776d->p += 2;777return (VEC_PUSH_STR(&d->vec, "operator!"));778case SIMPLE_HASH('c', 'o') :779d->p += 2;780return (VEC_PUSH_STR(&d->vec, "operator~"));781case SIMPLE_HASH('p', 'p') :782d->p += 2;783return (VEC_PUSH_STR(&d->vec, "operator++"));784case SIMPLE_HASH('m', 'm') :785d->p += 2;786return (VEC_PUSH_STR(&d->vec, "operator--"));787case SIMPLE_HASH('a', 's') :788d->p += 2;789return (VEC_PUSH_STR(&d->vec, "operator="));790case SIMPLE_HASH('r', 'f') :791d->p += 2;792return (VEC_PUSH_STR(&d->vec, "operator->"));793case SIMPLE_HASH('a', 'p') :794/* apl */795if (*(d->p + 2) != 'l')796return (false);797798d->p += 3;799return (VEC_PUSH_STR(&d->vec, "operator+="));800case SIMPLE_HASH('a', 'm') :801d->p += 2;802if (*d->p == 'i') {803++d->p;804return (VEC_PUSH_STR(&d->vec, "operator-="));805} else if (*d->p == 'u') {806++d->p;807return (VEC_PUSH_STR(&d->vec, "operator*="));808} else if (*d->p == 'd') {809++d->p;810return (VEC_PUSH_STR(&d->vec, "operator%="));811}812813return (false);814case SIMPLE_HASH('a', 'l') :815/* als */816if (*(d->p + 2) != 's')817return (false);818819d->p += 3;820return (VEC_PUSH_STR(&d->vec, "operator<<="));821case SIMPLE_HASH('a', 'r') :822/* ars */823if (*(d->p + 2) != 's')824return (false);825826d->p += 3;827return (VEC_PUSH_STR(&d->vec, "operator>>="));828case SIMPLE_HASH('a', 'o') :829/* aor */830if (*(d->p + 2) != 'r')831return (false);832833d->p += 3;834return (VEC_PUSH_STR(&d->vec, "operator|="));835case SIMPLE_HASH('a', 'e') :836/* aer */837if (*(d->p + 2) != 'r')838return (false);839840d->p += 3;841return (VEC_PUSH_STR(&d->vec, "operator^="));842case SIMPLE_HASH('c', 'm') :843d->p += 2;844return (VEC_PUSH_STR(&d->vec, "operator,"));845case SIMPLE_HASH('r', 'm') :846d->p += 2;847return (VEC_PUSH_STR(&d->vec, "operator->*"));848case SIMPLE_HASH('c', 'l') :849d->p += 2;850return (VEC_PUSH_STR(&d->vec, "()"));851case SIMPLE_HASH('v', 'c') :852d->p += 2;853return (VEC_PUSH_STR(&d->vec, "[]"));854case SIMPLE_HASH('c', 't') :855d->p += 4;856d->type = ENCODE_OP_CT;857858if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {859++d->p;860861return (read_qual_name(d));862} else if (ELFTC_ISDIGIT(*d->p))863return (read_class(d));864865return (false);866case SIMPLE_HASH('d', 't') :867d->p += 4;868d->type = ENCODE_OP_DT;869870if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {871++d->p;872873return (read_qual_name(d));874} else if (ELFTC_ISDIGIT(*d->p))875return (read_class(d));876877return (false);878case SIMPLE_HASH('n', 'w') :879d->p += 2;880return (VEC_PUSH_STR(&d->vec, "operator new()"));881case SIMPLE_HASH('d', 'l') :882d->p += 2;883return (VEC_PUSH_STR(&d->vec, "operator delete()"));884case SIMPLE_HASH('o', 'p') :885/* __op<TO_TYPE>__<FROM_TYPE> */886d->p += 2;887888d->type = ENCODE_OP_USER;889890return (read_op_user(d));891default :892return (false);893};894}895896static bool897read_op_user(struct demangle_data *d)898{899struct demangle_data from, to;900size_t from_len, to_len;901bool rtn;902char *from_str, *to_str;903904if (d == NULL)905return (false);906907if (init_demangle_data(&from) == false)908return (false);909910rtn = false;911from_str = NULL;912to_str = NULL;913if (init_demangle_data(&to) == false)914goto clean;915916to.p = d->p;917if (*to.p == 'Q') {918++to.p;919920if (read_qual_name(&to) == false)921goto clean;922923/* pop last '::' */924if (vector_str_pop(&to.vec) == false)925goto clean;926} else {927if (read_class(&to) == false)928goto clean;929930/* skip '__' */931to.p += 2;932}933934if ((to_str = vector_str_get_flat(&to.vec, &to_len)) == NULL)935goto clean;936937from.p = to.p;938if (*from.p == 'Q') {939++from.p;940941if (read_qual_name(&from) == false)942goto clean;943944/* pop last '::' */945if (vector_str_pop(&from.vec) == false)946goto clean;947} else {948if (read_class(&from) == false)949goto clean;950}951952if ((from_str = vector_str_get_flat(&from.vec, &from_len)) == NULL)953goto clean;954955if (vector_str_push(&d->vec, from_str, from_len) == false)956goto clean;957958if (VEC_PUSH_STR(&d->vec, "::operator ") == false)959goto clean;960961if (vector_str_push(&d->vec, to_str, to_len) == false)962goto clean;963964rtn = VEC_PUSH_STR(&d->vec, "()");965clean:966free(to_str);967free(from_str);968dest_demangle_data(&to);969dest_demangle_data(&from);970971return (rtn);972}973974/* single digit + class names */975static bool976read_qual_name(struct demangle_data *d)977{978int i;979char num;980981if (d == NULL)982return (false);983984assert(d->p != NULL && "d->p (org str) is NULL");985assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");986987num = *d->p - 48;988989assert(num > 0);990991++d->p;992for (i = 0; i < num ; ++i) {993if (read_class(d) == false)994return (false);995996if (VEC_PUSH_STR(&d->vec, "::") == false)997return (false);998}9991000if (*d->p != '\0')1001d->p = d->p + 2;10021003return (true);1004}10051006/* Return -1 at fail, 0 at success, and 1 at end */1007static int1008read_subst(struct demangle_data *d)1009{1010size_t idx;1011char *str;10121013if (d == NULL)1014return (-1);10151016idx = strtol(d->p + 1, &str, 10);1017if (idx == 0 && (errno == EINVAL || errno == ERANGE))1018return (-1);10191020assert(idx > 0);1021assert(str != NULL);10221023d->p = str;10241025if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)1026return (-1);10271028if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)1029return (-1);10301031if (*d->p == '\0')1032return (1);10331034return (0);1035}10361037static int1038read_subst_iter(struct demangle_data *d)1039{1040int i;1041size_t idx;1042char repeat;1043char *str;10441045if (d == NULL)1046return (-1);10471048++d->p;1049assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");10501051repeat = *d->p - 48;10521053assert(repeat > 1);10541055++d->p;10561057idx = strtol(d->p, &str, 10);1058if (idx == 0 && (errno == EINVAL || errno == ERANGE))1059return (-1);10601061assert(idx > 0);1062assert(str != NULL);10631064d->p = str;10651066for (i = 0; i < repeat ; ++i) {1067if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)1068return (-1);10691070if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)1071return (-1);10721073if (i != repeat - 1 &&1074VEC_PUSH_STR(&d->vec, ", ") == false)1075return (-1);1076}10771078if (*d->p == '\0')1079return (1);10801081return (0);1082}10831084static bool1085read_type(struct demangle_data *d)1086{10871088if (d == NULL)1089return (false);10901091assert(d->p != NULL && "d->p (org str) is NULL");10921093while (*d->p == 'U' || *d->p == 'C' || *d->p == 'V' || *d->p == 'S' ||1094*d->p == 'P' || *d->p == 'R' || *d->p == 'A' || *d->p == 'F' ||1095*d->p == 'M') {1096switch (*d->p) {1097case 'U' :1098++d->p;10991100if (VEC_PUSH_STR(&d->vec, "unsigned ") == false)1101return (false);11021103break;1104case 'C' :1105++d->p;11061107if (*d->p == 'P')1108d->cnst = true;1109else {1110if (VEC_PUSH_STR(&d->vec, "const ") ==1111false)1112return (false);1113}11141115break;1116case 'V' :1117++d->p;11181119if (VEC_PUSH_STR(&d->vec, "volatile ") == false)1120return (false);11211122break;1123case 'S' :1124++d->p;11251126if (VEC_PUSH_STR(&d->vec, "signed ") == false)1127return (false);11281129break;1130case 'P' :1131++d->p;11321133if (*d->p == 'F')1134return (read_func_ptr(d));1135else1136d->ptr = true;11371138break;1139case 'R' :1140++d->p;11411142d->ref = true;11431144break;1145case 'F' :1146break;1147case 'A' :1148++d->p;11491150if (read_array(d) == false)1151return (false);11521153break;1154case 'M' :1155++d->p;11561157if (read_memptr(d) == false)1158return (false);11591160break;1161default :1162break;1163}1164}11651166if (ELFTC_ISDIGIT(*d->p))1167return (read_class(d));11681169switch (*d->p) {1170case 'Q' :1171++d->p;11721173return (read_qual_name(d));1174case 'v' :1175++d->p;11761177return (VEC_PUSH_STR(&d->vec, "void"));1178case 'c' :1179++d->p;11801181return (VEC_PUSH_STR(&d->vec, "char"));1182case 's' :1183++d->p;11841185return (VEC_PUSH_STR(&d->vec, "short"));1186case 'i' :1187++d->p;11881189return (VEC_PUSH_STR(&d->vec, "int"));1190case 'l' :1191++d->p;11921193return (VEC_PUSH_STR(&d->vec, "long"));1194case 'f' :1195++d->p;11961197return (VEC_PUSH_STR(&d->vec, "float"));1198case 'd':1199++d->p;12001201return (VEC_PUSH_STR(&d->vec, "double"));1202case 'r':1203++d->p;12041205return (VEC_PUSH_STR(&d->vec, "long double"));1206case 'e':1207++d->p;12081209return (VEC_PUSH_STR(&d->vec, "..."));1210default:1211return (false);1212};12131214/* NOTREACHED */1215return (false);1216}121712181219