10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51618Srie * Common Development and Distribution License (the "License"). 61618Srie * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211618Srie 220Sstevel@tonic-gate /* 23*6206Sab196087 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <stdio.h> 300Sstevel@tonic-gate #include <stdlib.h> 310Sstevel@tonic-gate #include <unistd.h> 320Sstevel@tonic-gate #include <stdarg.h> 330Sstevel@tonic-gate #include <string.h> 34*6206Sab196087 #include <strings.h> 350Sstevel@tonic-gate #include <errno.h> 360Sstevel@tonic-gate #include <fcntl.h> 370Sstevel@tonic-gate #include <libintl.h> 380Sstevel@tonic-gate #include <locale.h> 390Sstevel@tonic-gate #include <fcntl.h> 400Sstevel@tonic-gate #include "conv.h" 410Sstevel@tonic-gate #include "libld.h" 42*6206Sab196087 #include "machdep.h" 430Sstevel@tonic-gate #include "msg.h" 440Sstevel@tonic-gate 450Sstevel@tonic-gate /* 460Sstevel@tonic-gate * The following prevent us from having to include ctype.h which defines these 470Sstevel@tonic-gate * functions as macros which reference the __ctype[] array. Go through .plt's 480Sstevel@tonic-gate * to get to these functions in libc rather than have every invocation of ld 490Sstevel@tonic-gate * have to suffer the R_SPARC_COPY overhead of the __ctype[] array. 500Sstevel@tonic-gate */ 510Sstevel@tonic-gate extern int isspace(int); 520Sstevel@tonic-gate 531618Srie /* 541618Srie * Print a message to stdout 551618Srie */ 561618Srie /* VARARGS3 */ 571618Srie void 581618Srie eprintf(Lm_list *lml, Error error, const char *format, ...) 591618Srie { 601618Srie va_list args; 611618Srie static const char *strings[ERR_NUM] = { MSG_ORIG(MSG_STR_EMPTY) }; 621618Srie 631618Srie #if defined(lint) 641618Srie /* 651618Srie * The lml argument is only meaningful for diagnostics sent to ld.so.1. 661618Srie * Supress the lint error by making a dummy assignment. 671618Srie */ 681618Srie lml = 0; 691618Srie #endif 701618Srie if (error > ERR_NONE) { 711618Srie if (error == ERR_WARNING) { 721618Srie if (strings[ERR_WARNING] == 0) 73*6206Sab196087 strings[ERR_WARNING] = 74*6206Sab196087 MSG_INTL(MSG_ERR_WARNING); 751618Srie } else if (error == ERR_FATAL) { 761618Srie if (strings[ERR_FATAL] == 0) 77*6206Sab196087 strings[ERR_FATAL] = MSG_INTL(MSG_ERR_FATAL); 781618Srie } else if (error == ERR_ELF) { 791618Srie if (strings[ERR_ELF] == 0) 80*6206Sab196087 strings[ERR_ELF] = MSG_INTL(MSG_ERR_ELF); 811618Srie } 821618Srie (void) fputs(MSG_ORIG(MSG_STR_LDDIAG), stderr); 831618Srie } 841618Srie (void) fputs(strings[error], stderr); 851618Srie 861618Srie va_start(args, format); 871618Srie (void) vfprintf(stderr, format, args); 881618Srie if (error == ERR_ELF) { 891618Srie int elferr; 901618Srie 911618Srie if ((elferr = elf_errno()) != 0) 921618Srie (void) fprintf(stderr, MSG_ORIG(MSG_STR_ELFDIAG), 931618Srie elf_errmsg(elferr)); 941618Srie } 951618Srie (void) fprintf(stderr, MSG_ORIG(MSG_STR_NL)); 961618Srie (void) fflush(stderr); 971618Srie va_end(args); 981618Srie } 991618Srie 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate /* 102*6206Sab196087 * Determine: 103*6206Sab196087 * - ELFCLASS of resulting object (aoutclass) 104*6206Sab196087 * - Whether we need the 32 or 64-bit libld (ldclass) 105*6206Sab196087 * - ELF machine type of resulting object (m_mach) 1060Sstevel@tonic-gate */ 1070Sstevel@tonic-gate static int 108*6206Sab196087 process_args(int argc, char **argv, uchar_t *aoutclass, uchar_t *ldclass, 109*6206Sab196087 Half *mach) 1100Sstevel@tonic-gate { 111*6206Sab196087 #if defined(_LP64) 112*6206Sab196087 uchar_t lclass = ELFCLASS64; 1132647Srie #else 114*6206Sab196087 uchar_t lclass = ELFCLASSNONE; 1152647Srie #endif 116*6206Sab196087 uchar_t aclass = ELFCLASSNONE; 117*6206Sab196087 Half mach32 = EM_NONE, mach64 = EM_NONE; 1182647Srie int c; 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate getmore: 1210Sstevel@tonic-gate /* 122*6206Sab196087 * In general, libld.so is responsible for processing the 123*6206Sab196087 * command line options. The exception to this are those options 124*6206Sab196087 * that contain information about which linker to run and the 125*6206Sab196087 * class/machine of the output object. We examine the options 126*6206Sab196087 * here looking for the following: 127*6206Sab196087 * 128*6206Sab196087 * -64 129*6206Sab196087 * Produce an ELFCLASS64 object. Use the 64-bit linker. 1300Sstevel@tonic-gate * 131*6206Sab196087 * -zaltexec64 132*6206Sab196087 * Use the 64-bit linker regardless of the class 133*6206Sab196087 * of the output object. 134*6206Sab196087 * 135*6206Sab196087 * -z target=platform 136*6206Sab196087 * Produce output object for the specified platform. 137*6206Sab196087 * 138*6206Sab196087 * The -64 and -ztarget options are used when the only input to 139*6206Sab196087 * ld() is a mapfile or archive, and a 64-bit or non-native output 140*6206Sab196087 * object is required. 1412647Srie * 1422647Srie * If we've already processed a 32-bit object and we find -64, we have 1432647Srie * an error condition, but let this fall through to libld to obtain the 1442647Srie * default error message. 1450Sstevel@tonic-gate */ 1460Sstevel@tonic-gate opterr = 0; 1470Sstevel@tonic-gate while ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) { 1480Sstevel@tonic-gate switch (c) { 1490Sstevel@tonic-gate case '6': 1502647Srie if (strncmp(optarg, MSG_ORIG(MSG_ARG_FOUR), 1512647Srie MSG_ARG_FOUR_SIZE) == 0) 1522647Srie aclass = ELFCLASS64; 1532647Srie break; 154*6206Sab196087 1552647Srie case 'z': 156*6206Sab196087 #if !defined(_LP64) 157*6206Sab196087 /* -z altexec64 */ 1582647Srie if (strncmp(optarg, MSG_ORIG(MSG_ARG_ALTEXEC64), 159*6206Sab196087 MSG_ARG_ALTEXEC64_SIZE) == 0) { 1602647Srie lclass = ELFCLASS64; 161*6206Sab196087 break; 162*6206Sab196087 } 163*6206Sab196087 #endif 164*6206Sab196087 165*6206Sab196087 /* -z target=platform */ 166*6206Sab196087 if (strncmp(optarg, MSG_ORIG(MSG_ARG_TARGET), 167*6206Sab196087 MSG_ARG_TARGET_SIZE) == 0) { 168*6206Sab196087 char *pstr = 169*6206Sab196087 optarg + MSG_ARG_TARGET_SIZE; 170*6206Sab196087 171*6206Sab196087 if (strcasecmp(pstr, 172*6206Sab196087 MSG_ORIG(MSG_TARG_SPARC)) == 0) { 173*6206Sab196087 mach32 = EM_SPARC; 174*6206Sab196087 mach64 = EM_SPARCV9; 175*6206Sab196087 } else if (strcasecmp(pstr, 176*6206Sab196087 MSG_ORIG(MSG_TARG_X86)) == 0) { 177*6206Sab196087 mach32 = EM_386; 178*6206Sab196087 mach64 = EM_AMD64; 179*6206Sab196087 } else { 180*6206Sab196087 eprintf(0, ERR_FATAL, 181*6206Sab196087 MSG_INTL(MSG_ERR_BADTARG), 182*6206Sab196087 pstr); 183*6206Sab196087 return (1); 184*6206Sab196087 } 185*6206Sab196087 } 1862647Srie break; 187*6206Sab196087 1880Sstevel@tonic-gate default: 1890Sstevel@tonic-gate break; 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate /* 1942647Srie * Continue to look for the first ELF object to determine the class of 1950Sstevel@tonic-gate * objects to operate on. 1960Sstevel@tonic-gate */ 1970Sstevel@tonic-gate for (; optind < argc; optind++) { 1980Sstevel@tonic-gate int fd; 199*6206Sab196087 Elf32_Ehdr ehdr32; 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate /* 2020Sstevel@tonic-gate * If we detect some more options return to getopt(). 2030Sstevel@tonic-gate * Checking argv[optind][1] against null prevents a forever 2040Sstevel@tonic-gate * loop if an unadorned `-' argument is passed to us. 2050Sstevel@tonic-gate */ 2060Sstevel@tonic-gate if (argv[optind][0] == '-') { 2070Sstevel@tonic-gate if (argv[optind][1] == '\0') 2080Sstevel@tonic-gate continue; 2090Sstevel@tonic-gate else 2100Sstevel@tonic-gate goto getmore; 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate 2132647Srie /* 214*6206Sab196087 * If we've already determined the object class and 215*6206Sab196087 * machine type, continue to the next argument. Only 216*6206Sab196087 * the first object contributes to this decision, and 217*6206Sab196087 * there's no value to opening or examing the subsequent 218*6206Sab196087 * ones. We do need to keep going though, because there 219*6206Sab196087 * may be additional options that might affect our 220*6206Sab196087 * class/machine decision. 2212647Srie */ 222*6206Sab196087 if ((aclass != ELFCLASSNONE) && (mach32 != EM_NONE)) 2232647Srie continue; 2242647Srie 2252647Srie /* 2262647Srie * Open the file and determine the files ELF class. 2272647Srie */ 2280Sstevel@tonic-gate if ((fd = open(argv[optind], O_RDONLY)) == -1) { 2290Sstevel@tonic-gate int err = errno; 2300Sstevel@tonic-gate 2311618Srie eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), 2320Sstevel@tonic-gate argv[optind], strerror(err)); 2332647Srie return (1); 2340Sstevel@tonic-gate } 2350Sstevel@tonic-gate 236*6206Sab196087 /* 237*6206Sab196087 * Note that we read an entire 32-bit ELF header struct 238*6206Sab196087 * here, even though we have yet to determine that the 239*6206Sab196087 * file is an ELF object or that it is ELFCLASS32. We 240*6206Sab196087 * do this because: 241*6206Sab196087 * - Any valid ELF object of any class must 242*6206Sab196087 * have at least this number of bytes in it, 243*6206Sab196087 * since an ELF header is manditory, and since 244*6206Sab196087 * a 32-bit header is smaller than a 64-bit one. 245*6206Sab196087 * - The 32 and 64-bit ELF headers are identical 246*6206Sab196087 * up through the e_version field, so we can 247*6206Sab196087 * obtain the e_machine value of a 64-bit 248*6206Sab196087 * object via the e_machine value we read into 249*6206Sab196087 * the 32-bit version. This cannot change, because 250*6206Sab196087 * the layout of an ELF header is fixed by the ABI. 251*6206Sab196087 * 252*6206Sab196087 * Note however that we do have to worry about the byte 253*6206Sab196087 * order difference between the object and the system 254*6206Sab196087 * running this program when we read the e_machine value, 255*6206Sab196087 * since it is a multi-byte value; 256*6206Sab196087 */ 257*6206Sab196087 if ((read(fd, &ehdr32, sizeof (ehdr32)) == sizeof (ehdr32)) && 258*6206Sab196087 (ehdr32.e_ident[EI_MAG0] == ELFMAG0) && 259*6206Sab196087 (ehdr32.e_ident[EI_MAG1] == ELFMAG1) && 260*6206Sab196087 (ehdr32.e_ident[EI_MAG2] == ELFMAG2) && 261*6206Sab196087 (ehdr32.e_ident[EI_MAG3] == ELFMAG3)) { 262*6206Sab196087 if (aclass == ELFCLASSNONE) { 263*6206Sab196087 aclass = ehdr32.e_ident[EI_CLASS]; 264*6206Sab196087 if ((aclass != ELFCLASS32) && 265*6206Sab196087 (aclass != ELFCLASS64)) 266*6206Sab196087 aclass = ELFCLASSNONE; 267*6206Sab196087 } 268*6206Sab196087 269*6206Sab196087 if (mach32 == EM_NONE) { 270*6206Sab196087 int one = 1; 271*6206Sab196087 uchar_t *one_p = (uchar_t *)&one; 272*6206Sab196087 int ld_elfdata; 273*6206Sab196087 274*6206Sab196087 ld_elfdata = (one_p[0] == 1) ? 275*6206Sab196087 ELFDATA2LSB : ELFDATA2MSB; 276*6206Sab196087 /* 277*6206Sab196087 * Both the 32 and 64-bit versions get the 278*6206Sab196087 * type from the object. If the user has 279*6206Sab196087 * asked for an inconsistant class/machine 280*6206Sab196087 * combination, libld will catch it. 281*6206Sab196087 */ 282*6206Sab196087 mach32 = mach64 = 283*6206Sab196087 (ld_elfdata == ehdr32.e_ident[EI_DATA]) ? 284*6206Sab196087 ehdr32.e_machine : 285*6206Sab196087 BSWAP_HALF(ehdr32.e_machine); 286*6206Sab196087 } 2870Sstevel@tonic-gate } 288*6206Sab196087 2890Sstevel@tonic-gate (void) close(fd); 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate /* 293*6206Sab196087 * If we couldn't establish a class, default to 32-bit. 2940Sstevel@tonic-gate */ 295*6206Sab196087 if (aclass == ELFCLASSNONE) 2962647Srie aclass = ELFCLASS32; 297*6206Sab196087 *aoutclass = aclass; 298*6206Sab196087 299*6206Sab196087 if (lclass == ELFCLASSNONE) 3002647Srie lclass = ELFCLASS32; 301*6206Sab196087 *ldclass = lclass; 3020Sstevel@tonic-gate 303*6206Sab196087 /* 304*6206Sab196087 * Use the machine type that goes with the class we've determined. 305*6206Sab196087 * If we didn't find a usable machine type, use the native 306*6206Sab196087 * machine. 307*6206Sab196087 */ 308*6206Sab196087 *mach = (aclass == ELFCLASS64) ? mach64 : mach32; 309*6206Sab196087 if (*mach == EM_NONE) 310*6206Sab196087 *mach = (aclass == ELFCLASS64) ? M_MACH_64 : M_MACH_32; 311*6206Sab196087 3122647Srie return (0); 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate /* 3160Sstevel@tonic-gate * Prepend environment string as a series of options to the argv array. 3170Sstevel@tonic-gate */ 3180Sstevel@tonic-gate static int 3190Sstevel@tonic-gate prepend_ldoptions(char *ld_options, int *argcp, char ***argvp) 3200Sstevel@tonic-gate { 3211618Srie int nargc; /* new argc */ 3221618Srie char **nargv; /* new argv */ 3230Sstevel@tonic-gate char *arg, *string; 3240Sstevel@tonic-gate int count; 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate /* 3270Sstevel@tonic-gate * Get rid of leading white space, and make sure the string has size. 3280Sstevel@tonic-gate */ 3290Sstevel@tonic-gate while (isspace(*ld_options)) 3300Sstevel@tonic-gate ld_options++; 3310Sstevel@tonic-gate if (*ld_options == '\0') 3320Sstevel@tonic-gate return (1); 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate nargc = 0; 3350Sstevel@tonic-gate arg = string = ld_options; 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate /* 3380Sstevel@tonic-gate * Walk the environment string counting any arguments that are 3390Sstevel@tonic-gate * separated by white space. 3400Sstevel@tonic-gate */ 3410Sstevel@tonic-gate while (*string != '\0') { 3420Sstevel@tonic-gate if (isspace(*string)) { 3430Sstevel@tonic-gate nargc++; 3440Sstevel@tonic-gate while (isspace(*string)) 3450Sstevel@tonic-gate string++; 3460Sstevel@tonic-gate arg = string; 3470Sstevel@tonic-gate } else 3480Sstevel@tonic-gate string++; 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate if (arg != string) 3510Sstevel@tonic-gate nargc++; 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate /* 3540Sstevel@tonic-gate * Allocate a new argv array big enough to hold the new options from 3550Sstevel@tonic-gate * the environment string and the old argv options. 3560Sstevel@tonic-gate */ 3571618Srie if ((nargv = calloc(nargc + *argcp, sizeof (char *))) == 0) { 3581618Srie int err = errno; 3591618Srie eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_ALLOC), strerror(err)); 3600Sstevel@tonic-gate return (0); 3611618Srie } 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate /* 3640Sstevel@tonic-gate * Initialize first element of new argv array to be the first element 3650Sstevel@tonic-gate * of the old argv array (ie. calling programs name). Then add the new 3660Sstevel@tonic-gate * args obtained from the environment. 3670Sstevel@tonic-gate */ 3680Sstevel@tonic-gate nargv[0] = (*argvp)[0]; 3690Sstevel@tonic-gate nargc = 0; 3700Sstevel@tonic-gate arg = string = ld_options; 3710Sstevel@tonic-gate while (*string != '\0') { 3720Sstevel@tonic-gate if (isspace(*string)) { 3730Sstevel@tonic-gate nargc++; 3740Sstevel@tonic-gate *string++ = '\0'; 3750Sstevel@tonic-gate nargv[nargc] = arg; 3760Sstevel@tonic-gate while (isspace(*string)) 3770Sstevel@tonic-gate string++; 3780Sstevel@tonic-gate arg = string; 3790Sstevel@tonic-gate } else 3800Sstevel@tonic-gate string++; 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate if (arg != string) { 3830Sstevel@tonic-gate nargc++; 3840Sstevel@tonic-gate nargv[nargc] = arg; 3850Sstevel@tonic-gate } 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate /* 3880Sstevel@tonic-gate * Now add the original argv array (skipping argv[0]) to the end of the 3890Sstevel@tonic-gate * new argv array, and overwrite the old argc and argv. 3900Sstevel@tonic-gate */ 3910Sstevel@tonic-gate for (count = 1; count < *argcp; count++) { 3920Sstevel@tonic-gate nargc++; 3930Sstevel@tonic-gate nargv[nargc] = (*argvp)[count]; 3940Sstevel@tonic-gate } 3950Sstevel@tonic-gate *argcp = ++nargc; 3960Sstevel@tonic-gate *argvp = nargv; 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate return (1); 3990Sstevel@tonic-gate } 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate /* 4021618Srie * Check to see if there is a LD_ALTEXEC=<path to alternate ld> in the 4031618Srie * environment. If so, first null the environment variable out, and then 4041618Srie * exec() the binary pointed to by the environment variable, passing the same 4051618Srie * arguments as the originating process. This mechanism permits using 4061618Srie * alternate link-editors (debugging/developer copies) even in complex build 4071618Srie * environments. 4080Sstevel@tonic-gate */ 4092647Srie static int 4100Sstevel@tonic-gate ld_altexec(char **argv, char **envp) 4110Sstevel@tonic-gate { 4120Sstevel@tonic-gate char *execstr; 4130Sstevel@tonic-gate char **str; 4142647Srie int err; 4152647Srie 4160Sstevel@tonic-gate for (str = envp; *str; str++) { 4170Sstevel@tonic-gate if (strncmp(*str, MSG_ORIG(MSG_LD_ALTEXEC), 4180Sstevel@tonic-gate MSG_LD_ALTEXEC_SIZE) == 0) { 4190Sstevel@tonic-gate break; 4200Sstevel@tonic-gate } 4210Sstevel@tonic-gate } 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate /* 4242647Srie * If LD_ALTEXEC isn't set, return to continue executing the present 4252647Srie * link-editor. 4262647Srie */ 4272647Srie if (*str == 0) 4282647Srie return (0); 4292647Srie 4302647Srie /* 4312647Srie * Get a pointer to the actual string. If it's a null entry, return. 4320Sstevel@tonic-gate */ 4330Sstevel@tonic-gate execstr = strdup(*str + MSG_LD_ALTEXEC_SIZE); 4340Sstevel@tonic-gate if (*execstr == '\0') 4352647Srie return (0); 4362647Srie 4370Sstevel@tonic-gate /* 4380Sstevel@tonic-gate * Null out the LD_ALTEXEC= environment entry. 4390Sstevel@tonic-gate */ 4400Sstevel@tonic-gate (*str)[MSG_LD_ALTEXEC_SIZE] = '\0'; 4410Sstevel@tonic-gate 4420Sstevel@tonic-gate /* 4430Sstevel@tonic-gate * Set argv[0] to point to our new linker 4440Sstevel@tonic-gate */ 4450Sstevel@tonic-gate argv[0] = execstr; 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate /* 4480Sstevel@tonic-gate * And attempt to execute it. 4490Sstevel@tonic-gate */ 4500Sstevel@tonic-gate (void) execve(execstr, argv, envp); 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate /* 4532647Srie * If the exec() fails, return a failure indication. 4540Sstevel@tonic-gate */ 4552647Srie err = errno; 4562647Srie eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_EXEC), execstr, 4572647Srie strerror(err)); 4582647Srie return (1); 4590Sstevel@tonic-gate } 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate int 4620Sstevel@tonic-gate main(int argc, char **argv, char **envp) 4630Sstevel@tonic-gate { 4640Sstevel@tonic-gate char *ld_options, **oargv = argv; 4652647Srie uchar_t aoutclass, ldclass, checkclass; 466*6206Sab196087 Half mach; 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate /* 4691618Srie * XX64 -- Strip "-Wl," from the head of each argument. This is to 4701618Srie * accommodate awkwardness in passing ld arguments to gcc while 4711618Srie * maintaining the structure of the OSNet build environment's Makefiles. 4720Sstevel@tonic-gate */ 4730Sstevel@tonic-gate { 4740Sstevel@tonic-gate int i; 4750Sstevel@tonic-gate char *p; 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate for (i = 0; i < argc; i++) { 4780Sstevel@tonic-gate p = argv[i]; 4790Sstevel@tonic-gate while (*(p + 1) == 'W' && strncmp(p, "-Wl,-", 5) == 0) 4800Sstevel@tonic-gate argv[i] = (p += 4); 4810Sstevel@tonic-gate } 4820Sstevel@tonic-gate } 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate /* 4850Sstevel@tonic-gate * Establish locale. 4860Sstevel@tonic-gate */ 4870Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 4880Sstevel@tonic-gate (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate /* 4912647Srie * Execute an alternate linker if the LD_ALTEXEC environment variable is 4922647Srie * set. If a specified alternative could not be found, bail. 4930Sstevel@tonic-gate */ 4942647Srie if (ld_altexec(argv, envp)) 4952647Srie return (1); 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate /* 4980Sstevel@tonic-gate * Check the LD_OPTIONS environment variable, and if present prepend 4990Sstevel@tonic-gate * the arguments specified to the command line argument list. 5000Sstevel@tonic-gate */ 5010Sstevel@tonic-gate if ((ld_options = getenv(MSG_ORIG(MSG_LD_OPTIONS))) != NULL) { 5020Sstevel@tonic-gate /* 5030Sstevel@tonic-gate * Prevent modification of actual environment strings. 5040Sstevel@tonic-gate */ 5050Sstevel@tonic-gate if (((ld_options = strdup(ld_options)) == NULL) || 5060Sstevel@tonic-gate (prepend_ldoptions(ld_options, &argc, &argv) == 0)) 5070Sstevel@tonic-gate return (1); 5080Sstevel@tonic-gate } 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate /* 511*6206Sab196087 * Examine the command arguments to determine: 512*6206Sab196087 * - object class 513*6206Sab196087 * - link-editor class 514*6206Sab196087 * - target machine 5150Sstevel@tonic-gate */ 516*6206Sab196087 if (process_args(argc, argv, &aoutclass, &ldclass, &mach)) 5170Sstevel@tonic-gate return (1); 5180Sstevel@tonic-gate 5190Sstevel@tonic-gate /* 5202647Srie * If we're processing 64-bit objects, or the user specifically asked 5212647Srie * for a 64-bit link-editor, determine if a 64-bit ld() can be executed. 5222647Srie * Bail if a 64-bit ld() was explicitly asked for, but one could not be 5232647Srie * found. 5240Sstevel@tonic-gate */ 5252647Srie if ((aoutclass == ELFCLASS64) || (ldclass == ELFCLASS64)) 5262647Srie checkclass = conv_check_native(oargv, envp); 5272647Srie 5282647Srie if ((ldclass == ELFCLASS64) && (checkclass != ELFCLASS64)) { 5292647Srie eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_64)); 5302647Srie return (1); 5312647Srie } 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate /* 5341618Srie * Reset the getopt(3c) error message flag, and call the generic entry 5351618Srie * point using the appropriate class. 5360Sstevel@tonic-gate */ 5370Sstevel@tonic-gate optind = opterr = 1; 5382647Srie if (aoutclass == ELFCLASS64) 539*6206Sab196087 return (ld64_main(argc, argv, mach)); 5401618Srie else 541*6206Sab196087 return (ld32_main(argc, argv, mach)); 5420Sstevel@tonic-gate } 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate /* 5450Sstevel@tonic-gate * Exported interfaces required by our dependencies. libld and friends bind to 5460Sstevel@tonic-gate * the different implementations of these provided by either ld or ld.so.1. 5470Sstevel@tonic-gate */ 5480Sstevel@tonic-gate const char * 5490Sstevel@tonic-gate _ld_msg(Msg mid) 5500Sstevel@tonic-gate { 5510Sstevel@tonic-gate return (gettext(MSG_ORIG(mid))); 5520Sstevel@tonic-gate } 553