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>

*** 8,18 **** * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* ! * Copyright (c) 2017, Joyent, Inc. */ /* * merge CTF containers */ --- 8,18 ---- * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* ! * Copyright (c) 2019, Joyent, Inc. */ /* * merge CTF containers */
*** 36,46 **** #include <limits.h> static char *g_progname; static char *g_unique; static char *g_outfile; - static boolean_t g_req; static uint_t g_nctf; #define CTFMERGE_OK 0 #define CTFMERGE_FATAL 1 #define CTFMERGE_USAGE 2 --- 36,45 ----
*** 62,138 **** (void) unlink(g_outfile); exit(CTFMERGE_FATAL); } ! static boolean_t ! ctfmerge_expect_ctf(const char *name, Elf *elf) { ! Elf_Scn *scn, *strscn; ! Elf_Data *data, *strdata; ! GElf_Shdr shdr; ! ulong_t i; ! if (g_req == B_FALSE) ! return (B_FALSE); ! scn = NULL; ! while ((scn = elf_nextscn(elf, scn)) != NULL) { ! if (gelf_getshdr(scn, &shdr) == NULL) { ! ctfmerge_fatal("failed to get section header for file " ! "%s: %s\n", name, elf_errmsg(elf_errno())); ! } ! ! if (shdr.sh_type == SHT_SYMTAB) break; - } ! if (scn == NULL) ! return (B_FALSE); ! if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL) ! ctfmerge_fatal("failed to get section header for file %s: %s\n", ! name, elf_errmsg(elf_errno())); ! ! if ((data = elf_getdata(scn, NULL)) == NULL) ! ctfmerge_fatal("failed to read symbol table for %s: %s\n", ! name, elf_errmsg(elf_errno())); ! ! if ((strdata = elf_getdata(strscn, NULL)) == NULL) ! ctfmerge_fatal("failed to read string table for %s: %s\n", ! name, elf_errmsg(elf_errno())); ! ! 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) ! ctfmerge_fatal("failed to read symbol table entry %lu " ! "for %s: %s\n", i, name, elf_errmsg(elf_errno())); ! ! 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 || name[len - 2] != '.') ! continue; ! ! if (name[len - 1] == 'c') ! return (B_TRUE); } - - return (B_FALSE); } /* * Go through and construct enough information for this Elf Object to try and do * a ctf_bufopen(). */ ! static void ! ctfmerge_elfopen(const char *name, Elf *elf, ctf_merge_t *cmh) { GElf_Ehdr ehdr; GElf_Shdr shdr; Elf_Scn *scn; Elf_Data *ctf_data, *str_data, *sym_data; --- 61,103 ---- (void) unlink(g_outfile); exit(CTFMERGE_FATAL); } ! /* ! * We failed to find CTF for this file, check if it's OK. If we're not derived ! * from C, or we have the -m option, we let missing CTF pass. ! */ ! static void ! ctfmerge_check_for_c(const char *name, Elf *elf, uint_t flags) { ! char errmsg[1024]; ! if (flags & CTF_ALLOW_MISSING_DEBUG) ! return; ! switch (ctf_has_c_source(elf, errmsg, sizeof (errmsg))) { ! case CHR_ERROR: ! ctfmerge_fatal("failed to open %s: %s\n", name, errmsg); break; ! case CHR_NO_C_SOURCE: ! return; ! default: ! ctfmerge_fatal("failed to open %s: %s\n", name, ! ctf_errmsg(ECTF_NOCTFDATA)); ! break; } } /* * Go through and construct enough information for this Elf Object to try and do * a ctf_bufopen(). */ ! static int ! ctfmerge_elfopen(const char *name, Elf *elf, ctf_merge_t *cmh, uint_t flags) { GElf_Ehdr ehdr; GElf_Shdr shdr; Elf_Scn *scn; Elf_Data *ctf_data, *str_data, *sym_data;
*** 212,264 **** strsect.cts_data = str_data->d_buf; } } if (ctfsect.cts_type == SHT_NULL) { ! if (ctfmerge_expect_ctf(name, elf) == B_FALSE) ! return; ! ctfmerge_fatal("failed to open %s: %s\n", name, ! ctf_errmsg(ECTF_NOCTFDATA)); } if (symsect.cts_type != SHT_NULL && strsect.cts_type != SHT_NULL) { fp = ctf_bufopen(&ctfsect, &symsect, &strsect, &err); } else { fp = ctf_bufopen(&ctfsect, NULL, NULL, &err); } if (fp == NULL) { - if (ctfmerge_expect_ctf(name, elf) == B_TRUE) { ctfmerge_fatal("failed to open file %s: %s\n", name, ctf_errmsg(err)); } ! } else { if ((err = ctf_merge_add(cmh, fp)) != 0) { ctfmerge_fatal("failed to add input %s: %s\n", name, ctf_errmsg(err)); } g_nctf++; ! } } static void ctfmerge_read_archive(const char *name, int fd, Elf *elf, ! ctf_merge_t *cmh) { - Elf *aelf; Elf_Cmd cmd = ELF_C_READ; int cursec = 1; ! char *nname; while ((aelf = elf_begin(fd, cmd, elf)) != NULL) { Elf_Arhdr *arhdr; - boolean_t leakelf = B_FALSE; if ((arhdr = elf_getarhdr(aelf)) == NULL) ctfmerge_fatal("failed to get archive header %d for " "%s: %s\n", cursec, name, elf_errmsg(elf_errno())); if (*(arhdr->ar_name) == '/') goto next; if (asprintf(&nname, "%s.%s.%d", name, arhdr->ar_name, cursec) < 0) --- 177,228 ---- strsect.cts_data = str_data->d_buf; } } if (ctfsect.cts_type == SHT_NULL) { ! ctfmerge_check_for_c(name, elf, flags); ! return (ENOENT); } if (symsect.cts_type != SHT_NULL && strsect.cts_type != SHT_NULL) { fp = ctf_bufopen(&ctfsect, &symsect, &strsect, &err); } else { fp = ctf_bufopen(&ctfsect, NULL, NULL, &err); } if (fp == NULL) { ctfmerge_fatal("failed to open file %s: %s\n", name, ctf_errmsg(err)); } ! if ((err = ctf_merge_add(cmh, fp)) != 0) { ctfmerge_fatal("failed to add input %s: %s\n", name, ctf_errmsg(err)); } + g_nctf++; ! return (0); } static void ctfmerge_read_archive(const char *name, int fd, Elf *elf, ! ctf_merge_t *cmh, uint_t flags) { Elf_Cmd cmd = ELF_C_READ; int cursec = 1; ! Elf *aelf; while ((aelf = elf_begin(fd, cmd, elf)) != NULL) { + char *nname = NULL; Elf_Arhdr *arhdr; if ((arhdr = elf_getarhdr(aelf)) == NULL) ctfmerge_fatal("failed to get archive header %d for " "%s: %s\n", cursec, name, elf_errmsg(elf_errno())); + cmd = elf_next(aelf); + if (*(arhdr->ar_name) == '/') goto next; if (asprintf(&nname, "%s.%s.%d", name, arhdr->ar_name, cursec) < 0)
*** 265,296 **** ctfmerge_fatal("failed to allocate memory for archive " "%d of file %s\n", cursec, name); switch (elf_kind(aelf)) { case ELF_K_AR: ! ctfmerge_read_archive(nname, fd, aelf, cmh); ! free(nname); break; case ELF_K_ELF: ! ctfmerge_elfopen(nname, aelf, cmh); ! free(nname); ! leakelf = B_TRUE; break; default: ctfmerge_fatal("unknown elf kind (%d) in archive %d " "for %s\n", elf_kind(aelf), cursec, name); } next: - cmd = elf_next(aelf); - if (leakelf == B_FALSE) (void) elf_end(aelf); cursec++; } } static void ctfmerge_usage(const char *fmt, ...) { if (fmt != NULL) { va_list ap; --- 229,296 ---- ctfmerge_fatal("failed to allocate memory for archive " "%d of file %s\n", cursec, name); switch (elf_kind(aelf)) { case ELF_K_AR: ! ctfmerge_read_archive(nname, fd, aelf, cmh, flags); break; case ELF_K_ELF: ! /* ctfmerge_elfopen() takes ownership of aelf. */ ! if (ctfmerge_elfopen(nname, aelf, cmh, flags) == 0) ! aelf = NULL; break; default: ctfmerge_fatal("unknown elf kind (%d) in archive %d " "for %s\n", elf_kind(aelf), cursec, name); + break; } next: (void) elf_end(aelf); + free(nname); cursec++; } } static void + ctfmerge_file_add(ctf_merge_t *cmh, const char *file, uint_t flags) + { + Elf *e; + int fd; + + if ((fd = open(file, O_RDONLY)) < 0) { + ctfmerge_fatal("failed to open file %s: %s\n", + file, strerror(errno)); + } + + if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { + (void) close(fd); + ctfmerge_fatal("failed to open %s: %s\n", + file, elf_errmsg(elf_errno())); + } + + switch (elf_kind(e)) { + case ELF_K_AR: + ctfmerge_read_archive(file, fd, e, cmh, flags); + break; + + case ELF_K_ELF: + /* ctfmerge_elfopen() takes ownership of e. */ + if (ctfmerge_elfopen(file, e, cmh, flags) == 0) + e = NULL; + break; + + default: + ctfmerge_fatal("unknown elf kind (%d) for %s\n", + elf_kind(e), file); + } + + (void) elf_end(e); + (void) close(fd); + } + + static void ctfmerge_usage(const char *fmt, ...) { if (fmt != NULL) { va_list ap;
*** 298,316 **** va_start(ap, fmt); (void) vfprintf(stderr, fmt, ap); va_end(ap); } ! (void) fprintf(stderr, "Usage: %s [-t] [-d uniqfile] [-l label] " "[-L labelenv] [-j nthrs] -o outfile file ...\n" "\n" "\t-d uniquify merged output against uniqfile\n" "\t-j use nthrs threads to perform the merge\n" "\t-l set output container's label to specified value\n" "\t-L set output container's label to value from environment\n" ! "\t-o file to add CTF data to\n" ! "\t-t require CTF data from all inputs built from C sources\n", g_progname); } static void ctfmerge_altexec(char **argv) --- 298,316 ---- va_start(ap, fmt); (void) vfprintf(stderr, fmt, ap); va_end(ap); } ! (void) fprintf(stderr, "Usage: %s [-m] [-d uniqfile] [-l label] " "[-L labelenv] [-j nthrs] -o outfile file ...\n" "\n" "\t-d uniquify merged output against uniqfile\n" "\t-j use nthrs threads to perform the merge\n" "\t-l set output container's label to specified value\n" "\t-L set output container's label to value from environment\n" ! "\t-m allow C-based input files to not have CTF\n" ! "\t-o file to add CTF data to\n", g_progname); } static void ctfmerge_altexec(char **argv)
*** 339,362 **** { int err, i, c, ofd; uint_t nthreads = CTFMERGE_DEFAULT_NTHREADS; char *tmpfile = NULL, *label = NULL; int wflags = CTF_ELFWRITE_F_COMPRESS; ! ctf_file_t *ofp; ctf_merge_t *cmh; long argj; char *eptr; g_progname = basename(argv[0]); ctfmerge_altexec(argv); /* * We support a subset of the old CTF merge flags, mostly for ! * compatability. */ ! while ((c = getopt(argc, argv, ":d:fgj:l:L:o:t")) != -1) { switch (c) { case 'd': g_unique = optarg; break; case 'f': --- 339,363 ---- { int err, i, c, ofd; uint_t nthreads = CTFMERGE_DEFAULT_NTHREADS; char *tmpfile = NULL, *label = NULL; int wflags = CTF_ELFWRITE_F_COMPRESS; ! uint_t flags = 0; ctf_merge_t *cmh; + ctf_file_t *ofp; long argj; char *eptr; g_progname = basename(argv[0]); ctfmerge_altexec(argv); /* * We support a subset of the old CTF merge flags, mostly for ! * compatibility. */ ! while ((c = getopt(argc, argv, ":d:fgj:l:L:mo:t")) != -1) { switch (c) { case 'd': g_unique = optarg; break; case 'f':
*** 379,393 **** label = optarg; break; case 'L': label = getenv(optarg); break; case 'o': g_outfile = optarg; break; case 't': ! g_req = B_TRUE; break; case ':': ctfmerge_usage("Option -%c requires an operand\n", optopt); return (CTFMERGE_USAGE); --- 380,397 ---- label = optarg; break; case 'L': label = getenv(optarg); break; + case 'm': + flags |= CTF_ALLOW_MISSING_DEBUG; + break; case 'o': g_outfile = optarg; break; case 't': ! /* Silently ignored for compatibility */ break; case ':': ctfmerge_usage("Option -%c requires an operand\n", optopt); return (CTFMERGE_USAGE);
*** 428,491 **** if ((err = ctf_merge_set_nthreads(cmh, nthreads)) != 0) ctfmerge_fatal("failed to set parallelism to %u: %s\n", nthreads, ctf_errmsg(err)); for (i = 0; i < argc; i++) { ! ctf_file_t *ifp; ! int fd; ! ! if ((fd = open(argv[i], O_RDONLY)) < 0) ! ctfmerge_fatal("failed to open file %s: %s\n", ! argv[i], strerror(errno)); ! ifp = ctf_fdopen(fd, &err); ! if (ifp == NULL) { ! Elf *e; ! ! if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { ! (void) close(fd); ! ctfmerge_fatal("failed to open %s: %s\n", ! argv[i], ctf_errmsg(err)); } - /* - * It's an ELF file, check if we have an archive or if - * we're expecting CTF here. - */ - switch (elf_kind(e)) { - case ELF_K_AR: - break; - case ELF_K_ELF: - if (ctfmerge_expect_ctf(argv[i], e) == B_TRUE) { - (void) elf_end(e); - (void) close(fd); - ctfmerge_fatal("failed to " - "open %s: file was built from C " - "sources, but missing CTF\n", - argv[i]); - } - (void) elf_end(e); - (void) close(fd); - continue; - default: - (void) elf_end(e); - (void) close(fd); - ctfmerge_fatal("failed to open %s: " - "unsupported ELF file type", argv[i]); - } - - ctfmerge_read_archive(argv[i], fd, e, cmh); - (void) elf_end(e); - (void) close(fd); - continue; - } - (void) close(fd); - if ((err = ctf_merge_add(cmh, ifp)) != 0) - ctfmerge_fatal("failed to add input %s: %s\n", - argv[i], ctf_errmsg(err)); - g_nctf++; - } - if (g_nctf == 0) { ctf_merge_fini(cmh); return (0); } --- 432,444 ---- if ((err = ctf_merge_set_nthreads(cmh, nthreads)) != 0) ctfmerge_fatal("failed to set parallelism to %u: %s\n", nthreads, ctf_errmsg(err)); for (i = 0; i < argc; i++) { ! ctfmerge_file_add(cmh, argv[i], flags); } if (g_nctf == 0) { ctf_merge_fini(cmh); return (0); }