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>

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/ctfmerge/ctfmerge.c
          +++ new/usr/src/cmd/ctfmerge/ctfmerge.c
↓ open down ↓ 2 lines elided ↑ open up ↑
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13      - * Copyright (c) 2017, Joyent, Inc.
       13 + * Copyright (c) 2019, Joyent, Inc.
  14   14   */
  15   15  
  16   16  /*
  17   17   * merge CTF containers
  18   18   */
  19   19  
  20   20  #include <stdio.h>
  21   21  #include <libctf.h>
  22   22  #include <sys/stat.h>
  23   23  #include <sys/types.h>
↓ open down ↓ 7 lines elided ↑ open up ↑
  31   31  #include <libelf.h>
  32   32  #include <gelf.h>
  33   33  #include <sys/mman.h>
  34   34  #include <libgen.h>
  35   35  #include <stdarg.h>
  36   36  #include <limits.h>
  37   37  
  38   38  static char *g_progname;
  39   39  static char *g_unique;
  40   40  static char *g_outfile;
  41      -static boolean_t g_req;
  42   41  static uint_t g_nctf;
  43   42  
  44   43  #define CTFMERGE_OK     0
  45   44  #define CTFMERGE_FATAL  1
  46   45  #define CTFMERGE_USAGE  2
  47   46  
  48   47  #define CTFMERGE_DEFAULT_NTHREADS       8
  49   48  #define CTFMERGE_ALTEXEC        "CTFMERGE_ALTEXEC"
  50   49  
  51   50  static void
