Update to ELF Tool Chain r3223

Highlights (upstream revisions):
 - Fix SHT_GROUP handling in elfcopy/strip (3206 3220 3221)
 - Misc elfcopy / strip bug fixes (3215 3216 3217)
 - Many C++ demangler improvements (3199 3200 3201 3202 3203 3204 3205
   3208 3210 3211 3212)
 - Improve GNU binutils compatibility in elfcopy / strip (3213 3214)
 - Add -g option to readelf(1): dump contents of section groups (3219)
 - Add EM_IAMCU 32-bit Intel MCU (3198)

Also add a compat #define for building with older FreeBSD ELF headers.
The GRP_COMDAT flag was added to elf_common.h in r283110, but it's not
available during the bootstrap build.  It is also convenient to be able
to build on older hosts.

Thanks to antoine@ for tracking down issues through multiple exp-runs
and to kaiw@ for fixing.

PR:		198611 (exp-run), 200350
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Ed Maste 2015-05-27 14:28:19 +00:00
commit 3ef90571c1
12 changed files with 692 additions and 78 deletions

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: _elftc.h 3175 2015-03-27 17:21:24Z emaste $ * $Id: _elftc.h 3209 2015-05-17 13:40:46Z kaiwang27 $
*/ */
/** /**
@ -342,12 +342,13 @@ struct name { \
#if defined(__GLIBC__) || defined(__linux__) #if defined(__GLIBC__) || defined(__linux__)
#ifndef _GNU_SOURCE
/* /*
* GLIBC based systems have a global 'char *' pointer referencing * GLIBC based systems have a global 'char *' pointer referencing
* the executable's name. * the executable's name.
*/ */
extern const char *program_invocation_short_name; extern const char *program_invocation_short_name;
#endif /* !_GNU_SOURCE */
#define ELFTC_GETPROGNAME() program_invocation_short_name #define ELFTC_GETPROGNAME() program_invocation_short_name

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: elfdefinitions.h 3178 2015-03-30 18:29:13Z emaste $ * $Id: elfdefinitions.h 3198 2015-05-14 18:36:19Z emaste $
*/ */
/* /*
@ -565,6 +565,7 @@ _ELF_DEFINE_EM(EM_SPARC, 2, "SPARC") \
_ELF_DEFINE_EM(EM_386, 3, "Intel 80386") \ _ELF_DEFINE_EM(EM_386, 3, "Intel 80386") \
_ELF_DEFINE_EM(EM_68K, 4, "Motorola 68000") \ _ELF_DEFINE_EM(EM_68K, 4, "Motorola 68000") \
_ELF_DEFINE_EM(EM_88K, 5, "Motorola 88000") \ _ELF_DEFINE_EM(EM_88K, 5, "Motorola 88000") \
_ELF_DEFINE_EM(EM_IAMCU, 6, "Intel MCU") \
_ELF_DEFINE_EM(EM_860, 7, "Intel 80860") \ _ELF_DEFINE_EM(EM_860, 7, "Intel 80860") \
_ELF_DEFINE_EM(EM_MIPS, 8, "MIPS I Architecture") \ _ELF_DEFINE_EM(EM_MIPS, 8, "MIPS I Architecture") \
_ELF_DEFINE_EM(EM_S370, 9, "IBM System/370 Processor") \ _ELF_DEFINE_EM(EM_S370, 9, "IBM System/370 Processor") \

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: elfcopy.h 3173 2015-03-27 16:46:13Z emaste $ * $Id: elfcopy.h 3221 2015-05-24 23:42:43Z kaiwang27 $
*/ */
#include <sys/queue.h> #include <sys/queue.h>
@ -237,6 +237,7 @@ struct elfcopy {
uint64_t *secndx; /* section index map. */ uint64_t *secndx; /* section index map. */
uint64_t *symndx; /* symbol index map. */ uint64_t *symndx; /* symbol index map. */
unsigned char *v_rel; /* symbols needed by relocation. */ unsigned char *v_rel; /* symbols needed by relocation. */
unsigned char *v_grp; /* symbols refered by section group. */
unsigned char *v_secsym; /* sections with section symbol. */ unsigned char *v_secsym; /* sections with section symbol. */
STAILQ_HEAD(, segment) v_seg; /* list of segments. */ STAILQ_HEAD(, segment) v_seg; /* list of segments. */
STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */ STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */

View File

@ -39,7 +39,7 @@
#include "elfcopy.h" #include "elfcopy.h"
ELFTC_VCSID("$Id: main.c 3174 2015-03-27 17:13:41Z emaste $"); ELFTC_VCSID("$Id: main.c 3216 2015-05-23 21:16:36Z kaiwang27 $");
enum options enum options
{ {
@ -404,7 +404,18 @@ create_elf(struct elfcopy *ecp)
* Insert SHDR table into the internal section list as a "pseudo" * Insert SHDR table into the internal section list as a "pseudo"
* section, so later it will get sorted and resynced just as "normal" * section, so later it will get sorted and resynced just as "normal"
* sections. * sections.
*
* Under FreeBSD, Binutils objcopy always put the section header
* at the end of all the sections. We want to do the same here.
*
* However, note that the behaviour is still different with Binutils:
* elfcopy checks the FreeBSD OSABI tag to tell whether it needs to
* move the section headers, while Binutils is probably configured
* this way when it's compiled on FreeBSD.
*/ */
if (oeh.e_ident[EI_OSABI] == ELFOSABI_FREEBSD)
shtab = insert_shtab(ecp, 1);
else
shtab = insert_shtab(ecp, 0); shtab = insert_shtab(ecp, 0);
/* /*
@ -485,6 +496,11 @@ free_elf(struct elfcopy *ecp)
free(sec); free(sec);
} }
} }
if (ecp->secndx != NULL) {
free(ecp->secndx);
ecp->secndx = NULL;
}
} }
/* Create a temporary file. */ /* Create a temporary file. */

View File

@ -34,7 +34,7 @@
#include "elfcopy.h" #include "elfcopy.h"
ELFTC_VCSID("$Id: sections.c 3185 2015-04-11 08:56:34Z kaiwang27 $"); ELFTC_VCSID("$Id: sections.c 3220 2015-05-24 23:42:39Z kaiwang27 $");
static void add_gnu_debuglink(struct elfcopy *ecp); static void add_gnu_debuglink(struct elfcopy *ecp);
static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc);
@ -56,6 +56,7 @@ static void print_data(const char *d, size_t sz);
static void print_section(struct section *s); static void print_section(struct section *s);
static void *read_section(struct section *s, size_t *size); static void *read_section(struct section *s, size_t *size);
static void update_reloc(struct elfcopy *ecp, struct section *s); static void update_reloc(struct elfcopy *ecp, struct section *s);
static void update_section_group(struct elfcopy *ecp, struct section *s);
int int
is_remove_section(struct elfcopy *ecp, const char *name) is_remove_section(struct elfcopy *ecp, const char *name)
@ -552,6 +553,14 @@ copy_content(struct elfcopy *ecp)
(s->type == SHT_REL || s->type == SHT_RELA)) (s->type == SHT_REL || s->type == SHT_RELA))
filter_reloc(ecp, s); filter_reloc(ecp, s);
/*
* The section indices in the SHT_GROUP section needs
* to be updated since we might have stripped some
* sections and changed section numbering.
*/
if (s->type == SHT_GROUP)
update_section_group(ecp, s);
if (is_modify_section(ecp, s->name)) if (is_modify_section(ecp, s->name))
modify_section(ecp, s); modify_section(ecp, s);
@ -571,6 +580,71 @@ copy_content(struct elfcopy *ecp)
} }
} }
/*
* Update section group section. The section indices in the SHT_GROUP
* section need update after section numbering changed.
*/
static void
update_section_group(struct elfcopy *ecp, struct section *s)
{
GElf_Shdr ish;
Elf_Data *id;
uint32_t *ws, *wd;
uint64_t n;
size_t ishnum;
int i, j;
if (!elf_getshnum(ecp->ein, &ishnum))
errx(EXIT_FAILURE, "elf_getshnum failed: %s",
elf_errmsg(-1));
if (gelf_getshdr(s->is, &ish) == NULL)
errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
elf_errmsg(-1));
if ((id = elf_getdata(s->is, NULL)) == NULL)
errx(EXIT_FAILURE, "elf_getdata() failed: %s",
elf_errmsg(-1));
if (ish.sh_size == 0)
return;
if (ish.sh_entsize == 0)
ish.sh_entsize = 4;
ws = id->d_buf;
/* We only support COMDAT section. */
#ifndef GRP_COMDAT
#define GRP_COMDAT 0x1
#endif
if ((*ws & GRP_COMDAT) == 0)
return;
if ((s->buf = malloc(ish.sh_size)) == NULL)
err(EXIT_FAILURE, "malloc failed");
s->sz = ish.sh_size;
wd = s->buf;
/* Copy the flag word as-is. */
*wd = *ws;
/* Update the section indices. */
n = ish.sh_size / ish.sh_entsize;
for(i = 1, j = 1; (uint64_t)i < n; i++) {
if (ws[i] != SHN_UNDEF && ws[i] < ishnum &&
ecp->secndx[ws[i]] != 0)
wd[j++] = ecp->secndx[ws[i]];
else
s->sz -= 4;
}
s->nocopy = 1;
}
/* /*
* Filter relocation entries, only keep those entries whose * Filter relocation entries, only keep those entries whose
* symbol is in the keep list. * symbol is in the keep list.
@ -1028,8 +1102,11 @@ copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy,
osh.sh_flags |= SHF_WRITE; osh.sh_flags |= SHF_WRITE;
if (sec_flags & SF_CODE) if (sec_flags & SF_CODE)
osh.sh_flags |= SHF_EXECINSTR; osh.sh_flags |= SHF_EXECINSTR;
} else } else {
osh.sh_flags = ish.sh_flags; osh.sh_flags = ish.sh_flags;
if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
osh.sh_flags |= SHF_INFO_LINK;
}
} }
if (name == NULL) if (name == NULL)

View File

@ -33,7 +33,7 @@
#include "elfcopy.h" #include "elfcopy.h"
ELFTC_VCSID("$Id: symbols.c 3191 2015-05-04 17:07:01Z jkoshy $"); ELFTC_VCSID("$Id: symbols.c 3222 2015-05-24 23:47:23Z kaiwang27 $");
/* Symbol table buffer structure. */ /* Symbol table buffer structure. */
struct symbuf { struct symbuf {
@ -77,7 +77,8 @@ static int is_weak_symbol(unsigned char st_info);
static int lookup_exact_string(hash_head *hash, const char *buf, static int lookup_exact_string(hash_head *hash, const char *buf,
const char *s); const char *s);
static int generate_symbols(struct elfcopy *ecp); static int generate_symbols(struct elfcopy *ecp);
static void mark_symbols(struct elfcopy *ecp, size_t sc); static void mark_reloc_symbols(struct elfcopy *ecp, size_t sc);
static void mark_section_group_symbols(struct elfcopy *ecp, size_t sc);
static int match_wildcard(const char *name, const char *pattern); static int match_wildcard(const char *name, const char *pattern);
uint32_t str_hash(const char *s); uint32_t str_hash(const char *s);
@ -160,6 +161,10 @@ is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s)
if (BIT_ISSET(ecp->v_rel, i)) if (BIT_ISSET(ecp->v_rel, i))
return (1); return (1);
/* Symbols refered by COMDAT sections are needed. */
if (BIT_ISSET(ecp->v_grp, i))
return (1);
/* /*
* For relocatable files (.o files), global and weak symbols * For relocatable files (.o files), global and weak symbols
* are needed. * are needed.
@ -207,7 +212,10 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
return (1); return (1);
if (ecp->v_rel == NULL) if (ecp->v_rel == NULL)
mark_symbols(ecp, sc); mark_reloc_symbols(ecp, sc);
if (ecp->v_grp == NULL)
mark_section_group_symbols(ecp, sc);
if (is_needed_symbol(ecp, i, s)) if (is_needed_symbol(ecp, i, s))
return (0); return (0);
@ -233,7 +241,7 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
* Mark symbols refered by relocation entries. * Mark symbols refered by relocation entries.
*/ */
static void static void
mark_symbols(struct elfcopy *ecp, size_t sc) mark_reloc_symbols(struct elfcopy *ecp, size_t sc)
{ {
const char *name; const char *name;
Elf_Data *d; Elf_Data *d;
@ -311,6 +319,49 @@ mark_symbols(struct elfcopy *ecp, size_t sc)
elf_errmsg(elferr)); elf_errmsg(elferr));
} }
static void
mark_section_group_symbols(struct elfcopy *ecp, size_t sc)
{
const char *name;
Elf_Scn *s;
GElf_Shdr sh;
size_t indx;
int elferr;
ecp->v_grp = calloc((sc + 7) / 8, 1);
if (ecp->v_grp == NULL)
err(EXIT_FAILURE, "calloc failed");
if (elf_getshstrndx(ecp->ein, &indx) == 0)
errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
elf_errmsg(-1));
s = NULL;
while ((s = elf_nextscn(ecp->ein, s)) != NULL) {
if (gelf_getshdr(s, &sh) != &sh)
errx(EXIT_FAILURE, "elf_getshdr failed: %s",
elf_errmsg(-1));
if (sh.sh_type != SHT_GROUP)
continue;
if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) == NULL)
errx(EXIT_FAILURE, "elf_strptr failed: %s",
elf_errmsg(-1));
if (is_remove_section(ecp, name))
continue;
if (sh.sh_info > 0 && sh.sh_info < sc)
BIT_SET(ecp->v_grp, sh.sh_info);
else if (sh.sh_info != 0)
warnx("invalid symbox index");
}
elferr = elf_errno();
if (elferr != 0)
errx(EXIT_FAILURE, "elf_nextscn failed: %s",
elf_errmsg(elferr));
}
static int static int
generate_symbols(struct elfcopy *ecp) generate_symbols(struct elfcopy *ecp)
{ {
@ -351,6 +402,8 @@ generate_symbols(struct elfcopy *ecp)
ecp->symtab->buf = sy_buf; ecp->symtab->buf = sy_buf;
ecp->strtab->buf = st_buf; ecp->strtab->buf = st_buf;
gsym = NULL;
/* /*
* Create bit vector v_secsym, which is used to mark sections * Create bit vector v_secsym, which is used to mark sections
* that already have corresponding STT_SECTION symbols. * that already have corresponding STT_SECTION symbols.
@ -384,7 +437,7 @@ generate_symbols(struct elfcopy *ecp)
/* Symbol table should exist if this function is called. */ /* Symbol table should exist if this function is called. */
if (symndx == 0) { if (symndx == 0) {
warnx("can't find .strtab section"); warnx("can't find .strtab section");
return (0); goto clean;
} }
/* Locate .symtab of input object. */ /* Locate .symtab of input object. */
@ -413,7 +466,6 @@ generate_symbols(struct elfcopy *ecp)
* output object, it is used by update_reloc() later to update * output object, it is used by update_reloc() later to update
* relocation information. * relocation information.
*/ */
gsym = NULL;
sc = ish.sh_size / ish.sh_entsize; sc = ish.sh_size / ish.sh_entsize;
if (sc > 0) { if (sc > 0) {
ecp->symndx = calloc(sc, sizeof(*ecp->symndx)); ecp->symndx = calloc(sc, sizeof(*ecp->symndx));
@ -427,7 +479,7 @@ generate_symbols(struct elfcopy *ecp)
if (elferr != 0) if (elferr != 0)
errx(EXIT_FAILURE, "elf_getdata failed: %s", errx(EXIT_FAILURE, "elf_getdata failed: %s",
elf_errmsg(elferr)); elf_errmsg(elferr));
return (0); goto clean;
} }
} else } else
return (0); return (0);
@ -523,7 +575,7 @@ generate_symbols(struct elfcopy *ecp)
* check if that only local symbol is the reserved symbol. * check if that only local symbol is the reserved symbol.
*/ */
if (sy_buf->nls <= 1 && sy_buf->ngs == 0) if (sy_buf->nls <= 1 && sy_buf->ngs == 0)
return (0); goto clean;
/* /*
* Create STT_SECTION symbols for sections that do not already * Create STT_SECTION symbols for sections that do not already
@ -550,6 +602,7 @@ generate_symbols(struct elfcopy *ecp)
sym.st_value = s->vma; sym.st_value = s->vma;
sym.st_size = 0; sym.st_size = 0;
sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION); sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION);
sym.st_other = STV_DEFAULT;
/* /*
* Don't let add_to_symtab() touch sym.st_shndx. * Don't let add_to_symtab() touch sym.st_shndx.
* In this case, we know the index already. * In this case, we know the index already.
@ -583,6 +636,12 @@ generate_symbols(struct elfcopy *ecp)
} }
return (1); return (1);
clean:
free(gsym);
free_symtab(ecp);
return (0);
} }
void void
@ -624,7 +683,9 @@ create_symtab(struct elfcopy *ecp)
if (((ecp->flags & SYMTAB_INTACT) == 0) && !generate_symbols(ecp)) { if (((ecp->flags & SYMTAB_INTACT) == 0) && !generate_symbols(ecp)) {
TAILQ_REMOVE(&ecp->v_sec, ecp->symtab, sec_list); TAILQ_REMOVE(&ecp->v_sec, ecp->symtab, sec_list);
TAILQ_REMOVE(&ecp->v_sec, ecp->strtab, sec_list); TAILQ_REMOVE(&ecp->v_sec, ecp->strtab, sec_list);
free(ecp->symtab->buf);
free(ecp->symtab); free(ecp->symtab);
free(ecp->strtab->buf);
free(ecp->strtab); free(ecp->strtab);
ecp->symtab = NULL; ecp->symtab = NULL;
ecp->strtab = NULL; ecp->strtab = NULL;
@ -697,6 +758,23 @@ free_symtab(struct elfcopy *ecp)
} }
} }
} }
if (ecp->symndx != NULL) {
free(ecp->symndx);
ecp->symndx = NULL;
}
if (ecp->v_rel != NULL) {
free(ecp->v_rel);
ecp->v_rel = NULL;
}
if (ecp->v_grp != NULL) {
free(ecp->v_grp);
ecp->v_grp = NULL;
}
if (ecp->v_secsym != NULL) {
free(ecp->v_secsym);
ecp->v_secsym = NULL;
}
} }
void void

View File

@ -26,7 +26,7 @@
#include "_libdwarf.h" #include "_libdwarf.h"
ELFTC_VCSID("$Id: libdwarf_reloc.c 3149 2015-02-15 19:00:06Z emaste $"); ELFTC_VCSID("$Id: libdwarf_reloc.c 3198 2015-05-14 18:36:19Z emaste $");
Dwarf_Unsigned Dwarf_Unsigned
_dwarf_get_reloc_type(Dwarf_P_Debug dbg, int is64) _dwarf_get_reloc_type(Dwarf_P_Debug dbg, int is64)
@ -75,6 +75,7 @@ _dwarf_get_reloc_size(Dwarf_Debug dbg, Dwarf_Unsigned rel_type)
return (4); return (4);
break; break;
case EM_386: case EM_386:
case EM_IAMCU:
if (rel_type == R_386_32) if (rel_type == R_386_32)
return (4); return (4);
break; break;

View File

@ -36,7 +36,7 @@
#include "_libelftc.h" #include "_libelftc.h"
ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3194 2015-05-05 17:55:16Z emaste $"); ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3212 2015-05-17 13:40:55Z kaiwang27 $");
/** /**
* @file cpp_demangle.c * @file cpp_demangle.c
@ -50,7 +50,7 @@ ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3194 2015-05-05 17:55:16Z emaste $");
enum type_qualifier { enum type_qualifier {
TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT, TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT,
TYPE_CST TYPE_CST, TYPE_VEC
}; };
struct vector_type_qualifier { struct vector_type_qualifier {
@ -84,6 +84,7 @@ struct cpp_demangle_data {
int func_type; int func_type;
const char *cur; /* current mangled name ptr */ const char *cur; /* current mangled name ptr */
const char *last_sname; /* last source name */ const char *last_sname; /* last source name */
int push_head;
}; };
#define CPP_DEMANGLE_TRY_LIMIT 128 #define CPP_DEMANGLE_TRY_LIMIT 128
@ -112,6 +113,8 @@ static int cpp_demangle_read_array(struct cpp_demangle_data *);
static int cpp_demangle_read_encoding(struct cpp_demangle_data *); static int cpp_demangle_read_encoding(struct cpp_demangle_data *);
static int cpp_demangle_read_expr_primary(struct cpp_demangle_data *); static int cpp_demangle_read_expr_primary(struct cpp_demangle_data *);
static int cpp_demangle_read_expression(struct cpp_demangle_data *); static int cpp_demangle_read_expression(struct cpp_demangle_data *);
static int cpp_demangle_read_expression_flat(struct cpp_demangle_data *,
char **);
static int cpp_demangle_read_expression_binary(struct cpp_demangle_data *, static int cpp_demangle_read_expression_binary(struct cpp_demangle_data *,
const char *, size_t); const char *, size_t);
static int cpp_demangle_read_expression_unary(struct cpp_demangle_data *, static int cpp_demangle_read_expression_unary(struct cpp_demangle_data *,
@ -123,8 +126,12 @@ static int cpp_demangle_read_function(struct cpp_demangle_data *, int *,
static int cpp_demangle_local_source_name(struct cpp_demangle_data *ddata); static int cpp_demangle_local_source_name(struct cpp_demangle_data *ddata);
static int cpp_demangle_read_local_name(struct cpp_demangle_data *); static int cpp_demangle_read_local_name(struct cpp_demangle_data *);
static int cpp_demangle_read_name(struct cpp_demangle_data *); static int cpp_demangle_read_name(struct cpp_demangle_data *);
static int cpp_demangle_read_name_flat(struct cpp_demangle_data *,
char**);
static int cpp_demangle_read_nested_name(struct cpp_demangle_data *); static int cpp_demangle_read_nested_name(struct cpp_demangle_data *);
static int cpp_demangle_read_number(struct cpp_demangle_data *, long *); static int cpp_demangle_read_number(struct cpp_demangle_data *, long *);
static int cpp_demangle_read_number_as_string(struct cpp_demangle_data *,
char **);
static int cpp_demangle_read_nv_offset(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(struct cpp_demangle_data *);
static int cpp_demangle_read_offset_number(struct cpp_demangle_data *); static int cpp_demangle_read_offset_number(struct cpp_demangle_data *);
@ -138,6 +145,8 @@ 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_args(struct cpp_demangle_data *);
static int cpp_demangle_read_tmpl_param(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 *, int);
static int cpp_demangle_read_type_flat(struct cpp_demangle_data *,
char **);
static int cpp_demangle_read_uqname(struct cpp_demangle_data *); static int cpp_demangle_read_uqname(struct cpp_demangle_data *);
static int cpp_demangle_read_v_offset(struct cpp_demangle_data *); static int cpp_demangle_read_v_offset(struct cpp_demangle_data *);
static char *decode_fp_to_double(const char *, size_t); static char *decode_fp_to_double(const char *, size_t);
@ -156,8 +165,6 @@ static int vector_type_qualifier_init(struct vector_type_qualifier *);
static int vector_type_qualifier_push(struct vector_type_qualifier *, static int vector_type_qualifier_push(struct vector_type_qualifier *,
enum type_qualifier); enum type_qualifier);
static int cpp_demangle_gnu3_push_head;
/** /**
* @brief Decode the input string by IA-64 C++ ABI style. * @brief Decode the input string by IA-64 C++ ABI style.
* *
@ -190,7 +197,6 @@ cpp_demangle_gnu3(const char *org)
if (!cpp_demangle_data_init(&ddata, org + 2)) if (!cpp_demangle_data_init(&ddata, org + 2))
return (NULL); return (NULL);
cpp_demangle_gnu3_push_head = 0;
rtn = NULL; rtn = NULL;
if (!cpp_demangle_read_encoding(&ddata)) if (!cpp_demangle_read_encoding(&ddata))
@ -277,6 +283,7 @@ cpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur)
d->func_type = 0; d->func_type = 0;
d->cur = cur; d->cur = cur;
d->last_sname = NULL; d->last_sname = NULL;
d->push_head = 0;
return (1); return (1);
@ -309,7 +316,6 @@ cpp_demangle_push_fp(struct cpp_demangle_data *ddata,
fp = ddata->cur; fp = ddata->cur;
while (*ddata->cur != 'E') while (*ddata->cur != 'E')
++ddata->cur; ++ddata->cur;
++ddata->cur;
if ((f = decoder(fp, ddata->cur - fp)) == NULL) if ((f = decoder(fp, ddata->cur - fp)) == NULL)
return (0); return (0);
@ -320,6 +326,8 @@ cpp_demangle_push_fp(struct cpp_demangle_data *ddata,
free(f); free(f);
++ddata->cur;
return (rtn); return (rtn);
} }
@ -331,7 +339,7 @@ cpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str,
if (ddata == NULL || str == NULL || len == 0) if (ddata == NULL || str == NULL || len == 0)
return (0); return (0);
if (cpp_demangle_gnu3_push_head > 0) if (ddata->push_head > 0)
return (vector_str_push(&ddata->output_tmp, str, len)); return (vector_str_push(&ddata->output_tmp, str, len));
return (vector_str_push(&ddata->output, str, len)); return (vector_str_push(&ddata->output, str, len));
@ -403,7 +411,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (type_str != NULL) { if (type_str != NULL) {
if (!vector_str_push(&subst_v, "*", 1)) if (!vector_str_push(&subst_v, "*", 1))
goto clean; goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v)) if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean; goto clean;
} }
break; break;
@ -414,7 +423,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (type_str != NULL) { if (type_str != NULL) {
if (!vector_str_push(&subst_v, "&", 1)) if (!vector_str_push(&subst_v, "&", 1))
goto clean; goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v)) if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean; goto clean;
} }
break; break;
@ -425,7 +435,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (type_str != NULL) { if (type_str != NULL) {
if (!vector_str_push(&subst_v, " complex", 8)) if (!vector_str_push(&subst_v, " complex", 8))
goto clean; goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v)) if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean; goto clean;
} }
break; break;
@ -434,23 +445,26 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (!cpp_demangle_push_str(ddata, " imaginary", 10)) if (!cpp_demangle_push_str(ddata, " imaginary", 10))
goto clean; goto clean;
if (type_str != NULL) { if (type_str != NULL) {
if (!vector_str_push(&subst_v, " imaginary", 10)) if (!vector_str_push(&subst_v, " imaginary",
10))
goto clean; goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v)) if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean; goto clean;
} }
break; break;
case TYPE_EXT: case TYPE_EXT:
if (e_idx > v->ext_name.size - 1) if (v->ext_name.size == 0 ||
e_idx > v->ext_name.size - 1)
goto clean; goto clean;
if ((e_len = strlen(v->ext_name.container[e_idx])) == 0) if ((e_len = strlen(v->ext_name.container[e_idx])) ==
0)
goto clean; goto clean;
if ((buf = malloc(sizeof(char) * (e_len + 1))) == NULL) if ((buf = malloc(e_len + 2)) == NULL)
goto clean; goto clean;
snprintf(buf, e_len + 2, " %s",
memcpy(buf, " ", 1); v->ext_name.container[e_idx]);
memcpy(buf + 1, v->ext_name.container[e_idx], e_len);
if (!cpp_demangle_push_str(ddata, buf, e_len + 1)) { if (!cpp_demangle_push_str(ddata, buf, e_len + 1)) {
free(buf); free(buf);
@ -463,7 +477,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
free(buf); free(buf);
goto clean; goto clean;
} }
if (!cpp_demangle_push_subst_v(ddata, &subst_v)) { if (!cpp_demangle_push_subst_v(ddata,
&subst_v)) {
free(buf); free(buf);
goto clean; goto clean;
} }
@ -478,7 +493,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (type_str != NULL) { if (type_str != NULL) {
if (!vector_str_push(&subst_v, " restrict", 9)) if (!vector_str_push(&subst_v, " restrict", 9))
goto clean; goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v)) if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean; goto clean;
} }
break; break;
@ -489,7 +505,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (type_str != NULL) { if (type_str != NULL) {
if (!vector_str_push(&subst_v, " volatile", 9)) if (!vector_str_push(&subst_v, " volatile", 9))
goto clean; goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v)) if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean; goto clean;
} }
break; break;
@ -500,11 +517,42 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (type_str != NULL) { if (type_str != NULL) {
if (!vector_str_push(&subst_v, " const", 6)) if (!vector_str_push(&subst_v, " const", 6))
goto clean; goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v)) if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean; goto clean;
} }
break; break;
case TYPE_VEC:
if (v->ext_name.size == 0 ||
e_idx > v->ext_name.size - 1)
goto clean;
if ((e_len = strlen(v->ext_name.container[e_idx])) ==
0)
goto clean;
if ((buf = malloc(e_len + 12)) == NULL)
goto clean;
snprintf(buf, e_len + 12, " __vector(%s)",
v->ext_name.container[e_idx]);
if (!cpp_demangle_push_str(ddata, buf, e_len + 11)) {
free(buf);
goto clean;
}
if (type_str != NULL) {
if (!vector_str_push(&subst_v, buf,
e_len + 11)) {
free(buf);
goto clean;
}
if (!cpp_demangle_push_subst_v(ddata,
&subst_v)) {
free(buf);
goto clean;
}
}
free(buf);
++e_idx;
break;
}; };
--idx; --idx;
} }
@ -655,10 +703,14 @@ cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
switch (*ddata->cur) { switch (*ddata->cur) {
case 'b': case 'b':
if (*(ddata->cur + 2) != 'E')
return (0);
switch (*(++ddata->cur)) { switch (*(++ddata->cur)) {
case '0': case '0':
ddata->cur += 2;
return (cpp_demangle_push_str(ddata, "false", 5)); return (cpp_demangle_push_str(ddata, "false", 5));
case '1': case '1':
ddata->cur += 2;
return (cpp_demangle_push_str(ddata, "true", 4)); return (cpp_demangle_push_str(ddata, "true", 4));
default: default:
return (0); return (0);
@ -707,7 +759,8 @@ cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
++ddata->cur; ++ddata->cur;
} }
++ddata->cur; ++ddata->cur;
return (cpp_demangle_push_str(ddata, num, ddata->cur - num)); return (cpp_demangle_push_str(ddata, num,
ddata->cur - num - 1));
default: default:
return (0); return (0);
@ -998,6 +1051,38 @@ cpp_demangle_read_expression(struct cpp_demangle_data *ddata)
return (0); return (0);
} }
static int
cpp_demangle_read_expression_flat(struct cpp_demangle_data *ddata, char **str)
{
struct vector_str *output;
size_t i, p_idx, idx, exp_len;
char *exp;
output = ddata->push_head > 0 ? &ddata->output_tmp :
&ddata->output;
p_idx = output->size;
if (!cpp_demangle_read_expression(ddata))
return (0);
if ((exp = vector_str_substr(output, p_idx, output->size - 1,
&exp_len)) == NULL)
return (0);
idx = output->size;
for (i = p_idx; i < idx; ++i) {
if (!vector_str_pop(output)) {
free(exp);
return (0);
}
}
*str = exp;
return (1);
}
static int static int
cpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata, cpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata,
const char *name, size_t len) const char *name, size_t len)
@ -1127,12 +1212,65 @@ cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c,
static int static int
cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
{ {
char *name, *type, *num_str;
long offset;
int rtn;
if (ddata == NULL || *ddata->cur == '\0') if (ddata == NULL || *ddata->cur == '\0')
return (0); return (0);
/* special name */ /* special name */
switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
case SIMPLE_HASH('G', 'A'):
if (!cpp_demangle_push_str(ddata, "hidden alias for ", 17))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_encoding(ddata));
case SIMPLE_HASH('G', 'R'):
if (!cpp_demangle_push_str(ddata, "reference temporary #", 21))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
if (!cpp_demangle_read_name_flat(ddata, &name))
return (0);
rtn = 0;
if (!cpp_demangle_read_number_as_string(ddata, &num_str))
goto clean1;
if (!cpp_demangle_push_str(ddata, num_str, strlen(num_str)))
goto clean2;
if (!cpp_demangle_push_str(ddata, " for ", 5))
goto clean2;
if (!cpp_demangle_push_str(ddata, name, strlen(name)))
goto clean2;
rtn = 1;
clean2:
free(num_str);
clean1:
free(name);
return (rtn);
case SIMPLE_HASH('G', 'T'):
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
switch (*ddata->cur) {
case 'n':
if (!cpp_demangle_push_str(ddata,
"non-transaction clone for ", 26))
return (0);
case 't':
default:
if (!cpp_demangle_push_str(ddata,
"transaction clone for ", 22))
return (0);
}
++ddata->cur;
return (cpp_demangle_read_encoding(ddata));
case SIMPLE_HASH('G', 'V'): case SIMPLE_HASH('G', 'V'):
/* sentry object for 1 time init */ /* sentry object for 1 time init */
if (!cpp_demangle_push_str(ddata, "guard variable for ", 20)) if (!cpp_demangle_push_str(ddata, "guard variable for ", 20))
@ -1154,14 +1292,49 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
return (0); return (0);
return (cpp_demangle_read_encoding(ddata)); return (cpp_demangle_read_encoding(ddata));
case SIMPLE_HASH('T', 'C'):
/* construction vtable */
if (!cpp_demangle_push_str(ddata, "construction vtable for ",
24))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
if (!cpp_demangle_read_type_flat(ddata, &type))
return (0);
rtn = 0;
if (!cpp_demangle_read_number(ddata, &offset))
goto clean3;
if (*ddata->cur++ != '_')
goto clean3;
if (!cpp_demangle_read_type(ddata, 0))
goto clean3;
if (!cpp_demangle_push_str(ddata, "-in-", 4))
goto clean3;
if (!cpp_demangle_push_str(ddata, type, strlen(type)))
goto clean3;
rtn = 1;
clean3:
free(type);
return (rtn);
case SIMPLE_HASH('T', 'D'): case SIMPLE_HASH('T', 'D'):
/* typeinfo common proxy */ /* typeinfo common proxy */
break; break;
case SIMPLE_HASH('T', 'F'):
/* typeinfo fn */
if (!cpp_demangle_push_str(ddata, "typeinfo fn for ", 16))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_type(ddata, 0));
case SIMPLE_HASH('T', 'h'): case SIMPLE_HASH('T', 'h'):
/* virtual function non-virtual override thunk */ /* virtual function non-virtual override thunk */
if (cpp_demangle_push_str(ddata, if (!cpp_demangle_push_str(ddata,
"virtual function non-virtual override ", 38) == 0) "virtual function non-virtual override ", 38))
return (0); return (0);
ddata->cur += 2; ddata->cur += 2;
if (*ddata->cur == '\0') if (*ddata->cur == '\0')
@ -1170,24 +1343,51 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
return (0); return (0);
return (cpp_demangle_read_encoding(ddata)); return (cpp_demangle_read_encoding(ddata));
case SIMPLE_HASH('T', 'I'): case SIMPLE_HASH('T', 'H'):
/* typeinfo structure */ /* TLS init function */
/* FALLTHROUGH */ if (!cpp_demangle_push_str(ddata, "TLS init function for ",
case SIMPLE_HASH('T', 'S'): 22))
/* RTTI name (NTBS) */
if (!cpp_demangle_push_str(ddata, "typeinfo for ", 14))
return (0); return (0);
ddata->cur += 2; ddata->cur += 2;
if (*ddata->cur == '\0') if (*ddata->cur == '\0')
return (0); return (0);
return (cpp_demangle_read_type(ddata, 1)); break;
case SIMPLE_HASH('T', 'I'):
/* typeinfo structure */
if (!cpp_demangle_push_str(ddata, "typeinfo for ", 13))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_type(ddata, 0));
case SIMPLE_HASH('T', 'J'):
/* java class */
if (!cpp_demangle_push_str(ddata, "java Class for ", 15))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_type(ddata, 0));
case SIMPLE_HASH('T', 'S'):
/* RTTI name (NTBS) */
if (!cpp_demangle_push_str(ddata, "typeinfo name for ", 18))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_type(ddata, 0));
case SIMPLE_HASH('T', 'T'): case SIMPLE_HASH('T', 'T'):
/* VTT table */ /* VTT table */
if (!cpp_demangle_push_str(ddata, "VTT for ", 8)) if (!cpp_demangle_push_str(ddata, "VTT for ", 8))
return (0); return (0);
ddata->cur += 2; ddata->cur += 2;
return (cpp_demangle_read_type(ddata, 1)); if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_type(ddata, 0));
case SIMPLE_HASH('T', 'v'): case SIMPLE_HASH('T', 'v'):
/* virtual function virtual override thunk */ /* virtual function virtual override thunk */
@ -1208,7 +1408,17 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
ddata->cur += 2; ddata->cur += 2;
if (*ddata->cur == '\0') if (*ddata->cur == '\0')
return (0); return (0);
return (cpp_demangle_read_type(ddata, 1)); return (cpp_demangle_read_type(ddata, 0));
case SIMPLE_HASH('T', 'W'):
/* TLS wrapper function */
if (!cpp_demangle_push_str(ddata, "TLS wrapper function for ",
25))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
break;
}; };
return (cpp_demangle_read_name(ddata)); return (cpp_demangle_read_name(ddata));
@ -1270,8 +1480,7 @@ cpp_demangle_read_name(struct cpp_demangle_data *ddata)
if (ddata == NULL || *ddata->cur == '\0') if (ddata == NULL || *ddata->cur == '\0')
return (0); return (0);
output = cpp_demangle_gnu3_push_head > 0 ? output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
&ddata->output_tmp : &ddata->output;
subst_str = NULL; subst_str = NULL;
@ -1326,6 +1535,38 @@ clean:
return (rtn); return (rtn);
} }
static int
cpp_demangle_read_name_flat(struct cpp_demangle_data *ddata, char **str)
{
struct vector_str *output;
size_t i, p_idx, idx, name_len;
char *name;
output = ddata->push_head > 0 ? &ddata->output_tmp :
&ddata->output;
p_idx = output->size;
if (!cpp_demangle_read_name(ddata))
return (0);
if ((name = vector_str_substr(output, p_idx, output->size - 1,
&name_len)) == NULL)
return (0);
idx = output->size;
for (i = p_idx; i < idx; ++i) {
if (!vector_str_pop(output)) {
free(name);
return (0);
}
}
*str = name;
return (1);
}
static int static int
cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata) cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
{ {
@ -1355,8 +1596,7 @@ cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
++ddata->cur; ++ddata->cur;
} }
output = cpp_demangle_gnu3_push_head > 0 ? output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
&ddata->output_tmp : &ddata->output;
if (!vector_str_init(&v)) if (!vector_str_init(&v))
return (0); return (0);
@ -1452,6 +1692,24 @@ cpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn)
return (1); return (1);
} }
static int
cpp_demangle_read_number_as_string(struct cpp_demangle_data *ddata, char **str)
{
long n;
if (!cpp_demangle_read_number(ddata, &n)) {
*str = NULL;
return (0);
}
if (asprintf(str, "%ld", n) < 0) {
*str = NULL;
return (0);
}
return (1);
}
static int static int
cpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata) cpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata)
{ {
@ -1581,9 +1839,18 @@ static int
cpp_demangle_read_sname(struct cpp_demangle_data *ddata) cpp_demangle_read_sname(struct cpp_demangle_data *ddata)
{ {
long len; long len;
int err;
if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 || if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 ||
len <= 0 || cpp_demangle_push_str(ddata, ddata->cur, len) == 0) len <= 0)
return (0);
if (len == 12 && (memcmp("_GLOBAL__N_1", ddata->cur, 12) == 0))
err = cpp_demangle_push_str(ddata, "(anonymous namespace)", 21);
else
err = cpp_demangle_push_str(ddata, ddata->cur, len);
if (err == 0)
return (0); return (0);
assert(ddata->output.size > 0); assert(ddata->output.size > 0);
@ -1732,8 +1999,7 @@ cpp_demangle_read_subst_std(struct cpp_demangle_data *ddata)
ddata->cur += 2; ddata->cur += 2;
output = cpp_demangle_gnu3_push_head > 0 ? output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
&ddata->output_tmp : &ddata->output;
p_idx = output->size; p_idx = output->size;
if (!cpp_demangle_read_uqname(ddata)) if (!cpp_demangle_read_uqname(ddata))
@ -1783,8 +2049,7 @@ cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata,
if (ddata == NULL || str == NULL || len == 0) if (ddata == NULL || str == NULL || len == 0)
return (0); return (0);
output = cpp_demangle_gnu3_push_head > 0 ? &ddata->output_tmp : output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
&ddata->output;
p_idx = output->size; p_idx = output->size;
substr = NULL; substr = NULL;
@ -1852,8 +2117,7 @@ cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
return (0); return (0);
limit = 0; limit = 0;
v = cpp_demangle_gnu3_push_head > 0 ? v = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
&ddata->output_tmp : &ddata->output;
for (;;) { for (;;) {
idx = v->size; idx = v->size;
if (!cpp_demangle_read_tmpl_arg(ddata)) if (!cpp_demangle_read_tmpl_arg(ddata))
@ -1936,14 +2200,14 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
size_t p_idx, type_str_len; size_t p_idx, type_str_len;
int extern_c, is_builtin; int extern_c, is_builtin;
long len; long len;
char *type_str; char *type_str, *exp_str, *num_str;
if (ddata == NULL) if (ddata == NULL)
return (0); return (0);
output = &ddata->output; output = &ddata->output;
if (!strncmp(ddata->output.container[ddata->output.size - 1], ">", 1)) { if (!strncmp(ddata->output.container[ddata->output.size - 1], ">", 1)) {
cpp_demangle_gnu3_push_head++; ddata->push_head++;
output = &ddata->output_tmp; output = &ddata->output_tmp;
} else if (delimit == 1) { } else if (delimit == 1) {
if (ddata->paren == false) { if (ddata->paren == false) {
@ -1978,7 +2242,7 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
extern_c = 0; extern_c = 0;
is_builtin = 1; is_builtin = 1;
p_idx = output->size; p_idx = output->size;
type_str = NULL; type_str = exp_str = num_str = NULL;
again: again:
/* builtin type */ /* builtin type */
switch (*ddata->cur) { switch (*ddata->cur) {
@ -2024,6 +2288,82 @@ again:
++ddata->cur; ++ddata->cur;
goto rtn; goto rtn;
case 'D':
++ddata->cur;
switch (*ddata->cur) {
case 'd':
/* IEEE 754r decimal floating point (64 bits) */
if (!cpp_demangle_push_str(ddata, "decimal64", 9))
goto clean;
++ddata->cur;
break;
case 'e':
/* IEEE 754r decimal floating point (128 bits) */
if (!cpp_demangle_push_str(ddata, "decimal128", 10))
goto clean;
++ddata->cur;
break;
case 'f':
/* IEEE 754r decimal floating point (32 bits) */
if (!cpp_demangle_push_str(ddata, "decimal32", 9))
goto clean;
++ddata->cur;
break;
case 'h':
/* IEEE 754r half-precision floating point (16 bits) */
if (!cpp_demangle_push_str(ddata, "half", 4))
goto clean;
++ddata->cur;
break;
case 'i':
/* char32_t */
if (!cpp_demangle_push_str(ddata, "char32_t", 8))
goto clean;
++ddata->cur;
break;
case 'n':
/* std::nullptr_t (i.e., decltype(nullptr)) */
if (!cpp_demangle_push_str(ddata, "decltype(nullptr)",
17))
goto clean;
++ddata->cur;
break;
case 's':
/* char16_t */
if (!cpp_demangle_push_str(ddata, "char16_t", 8))
goto clean;
++ddata->cur;
break;
case 'v':
/* gcc vector_size extension. */
++ddata->cur;
if (*ddata->cur == '_') {
++ddata->cur;
if (!cpp_demangle_read_expression_flat(ddata,
&exp_str))
goto clean;
if (!vector_str_push(&v.ext_name, exp_str,
strlen(exp_str)))
goto clean;
} else {
if (!cpp_demangle_read_number_as_string(ddata,
&num_str))
goto clean;
if (!vector_str_push(&v.ext_name, num_str,
strlen(num_str)))
goto clean;
}
if (*ddata->cur != '_')
goto clean;
++ddata->cur;
if (!vector_type_qualifier_push(&v, TYPE_VEC))
goto clean;
goto again;
default:
goto clean;
}
goto rtn;
case 'e': case 'e':
/* long double */ /* long double */
if (!cpp_demangle_push_str(ddata, "long double", 11)) if (!cpp_demangle_push_str(ddata, "long double", 11))
@ -2118,7 +2458,7 @@ again:
case 'o': case 'o':
/* unsigned __int128 */ /* unsigned __int128 */
if (!cpp_demangle_push_str(ddata, "unsigned _;int128", 17)) if (!cpp_demangle_push_str(ddata, "unsigned __int128", 17))
goto clean; goto clean;
++ddata->cur; ++ddata->cur;
goto rtn; goto rtn;
@ -2189,6 +2529,8 @@ again:
if (!vector_str_push(&v.ext_name, ddata->cur, len)) if (!vector_str_push(&v.ext_name, ddata->cur, len))
return (0); return (0);
ddata->cur += len; ddata->cur += len;
if (!vector_type_qualifier_push(&v, TYPE_EXT))
goto clean;
goto again; goto again;
case 'v': case 'v':
@ -2253,14 +2595,16 @@ rtn:
goto clean; goto clean;
free(type_str); free(type_str);
free(exp_str);
free(num_str);
vector_type_qualifier_dest(&v); vector_type_qualifier_dest(&v);
if (cpp_demangle_gnu3_push_head > 0) { if (ddata->push_head > 0) {
if (*ddata->cur == 'I' && cpp_demangle_read_tmpl_args(ddata) if (*ddata->cur == 'I' && cpp_demangle_read_tmpl_args(ddata)
== 0) == 0)
return (0); return (0);
if (--cpp_demangle_gnu3_push_head > 0) if (--ddata->push_head > 0)
return (1); return (1);
if (!vector_str_push(&ddata->output_tmp, " ", 1)) if (!vector_str_push(&ddata->output_tmp, " ", 1))
@ -2284,11 +2628,45 @@ rtn:
return (1); return (1);
clean: clean:
free(type_str); free(type_str);
free(exp_str);
free(num_str);
vector_type_qualifier_dest(&v); vector_type_qualifier_dest(&v);
return (0); return (0);
} }
static int
cpp_demangle_read_type_flat(struct cpp_demangle_data *ddata, char **str)
{
struct vector_str *output;
size_t i, p_idx, idx, type_len;
char *type;
output = ddata->push_head > 0 ? &ddata->output_tmp :
&ddata->output;
p_idx = output->size;
if (!cpp_demangle_read_type(ddata, 0))
return (0);
if ((type = vector_str_substr(output, p_idx, output->size - 1,
&type_len)) == NULL)
return (0);
idx = output->size;
for (i = p_idx; i < idx; ++i) {
if (!vector_str_pop(output)) {
free(type);
return (0);
}
}
*str = type;
return (1);
}
/* /*
* read unqualified-name, unqualified name are operator-name, ctor-dtor-name, * read unqualified-name, unqualified name are operator-name, ctor-dtor-name,
* source-name * source-name

View File

@ -1,3 +1,3 @@
# $Id: os.Linux.mk 994 2010-06-13 10:39:19Z jkoshy $ # $Id: os.Linux.mk 3210 2015-05-17 13:40:49Z kaiwang27 $
CFLAGS+= -Wall CFLAGS+= -Wall -D_GNU_SOURCE

View File

@ -22,7 +22,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $Id: readelf.1 3195 2015-05-12 17:22:19Z emaste $ .\" $Id: readelf.1 3219 2015-05-24 23:42:34Z kaiwang27 $
.\" .\"
.Dd September 13, 2012 .Dd September 13, 2012
.Os .Os
@ -90,7 +90,7 @@ sections in the ELF object.
.It Fl e | Fl -headers .It Fl e | Fl -headers
Print all program, file and section headers in the ELF object. Print all program, file and section headers in the ELF object.
.It Fl g | Fl -section-groups .It Fl g | Fl -section-groups
This option is recognized, but is ignored. Print the contents of the section groups in the ELF object.
.It Fl h | Fl -file-header .It Fl h | Fl -file-header
Print the file header of the ELF object. Print the file header of the ELF object.
.It Fl l | Fl -program-headers .It Fl l | Fl -program-headers

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2009-2014 Kai Wang * Copyright (c) 2009-2015 Kai Wang
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -46,7 +46,7 @@
#include "_elftc.h" #include "_elftc.h"
ELFTC_VCSID("$Id: readelf.c 3189 2015-04-20 17:02:01Z emaste $"); ELFTC_VCSID("$Id: readelf.c 3223 2015-05-25 20:37:57Z emaste $");
/* /*
* readelf(1) options. * readelf(1) options.
@ -302,6 +302,7 @@ static void dump_gnu_hash(struct readelf *re, struct section *s);
static void dump_hash(struct readelf *re); static void dump_hash(struct readelf *re);
static void dump_phdr(struct readelf *re); static void dump_phdr(struct readelf *re);
static void dump_ppc_attributes(uint8_t *p, uint8_t *pe); static void dump_ppc_attributes(uint8_t *p, uint8_t *pe);
static void dump_section_groups(struct readelf *re);
static void dump_symtab(struct readelf *re, int i); static void dump_symtab(struct readelf *re, int i);
static void dump_symtabs(struct readelf *re); static void dump_symtabs(struct readelf *re);
static uint8_t *dump_unknown_tag(uint64_t tag, uint8_t *p); static uint8_t *dump_unknown_tag(uint64_t tag, uint8_t *p);
@ -445,6 +446,7 @@ elf_machine(unsigned int mach)
case EM_SPARC: return "Sun SPARC"; case EM_SPARC: return "Sun SPARC";
case EM_386: return "Intel i386"; case EM_386: return "Intel i386";
case EM_68K: return "Motorola 68000"; case EM_68K: return "Motorola 68000";
case EM_IAMCU: return "Intel MCU";
case EM_88K: return "Motorola 88000"; case EM_88K: return "Motorola 88000";
case EM_860: return "Intel i860"; case EM_860: return "Intel i860";
case EM_MIPS: return "MIPS R3000 Big-Endian only"; case EM_MIPS: return "MIPS R3000 Big-Endian only";
@ -1050,6 +1052,7 @@ r_type(unsigned int mach, unsigned int type)
switch(mach) { switch(mach) {
case EM_NONE: return ""; case EM_NONE: return "";
case EM_386: case EM_386:
case EM_IAMCU:
switch(type) { switch(type) {
case 0: return "R_386_NONE"; case 0: return "R_386_NONE";
case 1: return "R_386_32"; case 1: return "R_386_32";
@ -2381,6 +2384,7 @@ dwarf_reg(unsigned int mach, unsigned int reg)
switch (mach) { switch (mach) {
case EM_386: case EM_386:
case EM_IAMCU:
switch (reg) { switch (reg) {
case 0: return "eax"; case 0: return "eax";
case 1: return "ecx"; case 1: return "ecx";
@ -4047,6 +4051,61 @@ dump_liblist(struct readelf *re)
#undef Elf_Lib #undef Elf_Lib
static void
dump_section_groups(struct readelf *re)
{
struct section *s;
const char *symname;
Elf_Data *d;
uint32_t *w;
int i, j, elferr;
size_t n;
for (i = 0; (size_t) i < re->shnum; i++) {
s = &re->sl[i];
if (s->type != SHT_GROUP)
continue;
(void) elf_errno();
if ((d = elf_getdata(s->scn, NULL)) == NULL) {
elferr = elf_errno();
if (elferr != 0)
warnx("elf_getdata failed: %s",
elf_errmsg(elferr));
continue;
}
if (d->d_size <= 0)
continue;
w = d->d_buf;
/* We only support COMDAT section. */
#ifndef GRP_COMDAT
#define GRP_COMDAT 0x1
#endif
if ((*w++ & GRP_COMDAT) == 0)
return;
if (s->entsize == 0)
s->entsize = 4;
symname = get_symbol_name(re, s->link, s->info);
n = s->sz / s->entsize;
if (n-- < 1)
return;
printf("\nCOMDAT group section [%5d] `%s' [%s] contains %ju"
" sections:\n", i, s->name, symname, (uintmax_t)n);
printf(" %-10.10s %s\n", "[Index]", "Name");
for (j = 0; (size_t) j < n; j++, w++) {
if (*w >= re->shnum) {
warnx("invalid section index: %u", *w);
continue;
}
printf(" [%5u] %s\n", *w, re->sl[*w].name);
}
}
}
static uint8_t * static uint8_t *
dump_unknown_tag(uint64_t tag, uint8_t *p) dump_unknown_tag(uint64_t tag, uint8_t *p)
{ {
@ -6838,6 +6897,8 @@ dump_elf(struct readelf *re)
dump_phdr(re); dump_phdr(re);
if (re->options & RE_SS) if (re->options & RE_SS)
dump_shdr(re); dump_shdr(re);
if (re->options & RE_G)
dump_section_groups(re);
if (re->options & RE_D) if (re->options & RE_D)
dump_dynamic(re); dump_dynamic(re);
if (re->options & RE_R) if (re->options & RE_R)
@ -7311,7 +7372,7 @@ Usage: %s [options] file...\n\
-c | --archive-index Print the archive symbol table for archives.\n\ -c | --archive-index Print the archive symbol table for archives.\n\
-d | --dynamic Print the contents of SHT_DYNAMIC sections.\n\ -d | --dynamic Print the contents of SHT_DYNAMIC sections.\n\
-e | --headers Print all headers in the object.\n\ -e | --headers Print all headers in the object.\n\
-g | --section-groups (accepted, but ignored)\n\ -g | --section-groups Print the contents of the section groups.\n\
-h | --file-header Print the file header for the object.\n\ -h | --file-header Print the file header for the object.\n\
-l | --program-headers Print the PHDR table for the object.\n\ -l | --program-headers Print the PHDR table for the object.\n\
-n | --notes Print the contents of SHT_NOTE sections.\n\ -n | --notes Print the contents of SHT_NOTE sections.\n\
@ -7365,8 +7426,8 @@ main(int argc, char **argv)
re->options |= RE_AA; re->options |= RE_AA;
break; break;
case 'a': case 'a':
re->options |= RE_AA | RE_D | RE_H | RE_II | RE_L | re->options |= RE_AA | RE_D | RE_G | RE_H | RE_II |
RE_R | RE_SS | RE_S | RE_VV; RE_L | RE_R | RE_SS | RE_S | RE_VV;
break; break;
case 'c': case 'c':
re->options |= RE_C; re->options |= RE_C;

View File

@ -6,5 +6,5 @@
const char * const char *
elftc_version(void) elftc_version(void)
{ {
return "elftoolchain r3197M"; return "elftoolchain r3223M";
} }