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