xref: /illumos-gate/usr/src/cmd/sgs/ld/common/ld.c (revision 7c478bd9)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 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	<dlfcn.h>
40 #include	"conv.h"
41 #include	"libld.h"
42 #include	"msg.h"
43 
44 
45 /*
46  * The following prevent us from having to include ctype.h which defines these
47  * functions as macros which reference the __ctype[] array.  Go through .plt's
48  * to get to these functions in libc rather than have every invocation of ld
49  * have to suffer the R_SPARC_COPY overhead of the __ctype[] array.
50  */
51 extern int	isspace(int);
52 
53 
54 /*
55  * Determine whether we need the Elf32 or Elf64 libld.
56  */
57 static int
58 determine_class(int argc, char ** argv)
59 {
60 	unsigned char	class = 0;
61 	int		c;
62 
63 getmore:
64 	/*
65 	 * Skip options.
66 	 *
67 	 * The only option we're interested in is -64, which enforces a 64-bit
68 	 * link-edit.  This option is used when the only input to ld() is a
69 	 * mapfile and a 64-bit object is required.  If we've already processed
70 	 * a 32-bit object and we find -64, we have an error condition, but let
71 	 * this fall through to libld to obtain the default error message.
72 	 */
73 	opterr = 0;
74 	while ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
75 		switch (c) {
76 			case '6':
77 				return (ELFCLASS64);
78 			default:
79 				break;
80 		}
81 	}
82 
83 	/*
84 	 * Otherwise look for the first ELF object to determine the class of
85 	 * objects to operate on.
86 	 */
87 	for (; optind < argc; optind++) {
88 		int		fd;
89 		unsigned char	ident[EI_NIDENT];
90 
91 		/*
92 		 * If we've already analyzed the initial object, continue.
93 		 * We're only interested in skipping all files to check for
94 		 * more options, and specifically if the -64 option is set.
95 		 */
96 		if (class)
97 			continue;
98 
99 		/*
100 		 * If we detect some more options return to getopt().
101 		 * Checking argv[optind][1] against null prevents a forever
102 		 * loop if an unadorned `-' argument is passed to us.
103 		 */
104 		if (argv[optind][0] == '-') {
105 			if (argv[optind][1] == '\0')
106 				continue;
107 			else
108 				goto getmore;
109 		}
110 
111 		if ((fd = open(argv[optind], O_RDONLY)) == -1) {
112 			int err = errno;
113 
114 			eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
115 			    argv[optind], strerror(err));
116 			return (0);
117 		}
118 
119 		/*
120 		 * Determine the files ELF class.
121 		 */
122 		if ((read(fd, ident, EI_NIDENT) == EI_NIDENT) &&
123 		    (ident[EI_MAG0] == ELFMAG0) &&
124 		    (ident[EI_MAG1] == ELFMAG1) &&
125 		    (ident[EI_MAG2] == ELFMAG2) &&
126 		    (ident[EI_MAG3] == ELFMAG3)) {
127 			if (((class = ident[EI_CLASS]) != ELFCLASS32) &&
128 			    (class != ELFCLASS64))
129 				class = 0;
130 		}
131 		(void) close(fd);
132 	}
133 
134 	/*
135 	 * If we couldn't establish a class default to 32-bit.
136 	 */
137 	if (class)
138 		return (class);
139 
140 	return (ELFCLASS32);
141 }
142 
143 /*
144  * Prepend environment string as a series of options to the argv array.
145  */
146 static int
147 prepend_ldoptions(char *ld_options, int *argcp, char ***argvp)
148 {
149 	int	nargc;			/* New argc */
150 	char	**nargv;			/* New argv */
151 	char	*arg, *string;
152 	int	count;
153 
154 	/*
155 	 * Get rid of leading white space, and make sure the string has size.
156 	 */
157 	while (isspace(*ld_options))
158 		ld_options++;
159 	if (*ld_options == '\0')
160 		return (1);
161 
162 	nargc = 0;
163 	arg = string = ld_options;
164 
165 	/*
166 	 * Walk the environment string counting any arguments that are
167 	 * separated by white space.
168 	 */
169 	while (*string != '\0') {
170 		if (isspace(*string)) {
171 			nargc++;
172 			while (isspace(*string))
173 				string++;
174 			arg = string;
175 		} else
176 			string++;
177 	}
178 	if (arg != string)
179 		nargc++;
180 
181 	/*
182 	 * Allocate a new argv array big enough to hold the new options from
183 	 * the environment string and the old argv options.
184 	 */
185 	if ((nargv = calloc(nargc + *argcp, sizeof (char *))) == 0)
186 		return (0);
187 
188 	/*
189 	 * Initialize first element of new argv array to be the first element
190 	 * of the old argv array (ie. calling programs name).  Then add the new
191 	 * args obtained from the environment.
192 	 */
193 	nargv[0] = (*argvp)[0];
194 	nargc = 0;
195 	arg = string = ld_options;
196 	while (*string != '\0') {
197 		if (isspace(*string)) {
198 			nargc++;
199 			*string++ = '\0';
200 			nargv[nargc] = arg;
201 			while (isspace(*string))
202 				string++;
203 			arg = string;
204 		} else
205 			string++;
206 	}
207 	if (arg != string) {
208 		nargc++;
209 		nargv[nargc] = arg;
210 	}
211 
212 	/*
213 	 * Now add the original argv array (skipping argv[0]) to the end of the
214 	 * new argv array, and overwrite the old argc and argv.
215 	 */
216 	for (count = 1; count < *argcp; count++) {
217 		nargc++;
218 		nargv[nargc] = (*argvp)[count];
219 	}
220 	*argcp = ++nargc;
221 	*argvp = nargv;
222 
223 	return (1);
224 }
225 
226 /*
227  * The ld_altexec() function checks to see if there is
228  * a LD_ALTEXEC=<path to alternate ld> in the environment.
229  * If there is - it will null that variable out - and then
230  * exec() the binary pointed to with the same arguements
231  * as the originating process.
232  * This permits using alternate link-editors (debugging/developer
233  * copies) even in complex build environments.
234  *
235  * If LD_ALTEXEC= isn't set, or the exec() fails this
236  * function silently returns and the execution of this
237  * link-editor continues on.
238  */
239 void
240 ld_altexec(char **argv, char **envp)
241 {
242 	char	*execstr;
243 	char	**str;
244 	for (str = envp; *str; str++) {
245 		if (strncmp(*str, MSG_ORIG(MSG_LD_ALTEXEC),
246 		    MSG_LD_ALTEXEC_SIZE) == 0) {
247 			break;
248 		}
249 	}
250 	if (*str == 0)
251 		return;
252 
253 	/*
254 	 * get a pointer to the actual string - if it's
255 	 * a null entry - we return.
256 	 */
257 	execstr = strdup(*str + MSG_LD_ALTEXEC_SIZE);
258 	if (*execstr == '\0')
259 		return;
260 	/*
261 	 * Null out the LD_ALTEXEC= environment entry.
262 	 */
263 	(*str)[MSG_LD_ALTEXEC_SIZE] = '\0';
264 
265 	/*
266 	 * Set argv[0] to point to our new linker
267 	 */
268 	argv[0] = execstr;
269 
270 	/*
271 	 * And attempt to execute it.
272 	 */
273 	(void) execve(execstr, argv, envp);
274 
275 	/*
276 	 * If the exec failes - we just silently fall
277 	 * through and continue execution of the
278 	 * current link-editor.
279 	 */
280 }
281 
282 int
283 main(int argc, char **argv, char **envp)
284 {
285 	char		*ld_options, **oargv = argv;
286 	const char	*libld = MSG_ORIG(MSG_LD_LIB32);
287 	void		*libld_h;
288 	int		(*libld_main)(int, char **);
289 	unsigned char	class;
290 
291 	/*
292 	 * XX64 -- Strip "-Wl," from the head of each argument.
293 	 * This is to accommodate awkwardness in pasing ld arguments
294 	 * to gcc while maintaining the structure of the build
295 	 * environment's Makefiles.
296 	 */
297 	{
298 		int i;
299 		char *p;
300 
301 		for (i = 0; i < argc; i++) {
302 			p = argv[i];
303 			while (*(p + 1) == 'W' && strncmp(p, "-Wl,-", 5) == 0)
304 				argv[i] = (p += 4);
305 		}
306 	}
307 
308 	/*
309 	 * Establish locale.
310 	 */
311 	(void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY));
312 	(void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS));
313 
314 	/*
315 	 * Execute alternate linker if LD_ALTEXEC environment variable is set.
316 	 */
317 	ld_altexec(argv, envp);
318 
319 	/*
320 	 * Check the LD_OPTIONS environment variable, and if present prepend
321 	 * the arguments specified to the command line argument list.
322 	 */
323 	if ((ld_options = getenv(MSG_ORIG(MSG_LD_OPTIONS))) != NULL) {
324 		/*
325 		 * Prevent modification of actual environment strings.
326 		 */
327 		if (((ld_options = strdup(ld_options)) == NULL) ||
328 		    (prepend_ldoptions(ld_options, &argc, &argv) == 0))
329 			return (1);
330 	}
331 
332 	/*
333 	 * Locate the first input file and from it determine the class of
334 	 * objects we're going to process.  If the class is ELFCLASS64 we'll
335 	 * specifically load libld.so.3, otherwise we'll fall back to
336 	 * libld.so.2.  Note that if the option -64 is encountered a 64-bit
337 	 * link is explicitly being requested.
338 	 */
339 	if ((class = determine_class(argc, argv)) == 0)
340 		return (1);
341 
342 	/*
343 	 * dlopen() right libld implementation.  Note: the RTLD_GLOBAL flag is
344 	 * added to make ld behave as if libld was one of its dependencies.
345 	 * Support libraries, like libldstab.so.1, may expect this, to get at
346 	 * libld_malloc, which they argueably shouldn't be using anyway.
347 	 */
348 	if (class == ELFCLASS64) {
349 		/*
350 		 * If we're on a 64-bit kernel, try to exec a full 64-bit
351 		 * version of ld.
352 		 */
353 		conv_check_native(oargv, envp);
354 		libld = MSG_ORIG(MSG_LD_LIB64);
355 	}
356 	if ((libld_h = dlopen(libld, (RTLD_LAZY | RTLD_GLOBAL))) == NULL) {
357 		eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_DLOPEN), libld, dlerror());
358 		return (1);
359 	}
360 
361 	/*
362 	 * Find ld_main(), which is ld's generic entry point.
363 	 */
364 	if ((libld_main = (int (*)(int, char **))dlsym(libld_h,
365 	    MSG_ORIG(MSG_LD_MAIN))) == NULL) {
366 		eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_DLSYM), libld, dlerror());
367 		return (1);
368 	}
369 
370 	/*
371 	 * Reset the arg counter and getopt(3c) error message flag and call the
372 	 * generic entry point.
373 	 */
374 	optind = opterr = 1;
375 	return (libld_main(argc, argv));
376 }
377 
378 
379 /*
380  * Exported interfaces required by our dependencies.  libld and friends bind to
381  * the different implementations of these provided by either ld or ld.so.1.
382  */
383 const char *
384 _ld_msg(Msg mid)
385 {
386 	return (gettext(MSG_ORIG(mid)));
387 }
388 
389 /*
390  * Print a message to stdout
391  */
392 /* VARARGS2 */
393 void
394 eprintf(Error error, const char *format, ...)
395 {
396 	va_list			args;
397 	static const char	*strings[ERR_NUM] = { MSG_ORIG(MSG_STR_EMPTY) };
398 
399 	if (error > ERR_NONE) {
400 		if (error == ERR_WARNING) {
401 			if (strings[ERR_WARNING] == 0)
402 			    strings[ERR_WARNING] = MSG_INTL(MSG_ERR_WARNING);
403 		} else if (error == ERR_FATAL) {
404 			if (strings[ERR_FATAL] == 0)
405 			    strings[ERR_FATAL] = MSG_INTL(MSG_ERR_FATAL);
406 		} else if (error == ERR_ELF) {
407 			if (strings[ERR_ELF] == 0)
408 			    strings[ERR_ELF] = MSG_INTL(MSG_ERR_ELF);
409 		}
410 		(void) fputs(MSG_ORIG(MSG_STR_LDDIAG), stderr);
411 	}
412 	(void) fputs(strings[error], stderr);
413 
414 	va_start(args, format);
415 	(void) vfprintf(stderr, format, args);
416 	if (error == ERR_ELF) {
417 		int	elferr;
418 
419 		if ((elferr = elf_errno()) != 0)
420 			(void) fprintf(stderr, MSG_ORIG(MSG_STR_ELFDIAG),
421 			    elf_errmsg(elferr));
422 	}
423 	(void) fprintf(stderr, MSG_ORIG(MSG_STR_NL));
424 	(void) fflush(stderr);
425 	va_end(args);
426 }
427