summaryrefslogtreecommitdiff
path: root/usr/src/lib/libctf
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2019-03-08 17:40:00 +0000
committerJohn Levon <john.levon@joyent.com>2019-04-02 08:56:25 +0000
commit495dfd0ac49c1326af24c839ba967d1e8264782d (patch)
treee9bc79ef1e9319e971ff31a62eb2ccca4033d9cd /usr/src/lib/libctf
parent8b607fd2753baed9c70e65eeda8ca3935dbe6077 (diff)
downloadillumos-joyent-495dfd0ac49c1326af24c839ba967d1e8264782d.tar.gz
OS-6428 bad free in ctf_dwarf_init_die
OS-6486 ctfconvert -i never converts OS-6488 ctfconvert should handle empty dies OS-6505 Improve ctfconvert error messages OS-7639 ctfconvert -i option is mis-handled OS-7663 ctf_dwarf_convert_type() relies on un-initialized id OS-7688 shouldn't build gcore.c as part of kmdb Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Approved by: Robert Mustacchi <rm@joyent.com>
Diffstat (limited to 'usr/src/lib/libctf')
-rw-r--r--usr/src/lib/libctf/common/ctf_convert.c136
-rw-r--r--usr/src/lib/libctf/common/ctf_dwarf.c260
-rw-r--r--usr/src/lib/libctf/common/libctf.h17
-rw-r--r--usr/src/lib/libctf/common/libctf_impl.h10
-rw-r--r--usr/src/lib/libctf/common/mapfile-vers3
5 files changed, 249 insertions, 177 deletions
diff --git a/usr/src/lib/libctf/common/ctf_convert.c b/usr/src/lib/libctf/common/ctf_convert.c
index 7190e66718..9441aa6ed7 100644
--- a/usr/src/lib/libctf/common/ctf_convert.c
+++ b/usr/src/lib/libctf/common/ctf_convert.c
@@ -21,6 +21,7 @@
*/
#include <libctf_impl.h>
+#include <assert.h>
#include <gelf.h>
ctf_convert_f ctf_converters[] = {
@@ -29,76 +30,73 @@ ctf_convert_f ctf_converters[] = {
#define NCONVERTS (sizeof (ctf_converters) / sizeof (ctf_convert_f))
-typedef enum ctf_convert_source {
- CTFCONV_SOURCE_NONE = 0x0,
- CTFCONV_SOURCE_UNKNOWN = 0x01,
- CTFCONV_SOURCE_C = 0x02,
- CTFCONV_SOURCE_S = 0x04
-} ctf_convert_source_t;
-
-static void
-ctf_convert_ftypes(Elf *elf, ctf_convert_source_t *types)
+ctf_hsc_ret_t
+ctf_has_c_source(Elf *elf, char *errmsg, size_t errlen)
{
- int i;
- Elf_Scn *scn = NULL, *strscn;
- *types = CTFCONV_SOURCE_NONE;
- GElf_Shdr shdr;
+ ctf_hsc_ret_t ret = CHR_NO_C_SOURCE;
+ Elf_Scn *scn, *strscn;
Elf_Data *data, *strdata;
+ GElf_Shdr shdr;
+ ulong_t i;
+ scn = NULL;
while ((scn = elf_nextscn(elf, scn)) != NULL) {
-
- if (gelf_getshdr(scn, &shdr) == NULL)
- return;
+ if (gelf_getshdr(scn, &shdr) == NULL) {
+ (void) snprintf(errmsg, errlen,
+ "failed to get section header: %s",
+ elf_errmsg(elf_errno()));
+ return (CHR_ERROR);
+ }
if (shdr.sh_type == SHT_SYMTAB)
break;
}
if (scn == NULL)
- return;
+ return (CHR_NO_C_SOURCE);
- if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL)
- return;
+ if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL) {
+ (void) snprintf(errmsg, errlen, "failed to get str section: %s",
+ elf_errmsg(elf_errno()));
+ return (CHR_ERROR);
+ }
- if ((data = elf_getdata(scn, NULL)) == NULL)
- return;
+ if ((data = elf_getdata(scn, NULL)) == NULL) {
+ (void) snprintf(errmsg, errlen, "failed to read section: %s",
+ elf_errmsg(elf_errno()));
+ return (CHR_ERROR);
+ }
- if ((strdata = elf_getdata(strscn, NULL)) == NULL)
- return;
+ if ((strdata = elf_getdata(strscn, NULL)) == NULL) {
+ (void) snprintf(errmsg, errlen,
+ "failed to read string table: %s", elf_errmsg(elf_errno()));
+ return (CHR_ERROR);
+ }
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)
- return;
+ if (gelf_getsym(data, i, &sym) == NULL) {
+ (void) snprintf(errmsg, errlen,
+ "failed to read sym %lu: %s",
+ i, elf_errmsg(elf_errno()));
+ return (CHR_ERROR);
+ }
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 || file[len - 2] != '.') {
- *types |= CTFCONV_SOURCE_UNKNOWN;
- continue;
- }
-
- switch (file[len - 1]) {
- case 'c':
- *types |= CTFCONV_SOURCE_C;
- break;
- case 'h':
- /* We traditionally ignore header files... */
- break;
- case 's':
- *types |= CTFCONV_SOURCE_S;
- break;
- default:
- *types |= CTFCONV_SOURCE_UNKNOWN;
+ if (len >= 2 && strncmp(".c", &file[len - 2], 2) == 0) {
+ ret = CHR_HAS_C_SOURCE;
break;
}
}
+
+ return (ret);
}
ctf_file_t *
@@ -107,8 +105,6 @@ ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t nthrs, uint_t flags,
{
int err, i;
ctf_file_t *fp = NULL;
- boolean_t notsup = B_TRUE;
- ctf_convert_source_t type;
if (errp == NULL)
errp = &err;
@@ -118,7 +114,7 @@ ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t nthrs, uint_t flags,
return (NULL);
}
- if (flags & ~CTF_CONVERT_F_IGNNONC) {
+ if (flags & ~CTF_ALLOW_MISSING_DEBUG) {
*errp = EINVAL;
return (NULL);
}
@@ -128,47 +124,35 @@ ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t nthrs, uint_t flags,
return (NULL);
}
- ctf_convert_ftypes(elf, &type);
- ctf_dprintf("got types: %d\n", type);
- if (flags & CTF_CONVERT_F_IGNNONC) {
- if (type == CTFCONV_SOURCE_NONE ||
- (type & CTFCONV_SOURCE_UNKNOWN)) {
- *errp = ECTF_CONVNOCSRC;
- return (NULL);
- }
+ switch (ctf_has_c_source(elf, errbuf, errlen)) {
+ case CHR_ERROR:
+ *errp = ECTF_ELF;
+ return (NULL);
+
+ case CHR_NO_C_SOURCE:
+ *errp = ECTF_CONVNOCSRC;
+ return (NULL);
+
+ default:
+ break;
}
for (i = 0; i < NCONVERTS; i++) {
- ctf_conv_status_t cs;
-
fp = NULL;
- cs = ctf_converters[i](fd, elf, nthrs, errp, &fp, errbuf,
- errlen);
- if (cs == CTF_CONV_SUCCESS) {
- notsup = B_FALSE;
- break;
- }
- if (cs == CTF_CONV_ERROR) {
- fp = NULL;
- notsup = B_FALSE;
+ err = ctf_converters[i](fd, elf, nthrs, flags,
+ &fp, errbuf, errlen);
+
+ if (err != ECTF_CONVNODEBUG)
break;
- }
}
- if (notsup == B_TRUE) {
- if ((flags & CTF_CONVERT_F_IGNNONC) != 0 &&
- (type & CTFCONV_SOURCE_C) == 0) {
- *errp = ECTF_CONVNOCSRC;
- return (NULL);
- }
- *errp = ECTF_NOCONVBKEND;
+ if (err != 0) {
+ assert(fp == NULL);
+ *errp = err;
return (NULL);
}
- /*
- * Succsesful conversion.
- */
- if (fp != NULL && label != NULL) {
+ if (label != NULL) {
if (ctf_add_label(fp, label, fp->ctf_typemax, 0) == CTF_ERR) {
*errp = ctf_errno(fp);
ctf_close(fp);
diff --git a/usr/src/lib/libctf/common/ctf_dwarf.c b/usr/src/lib/libctf/common/ctf_dwarf.c
index 7cd02db43c..aa55127d26 100644
--- a/usr/src/lib/libctf/common/ctf_dwarf.c
+++ b/usr/src/lib/libctf/common/ctf_dwarf.c
@@ -883,7 +883,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 unkown DWARF encoding: %d", type);
+ "encountered unknown DWARF encoding: %d", type);
return (ECTF_CONVBKERR);
}
@@ -1778,6 +1778,7 @@ ctf_dwarf_convert_type(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp,
break;
default:
ctf_dprintf("ignoring tag type %x\n", tag);
+ *idp = CTF_ERR;
ret = 0;
break;
}
@@ -2677,7 +2678,8 @@ ctf_dwarf_free_die(ctf_cu_t *cup)
}
ctf_dprintf("Trying to clean up dwarf_t: %p\n", cup->cu_dwarf);
- (void) dwarf_finish(cup->cu_dwarf, &derr);
+ if (cup->cu_dwarf != NULL)
+ (void) dwarf_finish(cup->cu_dwarf, &derr);
cup->cu_dwarf = NULL;
ctf_close(cup->cu_ctfp);
@@ -2727,13 +2729,6 @@ ctf_dwarf_count_dies(Dwarf_Debug dw, Dwarf_Error *derr, int *ndies,
*ndies = *ndies + 1;
}
- if (*ndies == 0) {
- (void) snprintf(errbuf, errlen,
- "file does not contain valid DWARF data: %s\n",
- dwarf_errmsg(*derr));
- return (ECTF_CONVBKERR);
- }
-
return (0);
}
@@ -2769,10 +2764,9 @@ ctf_dwarf_init_die(int fd, Elf *elf, ctf_cu_t *cup, int ndie, char *errbuf,
cup->cu_elf = elf;
cup->cu_maxoff = nexthdr - 1;
cup->cu_ctfp = ctf_fdcreate(fd, &ret);
- if (cup->cu_ctfp == NULL) {
- ctf_free(cup, sizeof (ctf_cu_t));
+ if (cup->cu_ctfp == NULL)
return (ret);
- }
+
avl_create(&cup->cu_map, ctf_dwmap_comp, sizeof (ctf_dwmap_t),
offsetof(ctf_dwmap_t, cdm_avl));
cup->cu_errbuf = errbuf;
@@ -2782,46 +2776,32 @@ ctf_dwarf_init_die(int fd, Elf *elf, ctf_cu_t *cup, int ndie, char *errbuf,
bzero(&cup->cu_bitfields, sizeof (ctf_list_t));
if ((ret = ctf_dwarf_die_elfenc(elf, cup, errbuf,
- errlen)) != 0) {
- avl_destroy(&cup->cu_map);
- ctf_free(cup, sizeof (ctf_cu_t));
+ errlen)) != 0)
return (ret);
- }
- if ((ret = ctf_dwarf_sib(cup, NULL, &cu)) != 0) {
- avl_destroy(&cup->cu_map);
- ctf_free(cup, sizeof (ctf_cu_t));
+ if ((ret = ctf_dwarf_sib(cup, NULL, &cu)) != 0)
return (ret);
- }
+
if (cu == NULL) {
(void) snprintf(errbuf, errlen,
- "file does not contain DWARF data\n");
- avl_destroy(&cup->cu_map);
- ctf_free(cup, sizeof (ctf_cu_t));
- return (ECTF_CONVBKERR);
+ "file does not contain DWARF data");
+ return (ECTF_CONVNODEBUG);
}
- if ((ret = ctf_dwarf_child(cup, cu, &child)) != 0) {
- avl_destroy(&cup->cu_map);
- ctf_free(cup, sizeof (ctf_cu_t));
+ if ((ret = ctf_dwarf_child(cup, cu, &child)) != 0)
return (ret);
- }
+
if (child == NULL) {
(void) snprintf(errbuf, errlen,
- "file does not contain DWARF data\n");
- avl_destroy(&cup->cu_map);
- ctf_free(cup, sizeof (ctf_cu_t));
- return (ECTF_CONVBKERR);
+ "file does not contain DWARF data");
+ return (ECTF_CONVNODEBUG);
}
cup->cu_cuoff = offset;
cup->cu_cu = child;
- if ((cup->cu_cmh = ctf_merge_init(fd, &ret)) == NULL) {
- avl_destroy(&cup->cu_map);
- ctf_free(cup, sizeof (ctf_cu_t));
+ if ((cup->cu_cmh = ctf_merge_init(fd, &ret)) == NULL)
return (ret);
- }
if (ctf_dwarf_string(cup, cu, DW_AT_name, &name) == 0) {
size_t len = strlen(name) + 1;
@@ -2835,41 +2815,143 @@ ctf_dwarf_init_die(int fd, Elf *elf, ctf_cu_t *cup, int ndie, char *errbuf,
return (0);
}
+/*
+ * This is our only recourse to identify a C source file that is missing debug
+ * info: it will be mentioned as an STT_FILE, but not have a compile unit entry.
+ * (A traditional ctfmerge works on individual files, so can identify missing
+ * DWARF more directly, via ctf_has_c_source() on the .o file.)
+ *
+ * As we operate on basenames, this can of course miss some cases, but it's
+ * better than not checking at all.
+ *
+ * We explicitly whitelist some CRT components. Failing that, there's always
+ * the -m option.
+ */
+static boolean_t
+c_source_has_debug(const char *file, ctf_cu_t *cus, size_t nr_cus)
+{
+ const char *basename = strrchr(file, '/');
+
+ if (basename == NULL)
+ basename = file;
+ else
+ basename++;
+
+ if (strcmp(basename, "common-crt.c") == 0 ||
+ strcmp(basename, "gmon.c") == 0 ||
+ strcmp(basename, "dlink_init.c") == 0 ||
+ strcmp(basename, "dlink_common.c") == 0 ||
+ strncmp(basename, "crt", strlen("crt")) == 0 ||
+ strncmp(basename, "values-", strlen("values-")) == 0)
+ return (B_TRUE);
-ctf_conv_status_t
-ctf_dwarf_convert(int fd, Elf *elf, uint_t nthrs, int *errp, ctf_file_t **fpp,
+ for (size_t i = 0; i < nr_cus; i++) {
+ if (strcmp(basename, cus[i].cu_name) == 0)
+ return (B_TRUE);
+ }
+
+ return (B_FALSE);
+}
+
+static int
+ctf_dwarf_check_missing(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;
+
+ scn = NULL;
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ if (gelf_getshdr(scn, &shdr) == NULL) {
+ (void) snprintf(errmsg, errlen,
+ "failed to get section header: %s\n",
+ elf_errmsg(elf_errno()));
+ return (EINVAL);
+ }
+
+ if (shdr.sh_type == SHT_SYMTAB)
+ break;
+ }
+
+ if (scn == NULL)
+ return (0);
+
+ if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL) {
+ (void) snprintf(errmsg, errlen,
+ "failed to get str section: %s\n",
+ elf_errmsg(elf_errno()));
+ return (EINVAL);
+ }
+
+ if ((data = elf_getdata(scn, NULL)) == NULL) {
+ (void) snprintf(errmsg, errlen, "failed to read section: %s\n",
+ elf_errmsg(elf_errno()));
+ return (EINVAL);
+ }
+
+ if ((strdata = elf_getdata(strscn, NULL)) == NULL) {
+ (void) snprintf(errmsg, errlen,
+ "failed to read string table: %s\n",
+ elf_errmsg(elf_errno()));
+ return (EINVAL);
+ }
+
+ 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) {
+ (void) snprintf(errmsg, errlen,
+ "failed to read sym %lu: %s\n",
+ i, elf_errmsg(elf_errno()));
+ return (EINVAL);
+ }
+
+ 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 || strncmp(".c", &file[len - 2], 2) != 0)
+ continue;
+
+ if (!c_source_has_debug(file, cus, nr_cus)) {
+ (void) snprintf(errmsg, errlen,
+ "file %s is missing debug info\n", file);
+ return (ECTF_CONVNODEBUG);
+ }
+ }
+
+ return (0);
+}
+
+int
+ctf_dwarf_convert(int fd, Elf *elf, uint_t nthrs, uint_t flags,
+ ctf_file_t **fpp, char *errbuf, size_t errlen)
+{
int err, ret, ndies, i;
Dwarf_Debug dw;
Dwarf_Error derr;
ctf_cu_t *cdies = NULL, *cup;
workq_t *wqp = NULL;
- if (errp == NULL)
- errp = &err;
- *errp = 0;
*fpp = NULL;
ret = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dw, &derr);
if (ret != DW_DLV_OK) {
- /*
- * We may want to expect DWARF data here and fail conversion if
- * it's missing. In this case, if we actually have some amount
- * of DWARF, but no section, for now, just go ahead and create
- * an empty CTF file.
- */
if (ret == DW_DLV_NO_ENTRY ||
dwarf_errno(derr) == DW_DLE_DEBUG_INFO_NULL) {
- *fpp = ctf_create(errp);
- return (*fpp != NULL ? CTF_CONV_SUCCESS :
- CTF_CONV_ERROR);
+ (void) snprintf(errbuf, errlen,
+ "file does not contain DWARF data\n");
+ return (ECTF_CONVNODEBUG);
}
- (void) snprintf(errmsg, errlen,
- "failed to initialize DWARF: %s\n",
- dwarf_errmsg(derr));
- *errp = ECTF_CONVBKERR;
- return (CTF_CONV_ERROR);
+
+ (void) snprintf(errbuf, errlen,
+ "dwarf_elf_init() failed: %s\n", dwarf_errmsg(derr));
+ return (ECTF_CONVBKERR);
}
/*
@@ -2880,42 +2962,47 @@ ctf_dwarf_convert(int fd, Elf *elf, uint_t nthrs, int *errp, ctf_file_t **fpp,
* only a single Dwarf_Debug as well.
*/
ndies = 0;
- ret = ctf_dwarf_count_dies(dw, &derr, &ndies, errmsg, errlen);
- if (ret != 0) {
- *errp = ret;
- goto out;
+ err = ctf_dwarf_count_dies(dw, &derr, &ndies, errbuf, errlen);
+
+ ctf_dprintf("found %d DWARF CUs\n", ndies);
+
+ if (ndies == 0) {
+ (void) snprintf(errbuf, errlen,
+ "file does not contain DWARF data\n");
+ return (ECTF_CONVNODEBUG);
}
(void) dwarf_finish(dw, &derr);
cdies = ctf_alloc(sizeof (ctf_cu_t) * ndies);
if (cdies == NULL) {
- *errp = ENOMEM;
- return (CTF_CONV_ERROR);
+ return (ENOMEM);
}
+ bzero(cdies, sizeof (ctf_cu_t) * ndies);
+
for (i = 0; i < ndies; i++) {
cup = &cdies[i];
ret = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL,
&cup->cu_dwarf, &derr);
if (ret != 0) {
ctf_free(cdies, sizeof (ctf_cu_t) * ndies);
- (void) snprintf(errmsg, errlen,
+ (void) snprintf(errbuf, errlen,
"failed to initialize DWARF: %s\n",
dwarf_errmsg(derr));
- *errp = ECTF_CONVBKERR;
- return (CTF_CONV_ERROR);
+ return (ECTF_CONVBKERR);
}
- ret = ctf_dwarf_init_die(fd, elf, &cdies[i], i, errmsg, errlen);
- if (ret != 0) {
- *errp = ret;
+ err = ctf_dwarf_init_die(fd, elf, cup, i, errbuf, errlen);
+ if (err != 0)
goto out;
- }
cup->cu_doweaks = ndies > 1 ? B_FALSE : B_TRUE;
}
- ctf_dprintf("found %d DWARF CUs\n", ndies);
+ if (!(flags & CTF_ALLOW_MISSING_DEBUG) &&
+ (err = ctf_dwarf_check_missing(cdies, ndies,
+ elf, errbuf, errlen)) != 0)
+ goto out;
/*
* If we only have one compilation unit, there's no reason to use
@@ -2926,7 +3013,7 @@ ctf_dwarf_convert(int fd, Elf *elf, uint_t nthrs, int *errp, ctf_file_t **fpp,
nthrs = 1;
if (workq_init(&wqp, nthrs) == -1) {
- *errp = errno;
+ err = errno;
goto out;
}
@@ -2935,18 +3022,18 @@ ctf_dwarf_convert(int fd, Elf *elf, uint_t nthrs, int *errp, ctf_file_t **fpp,
ctf_dprintf("adding cu %s: %p, %x %x\n", cup->cu_name,
cup->cu_cu, cup->cu_cuoff, cup->cu_maxoff);
if (workq_add(wqp, cup) == -1) {
- *errp = errno;
+ err = errno;
goto out;
}
}
- ret = workq_work(wqp, ctf_dwarf_convert_one, NULL, errp);
+ ret = workq_work(wqp, ctf_dwarf_convert_one, NULL, &err);
if (ret == WORKQ_ERROR) {
- *errp = errno;
+ err = errno;
goto out;
} else if (ret == WORKQ_UERROR) {
ctf_dprintf("internal convert failed: %s\n",
- ctf_errmsg(*errp));
+ ctf_errmsg(err));
goto out;
}
@@ -2954,44 +3041,37 @@ ctf_dwarf_convert(int fd, Elf *elf, uint_t nthrs, int *errp, ctf_file_t **fpp,
if (ndies != 1) {
ctf_merge_t *cmp;
- cmp = ctf_merge_init(fd, &ret);
- if (cmp == NULL) {
- *errp = ret;
+ cmp = ctf_merge_init(fd, &err);
+ if (cmp == NULL)
goto out;
- }
ctf_dprintf("setting threads\n");
- if ((ret = ctf_merge_set_nthreads(cmp, nthrs)) != 0) {
+ if ((err = ctf_merge_set_nthreads(cmp, nthrs)) != 0) {
ctf_merge_fini(cmp);
- *errp = ret;
goto out;
}
for (i = 0; i < ndies; i++) {
cup = &cdies[i];
- ctf_dprintf("adding cu %s (%p)\n", cup->cu_name,
- cup->cu_ctfp);
- if ((ret = ctf_merge_add(cmp, cup->cu_ctfp)) != 0) {
+ if ((err = ctf_merge_add(cmp, cup->cu_ctfp)) != 0) {
ctf_merge_fini(cmp);
- *errp = ret;
goto out;
}
}
ctf_dprintf("performing merge\n");
- ret = ctf_merge_merge(cmp, fpp);
- if (ret != 0) {
+ err = ctf_merge_merge(cmp, fpp);
+ if (err != 0) {
ctf_dprintf("failed merge!\n");
*fpp = NULL;
ctf_merge_fini(cmp);
- *errp = ret;
goto out;
}
ctf_merge_fini(cmp);
- *errp = 0;
+ err = 0;
ctf_dprintf("successfully converted!\n");
} else {
- *errp = 0;
+ err = 0;
*fpp = cdies->cu_ctfp;
cdies->cu_ctfp = NULL;
ctf_dprintf("successfully converted!\n");
@@ -3000,5 +3080,5 @@ ctf_dwarf_convert(int fd, Elf *elf, uint_t nthrs, int *errp, ctf_file_t **fpp,
out:
workq_fini(wqp);
ctf_dwarf_free_dies(cdies, ndies);
- return (*fpp != NULL ? CTF_CONV_SUCCESS : CTF_CONV_ERROR);
+ return (err);
}
diff --git a/usr/src/lib/libctf/common/libctf.h b/usr/src/lib/libctf/common/libctf.h
index a5c5027048..78b0a7a786 100644
--- a/usr/src/lib/libctf/common/libctf.h
+++ b/usr/src/lib/libctf/common/libctf.h
@@ -24,7 +24,7 @@
* Use is subject to license terms.
*/
/*
- * Copyright (c) 2015, Joyent, Inc.
+ * Copyright (c) 2019, Joyent, Inc.
*/
/*
@@ -75,12 +75,25 @@ 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 *);
-#define CTF_CONVERT_F_IGNNONC 0x01
+/*
+ * 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
+
extern ctf_file_t *ctf_elfconvert(int, Elf *, const char *, uint_t, uint_t,
int *, char *, size_t);
extern ctf_file_t *ctf_fdconvert(int, const char *, uint_t, uint_t, int *,
char *, size_t);
+typedef enum ctf_hsc_ret {
+ CHR_ERROR = -1,
+ CHR_NO_C_SOURCE = 0,
+ CHR_HAS_C_SOURCE = 1
+} ctf_hsc_ret_t;
+
+extern ctf_hsc_ret_t ctf_has_c_source(Elf *, char *, size_t);
+
typedef struct ctf_merge_handle ctf_merge_t;
extern ctf_merge_t *ctf_merge_init(int, int *);
extern int ctf_merge_add(ctf_merge_t *, ctf_file_t *);
diff --git a/usr/src/lib/libctf/common/libctf_impl.h b/usr/src/lib/libctf/common/libctf_impl.h
index be091ef199..5c88b9454d 100644
--- a/usr/src/lib/libctf/common/libctf_impl.h
+++ b/usr/src/lib/libctf/common/libctf_impl.h
@@ -29,15 +29,9 @@
extern "C" {
#endif
-typedef enum ctf_conv_status {
- CTF_CONV_SUCCESS = 0,
- CTF_CONV_ERROR = 1,
- CTF_CONV_NOTSUP = 2
-} ctf_conv_status_t;
-
-typedef ctf_conv_status_t (*ctf_convert_f)(int, Elf *, uint_t, int *,
+typedef int (*ctf_convert_f)(int, Elf *, uint_t, uint_t,
ctf_file_t **, char *, size_t);
-extern ctf_conv_status_t ctf_dwarf_convert(int, Elf *, uint_t, int *,
+extern int ctf_dwarf_convert(int, Elf *, uint_t, uint_t,
ctf_file_t **, char *, size_t);
/*
diff --git a/usr/src/lib/libctf/common/mapfile-vers b/usr/src/lib/libctf/common/mapfile-vers
index 243f072a3d..9281bbfff5 100644
--- a/usr/src/lib/libctf/common/mapfile-vers
+++ b/usr/src/lib/libctf/common/mapfile-vers
@@ -23,7 +23,7 @@
#
#
-# Copyright 2018 Joyent, Inc.
+# Copyright 2019 Joyent, Inc.
#
#
@@ -87,6 +87,7 @@ SYMBOL_VERSION SUNWprivate_1.2 {
ctf_func_args_by_id;
ctf_func_info_by_id;
ctf_function_iter;
+ ctf_has_c_source;
ctf_kind_name;
ctf_label_info;
ctf_label_iter;