diff options
author | Andy Fiddaman <omnios@citrus-it.co.uk> | 2020-11-04 12:07:58 +0000 |
---|---|---|
committer | Andy Fiddaman <omnios@citrus-it.co.uk> | 2020-12-17 21:17:56 +0000 |
commit | dd4422524768709a579a2a93a10c78a88a6b0ecb (patch) | |
tree | 7716bcc59f22cd4891503a8bc22e17710a774d28 /usr/src/lib/libctf/common | |
parent | 93d78aba5b32996fc2ae893a6237a0d3972f86b2 (diff) | |
download | illumos-joyent-dd4422524768709a579a2a93a10c78a88a6b0ecb.tar.gz |
13280 CTF: provide option to truncate and continue
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Reviewed by: Igor Kozhukhov <igor@dilos.org>
Approved by: Rich Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src/lib/libctf/common')
-rw-r--r-- | usr/src/lib/libctf/common/ctf_convert.c | 121 | ||||
-rw-r--r-- | usr/src/lib/libctf/common/ctf_dwarf.c | 191 | ||||
-rw-r--r-- | usr/src/lib/libctf/common/libctf.h | 47 | ||||
-rw-r--r-- | usr/src/lib/libctf/common/libctf_impl.h | 18 | ||||
-rw-r--r-- | usr/src/lib/libctf/common/mapfile-vers | 8 |
5 files changed, 290 insertions, 95 deletions
diff --git a/usr/src/lib/libctf/common/ctf_convert.c b/usr/src/lib/libctf/common/ctf_convert.c index a55c811386..b38831aa0e 100644 --- a/usr/src/lib/libctf/common/ctf_convert.c +++ b/usr/src/lib/libctf/common/ctf_convert.c @@ -11,12 +11,13 @@ /* * Copyright 2019 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ /* * Main conversion entry points. This has been designed such that there can be * any number of different conversion backends. Currently we only have one that - * understands DWARFv2 (and bits of DWARFv4). Each backend should be placed in + * understands DWARFv2 and DWARFv4. Each backend should be placed in * the ctf_converters list and each will be tried in turn. */ @@ -24,7 +25,7 @@ #include <assert.h> #include <gelf.h> -ctf_convert_f ctf_converters[] = { +static ctf_convert_f ctf_converters[] = { ctf_dwarf_convert }; @@ -100,8 +101,8 @@ ctf_has_c_source(Elf *elf, char *errmsg, size_t errlen) } static ctf_file_t * -ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t bsize, uint_t nthrs, - uint_t flags, int *errp, char *errbuf, size_t errlen) +ctf_elfconvert(ctf_convert_t *cch, int fd, Elf *elf, int *errp, char *errbuf, + size_t errlen) { int err, i; ctf_file_t *fp = NULL; @@ -114,11 +115,6 @@ ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t bsize, uint_t nthrs, return (NULL); } - if (flags & ~CTF_ALLOW_MISSING_DEBUG) { - *errp = EINVAL; - return (NULL); - } - if (elf_kind(elf) != ELF_K_ELF) { *errp = ECTF_FMT; return (NULL); @@ -139,8 +135,7 @@ ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t bsize, uint_t nthrs, for (i = 0; i < NCONVERTS; i++) { fp = NULL; - err = ctf_converters[i](fd, elf, bsize, nthrs, flags, - &fp, errbuf, errlen); + err = ctf_converters[i](cch, fd, elf, &fp, errbuf, errlen); if (err != ECTF_CONVNODEBUG) break; @@ -152,8 +147,9 @@ ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t bsize, uint_t nthrs, return (NULL); } - if (label != NULL) { - if (ctf_add_label(fp, label, fp->ctf_typemax, 0) == CTF_ERR) { + if (cch->cch_label != NULL) { + if (ctf_add_label(fp, cch->cch_label, fp->ctf_typemax, 0) == + CTF_ERR) { *errp = ctf_errno(fp); ctf_close(fp); return (NULL); @@ -168,9 +164,101 @@ ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t bsize, uint_t nthrs, return (fp); } +ctf_convert_t * +ctf_convert_init(int *errp) +{ + struct ctf_convert_handle *cch; + int err; + + if (errp == NULL) + errp = &err; + *errp = 0; + + cch = ctf_alloc(sizeof (struct ctf_convert_handle)); + if (cch == NULL) { + *errp = ENOMEM; + return (NULL); + } + + cch->cch_label = NULL; + cch->cch_flags = 0; + cch->cch_nthreads = CTF_CONVERT_DEFAULT_NTHREADS; + cch->cch_batchsize = CTF_CONVERT_DEFAULT_BATCHSIZE; + cch->cch_warncb = NULL; + cch->cch_warncb_arg = NULL; + + return (cch); +} + +void +ctf_convert_fini(ctf_convert_t *cch) +{ + if (cch->cch_label != NULL) { + size_t len = strlen(cch->cch_label) + 1; + ctf_free(cch->cch_label, len); + } + ctf_free(cch, sizeof (struct ctf_convert_handle)); +} + +int +ctf_convert_set_nthreads(ctf_convert_t *cch, uint_t nthrs) +{ + if (nthrs == 0) + return (EINVAL); + cch->cch_nthreads = nthrs; + return (0); +} + +int +ctf_convert_set_batchsize(ctf_convert_t *cch, uint_t bsize) +{ + if (bsize == 0) + return (EINVAL); + cch->cch_batchsize = bsize; + return (0); +} + +int +ctf_convert_set_flags(ctf_convert_t *cch, uint_t flags) +{ + if ((flags & ~CTF_CONVERT_ALL_FLAGS) != 0) + return (EINVAL); + cch->cch_flags = flags; + return (0); +} + +int +ctf_convert_set_label(ctf_convert_t *cch, const char *label) +{ + char *dup; + + if (label == NULL) + return (EINVAL); + + dup = ctf_strdup(label); + if (dup == NULL) + return (ENOMEM); + + if (cch->cch_label != NULL) { + size_t len = strlen(cch->cch_label) + 1; + ctf_free(cch->cch_label, len); + } + + cch->cch_label = dup; + return (0); +} + +int +ctf_convert_set_warncb(ctf_convert_t *cch, ctf_convert_warn_f cb, void *arg) +{ + cch->cch_warncb = cb; + cch->cch_warncb_arg = arg; + return (0); +} + ctf_file_t * -ctf_fdconvert(int fd, const char *label, uint_t bsize, uint_t nthrs, - uint_t flags, int *errp, char *errbuf, size_t errlen) +ctf_fdconvert(ctf_convert_t *cch, int fd, int *errp, + char *errbuf, size_t errlen) { int err; Elf *elf; @@ -185,8 +273,7 @@ ctf_fdconvert(int fd, const char *label, uint_t bsize, uint_t nthrs, return (NULL); } - fp = ctf_elfconvert(fd, elf, label, bsize, nthrs, flags, errp, errbuf, - errlen); + fp = ctf_elfconvert(cch, fd, elf, errp, errbuf, errlen); (void) elf_end(elf); return (fp); diff --git a/usr/src/lib/libctf/common/ctf_dwarf.c b/usr/src/lib/libctf/common/ctf_dwarf.c index 1618c8add4..6897dd3047 100644 --- a/usr/src/lib/libctf/common/ctf_dwarf.c +++ b/usr/src/lib/libctf/common/ctf_dwarf.c @@ -274,6 +274,7 @@ typedef struct ctf_die { avl_tree_t cu_map; /* map die offsets to CTF types */ char *cu_errbuf; /* error message buffer */ size_t cu_errlen; /* error message buffer length */ + ctf_convert_t *cu_handle; /* ctf convert handle */ size_t cu_ptrsz; /* object's pointer size */ boolean_t cu_bigend; /* is it big endian */ boolean_t cu_doweaks; /* should we convert weak symbols? */ @@ -485,7 +486,7 @@ ctf_dwarf_ref(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Half name, Dwarf_Off *refp) } (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "failed to get unsigned attribute for type: %s\n", + "failed to get attribute descriptor offset: %s\n", dwarf_errmsg(derr)); return (ECTF_CONVBKERR); } @@ -535,7 +536,7 @@ ctf_dwarf_signed(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Half name, } (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "failed to get unsigned attribute for type: %s\n", + "failed to get signed attribute for type: %s\n", dwarf_errmsg(derr)); return (ECTF_CONVBKERR); } @@ -649,7 +650,8 @@ ctf_dwarf_member_location(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Unsigned *valp) DWARF_UNLOCK(cup); if (ret != DW_DLV_OK) { (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "failed to get dwarf attribute for for member location: %s", + "failed to get dwarf attribute for for member " + "location: %s\n", dwarf_errmsg(derr)); ctf_dwarf_dealloc(cup, attr, DW_DLA_ATTR); return (ECTF_CONVBKERR); @@ -679,7 +681,7 @@ ctf_dwarf_member_location(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Unsigned *valp) if (sign < 0) { (void) snprintf(cup->cu_errbuf, cup->cu_errlen, "encountered negative member data " - "location: %d", sign); + "location: %d\n", sign); } *valp = (Dwarf_Unsigned)sign; return (0); @@ -689,7 +691,7 @@ ctf_dwarf_member_location(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Unsigned *valp) if (dwarf_loclist(attr, &loc, &locnum, &derr) != DW_DLV_OK) { DWARF_UNLOCK(cup); (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "failed to obtain location list for member offset: %s", + "failed to obtain location list for member offset: %s\n", dwarf_errmsg(derr)); ctf_dwarf_dealloc(cup, attr, DW_DLA_ATTR); return (ECTF_CONVBKERR); @@ -699,7 +701,7 @@ ctf_dwarf_member_location(ctf_cu_t *cup, Dwarf_Die die, Dwarf_Unsigned *valp) if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) { (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "failed to parse location structure for member"); + "failed to parse location structure for member\n"); ctf_dwarf_dealloc(cup, loc->ld_s, DW_DLA_LOC_BLOCK); ctf_dwarf_dealloc(cup, loc, DW_DLA_LOCDESC); return (ECTF_CONVBKERR); @@ -853,7 +855,7 @@ ctf_dwarf_die_elfenc(Elf *elf, ctf_cu_t *cup, char *errbuf, size_t errlen) VERIFY(ctf_setmodel(cup->cu_ctfp, CTF_MODEL_LP64) == 0); } else { (void) snprintf(errbuf, errlen, - "unknown ELF class %d", ehdr.e_ident[EI_CLASS]); + "unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]); return (ECTF_CONVBKERR); } @@ -863,7 +865,7 @@ ctf_dwarf_die_elfenc(Elf *elf, ctf_cu_t *cup, char *errbuf, size_t errlen) cup->cu_bigend = B_TRUE; } else { (void) snprintf(errbuf, errlen, - "unknown ELF data encoding: %hhu", ehdr.e_ident[EI_DATA]); + "unknown ELF data encoding: %hhu\n", ehdr.e_ident[EI_DATA]); return (ECTF_CONVBKERR); } @@ -1031,7 +1033,7 @@ ctf_dwarf_dwarf_base(ctf_cu_t *cup, Dwarf_Die die, int *kindp, break; default: (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "encountered unknown DWARF encoding: %d", type); + "encountered unknown DWARF encoding: %d\n", type); return (ECTF_CONVBKERR); } @@ -1230,7 +1232,7 @@ ctf_dwarf_member_offset(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t mid, if ((tsz = ctf_type_size(cup->cu_ctfp, mid)) == CTF_ERR) { int e = ctf_errno(cup->cu_ctfp); (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "failed to get type size: %s", ctf_errmsg(e)); + "failed to get type size: %s\n", ctf_errmsg(e)); return (ECTF_CONVBKERR); } } else { @@ -1350,7 +1352,7 @@ ctf_dwarf_member_bitfield(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp) name, &e); if (cdb->cdb_id == CTF_ERR) { (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "failed to get add bitfield type %s: %s", name, + "failed to get add bitfield type %s: %s\n", name, ctf_errmsg(ctf_errno(cup->cu_ctfp))); ctf_free(name, namesz + 1); ctf_free(cdb, sizeof (ctf_dwbitf_t)); @@ -1437,7 +1439,7 @@ ctf_dwarf_fixup_sou(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t base, boolean_t add) ret = ctf_add_member(cup->cu_ctfp, base, mname, mid, memboff); if (ret == CTF_ERR) { (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "failed to add member %s: %s", + "failed to add member %s: %s\n", mname, ctf_errmsg(ctf_errno(cup->cu_ctfp))); if (mname != NULL) ctf_free(mname, strlen(mname) + 1); @@ -1466,7 +1468,7 @@ next: if ((ctf_set_size(cup->cu_ctfp, base, size)) == CTF_ERR) { int e = ctf_errno(cup->cu_ctfp); (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "failed to set type size for %d to 0x%x: %s", base, + "failed to set type size for %d to 0x%x: %s\n", base, (uint32_t)size, ctf_errmsg(e)); return (ECTF_CONVBKERR); } @@ -1891,14 +1893,14 @@ ctf_dwarf_create_enum(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, int isroot) Dwarf_Die child; Dwarf_Unsigned dw; ctf_id_t id; - char *name; + char *enumname; int ret; - if ((ret = ctf_dwarf_string(cup, die, DW_AT_name, &name)) != 0 && - ret != ENOENT) + ret = ctf_dwarf_string(cup, die, DW_AT_name, &enumname); + if (ret != 0 && ret != ENOENT) return (ret); if (ret == ENOENT) - name = NULL; + enumname = NULL; /* * Enumerations may have a size associated with them, particularly if @@ -1910,20 +1912,21 @@ ctf_dwarf_create_enum(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, int isroot) size = (size_t)dw; } - id = ctf_add_enum(cup->cu_ctfp, isroot, name, size); - ctf_dprintf("added enum %s (%d)\n", name, id); - if (name != NULL) - ctf_free(name, strlen(name) + 1); - if (id == CTF_ERR) - return (ctf_errno(cup->cu_ctfp)); + id = ctf_add_enum(cup->cu_ctfp, isroot, enumname, size); + ctf_dprintf("added enum %s (%d)\n", + enumname == NULL ? "<anon>" : enumname, id); + if (id == CTF_ERR) { + ret = ctf_errno(cup->cu_ctfp); + goto out; + } *idp = id; if ((ret = ctf_dwmap_add(cup, id, die, B_FALSE)) != 0) - return (ret); + goto out; if ((ret = ctf_dwarf_child(cup, die, &child)) != 0) { if (ret == ENOENT) ret = 0; - return (ret); + goto out; } while (child != NULL) { @@ -1931,18 +1934,20 @@ ctf_dwarf_create_enum(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, int isroot) Dwarf_Signed sval; Dwarf_Unsigned uval; Dwarf_Die arg = child; + char *name; int eval; if ((ret = ctf_dwarf_sib(cup, arg, &child)) != 0) - return (ret); + break; if ((ret = ctf_dwarf_tag(cup, arg, &tag)) != 0) - return (ret); + break; if (tag != DW_TAG_enumerator) { if ((ret = ctf_dwarf_convert_type(cup, arg, NULL, - CTF_ADD_NONROOT)) != 0) - return (ret); + CTF_ADD_NONROOT)) != 0) { + break; + } continue; } @@ -1950,7 +1955,7 @@ ctf_dwarf_create_enum(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, int isroot) * DWARF v4 section 5.7 tells us we'll always have names. */ if ((ret = ctf_dwarf_string(cup, arg, DW_AT_name, &name)) != 0) - return (ret); + break; /* * We have to be careful here: newer GCCs generate DWARF where @@ -1961,32 +1966,62 @@ ctf_dwarf_create_enum(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, int isroot) if ((ret = ctf_dwarf_unsigned(cup, arg, DW_AT_const_value, &uval)) == 0) { eval = (int)uval; - } else if ((ret = ctf_dwarf_signed(cup, arg, DW_AT_const_value, - &sval)) == 0) { - eval = sval; + } else { + /* + * ctf_dwarf_unsigned will have left an error in the + * buffer + */ + *cup->cu_errbuf = '\0'; + + if ((ret = ctf_dwarf_signed(cup, arg, DW_AT_const_value, + &sval)) == 0) { + eval = sval; + } } if (ret != 0) { - if (ret != ENOENT) - return (ret); - - (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "encountered enumeration without constant value\n"); - return (ECTF_CONVBKERR); + if (ret == ENOENT) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "encountered enumeration without constant " + "value\n"); + ret = ECTF_CONVBKERR; + } + ctf_free(name, strlen(name) + 1); + break; } ret = ctf_add_enumerator(cup->cu_ctfp, id, name, eval); if (ret == CTF_ERR) { - (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "failed to add enumarator %s (%d) to %d\n", - name, eval, id); + ret = ctf_errno(cup->cu_ctfp); + + if (ret == ECTF_DTFULL && (cup->cu_handle->cch_flags & + CTF_ALLOW_TRUNCATION)) { + if (cup->cu_handle->cch_warncb != NULL) { + cup->cu_handle->cch_warncb( + cup->cu_handle->cch_warncb_arg, + "truncating enumeration %s at %s\n", + name, enumname == NULL ? "<anon>" : + enumname); + } + ret = 0; + } else { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to add enumerator %s (%d) " + "to %s (%d)\n", name, eval, + enumname == NULL ? "<anon>" : enumname, id); + } ctf_free(name, strlen(name) + 1); - return (ctf_errno(cup->cu_ctfp)); + break; } ctf_free(name, strlen(name) + 1); } - return (0); +out: + + if (enumname != NULL) + ctf_free(enumname, strlen(enumname) + 1); + + return (ret); } /* @@ -3124,9 +3159,9 @@ ctf_dwarf_count_dies(Dwarf_Debug dw, Dwarf_Error *derr, uint_t *ndies, * be able to finish the rest in a (potentially) multithreaded context. */ static int -ctf_dwarf_preinit_dies(int fd, Elf *elf, Dwarf_Debug dw, +ctf_dwarf_preinit_dies(ctf_convert_t *cch, int fd, Elf *elf, Dwarf_Debug dw, mutex_t *dwlock, Dwarf_Error *derr, uint_t ndies, ctf_cu_t *cdies, - uint_t flags, char *errbuf, size_t errlen) + char *errbuf, size_t errlen) { Dwarf_Unsigned hdrlen, abboff, nexthdr; Dwarf_Half addrsz, vers; @@ -3144,6 +3179,7 @@ ctf_dwarf_preinit_dies(int fd, Elf *elf, Dwarf_Debug dw, cup = &cdies[i++]; + cup->cu_handle = cch; cup->cu_fd = fd; cup->cu_elf = elf; cup->cu_dwarf = dw; @@ -3176,7 +3212,7 @@ ctf_dwarf_preinit_dies(int fd, Elf *elf, Dwarf_Debug dw, if (cu == NULL) { ctf_dprintf("cu %d - no cu data\n", i); (void) snprintf(cup->cu_errbuf, cup->cu_errlen, - "file does not contain DWARF data"); + "file does not contain DWARF data\n"); return (ECTF_CONVNODEBUG); } @@ -3212,13 +3248,20 @@ ctf_dwarf_preinit_dies(int fd, Elf *elf, Dwarf_Debug dw, * Missing DEBUG data for a .c file, return an * error unless this is permitted. */ - if (!(flags & CTF_ALLOW_MISSING_DEBUG)) { + if (!(cch->cch_flags & + CTF_ALLOW_MISSING_DEBUG)) { (void) snprintf( cup->cu_errbuf, cup->cu_errlen, - "file %s is missing debug info", + "missing debug information " + "(first seen in %s)\n", cup->cu_name); return (ECTF_CONVNODEBUG); } + if (cch->cch_warncb != NULL) { + cch->cch_warncb(cch->cch_warncb_arg, + "file %s is missing debug " + "information\n", cup->cu_name); + } } } else { added++; @@ -3304,13 +3347,14 @@ c_source_has_debug(const char *file, ctf_cu_t *cus, size_t nr_cus) } static int -ctf_dwarf_check_missing(ctf_cu_t *cus, size_t nr_cus, Elf *elf, - char *errmsg, size_t errlen) +ctf_dwarf_check_missing(ctf_convert_t *cch, ctf_cu_t *cus, size_t nr_cus, + Elf *elf, char *errmsg, size_t errlen) { Elf_Scn *scn, *strscn; Elf_Data *data, *strdata; GElf_Shdr shdr; ulong_t i; + int ret = 0; scn = NULL; while ((scn = elf_nextscn(elf, scn)) != NULL) { @@ -3369,13 +3413,22 @@ ctf_dwarf_check_missing(ctf_cu_t *cus, size_t nr_cus, Elf *elf, continue; if (!c_source_has_debug(file, cus, nr_cus)) { - (void) snprintf(errmsg, errlen, - "file %s is missing debug info", file); - return (ECTF_CONVNODEBUG); + if (cch->cch_warncb != NULL) { + cch->cch_warncb( + cch->cch_warncb_arg, + "file %s is missing debug information\n", + file); + } + if (ret != ECTF_CONVNODEBUG) { + (void) snprintf(errmsg, errlen, + "missing debug information " + "(first seen in %s)\n", file); + ret = ECTF_CONVNODEBUG; + } } } - return (0); + return (ret); } static int @@ -3488,11 +3541,11 @@ out: } int -ctf_dwarf_convert(int fd, Elf *elf, uint_t bsize, uint_t nthrs, uint_t flags, - ctf_file_t **fpp, char *errbuf, size_t errlen) +ctf_dwarf_convert(ctf_convert_t *cch, int fd, Elf *elf, ctf_file_t **fpp, + char *errbuf, size_t errlen) { int err, ret; - uint_t ndies, i; + uint_t ndies, i, bsize, nthrs; Dwarf_Debug dw; Dwarf_Error derr; ctf_cu_t *cdies = NULL, *cup; @@ -3542,15 +3595,21 @@ ctf_dwarf_convert(int fd, Elf *elf, uint_t bsize, uint_t nthrs, uint_t flags, bzero(cdies, sizeof (ctf_cu_t) * ndies); - if ((err = ctf_dwarf_preinit_dies(fd, elf, dw, &dwlock, &derr, - ndies, cdies, flags, errbuf, errlen)) != 0) { + if ((err = ctf_dwarf_preinit_dies(cch, fd, elf, dw, &dwlock, &derr, + ndies, cdies, errbuf, errlen)) != 0) { goto out; } - if (!(flags & CTF_ALLOW_MISSING_DEBUG) && - (err = ctf_dwarf_check_missing(cdies, ndies, - elf, errbuf, errlen)) != 0) { - goto out; + if ((err = ctf_dwarf_check_missing(cch, cdies, ndies, elf, + errbuf, errlen)) != 0) { + if (!(cch->cch_flags & CTF_ALLOW_MISSING_DEBUG)) { + goto out; + } + if (err != ECTF_CONVNODEBUG && *errbuf != '\0' && + cch->cch_warncb != NULL) { + cch->cch_warncb(cch->cch_warncb_arg, "%s", errbuf); + *errbuf = '\0'; + } } /* Only one cu, no merge required */ @@ -3570,8 +3629,8 @@ ctf_dwarf_convert(int fd, Elf *elf, uint_t bsize, uint_t nthrs, uint_t flags, * There's no need to have either more threads or a batch size larger * than the total number of dies, even if the user requested them. */ - nthrs = min(ndies, nthrs); - bsize = min(ndies, bsize); + nthrs = min(ndies, cch->cch_nthreads); + bsize = min(ndies, cch->cch_batchsize); if (workq_init(&wqp, nthrs) == -1) { err = errno; diff --git a/usr/src/lib/libctf/common/libctf.h b/usr/src/lib/libctf/common/libctf.h index 9ad878a107..5f0721e99f 100644 --- a/usr/src/lib/libctf/common/libctf.h +++ b/usr/src/lib/libctf/common/libctf.h @@ -25,6 +25,7 @@ */ /* * Copyright (c) 2019, Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ /* @@ -37,7 +38,7 @@ * In the meantime, be aware that any program linked with libctf in this * release of illumos is almost guaranteed to break in the next release. * - * In short, do not user this header file or libctf for any purpose. + * In short, do not use this header file or libctf for any purpose. */ #ifndef _LIBCTF_H @@ -75,14 +76,44 @@ extern int ctf_diff_functions(ctf_diff_t *, ctf_diff_func_f, void *); extern int ctf_diff_objects(ctf_diff_t *, ctf_diff_obj_f, void *); extern void ctf_diff_fini(ctf_diff_t *); -/* - * Normally, we return a failure if we find a C-derived compilation unit that - * lacks DWARF or CTF (as required). This flag over-rides this check. - */ -#define CTF_ALLOW_MISSING_DEBUG 0x01 +#define CTF_CONVERT_DEFAULT_BATCHSIZE 256 +#define CTF_CONVERT_DEFAULT_NTHREADS 4 + +typedef enum ctf_convert_flag { + /* + * Normally, we return a failure if we find a C-derived compilation + * unit that lacks DWARF or CTF (as required). This flag over-rides + * this check. + */ + CTF_ALLOW_MISSING_DEBUG = 0x01, + /* + * Normally, we return a failure if we can't fully convert a structure + * to CTF format, such as an enum with too many values. This flag + * allows us to continue and convert what we can. + */ + CTF_ALLOW_TRUNCATION = 0x02 +} ctf_convert_flag_t; + +#define CTF_CONVERT_ALL_FLAGS (CTF_ALLOW_MISSING_DEBUG | \ + CTF_ALLOW_TRUNCATION) + +/* opaque handle for ctfconvert functions */ +struct ctf_convert_handle; +typedef struct ctf_convert_handle ctf_convert_t; + +extern ctf_convert_t *ctf_convert_init(int *); +extern void ctf_convert_fini(ctf_convert_t *); + +typedef void (*ctf_convert_warn_f)(void *, const char *, ...); +/* Any warning callback must be MT-Safe if multiple threads are used */ +extern int ctf_convert_set_warncb(ctf_convert_t *, ctf_convert_warn_f, void *); +extern int ctf_convert_set_batchsize(ctf_convert_t *, uint_t); +extern int ctf_convert_set_flags(ctf_convert_t *, ctf_convert_flag_t); +extern int ctf_convert_set_label(ctf_convert_t *, const char *); +extern int ctf_convert_set_nthreads(ctf_convert_t *, uint_t); + +extern ctf_file_t *ctf_fdconvert(ctf_convert_t *, int, int *, char *, size_t); -extern ctf_file_t *ctf_fdconvert(int, const char *, uint_t, uint_t, uint_t, - int *, char *, size_t); typedef enum ctf_hsc_ret { CHR_ERROR = -1, diff --git a/usr/src/lib/libctf/common/libctf_impl.h b/usr/src/lib/libctf/common/libctf_impl.h index 0921a3ec1a..6ed2665d11 100644 --- a/usr/src/lib/libctf/common/libctf_impl.h +++ b/usr/src/lib/libctf/common/libctf_impl.h @@ -11,6 +11,7 @@ /* * Copyright 2019 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #ifndef _LIBCTF_IMPL_H @@ -29,10 +30,19 @@ extern "C" { #endif -typedef int (*ctf_convert_f)(int, Elf *, uint_t, uint_t, uint_t, - ctf_file_t **, char *, size_t); -extern int ctf_dwarf_convert(int, Elf *, uint_t, uint_t, uint_t, - ctf_file_t **, char *, size_t); +struct ctf_convert_handle { + char *cch_label; + uint_t cch_flags; + uint_t cch_nthreads; + uint_t cch_batchsize; + ctf_convert_warn_f cch_warncb; + void *cch_warncb_arg; +}; + +typedef int (*ctf_convert_f)(ctf_convert_t *, int, Elf *, ctf_file_t **, + char *, size_t); +extern int ctf_dwarf_convert(ctf_convert_t *, int, Elf *, ctf_file_t **, + char *, size_t); /* * Symbol walking diff --git a/usr/src/lib/libctf/common/mapfile-vers b/usr/src/lib/libctf/common/mapfile-vers index 37ef440ab3..9f5c408406 100644 --- a/usr/src/lib/libctf/common/mapfile-vers +++ b/usr/src/lib/libctf/common/mapfile-vers @@ -24,6 +24,7 @@ # # Copyright 2019 Joyent, Inc. +# Copyright 2020 OmniOS Community Edition (OmniOSce) Association. # # @@ -66,6 +67,13 @@ SYMBOL_VERSION SUNWprivate_1.2 { ctf_add_typedef; ctf_add_union; ctf_add_volatile; + ctf_convert_fini; + ctf_convert_init; + ctf_convert_set_batchsize; + ctf_convert_set_flags; + ctf_convert_set_label; + ctf_convert_set_nthreads; + ctf_convert_set_warncb; ctf_create; ctf_dataptr; ctf_delete_type; |