ld.c revision 2647:e440e3da2a6f
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 */
49extern int	isspace(int);
50
51/*
52 * Print a message to stdout
53 */
54/* VARARGS3 */
55void
56eprintf(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 */
101static int
102determine_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
111getmore:
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 */
211static int
212prepend_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 */
302static int
303ld_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
354int
355main(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 */
437const char *
438_ld_msg(Msg mid)
439{
440	return (gettext(MSG_ORIG(mid)));
441}
442