summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/cmd/ctfconvert/ctfconvert.c38
-rw-r--r--usr/src/lib/libctf/common/ctf_convert.c13
-rw-r--r--usr/src/lib/libctf/common/ctf_dwarf.c370
-rw-r--r--usr/src/lib/libctf/common/libctf.h4
-rw-r--r--usr/src/lib/libctf/common/libctf_impl.h4
5 files changed, 251 insertions, 178 deletions
diff --git a/usr/src/cmd/ctfconvert/ctfconvert.c b/usr/src/cmd/ctfconvert/ctfconvert.c
index a4394c3ec8..dbcf688657 100644
--- a/usr/src/cmd/ctfconvert/ctfconvert.c
+++ b/usr/src/cmd/ctfconvert/ctfconvert.c
@@ -37,6 +37,7 @@
#define CTFCONVERT_FATAL 1
#define CTFCONVERT_USAGE 2
+#define CTFCONVERT_DEFAULT_BATCHSIZE 256
#define CTFCONVERT_DEFAULT_NTHREADS 4
#define CTFCONVERT_ALTEXEC "CTFCONVERT_ALTEXEC"
@@ -70,15 +71,18 @@ ctfconvert_usage(const char *fmt, ...)
}
(void) fprintf(stderr, "Usage: %s [-is] [-j nthrs] [-l label | "
- "-L labelenv] [-o outfile] input\n"
+ "-L labelenv] [-b batchsize] [-o outfile] input\n"
"\n"
"\t-i ignore files not built partially from C sources\n"
- "\t-j use nthrs threads to perform the merge\n"
+ "\t-b batch process this many dies at a time (default %d)\n"
+ "\t-j use nthrs threads to perform the merge (default %d)\n"
"\t-k keep around original input file on failure\n"
"\t-o copy input to outfile and add CTF\n"
"\t-l set output container's label to specified value\n"
"\t-L set output container's label to value from environment\n",
- ctfconvert_progname);
+ ctfconvert_progname,
+ CTFCONVERT_DEFAULT_BATCHSIZE,
+ CTFCONVERT_DEFAULT_NTHREADS);
}
/*
@@ -249,13 +253,14 @@ main(int argc, char *argv[])
int c, ifd, err;
boolean_t keep = B_FALSE;
uint_t flags = 0;
+ uint_t bsize = CTFCONVERT_DEFAULT_BATCHSIZE;
uint_t nthreads = CTFCONVERT_DEFAULT_NTHREADS;
const char *outfile = NULL;
const char *label = NULL;
const char *infile = NULL;
char *tmpfile;
ctf_file_t *ofp;
- long argj;
+ long argno;
char *eptr;
char buf[4096];
boolean_t optx = B_FALSE;
@@ -264,7 +269,7 @@ main(int argc, char *argv[])
ctfconvert_altexec(argv);
- while ((c = getopt(argc, argv, ":j:kl:L:o:iX")) != -1) {
+ while ((c = getopt(argc, argv, ":b:j:kl:L:o:iX")) != -1) {
switch (c) {
case 'k':
keep = B_TRUE;
@@ -275,16 +280,27 @@ main(int argc, char *argv[])
case 'L':
label = getenv(optarg);
break;
+ case 'b':
+ errno = 0;
+ argno = strtol(optarg, &eptr, 10);
+ if (errno != 0 || argno == LONG_MAX ||
+ argno == LONG_MIN || argno <= 0 ||
+ argno > UINT_MAX || *eptr != '\0') {
+ ctfconvert_fatal("invalid argument for -b: "
+ "%s\n", optarg);
+ }
+ bsize = (uint_t)argno;
+ break;
case 'j':
errno = 0;
- argj = strtol(optarg, &eptr, 10);
- if (errno != 0 || argj == LONG_MAX ||
- argj == LONG_MIN || argj <= 0 ||
- argj > UINT_MAX || *eptr != '\0') {
+ argno = strtol(optarg, &eptr, 10);
+ if (errno != 0 || argno == LONG_MAX ||
+ argno == LONG_MIN || argno <= 0 ||
+ argno > UINT_MAX || *eptr != '\0') {
ctfconvert_fatal("invalid argument for -j: "
"%s\n", optarg);
}
- nthreads = (uint_t)argj;
+ nthreads = (uint_t)argno;
break;
case 'o':
outfile = optarg;
@@ -331,7 +347,7 @@ main(int argc, char *argv[])
if (outfile != NULL && strcmp(infile, outfile) != 0)
keep = B_TRUE;
- ofp = ctf_fdconvert(ifd, label, nthreads, flags, &err, buf,
+ ofp = ctf_fdconvert(ifd, label, bsize, nthreads, flags, &err, buf,
sizeof (buf));
if (ofp == NULL) {
/*
diff --git a/usr/src/lib/libctf/common/ctf_convert.c b/usr/src/lib/libctf/common/ctf_convert.c
index 1a433d17db..042cdf9b72 100644
--- a/usr/src/lib/libctf/common/ctf_convert.c
+++ b/usr/src/lib/libctf/common/ctf_convert.c
@@ -102,8 +102,8 @@ ctf_convert_ftypes(Elf *elf, ctf_convert_source_t *types)
}
ctf_file_t *
-ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t nthrs, uint_t flags,
- int *errp, char *errbuf, size_t errlen)
+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)
{
int err, i;
ctf_file_t *fp = NULL;
@@ -142,7 +142,7 @@ ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t nthrs, uint_t flags,
ctf_conv_status_t cs;
fp = NULL;
- cs = ctf_converters[i](fd, elf, nthrs, errp, &fp, errbuf,
+ cs = ctf_converters[i](fd, elf, bsize, nthrs, errp, &fp, errbuf,
errlen);
if (cs == CTF_CONV_SUCCESS) {
notsup = B_FALSE;
@@ -187,8 +187,8 @@ ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t nthrs, uint_t flags,
}
ctf_file_t *
-ctf_fdconvert(int fd, const char *label, uint_t nthrs, uint_t flags, int *errp,
- char *errbuf, size_t errlen)
+ctf_fdconvert(int fd, const char *label, uint_t bsize, uint_t nthrs,
+ uint_t flags, int *errp, char *errbuf, size_t errlen)
{
int err;
Elf *elf;
@@ -203,7 +203,8 @@ ctf_fdconvert(int fd, const char *label, uint_t nthrs, uint_t flags, int *errp,
return (NULL);
}
- fp = ctf_elfconvert(fd, elf, label, nthrs, flags, errp, errbuf, errlen);
+ fp = ctf_elfconvert(fd, elf, label, bsize, nthrs, flags, 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 811a55bc64..e75db3b883 100644
--- a/usr/src/lib/libctf/common/ctf_dwarf.c
+++ b/usr/src/lib/libctf/common/ctf_dwarf.c
@@ -252,6 +252,8 @@ typedef struct ctf_dwbitf {
*/
typedef struct ctf_die {
Elf *cd_elf; /* shared libelf handle */
+ int cd_fd; /* shared file descriptor */
+ int cd_ndie; /* DIE index */
char *cd_name; /* basename of the DIE */
ctf_merge_t *cd_cmh; /* merge handle */
ctf_list_t cd_vars; /* List of variables */
@@ -2495,92 +2497,6 @@ ctf_dwarf_conv_weaks(ctf_die_t *cdp)
return (ctf_dwarf_symtab_iter(cdp, ctf_dwarf_conv_weaks_cb, NULL));
}
-/* ARGSUSED */
-static int
-ctf_dwarf_convert_one(void *arg, void *unused)
-{
- int ret;
- ctf_file_t *dedup;
- ctf_die_t *cdp = arg;
-
- ctf_dprintf("converting die: %s\n", cdp->cd_name);
- ctf_dprintf("max offset: %x\n", cdp->cd_maxoff);
- VERIFY(cdp != NULL);
-
- ret = ctf_dwarf_convert_die(cdp, cdp->cd_cu);
- ctf_dprintf("ctf_dwarf_convert_die (%s) returned %d\n", cdp->cd_name,
- ret);
- if (ret != 0) {
- return (ret);
- }
- if (ctf_update(cdp->cd_ctfp) != 0) {
- return (ctf_dwarf_error(cdp, cdp->cd_ctfp, 0,
- "failed to update output ctf container"));
- }
-
- ret = ctf_dwarf_fixup_die(cdp, B_FALSE);
- ctf_dprintf("ctf_dwarf_fixup_die (%s) returned %d\n", cdp->cd_name,
- ret);
- if (ret != 0) {
- return (ret);
- }
- if (ctf_update(cdp->cd_ctfp) != 0) {
- return (ctf_dwarf_error(cdp, cdp->cd_ctfp, 0,
- "failed to update output ctf container"));
- }
-
- ret = ctf_dwarf_fixup_die(cdp, B_TRUE);
- ctf_dprintf("ctf_dwarf_fixup_die (%s) returned %d\n", cdp->cd_name,
- ret);
- if (ret != 0) {
- return (ret);
- }
- if (ctf_update(cdp->cd_ctfp) != 0) {
- return (ctf_dwarf_error(cdp, cdp->cd_ctfp, 0,
- "failed to update output ctf container"));
- }
-
-
- if ((ret = ctf_dwarf_conv_funcvars(cdp)) != 0) {
- return (ctf_dwarf_error(cdp, NULL, ret,
- "failed to convert strong functions and variables"));
- }
-
- if (ctf_update(cdp->cd_ctfp) != 0) {
- return (ctf_dwarf_error(cdp, cdp->cd_ctfp, 0,
- "failed to update output ctf container"));
- }
-
- if (cdp->cd_doweaks == B_TRUE) {
- if ((ret = ctf_dwarf_conv_weaks(cdp)) != 0) {
- return (ctf_dwarf_error(cdp, NULL, ret,
- "failed to convert weak functions and variables"));
- }
-
- if (ctf_update(cdp->cd_ctfp) != 0) {
- return (ctf_dwarf_error(cdp, cdp->cd_ctfp, 0,
- "failed to update output ctf container"));
- }
- }
-
- ctf_phase_dump(cdp->cd_ctfp, "pre-dedup");
- ctf_dprintf("adding inputs for dedup\n");
- if ((ret = ctf_merge_add(cdp->cd_cmh, cdp->cd_ctfp)) != 0) {
- return (ctf_dwarf_error(cdp, NULL, ret,
- "failed to add inputs for merge"));
- }
-
- ctf_dprintf("starting merge\n");
- if ((ret = ctf_merge_dedup(cdp->cd_cmh, &dedup)) != 0) {
- return (ctf_dwarf_error(cdp, NULL, ret,
- "failed to deduplicate die"));
- }
- ctf_close(cdp->cd_ctfp);
- cdp->cd_ctfp = dedup;
-
- return (0);
-}
-
/*
* Note, we expect that if we're returning a ctf_file_t from one of the dies,
* say in the single node case, it's been saved and the entry here has been set
@@ -2594,7 +2510,6 @@ ctf_dwarf_free_die(ctf_die_t *cdp)
ctf_dwbitf_t *cdb, *ndb;
ctf_dwmap_t *map;
void *cookie;
- Dwarf_Error derr;
ctf_dprintf("Beginning to free die: %p\n", cdp);
cdp->cd_elf = NULL;
@@ -2631,10 +2546,6 @@ ctf_dwarf_free_die(ctf_die_t *cdp)
ctf_free(cdb, sizeof (ctf_dwbitf_t));
}
- /* How do we clean up die usage? */
- ctf_dprintf("Trying to clean up dwarf_t: %p\n", cdp->cd_dwarf);
- (void) dwarf_finish(cdp->cd_dwarf, &derr);
- cdp->cd_dwarf = NULL;
ctf_close(cdp->cd_ctfp);
cookie = NULL;
@@ -2700,24 +2611,41 @@ ctf_dwarf_count_dies(Dwarf_Debug dw, Dwarf_Error *derr, int *ndies,
* No merge needed and only a single Dwarf_Debug as well.
*/
static int
-ctf_dwarf_init_die(int fd, Elf *elf, ctf_die_t *cdp, int ndie, char *errbuf,
- size_t errlen)
+ctf_dwarf_init_die(ctf_die_t *cdp)
{
- int ret;
+ int ret, n;
Dwarf_Unsigned hdrlen, abboff, nexthdr;
Dwarf_Half addrsz;
Dwarf_Unsigned offset = 0;
Dwarf_Error derr;
+ ret = dwarf_elf_init(cdp->cd_elf, DW_DLC_READ, NULL, NULL,
+ &cdp->cd_dwarf, &derr);
+ if (ret != DW_DLV_OK) {
+ (void) snprintf(cdp->cd_errbuf, cdp->cd_errlen,
+ "failed to initialize DWARF: %s\n",
+ dwarf_errmsg(derr));
+ return (ECTF_CONVBKERR);
+ }
+
+ n = cdp->cd_ndie;
+
while ((ret = dwarf_next_cu_header(cdp->cd_dwarf, &hdrlen, NULL,
&abboff, &addrsz, &nexthdr, &derr)) != DW_DLV_NO_ENTRY) {
char *name;
Dwarf_Die cu, child;
+ if (ret != DW_DLV_OK) {
+ (void) snprintf(cdp->cd_errbuf, cdp->cd_errlen,
+ "failed to read DWARF: %s\n",
+ dwarf_errmsg(derr));
+ return (ECTF_CONVBKERR);
+ }
+
/* Based on the counting above, we should be good to go */
VERIFY(ret == DW_DLV_OK);
- if (ndie > 0) {
- ndie--;
+ if (n > 0) {
+ n--;
offset = nexthdr;
continue;
}
@@ -2728,23 +2656,20 @@ ctf_dwarf_init_die(int fd, Elf *elf, ctf_die_t *cdp, int ndie, char *errbuf,
*/
cdp->cd_voidtid = CTF_ERR;
cdp->cd_longtid = CTF_ERR;
- cdp->cd_elf = elf;
cdp->cd_maxoff = nexthdr - 1;
- cdp->cd_ctfp = ctf_fdcreate(fd, &ret);
+ cdp->cd_ctfp = ctf_fdcreate(cdp->cd_fd, &ret);
if (cdp->cd_ctfp == NULL) {
ctf_free(cdp, sizeof (ctf_die_t));
return (ret);
}
avl_create(&cdp->cd_map, ctf_dwmap_comp, sizeof (ctf_dwmap_t),
offsetof(ctf_dwmap_t, cdm_avl));
- cdp->cd_errbuf = errbuf;
- cdp->cd_errlen = errlen;
bzero(&cdp->cd_vars, sizeof (ctf_list_t));
bzero(&cdp->cd_funcs, sizeof (ctf_list_t));
bzero(&cdp->cd_bitfields, sizeof (ctf_list_t));
- if ((ret = ctf_dwarf_die_elfenc(elf, cdp, errbuf,
- errlen)) != 0) {
+ if ((ret = ctf_dwarf_die_elfenc(cdp->cd_elf, cdp,
+ cdp->cd_errbuf, cdp->cd_errlen)) != 0) {
avl_destroy(&cdp->cd_map);
ctf_free(cdp, sizeof (ctf_die_t));
return (ret);
@@ -2756,7 +2681,7 @@ ctf_dwarf_init_die(int fd, Elf *elf, ctf_die_t *cdp, int ndie, char *errbuf,
return (ret);
}
if (cu == NULL) {
- (void) snprintf(errbuf, errlen,
+ (void) snprintf(cdp->cd_errbuf, cdp->cd_errlen,
"file does not contain DWARF data\n");
avl_destroy(&cdp->cd_map);
ctf_free(cdp, sizeof (ctf_die_t));
@@ -2769,7 +2694,7 @@ ctf_dwarf_init_die(int fd, Elf *elf, ctf_die_t *cdp, int ndie, char *errbuf,
return (ret);
}
if (child == NULL) {
- (void) snprintf(errbuf, errlen,
+ (void) snprintf(cdp->cd_errbuf, cdp->cd_errlen,
"file does not contain DWARF data\n");
avl_destroy(&cdp->cd_map);
ctf_free(cdp, sizeof (ctf_die_t));
@@ -2779,7 +2704,7 @@ ctf_dwarf_init_die(int fd, Elf *elf, ctf_die_t *cdp, int ndie, char *errbuf,
cdp->cd_cuoff = offset;
cdp->cd_cu = child;
- if ((cdp->cd_cmh = ctf_merge_init(fd, &ret)) == NULL) {
+ if ((cdp->cd_cmh = ctf_merge_init(cdp->cd_fd, &ret)) == NULL) {
avl_destroy(&cdp->cd_map);
ctf_free(cdp, sizeof (ctf_die_t));
return (ret);
@@ -2797,15 +2722,112 @@ ctf_dwarf_init_die(int fd, Elf *elf, ctf_die_t *cdp, int ndie, char *errbuf,
return (0);
}
+/* ARGSUSED */
+static int
+ctf_dwarf_convert_one(void *arg, void *unused)
+{
+ int ret;
+ ctf_file_t *dedup;
+ ctf_die_t *cdp = arg;
+ Dwarf_Error derr;
+
+ VERIFY(cdp != NULL);
+
+ if ((ret = ctf_dwarf_init_die(cdp)) != 0) {
+ return (ret);
+ }
+
+ ctf_dprintf("converting die: %s\n", cdp->cd_name);
+ ctf_dprintf("max offset: %x\n", cdp->cd_maxoff);
+
+ ret = ctf_dwarf_convert_die(cdp, cdp->cd_cu);
+ ctf_dprintf("ctf_dwarf_convert_die (%s) returned %d\n", cdp->cd_name,
+ ret);
+ if (ret != 0) {
+ return (ret);
+ }
+ if (ctf_update(cdp->cd_ctfp) != 0) {
+ return (ctf_dwarf_error(cdp, cdp->cd_ctfp, 0,
+ "failed to update output ctf container"));
+ }
+
+ ret = ctf_dwarf_fixup_die(cdp, B_FALSE);
+ ctf_dprintf("ctf_dwarf_fixup_die (%s) returned %d\n", cdp->cd_name,
+ ret);
+ if (ret != 0) {
+ return (ret);
+ }
+ if (ctf_update(cdp->cd_ctfp) != 0) {
+ return (ctf_dwarf_error(cdp, cdp->cd_ctfp, 0,
+ "failed to update output ctf container"));
+ }
+
+ ret = ctf_dwarf_fixup_die(cdp, B_TRUE);
+ ctf_dprintf("ctf_dwarf_fixup_die (%s) returned %d\n", cdp->cd_name,
+ ret);
+ if (ret != 0) {
+ return (ret);
+ }
+ if (ctf_update(cdp->cd_ctfp) != 0) {
+ return (ctf_dwarf_error(cdp, cdp->cd_ctfp, 0,
+ "failed to update output ctf container"));
+ }
+
+
+ if ((ret = ctf_dwarf_conv_funcvars(cdp)) != 0) {
+ return (ctf_dwarf_error(cdp, NULL, ret,
+ "failed to convert strong functions and variables"));
+ }
+
+ if (ctf_update(cdp->cd_ctfp) != 0) {
+ return (ctf_dwarf_error(cdp, cdp->cd_ctfp, 0,
+ "failed to update output ctf container"));
+ }
+
+ if (cdp->cd_doweaks == B_TRUE) {
+ if ((ret = ctf_dwarf_conv_weaks(cdp)) != 0) {
+ return (ctf_dwarf_error(cdp, NULL, ret,
+ "failed to convert weak functions and variables"));
+ }
+
+ if (ctf_update(cdp->cd_ctfp) != 0) {
+ return (ctf_dwarf_error(cdp, cdp->cd_ctfp, 0,
+ "failed to update output ctf container"));
+ }
+ }
+
+ ctf_phase_dump(cdp->cd_ctfp, "pre-dedup");
+ ctf_dprintf("adding inputs for dedup\n");
+ if ((ret = ctf_merge_add(cdp->cd_cmh, cdp->cd_ctfp)) != 0) {
+ return (ctf_dwarf_error(cdp, NULL, ret,
+ "failed to add inputs for merge"));
+ }
+
+ ctf_dprintf("starting merge\n");
+ if ((ret = ctf_merge_dedup(cdp->cd_cmh, &dedup)) != 0) {
+ return (ctf_dwarf_error(cdp, NULL, ret,
+ "failed to deduplicate die"));
+ }
+
+ ctf_dprintf("Trying to clean up dwarf_t: %p\n", cdp->cd_dwarf);
+ if ((ret = dwarf_finish(cdp->cd_dwarf, &derr)) != DW_DLV_OK)
+ ctf_dprintf("dwarf_finish fail: %s\n", dwarf_errmsg(derr));
+ cdp->cd_dwarf = NULL;
+ ctf_close(cdp->cd_ctfp);
+ cdp->cd_ctfp = dedup;
+
+ return (0);
+}
ctf_conv_status_t
-ctf_dwarf_convert(int fd, Elf *elf, uint_t nthrs, int *errp, ctf_file_t **fpp,
- char *errmsg, size_t errlen)
+ctf_dwarf_convert(int fd, Elf *elf, uint_t bsize, uint_t nthrs, int *errp,
+ ctf_file_t **fpp, char *errmsg, size_t errlen)
{
int err, ret, ndies, i;
Dwarf_Debug dw;
Dwarf_Error derr;
ctf_die_t *cdies = NULL, *cdp;
+ ctf_file_t *fpprev;
workq_t *wqp = NULL;
if (errp == NULL)
@@ -2848,65 +2870,72 @@ ctf_dwarf_convert(int fd, Elf *elf, uint_t nthrs, int *errp, ctf_file_t **fpp,
return (CTF_CONV_ERROR);
}
+ /*
+ * Fill out just enough of the ctf_die_t for the conversion process to
+ * be able to finish the rest in a (potentially) multithreaded context.
+ */
for (i = 0; i < ndies; i++) {
cdp = &cdies[i];
- ret = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL,
- &cdp->cd_dwarf, &derr);
- if (ret != 0) {
- ctf_free(cdies, sizeof (ctf_die_t) * ndies);
- (void) snprintf(errmsg, errlen,
- "failed to initialize DWARF: %s\n",
- dwarf_errmsg(derr));
- *errp = ECTF_CONVBKERR;
- return (CTF_CONV_ERROR);
- }
-
- ret = ctf_dwarf_init_die(fd, elf, &cdies[i], i, errmsg, errlen);
- if (ret != 0) {
- *errp = ret;
- goto out;
- }
+ cdp->cd_elf = elf;
+ cdp->cd_fd = fd;
+ cdp->cd_ndie = i;
+ cdp->cd_errbuf = errmsg;
+ cdp->cd_errlen = errlen;
cdp->cd_doweaks = ndies > 1 ? B_FALSE : B_TRUE;
}
ctf_dprintf("found %d DWARF die(s)\n", ndies);
/*
- * If we only have one die, there's no reason to use multiple threads,
- * even if the user requested them. After all, they just gave us an
- * upper bound.
+ * 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.
+ * After all, they just gave us an upper bound.
*/
- if (ndies == 1)
- nthrs = 1;
+ if (nthrs > ndies)
+ nthrs = ndies;
+ if (bsize > ndies)
+ bsize = ndies;
if (workq_init(&wqp, nthrs) == -1) {
*errp = errno;
goto out;
}
- for (i = 0; i < ndies; i++) {
- cdp = &cdies[i];
- ctf_dprintf("adding die %s: %p, %x %x\n", cdp->cd_name,
- cdp->cd_cu, cdp->cd_cuoff, cdp->cd_maxoff);
- if (workq_add(wqp, cdp) == -1) {
+ /*
+ * In order to avoid exhausting memory limits when converting files
+ * with a large number of dies, we process them in batches.
+ */
+ for (i = 0; i < ndies; i += bsize) {
+ ctf_merge_t *cmp;
+ int j;
+
+ ctf_dprintf("adding dies\n");
+ for (j = i; j < ndies; j++) {
+ if (j - i >= bsize)
+ break;
+ cdp = &cdies[j];
+ if (workq_add(wqp, cdp) == -1) {
+ *errp = errno;
+ goto out;
+ }
+ }
+
+ ret = workq_work(wqp, ctf_dwarf_convert_one, NULL, errp);
+ if (ret == WORKQ_ERROR) {
*errp = errno;
goto out;
+ } else if (ret == WORKQ_UERROR) {
+ ctf_dprintf("internal convert failed: %s\n",
+ ctf_errmsg(*errp));
+ goto out;
}
- }
-
- ret = workq_work(wqp, ctf_dwarf_convert_one, NULL, errp);
- if (ret == WORKQ_ERROR) {
- *errp = errno;
- goto out;
- } else if (ret == WORKQ_UERROR) {
- ctf_dprintf("internal convert failed: %s\n",
- ctf_errmsg(*errp));
- goto out;
- }
- ctf_dprintf("Determining next phase: have %d dies\n", ndies);
- if (ndies != 1) {
- ctf_merge_t *cmp;
+ /* Only one die, no merge required */
+ if (ndies == 1) {
+ *fpp = cdies->cd_ctfp;
+ cdies->cd_ctfp = NULL;
+ goto success;
+ }
cmp = ctf_merge_init(fd, &ret);
if (cmp == NULL) {
@@ -2921,11 +2950,32 @@ ctf_dwarf_convert(int fd, Elf *elf, uint_t nthrs, int *errp, ctf_file_t **fpp,
goto out;
}
- ctf_dprintf("adding dies\n");
- for (i = 0; i < ndies; i++) {
- cdp = &cdies[i];
+ /*
+ * If we have the result of a previous merge then go ahead and
+ * add it as an input to the next one, as well as saving the
+ * ctf_file_t so that it can be freed afterwards when it is no
+ * longer required.
+ */
+ fpprev = NULL;
+ if (*fpp) {
+ ctf_dprintf("adding previous merge die\n");
+ fpprev = *fpp;
+ if ((ret = ctf_merge_add(cmp, *fpp)) != 0) {
+ ctf_merge_fini(cmp);
+ *fpp = NULL;
+ *errp = ret;
+ goto out;
+ }
+ }
+
+ ctf_dprintf("adding dies to merge\n");
+ for (j = i; j < ndies; j++) {
+ if (j - i >= bsize)
+ break;
+ cdp = &cdies[j];
if ((ret = ctf_merge_add(cmp, cdp->cd_ctfp)) != 0) {
ctf_merge_fini(cmp);
+ *fpp = NULL;
*errp = ret;
goto out;
}
@@ -2940,15 +2990,21 @@ ctf_dwarf_convert(int fd, Elf *elf, uint_t nthrs, int *errp, ctf_file_t **fpp,
*errp = ret;
goto out;
}
+
+ ctf_dprintf("freeing dies\n");
+ for (j = i; j < ndies; j++) {
+ if (j - i >= bsize)
+ break;
+ cdp = &cdies[j];
+ ctf_dprintf("freeing die %d\n", j);
+ ctf_dwarf_free_die(cdp);
+ }
+ ctf_close(fpprev);
ctf_merge_fini(cmp);
- *errp = 0;
- ctf_dprintf("successfully converted!\n");
- } else {
- *errp = 0;
- *fpp = cdies->cd_ctfp;
- cdies->cd_ctfp = NULL;
- ctf_dprintf("successfully converted!\n");
}
+success:
+ *errp = 0;
+ ctf_dprintf("successfully converted!\n");
out:
workq_fini(wqp);
diff --git a/usr/src/lib/libctf/common/libctf.h b/usr/src/lib/libctf/common/libctf.h
index a5c5027048..f014737b43 100644
--- a/usr/src/lib/libctf/common/libctf.h
+++ b/usr/src/lib/libctf/common/libctf.h
@@ -77,9 +77,9 @@ extern void ctf_diff_fini(ctf_diff_t *);
#define CTF_CONVERT_F_IGNNONC 0x01
extern ctf_file_t *ctf_elfconvert(int, Elf *, const char *, uint_t, uint_t,
+ uint_t, int *, char *, size_t);
+extern ctf_file_t *ctf_fdconvert(int, const char *, uint_t, 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 struct ctf_merge_handle ctf_merge_t;
extern ctf_merge_t *ctf_merge_init(int, int *);
diff --git a/usr/src/lib/libctf/common/libctf_impl.h b/usr/src/lib/libctf/common/libctf_impl.h
index 11193e97d0..8a9fdd3013 100644
--- a/usr/src/lib/libctf/common/libctf_impl.h
+++ b/usr/src/lib/libctf/common/libctf_impl.h
@@ -35,9 +35,9 @@ typedef enum ctf_conv_status {
CTF_CONV_NOTSUP = 2
} ctf_conv_status_t;
-typedef ctf_conv_status_t (*ctf_convert_f)(int, Elf *, uint_t, int *,
+typedef ctf_conv_status_t (*ctf_convert_f)(int, Elf *, uint_t, uint_t, int *,
ctf_file_t **, char *, size_t);
-extern ctf_conv_status_t ctf_dwarf_convert(int, Elf *, uint_t, int *,
+extern ctf_conv_status_t ctf_dwarf_convert(int, Elf *, uint_t, uint_t, int *,
ctf_file_t **, char *, size_t);
/*