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 27 /* 28 * Wrap data in an elf file. 29 */ 30 #include <fcntl.h> 31 #include <unistd.h> 32 #include <libgen.h> 33 #include <errno.h> 34 #include <stdio.h> 35 #include <string.h> 36 #include <locale.h> 37 #include <libintl.h> 38 #include <conv.h> 39 #include <msg.h> 40 #include <_elfwrap.h> 41 42 const char * 43 _elfwrap_msg(Msg mid) 44 { 45 return (gettext(MSG_ORIG(mid))); 46 } 47 48 int 49 main(int argc, char **argv, char **envp) 50 { 51 const char *prog, *ofile = NULL, *pstr = NULL; 52 int fd, var; 53 uchar_t class = ELFCLASS32; 54 ushort_t mach = EM_NONE; 55 ObjDesc_t odesc = { NULL, 0, 0, 0 }; 56 57 /* 58 * If we're on a 64-bit kernel, try to exec a full 64-bit version of 59 * the binary. If successful, conv_check_native() won't return. 60 */ 61 (void) conv_check_native(argv, envp); 62 63 /* 64 * Establish locale. 65 */ 66 (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 67 (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 68 69 (void) setvbuf(stdout, NULL, _IOLBF, 0); 70 (void) setvbuf(stderr, NULL, _IOLBF, 0); 71 72 prog = basename(argv[0]); 73 opterr = 0; 74 while ((var = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != EOF) { 75 switch (var) { 76 case '6': /* Create a 64-bit object */ 77 if (optarg[0] != '4') { 78 (void) fprintf(stderr, 79 MSG_INTL(MSG_ARG_ILLEGAL), prog, 80 MSG_ORIG(MSG_ARG_6), optarg); 81 return (1); 82 } 83 class = ELFCLASS64; 84 break; 85 case 'o': /* output file name */ 86 ofile = optarg; 87 break; 88 case 'z': /* output file platform */ 89 if (strncmp(optarg, MSG_ORIG(MSG_ARG_TARGET), 90 MSG_ARG_TARGET_SIZE) == 0) 91 pstr = optarg + MSG_ARG_TARGET_SIZE; 92 else { 93 (void) fprintf(stderr, 94 MSG_INTL(MSG_ARG_ILLEGAL), prog, 95 MSG_ORIG(MSG_ARG_Z), optarg); 96 return (1); 97 } 98 break; 99 case '?': 100 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), 101 prog); 102 return (1); 103 default: 104 break; 105 } 106 } 107 108 /* 109 * Verify that we have at least one input data file, and if no output 110 * file has been specified, provide a default. Update argc and argv 111 * for input() to continue processing any input files. 112 */ 113 argv += optind; 114 argc -= optind; 115 if (argc == 0) { 116 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF), prog); 117 return (1); 118 } 119 if (ofile == NULL) 120 ofile = MSG_ORIG(MSG_STR_AWRAPO); 121 122 /* 123 * If the user specified a target, use it to determine the machine type 124 * for the output object. If no target is specified, we leave "mach" as 125 * EM_NONE. output() will replace EM_NONE with the appropriate machine 126 * code for the system running elfwrap(1). 127 */ 128 if (pstr) { 129 if (strcasecmp(pstr, MSG_ORIG(MSG_TARG_SPARC)) == 0) { 130 if (class == ELFCLASS64) 131 mach = EM_SPARCV9; 132 else 133 mach = EM_SPARC; 134 135 } else if (strcasecmp(pstr, MSG_ORIG(MSG_TARG_X86)) == 0) { 136 if (class == ELFCLASS64) 137 mach = EM_AMD64; 138 else 139 mach = EM_386; 140 141 } else { 142 (void) fprintf(stderr, MSG_INTL(MSG_ARG_BADTARG), prog, 143 pstr); 144 return (1); 145 } 146 } 147 148 /* 149 * Create the input information for the new image. 150 */ 151 if (class == ELFCLASS64) { 152 if (input64(argc, argv, prog, ofile, &odesc) == 1) 153 return (1); 154 } else { 155 if (input32(argc, argv, prog, ofile, &odesc) == 1) 156 return (1); 157 } 158 159 /* 160 * Create and truncate the output file. 161 */ 162 if ((fd = open(ofile, (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) { 163 int err = errno; 164 (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN), prog, 165 ofile, strerror(err)); 166 return (1); 167 } 168 169 /* 170 * Initialize libelf, and create the new ELF file as the class dictates. 171 */ 172 if (elf_version(EV_CURRENT) == EV_NONE) { 173 (void) fprintf(stderr, MSG_INTL(MSG_ERR_LIBELF), prog, 174 EV_CURRENT); 175 return (1); 176 } 177 if (class == ELFCLASS64) 178 return (output64(prog, fd, ofile, mach, &odesc)); 179 else 180 return (output32(prog, fd, ofile, mach, &odesc)); 181 } 182