summaryrefslogtreecommitdiff
path: root/usr/src/cmd/ctfmerge/ctfmerge.c
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2015-07-27 00:35:52 +0000
committerRobert Mustacchi <rm@joyent.com>2015-07-28 19:05:39 +0000
commit14c3d85bba96b10c225341f4c7f4af93c314b508 (patch)
tree8ef3a2513e220291581564d4db16bd5b4fbf127e /usr/src/cmd/ctfmerge/ctfmerge.c
parent9211d9b4c9ccc64292132e8e87c92ad6084b29a8 (diff)
downloadillumos-joyent-14c3d85bba96b10c225341f4c7f4af93c314b508.tar.gz
OS-4548 CTF Everywhere: Phase 1
OS-4549 ctfconvert should be implemented in terms of libctf OS-4550 ctfconvert could convert multiple compilation units OS-4553 want multi-threaded ctfmerge OS-4552 Want general workq OS-4551 Want general mergeq OS-4554 ctfdiff doesn't properly handle unknown options OS-4555 ctfdiff's symbols could be more consistently prefixed OS-4048 new ctfmerge uses tmpfile after freeing it OS-4556 ctfdump should drive on when incomplete files exist OS-4557 ctf_add_encoded assigns() incorrect byte size to types OS-4558 ctf_add_{struct,union,enum} can reuse forwards OS-4559 ctf_add_{struct,union,enum} occasionally forget to dirty the ctf_file_t OS-4560 ctf_add_member could better handle bitfields OS-4561 ctf_type_size() reports wrong size for forwards OS-4563 diffing CTF typedefs needs to walk multiple definitions OS-4564 build scripts shouldn't hardcode CTF paths OS-4565 ctf_fdcreate could be more flexible OS-4566 Want libctf ctf_kind_name() function OS-4567 Want libctf function to set struct/union size OS-4568 Want ctfmerge altexec
Diffstat (limited to 'usr/src/cmd/ctfmerge/ctfmerge.c')
-rw-r--r--usr/src/cmd/ctfmerge/ctfmerge.c81
1 files changed, 66 insertions, 15 deletions
diff --git a/usr/src/cmd/ctfmerge/ctfmerge.c b/usr/src/cmd/ctfmerge/ctfmerge.c
index a64936ccbe..5dea32b3aa 100644
--- a/usr/src/cmd/ctfmerge/ctfmerge.c
+++ b/usr/src/cmd/ctfmerge/ctfmerge.c
@@ -33,6 +33,7 @@
#include <sys/mman.h>
#include <libgen.h>
#include <stdarg.h>
+#include <limits.h>
static char *g_progname;
static char *g_unique;
@@ -40,6 +41,13 @@ 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
+
+#define CTFMERGE_DEFAULT_NTHREADS 8
+#define CTFMERGE_ALTEXEC "CTFMERGE_ALTEXEC"
+
static void
ctfmerge_fatal(const char *fmt, ...)
{
@@ -53,7 +61,7 @@ ctfmerge_fatal(const char *fmt, ...)
if (g_outfile != NULL)
(void) unlink(g_outfile);
- exit(1);
+ exit(CTFMERGE_FATAL);
}
static boolean_t
@@ -224,10 +232,9 @@ ctfmerge_elfopen(const char *name, Elf *elf, ctf_merge_t *cmh)
name, ctf_errmsg(err));
}
} else {
- if (ctf_merge_add(cmh, fp) != 0) {
+ if ((err = ctf_merge_add(cmh, fp)) != 0) {
ctfmerge_fatal("failed to add input %s: %s\n",
- name, ctf_errmsg(ctf_errno(fp)));
- exit(1);
+ name, ctf_errmsg(err));
}
g_nctf++;
}
@@ -294,10 +301,11 @@ ctfmerge_usage(const char *fmt, ...)
}
(void) fprintf(stderr, "Usage: %s [-gt] [-d uniqfile] [-l label] "
- "[-L labelenv] -o outfile file ...\n"
+ "[-L labelenv] [-j nthrs] -o outfile file ...\n"
"\n"
"\t-d uniquify merged output against uniqfile\n"
"\t-g do not remove source debug information (STABS, DWARF)\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"
@@ -305,22 +313,49 @@ ctfmerge_usage(const char *fmt, ...)
g_progname);
}
+static void
+ctfmerge_altexec(char **argv)
+{
+ const char *alt;
+ char *altexec;
+
+ alt = getenv(CTFMERGE_ALTEXEC);
+ if (alt == NULL || *alt == '\0')
+ return;
+
+ altexec = strdup(alt);
+ if (altexec == NULL)
+ ctfmerge_fatal("failed to allocate memory for altexec\n");
+ if (unsetenv(CTFMERGE_ALTEXEC) != 0)
+ ctfmerge_fatal("failed to unset %s from environment: %s\n",
+ CTFMERGE_ALTEXEC, strerror(errno));
+
+ (void) execv(altexec, argv);
+ ctfmerge_fatal("failed to execute alternate program %s: %s",
+ altexec, strerror(errno));
+}
+
int
main(int argc, char *argv[])
{
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:fgL:o:t")) != -1) {
+ while ((c = getopt(argc, argv, ":d:fgj:L:o:t")) != -1) {
switch (c) {
case 'd':
g_unique = optarg;
@@ -331,6 +366,17 @@ main(int argc, char *argv[])
case 'g':
/* Silently ignored for compatibility */
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') {
+ ctfmerge_fatal("invalid argument for -j: %s\n",
+ optarg);
+ }
+ nthreads = (uint_t)argj;
+ break;
case 'l':
label = optarg;
break;
@@ -344,18 +390,18 @@ main(int argc, char *argv[])
g_req = B_TRUE;
break;
case ':':
- ctfmerge_usage("ctfmerge: Option -%c requires an "
- "operand\n", optopt);
- return (2);
+ ctfmerge_usage("Option -%c requires an operand\n",
+ optopt);
+ return (CTFMERGE_USAGE);
case '?':
ctfmerge_usage("Unknown option: -%c\n", optopt);
- return (2);
+ return (CTFMERGE_USAGE);
}
}
if (g_outfile == NULL) {
ctfmerge_usage("missing required -o output file\n");
- return (2);
+ return (CTFMERGE_USAGE);
}
(void) elf_version(EV_CURRENT);
@@ -373,7 +419,7 @@ main(int argc, char *argv[])
if (argc < 1) {
ctfmerge_usage("no input files specified");
- return (2);
+ return (CTFMERGE_USAGE);
}
cmh = ctf_merge_init(ofd, &err);
@@ -381,6 +427,10 @@ main(int argc, char *argv[])
ctfmerge_fatal("failed to create merge handle: %s\n",
ctf_errmsg(err));
+ if ((err = ctf_merge_set_nthreads(cmh, nthreads)) != 0)
+ ctfmerge_fatal("failed to set parallelism to %d: %s\n",
+ nthreads, ctf_errmsg(err));
+
for (i = 0; i < argc; i++) {
ctf_file_t *ifp;
int fd;
@@ -449,7 +499,6 @@ main(int argc, char *argv[])
if (ufp == NULL) {
ctfmerge_fatal("failed to open uniquify file %s: %s\n",
g_unique, ctf_errmsg(err));
- return (1);
}
base = basename(g_unique);
@@ -470,18 +519,20 @@ main(int argc, char *argv[])
if (asprintf(&tmpfile, "%s.ctf", g_outfile) == -1)
ctfmerge_fatal("ran out of memory for temporary file name\n");
err = ctf_elfwrite(ofp, g_outfile, tmpfile, wflags);
- free(tmpfile);
if (err == CTF_ERR) {
(void) unlink(tmpfile);
+ free(tmpfile);
ctfmerge_fatal("encountered a libctf error: %s!\n",
ctf_errmsg(ctf_errno(ofp)));
}
if (rename(tmpfile, g_outfile) != 0) {
(void) unlink(tmpfile);
+ free(tmpfile);
ctfmerge_fatal("failed to rename temporary file: %s\n",
strerror(errno));
}
+ free(tmpfile);
- return (0);
+ return (CTFMERGE_OK);
}