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>


   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2019 Joyent, Inc.
  14  */
  15 
  16 /*
  17  * Main conversion entry points. This has been designed such that there can be
  18  * any number of different conversion backends. Currently we only have one that
  19  * understands DWARFv2 (and bits of DWARFv4). Each backend should be placed in
  20  * the ctf_converters list and each will be tried in turn.
  21  */
  22 
  23 #include <libctf_impl.h>

  24 #include <gelf.h>
  25 
  26 ctf_convert_f ctf_converters[] = {
  27         ctf_dwarf_convert
  28 };
  29 
  30 #define NCONVERTS       (sizeof (ctf_converters) / sizeof (ctf_convert_f))
  31 
  32 typedef enum ctf_convert_source {
  33         CTFCONV_SOURCE_NONE = 0x0,
  34         CTFCONV_SOURCE_UNKNOWN = 0x01,
  35         CTFCONV_SOURCE_C = 0x02,
  36         CTFCONV_SOURCE_S = 0x04
  37 } ctf_convert_source_t;
  38 
  39 static void
  40 ctf_convert_ftypes(Elf *elf, ctf_convert_source_t *types)
  41 {
  42         int i;
  43         Elf_Scn *scn = NULL, *strscn;
  44         *types = CTFCONV_SOURCE_NONE;
  45         GElf_Shdr shdr;
  46         Elf_Data *data, *strdata;


  47 

  48         while ((scn = elf_nextscn(elf, scn)) != NULL) {






  49 
  50                 if (gelf_getshdr(scn, &shdr) == NULL)
  51                         return;
  52 
  53                 if (shdr.sh_type == SHT_SYMTAB)
  54                         break;
  55         }
  56 
  57         if (scn == NULL)
  58                 return;
  59 
  60         if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL)
  61                 return;



  62 
  63         if ((data = elf_getdata(scn, NULL)) == NULL)
  64                 return;



  65 
  66         if ((strdata = elf_getdata(strscn, NULL)) == NULL)
  67                 return;



  68 
  69         for (i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
  70                 GElf_Sym sym;
  71                 const char *file;
  72                 size_t len;
  73 
  74                 if (gelf_getsym(data, i, &sym) == NULL)
  75                         return;




  76 
  77                 if (GELF_ST_TYPE(sym.st_info) != STT_FILE)
  78                         continue;
  79 
  80                 file = (const char *)((uintptr_t)strdata->d_buf + sym.st_name);
  81                 len = strlen(file);
  82                 if (len < 2 || file[len - 2] != '.') {
  83                         *types |= CTFCONV_SOURCE_UNKNOWN;
  84                         continue;
  85                 }
  86 
  87                 switch (file[len - 1]) {
  88                 case 'c':
  89                         *types |= CTFCONV_SOURCE_C;
  90                         break;
  91                 case 'h':
  92                         /* We traditionally ignore header files... */
  93                         break;
  94                 case 's':
  95                         *types |= CTFCONV_SOURCE_S;
  96                         break;
  97                 default:
  98                         *types |= CTFCONV_SOURCE_UNKNOWN;
  99                         break;
 100                 }
 101         }


 102 }
 103 
 104 static ctf_file_t *
 105 ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t nthrs, uint_t flags,
 106     int *errp, char *errbuf, size_t errlen)
 107 {
 108         int err, i;
 109         ctf_file_t *fp = NULL;
 110         boolean_t notsup = B_TRUE;
 111         ctf_convert_source_t type;
 112 
 113         if (errp == NULL)
 114                 errp = &err;
 115 
 116         if (elf == NULL) {
 117                 *errp = EINVAL;
 118                 return (NULL);
 119         }
 120 
 121         if (flags & ~CTF_CONVERT_F_IGNNONC) {
 122                 *errp = EINVAL;
 123                 return (NULL);
 124         }
 125 
 126         if (elf_kind(elf) != ELF_K_ELF) {
 127                 *errp = ECTF_FMT;
 128                 return (NULL);
 129         }
 130 
 131         ctf_convert_ftypes(elf, &type);
 132         ctf_dprintf("got types: %d\n", type);
 133         if (flags & CTF_CONVERT_F_IGNNONC) {
 134                 if (type == CTFCONV_SOURCE_NONE ||
 135                     (type & CTFCONV_SOURCE_UNKNOWN)) {

 136                         *errp = ECTF_CONVNOCSRC;
 137                         return (NULL);



 138                 }
 139         }
 140 
 141         for (i = 0; i < NCONVERTS; i++) {
 142                 ctf_conv_status_t cs;
 143 
 144                 fp = NULL;
 145                 cs = ctf_converters[i](fd, elf, nthrs, errp, &fp, errbuf,
 146                     errlen);
 147                 if (cs == CTF_CONV_SUCCESS) {
 148                         notsup = B_FALSE;
 149                         break;
 150                 }
 151                 if (cs == CTF_CONV_ERROR) {
 152                         fp = NULL;
 153                         notsup = B_FALSE;
 154                         break;
 155                 }
 156         }
 157 
 158         if (notsup == B_TRUE) {
 159                 if ((flags & CTF_CONVERT_F_IGNNONC) != 0 &&
 160                     (type & CTFCONV_SOURCE_C) == 0) {
 161                         *errp = ECTF_CONVNOCSRC;
 162                         return (NULL);
 163                 }
 164                 *errp = ECTF_NOCONVBKEND;
 165                 return (NULL);
 166         }
 167 
 168         /*
 169          * Succsesful conversion.
 170          */
 171         if (fp != NULL && label != NULL) {
 172                 if (ctf_add_label(fp, label, fp->ctf_typemax, 0) == CTF_ERR) {
 173                         *errp = ctf_errno(fp);
 174                         ctf_close(fp);
 175                         return (NULL);
 176                 }
 177                 if (ctf_update(fp) == CTF_ERR) {
 178                         *errp = ctf_errno(fp);
 179                         ctf_close(fp);
 180                         return (NULL);
 181                 }
 182         }
 183 
 184         return (fp);
 185 }
 186 
 187 ctf_file_t *
 188 ctf_fdconvert(int fd, const char *label, uint_t nthrs, uint_t flags, int *errp,
 189     char *errbuf, size_t errlen)
 190 {
 191         int err;


   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2019 Joyent, Inc.
  14  */
  15 
  16 /*
  17  * Main conversion entry points. This has been designed such that there can be
  18  * any number of different conversion backends. Currently we only have one that
  19  * understands DWARFv2 (and bits of DWARFv4). Each backend should be placed in
  20  * the ctf_converters list and each will be tried in turn.
  21  */
  22 
  23 #include <libctf_impl.h>
  24 #include <assert.h>
  25 #include <gelf.h>
  26 
  27 ctf_convert_f ctf_converters[] = {
  28         ctf_dwarf_convert
  29 };
  30 
  31 #define NCONVERTS       (sizeof (ctf_converters) / sizeof (ctf_convert_f))
  32 
  33 ctf_hsc_ret_t
  34 ctf_has_c_source(Elf *elf, char *errmsg, size_t errlen)







  35 {
  36         ctf_hsc_ret_t ret = CHR_NO_C_SOURCE;
  37         Elf_Scn *scn, *strscn;


  38         Elf_Data *data, *strdata;
  39         GElf_Shdr shdr;
  40         ulong_t i;
  41 
  42         scn = NULL;
  43         while ((scn = elf_nextscn(elf, scn)) != NULL) {
  44                 if (gelf_getshdr(scn, &shdr) == NULL) {
  45                         (void) snprintf(errmsg, errlen,
  46                             "failed to get section header: %s",
  47                             elf_errmsg(elf_errno()));
  48                         return (CHR_ERROR);
  49                 }
  50 



  51                 if (shdr.sh_type == SHT_SYMTAB)
  52                         break;
  53         }
  54 
  55         if (scn == NULL)
  56                 return (CHR_NO_C_SOURCE);
  57 
  58         if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL) {
  59                 (void) snprintf(errmsg, errlen, "failed to get str section: %s",
  60                     elf_errmsg(elf_errno()));
  61                 return (CHR_ERROR);
  62         }
  63 
  64         if ((data = elf_getdata(scn, NULL)) == NULL) {
  65                 (void) snprintf(errmsg, errlen, "failed to read section: %s",
  66                     elf_errmsg(elf_errno()));
  67                 return (CHR_ERROR);
  68         }
  69 
  70         if ((strdata = elf_getdata(strscn, NULL)) == NULL) {
  71                 (void) snprintf(errmsg, errlen,
  72                     "failed to read string table: %s", elf_errmsg(elf_errno()));
  73                 return (CHR_ERROR);
  74         }
  75 
  76         for (i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
  77                 GElf_Sym sym;
  78                 const char *file;
  79                 size_t len;
  80 
  81                 if (gelf_getsym(data, i, &sym) == NULL) {
  82                         (void) snprintf(errmsg, errlen,
  83                             "failed to read sym %lu: %s",
  84                             i, elf_errmsg(elf_errno()));
  85                         return (CHR_ERROR);
  86                 }
  87 
  88                 if (GELF_ST_TYPE(sym.st_info) != STT_FILE)
  89                         continue;
  90 
  91                 file = (const char *)((uintptr_t)strdata->d_buf + sym.st_name);
  92                 len = strlen(file);
  93                 if (len >= 2 && strncmp(".c", &file[len - 2], 2) == 0) {
  94                         ret = CHR_HAS_C_SOURCE;






  95                         break;









  96                 }
  97         }
  98 
  99         return (ret);
 100 }
 101 
 102 static ctf_file_t *
 103 ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t nthrs, uint_t flags,
 104     int *errp, char *errbuf, size_t errlen)
 105 {
 106         int err, i;
 107         ctf_file_t *fp = NULL;


 108 
 109         if (errp == NULL)
 110                 errp = &err;
 111 
 112         if (elf == NULL) {
 113                 *errp = EINVAL;
 114                 return (NULL);
 115         }
 116 
 117         if (flags & ~CTF_ALLOW_MISSING_DEBUG) {
 118                 *errp = EINVAL;
 119                 return (NULL);
 120         }
 121 
 122         if (elf_kind(elf) != ELF_K_ELF) {
 123                 *errp = ECTF_FMT;
 124                 return (NULL);
 125         }
 126 
 127         switch (ctf_has_c_source(elf, errbuf, errlen)) {
 128         case CHR_ERROR:
 129                 *errp = ECTF_ELF;
 130                 return (NULL);
 131 
 132         case CHR_NO_C_SOURCE:
 133                 *errp = ECTF_CONVNOCSRC;
 134                 return (NULL);
 135 
 136         default:
 137                 break;
 138         }

 139 
 140         for (i = 0; i < NCONVERTS; i++) {


 141                 fp = NULL;
 142                 err = ctf_converters[i](fd, elf, nthrs, flags,
 143                     &fp, errbuf, errlen);
 144 
 145                 if (err != ECTF_CONVNODEBUG)
 146                         break;
 147         }






 148 
 149         if (err != 0) {
 150                 assert(fp == NULL);
 151                 *errp = err;

 152                 return (NULL);
 153         }



 154 
 155         if (label != NULL) {



 156                 if (ctf_add_label(fp, label, fp->ctf_typemax, 0) == CTF_ERR) {
 157                         *errp = ctf_errno(fp);
 158                         ctf_close(fp);
 159                         return (NULL);
 160                 }
 161                 if (ctf_update(fp) == CTF_ERR) {
 162                         *errp = ctf_errno(fp);
 163                         ctf_close(fp);
 164                         return (NULL);
 165                 }
 166         }
 167 
 168         return (fp);
 169 }
 170 
 171 ctf_file_t *
 172 ctf_fdconvert(int fd, const char *label, uint_t nthrs, uint_t flags, int *errp,
 173     char *errbuf, size_t errlen)
 174 {
 175         int err;