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 8373197b54SAndy Fiddaman (void) fprintf(stderr, "Usage: %s [-fikms] [-j nthrs] [-l label | " 84effb27eeSAndy Fiddaman "-L labelenv] [-b batchsize]\n" 85*88a08813SAndy Fiddaman " [-o outfile] [-M ignorefile] input\n" 86bc1f688bSRobert Mustacchi "\n" 87effb27eeSAndy Fiddaman "\t-b batch process this many dies at a time (default %d)\n" 8873197b54SAndy 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" 95*88a08813SAndy Fiddaman "\t-M allow files listed in ignorefile to have missing debug\n" 96dd442252SAndy Fiddaman "\t-o copy input to outfile and add CTF\n" 97dd442252SAndy Fiddaman "\t-s allow truncation of data that cannot be fully converted\n", 98effb27eeSAndy Fiddaman ctfconvert_progname, 99dd442252SAndy Fiddaman CTF_CONVERT_DEFAULT_BATCHSIZE, 100dd442252SAndy Fiddaman CTF_CONVERT_DEFAULT_NTHREADS); 101bc1f688bSRobert Mustacchi } 102bc1f688bSRobert Mustacchi 103bc1f688bSRobert Mustacchi /* 104bc1f688bSRobert Mustacchi * This is a bit unfortunate. Traditionally we do type uniquification across all 105bc1f688bSRobert Mustacchi * modules in the kernel, including ip and unix against genunix. However, when 106bc1f688bSRobert Mustacchi * _MACHDEP is defined, then the cpu_t ends up having an additional member 107bc1f688bSRobert Mustacchi * (cpu_m), thus changing the ability for us to uniquify against it. This in 108bc1f688bSRobert Mustacchi * turn causes a lot of type sprawl, as there's a lot of things that end up 109bc1f688bSRobert Mustacchi * referring to the cpu_t and it chains out from there. 110bc1f688bSRobert Mustacchi * 111bc1f688bSRobert Mustacchi * So, if we find that a cpu_t has been defined and it has a couple of useful 112bc1f688bSRobert Mustacchi * sentinel members and it does *not* have the cpu_m member, then we will try 113bc1f688bSRobert Mustacchi * and lookup or create a forward declaration to the machcpu, append it to the 114bc1f688bSRobert Mustacchi * end, and update the file. 115bc1f688bSRobert Mustacchi * 116bc1f688bSRobert Mustacchi * This currently is only invoked if an undocumented option -X is passed. This 117bc1f688bSRobert Mustacchi * value is private to illumos and it can be changed at any time inside of it, 118bc1f688bSRobert Mustacchi * so if -X wants to be used for something, it should be. The ability to rely on 119bc1f688bSRobert Mustacchi * -X for others is strictly not an interface in any way, shape, or form. 120bc1f688bSRobert Mustacchi * 121bc1f688bSRobert Mustacchi * The following struct contains most of the information that we care about and 122bc1f688bSRobert Mustacchi * that we want to validate exists before we decide what to do. 123bc1f688bSRobert Mustacchi */ 124bc1f688bSRobert Mustacchi 125bc1f688bSRobert Mustacchi typedef struct ctfconvert_fixup { 126bc1f688bSRobert Mustacchi boolean_t cf_cyclic; /* Do we have a cpu_cyclic member */ 127bc1f688bSRobert Mustacchi boolean_t cf_mcpu; /* We have a cpu_m member */ 128bc1f688bSRobert Mustacchi boolean_t cf_lastpad; /* Is the pad member the last entry */ 129bc1f688bSRobert Mustacchi ulong_t cf_padoff; /* offset of the pad */ 130bc1f688bSRobert Mustacchi } ctfconvert_fixup_t; 131bc1f688bSRobert Mustacchi 132bc1f688bSRobert Mustacchi /* ARGSUSED */ 133bc1f688bSRobert Mustacchi static int 134bc1f688bSRobert Mustacchi ctfconvert_fixup_genunix_cb(const char *name, ctf_id_t tid, ulong_t off, 135bc1f688bSRobert Mustacchi void *arg) 136bc1f688bSRobert Mustacchi { 137bc1f688bSRobert Mustacchi ctfconvert_fixup_t *cfp = arg; 138bc1f688bSRobert Mustacchi 139bc1f688bSRobert Mustacchi cfp->cf_lastpad = B_FALSE; 140bc1f688bSRobert Mustacchi if (strcmp(name, "cpu_cyclic") == 0) { 141bc1f688bSRobert Mustacchi cfp->cf_cyclic = B_TRUE; 142bc1f688bSRobert Mustacchi return (0); 143bc1f688bSRobert Mustacchi } 144bc1f688bSRobert Mustacchi 145bc1f688bSRobert Mustacchi if (strcmp(name, "cpu_m") == 0) { 146bc1f688bSRobert Mustacchi cfp->cf_mcpu = B_TRUE; 147bc1f688bSRobert Mustacchi return (0); 148bc1f688bSRobert Mustacchi } 149bc1f688bSRobert Mustacchi 150bc1f688bSRobert Mustacchi if (strcmp(name, "cpu_m_pad") == 0) { 151bc1f688bSRobert Mustacchi cfp->cf_lastpad = B_TRUE; 152bc1f688bSRobert Mustacchi cfp->cf_padoff = off; 153bc1f688bSRobert Mustacchi return (0); 154bc1f688bSRobert Mustacchi } 155bc1f688bSRobert Mustacchi 156bc1f688bSRobert Mustacchi return (0); 157bc1f688bSRobert Mustacchi } 158bc1f688bSRobert Mustacchi 159bc1f688bSRobert Mustacchi static void 160bc1f688bSRobert Mustacchi ctfconvert_fixup_genunix(ctf_file_t *fp) 161bc1f688bSRobert Mustacchi { 162bc1f688bSRobert Mustacchi ctf_id_t cpuid, mcpu; 163bc1f688bSRobert Mustacchi ssize_t sz; 164bc1f688bSRobert Mustacchi ctfconvert_fixup_t cf; 165bc1f688bSRobert Mustacchi int model, ptrsz; 166bc1f688bSRobert Mustacchi 167bc1f688bSRobert Mustacchi cpuid = ctf_lookup_by_name(fp, "struct cpu"); 168bc1f688bSRobert Mustacchi if (cpuid == CTF_ERR) 169bc1f688bSRobert Mustacchi return; 170bc1f688bSRobert Mustacchi 171bc1f688bSRobert Mustacchi if (ctf_type_kind(fp, cpuid) != CTF_K_STRUCT) 172bc1f688bSRobert Mustacchi return; 173bc1f688bSRobert Mustacchi 174bc1f688bSRobert Mustacchi if ((sz = ctf_type_size(fp, cpuid)) == CTF_ERR) 175bc1f688bSRobert Mustacchi return; 176bc1f688bSRobert Mustacchi 177bc1f688bSRobert Mustacchi model = ctf_getmodel(fp); 178bc1f688bSRobert Mustacchi VERIFY(model == CTF_MODEL_ILP32 || model == CTF_MODEL_LP64); 179bc1f688bSRobert Mustacchi ptrsz = model == CTF_MODEL_ILP32 ? 4 : 8; 180bc1f688bSRobert Mustacchi 181bc1f688bSRobert Mustacchi bzero(&cf, sizeof (ctfconvert_fixup_t)); 182bc1f688bSRobert Mustacchi if (ctf_member_iter(fp, cpuid, ctfconvert_fixup_genunix_cb, &cf) == 183bc1f688bSRobert Mustacchi CTF_ERR) 184bc1f688bSRobert Mustacchi return; 185bc1f688bSRobert Mustacchi 186bc1f688bSRobert Mustacchi /* 187bc1f688bSRobert Mustacchi * Finally, we want to verify that the cpu_m is actually the last member 188bc1f688bSRobert Mustacchi * that we have here. 189bc1f688bSRobert Mustacchi */ 190bc1f688bSRobert Mustacchi if (cf.cf_cyclic == B_FALSE || cf.cf_mcpu == B_TRUE || 191bc1f688bSRobert Mustacchi cf.cf_lastpad == B_FALSE) { 192bc1f688bSRobert Mustacchi return; 193bc1f688bSRobert Mustacchi } 194bc1f688bSRobert Mustacchi 195bc1f688bSRobert Mustacchi if (cf.cf_padoff + ptrsz * NBBY != sz * NBBY) { 196bc1f688bSRobert Mustacchi return; 197bc1f688bSRobert Mustacchi } 198bc1f688bSRobert Mustacchi 199bc1f688bSRobert Mustacchi /* 200bc1f688bSRobert Mustacchi * Okay, we're going to do this, try to find a struct machcpu. We either 201bc1f688bSRobert Mustacchi * want a forward or a struct. If we find something else, error. If we 202bc1f688bSRobert Mustacchi * find nothing, add a forward and then add the member. 203bc1f688bSRobert Mustacchi */ 204bc1f688bSRobert Mustacchi mcpu = ctf_lookup_by_name(fp, "struct machcpu"); 205bc1f688bSRobert Mustacchi if (mcpu == CTF_ERR) { 206bc1f688bSRobert Mustacchi mcpu = ctf_add_forward(fp, CTF_ADD_NONROOT, "machcpu", 207bc1f688bSRobert Mustacchi CTF_K_STRUCT); 208bc1f688bSRobert Mustacchi if (mcpu == CTF_ERR) { 209bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to add 'struct machcpu' " 210dd442252SAndy Fiddaman "forward: %s\n", ctf_errmsg(ctf_errno(fp))); 211bc1f688bSRobert Mustacchi } 212bc1f688bSRobert Mustacchi } else { 213bc1f688bSRobert Mustacchi int kind; 214bc1f688bSRobert Mustacchi if ((kind = ctf_type_kind(fp, mcpu)) == CTF_ERR) { 215bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to get the type kind for " 216dd442252SAndy Fiddaman "the struct machcpu: %s\n", 217bc1f688bSRobert Mustacchi ctf_errmsg(ctf_errno(fp))); 218bc1f688bSRobert Mustacchi } 219bc1f688bSRobert Mustacchi 220bc1f688bSRobert Mustacchi if (kind != CTF_K_STRUCT && kind != CTF_K_FORWARD) 221bc1f688bSRobert Mustacchi ctfconvert_fatal("encountered a struct machcpu of the " 222bc1f688bSRobert Mustacchi "wrong type, found type kind %d\n", kind); 223bc1f688bSRobert Mustacchi } 224bc1f688bSRobert Mustacchi 225bc1f688bSRobert Mustacchi if (ctf_update(fp) == CTF_ERR) { 226bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to update output file: %s\n", 227bc1f688bSRobert Mustacchi ctf_errmsg(ctf_errno(fp))); 228bc1f688bSRobert Mustacchi } 229bc1f688bSRobert Mustacchi 230bc1f688bSRobert Mustacchi if (ctf_add_member(fp, cpuid, "cpu_m", mcpu, sz * NBBY) == CTF_ERR) { 231bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to add the m_cpu member: %s\n", 232bc1f688bSRobert Mustacchi ctf_errmsg(ctf_errno(fp))); 233bc1f688bSRobert Mustacchi } 234bc1f688bSRobert Mustacchi 235bc1f688bSRobert Mustacchi if (ctf_update(fp) == CTF_ERR) { 236bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to update output file: %s\n", 237bc1f688bSRobert Mustacchi ctf_errmsg(ctf_errno(fp))); 238bc1f688bSRobert Mustacchi } 239bc1f688bSRobert Mustacchi 240bc1f688bSRobert Mustacchi VERIFY(ctf_type_size(fp, cpuid) == sz); 241bc1f688bSRobert Mustacchi } 242bc1f688bSRobert Mustacchi 243bc1f688bSRobert Mustacchi int 244bc1f688bSRobert Mustacchi main(int argc, char *argv[]) 245bc1f688bSRobert Mustacchi { 246bc1f688bSRobert Mustacchi int c, ifd, err; 247bc1f688bSRobert Mustacchi boolean_t keep = B_FALSE; 248dd442252SAndy Fiddaman ctf_convert_flag_t flags = 0; 249dd442252SAndy Fiddaman uint_t bsize = CTF_CONVERT_DEFAULT_BATCHSIZE; 250dd442252SAndy Fiddaman uint_t nthreads = CTF_CONVERT_DEFAULT_NTHREADS; 251bc1f688bSRobert Mustacchi const char *outfile = NULL; 252bc1f688bSRobert Mustacchi const char *label = NULL; 253bc1f688bSRobert Mustacchi const char *infile = NULL; 254*88a08813SAndy Fiddaman const char *ignorefile = NULL; 255bc1f688bSRobert Mustacchi char *tmpfile; 256bc1f688bSRobert Mustacchi ctf_file_t *ofp; 257dd442252SAndy Fiddaman char buf[4096] = ""; 258bc1f688bSRobert Mustacchi boolean_t optx = B_FALSE; 2593eca6103SJohn Levon boolean_t ignore_non_c = B_FALSE; 260dd442252SAndy Fiddaman ctf_convert_t *cch; 261bc1f688bSRobert Mustacchi 262bc1f688bSRobert Mustacchi ctfconvert_progname = basename(argv[0]); 263bc1f688bSRobert Mustacchi 264*88a08813SAndy Fiddaman while ((c = getopt(argc, argv, ":b:fij:kl:L:mM:o:sX")) != -1) { 265bc1f688bSRobert Mustacchi switch (c) { 266effb27eeSAndy Fiddaman case 'b': { 267effb27eeSAndy Fiddaman long argno; 268effb27eeSAndy Fiddaman const char *errstr; 269effb27eeSAndy Fiddaman 270effb27eeSAndy Fiddaman argno = strtonum(optarg, 1, UINT_MAX, &errstr); 271effb27eeSAndy Fiddaman if (errstr != NULL) { 272effb27eeSAndy Fiddaman ctfconvert_fatal("invalid argument for -b: " 273effb27eeSAndy Fiddaman "%s - %s\n", optarg, errstr); 274effb27eeSAndy Fiddaman } 275effb27eeSAndy Fiddaman bsize = (uint_t)argno; 276effb27eeSAndy Fiddaman break; 277effb27eeSAndy Fiddaman } 27873197b54SAndy Fiddaman case 'f': 27973197b54SAndy Fiddaman flags |= CTF_FORCE_CONVERSION; 28073197b54SAndy Fiddaman break; 2813eca6103SJohn Levon case 'i': 2823eca6103SJohn Levon ignore_non_c = B_TRUE; 283bc1f688bSRobert Mustacchi break; 284effb27eeSAndy Fiddaman case 'j': { 285effb27eeSAndy Fiddaman long argno; 286effb27eeSAndy Fiddaman const char *errstr; 287effb27eeSAndy Fiddaman 288effb27eeSAndy Fiddaman argno = strtonum(optarg, 1, 1024, &errstr); 289effb27eeSAndy Fiddaman if (errstr != NULL) { 290bc1f688bSRobert Mustacchi ctfconvert_fatal("invalid argument for -j: " 291effb27eeSAndy Fiddaman "%s - %s\n", optarg, errstr); 292bc1f688bSRobert Mustacchi } 293effb27eeSAndy Fiddaman nthreads = (uint_t)argno; 294bc1f688bSRobert Mustacchi break; 295effb27eeSAndy Fiddaman } 2963eca6103SJohn Levon case 'k': 2973eca6103SJohn Levon keep = B_TRUE; 2983eca6103SJohn Levon break; 2993eca6103SJohn Levon case 'l': 3003eca6103SJohn Levon label = optarg; 3013eca6103SJohn Levon break; 3023eca6103SJohn Levon case 'L': 3033eca6103SJohn Levon label = getenv(optarg); 3043eca6103SJohn Levon break; 3053eca6103SJohn Levon case 'm': 3063eca6103SJohn Levon flags |= CTF_ALLOW_MISSING_DEBUG; 3073eca6103SJohn Levon break; 308*88a08813SAndy Fiddaman case 'M': 309*88a08813SAndy Fiddaman ignorefile = optarg; 310*88a08813SAndy Fiddaman break; 311bc1f688bSRobert Mustacchi case 'o': 312bc1f688bSRobert Mustacchi outfile = optarg; 313bc1f688bSRobert Mustacchi break; 314dd442252SAndy Fiddaman case 's': 315dd442252SAndy Fiddaman flags |= CTF_ALLOW_TRUNCATION; 316dd442252SAndy Fiddaman break; 317bc1f688bSRobert Mustacchi case 'X': 318bc1f688bSRobert Mustacchi optx = B_TRUE; 319bc1f688bSRobert Mustacchi break; 320bc1f688bSRobert Mustacchi case ':': 321bc1f688bSRobert Mustacchi ctfconvert_usage("Option -%c requires an operand\n", 322bc1f688bSRobert Mustacchi optopt); 323bc1f688bSRobert Mustacchi return (CTFCONVERT_USAGE); 324bc1f688bSRobert Mustacchi case '?': 325bc1f688bSRobert Mustacchi ctfconvert_usage("Unknown option: -%c\n", optopt); 326bc1f688bSRobert Mustacchi return (CTFCONVERT_USAGE); 327bc1f688bSRobert Mustacchi } 328bc1f688bSRobert Mustacchi } 329bc1f688bSRobert Mustacchi 330bc1f688bSRobert Mustacchi argv += optind; 331bc1f688bSRobert Mustacchi argc -= optind; 332bc1f688bSRobert Mustacchi 3333eca6103SJohn Levon if (argc != 1) { 3343eca6103SJohn Levon ctfconvert_usage("Exactly one input file is required\n"); 335bc1f688bSRobert Mustacchi return (CTFCONVERT_USAGE); 336bc1f688bSRobert Mustacchi } 337bc1f688bSRobert Mustacchi infile = argv[0]; 338bc1f688bSRobert Mustacchi 339bc1f688bSRobert Mustacchi if (elf_version(EV_CURRENT) == EV_NONE) 340bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to initialize libelf: library is " 341bc1f688bSRobert Mustacchi "out of date\n"); 342bc1f688bSRobert Mustacchi 343bc1f688bSRobert Mustacchi ifd = open(infile, O_RDONLY); 344bc1f688bSRobert Mustacchi if (ifd < 0) { 345bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to open input file %s: %s\n", infile, 346bc1f688bSRobert Mustacchi strerror(errno)); 347bc1f688bSRobert Mustacchi } 348bc1f688bSRobert Mustacchi 349bc1f688bSRobert Mustacchi /* 350bc1f688bSRobert Mustacchi * By default we remove the input file on failure unless we've been 351bc1f688bSRobert Mustacchi * given an output file or -k has been specified. 352bc1f688bSRobert Mustacchi */ 353bc1f688bSRobert Mustacchi if (outfile != NULL && strcmp(infile, outfile) != 0) 354bc1f688bSRobert Mustacchi keep = B_TRUE; 355bc1f688bSRobert Mustacchi 356dd442252SAndy Fiddaman cch = ctf_convert_init(&err); 357dd442252SAndy Fiddaman if (cch == NULL) { 358dd442252SAndy Fiddaman ctfconvert_fatal( 359dd442252SAndy Fiddaman "failed to create libctf conversion handle: %s\n", 360dd442252SAndy Fiddaman strerror(err)); 361dd442252SAndy Fiddaman } 362dd442252SAndy Fiddaman if ((err = ctf_convert_set_nthreads(cch, nthreads)) != 0) 363dd442252SAndy Fiddaman ctfconvert_fatal("Could not set number of threads: %s\n", 364dd442252SAndy Fiddaman strerror(err)); 365dd442252SAndy Fiddaman if ((err = ctf_convert_set_batchsize(cch, bsize)) != 0) 366dd442252SAndy Fiddaman ctfconvert_fatal("Could not set batch size: %s\n", 367dd442252SAndy Fiddaman strerror(err)); 368dd442252SAndy Fiddaman if ((err = ctf_convert_set_flags(cch, flags)) != 0) 369dd442252SAndy Fiddaman ctfconvert_fatal("Could not set conversion flags: %s\n", 370dd442252SAndy Fiddaman strerror(err)); 371dd442252SAndy Fiddaman if (label != NULL && (err = ctf_convert_set_label(cch, label)) != 0) 372dd442252SAndy Fiddaman ctfconvert_fatal("Could not set label: %s\n", 373dd442252SAndy Fiddaman strerror(err)); 374dd442252SAndy Fiddaman if ((err = ctf_convert_set_warncb(cch, ctfconvert_warning, NULL)) != 0) 375dd442252SAndy Fiddaman ctfconvert_fatal("Could not set warning callback: %s\n", 376dd442252SAndy Fiddaman strerror(err)); 377dd442252SAndy Fiddaman 378*88a08813SAndy Fiddaman if (ignorefile != NULL) { 379*88a08813SAndy Fiddaman char *buf = NULL; 380*88a08813SAndy Fiddaman ssize_t cnt; 381*88a08813SAndy Fiddaman size_t len = 0; 382*88a08813SAndy Fiddaman FILE *fp; 383*88a08813SAndy Fiddaman 384*88a08813SAndy Fiddaman if ((fp = fopen(ignorefile, "r")) == NULL) { 385*88a08813SAndy Fiddaman ctfconvert_fatal("Could not open ignorefile '%s': %s\n", 386*88a08813SAndy Fiddaman ignorefile, strerror(errno)); 387*88a08813SAndy Fiddaman } 388*88a08813SAndy Fiddaman 389*88a08813SAndy Fiddaman while ((cnt = getline(&buf, &len, fp)) != -1) { 390*88a08813SAndy Fiddaman char *p = buf; 391*88a08813SAndy Fiddaman 392*88a08813SAndy Fiddaman if (cnt == 0 || *p == '#') 393*88a08813SAndy Fiddaman continue; 394*88a08813SAndy Fiddaman 395*88a08813SAndy Fiddaman (void) strsep(&p, "\n"); 396*88a08813SAndy Fiddaman if ((err = ctf_convert_add_ignore(cch, buf)) != 0) { 397*88a08813SAndy Fiddaman ctfconvert_fatal( 398*88a08813SAndy Fiddaman "Failed to add '%s' to ignore list: %s\n", 399*88a08813SAndy Fiddaman buf, strerror(err)); 400*88a08813SAndy Fiddaman } 401*88a08813SAndy Fiddaman } 402*88a08813SAndy Fiddaman free(buf); 403*88a08813SAndy Fiddaman if (cnt == -1 && ferror(fp) != 0) { 404*88a08813SAndy Fiddaman ctfconvert_fatal( 405*88a08813SAndy Fiddaman "Error reading from ignorefile '%s': %s\n", 406*88a08813SAndy Fiddaman ignorefile, strerror(errno)); 407*88a08813SAndy Fiddaman } 408*88a08813SAndy Fiddaman 409*88a08813SAndy Fiddaman (void) fclose(fp); 410*88a08813SAndy Fiddaman } 411*88a08813SAndy Fiddaman 412dd442252SAndy Fiddaman ofp = ctf_fdconvert(cch, ifd, &err, buf, sizeof (buf)); 413dd442252SAndy Fiddaman 414dd442252SAndy Fiddaman ctf_convert_fini(cch); 415dd442252SAndy Fiddaman 416bc1f688bSRobert Mustacchi if (ofp == NULL) { 417bc1f688bSRobert Mustacchi /* 4183eca6103SJohn Levon * Normally, ctfconvert requires that its input file has at 4193eca6103SJohn Levon * least one C-source compilation unit, and that every C-source 4203eca6103SJohn Levon * compilation unit has DWARF. This is to avoid accidentally 4213eca6103SJohn Levon * leaving out useful CTF. 4223eca6103SJohn Levon * 4233eca6103SJohn Levon * However, for the benefit of intransigent build environments, 4243eca6103SJohn Levon * the -i and -m options can be used to relax this. 425bc1f688bSRobert Mustacchi */ 4263eca6103SJohn Levon if (err == ECTF_CONVNOCSRC && ignore_non_c) { 427bc1f688bSRobert Mustacchi exit(CTFCONVERT_OK); 428bc1f688bSRobert Mustacchi } 4293eca6103SJohn Levon 4303eca6103SJohn Levon if (err == ECTF_CONVNODEBUG && 4313eca6103SJohn Levon (flags & CTF_ALLOW_MISSING_DEBUG) != 0) { 4323eca6103SJohn Levon exit(CTFCONVERT_OK); 4333eca6103SJohn Levon } 4343eca6103SJohn Levon 435bc1f688bSRobert Mustacchi if (keep == B_FALSE) 436bc1f688bSRobert Mustacchi (void) unlink(infile); 4373eca6103SJohn Levon 438dd442252SAndy Fiddaman switch (err) { 439dd442252SAndy Fiddaman case ECTF_CONVBKERR: 440dd442252SAndy Fiddaman ctfconvert_fatal("CTF conversion failed: %s", buf); 441dd442252SAndy Fiddaman break; 442dd442252SAndy Fiddaman case ECTF_CONVNODEBUG: 443dd442252SAndy Fiddaman ctfconvert_fatal("CTF conversion failed due to " 444dd442252SAndy Fiddaman "missing debug data; use -m to override\n"); 445dd442252SAndy Fiddaman break; 446dd442252SAndy Fiddaman default: 447dd442252SAndy Fiddaman if (*buf != '\0') { 448dd442252SAndy Fiddaman (void) fprintf(stderr, "%s: %s", 449dd442252SAndy Fiddaman ctfconvert_progname, buf); 450dd442252SAndy Fiddaman } 4513eca6103SJohn Levon ctfconvert_fatal("CTF conversion failed: %s\n", 4523eca6103SJohn Levon ctf_errmsg(err)); 4533eca6103SJohn Levon } 454bc1f688bSRobert Mustacchi } 455bc1f688bSRobert Mustacchi 456bc1f688bSRobert Mustacchi if (optx == B_TRUE) 457bc1f688bSRobert Mustacchi ctfconvert_fixup_genunix(ofp); 458bc1f688bSRobert Mustacchi 459bc1f688bSRobert Mustacchi tmpfile = NULL; 460bc1f688bSRobert Mustacchi if (outfile == NULL || strcmp(infile, outfile) == 0) { 461bc1f688bSRobert Mustacchi if (asprintf(&tmpfile, "%s.ctf", infile) == -1) { 462bc1f688bSRobert Mustacchi if (keep == B_FALSE) 463bc1f688bSRobert Mustacchi (void) unlink(infile); 464bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to allocate memory for " 465bc1f688bSRobert Mustacchi "temporary file: %s\n", strerror(errno)); 466bc1f688bSRobert Mustacchi } 467bc1f688bSRobert Mustacchi outfile = tmpfile; 468bc1f688bSRobert Mustacchi } 469bc1f688bSRobert Mustacchi err = ctf_elfwrite(ofp, infile, outfile, CTF_ELFWRITE_F_COMPRESS); 470bc1f688bSRobert Mustacchi if (err == CTF_ERR) { 471bc1f688bSRobert Mustacchi (void) unlink(outfile); 472bc1f688bSRobert Mustacchi if (keep == B_FALSE) 473bc1f688bSRobert Mustacchi (void) unlink(infile); 474bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to write CTF section to output file: " 475dd442252SAndy Fiddaman "%s\n", ctf_errmsg(ctf_errno(ofp))); 476bc1f688bSRobert Mustacchi } 477bc1f688bSRobert Mustacchi ctf_close(ofp); 478bc1f688bSRobert Mustacchi 479bc1f688bSRobert Mustacchi if (tmpfile != NULL) { 480bc1f688bSRobert Mustacchi if (rename(tmpfile, infile) != 0) { 481bc1f688bSRobert Mustacchi int e = errno; 482bc1f688bSRobert Mustacchi (void) unlink(outfile); 483bc1f688bSRobert Mustacchi if (keep == B_FALSE) 484bc1f688bSRobert Mustacchi (void) unlink(infile); 485bc1f688bSRobert Mustacchi ctfconvert_fatal("failed to rename temporary file: " 486bc1f688bSRobert Mustacchi "%s\n", strerror(e)); 487bc1f688bSRobert Mustacchi } 488bc1f688bSRobert Mustacchi } 489bc1f688bSRobert Mustacchi free(tmpfile); 490bc1f688bSRobert Mustacchi 491bc1f688bSRobert Mustacchi return (CTFCONVERT_OK); 492bc1f688bSRobert Mustacchi } 493