1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Wrap data in an elf file. 30 */ 31 #include <fcntl.h> 32 #include <unistd.h> 33 #include <libgen.h> 34 #include <errno.h> 35 #include <stdio.h> 36 #include <string.h> 37 #include <locale.h> 38 #include <libintl.h> 39 #include <conv.h> 40 #include <msg.h> 41 #include <_elfwrap.h> 42 43 const char * 44 _elfwrap_msg(Msg mid) 45 { 46 return (gettext(MSG_ORIG(mid))); 47 } 48 49 int 50 main(int argc, char **argv, char **envp) 51 { 52 const char *prog, *ofile = NULL, *pstr = NULL; 53 int fd, var; 54 uchar_t class = ELFCLASS32; 55 ushort_t mach = EM_NONE; 56 ObjDesc_t odesc = { NULL, 0, 0, 0 }; 57 58 /* 59 * If we're on a 64-bit kernel, try to exec a full 64-bit version of 60 * the binary. If successful, conv_check_native() won't return. 61 */ 62 (void) conv_check_native(argv, envp); 63 64 /* 65 * Establish locale. 66 */ 67 (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 68 (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 69 70 (void) setvbuf(stdout, NULL, _IOLBF, 0); 71 (void) setvbuf(stderr, NULL, _IOLBF, 0); 72 73 prog = basename(argv[0]); 74 opterr = 0; 75 while ((var = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != EOF) { 76 switch (var) { 77 case '6': /* Create a 64-bit object */ 78 if (optarg[0] != '4') { 79 (void) fprintf(stderr, 80 MSG_INTL(MSG_ARG_ILLEGAL), prog, 81 MSG_ORIG(MSG_ARG_6), optarg); 82 return (1); 83 } 84 class = ELFCLASS64; 85 break; 86 case 'o': /* output file name */ 87 ofile = optarg; 88 break; 89 case 'z': /* output file platform */ 90 if (strncmp(optarg, MSG_ORIG(MSG_ARG_TARGET), 91 MSG_ARG_TARGET_SIZE) == 0) 92 pstr = optarg + MSG_ARG_TARGET_SIZE; 93 else { 94 (void) fprintf(stderr, 95 MSG_INTL(MSG_ARG_ILLEGAL), prog, 96 MSG_ORIG(MSG_ARG_Z), optarg); 97 return (1); 98 } 99 break; 100 case '?': 101 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 102 prog); 103 return (1); 104 default: 105 break; 106 } 107 } 108 109 /* 110 * Verify that we have at least one input data file, and if no output 111 * file has been specified, provide a default. Update argc and argv 112 * for input() to continue processing any input files. 113 */ 114 argv += optind; 115 argc -= optind; 116 if (argc == 0) { 117 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), prog); 118 return (1); 119 } 120 if (ofile == NULL) 121 ofile = MSG_ORIG(MSG_STR_AWRAPO); 122 123 /* 124 * If the user specified a target, use it to determine the machine type 125 * for the output object. If no target is specified, we leave "mach" as 126 * EM_NONE. output() will replace EM_NONE with the appropriate machine 127 * code for the system running elfwrap(1). 128 */ 129 if (pstr) { 130 if (strcasecmp(pstr, MSG_ORIG(MSG_TARG_SPARC)) == 0) { 131 if (class == ELFCLASS64) 132 mach = EM_SPARCV9; 133 else 134 mach = EM_SPARC; 135 136 } else if (strcasecmp(pstr, MSG_ORIG(MSG_TARG_X86)) == 0) { 137 if (class == ELFCLASS64) 138 mach = EM_AMD64; 139 else 140 mach = EM_386; 141 142 } else { 143 (void) fprintf(stderr, MSG_INTL(MSG_ARG_BADTARG), prog, 144 pstr); 145 return (1); 146 } 147 } 148 149 /* 150 * Create the input information for the new image. 151 */ 152 if (class == ELFCLASS64) { 153 if (input64(argc, argv, prog, ofile, &odesc) == 1) 154 return (1); 155 } else { 156 if (input32(argc, argv, prog, ofile, &odesc) == 1) 157 return (1); 158 } 159 160 /* 161 * Create and truncate the output file. 162 */ 163 if ((fd = open(ofile, (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) { 164 int err = errno; 165 (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), prog, 166 ofile, strerror(err)); 167 return (1); 168 } 169 170 /* 171 * Initialize libelf, and create the new ELF file as the class dictates. 172 */ 173 if (elf_version(EV_CURRENT) == EV_NONE) { 174 (void) fprintf(stderr, MSG_INTL(MSG_ERR_LIBELF), prog, 175 EV_CURRENT); 176 return (1); 177 } 178 if (class == ELFCLASS64) 179 return (output64(prog, fd, ofile, mach, &odesc)); 180 else 181 return (output32(prog, fd, ofile, mach, &odesc)); 182 } 183