diff options
Diffstat (limited to 'cddl/contrib/opensolaris/tools')
-rw-r--r-- | cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c | 15 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h | 2 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c | 112 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c | 6 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/tools/ctf/cvt/traverse.c | 8 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/tools/ctf/cvt/util.c | 4 |
6 files changed, 128 insertions, 19 deletions
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c b/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c index 55dd39e3a900..82ec5fafda4a 100644 --- a/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c +++ b/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c @@ -47,11 +47,13 @@ * * The value is only valid during a call to ctf_load. */ -char *curfile; +static char *curfile; #define CTF_BUF_CHUNK_SIZE (64 * 1024) #define RES_BUF_CHUNK_SIZE (64 * 1024) +static int ntypes = 0; /* The number of types. */ + struct ctf_buf { strtab_t ctb_strtab; /* string table */ caddr_t ctb_base; /* pointer to base of buffer */ @@ -1143,6 +1145,10 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, (*mpp)->ml_type = tdarr[ctm->ctm_type]; (*mpp)->ml_offset = ctm->ctm_offset; (*mpp)->ml_size = 0; + if (ctm->ctm_type > ntypes) { + parseterminate("Invalid member type ctm_type=%d", + ctm->ctm_type); + } } } else { for (i = 0, mpp = &tdp->t_members; i < vlen; @@ -1159,6 +1165,10 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, (*mpp)->ml_offset = (int)CTF_LMEM_OFFSET(ctlm); (*mpp)->ml_size = 0; + if (ctlm->ctlm_type > ntypes) { + parseterminate("Invalid lmember type ctlm_type=%d", + ctlm->ctlm_type); + } } } @@ -1272,9 +1282,10 @@ ctf_parse(ctf_header_t *h, caddr_t buf, symit_data_t *si, char *label) { tdata_t *td = tdata_new(); tdesc_t **tdarr; - int ntypes = count_types(h, buf); int idx, i; + ntypes = count_types(h, buf); + /* shudder */ tdarr = xcalloc(sizeof (tdesc_t *) * (ntypes + 1)); tdarr[0] = NULL; diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h b/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h index 93a540d22c60..9b2ee3d7565c 100644 --- a/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h +++ b/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h @@ -159,7 +159,7 @@ typedef struct ardef { /* Auxiliary structure for structure/union tdesc_t */ typedef struct mlist { int ml_offset; /* Offset from start of structure (in bits) */ - int ml_size; /* Member size (in bits) */ + uint_t ml_size; /* Member size (in bits) */ char *ml_name; /* Member name */ struct tdesc *ml_type; /* Member type */ struct mlist *ml_next; /* Next member */ diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c b/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c index 19aeff2c7942..0738dd080f83 100644 --- a/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c +++ b/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c @@ -23,8 +23,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * DWARF to tdata conversion * @@ -674,6 +672,13 @@ die_array_create(dwarf_t *dw, Dwarf_Die arr, Dwarf_Off off, tdesc_t *tdp) tdesc_t *dimtdp; int flags; + /* Check for bogus gcc DW_AT_byte_size attribute */ + if (uval == (unsigned)-1) { + printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n", + __func__); + uval = 0; + } + tdp->t_size = uval; /* @@ -760,6 +765,12 @@ die_enum_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp) tdp->t_type = ENUM; (void) die_unsigned(dw, die, DW_AT_byte_size, &uval, DW_ATTR_REQ); + /* Check for bogus gcc DW_AT_byte_size attribute */ + if (uval == (unsigned)-1) { + printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n", + __func__); + uval = 0; + } tdp->t_size = uval; if ((mem = die_child(dw, die)) != NULL) { @@ -873,7 +884,7 @@ static void die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp, int type, const char *typename) { - Dwarf_Unsigned sz, bitsz, bitoff; + Dwarf_Unsigned sz, bitsz, bitoff, maxsz=0; Dwarf_Die mem; mlist_t *ml, **mlastp; iidesc_t *ii; @@ -929,6 +940,8 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp, ml->ml_name = NULL; ml->ml_type = die_lookup_pass1(dw, mem, DW_AT_type); + debug(3, "die_sou_create(): ml_type = %p t_id = %d\n", + ml->ml_type, ml->ml_type->t_id); if (die_mem_offset(dw, mem, DW_AT_data_member_location, &mloff, 0)) { @@ -956,8 +969,24 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp, *mlastp = ml; mlastp = &ml->ml_next; + + /* Find the size of the largest member to work around a gcc + * bug. See GCC Bugzilla 35998. + */ + if (maxsz < ml->ml_size) + maxsz = ml->ml_size; + } while ((mem = die_sibling(dw, mem)) != NULL); + /* See if we got a bogus DW_AT_byte_size. GCC will sometimes + * emit this. + */ + if (sz == (unsigned)-1) { + printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n", + __func__); + tdp->t_size = maxsz / 8; /* maxsz is in bits, t_size is bytes */ + } + /* * GCC will attempt to eliminate unused types, thus decreasing the * size of the emitted dwarf. That is, if you declare a foo_t in your @@ -1054,7 +1083,7 @@ die_sou_resolve(tdesc_t *tdp, tdesc_t **tdpp __unused, void *private) } if (ml->ml_size != 0 && mt->t_type == INTRINSIC && - mt->t_intr->intr_nbits != ml->ml_size) { + mt->t_intr->intr_nbits != (int)ml->ml_size) { /* * This member is a bitfield, and needs to reference * an intrinsic type with the same width. If the @@ -1370,6 +1399,13 @@ die_base_create(dwarf_t *dw, Dwarf_Die base, Dwarf_Off off, tdesc_t *tdp) */ (void) die_unsigned(dw, base, DW_AT_byte_size, &sz, DW_ATTR_REQ); + /* Check for bogus gcc DW_AT_byte_size attribute */ + if (sz == (unsigned)-1) { + printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n", + __func__); + sz = 0; + } + if (tdp->t_name == NULL) terminate("die %llu: base type without name\n", off); @@ -1758,6 +1794,59 @@ die_resolve(dwarf_t *dw) } while (dw->dw_nunres != 0); } +/* + * Any object containing a function or object symbol at any scope should also + * contain DWARF data. + */ +static boolean_t +should_have_dwarf(Elf *elf) +{ + Elf_Scn *scn = NULL; + Elf_Data *data = NULL; + GElf_Shdr shdr; + GElf_Sym sym; + uint32_t symdx = 0; + size_t nsyms = 0; + boolean_t found = B_FALSE; + + while ((scn = elf_nextscn(elf, scn)) != NULL) { + gelf_getshdr(scn, &shdr); + + if (shdr.sh_type == SHT_SYMTAB) { + found = B_TRUE; + break; + } + } + + if (!found) + terminate("cannot convert stripped objects\n"); + + data = elf_getdata(scn, NULL); + nsyms = shdr.sh_size / shdr.sh_entsize; + + for (symdx = 0; symdx < nsyms; symdx++) { + gelf_getsym(data, symdx, &sym); + + if ((GELF_ST_TYPE(sym.st_info) == STT_FUNC) || + (GELF_ST_TYPE(sym.st_info) == STT_TLS) || + (GELF_ST_TYPE(sym.st_info) == STT_OBJECT)) { + char *name; + + name = elf_strptr(elf, shdr.sh_link, sym.st_name); + + /* Studio emits these local symbols regardless */ + if ((strcmp(name, "Bbss.bss") != 0) && + (strcmp(name, "Ttbss.bss") != 0) && + (strcmp(name, "Ddata.data") != 0) && + (strcmp(name, "Ttdata.data") != 0) && + (strcmp(name, "Drodata.rodata") != 0)) + return (B_TRUE); + } + } + + return (B_FALSE); +} + /*ARGSUSED*/ int dw_read(tdata_t *td, Elf *elf, char *filename __unused) @@ -1782,8 +1871,12 @@ dw_read(tdata_t *td, Elf *elf, char *filename __unused) if ((rc = dwarf_elf_init(elf, DW_DLC_READ, &dw.dw_dw, &dw.dw_err)) == DW_DLV_NO_ENTRY) { - errno = ENOENT; - return (-1); + if (should_have_dwarf(elf)) { + errno = ENOENT; + return (-1); + } else { + return (0); + } } else if (rc != DW_DLV_OK) { if (dwarf_errno(&dw.dw_err) == DW_DLE_DEBUG_INFO_NULL) { /* @@ -1801,9 +1894,14 @@ dw_read(tdata_t *td, Elf *elf, char *filename __unused) &addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_OK) terminate("rc = %d %s\n", rc, dwarf_errmsg(&dw.dw_err)); - if ((cu = die_sibling(&dw, NULL)) == NULL) + if ((cu = die_sibling(&dw, NULL)) == NULL || + (((child = die_child(&dw, cu)) == NULL) && + should_have_dwarf(elf))) { terminate("file does not contain dwarf type data " "(try compiling with -g)\n"); + } else if (child == NULL) { + return (0); + } dw.dw_maxoff = nxthdr - 1; diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c b/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c index 1dca82a0d3b2..e136c94ab9b0 100644 --- a/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c +++ b/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c @@ -54,7 +54,7 @@ static int faketypenumber = 100000000; static tdesc_t *hash_table[BUCKETS]; static tdesc_t *name_table[BUCKETS]; -list_t *typedbitfldmems; +static list_t *typedbitfldmems; static void reset(void); static jmp_buf resetbuf; @@ -952,7 +952,7 @@ soudef(char *cp, stabtype_t type, tdesc_t **rtdp) itdp = find_intrinsic(tdp); if (itdp->t_type == INTRINSIC) { - if (mlp->ml_size != itdp->t_intr->intr_nbits) { + if ((int)mlp->ml_size != itdp->t_intr->intr_nbits) { parse_debug(4, cp, "making %d bit intrinsic " "from %s", mlp->ml_size, tdesc_name(itdp)); mlp->ml_type = bitintrinsic(itdp, mlp->ml_size); @@ -1173,7 +1173,7 @@ resolve_typed_bitfields_cb(void *arg, void *private __unused) while (tdp) { switch (tdp->t_type) { case INTRINSIC: - if (ml->ml_size != tdp->t_intr->intr_nbits) { + if ((int)ml->ml_size != tdp->t_intr->intr_nbits) { debug(3, "making %d bit intrinsic from %s", ml->ml_size, tdesc_name(tdp)); ml->ml_type = bitintrinsic(tdp, ml->ml_size); diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/traverse.c b/cddl/contrib/opensolaris/tools/ctf/cvt/traverse.c index feb9908638af..2d6d74bc78b1 100644 --- a/cddl/contrib/opensolaris/tools/ctf/cvt/traverse.c +++ b/cddl/contrib/opensolaris/tools/ctf/cvt/traverse.c @@ -37,8 +37,8 @@ #include "traverse.h" #include "memory.h" -int (*tddescenders[])(tdesc_t *, tdtrav_data_t *); -tdtrav_cb_f tdnops[]; +static int (*tddescenders[])(tdesc_t *, tdtrav_data_t *); +static tdtrav_cb_f tdnops[]; void tdtrav_init(tdtrav_data_t *tdtd, int *vgenp, tdtrav_cb_f *firstops, @@ -111,7 +111,7 @@ tdtrav_assert(tdesc_t *node __unused, tdesc_t **nodep __unused, void *private __ return (-1); } -tdtrav_cb_f tdnops[] = { +static tdtrav_cb_f tdnops[] = { NULL, NULL, /* intrinsic */ NULL, /* pointer */ @@ -128,7 +128,7 @@ tdtrav_cb_f tdnops[] = { NULL /* restrict */ }; -int (*tddescenders[])(tdesc_t *, tdtrav_data_t *) = { +static int (*tddescenders[])(tdesc_t *, tdtrav_data_t *) = { NULL, NULL, /* intrinsic */ tdtrav_plain, /* pointer */ diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/util.c b/cddl/contrib/opensolaris/tools/ctf/cvt/util.c index 0f36fa02decf..82dfe63ad579 100644 --- a/cddl/contrib/opensolaris/tools/ctf/cvt/util.c +++ b/cddl/contrib/opensolaris/tools/ctf/cvt/util.c @@ -249,8 +249,8 @@ tdesc_name(tdesc_t *tdp) return (tdp->t_name == NULL ? "(anon)" : tdp->t_name); } -char *watch_address = NULL; -int watch_length = 0; +static char *watch_address = NULL; +static int watch_length = 0; void watch_set(void *addr, int len) |