summaryrefslogtreecommitdiff
path: root/usr/src/lib/libctf/common
diff options
context:
space:
mode:
authorAndy Fiddaman <omnios@citrus-it.co.uk>2020-11-04 12:07:58 +0000
committerAndy Fiddaman <omnios@citrus-it.co.uk>2020-12-17 21:17:56 +0000
commitdd4422524768709a579a2a93a10c78a88a6b0ecb (patch)
tree7716bcc59f22cd4891503a8bc22e17710a774d28 /usr/src/lib/libctf/common
parent93d78aba5b32996fc2ae893a6237a0d3972f86b2 (diff)
downloadillumos-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.c121
-rw-r--r--usr/src/lib/libctf/common/ctf_dwarf.c191
-rw-r--r--usr/src/lib/libctf/common/libctf.h47
-rw-r--r--usr/src/lib/libctf/common/libctf_impl.h18
-rw-r--r--usr/src/lib/libctf/common/mapfile-vers8
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;