1*7fd79137SRobert Mustacchi /* 2*7fd79137SRobert Mustacchi * This file and its contents are supplied under the terms of the 3*7fd79137SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0. 4*7fd79137SRobert Mustacchi * You may only use this file in accordance with the terms of version 5*7fd79137SRobert Mustacchi * 1.0 of the CDDL. 6*7fd79137SRobert Mustacchi * 7*7fd79137SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this 8*7fd79137SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at 9*7fd79137SRobert Mustacchi * http://www.illumos.org/license/CDDL. 10*7fd79137SRobert Mustacchi */ 11*7fd79137SRobert Mustacchi 12*7fd79137SRobert Mustacchi /* 13*7fd79137SRobert Mustacchi * Copyright (c) 2015, Joyent, Inc. 14*7fd79137SRobert Mustacchi */ 15*7fd79137SRobert Mustacchi 16*7fd79137SRobert Mustacchi /* 17*7fd79137SRobert Mustacchi * Create CTF from extant debugging information 18*7fd79137SRobert Mustacchi */ 19*7fd79137SRobert Mustacchi 20*7fd79137SRobert Mustacchi #include <stdio.h> 21*7fd79137SRobert Mustacchi #include <unistd.h> 22*7fd79137SRobert Mustacchi #include <stdlib.h> 23*7fd79137SRobert Mustacchi #include <stdarg.h> 24*7fd79137SRobert Mustacchi #include <sys/types.h> 25*7fd79137SRobert Mustacchi #include <sys/stat.h> 26*7fd79137SRobert Mustacchi #include <fcntl.h> 27*7fd79137SRobert Mustacchi #include <errno.h> 28*7fd79137SRobert Mustacchi #include <libelf.h> 29*7fd79137SRobert Mustacchi #include <libctf.h> 30*7fd79137SRobert Mustacchi #include <string.h> 31*7fd79137SRobert Mustacchi #include <libgen.h> 32*7fd79137SRobert Mustacchi #include <limits.h> 33*7fd79137SRobert Mustacchi #include <strings.h> 34*7fd79137SRobert Mustacchi #include <sys/debug.h> 35*7fd79137SRobert Mustacchi 36*7fd79137SRobert Mustacchi #define CTFCONVERT_OK 0 37*7fd79137SRobert Mustacchi #define CTFCONVERT_FATAL 1 38*7fd79137SRobert Mustacchi #define CTFCONVERT_USAGE 2 39*7fd79137SRobert Mustacchi 40*7fd79137SRobert Mustacchi #define CTFCONVERT_DEFAULT_NTHREADS 4 41*7fd79137SRobert Mustacchi 42*7fd79137SRobert Mustacchi #define CTFCONVERT_ALTEXEC "CTFCONVERT_ALTEXEC" 43*7fd79137SRobert Mustacchi 44*7fd79137SRobert Mustacchi static char *ctfconvert_progname; 45*7fd79137SRobert Mustacchi 46*7fd79137SRobert Mustacchi static void 47*7fd79137SRobert Mustacchi ctfconvert_fatal(const char *fmt, ...) 48*7fd79137SRobert Mustacchi { 49*7fd79137SRobert Mustacchi va_list ap; 50*7fd79137SRobert Mustacchi 51*7fd79137SRobert Mustacchi (void) fprintf(stderr, "%s: ", ctfconvert_progname); 52*7fd79137SRobert Mustacchi va_start(ap, fmt); 53*7fd79137SRobert Mustacchi (void) vfprintf(stderr, fmt, ap); 54*7fd79137SRobert Mustacchi va_end(ap); 55*7fd79137SRobert Mustacchi 56*7fd79137SRobert Mustacchi exit(CTFCONVERT_FATAL); 57*7fd79137SRobert Mustacchi } 58*7fd79137SRobert Mustacchi 59*7fd79137SRobert Mustacchi 60*7fd79137SRobert Mustacchi static void 61*7fd79137SRobert Mustacchi ctfconvert_usage(const char *fmt, ...) 62*7fd79137SRobert Mustacchi { 63*7fd79137SRobert Mustacchi if (fmt != NULL) { 64*7fd79137SRobert Mustacchi va_list ap; 65*7fd79137SRobert Mustacchi 66*7fd79137SRobert Mustacchi (void) fprintf(stderr, "%s: ", ctfconvert_progname); 67*7fd79137SRobert Mustacchi va_start(ap, fmt); 68*7fd79137SRobert Mustacchi (void) vfprintf(stderr, fmt, ap); 69*7fd79137SRobert Mustacchi va_end(ap); 70*7fd79137SRobert Mustacchi } 71*7fd79137SRobert Mustacchi 72*7fd79137SRobert Mustacchi (void) fprintf(stderr, "Usage: %s [-is] [-j nthrs] [-l label | " 73*7fd79137SRobert Mustacchi "-L labelenv] [-o outfile] input\n" 74*7fd79137SRobert Mustacchi "\n" 75*7fd79137SRobert Mustacchi "\t-i ignore files not built partially from C sources\n" 76*7fd79137SRobert Mustacchi "\t-j use nthrs threads to perform the merge\n" 77*7fd79137SRobert Mustacchi "\t-k keep around original input file on failure\n" 78*7fd79137SRobert Mustacchi "\t-o copy input to outfile and add CTF\n" 79*7fd79137SRobert Mustacchi "\t-l set output container's label to specified value\n" 80*7fd79137SRobert Mustacchi "\t-L set output container's label to value from environment\n", 81*7fd79137SRobert Mustacchi ctfconvert_progname); 82*7fd79137SRobert Mustacchi } 83*7fd79137SRobert Mustacchi 84*7fd79137SRobert Mustacchi /* 85*7fd79137SRobert Mustacchi * This is a bit unfortunate. Traditionally we do type uniquification across all 86*7fd79137SRobert Mustacchi * modules in the kernel, including ip and unix against genunix. However, when 87*7fd79137SRobert Mustacchi * _MACHDEP is defined, then the cpu_t ends up having an additional member 88*7fd79137SRobert Mustacchi * (cpu_m), thus changing the ability for us to uniquify against it. This in 89*7fd79137SRobert Mustacchi * turn causes a lot of type sprawl, as there's a lot of things that end up 90*7fd79137SRobert Mustacchi * referring to the cpu_t and it chains out from there. 91*7fd79137SRobert Mustacchi * 92*7fd79137SRobert Mustacchi * So, if we find that a cpu_t has been defined and it has a couple of useful 93*7fd79137SRobert Mustacchi * sentinel members and it does *not* have the cpu_m member, then we will try 94*7fd79137SRobert Mustacchi * and lookup or create a forward declaration to the machcpu, append it to the 95*7fd79137SRobert Mustacchi * end, and update the file. 96*7fd79137SRobert Mustacchi * 97*7fd79137SRobert Mustacchi * This currently is only invoked if an undocumented option -X is passed. This 98*7fd79137SRobert Mustacchi * value is private to illumos and it can be changed at any time inside of it, 99*7fd79137SRobert Mustacchi * so if -X wants to be used for something, it should be. The ability to rely on 100*7fd79137SRobert Mustacchi * -X for others is strictly not an interface in any way, shape, or form. 101*7fd79137SRobert Mustacchi * 102*7fd79137SRobert Mustacchi * The following struct contains most of the information that we care about and 103*7fd79137SRobert Mustacchi * that we want to validate exists before we decide what to do. 104*7fd79137SRobert Mustacchi */ 105*7fd79137SRobert Mustacchi 106*7fd79137SRobert Mustacchi typedef struct ctfconvert_fixup { 107*7fd79137SRobert Mustacchi boolean_t cf_cyclic; /* Do we have a cpu_cyclic member */ 108*7fd79137SRobert Mustacchi boolean_t cf_mcpu; /* We have a cpu_m member */ 109*7fd79137SRobert Mustacchi boolean_t cf_lastpad; /* Is the pad member the last entry */ 110*7fd79137SRobert Mustacchi ulong_t cf_padoff; /* offset of the pad */ 111*7fd79137SRobert Mustacchi } ctfconvert_fixup_t; 112*7fd79137SRobert Mustacchi 113*7fd79137SRobert Mustacchi /* ARGSUSED */ 114*7fd79137SRobert Mustacchi static int 115*7fd79137SRobert Mustacchi ctfconvert_fixup_genunix_cb(const char *name, ctf_id_t tid, ulong_t off, 116*7fd79137SRobert Mustacchi void *arg) 117*7fd79137SRobert Mustacchi { 118*7fd79137SRobert Mustacchi ctfconvert_fixup_t *cfp = arg; 119*7fd79137SRobert Mustacchi 120*7fd79137SRobert Mustacchi cfp->cf_lastpad = B_FALSE; 121*7fd79137SRobert Mustacchi if (strcmp(name, "cpu_cyclic") == 0) { 122*7fd79137SRobert Mustacchi cfp->cf_cyclic = B_TRUE; 123*7fd79137SRobert Mustacchi return (0); 124*7fd79137SRobert Mustacchi } 125*7fd79137SRobert Mustacchi 126*7fd79137SRobert Mustacchi if (strcmp(name, "cpu_m") == 0) { 127*7fd79137SRobert Mustacchi cfp->cf_mcpu = B_TRUE; 128*7fd79137SRobert Mustacchi return (0); 129*7fd79137SRobert Mustacchi } 130*7fd79137SRobert Mustacchi 131*7fd79137SRobert Mustacchi if (strcmp(name, "cpu_m_pad") == 0) { 132*7fd79137SRobert Mustacchi cfp->cf_lastpad = B_TRUE; 133*7fd79137SRobert Mustacchi cfp->cf_padoff = off; 134*7fd79137SRobert Mustacchi return (0); 135*7fd79137SRobert Mustacchi } 136*7fd79137SRobert Mustacchi 137*7fd79137SRobert Mustacchi return (0); 138*7fd79137SRobert Mustacchi } 139*7fd79137SRobert Mustacchi 140*7fd79137SRobert Mustacchi static void 141*7fd79137SRobert Mustacchi ctfconvert_fixup_genunix(ctf_file_t *fp) 142*7fd79137SRobert Mustacchi { 143*7fd79137SRobert Mustacchi ctf_id_t cpuid, mcpu; 144*7fd79137SRobert Mustacchi ssize_t sz; 145*7fd79137SRobert Mustacchi ctfconvert_fixup_t cf; 146*7fd79137SRobert Mustacchi int model, ptrsz; 147*7fd79137SRobert Mustacchi 148*7fd79137SRobert Mustacchi cpuid = ctf_lookup_by_name(fp, "struct cpu"); 149*7fd79137SRobert Mustacchi if (cpuid == CTF_ERR) 150*7fd79137SRobert Mustacchi return; 151*7fd79137SRobert Mustacchi 152*7fd79137SRobert Mustacchi if (ctf_type_kind(fp, cpuid) != CTF_K_STRUCT) 153*7fd79137SRobert Mustacchi return; 154*7fd79137SRobert Mustacchi 155*7fd79137SRobert Mustacchi if ((sz = ctf_type_size(fp, cpuid)) == CTF_ERR) 156*7fd79137SRobert Mustacchi return; 157*7fd79137SRobert Mustacchi 158*7fd79137SRobert Mustacchi model = ctf_getmodel(fp); 159*7fd79137SRobert Mustacchi VERIFY(model == CTF_MODEL_ILP32 || model == CTF_MODEL_LP64); 160*7fd79137SRobert Mustacchi ptrsz = model == CTF_MODEL_ILP32 ? 4 : 8; 161*7fd79137SRobert Mustacchi 162*7fd79137SRobert Mustacchi bzero(&cf, sizeof (ctfconvert_fixup_t)); 163*7fd79137SRobert Mustacchi if (ctf_member_iter(fp, cpuid, ctfconvert_fixup_genunix_cb, &cf) == 164*7fd79137SRobert Mustacchi CTF_ERR) 165*7fd79137SRobert Mustacchi return; 166*7fd79137SRobert Mustacchi 167*7fd79137SRobert Mustacchi /* 168*7fd79137SRobert Mustacchi * Finally, we want to verify that the cpu_m is actually the last member 169*7fd79137SRobert Mustacchi * that we have here. 170*7fd79137SRobert Mustacchi */ 171*7fd79137SRobert Mustacchi if (cf.cf_cyclic == B_FALSE || cf.cf_mcpu == B_TRUE || 172*7fd79137SRobert Mustacchi cf.cf_lastpad == B_FALSE) { 173*7fd79137SRobert Mustacchi return; 174*7fd79137SRobert Mustacchi } 175*7fd79137SRobert Mustacchi 176*7fd79137SRobert Mustacchi if (cf.cf_padoff + ptrsz * NBBY != sz * NBBY) { 177*7fd79137SRobert Mustacchi return; 178*7fd79137SRobert Mustacchi } 179*7fd79137SRobert Mustacchi 180*7fd79137SRobert Mustacchi /* 181*7fd79137SRobert Mustacchi * Okay, we're going to do this, try to find a struct machcpu. We either 182*7fd79137SRobert Mustacchi * want a forward or a struct. If we find something else, error. If we 183*7fd79137SRobert Mustacchi * find nothing, add a forward and then add the member. 184*7fd79137SRobert Mustacchi */ 185*7fd79137SRobert Mustacchi mcpu = ctf_lookup_by_name(fp, "struct machcpu"); 186*7fd79137SRobert Mustacchi if (mcpu == CTF_ERR) { 187*7fd79137SRobert Mustacchi mcpu = ctf_add_forward(fp, CTF_ADD_NONROOT, "machcpu", 188*7fd79137SRobert Mustacchi CTF_K_STRUCT); 189*7fd79137SRobert Mustacchi if (mcpu == CTF_ERR) { 190*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to add 'struct machcpu' " 191*7fd79137SRobert Mustacchi "forward: %s", ctf_errmsg(ctf_errno(fp))); 192*7fd79137SRobert Mustacchi } 193*7fd79137SRobert Mustacchi } else { 194*7fd79137SRobert Mustacchi int kind; 195*7fd79137SRobert Mustacchi if ((kind = ctf_type_kind(fp, mcpu)) == CTF_ERR) { 196*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to get the type kind for " 197*7fd79137SRobert Mustacchi "the struct machcpu: %s", 198*7fd79137SRobert Mustacchi ctf_errmsg(ctf_errno(fp))); 199*7fd79137SRobert Mustacchi } 200*7fd79137SRobert Mustacchi 201*7fd79137SRobert Mustacchi if (kind != CTF_K_STRUCT && kind != CTF_K_FORWARD) 202*7fd79137SRobert Mustacchi ctfconvert_fatal("encountered a struct machcpu of the " 203*7fd79137SRobert Mustacchi "wrong type, found type kind %d\n", kind); 204*7fd79137SRobert Mustacchi } 205*7fd79137SRobert Mustacchi 206*7fd79137SRobert Mustacchi if (ctf_update(fp) == CTF_ERR) { 207*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to update output file: %s\n", 208*7fd79137SRobert Mustacchi ctf_errmsg(ctf_errno(fp))); 209*7fd79137SRobert Mustacchi } 210*7fd79137SRobert Mustacchi 211*7fd79137SRobert Mustacchi if (ctf_add_member(fp, cpuid, "cpu_m", mcpu, sz * NBBY) == CTF_ERR) { 212*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to add the m_cpu member: %s\n", 213*7fd79137SRobert Mustacchi ctf_errmsg(ctf_errno(fp))); 214*7fd79137SRobert Mustacchi } 215*7fd79137SRobert Mustacchi 216*7fd79137SRobert Mustacchi if (ctf_update(fp) == CTF_ERR) { 217*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to update output file: %s\n", 218*7fd79137SRobert Mustacchi ctf_errmsg(ctf_errno(fp))); 219*7fd79137SRobert Mustacchi } 220*7fd79137SRobert Mustacchi 221*7fd79137SRobert Mustacchi VERIFY(ctf_type_size(fp, cpuid) == sz); 222*7fd79137SRobert Mustacchi } 223*7fd79137SRobert Mustacchi 224*7fd79137SRobert Mustacchi static void 225*7fd79137SRobert Mustacchi ctfconvert_altexec(char **argv) 226*7fd79137SRobert Mustacchi { 227*7fd79137SRobert Mustacchi const char *alt; 228*7fd79137SRobert Mustacchi char *altexec; 229*7fd79137SRobert Mustacchi 230*7fd79137SRobert Mustacchi alt = getenv(CTFCONVERT_ALTEXEC); 231*7fd79137SRobert Mustacchi if (alt == NULL || *alt == '\0') 232*7fd79137SRobert Mustacchi return; 233*7fd79137SRobert Mustacchi 234*7fd79137SRobert Mustacchi altexec = strdup(alt); 235*7fd79137SRobert Mustacchi if (altexec == NULL) 236*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to allocate memory for altexec\n"); 237*7fd79137SRobert Mustacchi if (unsetenv(CTFCONVERT_ALTEXEC) != 0) 238*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to unset %s from environment: %s\n", 239*7fd79137SRobert Mustacchi CTFCONVERT_ALTEXEC, strerror(errno)); 240*7fd79137SRobert Mustacchi 241*7fd79137SRobert Mustacchi (void) execv(altexec, argv); 242*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to execute alternate program %s: %s", 243*7fd79137SRobert Mustacchi altexec, strerror(errno)); 244*7fd79137SRobert Mustacchi } 245*7fd79137SRobert Mustacchi 246*7fd79137SRobert Mustacchi int 247*7fd79137SRobert Mustacchi main(int argc, char *argv[]) 248*7fd79137SRobert Mustacchi { 249*7fd79137SRobert Mustacchi int c, ifd, err; 250*7fd79137SRobert Mustacchi boolean_t keep = B_FALSE; 251*7fd79137SRobert Mustacchi uint_t flags = 0; 252*7fd79137SRobert Mustacchi uint_t nthreads = CTFCONVERT_DEFAULT_NTHREADS; 253*7fd79137SRobert Mustacchi const char *outfile = NULL; 254*7fd79137SRobert Mustacchi const char *label = NULL; 255*7fd79137SRobert Mustacchi const char *infile = NULL; 256*7fd79137SRobert Mustacchi char *tmpfile; 257*7fd79137SRobert Mustacchi ctf_file_t *ofp; 258*7fd79137SRobert Mustacchi long argj; 259*7fd79137SRobert Mustacchi char *eptr; 260*7fd79137SRobert Mustacchi char buf[4096]; 261*7fd79137SRobert Mustacchi boolean_t optx = B_FALSE; 262*7fd79137SRobert Mustacchi 263*7fd79137SRobert Mustacchi ctfconvert_progname = basename(argv[0]); 264*7fd79137SRobert Mustacchi 265*7fd79137SRobert Mustacchi ctfconvert_altexec(argv); 266*7fd79137SRobert Mustacchi 267*7fd79137SRobert Mustacchi while ((c = getopt(argc, argv, ":j:kl:L:o:iX")) != -1) { 268*7fd79137SRobert Mustacchi switch (c) { 269*7fd79137SRobert Mustacchi case 'k': 270*7fd79137SRobert Mustacchi keep = B_TRUE; 271*7fd79137SRobert Mustacchi break; 272*7fd79137SRobert Mustacchi case 'l': 273*7fd79137SRobert Mustacchi label = optarg; 274*7fd79137SRobert Mustacchi break; 275*7fd79137SRobert Mustacchi case 'L': 276*7fd79137SRobert Mustacchi label = getenv(optarg); 277*7fd79137SRobert Mustacchi break; 278*7fd79137SRobert Mustacchi case 'j': 279*7fd79137SRobert Mustacchi errno = 0; 280*7fd79137SRobert Mustacchi argj = strtol(optarg, &eptr, 10); 281*7fd79137SRobert Mustacchi if (errno != 0 || argj == LONG_MAX || 282*7fd79137SRobert Mustacchi argj > 1024 || *eptr != '\0') { 283*7fd79137SRobert Mustacchi ctfconvert_fatal("invalid argument for -j: " 284*7fd79137SRobert Mustacchi "%s\n", optarg); 285*7fd79137SRobert Mustacchi } 286*7fd79137SRobert Mustacchi nthreads = (uint_t)argj; 287*7fd79137SRobert Mustacchi break; 288*7fd79137SRobert Mustacchi case 'o': 289*7fd79137SRobert Mustacchi outfile = optarg; 290*7fd79137SRobert Mustacchi break; 291*7fd79137SRobert Mustacchi case 'i': 292*7fd79137SRobert Mustacchi flags |= CTF_CONVERT_F_IGNNONC; 293*7fd79137SRobert Mustacchi break; 294*7fd79137SRobert Mustacchi case 'X': 295*7fd79137SRobert Mustacchi optx = B_TRUE; 296*7fd79137SRobert Mustacchi break; 297*7fd79137SRobert Mustacchi case ':': 298*7fd79137SRobert Mustacchi ctfconvert_usage("Option -%c requires an operand\n", 299*7fd79137SRobert Mustacchi optopt); 300*7fd79137SRobert Mustacchi return (CTFCONVERT_USAGE); 301*7fd79137SRobert Mustacchi case '?': 302*7fd79137SRobert Mustacchi ctfconvert_usage("Unknown option: -%c\n", optopt); 303*7fd79137SRobert Mustacchi return (CTFCONVERT_USAGE); 304*7fd79137SRobert Mustacchi } 305*7fd79137SRobert Mustacchi } 306*7fd79137SRobert Mustacchi 307*7fd79137SRobert Mustacchi argv += optind; 308*7fd79137SRobert Mustacchi argc -= optind; 309*7fd79137SRobert Mustacchi 310*7fd79137SRobert Mustacchi if (argc < 1) { 311*7fd79137SRobert Mustacchi ctfconvert_usage("Missing required input file\n"); 312*7fd79137SRobert Mustacchi return (CTFCONVERT_USAGE); 313*7fd79137SRobert Mustacchi } 314*7fd79137SRobert Mustacchi infile = argv[0]; 315*7fd79137SRobert Mustacchi 316*7fd79137SRobert Mustacchi if (elf_version(EV_CURRENT) == EV_NONE) 317*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to initialize libelf: library is " 318*7fd79137SRobert Mustacchi "out of date\n"); 319*7fd79137SRobert Mustacchi 320*7fd79137SRobert Mustacchi ifd = open(infile, O_RDONLY); 321*7fd79137SRobert Mustacchi if (ifd < 0) { 322*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to open input file %s: %s\n", infile, 323*7fd79137SRobert Mustacchi strerror(errno)); 324*7fd79137SRobert Mustacchi } 325*7fd79137SRobert Mustacchi 326*7fd79137SRobert Mustacchi /* 327*7fd79137SRobert Mustacchi * By default we remove the input file on failure unless we've been 328*7fd79137SRobert Mustacchi * given an output file or -k has been specified. 329*7fd79137SRobert Mustacchi */ 330*7fd79137SRobert Mustacchi if (outfile != NULL && strcmp(infile, outfile) != 0) 331*7fd79137SRobert Mustacchi keep = B_TRUE; 332*7fd79137SRobert Mustacchi 333*7fd79137SRobert Mustacchi ofp = ctf_fdconvert(ifd, label, nthreads, flags, &err, buf, 334*7fd79137SRobert Mustacchi sizeof (buf)); 335*7fd79137SRobert Mustacchi if (ofp == NULL) { 336*7fd79137SRobert Mustacchi /* 337*7fd79137SRobert Mustacchi * -i says that we shouldn't concern ourselves with source files 338*7fd79137SRobert Mustacchi * that weren't built from C source code in part. Because this 339*7fd79137SRobert Mustacchi * has been traditionally used across all of illumos, we still 340*7fd79137SRobert Mustacchi * honor it. 341*7fd79137SRobert Mustacchi */ 342*7fd79137SRobert Mustacchi if ((flags & CTF_CONVERT_F_IGNNONC) != 0 && 343*7fd79137SRobert Mustacchi err == ECTF_CONVNOCSRC) { 344*7fd79137SRobert Mustacchi exit(CTFCONVERT_OK); 345*7fd79137SRobert Mustacchi } 346*7fd79137SRobert Mustacchi if (keep == B_FALSE) 347*7fd79137SRobert Mustacchi (void) unlink(infile); 348*7fd79137SRobert Mustacchi ctfconvert_fatal("CTF conversion failed: %s\n", 349*7fd79137SRobert Mustacchi err == ECTF_CONVBKERR ? buf : ctf_errmsg(err)); 350*7fd79137SRobert Mustacchi } 351*7fd79137SRobert Mustacchi 352*7fd79137SRobert Mustacchi if (optx == B_TRUE) 353*7fd79137SRobert Mustacchi ctfconvert_fixup_genunix(ofp); 354*7fd79137SRobert Mustacchi 355*7fd79137SRobert Mustacchi tmpfile = NULL; 356*7fd79137SRobert Mustacchi if (outfile == NULL || strcmp(infile, outfile) == 0) { 357*7fd79137SRobert Mustacchi if (asprintf(&tmpfile, "%s.ctf", infile) == -1) { 358*7fd79137SRobert Mustacchi if (keep == B_FALSE) 359*7fd79137SRobert Mustacchi (void) unlink(infile); 360*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to allocate memory for " 361*7fd79137SRobert Mustacchi "temporary file: %s\n", strerror(errno)); 362*7fd79137SRobert Mustacchi } 363*7fd79137SRobert Mustacchi outfile = tmpfile; 364*7fd79137SRobert Mustacchi } 365*7fd79137SRobert Mustacchi err = ctf_elfwrite(ofp, infile, outfile, CTF_ELFWRITE_F_COMPRESS); 366*7fd79137SRobert Mustacchi if (err == CTF_ERR) { 367*7fd79137SRobert Mustacchi (void) unlink(outfile); 368*7fd79137SRobert Mustacchi if (keep == B_FALSE) 369*7fd79137SRobert Mustacchi (void) unlink(infile); 370*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to write CTF section to output file: " 371*7fd79137SRobert Mustacchi "%s", ctf_errmsg(ctf_errno(ofp))); 372*7fd79137SRobert Mustacchi } 373*7fd79137SRobert Mustacchi ctf_close(ofp); 374*7fd79137SRobert Mustacchi 375*7fd79137SRobert Mustacchi if (tmpfile != NULL) { 376*7fd79137SRobert Mustacchi if (rename(tmpfile, infile) != 0) { 377*7fd79137SRobert Mustacchi int e = errno; 378*7fd79137SRobert Mustacchi (void) unlink(outfile); 379*7fd79137SRobert Mustacchi if (keep == B_FALSE) 380*7fd79137SRobert Mustacchi (void) unlink(infile); 381*7fd79137SRobert Mustacchi ctfconvert_fatal("failed to rename temporary file: " 382*7fd79137SRobert Mustacchi "%s\n", strerror(e)); 383*7fd79137SRobert Mustacchi } 384*7fd79137SRobert Mustacchi } 385*7fd79137SRobert Mustacchi free(tmpfile); 386*7fd79137SRobert Mustacchi 387*7fd79137SRobert Mustacchi return (CTFCONVERT_OK); 388*7fd79137SRobert Mustacchi } 389