↓ open down ↓ 5 lines elided ↑ open up ↑
  57   56          va_start(ap, fmt);
  58   57          (void) vfprintf(stderr, fmt, ap);
  59   58          va_end(ap);
  60   59  
  61   60          if (g_outfile != NULL)
  62   61                  (void) unlink(g_outfile);
  63   62  
  64   63          exit(CTFMERGE_FATAL);
  65   64  }
  66   65  
  67      -static boolean_t
  68      -ctfmerge_expect_ctf(const char *name, Elf *elf)
       66 +/*
       67 + * We failed to find CTF for this file, check if it's OK. If we're not derived
       68 + * from C, or we have the -m option, we let missing CTF pass.
       69 + */
       70 +static void
       71 +ctfmerge_check_for_c(const char *name, Elf *elf, uint_t flags)
  69   72  {
  70      -        Elf_Scn *scn, *strscn;
  71      -        Elf_Data *data, *strdata;
  72      -        GElf_Shdr shdr;
  73      -        ulong_t i;
       73 +        char errmsg[1024];
  74   74  
  75      -        if (g_req == B_FALSE)
  76      -                return (B_FALSE);
       75 +        if (flags & CTF_ALLOW_MISSING_DEBUG)
       76 +                return;
  77   77  
  78      -        scn = NULL;
  79      -        while ((scn = elf_nextscn(elf, scn)) != NULL) {
  80      -                if (gelf_getshdr(scn, &shdr) == NULL) {
  81      -                        ctfmerge_fatal("failed to get section header for file "
  82      -                            "%s: %s\n", name, elf_errmsg(elf_errno()));
  83      -                }
       78 +        switch (ctf_has_c_source(elf, errmsg, sizeof (errmsg))) {
       79 +        case CHR_ERROR:
       80 +                ctfmerge_fatal("failed to open %s: %s\n", name, errmsg);
       81 +                break;
  84   82  
  85      -                if (shdr.sh_type == SHT_SYMTAB)
  86      -                        break;
  87      -        }
       83 +        case CHR_NO_C_SOURCE:
       84 +                return;
  88   85  
  89      -        if (scn == NULL)
  90      -                return (B_FALSE);
  91      -
  92      -        if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL)
  93      -                ctfmerge_fatal("failed to get section header for file %s: %s\n",
  94      -                    name, elf_errmsg(elf_errno()));
  95      -
  96      -        if ((data = elf_getdata(scn, NULL)) == NULL)
  97      -                ctfmerge_fatal("failed to read symbol table for %s: %s\n",
  98      -                    name, elf_errmsg(elf_errno()));
  99      -
 100      -        if ((strdata = elf_getdata(strscn, NULL)) == NULL)
 101      -                ctfmerge_fatal("failed to read string table for %s: %s\n",
 102      -                    name, elf_errmsg(elf_errno()));
 103      -
 104      -        for (i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
 105      -                GElf_Sym sym;
 106      -                const char *file;
 107      -                size_t len;
 108      -
 109      -                if (gelf_getsym(data, i, &sym) == NULL)
 110      -                        ctfmerge_fatal("failed to read symbol table entry %lu "
 111      -                            "for %s: %s\n", i, name, elf_errmsg(elf_errno()));
 112      -
 113      -                if (GELF_ST_TYPE(sym.st_info) != STT_FILE)
 114      -                        continue;
 115      -
 116      -                file = (const char *)((uintptr_t)strdata->d_buf + sym.st_name);
 117      -                len = strlen(file);
 118      -                if (len < 2 || name[len - 2] != '.')
 119      -                        continue;
 120      -
 121      -                if (name[len - 1] == 'c')
 122      -                        return (B_TRUE);
       86 +        default:
       87 +                ctfmerge_fatal("failed to open %s: %s\n", name,
       88 +                    ctf_errmsg(ECTF_NOCTFDATA));
       89 +                break;
 123   90          }
 124      -
 125      -        return (B_FALSE);
 126   91  }
 127   92  
 128   93  /*
 129   94   * Go through and construct enough information for this Elf Object to try and do
 130   95   * a ctf_bufopen().
 131   96   */
 132      -static void
 133      -ctfmerge_elfopen(const char *name, Elf *elf, ctf_merge_t *cmh)
       97 +static int
       98 +ctfmerge_elfopen(const char *name, Elf *elf, ctf_merge_t *cmh, uint_t flags)
 134   99  {
 135  100          GElf_Ehdr ehdr;
 136  101          GElf_Shdr shdr;
 137  102          Elf_Scn *scn;
 138  103          Elf_Data *ctf_data, *str_data, *sym_data;
 139  104          ctf_sect_t ctfsect, symsect, strsect;
 140  105          ctf_file_t *fp;
 141  106          int err;
 142  107  
 143  108          if (gelf_getehdr(elf, &ehdr) == NULL)
↓ open down ↓ 63 lines elided ↑ open up ↑
 207  172                          str_data = elf_getdata(strscn, NULL);
 208  173                          if (str_data == NULL)
 209  174                                  ctfmerge_fatal("failed to get ELF CTF "
 210  175                                      "data section for %s: %s\n", name,
 211  176                                      elf_errmsg(elf_errno()));
 212  177                          strsect.cts_data = str_data->d_buf;
 213  178                  }
 214  179          }
 215  180  
 216  181          if (ctfsect.cts_type == SHT_NULL) {
 217      -                if (ctfmerge_expect_ctf(name, elf) == B_FALSE)
 218      -                        return;
 219      -                ctfmerge_fatal("failed to open %s: %s\n", name,
 220      -                    ctf_errmsg(ECTF_NOCTFDATA));
      182 +                ctfmerge_check_for_c(name, elf, flags);
      183 +                return (ENOENT);
 221  184          }
 222  185  
 223  186          if (symsect.cts_type != SHT_NULL && strsect.cts_type != SHT_NULL) {
 224  187                  fp = ctf_bufopen(&ctfsect, &symsect, &strsect, &err);
 225  188          } else {
 226  189                  fp = ctf_bufopen(&ctfsect, NULL, NULL, &err);
 227  190          }
 228  191  
 229  192          if (fp == NULL) {
 230      -                if (ctfmerge_expect_ctf(name, elf) == B_TRUE) {
 231      -                        ctfmerge_fatal("failed to open file %s: %s\n",
 232      -                            name, ctf_errmsg(err));
 233      -                }
 234      -        } else {
 235      -                if ((err = ctf_merge_add(cmh, fp)) != 0) {
 236      -                        ctfmerge_fatal("failed to add input %s: %s\n",
 237      -                            name, ctf_errmsg(err));
 238      -                }
 239      -                g_nctf++;
      193 +                ctfmerge_fatal("failed to open file %s: %s\n",
      194 +                    name, ctf_errmsg(err));
 240  195          }
      196 +
      197 +        if ((err = ctf_merge_add(cmh, fp)) != 0) {
      198 +                ctfmerge_fatal("failed to add input %s: %s\n",
      199 +                    name, ctf_errmsg(err));
      200 +        }
      201 +
      202 +        g_nctf++;
      203 +        return (0);
 241  204  }
 242  205  
 243  206  static void
 244  207  ctfmerge_read_archive(const char *name, int fd, Elf *elf,
 245      -    ctf_merge_t *cmh)
      208 +    ctf_merge_t *cmh, uint_t flags)
 246  209  {
 247      -        Elf *aelf;
 248  210          Elf_Cmd cmd = ELF_C_READ;
 249  211          int cursec = 1;
 250      -        char *nname;
      212 +        Elf *aelf;
 251  213  
 252  214          while ((aelf = elf_begin(fd, cmd, elf)) != NULL) {
      215 +                char *nname = NULL;
 253  216                  Elf_Arhdr *arhdr;
 254      -                boolean_t leakelf = B_FALSE;
 255  217  
 256  218                  if ((arhdr = elf_getarhdr(aelf)) == NULL)
 257  219                          ctfmerge_fatal("failed to get archive header %d for "
 258  220                              "%s: %s\n", cursec, name, elf_errmsg(elf_errno()));
 259  221  
      222 +                cmd = elf_next(aelf);
      223 +
 260  224                  if (*(arhdr->ar_name) == '/')
 261  225                          goto next;
 262  226  
 263  227                  if (asprintf(&nname, "%s.%s.%d", name, arhdr->ar_name,
 264  228                      cursec) < 0)
 265  229                          ctfmerge_fatal("failed to allocate memory for archive "
 266  230                              "%d of file %s\n", cursec, name);
 267  231  
 268  232                  switch (elf_kind(aelf)) {
 269  233                  case ELF_K_AR:
 270      -                        ctfmerge_read_archive(nname, fd, aelf, cmh);
 271      -                        free(nname);
      234 +                        ctfmerge_read_archive(nname, fd, aelf, cmh, flags);
 272  235                          break;
 273  236                  case ELF_K_ELF:
 274      -                        ctfmerge_elfopen(nname, aelf, cmh);
 275      -                        free(nname);
 276      -                        leakelf = B_TRUE;
      237 +                        /* ctfmerge_elfopen() takes ownership of aelf. */
      238 +                        if (ctfmerge_elfopen(nname, aelf, cmh, flags) == 0)
      239 +                                aelf = NULL;
 277  240                          break;
 278  241                  default:
 279  242                          ctfmerge_fatal("unknown elf kind (%d) in archive %d "
 280  243                              "for %s\n", elf_kind(aelf), cursec, name);
      244 +                        break;
 281  245                  }
 282  246  
 283  247  next:
 284      -                cmd = elf_next(aelf);
 285      -                if (leakelf == B_FALSE)
 286      -                        (void) elf_end(aelf);
      248 +                (void) elf_end(aelf);
      249 +                free(nname);
 287  250                  cursec++;
 288  251          }
 289  252  }
 290  253  
 291  254  static void
      255 +ctfmerge_file_add(ctf_merge_t *cmh, const char *file, uint_t flags)
      256 +{
      257 +        Elf *e;
      258 +        int fd;
      259 +
      260 +        if ((fd = open(file, O_RDONLY)) < 0) {
      261 +                ctfmerge_fatal("failed to open file %s: %s\n",
      262 +                    file, strerror(errno));
      263 +        }
      264 +
      265 +        if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
      266 +                (void) close(fd);
      267 +                ctfmerge_fatal("failed to open %s: %s\n",
      268 +                    file, elf_errmsg(elf_errno()));
      269 +        }
      270 +
      271 +        switch (elf_kind(e)) {
      272 +        case ELF_K_AR:
      273 +                ctfmerge_read_archive(file, fd, e, cmh, flags);
      274 +                break;
      275 +
      276 +        case ELF_K_ELF:
      277 +                /* ctfmerge_elfopen() takes ownership of e. */
      278 +                if (ctfmerge_elfopen(file, e, cmh, flags) == 0)
      279 +                        e = NULL;
      280 +                break;
      281 +
      282 +        default:
      283 +                ctfmerge_fatal("unknown elf kind (%d) for %s\n",
      284 +                    elf_kind(e), file);
      285 +        }
      286 +
      287 +        (void) elf_end(e);
      288 +        (void) close(fd);
      289 +}
      290 +
      291 +static void
 292  292  ctfmerge_usage(const char *fmt, ...)
 293  293  {
 294  294          if (fmt != NULL) {
 295  295                  va_list ap;
 296  296  
 297  297                  (void) fprintf(stderr, "%s: ", g_progname);
 298  298                  va_start(ap, fmt);
 299  299                  (void) vfprintf(stderr, fmt, ap);
 300  300                  va_end(ap);
 301  301          }
 302  302  
 303      -        (void) fprintf(stderr, "Usage: %s [-t] [-d uniqfile] [-l label] "
      303 +        (void) fprintf(stderr, "Usage: %s [-m] [-d uniqfile] [-l label] "
 304  304              "[-L labelenv] [-j nthrs] -o outfile file ...\n"
 305  305              "\n"
 306  306              "\t-d  uniquify merged output against uniqfile\n"
 307  307              "\t-j  use nthrs threads to perform the merge\n"
 308  308              "\t-l  set output container's label to specified value\n"
 309  309              "\t-L  set output container's label to value from environment\n"
 310      -            "\t-o  file to add CTF data to\n"
 311      -            "\t-t  require CTF data from all inputs built from C sources\n",
      310 +            "\t-m  allow C-based input files to not have CTF\n"
      311 +            "\t-o  file to add CTF data to\n",
 312  312              g_progname);
 313  313  }
 314  314  
 315  315  static void
 316  316  ctfmerge_altexec(char **argv)
 317  317  {
 318  318          const char *alt;
 319  319          char *altexec;
 320  320  
 321  321          alt = getenv(CTFMERGE_ALTEXEC);
↓ open down ↓ 12 lines elided ↑ open up ↑
 334  334              altexec, strerror(errno));
 335  335  }
 336  336  
 337  337  int
 338  338  main(int argc, char *argv[])
 339  339  {
 340  340          int err, i, c, ofd;
 341  341          uint_t nthreads = CTFMERGE_DEFAULT_NTHREADS;
 342  342          char *tmpfile = NULL, *label = NULL;
 343  343          int wflags = CTF_ELFWRITE_F_COMPRESS;
 344      -        ctf_file_t *ofp;
      344 +        uint_t flags = 0;
 345  345          ctf_merge_t *cmh;
      346 +        ctf_file_t *ofp;
 346  347          long argj;
 347  348          char *eptr;
 348  349  
 349  350          g_progname = basename(argv[0]);
 350  351  
 351  352          ctfmerge_altexec(argv);
 352  353  
 353  354          /*
 354  355           * We support a subset of the old CTF merge flags, mostly for
 355      -         * compatability.
      356 +         * compatibility.
 356  357           */
 357      -        while ((c = getopt(argc, argv, ":d:fgj:l:L:o:t")) != -1) {
      358 +        while ((c = getopt(argc, argv, ":d:fgj:l:L:mo:t")) != -1) {
 358  359                  switch (c) {
 359  360                  case 'd':
 360  361                          g_unique = optarg;
 361  362                          break;
 362  363                  case 'f':
 363  364                          /* Silently ignored for compatibility */
 364  365                          break;
 365  366                  case 'g':
 366  367                          /* Silently ignored for compatibility */
 367  368                          break;
↓ open down ↓ 6 lines elided ↑ open up ↑
 374  375                                      optarg);
 375  376                          }
 376  377                          nthreads = (uint_t)argj;
 377  378                          break;
 378  379                  case 'l':
 379  380                          label = optarg;
 380  381                          break;
 381  382                  case 'L':
 382  383                          label = getenv(optarg);
 383  384                          break;
      385 +                case 'm':
      386 +                        flags |= CTF_ALLOW_MISSING_DEBUG;
      387 +                        break;
 384  388                  case 'o':
 385  389                          g_outfile = optarg;
 386  390                          break;
 387  391                  case 't':
 388      -                        g_req = B_TRUE;
      392 +                        /* Silently ignored for compatibility */
 389  393                          break;
 390  394                  case ':':
 391  395                          ctfmerge_usage("Option -%c requires an operand\n",
 392  396                              optopt);
 393  397                          return (CTFMERGE_USAGE);
 394  398                  case '?':
 395  399                          ctfmerge_usage("Unknown option: -%c\n", optopt);
 396  400                          return (CTFMERGE_USAGE);
 397  401                  }
 398  402          }
