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:
parent
abf78a3a27
commit
aa01a21e0c
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* 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__)
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
/*
|
||||
* GLIBC based systems have a global 'char *' pointer referencing
|
||||
* the executable's name.
|
||||
*/
|
||||
extern const char *program_invocation_short_name;
|
||||
#endif /* !_GNU_SOURCE */
|
||||
|
||||
#define ELFTC_GETPROGNAME() program_invocation_short_name
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* 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_68K, 4, "Motorola 68000") \
|
||||
_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_MIPS, 8, "MIPS I Architecture") \
|
||||
_ELF_DEFINE_EM(EM_S370, 9, "IBM System/370 Processor") \
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* 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>
|
||||
@ -237,6 +237,7 @@ struct elfcopy {
|
||||
uint64_t *secndx; /* section index map. */
|
||||
uint64_t *symndx; /* symbol index map. */
|
||||
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. */
|
||||
STAILQ_HEAD(, segment) v_seg; /* list of segments. */
|
||||
STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
#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
|
||||
{
|
||||
@ -404,8 +404,19 @@ create_elf(struct elfcopy *ecp)
|
||||
* Insert SHDR table into the internal section list as a "pseudo"
|
||||
* section, so later it will get sorted and resynced just as "normal"
|
||||
* 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.
|
||||
*/
|
||||
shtab = insert_shtab(ecp, 0);
|
||||
if (oeh.e_ident[EI_OSABI] == ELFOSABI_FREEBSD)
|
||||
shtab = insert_shtab(ecp, 1);
|
||||
else
|
||||
shtab = insert_shtab(ecp, 0);
|
||||
|
||||
/*
|
||||
* Resync section offsets in the output object. This is needed
|
||||
@ -485,6 +496,11 @@ free_elf(struct elfcopy *ecp)
|
||||
free(sec);
|
||||
}
|
||||
}
|
||||
|
||||
if (ecp->secndx != NULL) {
|
||||
free(ecp->secndx);
|
||||
ecp->secndx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a temporary file. */
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#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 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 *read_section(struct section *s, size_t *size);
|
||||
static void update_reloc(struct elfcopy *ecp, struct section *s);
|
||||
static void update_section_group(struct elfcopy *ecp, struct section *s);
|
||||
|
||||
int
|
||||
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))
|
||||
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))
|
||||
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
|
||||
* 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;
|
||||
if (sec_flags & SF_CODE)
|
||||
osh.sh_flags |= SHF_EXECINSTR;
|
||||
} else
|
||||
} else {
|
||||
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)
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#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. */
|
||||
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,
|
||||
const char *s);
|
||||
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);
|
||||
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))
|
||||
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
|
||||
* are needed.
|
||||
@ -207,7 +212,10 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
|
||||
return (1);
|
||||
|
||||
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))
|
||||
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.
|
||||
*/
|
||||
static void
|
||||
mark_symbols(struct elfcopy *ecp, size_t sc)
|
||||
mark_reloc_symbols(struct elfcopy *ecp, size_t sc)
|
||||
{
|
||||
const char *name;
|
||||
Elf_Data *d;
|
||||
@ -311,6 +319,49 @@ mark_symbols(struct elfcopy *ecp, size_t sc)
|
||||
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
|
||||
generate_symbols(struct elfcopy *ecp)
|
||||
{
|
||||
@ -351,6 +402,8 @@ generate_symbols(struct elfcopy *ecp)
|
||||
ecp->symtab->buf = sy_buf;
|
||||
ecp->strtab->buf = st_buf;
|
||||
|
||||
gsym = NULL;
|
||||
|
||||
/*
|
||||
* Create bit vector v_secsym, which is used to mark sections
|
||||
* 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. */
|
||||
if (symndx == 0) {
|
||||
warnx("can't find .strtab section");
|
||||
return (0);
|
||||
goto clean;
|
||||
}
|
||||
|
||||
/* 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
|
||||
* relocation information.
|
||||
*/
|
||||
gsym = NULL;
|
||||
sc = ish.sh_size / ish.sh_entsize;
|
||||
if (sc > 0) {
|
||||
ecp->symndx = calloc(sc, sizeof(*ecp->symndx));
|
||||
@ -427,7 +479,7 @@ generate_symbols(struct elfcopy *ecp)
|
||||
if (elferr != 0)
|
||||
errx(EXIT_FAILURE, "elf_getdata failed: %s",
|
||||
elf_errmsg(elferr));
|
||||
return (0);
|
||||
goto clean;
|
||||
}
|
||||
} else
|
||||
return (0);
|
||||
@ -523,7 +575,7 @@ generate_symbols(struct elfcopy *ecp)
|
||||
* check if that only local symbol is the reserved symbol.
|
||||
*/
|
||||
if (sy_buf->nls <= 1 && sy_buf->ngs == 0)
|
||||
return (0);
|
||||
goto clean;
|
||||
|
||||
/*
|
||||
* 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_size = 0;
|
||||
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.
|
||||
* In this case, we know the index already.
|
||||
@ -583,6 +636,12 @@ generate_symbols(struct elfcopy *ecp)
|
||||
}
|
||||
|
||||
return (1);
|
||||
|
||||
clean:
|
||||
free(gsym);
|
||||
free_symtab(ecp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -624,7 +683,9 @@ create_symtab(struct elfcopy *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->strtab, sec_list);
|
||||
free(ecp->symtab->buf);
|
||||
free(ecp->symtab);
|
||||
free(ecp->strtab->buf);
|
||||
free(ecp->strtab);
|
||||
ecp->symtab = 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
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#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_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);
|
||||
break;
|
||||
case EM_386:
|
||||
case EM_IAMCU:
|
||||
if (rel_type == R_386_32)
|
||||
return (4);
|
||||
break;
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
#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
|
||||
@ -50,7 +50,7 @@ ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3194 2015-05-05 17:55:16Z emaste $");
|
||||
|
||||
enum type_qualifier {
|
||||
TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT,
|
||||
TYPE_CST
|
||||
TYPE_CST, TYPE_VEC
|
||||
};
|
||||
|
||||
struct vector_type_qualifier {
|
||||
@ -84,6 +84,7 @@ struct cpp_demangle_data {
|
||||
int func_type;
|
||||
const char *cur; /* current mangled name ptr */
|
||||
const char *last_sname; /* last source name */
|
||||
int push_head;
|
||||
};
|
||||
|
||||
#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_expr_primary(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 *,
|
||||
const char *, size_t);
|
||||
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_read_local_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_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_offset(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_param(struct cpp_demangle_data *);
|
||||
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_v_offset(struct cpp_demangle_data *);
|
||||
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 *,
|
||||
enum type_qualifier);
|
||||
|
||||
static int cpp_demangle_gnu3_push_head;
|
||||
|
||||
/**
|
||||
* @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))
|
||||
return (NULL);
|
||||
|
||||
cpp_demangle_gnu3_push_head = 0;
|
||||
rtn = NULL;
|
||||
|
||||
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->cur = cur;
|
||||
d->last_sname = NULL;
|
||||
d->push_head = 0;
|
||||
|
||||
return (1);
|
||||
|
||||
@ -309,7 +316,6 @@ cpp_demangle_push_fp(struct cpp_demangle_data *ddata,
|
||||
fp = ddata->cur;
|
||||
while (*ddata->cur != 'E')
|
||||
++ddata->cur;
|
||||
++ddata->cur;
|
||||
|
||||
if ((f = decoder(fp, ddata->cur - fp)) == NULL)
|
||||
return (0);
|
||||
@ -320,6 +326,8 @@ cpp_demangle_push_fp(struct cpp_demangle_data *ddata,
|
||||
|
||||
free(f);
|
||||
|
||||
++ddata->cur;
|
||||
|
||||
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)
|
||||
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, str, len));
|
||||
@ -403,7 +411,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, "*", 1))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
@ -414,7 +423,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, "&", 1))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
@ -425,7 +435,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, " complex", 8))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
@ -434,23 +445,26 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (!cpp_demangle_push_str(ddata, " imaginary", 10))
|
||||
goto clean;
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, " imaginary", 10))
|
||||
if (!vector_str_push(&subst_v, " imaginary",
|
||||
10))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
|
||||
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;
|
||||
if ((e_len = strlen(v->ext_name.container[e_idx])) == 0)
|
||||
if ((e_len = strlen(v->ext_name.container[e_idx])) ==
|
||||
0)
|
||||
goto clean;
|
||||
if ((buf = malloc(sizeof(char) * (e_len + 1))) == NULL)
|
||||
if ((buf = malloc(e_len + 2)) == NULL)
|
||||
goto clean;
|
||||
|
||||
memcpy(buf, " ", 1);
|
||||
memcpy(buf + 1, v->ext_name.container[e_idx], e_len);
|
||||
snprintf(buf, e_len + 2, " %s",
|
||||
v->ext_name.container[e_idx]);
|
||||
|
||||
if (!cpp_demangle_push_str(ddata, buf, e_len + 1)) {
|
||||
free(buf);
|
||||
@ -463,7 +477,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
free(buf);
|
||||
goto clean;
|
||||
}
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v)) {
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v)) {
|
||||
free(buf);
|
||||
goto clean;
|
||||
}
|
||||
@ -478,7 +493,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, " restrict", 9))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
@ -489,7 +505,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, " volatile", 9))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
@ -500,11 +517,42 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, " const", 6))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -655,10 +703,14 @@ cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
|
||||
|
||||
switch (*ddata->cur) {
|
||||
case 'b':
|
||||
if (*(ddata->cur + 2) != 'E')
|
||||
return (0);
|
||||
switch (*(++ddata->cur)) {
|
||||
case '0':
|
||||
ddata->cur += 2;
|
||||
return (cpp_demangle_push_str(ddata, "false", 5));
|
||||
case '1':
|
||||
ddata->cur += 2;
|
||||
return (cpp_demangle_push_str(ddata, "true", 4));
|
||||
default:
|
||||
return (0);
|
||||
@ -707,7 +759,8 @@ cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
|
||||
++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:
|
||||
return (0);
|
||||
@ -998,6 +1051,38 @@ cpp_demangle_read_expression(struct cpp_demangle_data *ddata)
|
||||
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
|
||||
cpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata,
|
||||
const char *name, size_t len)
|
||||
@ -1127,12 +1212,65 @@ cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c,
|
||||
static int
|
||||
cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
|
||||
{
|
||||
char *name, *type, *num_str;
|
||||
long offset;
|
||||
int rtn;
|
||||
|
||||
if (ddata == NULL || *ddata->cur == '\0')
|
||||
return (0);
|
||||
|
||||
/* special name */
|
||||
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'):
|
||||
/* sentry object for 1 time init */
|
||||
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 (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'):
|
||||
/* typeinfo common proxy */
|
||||
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'):
|
||||
/* virtual function non-virtual override thunk */
|
||||
if (cpp_demangle_push_str(ddata,
|
||||
"virtual function non-virtual override ", 38) == 0)
|
||||
if (!cpp_demangle_push_str(ddata,
|
||||
"virtual function non-virtual override ", 38))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
@ -1170,24 +1343,51 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
|
||||
return (0);
|
||||
return (cpp_demangle_read_encoding(ddata));
|
||||
|
||||
case SIMPLE_HASH('T', 'I'):
|
||||
/* typeinfo structure */
|
||||
/* FALLTHROUGH */
|
||||
case SIMPLE_HASH('T', 'S'):
|
||||
/* RTTI name (NTBS) */
|
||||
if (!cpp_demangle_push_str(ddata, "typeinfo for ", 14))
|
||||
case SIMPLE_HASH('T', 'H'):
|
||||
/* TLS init function */
|
||||
if (!cpp_demangle_push_str(ddata, "TLS init function for ",
|
||||
22))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\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'):
|
||||
/* VTT table */
|
||||
if (!cpp_demangle_push_str(ddata, "VTT for ", 8))
|
||||
return (0);
|
||||
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'):
|
||||
/* virtual function virtual override thunk */
|
||||
@ -1208,7 +1408,17 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\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));
|
||||
@ -1270,8 +1480,7 @@ cpp_demangle_read_name(struct cpp_demangle_data *ddata)
|
||||
if (ddata == NULL || *ddata->cur == '\0')
|
||||
return (0);
|
||||
|
||||
output = cpp_demangle_gnu3_push_head > 0 ?
|
||||
&ddata->output_tmp : &ddata->output;
|
||||
output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
|
||||
|
||||
subst_str = NULL;
|
||||
|
||||
@ -1326,6 +1535,38 @@ cpp_demangle_read_name(struct cpp_demangle_data *ddata)
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
output = cpp_demangle_gnu3_push_head > 0 ?
|
||||
&ddata->output_tmp : &ddata->output;
|
||||
output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
|
||||
if (!vector_str_init(&v))
|
||||
return (0);
|
||||
|
||||
@ -1452,6 +1692,24 @@ cpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn)
|
||||
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
|
||||
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)
|
||||
{
|
||||
long len;
|
||||
int err;
|
||||
|
||||
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);
|
||||
|
||||
assert(ddata->output.size > 0);
|
||||
@ -1732,8 +1999,7 @@ cpp_demangle_read_subst_std(struct cpp_demangle_data *ddata)
|
||||
|
||||
ddata->cur += 2;
|
||||
|
||||
output = cpp_demangle_gnu3_push_head > 0 ?
|
||||
&ddata->output_tmp : &ddata->output;
|
||||
output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
|
||||
|
||||
p_idx = output->size;
|
||||
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)
|
||||
return (0);
|
||||
|
||||
output = cpp_demangle_gnu3_push_head > 0 ? &ddata->output_tmp :
|
||||
&ddata->output;
|
||||
output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
|
||||
|
||||
p_idx = output->size;
|
||||
substr = NULL;
|
||||
@ -1852,8 +2117,7 @@ cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
|
||||
return (0);
|
||||
|
||||
limit = 0;
|
||||
v = cpp_demangle_gnu3_push_head > 0 ?
|
||||
&ddata->output_tmp : &ddata->output;
|
||||
v = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
|
||||
for (;;) {
|
||||
idx = v->size;
|
||||
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;
|
||||
int extern_c, is_builtin;
|
||||
long len;
|
||||
char *type_str;
|
||||
char *type_str, *exp_str, *num_str;
|
||||
|
||||
if (ddata == NULL)
|
||||
return (0);
|
||||
|
||||
output = &ddata->output;
|
||||
if (!strncmp(ddata->output.container[ddata->output.size - 1], ">", 1)) {
|
||||
cpp_demangle_gnu3_push_head++;
|
||||
ddata->push_head++;
|
||||
output = &ddata->output_tmp;
|
||||
} else if (delimit == 1) {
|
||||
if (ddata->paren == false) {
|
||||
@ -1978,7 +2242,7 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
|
||||
extern_c = 0;
|
||||
is_builtin = 1;
|
||||
p_idx = output->size;
|
||||
type_str = NULL;
|
||||
type_str = exp_str = num_str = NULL;
|
||||
again:
|
||||
/* builtin type */
|
||||
switch (*ddata->cur) {
|
||||
@ -2024,6 +2288,82 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
|
||||
++ddata->cur;
|
||||
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':
|
||||
/* long double */
|
||||
if (!cpp_demangle_push_str(ddata, "long double", 11))
|
||||
@ -2118,7 +2458,7 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
|
||||
|
||||
case 'o':
|
||||
/* unsigned __int128 */
|
||||
if (!cpp_demangle_push_str(ddata, "unsigned _;int128", 17))
|
||||
if (!cpp_demangle_push_str(ddata, "unsigned __int128", 17))
|
||||
goto clean;
|
||||
++ddata->cur;
|
||||
goto rtn;
|
||||
@ -2189,6 +2529,8 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
|
||||
if (!vector_str_push(&v.ext_name, ddata->cur, len))
|
||||
return (0);
|
||||
ddata->cur += len;
|
||||
if (!vector_type_qualifier_push(&v, TYPE_EXT))
|
||||
goto clean;
|
||||
goto again;
|
||||
|
||||
case 'v':
|
||||
@ -2253,14 +2595,16 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
|
||||
goto clean;
|
||||
|
||||
free(type_str);
|
||||
free(exp_str);
|
||||
free(num_str);
|
||||
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)
|
||||
== 0)
|
||||
return (0);
|
||||
|
||||
if (--cpp_demangle_gnu3_push_head > 0)
|
||||
if (--ddata->push_head > 0)
|
||||
return (1);
|
||||
|
||||
if (!vector_str_push(&ddata->output_tmp, " ", 1))
|
||||
@ -2284,11 +2628,45 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
|
||||
return (1);
|
||||
clean:
|
||||
free(type_str);
|
||||
free(exp_str);
|
||||
free(num_str);
|
||||
vector_type_qualifier_dest(&v);
|
||||
|
||||
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,
|
||||
* source-name
|
||||
|
@ -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
|
||||
|
@ -22,7 +22,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: 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
|
||||
.Os
|
||||
@ -90,7 +90,7 @@ sections in the ELF object.
|
||||
.It Fl e | Fl -headers
|
||||
Print all program, file and section headers in the ELF object.
|
||||
.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
|
||||
Print the file header of the ELF object.
|
||||
.It Fl l | Fl -program-headers
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2009-2014 Kai Wang
|
||||
* Copyright (c) 2009-2015 Kai Wang
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
#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.
|
||||
@ -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_phdr(struct readelf *re);
|
||||
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_symtabs(struct readelf *re);
|
||||
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_386: return "Intel i386";
|
||||
case EM_68K: return "Motorola 68000";
|
||||
case EM_IAMCU: return "Intel MCU";
|
||||
case EM_88K: return "Motorola 88000";
|
||||
case EM_860: return "Intel i860";
|
||||
case EM_MIPS: return "MIPS R3000 Big-Endian only";
|
||||
@ -1050,6 +1052,7 @@ r_type(unsigned int mach, unsigned int type)
|
||||
switch(mach) {
|
||||
case EM_NONE: return "";
|
||||
case EM_386:
|
||||
case EM_IAMCU:
|
||||
switch(type) {
|
||||
case 0: return "R_386_NONE";
|
||||
case 1: return "R_386_32";
|
||||
@ -2381,6 +2384,7 @@ dwarf_reg(unsigned int mach, unsigned int reg)
|
||||
|
||||
switch (mach) {
|
||||
case EM_386:
|
||||
case EM_IAMCU:
|
||||
switch (reg) {
|
||||
case 0: return "eax";
|
||||
case 1: return "ecx";
|
||||
@ -4047,6 +4051,61 @@ dump_liblist(struct readelf *re)
|
||||
|
||||
#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 *
|
||||
dump_unknown_tag(uint64_t tag, uint8_t *p)
|
||||
{
|
||||
@ -6838,6 +6897,8 @@ dump_elf(struct readelf *re)
|
||||
dump_phdr(re);
|
||||
if (re->options & RE_SS)
|
||||
dump_shdr(re);
|
||||
if (re->options & RE_G)
|
||||
dump_section_groups(re);
|
||||
if (re->options & RE_D)
|
||||
dump_dynamic(re);
|
||||
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\
|
||||
-d | --dynamic Print the contents of SHT_DYNAMIC sections.\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\
|
||||
-l | --program-headers Print the PHDR table for the object.\n\
|
||||
-n | --notes Print the contents of SHT_NOTE sections.\n\
|
||||
@ -7365,8 +7426,8 @@ main(int argc, char **argv)
|
||||
re->options |= RE_AA;
|
||||
break;
|
||||
case 'a':
|
||||
re->options |= RE_AA | RE_D | RE_H | RE_II | RE_L |
|
||||
RE_R | RE_SS | RE_S | RE_VV;
|
||||
re->options |= RE_AA | RE_D | RE_G | RE_H | RE_II |
|
||||
RE_L | RE_R | RE_SS | RE_S | RE_VV;
|
||||
break;
|
||||
case 'c':
|
||||
re->options |= RE_C;
|
||||
|
@ -6,5 +6,5 @@
|
||||
const char *
|
||||
elftc_version(void)
|
||||
{
|
||||
return "elftoolchain r3197M";
|
||||
return "elftoolchain r3223M";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user