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