1bc1f688bSRobert Mustacchi /* 2bc1f688bSRobert Mustacchi * This file and its contents are supplied under the terms of the 3bc1f688bSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0. 4bc1f688bSRobert Mustacchi * You may only use this file in accordance with the terms of version 5bc1f688bSRobert Mustacchi * 1.0 of the CDDL. 6bc1f688bSRobert Mustacchi * 7bc1f688bSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this 8bc1f688bSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at 9bc1f688bSRobert Mustacchi * http://www.illumos.org/license/CDDL. 10bc1f688bSRobert Mustacchi */ 11bc1f688bSRobert Mustacchi 12bc1f688bSRobert Mustacchi /* 13ce115d25SJohn Levon * Copyright 2019 Joyent, Inc. 14dd442252SAndy Fiddaman * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. 15bc1f688bSRobert Mustacchi */ 16bc1f688bSRobert Mustacchi 17bc1f688bSRobert Mustacchi /* 18bc1f688bSRobert Mustacchi * Create CTF from extant debugging information 19bc1f688bSRobert Mustacchi */ 20bc1f688bSRobert Mustacchi 21bc1f688bSRobert Mustacchi #include <stdio.h> 22bc1f688bSRobert Mustacchi #include <unistd.h> 23bc1f688bSRobert Mustacchi #include <stdlib.h> 24bc1f688bSRobert Mustacchi #include <stdarg.h> 25bc1f688bSRobert Mustacchi #include <sys/types.h> 26bc1f688bSRobert Mustacchi #include <sys/stat.h> 27bc1f688bSRobert Mustacchi #include <fcntl.h> 28bc1f688bSRobert Mustacchi #include <errno.h> 29bc1f688bSRobert Mustacchi #include <libelf.h> 30bc1f688bSRobert Mustacchi #include <libctf.h> 31bc1f688bSRobert Mustacchi #include <string.h> 32bc1f688bSRobert Mustacchi #include <libgen.h> 33bc1f688bSRobert Mustacchi #include <limits.h> 34bc1f688bSRobert Mustacchi #include <strings.h> 35bc1f688bSRobert Mustacchi #include <sys/debug.h> 36bc1f688bSRobert Mustacchi 37bc1f688bSRobert Mustacchi #define CTFCONVERT_OK 0 38bc1f688bSRobert Mustacchi #define CTFCONVERT_FATAL 1 39bc1f688bSRobert Mustacchi #define CTFCONVERT_USAGE 2 40bc1f688bSRobert Mustacchi 41bc1f688bSRobert Mustacchi static char *ctfconvert_progname; 42bc1f688bSRobert Mustacchi 43bc1f688bSRobert Mustacchi static void 44bc1f688bSRobert Mustacchi ctfconvert_fatal(const char *fmt, ...) 45bc1f688bSRobert Mustacchi { 46bc1f688bSRobert Mustacchi va_list ap; 47bc1f688bSRobert Mustacchi 48bc1f688bSRobert Mustacchi (void) fprintf(stderr, "%s: ", ctfconvert_progname); 49bc1f688bSRobert Mustacchi va_start(ap, fmt); 50bc1f688bSRobert Mustacchi (void) vfprintf(stderr, fmt, ap); 51bc1f688bSRobert Mustacchi va_end(ap); 52bc1f688bSRobert Mustacchi 53bc1f688bSRobert Mustacchi exit(CTFCONVERT_FATAL); 54bc1f688bSRobert Mustacchi } 55bc1f688bSRobert Mustacchi 56dd442252SAndy Fiddaman static void 57dd442252SAndy Fiddaman ctfconvert_warning(void *arg, const char *fmt, ...) 58dd442252SAndy Fiddaman { 59dd442252SAndy Fiddaman va_list ap; 60dd442252SAndy Fiddaman char *buf; 61dd442252SAndy Fiddaman 62dd442252SAndy Fiddaman va_start(ap, fmt); 63dd442252SAndy Fiddaman if (vasprintf(&buf, fmt, ap) != -1) { 64dd442252SAndy Fiddaman (void) fprintf(stderr, "%s: WARNING: %s", ctfconvert_progname, 65dd442252SAndy Fiddaman buf); 66dd442252SAndy Fiddaman free(buf); 67dd442252SAndy Fiddaman } 68dd442252SAndy Fiddaman va_end(ap); 69dd442252SAndy Fiddaman } 70bc1f688bSRobert Mustacchi 71bc1f688bSRobert Mustacchi static void 72bc1f688bSRobert Mustacchi ctfconvert_usage(const char *fmt, ...) 73bc1f688bSRobert Mustacchi { 74bc1f688bSRobert Mustacchi if (fmt != NULL) { 75bc1f688bSRobert Mustacchi va_list ap; 76bc1f688bSRobert Mustacchi 77bc1f688bSRobert Mustacchi (void) fprintf(stderr, "%s: ", ctfconvert_progname); 78bc1f688bSRobert Mustacchi va_start(ap, fmt); 79bc1f688bSRobert Mustacchi (void) vfprintf(stderr, fmt, ap); 80bc1f688bSRobert Mustacchi va_end(ap); 81bc1f688bSRobert Mustacchi } 82bc1f688bSRobert Mustacchi 83*73197b54SAndy Fiddaman (void) fprintf(stderr, "Usage: %s [-fikms] [-j nthrs] [-l label | " 84effb27eeSAndy Fiddaman "-L labelenv] [-b batchsize]\n" 85effb27eeSAndy Fiddaman " [-o outfile] input\n" 86bc1f688bSRobert Mustacchi "\n" 87effb27eeSAndy Fiddaman "\t-b batch process this many dies at a time (default %d)\n" 88*73197b54SAndy Fiddaman "\t-f always attempt to convert files\n" 89bc1f688bSRobert Mustacchi "\t-i ignore files not built partially from C sources\n" 90effb27eeSAndy Fiddaman "\t-j use nthrs threads to perform the merge (default %d)\n" 91bc1f688bSRobert Mustacchi "\t-k keep around original input file on failure\n" 92bc1f688bSRobert Mustacchi "\t-l set output container's label to specified value\n" 93effb27eeSAndy Fiddaman "\t-L set output container's label to value from environment\n" 94effb27eeSAndy Fiddaman "\t-m allow input to have missing debug info\n" 95dd442252SAndy Fiddaman "\t-o copy input to outfile and add CTF\n" 96dd442252SAndy Fiddaman "\t-s allow truncation of data that cannot be fully converted\n", 97effb27eeSAndy Fiddaman ctfconvert_progname, 98dd442252SAndy Fiddaman CTF_CONVERT_DEFAULT_BATCHSIZE, 99dd442252SAndy Fiddaman CTF_CONVERT_DEFAULT_NTHREADS); 100bc1f688bSRobert Mustacchi } 101bc1f688bSRobert Mustacchi 102bc1f688bSRobert Mustacchi /* 103bc1f688bSRobert Mustacchi * This is a bit unfortunate. Traditionally we do type uniquification across all 104bc1f688bSRobert Mustacchi * modules in the kernel, including ip and unix against genunix. However, when 105bc1f688bSRobert Mustacchi * _MACHDEP is defined, then the cpu_t ends up having an additional member 106bc1f688bSRobert Mustacchi * (cpu_m), thus changing the ability for us to uniquify against it. This in 107bc1f688bSRobert Mustacchi * turn causes a lot of type sprawl, as there's a lot of things that end up 108bc1f688bSRobert Mustacchi * referring to the cpu_t and it chains out from there. 109bc1f688bSRobert Mustacchi * 110bc1f688bSRobert Mustacchi * So, if we find that a cpu_t has been defined and it has a couple of useful 111bc1f688bSRobert Mustacchi * sentinel members and it does *not* have the cpu_m member, then we will try 112bc1f688bSRobert Mustacchi * and lookup or create a forward declaration to the machcpu, append it to the 113bc1f688bSRobert Mustacchi * end, and update the file. 114bc1f688bSRobert Mustacchi * 115bc1f688bSRobert Mustacchi * This currently is only invoked if an undocumented option -X is passed. This 116bc1f688bSRobert Mustacchi * value is private to illumos and it can be changed at any time inside of it, 117bc1f688bSRobert Mustacchi * so if -X wants to be used for something, it should be. The ability to rely on 118bc1f688bSRobert Mustacchi * -X for others is strictly not an interface in any way, shape, or form. 119bc1f688bSRobert Mustacchi * 120bc1f688bSRobert Mustacchi * The following struct contains most of the information that we care about and 121bc1f688bSRobert Mustacchi * that we want to validate exists before we decide what to do. 122bc1f688bSRobert Mustacchi */ 123bc1f688bSRobert Mustacchi 124bc1f688bSRobert Mustacchi typedef struct ctfconvert_fixup { 125bc1f688bSRobert Mustacchi boolean_t cf_cyclic; /* Do we have a cpu_cyclic member */ 126bc1f688bSRobert Mustacchi boolean_t cf_mcpu; /* We have a cpu_m member */ 127bc1f688bSRobert Mustacchi boolean_t cf_lastpad; /* Is the pad member the last entry */ 128bc1f688bSRobert Mustacchi ulong_t cf_padoff; /* offset of the pad */ 129bc1f688bSRobert Mustacchi } ctfconvert_fixup_t; 130bc1f688bSRobert Mustacchi 131bc1f688bSRobert Mustacchi /* ARGSUSED */ 132bc1f688bSRobert Mustacchi static int 133bc1f688bSRobert Mustacchi ctfconvert_fixup_genunix_cb(const char *name, ctf_id_t tid, ulong_t off, 134bc1f688bSRobert Mustacchi void *arg) 135bc1f688bSRobert Mustacchi { 136bc1f688bSRobert Mustacchi ctfconvert_fixup_t *cfp = arg; 137bc1f688bSRobert Mustacchi 138bc1f688bSRobert Mustacchi cfp->cf_lastpad = B_FALSE; 139bc1f688bSRobert Mustacchi if (strcmp(name, "cpu_cyclic") == 0) { 140bc1f688bSRobert Mustacchi cfp->cf_cyclic = B_TRUE; 141bc1f688bSRobert Mustacchi return (0); 142bc1f688bSRobert Mustacchi } 143bc1f688bSRobert Mustacchi 144bc1f688bSRobert Mustacchi if (strcmp(name, "cpu_m") == 0) { 145bc1f688bSRobert Mustacchi cfp->cf_mcpu = B_TRUE; 146bc1f688bSRobert Mustacchi return (0); 147bc1f688bSRobert Mustacchi } 148bc1f688bSRobert Mustacchi 149bc1f688bSRobert Mustacchi if (strcmp(name, "cpu_m_pad") == 0) { 150bc1f688bSRobert Mustacchi cfp->cf_lastpad = B_TRUE; 151bc1f688bSRobert Mustacchi cfp->cf_padoff = off; 152bc1f688bSRobert Mustacchi return (0); 153bc1f688bSRobert Mustacchi } 154bc1f688bSRobert Mustacchi 155bc1f688bSRobert Mustacchi return (0); 156bc1f688bSRobert Mustacchi } 157bc1f688bSRobert Mustacchi 158bc1f688bSRobert Mustacchi static void 159bc1f688bSRobert Mustacchi ctfconvert_fixup_genunix(ctf_file_t *fp) 160bc1f688bSRobert Mustacchi { 161bc1f688bSRobert Mustacchi ctf_id_t cpuid, mcpu; 162bc1f688bSRobert Mustacchi ssize_t sz; 163bc1f688bSRobert Mustacchi ctfconvert_fixup_t cf; 164bc1f688bSRobert Mustacchi int model, ptrsz; 165bc1f688bSRobert Mustacchi 166bc1f688bSRobert Mustacchi cpuid = ctf_lookup_by_name(fp, "struct cpu"); 167bc1f688bSRobert Mustacchi if (cpuid == CTF_ERR) 168bc1f688bSRobert Mustacchi return; 169bc1f688bSRobert Mustacchi 170bc1f688bSRobert Mustacchi if (ctf_type_kind(fp, cpuid) != CTF_K_STRUCT) 171bc1f688bSRobert Mustacchi return; 172bc1f688bSRobert Mustacchi 173bc1f688bSRobert Mustacchi if ((sz = ctf_type_size(fp, cpuid)) == CTF_ERR) 174bc1f688bSRobert Mustacchi return; 175bc1f688bSRobert Mustacchi 176bc1f688bSRobert Mustacchi model = ctf_getmodel(fp); 177bc1f688bSRobert Mustacchi VERIFY(model == CTF_MODEL_ILP32 || model == CTF_MODEL_LP64); 178bc1f688bSRobert Mustacchi ptrsz = model == CTF_MODEL_ILP32 ? 4 : 8; 179bc1f688bSRobert Mustacchi 180bc1f688bSRobert Mustacchi bzero(&cf, sizeof (ctfconvert_fixup_t)); 181bc1f688bSRobert Mustacchi if (ctf_member_iter(fp, cpuid, ctfconvert_fixup_genunix_cb, &cf) == 182bc1f688bSRobert Mustacchi CTF_ERR) 183bc1f688bSRobert Mustacchi return; 184bc1f688bSRobert Mustacchi 185bc1f688bSRobert Mustacchi /* 186bc1f688bSRobert Mustacchi * Finally, we want to verify that the cpu_m is actually the last member 187bc1f688bSRobert Mustacchi * that we have here. 188bc1f688bSRobert Mustacchi */ 189bc1f688bSRobert Mustacchi if (cf.cf_cyclic == B_FALSE || cf.cf_mcpu == B_TRUE || 190bc1f688bSRobert Mustacchi cf.cf_lastpad == B_FALSE) { 191bc1f688bSRobert Mustacchi return; 192bc1f688bSRobert Mustacchi } 193bc1f688bSRobert Mustacchi 194bc1f688bSRobert Mustacchi if (cf.cf_padoff + ptrsz * NBBY != sz * NBBY) { 195bc1f688bSRobert Mustacchi return; 196bc1f688bSRobert Mustacchi } 197bc1f688bSRobert Mustacchi 198bc1f688bSRobert Mustacchi /* 199bc1f688bSRobert Mustacchi * Okay, we're going to do this, try to find a struct machcpu. We either 200bc1f688bSRobert Mustacchi * want a forward or a struct. If we find something else, error. If we 201bc1f688bSRobert Mustacchi * find nothing, add a forward and then add the member. 202bc1f688bSRobert Mustacchi */ 203bc1f688bSRobert Mustacchi mcpu = ctf_lookup_by_name(fp, "struct machcpu"); 204bc1f688bSRobert Mustacchi if (mcpu == CTF_ERR) { 205bc1f688bSRobert Mustacchi mcpu = ctf_add_forward(fp, CTF_ADD_NONROOT, "machcpu", 206bc1f688bSRobert Mustacchi CTF_K_STRUCT); 207bc1f688bSRobert Mustacchi if (mcpu == CTF_ERR) { 208bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to add 'struct machcpu' " 209dd442252SAndy Fiddaman "forward: %s\n", ctf_errmsg(ctf_errno(fp))); 210bc1f688bSRobert Mustacchi } 211bc1f688bSRobert Mustacchi } else { 212bc1f688bSRobert Mustacchi int kind; 213bc1f688bSRobert Mustacchi if ((kind = ctf_type_kind(fp, mcpu)) == CTF_ERR) { 214bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to get the type kind for " 215dd442252SAndy Fiddaman "the struct machcpu: %s\n", 216bc1f688bSRobert Mustacchi ctf_errmsg(ctf_errno(fp))); 217bc1f688bSRobert Mustacchi } 218bc1f688bSRobert Mustacchi 219bc1f688bSRobert Mustacchi if (kind != CTF_K_STRUCT && kind != CTF_K_FORWARD) 220bc1f688bSRobert Mustacchi ctfconvert_fatal("encountered a struct machcpu of the " 221bc1f688bSRobert Mustacchi "wrong type, found type kind %d\n", kind); 222bc1f688bSRobert Mustacchi } 223bc1f688bSRobert Mustacchi 224bc1f688bSRobert Mustacchi if (ctf_update(fp) == CTF_ERR) { 225bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to update output file: %s\n", 226bc1f688bSRobert Mustacchi ctf_errmsg(ctf_errno(fp))); 227bc1f688bSRobert Mustacchi } 228bc1f688bSRobert Mustacchi 229bc1f688bSRobert Mustacchi if (ctf_add_member(fp, cpuid, "cpu_m", mcpu, sz * NBBY) == CTF_ERR) { 230bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to add the m_cpu member: %s\n", 231bc1f688bSRobert Mustacchi ctf_errmsg(ctf_errno(fp))); 232bc1f688bSRobert Mustacchi } 233bc1f688bSRobert Mustacchi 234bc1f688bSRobert Mustacchi if (ctf_update(fp) == CTF_ERR) { 235bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to update output file: %s\n", 236bc1f688bSRobert Mustacchi ctf_errmsg(ctf_errno(fp))); 237bc1f688bSRobert Mustacchi } 238bc1f688bSRobert Mustacchi 239bc1f688bSRobert Mustacchi VERIFY(ctf_type_size(fp, cpuid) == sz); 240bc1f688bSRobert Mustacchi } 241bc1f688bSRobert Mustacchi 242bc1f688bSRobert Mustacchi int 243bc1f688bSRobert Mustacchi main(int argc, char *argv[]) 244bc1f688bSRobert Mustacchi { 245bc1f688bSRobert Mustacchi int c, ifd, err; 246bc1f688bSRobert Mustacchi boolean_t keep = B_FALSE; 247dd442252SAndy Fiddaman ctf_convert_flag_t flags = 0; 248dd442252SAndy Fiddaman uint_t bsize = CTF_CONVERT_DEFAULT_BATCHSIZE; 249dd442252SAndy Fiddaman uint_t nthreads = CTF_CONVERT_DEFAULT_NTHREADS; 250bc1f688bSRobert Mustacchi const char *outfile = NULL; 251bc1f688bSRobert Mustacchi const char *label = NULL; 252bc1f688bSRobert Mustacchi const char *infile = NULL; 253bc1f688bSRobert Mustacchi char *tmpfile; 254bc1f688bSRobert Mustacchi ctf_file_t *ofp; 255dd442252SAndy Fiddaman char buf[4096] = ""; 256bc1f688bSRobert Mustacchi boolean_t optx = B_FALSE; 2573eca6103SJohn Levon boolean_t ignore_non_c = B_FALSE; 258dd442252SAndy Fiddaman ctf_convert_t *cch; 259bc1f688bSRobert Mustacchi 260bc1f688bSRobert Mustacchi ctfconvert_progname = basename(argv[0]); 261bc1f688bSRobert Mustacchi 262*73197b54SAndy Fiddaman while ((c = getopt(argc, argv, ":b:fij:kl:L:mo:sX")) != -1) { 263bc1f688bSRobert Mustacchi switch (c) { 264effb27eeSAndy Fiddaman case 'b': { 265effb27eeSAndy Fiddaman long argno; 266effb27eeSAndy Fiddaman const char *errstr; 267effb27eeSAndy Fiddaman 268effb27eeSAndy Fiddaman argno = strtonum(optarg, 1, UINT_MAX, &errstr); 269effb27eeSAndy Fiddaman if (errstr != NULL) { 270effb27eeSAndy Fiddaman ctfconvert_fatal("invalid argument for -b: " 271effb27eeSAndy Fiddaman "%s - %s\n", optarg, errstr); 272effb27eeSAndy Fiddaman } 273effb27eeSAndy Fiddaman bsize = (uint_t)argno; 274effb27eeSAndy Fiddaman break; 275effb27eeSAndy Fiddaman } 276*73197b54SAndy Fiddaman case 'f': 277*73197b54SAndy Fiddaman flags |= CTF_FORCE_CONVERSION; 278*73197b54SAndy Fiddaman break; 2793eca6103SJohn Levon case 'i': 2803eca6103SJohn Levon ignore_non_c = B_TRUE; 281bc1f688bSRobert Mustacchi break; 282effb27eeSAndy Fiddaman case 'j': { 283effb27eeSAndy Fiddaman long argno; 284effb27eeSAndy Fiddaman const char *errstr; 285effb27eeSAndy Fiddaman 286effb27eeSAndy Fiddaman argno = strtonum(optarg, 1, 1024, &errstr); 287effb27eeSAndy Fiddaman if (errstr != NULL) { 288bc1f688bSRobert Mustacchi ctfconvert_fatal("invalid argument for -j: " 289effb27eeSAndy Fiddaman "%s - %s\n", optarg, errstr); 290bc1f688bSRobert Mustacchi } 291effb27eeSAndy Fiddaman nthreads = (uint_t)argno; 292bc1f688bSRobert Mustacchi break; 293effb27eeSAndy Fiddaman } 2943eca6103SJohn Levon case 'k': 2953eca6103SJohn Levon keep = B_TRUE; 2963eca6103SJohn Levon break; 2973eca6103SJohn Levon case 'l': 2983eca6103SJohn Levon label = optarg; 2993eca6103SJohn Levon break; 3003eca6103SJohn Levon case 'L': 3013eca6103SJohn Levon label = getenv(optarg); 3023eca6103SJohn Levon break; 3033eca6103SJohn Levon case 'm': 3043eca6103SJohn Levon flags |= CTF_ALLOW_MISSING_DEBUG; 3053eca6103SJohn Levon break; 306bc1f688bSRobert Mustacchi case 'o': 307bc1f688bSRobert Mustacchi outfile = optarg; 308bc1f688bSRobert Mustacchi break; 309dd442252SAndy Fiddaman case 's': 310dd442252SAndy Fiddaman flags |= CTF_ALLOW_TRUNCATION; 311dd442252SAndy Fiddaman break; 312bc1f688bSRobert Mustacchi case 'X': 313bc1f688bSRobert Mustacchi optx = B_TRUE; 314bc1f688bSRobert Mustacchi break; 315bc1f688bSRobert Mustacchi case ':': 316bc1f688bSRobert Mustacchi ctfconvert_usage("Option -%c requires an operand\n", 317bc1f688bSRobert Mustacchi optopt); 318bc1f688bSRobert Mustacchi return (CTFCONVERT_USAGE); 319bc1f688bSRobert Mustacchi case '?': 320bc1f688bSRobert Mustacchi ctfconvert_usage("Unknown option: -%c\n", optopt); 321bc1f688bSRobert Mustacchi return (CTFCONVERT_USAGE); 322bc1f688bSRobert Mustacchi } 323bc1f688bSRobert Mustacchi } 324bc1f688bSRobert Mustacchi 325bc1f688bSRobert Mustacchi argv += optind; 326bc1f688bSRobert Mustacchi argc -= optind; 327bc1f688bSRobert Mustacchi 3283eca6103SJohn Levon if (argc != 1) { 3293eca6103SJohn Levon ctfconvert_usage("Exactly one input file is required\n"); 330bc1f688bSRobert Mustacchi return (CTFCONVERT_USAGE); 331bc1f688bSRobert Mustacchi } 332bc1f688bSRobert Mustacchi infile = argv[0]; 333bc1f688bSRobert Mustacchi 334bc1f688bSRobert Mustacchi if (elf_version(EV_CURRENT) == EV_NONE) 335bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to initialize libelf: library is " 336bc1f688bSRobert Mustacchi "out of date\n"); 337bc1f688bSRobert Mustacchi 338bc1f688bSRobert Mustacchi ifd = open(infile, O_RDONLY); 339bc1f688bSRobert Mustacchi if (ifd < 0) { 340bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to open input file %s: %s\n", infile, 341bc1f688bSRobert Mustacchi strerror(errno)); 342bc1f688bSRobert Mustacchi } 343bc1f688bSRobert Mustacchi 344bc1f688bSRobert Mustacchi /* 345bc1f688bSRobert Mustacchi * By default we remove the input file on failure unless we've been 346bc1f688bSRobert Mustacchi * given an output file or -k has been specified. 347bc1f688bSRobert Mustacchi */ 348bc1f688bSRobert Mustacchi if (outfile != NULL && strcmp(infile, outfile) != 0) 349bc1f688bSRobert Mustacchi keep = B_TRUE; 350bc1f688bSRobert Mustacchi 351dd442252SAndy Fiddaman cch = ctf_convert_init(&err); 352dd442252SAndy Fiddaman if (cch == NULL) { 353dd442252SAndy Fiddaman ctfconvert_fatal( 354dd442252SAndy Fiddaman "failed to create libctf conversion handle: %s\n", 355dd442252SAndy Fiddaman strerror(err)); 356dd442252SAndy Fiddaman } 357dd442252SAndy Fiddaman if ((err = ctf_convert_set_nthreads(cch, nthreads)) != 0) 358dd442252SAndy Fiddaman ctfconvert_fatal("Could not set number of threads: %s\n", 359dd442252SAndy Fiddaman strerror(err)); 360dd442252SAndy Fiddaman if ((err = ctf_convert_set_batchsize(cch, bsize)) != 0) 361dd442252SAndy Fiddaman ctfconvert_fatal("Could not set batch size: %s\n", 362dd442252SAndy Fiddaman strerror(err)); 363dd442252SAndy Fiddaman if ((err = ctf_convert_set_flags(cch, flags)) != 0) 364dd442252SAndy Fiddaman ctfconvert_fatal("Could not set conversion flags: %s\n", 365dd442252SAndy Fiddaman strerror(err)); 366dd442252SAndy Fiddaman if (label != NULL && (err = ctf_convert_set_label(cch, label)) != 0) 367dd442252SAndy Fiddaman ctfconvert_fatal("Could not set label: %s\n", 368dd442252SAndy Fiddaman strerror(err)); 369dd442252SAndy Fiddaman if ((err = ctf_convert_set_warncb(cch, ctfconvert_warning, NULL)) != 0) 370dd442252SAndy Fiddaman ctfconvert_fatal("Could not set warning callback: %s\n", 371dd442252SAndy Fiddaman strerror(err)); 372dd442252SAndy Fiddaman 373dd442252SAndy Fiddaman ofp = ctf_fdconvert(cch, ifd, &err, buf, sizeof (buf)); 374dd442252SAndy Fiddaman 375dd442252SAndy Fiddaman ctf_convert_fini(cch); 376dd442252SAndy Fiddaman 377bc1f688bSRobert Mustacchi if (ofp == NULL) { 378bc1f688bSRobert Mustacchi /* 3793eca6103SJohn Levon * Normally, ctfconvert requires that its input file has at 3803eca6103SJohn Levon * least one C-source compilation unit, and that every C-source 3813eca6103SJohn Levon * compilation unit has DWARF. This is to avoid accidentally 3823eca6103SJohn Levon * leaving out useful CTF. 3833eca6103SJohn Levon * 3843eca6103SJohn Levon * However, for the benefit of intransigent build environments, 3853eca6103SJohn Levon * the -i and -m options can be used to relax this. 386bc1f688bSRobert Mustacchi */ 3873eca6103SJohn Levon if (err == ECTF_CONVNOCSRC && ignore_non_c) { 388bc1f688bSRobert Mustacchi exit(CTFCONVERT_OK); 389bc1f688bSRobert Mustacchi } 3903eca6103SJohn Levon 3913eca6103SJohn Levon if (err == ECTF_CONVNODEBUG && 3923eca6103SJohn Levon (flags & CTF_ALLOW_MISSING_DEBUG) != 0) { 3933eca6103SJohn Levon exit(CTFCONVERT_OK); 3943eca6103SJohn Levon } 3953eca6103SJohn Levon 396bc1f688bSRobert Mustacchi if (keep == B_FALSE) 397bc1f688bSRobert Mustacchi (void) unlink(infile); 3983eca6103SJohn Levon 399dd442252SAndy Fiddaman switch (err) { 400dd442252SAndy Fiddaman case ECTF_CONVBKERR: 401dd442252SAndy Fiddaman ctfconvert_fatal("CTF conversion failed: %s", buf); 402dd442252SAndy Fiddaman break; 403dd442252SAndy Fiddaman case ECTF_CONVNODEBUG: 404dd442252SAndy Fiddaman ctfconvert_fatal("CTF conversion failed due to " 405dd442252SAndy Fiddaman "missing debug data; use -m to override\n"); 406dd442252SAndy Fiddaman break; 407dd442252SAndy Fiddaman default: 408dd442252SAndy Fiddaman if (*buf != '\0') { 409dd442252SAndy Fiddaman (void) fprintf(stderr, "%s: %s", 410dd442252SAndy Fiddaman ctfconvert_progname, buf); 411dd442252SAndy Fiddaman } 4123eca6103SJohn Levon ctfconvert_fatal("CTF conversion failed: %s\n", 4133eca6103SJohn Levon ctf_errmsg(err)); 4143eca6103SJohn Levon } 415bc1f688bSRobert Mustacchi } 416bc1f688bSRobert Mustacchi 417bc1f688bSRobert Mustacchi if (optx == B_TRUE) 418bc1f688bSRobert Mustacchi ctfconvert_fixup_genunix(ofp); 419bc1f688bSRobert Mustacchi 420bc1f688bSRobert Mustacchi tmpfile = NULL; 421bc1f688bSRobert Mustacchi if (outfile == NULL || strcmp(infile, outfile) == 0) { 422bc1f688bSRobert Mustacchi if (asprintf(&tmpfile, "%s.ctf", infile) == -1) { 423bc1f688bSRobert Mustacchi if (keep == B_FALSE) 424bc1f688bSRobert Mustacchi (void) unlink(infile); 425bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to allocate memory for " 426bc1f688bSRobert Mustacchi "temporary file: %s\n", strerror(errno)); 427bc1f688bSRobert Mustacchi } 428bc1f688bSRobert Mustacchi outfile = tmpfile; 429bc1f688bSRobert Mustacchi } 430bc1f688bSRobert Mustacchi err = ctf_elfwrite(ofp, infile, outfile, CTF_ELFWRITE_F_COMPRESS); 431bc1f688bSRobert Mustacchi if (err == CTF_ERR) { 432bc1f688bSRobert Mustacchi (void) unlink(outfile); 433bc1f688bSRobert Mustacchi if (keep == B_FALSE) 434bc1f688bSRobert Mustacchi (void) unlink(infile); 435bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to write CTF section to output file: " 436dd442252SAndy Fiddaman "%s\n", ctf_errmsg(ctf_errno(ofp))); 437bc1f688bSRobert Mustacchi } 438bc1f688bSRobert Mustacchi ctf_close(ofp); 439bc1f688bSRobert Mustacchi 440bc1f688bSRobert Mustacchi if (tmpfile != NULL) { 441bc1f688bSRobert Mustacchi if (rename(tmpfile, infile) != 0) { 442bc1f688bSRobert Mustacchi int e = errno; 443bc1f688bSRobert Mustacchi (void) unlink(outfile); 444bc1f688bSRobert Mustacchi if (keep == B_FALSE) 445bc1f688bSRobert Mustacchi (void) unlink(infile); 446bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to rename temporary file: " 447bc1f688bSRobert Mustacchi "%s\n", strerror(e)); 448bc1f688bSRobert Mustacchi } 449bc1f688bSRobert Mustacchi } 450bc1f688bSRobert Mustacchi free(tmpfile); 451bc1f688bSRobert Mustacchi 452bc1f688bSRobert Mustacchi return (CTFCONVERT_OK); 453bc1f688bSRobert Mustacchi } 454