Print this page
10816 ctf_dwarf_convert_type() relies on un-initialized id
10817 ctfconvert -i option is mis-handled
10818 Improve ctfconvert error messages
10819 ctfconvert should handle empty dies
10820 ctfconvert -i never converts
10821 bad free in ctf_dwarf_init_die
10815 shouldn't build gcore.c as part of kmdb
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>

*** 19,176 **** * understands DWARFv2 (and bits of DWARFv4). Each backend should be placed in * the ctf_converters list and each will be tried in turn. */ #include <libctf_impl.h> #include <gelf.h> ctf_convert_f ctf_converters[] = { ctf_dwarf_convert }; #define NCONVERTS (sizeof (ctf_converters) / sizeof (ctf_convert_f)) ! typedef enum ctf_convert_source { ! CTFCONV_SOURCE_NONE = 0x0, ! CTFCONV_SOURCE_UNKNOWN = 0x01, ! CTFCONV_SOURCE_C = 0x02, ! CTFCONV_SOURCE_S = 0x04 ! } ctf_convert_source_t; ! ! static void ! ctf_convert_ftypes(Elf *elf, ctf_convert_source_t *types) { ! int i; ! Elf_Scn *scn = NULL, *strscn; ! *types = CTFCONV_SOURCE_NONE; ! GElf_Shdr shdr; Elf_Data *data, *strdata; while ((scn = elf_nextscn(elf, scn)) != NULL) { - if (gelf_getshdr(scn, &shdr) == NULL) - return; - if (shdr.sh_type == SHT_SYMTAB) break; } if (scn == NULL) ! return; ! if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL) ! return; ! if ((data = elf_getdata(scn, NULL)) == NULL) ! return; ! if ((strdata = elf_getdata(strscn, NULL)) == NULL) ! return; for (i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { GElf_Sym sym; const char *file; size_t len; ! if (gelf_getsym(data, i, &sym) == NULL) ! return; if (GELF_ST_TYPE(sym.st_info) != STT_FILE) continue; file = (const char *)((uintptr_t)strdata->d_buf + sym.st_name); len = strlen(file); ! if (len < 2 || file[len - 2] != '.') { ! *types |= CTFCONV_SOURCE_UNKNOWN; ! continue; ! } ! ! switch (file[len - 1]) { ! case 'c': ! *types |= CTFCONV_SOURCE_C; break; - case 'h': - /* We traditionally ignore header files... */ - break; - case 's': - *types |= CTFCONV_SOURCE_S; - break; - default: - *types |= CTFCONV_SOURCE_UNKNOWN; - break; } } } static ctf_file_t * ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t nthrs, uint_t flags, int *errp, char *errbuf, size_t errlen) { int err, i; ctf_file_t *fp = NULL; - boolean_t notsup = B_TRUE; - ctf_convert_source_t type; if (errp == NULL) errp = &err; if (elf == NULL) { *errp = EINVAL; return (NULL); } ! if (flags & ~CTF_CONVERT_F_IGNNONC) { *errp = EINVAL; return (NULL); } if (elf_kind(elf) != ELF_K_ELF) { *errp = ECTF_FMT; return (NULL); } ! ctf_convert_ftypes(elf, &type); ! ctf_dprintf("got types: %d\n", type); ! if (flags & CTF_CONVERT_F_IGNNONC) { ! if (type == CTFCONV_SOURCE_NONE || ! (type & CTFCONV_SOURCE_UNKNOWN)) { *errp = ECTF_CONVNOCSRC; return (NULL); } - } for (i = 0; i < NCONVERTS; i++) { - ctf_conv_status_t cs; - fp = NULL; ! cs = ctf_converters[i](fd, elf, nthrs, errp, &fp, errbuf, ! errlen); ! if (cs == CTF_CONV_SUCCESS) { ! notsup = B_FALSE; break; } - if (cs == CTF_CONV_ERROR) { - fp = NULL; - notsup = B_FALSE; - break; - } - } ! if (notsup == B_TRUE) { ! if ((flags & CTF_CONVERT_F_IGNNONC) != 0 && ! (type & CTFCONV_SOURCE_C) == 0) { ! *errp = ECTF_CONVNOCSRC; return (NULL); } - *errp = ECTF_NOCONVBKEND; - return (NULL); - } ! /* ! * Succsesful conversion. ! */ ! if (fp != NULL && label != NULL) { if (ctf_add_label(fp, label, fp->ctf_typemax, 0) == CTF_ERR) { *errp = ctf_errno(fp); ctf_close(fp); return (NULL); } --- 19,160 ---- * understands DWARFv2 (and bits of DWARFv4). Each backend should be placed in * the ctf_converters list and each will be tried in turn. */ #include <libctf_impl.h> + #include <assert.h> #include <gelf.h> ctf_convert_f ctf_converters[] = { ctf_dwarf_convert }; #define NCONVERTS (sizeof (ctf_converters) / sizeof (ctf_convert_f)) ! ctf_hsc_ret_t ! ctf_has_c_source(Elf *elf, char *errmsg, size_t errlen) { ! ctf_hsc_ret_t ret = CHR_NO_C_SOURCE; ! Elf_Scn *scn, *strscn; Elf_Data *data, *strdata; + GElf_Shdr shdr; + ulong_t i; + scn = NULL; while ((scn = elf_nextscn(elf, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) == NULL) { + (void) snprintf(errmsg, errlen, + "failed to get section header: %s", + elf_errmsg(elf_errno())); + return (CHR_ERROR); + } if (shdr.sh_type == SHT_SYMTAB) break; } if (scn == NULL) ! return (CHR_NO_C_SOURCE); ! if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL) { ! (void) snprintf(errmsg, errlen, "failed to get str section: %s", ! elf_errmsg(elf_errno())); ! return (CHR_ERROR); ! } ! if ((data = elf_getdata(scn, NULL)) == NULL) { ! (void) snprintf(errmsg, errlen, "failed to read section: %s", ! elf_errmsg(elf_errno())); ! return (CHR_ERROR); ! } ! if ((strdata = elf_getdata(strscn, NULL)) == NULL) { ! (void) snprintf(errmsg, errlen, ! "failed to read string table: %s", elf_errmsg(elf_errno())); ! return (CHR_ERROR); ! } for (i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { GElf_Sym sym; const char *file; size_t len; ! if (gelf_getsym(data, i, &sym) == NULL) { ! (void) snprintf(errmsg, errlen, ! "failed to read sym %lu: %s", ! i, elf_errmsg(elf_errno())); ! return (CHR_ERROR); ! } if (GELF_ST_TYPE(sym.st_info) != STT_FILE) continue; file = (const char *)((uintptr_t)strdata->d_buf + sym.st_name); len = strlen(file); ! if (len >= 2 && strncmp(".c", &file[len - 2], 2) == 0) { ! ret = CHR_HAS_C_SOURCE; break; } } + + return (ret); } static ctf_file_t * ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t nthrs, uint_t flags, int *errp, char *errbuf, size_t errlen) { int err, i; ctf_file_t *fp = NULL; if (errp == NULL) errp = &err; if (elf == NULL) { *errp = EINVAL; return (NULL); } ! if (flags & ~CTF_ALLOW_MISSING_DEBUG) { *errp = EINVAL; return (NULL); } if (elf_kind(elf) != ELF_K_ELF) { *errp = ECTF_FMT; return (NULL); } ! switch (ctf_has_c_source(elf, errbuf, errlen)) { ! case CHR_ERROR: ! *errp = ECTF_ELF; ! return (NULL); ! ! case CHR_NO_C_SOURCE: *errp = ECTF_CONVNOCSRC; return (NULL); + + default: + break; } for (i = 0; i < NCONVERTS; i++) { fp = NULL; ! err = ctf_converters[i](fd, elf, nthrs, flags, ! &fp, errbuf, errlen); ! ! if (err != ECTF_CONVNODEBUG) break; } ! if (err != 0) { ! assert(fp == NULL); ! *errp = err; return (NULL); } ! if (label != NULL) { if (ctf_add_label(fp, label, fp->ctf_typemax, 0) == CTF_ERR) { *errp = ctf_errno(fp); ctf_close(fp); return (NULL); }