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