diff options
author | Ed Maste <emaste@FreeBSD.org> | 2017-06-25 22:19:01 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2017-06-25 22:19:01 +0000 |
commit | 2b7f789ebfc1d2b049bf705a49f76e078e3b11b7 (patch) | |
tree | 7c99930aa2aec9afef2f469345940b4d94ad176f | |
parent | 8cc1f6cc64e76b11cee23af79828b63cd7be4c09 (diff) |
Import ELF Tool Chain snapshot at r3561vendor/elftoolchain/elftoolchain-r3561
Notes
Notes:
svn path=/vendor/elftoolchain/dist/; revision=320341
svn path=/vendor/elftoolchain/elftoolchain-r3561/; revision=320342; tag=vendor/elftoolchain/elftoolchain-r3561
-rw-r--r-- | elfdump/elfdump.c | 6 | ||||
-rw-r--r-- | libelftc/_libelftc.h | 4 | ||||
-rw-r--r-- | libelftc/libelftc_dem_gnu3.c | 757 | ||||
-rw-r--r-- | libelftc/libelftc_vstr.c | 43 | ||||
-rw-r--r-- | test/cxxfilt/tet_scen | 24 | ||||
-rw-r--r-- | test/cxxfilt/ts/Makefile | 4 | ||||
-rw-r--r-- | test/cxxfilt/ts/builtin/Makefile | 5 | ||||
-rw-r--r-- | test/cxxfilt/ts/builtin/tclist | 48 | ||||
-rw-r--r-- | test/cxxfilt/ts/misc/tclist | 40 | ||||
-rw-r--r-- | test/cxxfilt/ts/qualifiers/Makefile | 5 | ||||
-rw-r--r-- | test/cxxfilt/ts/qualifiers/tclist | 36 | ||||
-rw-r--r-- | test/cxxfilt/ts/substitute/Makefile | 5 | ||||
-rw-r--r-- | test/cxxfilt/ts/substitute/tclist | 56 | ||||
-rw-r--r-- | test/cxxfilt/ts/template/Makefile | 5 | ||||
-rw-r--r-- | test/cxxfilt/ts/template/tclist | 10 | ||||
-rw-r--r-- | test/elfcopy/plugin/os.FreeBSD.mk | 2 |
16 files changed, 857 insertions, 193 deletions
diff --git a/elfdump/elfdump.c b/elfdump/elfdump.c index 2e8620c2d492..6194554b85d8 100644 --- a/elfdump/elfdump.c +++ b/elfdump/elfdump.c @@ -50,7 +50,7 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: elfdump.c 3497 2016-10-17 20:57:22Z emaste $"); +ELFTC_VCSID("$Id: elfdump.c 3521 2017-06-04 20:07:09Z jkoshy $"); #if defined(ELFTC_NEED_ELF_NOTE_DEFINITION) #include "native-elf-format.h" @@ -2226,8 +2226,8 @@ elf_print_svr4_hash64(struct elfdump *ed, struct section *s) uint64_t *buf; uint64_t *bucket, *chain; uint64_t nbucket, nchain; - uint64_t *bl, *c, maxl, total; - uint64_t i, j; + uint64_t *bl, *c, j, maxl, total; + size_t i; int elferr, first; char idx[10]; diff --git a/libelftc/_libelftc.h b/libelftc/_libelftc.h index ba0b10112a57..a56e29ee4a5b 100644 --- a/libelftc/_libelftc.h +++ b/libelftc/_libelftc.h @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: _libelftc.h 3174 2015-03-27 17:13:41Z emaste $ + * $Id: _libelftc.h 3531 2017-06-05 05:08:43Z kaiwang27 $ */ #ifndef __LIBELFTC_H_ @@ -82,6 +82,8 @@ bool vector_str_init(struct vector_str *_vs); bool vector_str_pop(struct vector_str *_vs); bool vector_str_push(struct vector_str *_vs, const char *_str, size_t _len); +bool vector_str_push_vector(struct vector_str *_dst, + struct vector_str *_org); bool vector_str_push_vector_head(struct vector_str *_dst, struct vector_str *_org); char *vector_str_substr(const struct vector_str *_vs, size_t _begin, diff --git a/libelftc/libelftc_dem_gnu3.c b/libelftc/libelftc_dem_gnu3.c index bd571228fb1a..9f04999ed5b6 100644 --- a/libelftc/libelftc_dem_gnu3.c +++ b/libelftc/libelftc_dem_gnu3.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com> + * Copyright (c) 2015-2017 Kai Wang <kaiwang27@gmail.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,7 +37,7 @@ #include "_libelftc.h" -ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3512 2016-12-29 07:04:19Z kaiwang27 $"); +ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3560 2017-06-25 00:28:23Z kaiwang27 $"); /** * @file cpp_demangle.c @@ -50,7 +51,7 @@ ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3512 2016-12-29 07:04:19Z kaiwang27 $"); enum type_qualifier { TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT, - TYPE_CST, TYPE_VEC + TYPE_CST, TYPE_VEC, TYPE_RREF }; struct vector_type_qualifier { @@ -64,27 +65,47 @@ enum read_cmd { READ_TYPE, READ_FUNC, READ_PTRMEM }; +struct read_cmd_item { + enum read_cmd cmd; + void *data; +}; + struct vector_read_cmd { size_t size, capacity; - enum read_cmd *r_container; + struct read_cmd_item *r_container; +}; + +enum push_qualifier { + PUSH_ALL_QUALIFIER, + PUSH_CV_QUALIFIER, + PUSH_NON_CV_QUALIFIER, }; struct cpp_demangle_data { struct vector_str output; /* output string vector */ - struct vector_str output_tmp; struct vector_str subst; /* substitution string vector */ struct vector_str tmpl; struct vector_str class_type; + struct vector_str *cur_output; /* ptr to current output vec */ struct vector_read_cmd cmd; - bool paren; /* parenthesis opened */ - bool pfirst; /* first element of parameter */ bool mem_rst; /* restrict member function */ bool mem_vat; /* volatile member function */ bool mem_cst; /* const member function */ + bool mem_ref; /* lvalue-ref member func */ + bool mem_rref; /* rvalue-ref member func */ + bool is_tmpl; /* template args */ + bool is_functype; /* function type */ + bool ref_qualifier; /* ref qualifier */ + enum type_qualifier ref_qualifier_type; /* ref qualifier type */ + enum push_qualifier push_qualifier; /* which qualifiers to push */ int func_type; const char *cur; /* current mangled name ptr */ const char *last_sname; /* last source name */ - int push_head; +}; + +struct type_delimit { + bool paren; + bool firstp; }; #define CPP_DEMANGLE_TRY_LIMIT 128 @@ -105,6 +126,7 @@ static int cpp_demangle_push_fp(struct cpp_demangle_data *, char *(*)(const char *, size_t)); static int cpp_demangle_push_str(struct cpp_demangle_data *, const char *, size_t); +static int cpp_demangle_pop_str(struct cpp_demangle_data *); static int cpp_demangle_push_subst(struct cpp_demangle_data *, const char *, size_t); static int cpp_demangle_push_subst_v(struct cpp_demangle_data *, @@ -137,16 +159,18 @@ static int cpp_demangle_read_number_as_string(struct cpp_demangle_data *, static int cpp_demangle_read_nv_offset(struct cpp_demangle_data *); static int cpp_demangle_read_offset(struct cpp_demangle_data *); static int cpp_demangle_read_offset_number(struct cpp_demangle_data *); -static int cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *); +static int cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *, + struct vector_type_qualifier *); static int cpp_demangle_read_sname(struct cpp_demangle_data *); static int cpp_demangle_read_subst(struct cpp_demangle_data *); static int cpp_demangle_read_subst_std(struct cpp_demangle_data *); static int cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *, - const char *, size_t); + const char *); static int cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *); static int cpp_demangle_read_tmpl_args(struct cpp_demangle_data *); static int cpp_demangle_read_tmpl_param(struct cpp_demangle_data *); -static int cpp_demangle_read_type(struct cpp_demangle_data *, int); +static int cpp_demangle_read_type(struct cpp_demangle_data *, + struct type_delimit *); static int cpp_demangle_read_type_flat(struct cpp_demangle_data *, char **); static int cpp_demangle_read_uqname(struct cpp_demangle_data *); @@ -158,10 +182,12 @@ static char *decode_fp_to_float80(const char *, size_t); static char *decode_fp_to_long_double(const char *, size_t); static int hex_to_dec(char); static void vector_read_cmd_dest(struct vector_read_cmd *); -static int vector_read_cmd_find(struct vector_read_cmd *, enum read_cmd); +static struct read_cmd_item *vector_read_cmd_find(struct vector_read_cmd *, + enum read_cmd); static int vector_read_cmd_init(struct vector_read_cmd *); static int vector_read_cmd_pop(struct vector_read_cmd *); -static int vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd); +static int vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd, + void *); static void vector_type_qualifier_dest(struct vector_type_qualifier *); static int vector_type_qualifier_init(struct vector_type_qualifier *); static int vector_type_qualifier_push(struct vector_type_qualifier *, @@ -178,9 +204,12 @@ char * cpp_demangle_gnu3(const char *org) { struct cpp_demangle_data ddata; + struct vector_str ret_type; + struct type_delimit td; ssize_t org_len; unsigned int limit; char *rtn; + bool has_ret, more_type; if (org == NULL || (org_len = strlen(org)) < 2) return (NULL); @@ -200,26 +229,75 @@ cpp_demangle_gnu3(const char *org) return (NULL); rtn = NULL; + has_ret = more_type = false; if (!cpp_demangle_read_encoding(&ddata)) goto clean; + /* + * Pop function name from substitution candidate list. + */ + if (*ddata.cur != 0 && ddata.subst.size >= 1) { + if (!vector_str_pop(&ddata.subst)) + goto clean; + } + + td.paren = false; + td.firstp = true; limit = 0; + + /* + * The first type is a return type if we just demangled template + * args. (the template args is right next to the function name, + * which means it's a template function) + */ + if (ddata.is_tmpl) { + ddata.is_tmpl = false; + if (!vector_str_init(&ret_type)) + goto clean; + ddata.cur_output = &ret_type; + has_ret = true; + } + while (*ddata.cur != '\0') { /* * Breaking at some gcc info at tail. e.g) @@GLIBCXX_3.4 */ if (*ddata.cur == '@' && *(ddata.cur + 1) == '@') break; - if (!cpp_demangle_read_type(&ddata, 1)) - goto clean; + + if (has_ret) { + /* Read return type */ + if (!cpp_demangle_read_type(&ddata, NULL)) + goto clean; + } else { + /* Read function arg type */ + if (!cpp_demangle_read_type(&ddata, &td)) + goto clean; + } + + if (has_ret) { + /* Push return type to the beginning */ + if (!VEC_PUSH_STR(&ret_type, " ")) + goto clean; + if (!vector_str_push_vector_head(&ddata.output, + &ret_type)) + goto clean; + ddata.cur_output = &ddata.output; + vector_str_dest(&ret_type); + has_ret = false; + more_type = true; + } else if (more_type) + more_type = false; if (limit++ > CPP_DEMANGLE_TRY_LIMIT) goto clean; } + if (more_type) + goto clean; if (ddata.output.size == 0) goto clean; - if (ddata.paren && !VEC_PUSH_STR(&ddata.output, ")")) + if (td.paren && !VEC_PUSH_STR(&ddata.output, ")")) goto clean; if (ddata.mem_vat && !VEC_PUSH_STR(&ddata.output, " volatile")) goto clean; @@ -227,10 +305,17 @@ cpp_demangle_gnu3(const char *org) goto clean; if (ddata.mem_rst && !VEC_PUSH_STR(&ddata.output, " restrict")) goto clean; + if (ddata.mem_ref && !VEC_PUSH_STR(&ddata.output, " &")) + goto clean; + if (ddata.mem_rref && !VEC_PUSH_STR(&ddata.output, " &&")) + goto clean; rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL); clean: + if (has_ret) + vector_str_dest(&ret_type); + cpp_demangle_data_dest(&ddata); return (rtn); @@ -247,7 +332,6 @@ cpp_demangle_data_dest(struct cpp_demangle_data *d) vector_str_dest(&d->class_type); vector_str_dest(&d->tmpl); vector_str_dest(&d->subst); - vector_str_dest(&d->output_tmp); vector_str_dest(&d->output); } @@ -260,43 +344,42 @@ cpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur) if (!vector_str_init(&d->output)) return (0); - if (!vector_str_init(&d->output_tmp)) - goto clean1; if (!vector_str_init(&d->subst)) - goto clean2; + goto clean1; if (!vector_str_init(&d->tmpl)) - goto clean3; + goto clean2; if (!vector_str_init(&d->class_type)) - goto clean4; + goto clean3; if (!vector_read_cmd_init(&d->cmd)) - goto clean5; + goto clean4; assert(d->output.container != NULL); - assert(d->output_tmp.container != NULL); assert(d->subst.container != NULL); assert(d->tmpl.container != NULL); assert(d->class_type.container != NULL); - d->paren = false; - d->pfirst = false; d->mem_rst = false; d->mem_vat = false; d->mem_cst = false; + d->mem_ref = false; + d->mem_rref = false; + d->is_tmpl = false; + d->is_functype = false; + d->ref_qualifier = false; + d->push_qualifier = PUSH_ALL_QUALIFIER; d->func_type = 0; d->cur = cur; + d->cur_output = &d->output; d->last_sname = NULL; - d->push_head = 0; return (1); -clean5: - vector_str_dest(&d->class_type); clean4: - vector_str_dest(&d->tmpl); + vector_str_dest(&d->class_type); clean3: - vector_str_dest(&d->subst); + vector_str_dest(&d->tmpl); clean2: - vector_str_dest(&d->output_tmp); + vector_str_dest(&d->subst); clean1: vector_str_dest(&d->output); @@ -341,10 +424,24 @@ cpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str, if (ddata == NULL || str == NULL || len == 0) return (0); - if (ddata->push_head > 0) - return (vector_str_push(&ddata->output_tmp, str, len)); + /* + * is_tmpl is used to check if the type (function arg) is right next + * to template args, and should always be cleared whenever new string + * pushed. + */ + ddata->is_tmpl = false; + + return (vector_str_push(ddata->cur_output, str, len)); +} + +static int +cpp_demangle_pop_str(struct cpp_demangle_data *ddata) +{ + + if (ddata == NULL) + return (0); - return (vector_str_push(&ddata->output, str, len)); + return (vector_str_pop(ddata->cur_output)); } static int @@ -386,9 +483,11 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, struct vector_type_qualifier *v, const char *type_str) { struct vector_str subst_v; + enum type_qualifier t; size_t idx, e_idx, e_len; - int rtn; char *buf; + int rtn; + bool cv; if (ddata == NULL || v == NULL) return (0); @@ -404,10 +503,14 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, goto clean; } + cv = true; e_idx = 0; while (idx > 0) { switch (v->q_container[idx - 1]) { case TYPE_PTR: + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; if (!DEM_PUSH_STR(ddata, "*")) goto clean; if (type_str != NULL) { @@ -420,6 +523,9 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, break; case TYPE_REF: + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; if (!DEM_PUSH_STR(ddata, "&")) goto clean; if (type_str != NULL) { @@ -431,7 +537,25 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, } break; + case TYPE_RREF: + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; + if (!DEM_PUSH_STR(ddata, "&&")) + goto clean; + if (type_str != NULL) { + if (!VEC_PUSH_STR(&subst_v, "&&")) + goto clean; + if (!cpp_demangle_push_subst_v(ddata, + &subst_v)) + goto clean; + } + break; + case TYPE_CMX: + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; if (!DEM_PUSH_STR(ddata, " complex")) goto clean; if (type_str != NULL) { @@ -444,6 +568,9 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, break; case TYPE_IMG: + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; if (!DEM_PUSH_STR(ddata, " imaginary")) goto clean; if (type_str != NULL) { @@ -457,6 +584,9 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, break; case TYPE_EXT: + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; if (v->ext_name.size == 0 || e_idx > v->ext_name.size - 1) goto clean; @@ -489,11 +619,22 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, break; case TYPE_RST: + if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER && + cv) + break; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv) + break; if (!DEM_PUSH_STR(ddata, " restrict")) goto clean; if (type_str != NULL) { if (!VEC_PUSH_STR(&subst_v, " restrict")) goto clean; + if (idx - 1 > 0) { + t = v->q_container[idx - 2]; + if (t == TYPE_RST || t == TYPE_VAT || + t == TYPE_CST) + break; + } if (!cpp_demangle_push_subst_v(ddata, &subst_v)) goto clean; @@ -501,11 +642,22 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, break; case TYPE_VAT: + if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER && + cv) + break; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv) + break; if (!DEM_PUSH_STR(ddata, " volatile")) goto clean; if (type_str != NULL) { if (!VEC_PUSH_STR(&subst_v, " volatile")) goto clean; + if (idx - 1 > 0) { + t = v->q_container[idx - 2]; + if (t == TYPE_RST || t == TYPE_VAT || + t == TYPE_CST) + break; + } if (!cpp_demangle_push_subst_v(ddata, &subst_v)) goto clean; @@ -513,11 +665,22 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, break; case TYPE_CST: + if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER && + cv) + break; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv) + break; if (!DEM_PUSH_STR(ddata, " const")) goto clean; if (type_str != NULL) { if (!VEC_PUSH_STR(&subst_v, " const")) goto clean; + if (idx - 1 > 0) { + t = v->q_container[idx - 2]; + if (t == TYPE_RST || t == TYPE_VAT || + t == TYPE_CST) + break; + } if (!cpp_demangle_push_subst_v(ddata, &subst_v)) goto clean; @@ -525,6 +688,9 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, break; case TYPE_VEC: + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; if (v->ext_name.size == 0 || e_idx > v->ext_name.size - 1) goto clean; @@ -614,7 +780,7 @@ cpp_demangle_read_array(struct cpp_demangle_data *ddata) if (*(++ddata->cur) == '\0') return (0); - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) return (0); if (!DEM_PUSH_STR(ddata, "[]")) @@ -630,7 +796,7 @@ cpp_demangle_read_array(struct cpp_demangle_data *ddata) assert(num_len > 0); if (*(++ddata->cur) == '\0') return (0); - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) return (0); if (!DEM_PUSH_STR(ddata, "[")) return (0); @@ -660,7 +826,7 @@ cpp_demangle_read_array(struct cpp_demangle_data *ddata) free(exp); return (0); } - if (!cpp_demangle_read_type(ddata, 0)) { + if (!cpp_demangle_read_type(ddata, NULL)) { free(exp); return (0); } @@ -777,11 +943,11 @@ cpp_demangle_read_expression(struct cpp_demangle_data *ddata) switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { case SIMPLE_HASH('s', 't'): ddata->cur += 2; - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('s', 'r'): ddata->cur += 2; - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) return (0); if (!cpp_demangle_read_uqname(ddata)) return (0); @@ -1058,8 +1224,7 @@ cpp_demangle_read_expression_flat(struct cpp_demangle_data *ddata, char **str) size_t i, p_idx, idx, exp_len; char *exp; - output = ddata->push_head > 0 ? &ddata->output_tmp : - &ddata->output; + output = &ddata->output; p_idx = output->size; @@ -1136,8 +1301,12 @@ static int cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c, struct vector_type_qualifier *v) { + struct type_delimit td; + struct read_cmd_item *rc; size_t class_type_size, class_type_len, limit; const char *class_type; + int i; + bool paren, non_cv_qualifier; if (ddata == NULL || *ddata->cur != 'F' || v == NULL) return (0); @@ -1148,12 +1317,43 @@ cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c, *ext_c = 1; ++ddata->cur; } - if (!cpp_demangle_read_type(ddata, 0)) + + /* Return type */ + if (!cpp_demangle_read_type(ddata, NULL)) return (0); + if (*ddata->cur != 'E') { - if (!DEM_PUSH_STR(ddata, "(")) + if (!DEM_PUSH_STR(ddata, " ")) + return (0); + + non_cv_qualifier = false; + if (v->size > 0) { + for (i = 0; (size_t) i < v->size; i++) { + if (v->q_container[i] != TYPE_RST && + v->q_container[i] != TYPE_VAT && + v->q_container[i] != TYPE_CST) { + non_cv_qualifier = true; + break; + } + } + } + + paren = false; + rc = vector_read_cmd_find(&ddata->cmd, READ_PTRMEM); + if (non_cv_qualifier || rc != NULL) { + if (!DEM_PUSH_STR(ddata, "(")) + return (0); + paren = true; + } + + /* Push non-cv qualifiers. */ + ddata->push_qualifier = PUSH_NON_CV_QUALIFIER; + if (!cpp_demangle_push_type_qualifier(ddata, v, NULL)) return (0); - if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM)) { + + if (rc) { + if (non_cv_qualifier && !DEM_PUSH_STR(ddata, " ")) + return (0); if ((class_type_size = ddata->class_type.size) == 0) return (0); class_type = @@ -1167,40 +1367,67 @@ cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c, return (0); if (!DEM_PUSH_STR(ddata, "::*")) return (0); - ++ddata->func_type; - } else { - if (!cpp_demangle_push_type_qualifier(ddata, v, - (const char *) NULL)) - return (0); - vector_type_qualifier_dest(v); - if (!vector_type_qualifier_init(v)) + /* Push pointer-to-member qualifiers. */ + ddata->push_qualifier = PUSH_ALL_QUALIFIER; + if (!cpp_demangle_push_type_qualifier(ddata, rc->data, + NULL)) return (0); + ++ddata->func_type; } - if (!DEM_PUSH_STR(ddata, ")(")) - return (0); + if (paren) { + if (!DEM_PUSH_STR(ddata, ")")) + return (0); + paren = false; + } + td.paren = false; + td.firstp = true; limit = 0; + ddata->is_functype = true; for (;;) { - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, &td)) return (0); if (*ddata->cur == 'E') break; if (limit++ > CPP_DEMANGLE_TRY_LIMIT) return (0); } - - if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM) == 1) { - if (!cpp_demangle_push_type_qualifier(ddata, v, - (const char *) NULL)) - return (0); - vector_type_qualifier_dest(v); - if (!vector_type_qualifier_init(v)) + ddata->is_functype = false; + if (td.paren) { + if (!DEM_PUSH_STR(ddata, ")")) return (0); + td.paren = false; } - if (!DEM_PUSH_STR(ddata, ")")) + /* Push CV qualifiers. */ + ddata->push_qualifier = PUSH_CV_QUALIFIER; + if (!cpp_demangle_push_type_qualifier(ddata, v, NULL)) return (0); + + ddata->push_qualifier = PUSH_ALL_QUALIFIER; + + /* Release type qualifier vector. */ + vector_type_qualifier_dest(v); + if (!vector_type_qualifier_init(v)) + return (0); + + /* Push ref-qualifiers. */ + if (ddata->ref_qualifier) { + switch (ddata->ref_qualifier_type) { + case TYPE_REF: + if (!DEM_PUSH_STR(ddata, " &")) + return (0); + break; + case TYPE_RREF: + if (!DEM_PUSH_STR(ddata, " &&")) + return (0); + break; + default: + return (0); + } + ddata->ref_qualifier = false; + } } ++ddata->cur; @@ -1306,7 +1533,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) goto clean3; if (*ddata->cur++ != '_') goto clean3; - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) goto clean3; if (!DEM_PUSH_STR(ddata, "-in-")) goto clean3; @@ -1328,7 +1555,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('T', 'h'): /* virtual function non-virtual override thunk */ @@ -1358,7 +1585,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('T', 'J'): /* java class */ @@ -1367,7 +1594,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('T', 'S'): /* RTTI name (NTBS) */ @@ -1376,7 +1603,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('T', 'T'): /* VTT table */ @@ -1385,7 +1612,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('T', 'v'): /* virtual function virtual override thunk */ @@ -1406,7 +1633,7 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('T', 'W'): /* TLS wrapper function */ @@ -1424,30 +1651,74 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) static int cpp_demangle_read_local_name(struct cpp_demangle_data *ddata) { + struct vector_str local_name; + struct type_delimit td; size_t limit; + bool more_type; if (ddata == NULL) return (0); if (*(++ddata->cur) == '\0') return (0); - if (!cpp_demangle_read_encoding(ddata)) + + vector_str_init(&local_name); + ddata->cur_output = &local_name; + + if (!cpp_demangle_read_encoding(ddata)) { + vector_str_dest(&local_name); return (0); + } + ddata->cur_output = &ddata->output; + + td.paren = false; + td.firstp = true; + more_type = false; limit = 0; - for (;;) { - if (!cpp_demangle_read_type(ddata, 1)) + + /* + * The first type is a return type if we just demangled template + * args. (the template args is right next to the function name, + * which means it's a template function) + */ + if (ddata->is_tmpl) { + ddata->is_tmpl = false; + + /* Read return type */ + if (!cpp_demangle_read_type(ddata, NULL)) { + vector_str_dest(&local_name); + return (0); + } + + more_type = true; + } + + /* Now we can push the name after possible return type is handled. */ + if (!vector_str_push_vector(&ddata->output, &local_name)) { + vector_str_dest(&local_name); + return (0); + } + vector_str_dest(&local_name); + + while (*ddata->cur != '\0') { + if (!cpp_demangle_read_type(ddata, &td)) return (0); + if (more_type) + more_type = false; if (*ddata->cur == 'E') break; if (limit++ > CPP_DEMANGLE_TRY_LIMIT) return (0); } + if (more_type) + return (0); + if (*(++ddata->cur) == '\0') return (0); - if (ddata->paren == true) { + if (td.paren == true) { if (!DEM_PUSH_STR(ddata, ")")) return (0); - ddata->paren = false; + td.paren = false; } if (*ddata->cur == 's') ++ddata->cur; @@ -1477,7 +1748,7 @@ cpp_demangle_read_name(struct cpp_demangle_data *ddata) if (ddata == NULL || *ddata->cur == '\0') return (0); - output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; + output = ddata->cur_output; subst_str = NULL; @@ -1539,8 +1810,7 @@ cpp_demangle_read_name_flat(struct cpp_demangle_data *ddata, char **str) size_t i, p_idx, idx, name_len; char *name; - output = ddata->push_head > 0 ? &ddata->output_tmp : - &ddata->output; + output = ddata->cur_output; p_idx = output->size; @@ -1577,8 +1847,7 @@ cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata) if (*(++ddata->cur) == '\0') return (0); - while (*ddata->cur == 'r' || *ddata->cur == 'V' || - *ddata->cur == 'K') { + do { switch (*ddata->cur) { case 'r': ddata->mem_rst = true; @@ -1589,11 +1858,19 @@ cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata) case 'K': ddata->mem_cst = true; break; + case 'R': + ddata->mem_ref = true; + break; + case 'O': + ddata->mem_rref = true; + break; + default: + goto next; } - ++ddata->cur; - } + } while (*(++ddata->cur)); - output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; +next: + output = ddata->cur_output; if (!vector_str_init(&v)) return (0); @@ -1619,6 +1896,8 @@ cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata) goto clean; } + if (p_idx == output->size) + goto next_comp; if ((subst_str = vector_str_substr(output, p_idx, output->size - 1, &subst_str_len)) == NULL) goto clean; @@ -1630,10 +1909,12 @@ cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata) if (!cpp_demangle_push_subst_v(ddata, &v)) goto clean; + + next_comp: if (*ddata->cur == 'E') break; - else if (*ddata->cur != 'I' && - *ddata->cur != 'C' && *ddata->cur != 'D') { + else if (*ddata->cur != 'I' && *ddata->cur != 'C' && + *ddata->cur != 'D' && p_idx != output->size) { if (!DEM_PUSH_STR(ddata, "::")) goto clean; if (!VEC_PUSH_STR(&v, "::")) @@ -1776,7 +2057,8 @@ cpp_demangle_read_offset_number(struct cpp_demangle_data *ddata) } static int -cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata) +cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata, + struct vector_type_qualifier *v) { size_t class_type_len, i, idx, p_idx; int p_func_type, rtn; @@ -1786,7 +2068,7 @@ cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata) return (0); p_idx = ddata->output.size; - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) return (0); if ((class_type = vector_str_substr(&ddata->output, p_idx, @@ -1799,14 +2081,14 @@ cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata) if (!vector_str_pop(&ddata->output)) goto clean1; - if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM)) + if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM, v)) goto clean1; if (!vector_str_push(&ddata->class_type, class_type, class_type_len)) goto clean2; p_func_type = ddata->func_type; - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) goto clean3; if (p_func_type == ddata->func_type) { @@ -1828,6 +2110,10 @@ clean2: clean1: free(class_type); + vector_type_qualifier_dest(v); + if (!vector_type_qualifier_init(v)) + return (0); + return (rtn); } @@ -1851,7 +2137,7 @@ cpp_demangle_read_sname(struct cpp_demangle_data *ddata) return (0); assert(ddata->output.size > 0); - if (vector_read_cmd_find(&ddata->cmd, READ_TMPL) == 0) + if (vector_read_cmd_find(&ddata->cmd, READ_TMPL) == NULL) ddata->last_sname = ddata->output.container[ddata->output.size - 1]; @@ -1877,7 +2163,7 @@ cpp_demangle_read_subst(struct cpp_demangle_data *ddata) ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::allocator", 14)); + "std::allocator")); return (1); case SIMPLE_HASH('S', 'b'): @@ -1887,40 +2173,46 @@ cpp_demangle_read_subst(struct cpp_demangle_data *ddata) ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::basic_string", 17)); + "std::basic_string")); return (1); case SIMPLE_HASH('S', 'd'): /* std::basic_iostream<char, std::char_traits<char> > */ - if (!DEM_PUSH_STR(ddata, "std::basic_iostream")) + if (!DEM_PUSH_STR(ddata, "std::basic_iostream<char, " + "std::char_traits<char> >")) return (0); ddata->last_sname = "basic_iostream"; ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::basic_iostream", 19)); + "std::basic_iostream<char, std::char_traits" + "<char> >")); return (1); case SIMPLE_HASH('S', 'i'): /* std::basic_istream<char, std::char_traits<char> > */ - if (!DEM_PUSH_STR(ddata, "std::basic_istream")) + if (!DEM_PUSH_STR(ddata, "std::basic_istream<char, " + "std::char_traits<char> >")) return (0); ddata->last_sname = "basic_istream"; ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::basic_istream", 18)); + "std::basic_istream<char, std::char_traits" + "<char> >")); return (1); case SIMPLE_HASH('S', 'o'): /* std::basic_ostream<char, std::char_traits<char> > */ - if (!DEM_PUSH_STR(ddata, "std::basic_ostream")) + if (!DEM_PUSH_STR(ddata, "std::basic_ostream<char, " + "std::char_traits<char> >")) return (0); ddata->last_sname = "basic_ostream"; ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::basic_ostream", 18)); + "std::basic_ostream<char, std::char_traits" + "<char> >")); return (1); case SIMPLE_HASH('S', 's'): @@ -1930,13 +2222,15 @@ cpp_demangle_read_subst(struct cpp_demangle_data *ddata) * * a.k.a std::string */ - if (!DEM_PUSH_STR(ddata, "std::string")) + if (!DEM_PUSH_STR(ddata, "std::basic_string<char, " + "std::char_traits<char>, std::allocator<char> >")) return (0); ddata->last_sname = "string"; ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::string", 11)); + "std::basic_string<char, std::char_traits<char>," + " std::allocator<char> >")); return (1); case SIMPLE_HASH('S', 't'): @@ -1947,6 +2241,14 @@ cpp_demangle_read_subst(struct cpp_demangle_data *ddata) if (*(++ddata->cur) == '\0') return (0); + /* Skip unknown substitution abbreviations. */ + if (!(*ddata->cur >= '0' && *ddata->cur <= '9') && + !(*ddata->cur >= 'A' && *ddata->cur <= 'Z') && + *ddata->cur != '_') { + ++ddata->cur; + return (1); + } + /* substitution */ if (*ddata->cur == '_') return (cpp_demangle_get_subst(ddata, 0)); @@ -1996,7 +2298,7 @@ cpp_demangle_read_subst_std(struct cpp_demangle_data *ddata) ddata->cur += 2; - output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; + output = ddata->cur_output; p_idx = output->size; if (!cpp_demangle_read_uqname(ddata)) @@ -2036,17 +2338,20 @@ clean: static int cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata, - const char *str, size_t len) + const char *str) { struct vector_str *output; - size_t p_idx, substr_len; + size_t p_idx, substr_len, len; int rtn; char *subst_str, *substr; - if (ddata == NULL || str == NULL || len == 0) + if (ddata == NULL || str == NULL) return (0); - output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; + if ((len = strlen(str)) == 0) + return (0); + + output = ddata->cur_output; p_idx = output->size; substr = NULL; @@ -2089,10 +2394,13 @@ cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *ddata) case 'L': return (cpp_demangle_read_expr_primary(ddata)); case 'X': - return (cpp_demangle_read_expression(ddata)); + ++ddata->cur; + if (!cpp_demangle_read_expression(ddata)) + return (0); + return (*ddata->cur++ == 'E'); } - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); } static int @@ -2107,14 +2415,14 @@ cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata) ++ddata->cur; - if (!vector_read_cmd_push(&ddata->cmd, READ_TMPL)) + if (!vector_read_cmd_push(&ddata->cmd, READ_TMPL, NULL)) return (0); if (!DEM_PUSH_STR(ddata, "<")) return (0); limit = 0; - v = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; + v = &ddata->output; for (;;) { idx = v->size; if (!cpp_demangle_read_tmpl_arg(ddata)) @@ -2139,6 +2447,7 @@ cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata) return (0); } else if (!DEM_PUSH_STR(ddata, ">")) return (0); + ddata->is_tmpl = true; break; } else if (*ddata->cur != 'I' && !DEM_PUSH_STR(ddata, ", ")) @@ -2190,46 +2499,42 @@ cpp_demangle_read_tmpl_param(struct cpp_demangle_data *ddata) } static int -cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit) +cpp_demangle_read_type(struct cpp_demangle_data *ddata, + struct type_delimit *td) { struct vector_type_qualifier v; - struct vector_str *output; - size_t p_idx, type_str_len; + struct vector_str *output, sv; + size_t p_idx, type_str_len, subst_str_len; int extern_c, is_builtin; long len; - char *type_str, *exp_str, *num_str; + const char *p; + char *type_str, *exp_str, *num_str, *subst_str; + bool skip_ref_qualifier, omit_void; if (ddata == NULL) return (0); - output = &ddata->output; - if (!strncmp(ddata->output.container[ddata->output.size - 1], ">", 1)) { - ddata->push_head++; - output = &ddata->output_tmp; - } else if (delimit == 1) { - if (ddata->paren == false) { + output = ddata->cur_output; + if (td) { + if (td->paren == false) { if (!DEM_PUSH_STR(ddata, "(")) return (0); if (ddata->output.size < 2) return (0); - ddata->paren = true; - ddata->pfirst = true; - /* Need pop function name */ - if (ddata->subst.size == 1 && - !vector_str_pop(&ddata->subst)) - return (0); + td->paren = true; } - if (ddata->pfirst) - ddata->pfirst = false; - else if (*ddata->cur != 'I' && - !DEM_PUSH_STR(ddata, ", ")) - return (0); + if (!td->firstp) { + if (*ddata->cur != 'I') { + if (!DEM_PUSH_STR(ddata, ", ")) + return (0); + } + } } assert(output != NULL); /* - * [r, V, K] [P, R, C, G, U] builtin, function, class-enum, array + * [r, V, K] [P, R, O, C, G, U] builtin, function, class-enum, array * pointer-to-member, template-param, template-template-param, subst */ @@ -2240,7 +2545,14 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit) is_builtin = 1; p_idx = output->size; type_str = exp_str = num_str = NULL; + skip_ref_qualifier = false; + again: + + /* Clear ref-qualifier flag */ + if (*ddata->cur != 'R' && *ddata->cur != 'O' && *ddata->cur != 'E') + ddata->ref_qualifier = false; + /* builtin type */ switch (*ddata->cur) { case 'a': @@ -2269,6 +2581,8 @@ again: if (!vector_type_qualifier_push(&v, TYPE_CMX)) goto clean; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 'c': @@ -2288,6 +2602,18 @@ again: case 'D': ++ddata->cur; switch (*ddata->cur) { + case 'a': + /* auto */ + if (!DEM_PUSH_STR(ddata, "auto")) + goto clean; + ++ddata->cur; + break; + case 'c': + /* decltype(auto) */ + if (!DEM_PUSH_STR(ddata, "decltype(auto)")) + goto clean; + ++ddata->cur; + break; case 'd': /* IEEE 754r decimal floating point (64 bits) */ if (!DEM_PUSH_STR(ddata, "decimal64")) @@ -2352,6 +2678,8 @@ again: ++ddata->cur; if (!vector_type_qualifier_push(&v, TYPE_VEC)) goto clean; + if (td) + td->firstp = false; goto again; default: goto clean; @@ -2365,6 +2693,16 @@ again: ++ddata->cur; goto rtn; + case 'E': + /* unexpected end except ref-qualifiers */ + if (ddata->ref_qualifier && ddata->is_functype) { + skip_ref_qualifier = true; + /* Pop the delimiter. */ + cpp_demangle_pop_str(ddata); + goto rtn; + } + goto clean; + case 'f': /* float */ if (!DEM_PUSH_STR(ddata, "float")) @@ -2391,6 +2729,8 @@ again: if (!vector_type_qualifier_push(&v, TYPE_IMG)) goto clean; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 'h': @@ -2407,6 +2747,32 @@ again: ++ddata->cur; goto rtn; + case 'I': + /* template args. */ + /* handles <substitute><template-args> */ + p_idx = output->size; + if (!cpp_demangle_read_tmpl_args(ddata)) + goto clean; + if ((subst_str = vector_str_substr(output, p_idx, + output->size - 1, &subst_str_len)) == NULL) + goto clean; + if (!vector_str_init(&sv)) { + free(subst_str); + goto clean; + } + if (!vector_str_push(&sv, subst_str, subst_str_len)) { + free(subst_str); + vector_str_dest(&sv); + goto clean; + } + free(subst_str); + if (!cpp_demangle_push_subst_v(ddata, &sv)) { + vector_str_dest(&sv); + goto clean; + } + vector_str_dest(&sv); + goto rtn; + case 'j': /* unsigned int */ if (!DEM_PUSH_STR(ddata, "unsigned int")) @@ -2419,6 +2785,8 @@ again: if (!vector_type_qualifier_push(&v, TYPE_CST)) goto clean; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 'l': @@ -2438,7 +2806,7 @@ again: goto rtn; case 'M': /* pointer to member */ - if (!cpp_demangle_read_pointer_to_member(ddata)) + if (!cpp_demangle_read_pointer_to_member(ddata, &v)) goto clean; is_builtin = 0; goto rtn; @@ -2457,11 +2825,26 @@ again: ++ddata->cur; goto rtn; + case 'O': + /* rvalue reference */ + if (ddata->ref_qualifier) + goto clean; + if (!vector_type_qualifier_push(&v, TYPE_RREF)) + goto clean; + ddata->ref_qualifier = true; + ddata->ref_qualifier_type = TYPE_RREF; + ++ddata->cur; + if (td) + td->firstp = false; + goto again; + case 'P': /* pointer */ if (!vector_type_qualifier_push(&v, TYPE_PTR)) goto clean; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 'r': @@ -2469,13 +2852,21 @@ again: if (!vector_type_qualifier_push(&v, TYPE_RST)) goto clean; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 'R': /* reference */ + if (ddata->ref_qualifier) + goto clean; if (!vector_type_qualifier_push(&v, TYPE_REF)) goto clean; + ddata->ref_qualifier = true; + ddata->ref_qualifier_type = TYPE_REF; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 's': @@ -2516,6 +2907,7 @@ again: case 'U': /* vendor extended type qualifier */ + ++ddata->cur; if (!cpp_demangle_read_number(ddata, &len)) goto clean; if (len <= 0) @@ -2525,11 +2917,29 @@ again: ddata->cur += len; if (!vector_type_qualifier_push(&v, TYPE_EXT)) goto clean; + if (td) + td->firstp = false; goto again; case 'v': /* void */ - if (!DEM_PUSH_STR(ddata, "void")) + omit_void = false; + if (td && td->firstp) { + /* + * peek into next bytes and see if we should omit + * the "void". + */ + omit_void = true; + for (p = ddata->cur + 1; *p != '\0'; p++) { + if (*p == 'E') + break; + if (*p != 'R' && *p != 'O') { + omit_void = false; + break; + } + } + } + if (!omit_void && !DEM_PUSH_STR(ddata, "void")) goto clean; ++ddata->cur; goto rtn; @@ -2539,6 +2949,8 @@ again: if (!vector_type_qualifier_push(&v, TYPE_VAT)) goto clean; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 'w': @@ -2575,9 +2987,9 @@ again: is_builtin = 0; rtn: - if ((type_str = vector_str_substr(output, p_idx, output->size - 1, - &type_str_len)) == NULL) - goto clean; + + type_str = vector_str_substr(output, p_idx, output->size - 1, + &type_str_len); if (is_builtin == 0) { if (!vector_str_find(&ddata->subst, type_str, type_str_len) && @@ -2585,40 +2997,18 @@ rtn: goto clean; } - if (!cpp_demangle_push_type_qualifier(ddata, &v, type_str)) + if (!skip_ref_qualifier && + !cpp_demangle_push_type_qualifier(ddata, &v, type_str)) goto clean; + if (td) + td->firstp = false; + free(type_str); free(exp_str); free(num_str); vector_type_qualifier_dest(&v); - if (ddata->push_head > 0) { - if (*ddata->cur == 'I' && cpp_demangle_read_tmpl_args(ddata) - == 0) - return (0); - - if (--ddata->push_head > 0) - return (1); - - if (!VEC_PUSH_STR(&ddata->output_tmp, " ")) - return (0); - - if (!vector_str_push_vector_head(&ddata->output, - &ddata->output_tmp)) - return (0); - - vector_str_dest(&ddata->output_tmp); - if (!vector_str_init(&ddata->output_tmp)) - return (0); - - if (!DEM_PUSH_STR(ddata, "(")) - return (0); - - ddata->paren = true; - ddata->pfirst = true; - } - return (1); clean: free(type_str); @@ -2636,12 +3026,11 @@ cpp_demangle_read_type_flat(struct cpp_demangle_data *ddata, char **str) size_t i, p_idx, idx, type_len; char *type; - output = ddata->push_head > 0 ? &ddata->output_tmp : - &ddata->output; + output = ddata->cur_output; p_idx = output->size; - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) return (0); if ((type = vector_str_substr(output, p_idx, output->size - 1, @@ -2736,7 +3125,7 @@ cpp_demangle_read_uqname(struct cpp_demangle_data *ddata) if (!DEM_PUSH_STR(ddata, "operator(cast)")) return (0); ddata->cur += 2; - return (cpp_demangle_read_type(ddata, 1)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('d', 'a'): /* operator delete [] */ @@ -3046,9 +3435,7 @@ cpp_demangle_read_uqname(struct cpp_demangle_data *ddata) /* ctor-dtor-name */ switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { case SIMPLE_HASH('C', '1'): - /* FALLTHROUGH */ case SIMPLE_HASH('C', '2'): - /* FALLTHROUGH */ case SIMPLE_HASH('C', '3'): if (ddata->last_sname == NULL) return (0); @@ -3062,9 +3449,7 @@ cpp_demangle_read_uqname(struct cpp_demangle_data *ddata) return (1); case SIMPLE_HASH('D', '0'): - /* FALLTHROUGH */ case SIMPLE_HASH('D', '1'): - /* FALLTHROUGH */ case SIMPLE_HASH('D', '2'): if (ddata->last_sname == NULL) return (0); @@ -3468,20 +3853,19 @@ vector_read_cmd_dest(struct vector_read_cmd *v) free(v->r_container); } -/* return -1 at failed, 0 at not found, 1 at found. */ -static int +static struct read_cmd_item * vector_read_cmd_find(struct vector_read_cmd *v, enum read_cmd dst) { - size_t i; + int i; if (v == NULL || dst == READ_FAIL) - return (-1); + return (NULL); - for (i = 0; i < v->size; ++i) - if (v->r_container[i] == dst) - return (1); + for (i = (int) v->size - 1; i >= 0; i--) + if (v->r_container[i].cmd == dst) + return (&v->r_container[i]); - return (0); + return (NULL); } static int @@ -3494,7 +3878,7 @@ vector_read_cmd_init(struct vector_read_cmd *v) v->size = 0; v->capacity = VECTOR_DEF_CAPACITY; - if ((v->r_container = malloc(sizeof(enum read_cmd) * v->capacity)) + if ((v->r_container = malloc(sizeof(*v->r_container) * v->capacity)) == NULL) return (0); @@ -3509,15 +3893,16 @@ vector_read_cmd_pop(struct vector_read_cmd *v) return (0); --v->size; - v->r_container[v->size] = READ_FAIL; + v->r_container[v->size].cmd = READ_FAIL; + v->r_container[v->size].data = NULL; return (1); } static int -vector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd) +vector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd, void *data) { - enum read_cmd *tmp_r_ctn; + struct read_cmd_item *tmp_r_ctn; size_t tmp_cap; size_t i; @@ -3526,8 +3911,7 @@ vector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd) if (v->size == v->capacity) { tmp_cap = v->capacity * BUFFER_GROWFACTOR; - if ((tmp_r_ctn = malloc(sizeof(enum read_cmd) * tmp_cap)) - == NULL) + if ((tmp_r_ctn = malloc(sizeof(*tmp_r_ctn) * tmp_cap)) == NULL) return (0); for (i = 0; i < v->size; ++i) tmp_r_ctn[i] = v->r_container[i]; @@ -3536,7 +3920,8 @@ vector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd) v->capacity = tmp_cap; } - v->r_container[v->size] = cmd; + v->r_container[v->size].cmd = cmd; + v->r_container[v->size].data = data; ++v->size; return (1); diff --git a/libelftc/libelftc_vstr.c b/libelftc/libelftc_vstr.c index 4b0977efa0f5..934b5dba4c96 100644 --- a/libelftc/libelftc_vstr.c +++ b/libelftc/libelftc_vstr.c @@ -33,7 +33,7 @@ #include "_libelftc.h" -ELFTC_VCSID("$Id: libelftc_vstr.c 2065 2011-10-26 15:24:47Z jkoshy $"); +ELFTC_VCSID("$Id: libelftc_vstr.c 3531 2017-06-05 05:08:43Z kaiwang27 $"); /** * @file vector_str.c @@ -281,6 +281,47 @@ vector_str_push_vector_head(struct vector_str *dst, struct vector_str *org) } /** + * @brief Push org vector to the tail of det vector. + * @return false at failed, true at success. + */ +bool +vector_str_push_vector(struct vector_str *dst, struct vector_str *org) +{ + size_t i, j, tmp_cap; + char **tmp_ctn; + + if (dst == NULL || org == NULL) + return (false); + + tmp_cap = (dst->size + org->size) * BUFFER_GROWFACTOR; + + if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL) + return (false); + + for (i = 0; i < dst->size; ++i) + tmp_ctn[i] = dst->container[i]; + + for (i = 0; i < org->size; ++i) + if ((tmp_ctn[i + dst->size] = strdup(org->container[i])) == + NULL) { + for (j = 0; j < i + dst->size; ++j) + free(tmp_ctn[j]); + + free(tmp_ctn); + + return (false); + } + + free(dst->container); + + dst->container = tmp_ctn; + dst->capacity = tmp_cap; + dst->size += org->size; + + return (true); +} + +/** * @brief Get new allocated flat string from vector between begin and end. * * If r_len is not NULL, string length will be returned. diff --git a/test/cxxfilt/tet_scen b/test/cxxfilt/tet_scen index ec503cd8389d..9ec6da840fa6 100644 --- a/test/cxxfilt/tet_scen +++ b/test/cxxfilt/tet_scen @@ -2,16 +2,40 @@ all "Starting Test Suite" + ^builtin ^misc + ^qualifiers ^regression + ^substitute + ^template "Complete Test Suite" +builtin + "Starting builtin Test" + /ts/builtin/tc + "Complete builtin Test" + misc "Starting misc Test" /ts/misc/tc "Complete misc Test" +qualifiers + "Starting qualifiers Test" + /ts/qualifiers/tc + "Complete qualifiers Test" + regression "Starting regression Test" /ts/regression/tc "Complete regression Test" + +substitute + "Starting substitute Test" + /ts/substitute/tc + "Complete substitute Test" + +template + "Starting template Test" + /ts/template/tc + "Complete template Test" diff --git a/test/cxxfilt/ts/Makefile b/test/cxxfilt/ts/Makefile index 9e2f728033c4..45e4e5560918 100644 --- a/test/cxxfilt/ts/Makefile +++ b/test/cxxfilt/ts/Makefile @@ -2,7 +2,11 @@ TOP= ../../.. +SUBDIR+= builtin SUBDIR+= misc +SUBDIR+= qualifiers SUBDIR+= regression +SUBDIR+= substitute +SUBDIR+= template .include "${TOP}/mk/elftoolchain.subdir.mk" diff --git a/test/cxxfilt/ts/builtin/Makefile b/test/cxxfilt/ts/builtin/Makefile new file mode 100644 index 000000000000..ecc228b09b30 --- /dev/null +++ b/test/cxxfilt/ts/builtin/Makefile @@ -0,0 +1,5 @@ +# $Id$ + +TOP= ../../../.. + +.include "../common/ts.mk" diff --git a/test/cxxfilt/ts/builtin/tclist b/test/cxxfilt/ts/builtin/tclist new file mode 100644 index 000000000000..3c8ae278332e --- /dev/null +++ b/test/cxxfilt/ts/builtin/tclist @@ -0,0 +1,48 @@ +# <builtin-type> ::= v # void +# ::= w # wchar_t +# ::= b # bool +# ::= c # char +# ::= a # signed char +# ::= h # unsigned char +# ::= s # short +# ::= t # unsigned short +# ::= i # int +# ::= j # unsigned int +# ::= l # long +# ::= m # unsigned long +# ::= x # long long, __int64 +# ::= y # unsigned long long, __int64 +# ::= n # __int128 +# ::= o # unsigned __int128 +# ::= f # float +# ::= d # double +# ::= e # long double, __float80 +# ::= g # __float128 +# ::= z # ellipsis +# ::= Dd # IEEE 754r decimal floating point (64 bits) +# ::= De # IEEE 754r decimal floating point (128 bits) +# ::= Df # IEEE 754r decimal floating point (32 bits) +# ::= Dh # IEEE 754r half-precision floating point (16 bits) +# ::= Di # char32_t +# ::= Ds # char16_t +# ::= Da # auto +# ::= Dc # decltype(auto) +# ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) +# ::= u <source-name> # vendor extended type + +"_Z3barv", "bar()" +"_Z3barPv", "bar(void*)" +"_Z3bariPv", "bar(int, void*)" +"_Z3fooww", "foo(wchar_t, wchar_t)" +"_Z3foob", "foo(bool)" +"_Z3foocah", "foo(char, signed char, unsigned char)" +"_Z3barstij", "bar(short, unsigned short, int, unsigned int)" +"_Z3barlmxy", "bar(long, unsigned long, long long, unsigned long long)" +"_Z3barno", "bar(__int128, unsigned __int128)" +"_Z3foofdeg", "foo(float, double, long double, __float128)" +"_Z3fooiPcz", "foo(int, char*, ...)" +"_Z3fooDdDeDfDh", "foo(decimal64, decimal128, decimal32, half)" +"_Z3barDiDs", "bar(char32_t, char16_t)" +"_Z3barIiEDai", "auto bar<int>(int)" +"_Z3barIiEDci", "decltype(auto) bar<int>(int)" +"_Z3barIiEDni", "decltype(nullptr) bar<int>(int)" diff --git a/test/cxxfilt/ts/misc/tclist b/test/cxxfilt/ts/misc/tclist index afc1cf62fcbb..ebe3e65c1d1b 100644 --- a/test/cxxfilt/ts/misc/tclist +++ b/test/cxxfilt/ts/misc/tclist @@ -1,11 +1,11 @@ # simple function - "_Z1f", "f" "_Z1fi", "f(int)" "_Z1fic", "f(int, char)" +"_Z1f3bar", "f(bar)" +"_Z1fFviE", "f(void (int))" # namespace - "_ZN12elftoolchainE", "elftoolchain" "_ZN11elftoolchainE", "_ZN11elftoolchainE" "_ZN12elftoolchain", "_ZN12elftoolchain" @@ -13,3 +13,39 @@ "_ZN12elftoolchain3foo3barEi", "elftoolchain::foo::bar(int)" "_ZN12elftoolchain3foo3barEic", "elftoolchain::foo::bar(int, char)" +# non-static member function with qualifiers <nested-name> +# N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E +"_ZNKR12elftoolchain3fooEi", "elftoolchain::foo(int) const &" +"_ZNKO12elftoolchain3fooEi", "elftoolchain::foo(int) const &&" + +# function type with qualifiers. (note that the place to encode qualifiers +# is different than <nested-name>) +# <function-type> ::= [<CV-qualifiers>] [Dx] F [Y] <bare-function-type> + [<ref-qualifier>] E +"_Z3fooKFviRE", "foo(void (int) const &)" +"_Z3fooKFviOE", "foo(void (int) const &&)" + +# Pointer-to-member type and type qualifiers +# <pointer-to-member-type> ::= M <class type> <member type> +"_Z3barM12elftoolchainFviE", "bar(void (elftoolchain::*)(int))" +"_Z3barM12elftoolchainKFviRE", "bar(void (elftoolchain::*)(int) const &)" +"_Z3fooFvvEM1AFvvE", "foo(void (), void (A::*)())" +"_Z3fooPFvvEM1AFvvE", "foo(void (*)(), void (A::*)())" +"_Z3fooPFvvREM1AFvvE", "foo(void (*)() &, void (A::*)())" +"_Z3fooPFvvREM1AFvvOE", "foo(void (*)() &, void (A::*)() &&)" +"_Z3fooKFvvREM1AFvvE", "foo(void () const &, void (A::*)())" +"_Z3fooKPFvvREM1AFvvE", "foo(void (* const)() &, void (A::*)())" +"_Z3fooPKFvvREM1AFvvE", "foo(void (*)() const &, void (A::*)())" +"_Z3fooPKFvvREPM1AFvvE", "foo(void (*)() const &, void (A::**)())" +"_Z3fooPKFviREPM1AFvidE", "foo(void (*)(int) const &, void (A::**)(int, double))" +"_Z3fooPrKFvvREPKVM1APKFvvE", "foo(void (*)() const restrict &, void (* A::* volatile const*)() const)" + +# local names + + + +# abbreviation St +"_ZSt3foo", '::std::foo' +"_ZNSt3for3barE", 'std::for::bar' + +# c++11 decltype diff --git a/test/cxxfilt/ts/qualifiers/Makefile b/test/cxxfilt/ts/qualifiers/Makefile new file mode 100644 index 000000000000..ecc228b09b30 --- /dev/null +++ b/test/cxxfilt/ts/qualifiers/Makefile @@ -0,0 +1,5 @@ +# $Id$ + +TOP= ../../../.. + +.include "../common/ts.mk" diff --git a/test/cxxfilt/ts/qualifiers/tclist b/test/cxxfilt/ts/qualifiers/tclist new file mode 100644 index 000000000000..98e725c7a6a2 --- /dev/null +++ b/test/cxxfilt/ts/qualifiers/tclist @@ -0,0 +1,36 @@ +# <type> ::= <CV-qualifiers> <type> +# ::= P <type> # pointer-to +# ::= R <type> # reference-to +# ::= O <type> # rvalue reference-to (C++0x) +# ::= C <type> # complex pair (C 2000) +# ::= G <type> # imaginary (C 2000) +# ::= U <source-name> [<template-args>] <type> # vendor extended type qualifier + +# <CV-qualifiers> ::= [r] [V] [K] +"_Z3foorPirPirPi", "foo(int* restrict, int* restrict, int* restrict)" +"_Z3fooVPd", "foo(double* volatile)" + +# Pointer +"_Z3fooPi", "foo(int*)" +"_Z3fooPPi", "foo(int**)" +"_Z3fooKPi", "foo(int* const)" +"_Z3fooPKi", "foo(int const*)" +"_Z3fooKPKi", "foo(int const* const)" +"_Z3fooKPPi", "foo(int** const)" +"_Z3fooPKPi", "foo(int* const*)" +"_Z3fooPPKi", "foo(int const**)" +"_Z3fooKPKPi", "foo(int* const* const)" + +# Reference +"_Z3barRi", "bar(int&)" +"_Z3barRKi", "bar(int const&)" +"_ZplR1XS0_", "operator+(X&, X&)" +"_ZrsRK1XS1_", "operator>>(X const&, X const&)" +"_ZN1XaSEO1X", "X::operator=(X&&)" + +# Complex +"_Z3fooCd", "foo(double complex)" +"_Z3fooGdGf", "foo(double imaginary, float imaginary)" + +# Vendor +"_Z3fooPU3farc", "foo(char far*)" diff --git a/test/cxxfilt/ts/substitute/Makefile b/test/cxxfilt/ts/substitute/Makefile new file mode 100644 index 000000000000..ecc228b09b30 --- /dev/null +++ b/test/cxxfilt/ts/substitute/Makefile @@ -0,0 +1,5 @@ +# $Id$ + +TOP= ../../../.. + +.include "../common/ts.mk" diff --git a/test/cxxfilt/ts/substitute/tclist b/test/cxxfilt/ts/substitute/tclist new file mode 100644 index 000000000000..41173dc6fa82 --- /dev/null +++ b/test/cxxfilt/ts/substitute/tclist @@ -0,0 +1,56 @@ +# <substitution> ::= S <seq-id> _ +# ::= S_ + +"_ZN1N1TIiiE2mfES_IddE", "N::T<int, int>::mf(N<double, double>)" +"_ZN1N1TIiiE2mfES0_IddE", "N::T<int, int>::mf(N::T<double, double>)" +"_ZN1N1TIiiE2mfES1_IddE", "N::T<int, int>::mf(N::T<int, int><double, double>)" +"_ZN1N1TIiiE2mfES2_IddE", "_ZN1N1TIiiE2mfES2_IddE" +# wrong result: +# "_ZN1N1TIiiE2mfES2_IddE", "N::T<int, int>::mf(N::T<int, int>::mf<double, double>)" + +"_ZN1f1gEP1hNS_1iE", "f::g(h*, f::i)" +"_ZN1f1gEP1hNS0_1iE", "f::g(h*, h::i)" +# wrong result: +# "_ZN1f1gEP1hNS0_1iE", "f::g(h*, f::g::i)" +"_ZN1f1gEP1hNS1_1iE", "f::g(h*, h*::i)" + +"_Z3fooN1A1B1TES_", "foo(A::B::T, A)" +"_Z3fooN1A1B1TES0_", "foo(A::B::T, A::B)" +"_Z3fooN1A1B1TES1_", "foo(A::B::T, A::B::T)" + +"_Z3foo5Hello5WorldS_S0_", "foo(Hello, World, Hello, World)" + +# qualifiers with builtin type should be substitute candidates +"_Z3fooPiS_", "foo(int*, int*)" +"_Z3fooKPiS_", "foo(int* const, int*)" +"_Z3fooKPiS0_", "foo(int* const, int* const)" +"_Z3fooRKiS_", "foo(int const&, int const)" +"_Z3fooRKiS0_", "foo(int const&, int const&)" +"_Z3foorKiS_", "foo(int const restrict, int const restrict)" +"_Z3fooPrKiS_", "foo(int const restrict*, int const restrict)" +"_Z3fooPrKiS0_", "foo(int const restrict*, int const restrict*)" +"_Z3foorPKiS_", "foo(int const* restrict, int const)" +"_Z3foorPKiS0_", "foo(int const* restrict, int const*)" +"_Z3foorPKiS1_", "foo(int const* restrict, int const* restrict)" +"_Z3foorKPiS_", "foo(int* const restrict, int*)" +"_Z3foorKPiS0_", "foo(int* const restrict, int* const restrict)" + +# qualifers with non-builin type +"_Z3fooP3BarS_", "foo(Bar*, Bar)" +"_Z3fooP3BarS0_", "foo(Bar*, Bar*)" +"_Z3fooPK3BarS_", "foo(Bar const*, Bar)" +"_Z3fooPK3BarS1_", "foo(Bar const*, Bar const*)" +"_Z3foorKP3BarS0_", "foo(Bar* const restrict, Bar*)" +"_Z3foorKP3BarS1_", "foo(Bar* const restrict, Bar* const restrict)" + +# vendor extended qualifiers and substitution +# note that ABI requires that "the type with all the K, V, and r qualifiers +# " plus any vendor extended types in the same order-insensitive set is +# substitutible". Here vendor extended type is not handled as above +# requirement. +"_Z3fooU3barKiS_", "foo(int const bar, int const)" +"_Z3fooU3barKiS0_", "foo(int const bar, int const bar)" + +# bug introduced with a botched fix for omitting "void" +"_Z3barvPvS_", "bar(void, void*, void*)" +# wrong result: bar(void, void*, void, void*) diff --git a/test/cxxfilt/ts/template/Makefile b/test/cxxfilt/ts/template/Makefile new file mode 100644 index 000000000000..ecc228b09b30 --- /dev/null +++ b/test/cxxfilt/ts/template/Makefile @@ -0,0 +1,5 @@ +# $Id$ + +TOP= ../../../.. + +.include "../common/ts.mk" diff --git a/test/cxxfilt/ts/template/tclist b/test/cxxfilt/ts/template/tclist new file mode 100644 index 000000000000..bb1a6234b605 --- /dev/null +++ b/test/cxxfilt/ts/template/tclist @@ -0,0 +1,10 @@ +# Misc +"_Z1TIiE", "T<int>" +"_Z1TIidE", "T<int, double>" +"_Z1TIidET_T0_", "int T<int, double>(double)" +"_ZN3Foo3BarIiiE1fEii", "Foo::Bar<int, int>::f(int, int)" +"_ZN3Foo3BarIiiE1fIiiEEii", "int Foo::Bar<int, int>::f<int, int>(int)" +"_ZN3Foo3BarIiiE1fE1TIiE", "Foo::Bar<int, int>::f(T<int>)" +"_ZN3Foo3BarIiiE1fE1TIiEi", "Foo::Bar<int, int>::f(T<int>, int)" +"_ZN3Foo3BarIiiE1fE1TIiEii", "Foo::Bar<int, int>::f(T<int>, int, int)" +"_Z3foo1TIiEdh", "foo(T<int>, double, unsigned char)" diff --git a/test/elfcopy/plugin/os.FreeBSD.mk b/test/elfcopy/plugin/os.FreeBSD.mk new file mode 100644 index 000000000000..c29af70518a9 --- /dev/null +++ b/test/elfcopy/plugin/os.FreeBSD.mk @@ -0,0 +1,2 @@ +DPADD+= ${LIBBZ2} +LDADD+= -lbz2 |