xref: /illumos-gate/usr/src/cmd/sgs/ld/common/ld.c (revision ef8846857fcf954444cdc77e72249afef48377d2)
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 2006 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 #include	<stdio.h>
30 #include	<stdlib.h>
31 #include	<unistd.h>
32 #include	<stdarg.h>
33 #include	<string.h>
34 #include	<errno.h>
35 #include	<fcntl.h>
36 #include	<libintl.h>
37 #include	<locale.h>
38 #include	<fcntl.h>
39 #include	"conv.h"
40 #include	"libld.h"
41 #include	"msg.h"
42 
43 /*
44  * The following prevent us from having to include ctype.h which defines these
45  * functions as macros which reference the __ctype[] array.  Go through .plt's
46  * to get to these functions in libc rather than have every invocation of ld
47  * have to suffer the R_SPARC_COPY overhead of the __ctype[] array.
48  */
49 extern int	isspace(int);
50 
51 /*
52  * Print a message to stdout
53  */
54 /* VARARGS3 */
55 void
56 eprintf(Lm_list *lml, Error error, const char *format, ...)
57 {
58 	va_list			args;
59 	static const char	*strings[ERR_NUM] = { MSG_ORIG(MSG_STR_EMPTY) };
60 
61 #if	defined(lint)
62 	/*
63 	 * The lml argument is only meaningful for diagnostics sent to ld.so.1.
64 	 * Supress the lint error by making a dummy assignment.
65 	 */
66 	lml = 0;
67 #endif
68 	if (error > ERR_NONE) {
69 		if (error == ERR_WARNING) {
70 			if (strings[ERR_WARNING] == 0)
71 			    strings[ERR_WARNING] = MSG_INTL(MSG_ERR_WARNING);
72 		} else if (error == ERR_FATAL) {
73 			if (strings[ERR_FATAL] == 0)
74 			    strings[ERR_FATAL] = MSG_INTL(MSG_ERR_FATAL);
75 		} else if (error == ERR_ELF) {
76 			if (strings[ERR_ELF] == 0)
77 			    strings[ERR_ELF] = MSG_INTL(MSG_ERR_ELF);
78 		}
79 		(void) fputs(MSG_ORIG(MSG_STR_LDDIAG), stderr);
80 	}
81 	(void) fputs(strings[error], stderr);
82 
83 	va_start(args, format);
84 	(void) vfprintf(stderr, format, args);
85 	if (error == ERR_ELF) {
86 		int	elferr;
87 
88 		if ((elferr = elf_errno()) != 0)
89 			(void) fprintf(stderr, MSG_ORIG(MSG_STR_ELFDIAG),
90 			    elf_errmsg(elferr));
91 	}
92 	(void) fprintf(stderr, MSG_ORIG(MSG_STR_NL));
93 	(void) fflush(stderr);
94 	va_end(args);
95 }
96 
97 
98 /*
99  * Determine whether we need the Elf32 or Elf64 libld.
100  */
101 static int
102 determine_class(int argc, char **argv, uchar_t *aoutclass, uchar_t *ldclass)
103 {
104 #if	defined(__sparcv9) || defined(__amd64)
105 	uchar_t aclass = 0, lclass = ELFCLASS64;
106 #else
107 	uchar_t	aclass = 0, lclass = 0;
108 #endif
109 	int	c;
110 
111 getmore:
112 	/*
113 	 * Skip options.
114 	 *
115 	 * The only options we're interested in is -64 or -altzexec64.  The -64
116 	 * option is used when the only input to ld() is a mapfile or archive,
117 	 * and a 64-bit a.out is required.  The -zaltexec64 option requests the
118 	 * 64-bit version of ld() is used regardless of the required a.out.
119 	 *
120 	 * If we've already processed a 32-bit object and we find -64, we have
121 	 * an error condition, but let this fall through to libld to obtain the
122 	 * default error message.
123 	 */
124 	opterr = 0;
125 	while ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
126 		switch (c) {
127 			case '6':
128 				if (strncmp(optarg, MSG_ORIG(MSG_ARG_FOUR),
129 				    MSG_ARG_FOUR_SIZE) == 0)
130 					aclass = ELFCLASS64;
131 				break;
132 #if	!defined(__sparcv9) && !defined(__amd64)
133 			case 'z':
134 				if (strncmp(optarg, MSG_ORIG(MSG_ARG_ALTEXEC64),
135 				    MSG_ARG_ALTEXEC64_SIZE) == 0)
136 					lclass = ELFCLASS64;
137 				break;
138 #endif
139 			default:
140 				break;
141 		}
142 	}
143 
144 	/*
145 	 * Continue to look for the first ELF object to determine the class of
146 	 * objects to operate on.
147 	 */
148 	for (; optind < argc; optind++) {
149 		int		fd;
150 		unsigned char	ident[EI_NIDENT];
151 
152 		/*
153 		 * If we detect some more options return to getopt().
154 		 * Checking argv[optind][1] against null prevents a forever
155 		 * loop if an unadorned `-' argument is passed to us.
156 		 */
157 		if (argv[optind][0] == '-') {
158 			if (argv[optind][1] == '\0')
159 				continue;
160 			else
161 				goto getmore;
162 		}
163 
164 		/*
165 		 * If we've already determined the object class, continue.
166 		 * We're only interested in skipping all files to check for
167 		 * more options, and specifically if the -64 option is set.
168 		 */
169 		if (aclass)
170 			continue;
171 
172 		/*
173 		 * Open the file and determine the files ELF class.
174 		 */
175 		if ((fd = open(argv[optind], O_RDONLY)) == -1) {
176 			int err = errno;
177 
178 			eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
179 			    argv[optind], strerror(err));
180 			return (1);
181 		}
182 
183 		if ((read(fd, ident, EI_NIDENT) == EI_NIDENT) &&
184 		    (ident[EI_MAG0] == ELFMAG0) &&
185 		    (ident[EI_MAG1] == ELFMAG1) &&
186 		    (ident[EI_MAG2] == ELFMAG2) &&
187 		    (ident[EI_MAG3] == ELFMAG3)) {
188 			if (((aclass = ident[EI_CLASS]) != ELFCLASS32) &&
189 			    (aclass != ELFCLASS64))
190 				aclass = 0;
191 		}
192 		(void) close(fd);
193 	}
194 
195 	/*
196 	 * If we couldn't establish a class default to 32-bit.
197 	 */
198 	if (aclass == 0)
199 		aclass = ELFCLASS32;
200 	if (lclass == 0)
201 		lclass = ELFCLASS32;
202 
203 	*aoutclass = aclass;
204 	*ldclass = lclass;
205 	return (0);
206 }
207 
208 /*
209  * Prepend environment string as a series of options to the argv array.
210  */
211 static int
212 prepend_ldoptions(char *ld_options, int *argcp, char ***argvp)
213 {
214 	int	nargc;			/* new argc */
215 	char	**nargv;		/* new argv */
216 	char	*arg, *string;
217 	int	count;
218 
219 	/*
220 	 * Get rid of leading white space, and make sure the string has size.
221 	 */
222 	while (isspace(*ld_options))
223 		ld_options++;
224 	if (*ld_options == '\0')
225 		return (1);
226 
227 	nargc = 0;
228 	arg = string = ld_options;
229 
230 	/*
231 	 * Walk the environment string counting any arguments that are
232 	 * separated by white space.
233 	 */
234 	while (*string != '\0') {
235 		if (isspace(*string)) {
236 			nargc++;
237 			while (isspace(*string))
238 				string++;
239 			arg = string;
240 		} else
241 			string++;
242 	}
243 	if (arg != string)
244 		nargc++;
245 
246 	/*
247 	 * Allocate a new argv array big enough to hold the new options from
248 	 * the environment string and the old argv options.
249 	 */
250 	if ((nargv = calloc(nargc + *argcp, sizeof (char *))) == 0) {
251 		int	err = errno;
252 		eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_ALLOC), strerror(err));
253 		return (0);
254 	}
255 
256 	/*
257 	 * Initialize first element of new argv array to be the first element
258 	 * of the old argv array (ie. calling programs name).  Then add the new
259 	 * args obtained from the environment.
260 	 */
261 	nargv[0] = (*argvp)[0];
262 	nargc = 0;
263 	arg = string = ld_options;
264 	while (*string != '\0') {
265 		if (isspace(*string)) {
266 			nargc++;
267 			*string++ = '\0';
268 			nargv[nargc] = arg;
269 			while (isspace(*string))
270 				string++;
271 			arg = string;
272 		} else
273 			string++;
274 	}
275 	if (arg != string) {
276 		nargc++;
277 		nargv[nargc] = arg;
278 	}
279 
280 	/*
281 	 * Now add the original argv array (skipping argv[0]) to the end of the
282 	 * new argv array, and overwrite the old argc and argv.
283 	 */
284 	for (count = 1; count < *argcp; count++) {
285 		nargc++;
286 		nargv[nargc] = (*argvp)[count];
287 	}
288 	*argcp = ++nargc;
289 	*argvp = nargv;
290 
291 	return (1);
292 }
293 
294 /*
295  * Check to see if there is a LD_ALTEXEC=<path to alternate ld> in the
296  * environment.  If so, first null the environment variable out, and then
297  * exec() the binary pointed to by the environment variable, passing the same
298  * arguments as the originating process.  This mechanism permits using
299  * alternate link-editors (debugging/developer copies) even in complex build
300  * environments.
301  */
302 static int
303 ld_altexec(char **argv, char **envp)
304 {
305 	char	*execstr;
306 	char	**str;
307 	int	err;
308 
309 	for (str = envp; *str; str++) {
310 		if (strncmp(*str, MSG_ORIG(MSG_LD_ALTEXEC),
311 		    MSG_LD_ALTEXEC_SIZE) == 0) {
312 			break;
313 		}
314 	}
315 
316 	/*
317 	 * If LD_ALTEXEC isn't set, return to continue executing the present
318 	 * link-editor.
319 	 */
320 	if (*str == 0)
321 		return (0);
322 
323 	/*
324 	 * Get a pointer to the actual string.  If it's a null entry, return.
325 	 */
326 	execstr = strdup(*str + MSG_LD_ALTEXEC_SIZE);
327 	if (*execstr == '\0')
328 		return (0);
329 
330 	/*
331 	 * Null out the LD_ALTEXEC= environment entry.
332 	 */
333 	(*str)[MSG_LD_ALTEXEC_SIZE] = '\0';
334 
335 	/*
336 	 * Set argv[0] to point to our new linker
337 	 */
338 	argv[0] = execstr;
339 
340 	/*
341 	 * And attempt to execute it.
342 	 */
343 	(void) execve(execstr, argv, envp);
344 
345 	/*
346 	 * If the exec() fails, return a failure indication.
347 	 */
348 	err = errno;
349 	eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_EXEC), execstr,
350 	    strerror(err));
351 	return (1);
352 }
353 
354 int
355 main(int argc, char **argv, char **envp)
356 {
357 	char		*ld_options, **oargv = argv;
358 	uchar_t 	aoutclass, ldclass, checkclass;
359 
360 	/*
361 	 * XX64 -- Strip "-Wl," from the head of each argument.  This is to
362 	 * accommodate awkwardness in passing ld arguments to gcc while
363 	 * maintaining the structure of the OSNet build environment's Makefiles.
364 	 */
365 	{
366 		int i;
367 		char *p;
368 
369 		for (i = 0; i < argc; i++) {
370 			p = argv[i];
371 			while (*(p + 1) == 'W' && strncmp(p, "-Wl,-", 5) == 0)
372 				argv[i] = (p += 4);
373 		}
374 	}
375 
376 	/*
377 	 * Establish locale.
378 	 */
379 	(void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY));
380 	(void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS));
381 
382 	/*
383 	 * Execute an alternate linker if the LD_ALTEXEC environment variable is
384 	 * set.  If a specified alternative could not be found, bail.
385 	 */
386 	if (ld_altexec(argv, envp))
387 		return (1);
388 
389 	/*
390 	 * Check the LD_OPTIONS environment variable, and if present prepend
391 	 * the arguments specified to the command line argument list.
392 	 */
393 	if ((ld_options = getenv(MSG_ORIG(MSG_LD_OPTIONS))) != NULL) {
394 		/*
395 		 * Prevent modification of actual environment strings.
396 		 */
397 		if (((ld_options = strdup(ld_options)) == NULL) ||
398 		    (prepend_ldoptions(ld_options, &argc, &argv) == 0))
399 			return (1);
400 	}
401 
402 	/*
403 	 * Determine the object class, and link-editor class required.
404 	 */
405 	if (determine_class(argc, argv, &aoutclass, &ldclass))
406 		return (1);
407 
408 	/*
409 	 * If we're processing 64-bit objects, or the user specifically asked
410 	 * for a 64-bit link-editor, determine if a 64-bit ld() can be executed.
411 	 * Bail if a 64-bit ld() was explicitly asked for, but one could not be
412 	 * found.
413 	 */
414 	if ((aoutclass == ELFCLASS64) || (ldclass == ELFCLASS64))
415 		checkclass = conv_check_native(oargv, envp);
416 
417 	if ((ldclass == ELFCLASS64) && (checkclass != ELFCLASS64)) {
418 		eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_64));
419 		return (1);
420 	}
421 
422 	/*
423 	 * Reset the getopt(3c) error message flag, and call the generic entry
424 	 * point using the appropriate class.
425 	 */
426 	optind = opterr = 1;
427 	if (aoutclass == ELFCLASS64)
428 		return (ld64_main(argc, argv));
429 	else
430 		return (ld32_main(argc, argv));
431 }
432 
433 /*
434  * Exported interfaces required by our dependencies.  libld and friends bind to
435  * the different implementations of these provided by either ld or ld.so.1.
436  */
437 const char *
438 _ld_msg(Msg mid)
439 {
440 	return (gettext(MSG_ORIG(mid)));
441 }
442