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 *
_elfwrap_msg(Msg mid)43 _elfwrap_msg(Msg mid)
44 {
45 return (gettext(MSG_ORIG(mid)));
46 }
47
48 int
main(int argc,char ** argv,char ** envp)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