↓ open down ↓ 24 lines elided ↑ open up ↑
 423  427          cmh = ctf_merge_init(ofd, &err);
 424  428          if (cmh == NULL)
 425  429                  ctfmerge_fatal("failed to create merge handle: %s\n",
 426  430                      ctf_errmsg(err));
 427  431  
 428  432          if ((err = ctf_merge_set_nthreads(cmh, nthreads)) != 0)
 429  433                  ctfmerge_fatal("failed to set parallelism to %u: %s\n",
 430  434                      nthreads, ctf_errmsg(err));
 431  435  
 432  436          for (i = 0; i < argc; i++) {
 433      -                ctf_file_t *ifp;
 434      -                int fd;
 435      -
 436      -                if ((fd = open(argv[i], O_RDONLY)) < 0)
 437      -                        ctfmerge_fatal("failed to open file %s: %s\n",
 438      -                            argv[i], strerror(errno));
 439      -                ifp = ctf_fdopen(fd, &err);
 440      -                if (ifp == NULL) {
 441      -                        Elf *e;
 442      -
 443      -                        if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
 444      -                                (void) close(fd);
 445      -                                ctfmerge_fatal("failed to open %s: %s\n",
 446      -                                    argv[i], ctf_errmsg(err));
 447      -                        }
 448      -
 449      -                        /*
 450      -                         * It's an ELF file, check if we have an archive or if
 451      -                         * we're expecting CTF here.
 452      -                         */
 453      -                        switch (elf_kind(e)) {
 454      -                        case ELF_K_AR:
 455      -                                break;
 456      -                        case ELF_K_ELF:
 457      -                                if (ctfmerge_expect_ctf(argv[i], e) == B_TRUE) {
 458      -                                        (void) elf_end(e);
 459      -                                        (void) close(fd);
 460      -                                        ctfmerge_fatal("failed to "
 461      -                                            "open %s: file was built from C "
 462      -                                            "sources, but missing CTF\n",
 463      -                                            argv[i]);
 464      -                                }
 465      -                                (void) elf_end(e);
 466      -                                (void) close(fd);
 467      -                                continue;
 468      -                        default:
 469      -                                (void) elf_end(e);
 470      -                                (void) close(fd);
 471      -                                ctfmerge_fatal("failed to open %s: "
 472      -                                    "unsupported ELF file type", argv[i]);
 473      -                        }
 474      -
 475      -                        ctfmerge_read_archive(argv[i], fd, e, cmh);
 476      -                        (void) elf_end(e);
 477      -                        (void) close(fd);
 478      -                        continue;
 479      -                }
 480      -                (void) close(fd);
 481      -                if ((err = ctf_merge_add(cmh, ifp)) != 0)
 482      -                        ctfmerge_fatal("failed to add input %s: %s\n",
 483      -                            argv[i], ctf_errmsg(err));
 484      -                g_nctf++;
      437 +                ctfmerge_file_add(cmh, argv[i], flags);
 485  438          }
 486  439  
 487  440          if (g_nctf == 0) {
 488  441                  ctf_merge_fini(cmh);
 489  442                  return (0);
 490  443          }
 491  444  
 492  445          if (g_unique != NULL) {
 493  446                  ctf_file_t *ufp;
 494  447                  char *base;
↓ open down ↓ 42 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX