xref: /onnv-gate/usr/src/cmd/sgs/rtld/common/setup.c (revision 12877:69001e4756ae)
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 /*
2312650SRod.Evans@Sun.COM  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
256812Sraf 
266812Sraf /*
276812Sraf  *	Copyright (c) 1988 AT&T
286812Sraf  *	  All Rights Reserved
296812Sraf  */
306812Sraf 
310Sstevel@tonic-gate /*
320Sstevel@tonic-gate  * Run time linker common setup.
330Sstevel@tonic-gate  *
340Sstevel@tonic-gate  * Called from _setup to get the process going at startup.
350Sstevel@tonic-gate  */
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #include	<stdlib.h>
380Sstevel@tonic-gate #include	<fcntl.h>
390Sstevel@tonic-gate #include	<stdio.h>
400Sstevel@tonic-gate #include	<sys/types.h>
410Sstevel@tonic-gate #include	<sys/stat.h>
420Sstevel@tonic-gate #include	<sys/mman.h>
430Sstevel@tonic-gate #include	<string.h>
440Sstevel@tonic-gate #include	<unistd.h>
450Sstevel@tonic-gate #include	<dlfcn.h>
460Sstevel@tonic-gate #include	<sys/sysconfig.h>
470Sstevel@tonic-gate #include	<sys/auxv.h>
481618Srie #include	<debug.h>
491618Srie #include	<conv.h>
500Sstevel@tonic-gate #include	"_rtld.h"
510Sstevel@tonic-gate #include	"_audit.h"
520Sstevel@tonic-gate #include	"_elf.h"
530Sstevel@tonic-gate #include	"_a.out.h"
540Sstevel@tonic-gate #include	"msg.h"
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 
570Sstevel@tonic-gate extern int	_end, _edata, _etext;
580Sstevel@tonic-gate extern void	_init(void);
590Sstevel@tonic-gate extern int	_brk_unlocked(void *);
600Sstevel@tonic-gate 
610Sstevel@tonic-gate #ifndef	SGS_PRE_UNIFIED_PROCESS
620Sstevel@tonic-gate /* needed for _brk_unlocked() */
630Sstevel@tonic-gate void *_nd = &_end;
640Sstevel@tonic-gate #endif
650Sstevel@tonic-gate 
660Sstevel@tonic-gate /*
6711690SAli.Bahrami@Sun.COM  * Counters that are incremented every time an object is mapped/unmapped.
6811690SAli.Bahrami@Sun.COM  *
6911690SAli.Bahrami@Sun.COM  * Note that exec() will usually map 2 objects before we receive control,
7011690SAli.Bahrami@Sun.COM  * but this can be 1 if ld.so.1 is executed directly. We count one of these
7111690SAli.Bahrami@Sun.COM  * here, and add another as necessary in setup().
7211690SAli.Bahrami@Sun.COM  */
7311690SAli.Bahrami@Sun.COM u_longlong_t	cnt_map = 1;
7411690SAli.Bahrami@Sun.COM u_longlong_t	cnt_unmap = 0;
7511690SAli.Bahrami@Sun.COM 
7611690SAli.Bahrami@Sun.COM 
7711690SAli.Bahrami@Sun.COM /*
780Sstevel@tonic-gate  * Define for the executable's interpreter.
790Sstevel@tonic-gate  * Usually it is ld.so.1, but for the first release of ICL binaries
800Sstevel@tonic-gate  * it is libc.so.1.  We keep this information so that we don't end
810Sstevel@tonic-gate  * up mapping libc twice if it is the interpreter.
820Sstevel@tonic-gate  */
830Sstevel@tonic-gate static Interp _interp;
840Sstevel@tonic-gate 
859340SRod.Evans@Sun.COM /*
869340SRod.Evans@Sun.COM  * LD_PRELOAD objects.
879340SRod.Evans@Sun.COM  */
880Sstevel@tonic-gate static int
preload(const char * str,Rt_map * mlmp,Rt_map ** clmp)899340SRod.Evans@Sun.COM preload(const char *str, Rt_map *mlmp, Rt_map **clmp)
900Sstevel@tonic-gate {
918598SRod.Evans@Sun.COM 	Alist		*palp = NULL;
920Sstevel@tonic-gate 	char		*objs, *ptr, *next;
930Sstevel@tonic-gate 	Word		lmflags = lml_main.lm_flags;
949340SRod.Evans@Sun.COM 	int		lddstub;
950Sstevel@tonic-gate 
961618Srie 	DBG_CALL(Dbg_util_nl(&lml_main, DBG_NL_STD));
970Sstevel@tonic-gate 
988598SRod.Evans@Sun.COM 	if ((objs = strdup(str)) == NULL)
990Sstevel@tonic-gate 		return (0);
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 	/*
1029340SRod.Evans@Sun.COM 	 * Determine if we've been called from lddstub.
1030Sstevel@tonic-gate 	 */
1049340SRod.Evans@Sun.COM 	lddstub = (lmflags & LML_FLG_TRC_ENABLE) &&
1059340SRod.Evans@Sun.COM 	    (FLAGS1(*clmp) & FL1_RT_LDDSTUB);
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 	ptr = strtok_r(objs, MSG_ORIG(MSG_STR_DELIMIT), &next);
1080Sstevel@tonic-gate 	do {
1098598SRod.Evans@Sun.COM 		Rt_map	*nlmp = NULL;
1109340SRod.Evans@Sun.COM 		uint_t	flags;
1110Sstevel@tonic-gate 
1121618Srie 		DBG_CALL(Dbg_file_preload(&lml_main, ptr));
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 		/*
1159340SRod.Evans@Sun.COM 		 * Establish the flags for loading each object.  If we're
1169340SRod.Evans@Sun.COM 		 * called via lddstub, then the first preloaded object is the
1179340SRod.Evans@Sun.COM 		 * object being inspected by ldd(1).  This object should not be
1189340SRod.Evans@Sun.COM 		 * marked as an interposer, as this object is intended to act
1199340SRod.Evans@Sun.COM 		 * as the target object of the process.
1209340SRod.Evans@Sun.COM 		 */
1219340SRod.Evans@Sun.COM 		if (lddstub)
1229340SRod.Evans@Sun.COM 			flags = FLG_RT_PRELOAD;
1239340SRod.Evans@Sun.COM 		else
1249340SRod.Evans@Sun.COM 			flags = (FLG_RT_PRELOAD | FLG_RT_OBJINTPO);
1259340SRod.Evans@Sun.COM 
1269340SRod.Evans@Sun.COM 		/*
1270Sstevel@tonic-gate 		 * If this a secure application, then preload errors are
1280Sstevel@tonic-gate 		 * reduced to warnings, as the errors are non-fatal.
1290Sstevel@tonic-gate 		 */
1300Sstevel@tonic-gate 		if (rtld_flags & RT_FL_SECURE)
1310Sstevel@tonic-gate 			rtld_flags2 |= RT_FL2_FTL2WARN;
1329340SRod.Evans@Sun.COM 		if (expand_paths(*clmp, ptr, &palp, AL_CNT_NEEDED,
1338598SRod.Evans@Sun.COM 		    PD_FLG_EXTLOAD, 0) != 0)
1349340SRod.Evans@Sun.COM 			nlmp = load_one(&lml_main, ALIST_OFF_DATA, palp, *clmp,
1359340SRod.Evans@Sun.COM 			    MODE(mlmp), flags, 0, NULL);
136*12877SRod.Evans@Sun.COM 		remove_alist(&palp, 0);
1370Sstevel@tonic-gate 		if (rtld_flags & RT_FL_SECURE)
1380Sstevel@tonic-gate 			rtld_flags2 &= ~RT_FL2_FTL2WARN;
1399340SRod.Evans@Sun.COM 		if (nlmp && (bind_one(*clmp, nlmp, BND_NEEDED) == 0))
1408598SRod.Evans@Sun.COM 			nlmp = NULL;
1410Sstevel@tonic-gate 
1429340SRod.Evans@Sun.COM 		if (lddstub && nlmp) {
1439340SRod.Evans@Sun.COM 			lddstub = 0;
1449340SRod.Evans@Sun.COM 
1459340SRod.Evans@Sun.COM 			/*
1469340SRod.Evans@Sun.COM 			 * Fabricate a binding between the target shared object
1479340SRod.Evans@Sun.COM 			 * and lddstub so that the target object isn't called
1489340SRod.Evans@Sun.COM 			 * out from unused() processing.
1499340SRod.Evans@Sun.COM 			 */
1509340SRod.Evans@Sun.COM 			if (lmflags &
1519340SRod.Evans@Sun.COM 			    (LML_FLG_TRC_UNREF | LML_FLG_TRC_UNUSED)) {
1529340SRod.Evans@Sun.COM 				if (bind_one(*clmp, nlmp, BND_REFER) == 0)
1539340SRod.Evans@Sun.COM 					nlmp = NULL;
1549340SRod.Evans@Sun.COM 			}
1559340SRod.Evans@Sun.COM 
1569340SRod.Evans@Sun.COM 			/*
1579340SRod.Evans@Sun.COM 			 * By identifying lddstub as the caller, several
1589340SRod.Evans@Sun.COM 			 * confusing ldd() diagnostics get suppressed.  These
1599340SRod.Evans@Sun.COM 			 * diagnostics would reveal how the target shared object
1609340SRod.Evans@Sun.COM 			 * was found from lddstub.  Now that the real target is
1619340SRod.Evans@Sun.COM 			 * loaded, identify the target as the caller so that all
1629340SRod.Evans@Sun.COM 			 * ldd() diagnostics are enabled for subsequent objects.
1639340SRod.Evans@Sun.COM 			 */
1649340SRod.Evans@Sun.COM 			if (nlmp)
1659340SRod.Evans@Sun.COM 				*clmp = nlmp;
1669340SRod.Evans@Sun.COM 		}
1679340SRod.Evans@Sun.COM 
1680Sstevel@tonic-gate 		/*
1699340SRod.Evans@Sun.COM 		 * If no error occurred with loading this object, indicate that
1709340SRod.Evans@Sun.COM 		 * this link-map list contains an interposer.
1710Sstevel@tonic-gate 		 */
1728598SRod.Evans@Sun.COM 		if (nlmp == NULL) {
1730Sstevel@tonic-gate 			if ((lmflags & LML_FLG_TRC_ENABLE) ||
1740Sstevel@tonic-gate 			    (rtld_flags & RT_FL_SECURE))
1750Sstevel@tonic-gate 				continue;
1760Sstevel@tonic-gate 			else
1770Sstevel@tonic-gate 				return (0);
1780Sstevel@tonic-gate 		}
1799340SRod.Evans@Sun.COM 		if (flags & FLG_RT_OBJINTPO)
1809340SRod.Evans@Sun.COM 			lml_main.lm_flags |= LML_FLG_INTRPOSE;
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	} while ((ptr = strtok_r(NULL,
1830Sstevel@tonic-gate 	    MSG_ORIG(MSG_STR_DELIMIT), &next)) != NULL);
1840Sstevel@tonic-gate 
1858598SRod.Evans@Sun.COM 	free(palp);
1860Sstevel@tonic-gate 	free(objs);
1870Sstevel@tonic-gate 	return (1);
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate Rt_map *
setup(char ** envp,auxv_t * auxv,Word _flags,char * _platform,int _syspagsz,char * _rtldname,ulong_t ld_base,ulong_t interp_base,int fd,Phdr * phdr,char * execname,char ** argv,uid_t uid,uid_t euid,gid_t gid,gid_t egid,void * aoutdyn,int auxflags,uint_t hwcap_1)1916Srie setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz,
1928598SRod.Evans@Sun.COM     char *_rtldname, ulong_t ld_base, ulong_t interp_base, int fd, Phdr *phdr,
1938598SRod.Evans@Sun.COM     char *execname, char **argv, uid_t uid, uid_t euid, gid_t gid, gid_t egid,
1948598SRod.Evans@Sun.COM     void *aoutdyn, int auxflags, uint_t hwcap_1)
1950Sstevel@tonic-gate {
1969340SRod.Evans@Sun.COM 	Rt_map			*rlmp, *mlmp, *clmp, **tobj = NULL;
1978598SRod.Evans@Sun.COM 	Ehdr			*ehdr;
1988598SRod.Evans@Sun.COM 	rtld_stat_t		status;
1998598SRod.Evans@Sun.COM 	int			features = 0, ldsoexec = 0;
2008598SRod.Evans@Sun.COM 	size_t			eaddr, esize;
2018598SRod.Evans@Sun.COM 	char			*str, *argvname;
2028598SRod.Evans@Sun.COM 	Word			lmflags;
2038598SRod.Evans@Sun.COM 	mmapobj_result_t	*mpp;
2048598SRod.Evans@Sun.COM 	Fdesc			fdr = { 0 }, fdm = { 0 };
2058598SRod.Evans@Sun.COM 	Rej_desc		rej = { 0 };
20612650SRod.Evans@Sun.COM 	APlist			*ealp = NULL;
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	/*
2096Srie 	 * Now that ld.so has relocated itself, initialize our own 'environ' so
2109577SRod.Evans@Sun.COM 	 * as to establish an address suitable for any libc requirements.
2116Srie 	 */
2126Srie 	_environ = (char **)((ulong_t)auxv - sizeof (char *));
2136Srie 	_init();
2146Srie 	_environ = envp;
2156Srie 
2166Srie 	/*
2179577SRod.Evans@Sun.COM 	 * Establish a base time.  Total time diagnostics start from entering
2189577SRod.Evans@Sun.COM 	 * ld.so.1 here, however the base time is reset each time the ld.so.1
2199577SRod.Evans@Sun.COM 	 * is re-entered.  Note also, there will be a large time associated
2209577SRod.Evans@Sun.COM 	 * with the first diagnostic from ld.so.1, as bootstrapping ld.so.1
2219577SRod.Evans@Sun.COM 	 * and establishing the liblddbg infrastructure takes some time.
2229577SRod.Evans@Sun.COM 	 */
2239577SRod.Evans@Sun.COM 	(void) gettimeofday(&DBG_TOTALTIME, NULL);
2249577SRod.Evans@Sun.COM 	DBG_DELTATIME = DBG_TOTALTIME;
2259577SRod.Evans@Sun.COM 
2269577SRod.Evans@Sun.COM 	/*
2276Srie 	 * Determine how ld.so.1 has been executed.
2280Sstevel@tonic-gate 	 */
2298598SRod.Evans@Sun.COM 	if ((fd == -1) && (phdr == NULL)) {
2306Srie 		/*
2316Srie 		 * If we received neither the AT_EXECFD nor the AT_PHDR aux
2326Srie 		 * vector, ld.so.1 must have been invoked directly from the
2336Srie 		 * command line.
2346Srie 		 */
2356Srie 		ldsoexec = 1;
2360Sstevel@tonic-gate 
2376Srie 		/*
2386Srie 		 * AT_SUN_EXECNAME provides the most precise name, if it is
2396Srie 		 * available, otherwise fall back to argv[0].  At this time,
2406Srie 		 * there is no process name.
2416Srie 		 */
2426Srie 		if (execname)
2436Srie 			rtldname = execname;
2446Srie 		else if (argv[0])
2456Srie 			rtldname = argv[0];
2466Srie 		else
2476Srie 			rtldname = (char *)MSG_INTL(MSG_STR_UNKNOWN);
2486Srie 	} else {
2496Srie 		/*
2506Srie 		 * Otherwise, we have a standard process.  AT_SUN_EXECNAME
2516Srie 		 * provides the most precise name, if it is available,
2526Srie 		 * otherwise fall back to argv[0].  Provided the application
2536Srie 		 * is already mapped, the process is the application, so
2546Srie 		 * simplify the application name for use in any diagnostics.
2556Srie 		 */
2566Srie 		if (execname)
2576Srie 			argvname = execname;
2586Srie 		else if (argv[0])
2596Srie 			argvname = execname = argv[0];
2606Srie 		else
2616Srie 			argvname = execname = (char *)MSG_INTL(MSG_STR_UNKNOWN);
2626Srie 
2636Srie 		if (fd == -1) {
2648598SRod.Evans@Sun.COM 			if ((str = strrchr(argvname, '/')) != NULL)
2656Srie 				procname = ++str;
2666Srie 			else
2676Srie 				procname = argvname;
2686Srie 		}
2696Srie 
2706Srie 		/*
2716Srie 		 * At this point, we don't know the runtime linkers full path
2726Srie 		 * name.  The _rtldname passed to us is the SONAME of the
2736Srie 		 * runtime linker, which is typically /lib/ld.so.1 no matter
2746Srie 		 * what the full path is.   Use this for now, we'll reset the
2756Srie 		 * runtime linkers name once the application is analyzed.
2766Srie 		 */
2776Srie 		if (_rtldname) {
2788598SRod.Evans@Sun.COM 			if ((str = strrchr(_rtldname, '/')) != NULL)
2796Srie 				rtldname = ++str;
2806Srie 			else
2816Srie 				rtldname = _rtldname;
2826Srie 		} else
2836Srie 			rtldname = (char *)MSG_INTL(MSG_STR_UNKNOWN);
28411690SAli.Bahrami@Sun.COM 
28511690SAli.Bahrami@Sun.COM 		/* exec() brought in two objects for us. Count the second one */
28611690SAli.Bahrami@Sun.COM 		cnt_map++;
2876Srie 	}
2886Srie 
2896Srie 	/*
2906Srie 	 * Initialize any global variables.
2916Srie 	 */
2920Sstevel@tonic-gate 	at_flags = _flags;
29311827SRod.Evans@Sun.COM 
29411827SRod.Evans@Sun.COM 	if ((org_scapset->sc_plat = _platform) != NULL)
29511827SRod.Evans@Sun.COM 		org_scapset->sc_platsz = strlen(_platform);
29611827SRod.Evans@Sun.COM 
29711827SRod.Evans@Sun.COM 	if (org_scapset->sc_plat == NULL)
29811827SRod.Evans@Sun.COM 		platform_name(org_scapset);
29911827SRod.Evans@Sun.COM 	if (org_scapset->sc_mach == NULL)
30011827SRod.Evans@Sun.COM 		machine_name(org_scapset);
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	/*
3030Sstevel@tonic-gate 	 * If pagesize is unspecified find its value.
3040Sstevel@tonic-gate 	 */
3050Sstevel@tonic-gate 	if ((syspagsz = _syspagsz) == 0)
3060Sstevel@tonic-gate 		syspagsz = _sysconfig(_CONFIG_PAGESIZE);
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	/*
3090Sstevel@tonic-gate 	 * Add the unused portion of the last data page to the free space list.
3100Sstevel@tonic-gate 	 * The page size must be set before doing this.  Here, _end refers to
3110Sstevel@tonic-gate 	 * the end of the runtime linkers bss.  Note that we do not use the
3120Sstevel@tonic-gate 	 * unused data pages from any included .so's to supplement this free
3130Sstevel@tonic-gate 	 * space as badly behaved .os's may corrupt this data space, and in so
3140Sstevel@tonic-gate 	 * doing ruin our data.
3150Sstevel@tonic-gate 	 */
3160Sstevel@tonic-gate 	eaddr = S_DROUND((size_t)&_end);
3170Sstevel@tonic-gate 	esize = eaddr % syspagsz;
3180Sstevel@tonic-gate 	if (esize) {
3190Sstevel@tonic-gate 		esize = syspagsz - esize;
3200Sstevel@tonic-gate 		addfree((void *)eaddr, esize);
3210Sstevel@tonic-gate 	}
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	/*
3240Sstevel@tonic-gate 	 * Establish initial link-map list flags, and link-map list alists.
3250Sstevel@tonic-gate 	 */
3269340SRod.Evans@Sun.COM 	if (alist_append(&lml_main.lm_lists, NULL, sizeof (Lm_cntl),
3278598SRod.Evans@Sun.COM 	    AL_CNT_LMLISTS) == NULL)
3280Sstevel@tonic-gate 		return (0);
3290Sstevel@tonic-gate 	lml_main.lm_flags |= LML_FLG_BASELM;
3301618Srie 	lml_main.lm_lmid = LM_ID_BASE;
3311618Srie 	lml_main.lm_lmidstr = (char *)MSG_ORIG(MSG_LMID_BASE);
3320Sstevel@tonic-gate 
3339340SRod.Evans@Sun.COM 	if (alist_append(&lml_rtld.lm_lists, NULL, sizeof (Lm_cntl),
3348598SRod.Evans@Sun.COM 	    AL_CNT_LMLISTS) == NULL)
3350Sstevel@tonic-gate 		return (0);
336*12877SRod.Evans@Sun.COM 	lml_rtld.lm_flags |= (LML_FLG_RTLDLM | LML_FLG_HOLDLOCK);
337*12877SRod.Evans@Sun.COM 	lml_rtld.lm_tflags |= LML_TFLG_NOAUDIT;
3381618Srie 	lml_rtld.lm_lmid = LM_ID_LDSO;
3391618Srie 	lml_rtld.lm_lmidstr = (char *)MSG_ORIG(MSG_LMID_LDSO);
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	/*
3420Sstevel@tonic-gate 	 * Determine whether we have a secure executable.
3430Sstevel@tonic-gate 	 */
3440Sstevel@tonic-gate 	security(uid, euid, gid, egid, auxflags);
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 	/*
34712650SRod.Evans@Sun.COM 	 * Make an initial pass of environment variables to pick off those
34812650SRod.Evans@Sun.COM 	 * related to locale processing.  At the same time, collect and save
34912650SRod.Evans@Sun.COM 	 * any LD_XXXX variables for later processing.  Note that this later
35012650SRod.Evans@Sun.COM 	 * processing will be skipped if ld.so.1 is invoked from the command
35112650SRod.Evans@Sun.COM 	 * line with -e LD_NOENVIRON.
35212650SRod.Evans@Sun.COM 	 */
35312650SRod.Evans@Sun.COM 	if (envp && (readenv_user((const char **)envp, &ealp) == 1))
35412650SRod.Evans@Sun.COM 		return (0);
35512650SRod.Evans@Sun.COM 
35612650SRod.Evans@Sun.COM 	/*
35712650SRod.Evans@Sun.COM 	 * If ld.so.1 has been invoked directly, process its arguments.
3580Sstevel@tonic-gate 	 */
35912650SRod.Evans@Sun.COM 	if (ldsoexec) {
36012650SRod.Evans@Sun.COM 		/*
36112650SRod.Evans@Sun.COM 		 * Process any arguments that are specific to ld.so.1, and
36212650SRod.Evans@Sun.COM 		 * reorganize the process stack to effectively remove ld.so.1
36312650SRod.Evans@Sun.COM 		 * from the stack.  Reinitialize the environment pointer, as
36412650SRod.Evans@Sun.COM 		 * this pointer may have been shifted after skipping ld.so.1's
36512650SRod.Evans@Sun.COM 		 * arguments.
36612650SRod.Evans@Sun.COM 		 */
36712650SRod.Evans@Sun.COM 		if (rtld_getopt(argv, &envp, &auxv, &(lml_main.lm_flags),
36812650SRod.Evans@Sun.COM 		    &(lml_main.lm_tflags), (aoutdyn != 0)) == 1) {
36912650SRod.Evans@Sun.COM 			eprintf(&lml_main, ERR_NONE, MSG_INTL(MSG_USG_BADOPT));
37012650SRod.Evans@Sun.COM 			return (0);
37112650SRod.Evans@Sun.COM 		}
37212650SRod.Evans@Sun.COM 		_environ = envp;
37312650SRod.Evans@Sun.COM 
37412650SRod.Evans@Sun.COM 		/*
37512650SRod.Evans@Sun.COM 		 * Open the object that ld.so.1 is to execute.
37612650SRod.Evans@Sun.COM 		 */
37712650SRod.Evans@Sun.COM 		argvname = execname = argv[0];
37812650SRod.Evans@Sun.COM 
37912650SRod.Evans@Sun.COM 		if ((fd = open(argvname, O_RDONLY)) == -1) {
38012650SRod.Evans@Sun.COM 			int	err = errno;
38112650SRod.Evans@Sun.COM 			eprintf(&lml_main, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
38212650SRod.Evans@Sun.COM 			    argvname, strerror(err));
38312650SRod.Evans@Sun.COM 			return (0);
38412650SRod.Evans@Sun.COM 		}
38512650SRod.Evans@Sun.COM 	}
38612650SRod.Evans@Sun.COM 
38712650SRod.Evans@Sun.COM 	/*
38812650SRod.Evans@Sun.COM 	 * Having processed any ld.so.1 command line options, return to process
38912650SRod.Evans@Sun.COM 	 * any LD_XXXX environment variables.
39012650SRod.Evans@Sun.COM 	 */
39112650SRod.Evans@Sun.COM 	if (ealp) {
39212650SRod.Evans@Sun.COM 		if (((rtld_flags & RT_FL_NOENVIRON) == 0) &&
39312650SRod.Evans@Sun.COM 		    (procenv_user(ealp, &(lml_main.lm_flags),
39412650SRod.Evans@Sun.COM 		    &(lml_main.lm_tflags), (aoutdyn != 0)) == 1))
39512650SRod.Evans@Sun.COM 			return (0);
39612650SRod.Evans@Sun.COM 		free(ealp);
39712650SRod.Evans@Sun.COM 	}
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	/*
40011827SRod.Evans@Sun.COM 	 * Initialize a hardware capability descriptor for use in comparing
40111827SRod.Evans@Sun.COM 	 * each loaded object.  The aux vector must provide AF_SUN_HWCAPVERIFY,
40211827SRod.Evans@Sun.COM 	 * as prior to this setting any hardware capabilities that were found
40312650SRod.Evans@Sun.COM 	 * could not be relied upon.
40411827SRod.Evans@Sun.COM 	 */
40511827SRod.Evans@Sun.COM 	if (auxflags & AF_SUN_HWCAPVERIFY) {
40611827SRod.Evans@Sun.COM 		rtld_flags2 |= RT_FL2_HWCAP;
40711827SRod.Evans@Sun.COM 		org_scapset->sc_hw_1 = (Xword)hwcap_1;
40811827SRod.Evans@Sun.COM 	}
40911827SRod.Evans@Sun.COM 
41011827SRod.Evans@Sun.COM 	/*
4110Sstevel@tonic-gate 	 * Create a mapping descriptor for ld.so.1.  We can determine our
4120Sstevel@tonic-gate 	 * two segments information from known symbols.
4130Sstevel@tonic-gate 	 */
4148598SRod.Evans@Sun.COM 	if ((mpp = calloc(2, sizeof (mmapobj_result_t))) == NULL)
4150Sstevel@tonic-gate 		return (0);
4168598SRod.Evans@Sun.COM 	mpp[0].mr_addr = (caddr_t)M_PTRUNC(ld_base);
4178598SRod.Evans@Sun.COM 	mpp[0].mr_msize = (caddr_t)&_etext - mpp[0].mr_addr;
4188598SRod.Evans@Sun.COM 	mpp[0].mr_fsize = mpp[0].mr_msize;
4198598SRod.Evans@Sun.COM 	mpp[0].mr_prot = (PROT_READ | PROT_EXEC);
4208598SRod.Evans@Sun.COM 
4218598SRod.Evans@Sun.COM 	mpp[1].mr_addr = (caddr_t)M_PTRUNC((uintptr_t)&r_debug);
4228598SRod.Evans@Sun.COM 	mpp[1].mr_msize = (caddr_t)&_end - mpp[1].mr_addr;
4238598SRod.Evans@Sun.COM 	mpp[1].mr_fsize = (caddr_t)&_edata - mpp[1].mr_addr;
4248598SRod.Evans@Sun.COM 	mpp[1].mr_prot = (PROT_READ | PROT_WRITE | PROT_EXEC);
4250Sstevel@tonic-gate 
4268598SRod.Evans@Sun.COM 	if ((fdr.fd_nname = stravl_insert(_rtldname, 0, 0, 0)) == NULL)
4278598SRod.Evans@Sun.COM 		return (0);
4288598SRod.Evans@Sun.COM 	if ((rlmp = elf_new_lmp(&lml_rtld, ALIST_OFF_DATA, &fdr,
4298598SRod.Evans@Sun.COM 	    (Addr)mpp->mr_addr, (size_t)((uintptr_t)eaddr - (uintptr_t)ld_base),
430*12877SRod.Evans@Sun.COM 	    NULL, NULL, NULL)) == NULL)
4310Sstevel@tonic-gate 		return (0);
4328598SRod.Evans@Sun.COM 
4338598SRod.Evans@Sun.COM 	MMAPS(rlmp) = mpp;
4348598SRod.Evans@Sun.COM 	MMAPCNT(rlmp) = 2;
4358598SRod.Evans@Sun.COM 	PADSTART(rlmp) = (ulong_t)mpp[0].mr_addr;
4368598SRod.Evans@Sun.COM 	PADIMLEN(rlmp) = (ulong_t)mpp[0].mr_addr + (ulong_t)mpp[1].mr_addr +
4378598SRod.Evans@Sun.COM 	    (ulong_t)mpp[1].mr_msize;
4386Srie 
4390Sstevel@tonic-gate 	MODE(rlmp) |= (RTLD_LAZY | RTLD_NODELETE | RTLD_GLOBAL | RTLD_WORLD);
4400Sstevel@tonic-gate 	FLAGS(rlmp) |= (FLG_RT_ANALYZED | FLG_RT_RELOCED | FLG_RT_INITDONE |
4414679Srie 	    FLG_RT_INITCLCT | FLG_RT_FINICLCT | FLG_RT_MODESET);
4426Srie 
4436Srie 	/*
4446Srie 	 * Initialize the runtime linkers information.
4456Srie 	 */
4466Srie 	interp = &_interp;
4478598SRod.Evans@Sun.COM 	interp->i_name = (char *)rtldname;
4486Srie 	interp->i_faddr = (caddr_t)ADDR(rlmp);
4490Sstevel@tonic-gate 	ldso_plt_init(rlmp);
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	/*
4528598SRod.Evans@Sun.COM 	 * Map in the file, if exec has not already done so, or if the file
4538598SRod.Evans@Sun.COM 	 * was passed as an argument to an explicit execution of ld.so.1 from
4548598SRod.Evans@Sun.COM 	 * the command line.
4550Sstevel@tonic-gate 	 */
4560Sstevel@tonic-gate 	if (fd != -1) {
4570Sstevel@tonic-gate 		/*
4588598SRod.Evans@Sun.COM 		 * Map the file.  Once the object is mapped we no longer need
4598598SRod.Evans@Sun.COM 		 * the file descriptor.
4600Sstevel@tonic-gate 		 */
4618394SAli.Bahrami@Sun.COM 		(void) rtld_fstat(fd, &status);
46212650SRod.Evans@Sun.COM 		fdm.fd_oname = argvname;
4638598SRod.Evans@Sun.COM 		fdm.fd_ftp = map_obj(&lml_main, &fdm, status.st_size, argvname,
4648598SRod.Evans@Sun.COM 		    fd, &rej);
4658598SRod.Evans@Sun.COM 		(void) close(fd);
4668598SRod.Evans@Sun.COM 
4678598SRod.Evans@Sun.COM 		if (fdm.fd_ftp == NULL) {
4684734Sab196087 			Conv_reject_desc_buf_t rej_buf;
4694734Sab196087 
4701618Srie 			eprintf(&lml_main, ERR_FATAL,
4711618Srie 			    MSG_INTL(err_reject[rej.rej_type]), argvname,
4726206Sab196087 			    conv_reject_desc(&rej, &rej_buf, M_MACH));
4730Sstevel@tonic-gate 			return (0);
4740Sstevel@tonic-gate 		}
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 		/*
4778598SRod.Evans@Sun.COM 		 * Finish processing the loading of the file.
4780Sstevel@tonic-gate 		 */
4798598SRod.Evans@Sun.COM 		if ((fdm.fd_nname = stravl_insert(argvname, 0, 0, 0)) == NULL)
4808598SRod.Evans@Sun.COM 			return (0);
4818598SRod.Evans@Sun.COM 		fdm.fd_dev = status.st_dev;
4828598SRod.Evans@Sun.COM 		fdm.fd_ino = status.st_ino;
4838598SRod.Evans@Sun.COM 
484*12877SRod.Evans@Sun.COM 		if ((mlmp = load_file(&lml_main, ALIST_OFF_DATA, NULL, &fdm,
4858598SRod.Evans@Sun.COM 		    NULL)) == NULL)
4860Sstevel@tonic-gate 			return (0);
4870Sstevel@tonic-gate 
4886Srie 		/*
4896Srie 		 * We now have a process name for error diagnostics.
4906Srie 		 */
4918598SRod.Evans@Sun.COM 		if ((str = strrchr(argvname, '/')) != NULL)
4926Srie 			procname = ++str;
4936Srie 		else
4946Srie 			procname = argvname;
4956Srie 
4960Sstevel@tonic-gate 		if (ldsoexec) {
4978598SRod.Evans@Sun.COM 			mmapobj_result_t	*mpp = MMAPS(mlmp);
4988598SRod.Evans@Sun.COM 			uint_t			mnum, mapnum = MMAPCNT(mlmp);
4998598SRod.Evans@Sun.COM 			void			*brkbase = NULL;
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 			/*
5020Sstevel@tonic-gate 			 * Since ld.so.1 was the primary executed object - the
5030Sstevel@tonic-gate 			 * brk() base has not yet been initialized, we need to
5040Sstevel@tonic-gate 			 * initialize it.  For an executable, initialize it to
5050Sstevel@tonic-gate 			 * the end of the object.  For a shared object (ET_DYN)
5060Sstevel@tonic-gate 			 * initialize it to the first page in memory.
5070Sstevel@tonic-gate 			 */
5088598SRod.Evans@Sun.COM 			for (mnum = 0; mnum < mapnum; mnum++, mpp++)
5098598SRod.Evans@Sun.COM 				brkbase = mpp->mr_addr + mpp->mr_msize;
5100Sstevel@tonic-gate 
5118598SRod.Evans@Sun.COM 			if (brkbase == NULL)
5128598SRod.Evans@Sun.COM 				brkbase = (void *)syspagsz;
5130Sstevel@tonic-gate 
5148598SRod.Evans@Sun.COM 			if (_brk_unlocked(brkbase) == -1) {
5158598SRod.Evans@Sun.COM 				int	err = errno;
5160Sstevel@tonic-gate 
5171618Srie 				eprintf(&lml_main, ERR_FATAL,
5181618Srie 				    MSG_INTL(MSG_SYS_BRK), argvname,
5191618Srie 				    strerror(err));
5208598SRod.Evans@Sun.COM 				return (0);
5210Sstevel@tonic-gate 			}
5220Sstevel@tonic-gate 		}
5230Sstevel@tonic-gate 	} else {
5240Sstevel@tonic-gate 		/*
5250Sstevel@tonic-gate 		 * Set up function ptr and arguments according to the type
5260Sstevel@tonic-gate 		 * of file class the executable is. (Currently only supported
5270Sstevel@tonic-gate 		 * types are ELF and a.out format.)  Then create a link map
5280Sstevel@tonic-gate 		 * for the executable.
5290Sstevel@tonic-gate 		 */
5300Sstevel@tonic-gate 		if (aoutdyn) {
5310Sstevel@tonic-gate #ifdef A_OUT
5328598SRod.Evans@Sun.COM 			mmapobj_result_t	*mpp;
5338598SRod.Evans@Sun.COM 
5348598SRod.Evans@Sun.COM 			/*
5358598SRod.Evans@Sun.COM 			 * Create a mapping structure sufficient to describe
5368598SRod.Evans@Sun.COM 			 * a single two segments.  The ADDR() of the a.out is
5378598SRod.Evans@Sun.COM 			 * established as 0, which is required but the AOUT
5388598SRod.Evans@Sun.COM 			 * relocation code.
5398598SRod.Evans@Sun.COM 			 */
5408598SRod.Evans@Sun.COM 			if ((mpp =
5418598SRod.Evans@Sun.COM 			    calloc(sizeof (mmapobj_result_t), 2)) == NULL)
5428598SRod.Evans@Sun.COM 				return (0);
5438598SRod.Evans@Sun.COM 
5448598SRod.Evans@Sun.COM 			if ((fdm.fd_nname =
5458598SRod.Evans@Sun.COM 			    stravl_insert(execname, 0, 0, 0)) == NULL)
5468598SRod.Evans@Sun.COM 				return (0);
5478598SRod.Evans@Sun.COM 			if ((mlmp = aout_new_lmp(&lml_main, ALIST_OFF_DATA,
548*12877SRod.Evans@Sun.COM 			    &fdm, 0, 0, aoutdyn, NULL, NULL)) == NULL)
5490Sstevel@tonic-gate 				return (0);
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 			/*
5528598SRod.Evans@Sun.COM 			 * Establish the true mapping information for the a.out.
5530Sstevel@tonic-gate 			 */
5548598SRod.Evans@Sun.COM 			if (aout_get_mmap(&lml_main, mpp)) {
5558598SRod.Evans@Sun.COM 				free(mpp);
5568598SRod.Evans@Sun.COM 				return (0);
5578598SRod.Evans@Sun.COM 			}
5588598SRod.Evans@Sun.COM 
5598598SRod.Evans@Sun.COM 			MSIZE(mlmp) =
5608598SRod.Evans@Sun.COM 			    (size_t)(mpp[1].mr_addr + mpp[1].mr_msize) -
5618598SRod.Evans@Sun.COM 			    S_ALIGN((size_t)mpp[0].mr_addr, syspagsz);
5628598SRod.Evans@Sun.COM 			MMAPS(mlmp) = mpp;
5638598SRod.Evans@Sun.COM 			MMAPCNT(mlmp) = 2;
5648598SRod.Evans@Sun.COM 			PADSTART(mlmp) = (ulong_t)mpp->mr_addr;
5658598SRod.Evans@Sun.COM 			PADIMLEN(mlmp) = mpp->mr_msize;
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate 			/*
5680Sstevel@tonic-gate 			 * Disable any object configuration cache (BCP apps
5690Sstevel@tonic-gate 			 * bring in sbcp which can benefit from any object
5700Sstevel@tonic-gate 			 * cache, but both the app and sbcp can't use the same
5710Sstevel@tonic-gate 			 * objects).
5720Sstevel@tonic-gate 			 */
5730Sstevel@tonic-gate 			rtld_flags |= RT_FL_NOOBJALT;
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 			/*
5760Sstevel@tonic-gate 			 * Make sure no-direct bindings are in effect.
5770Sstevel@tonic-gate 			 */
5780Sstevel@tonic-gate 			lml_main.lm_tflags |= LML_TFLG_NODIRECT;
5790Sstevel@tonic-gate #else
5801618Srie 			eprintf(&lml_main, ERR_FATAL,
5811618Srie 			    MSG_INTL(MSG_ERR_REJ_UNKFILE), argvname);
5820Sstevel@tonic-gate 			return (0);
5830Sstevel@tonic-gate #endif
5840Sstevel@tonic-gate 		} else if (phdr) {
5858598SRod.Evans@Sun.COM 			Phdr			*pptr;
5868598SRod.Evans@Sun.COM 			Off			i_offset = 0;
5878598SRod.Evans@Sun.COM 			Addr			base = 0;
5888598SRod.Evans@Sun.COM 			ulong_t			phsize;
5898598SRod.Evans@Sun.COM 			mmapobj_result_t	*mpp, *fmpp, *hmpp = NULL;
5908598SRod.Evans@Sun.COM 			uint_t			mapnum = 0;
5918598SRod.Evans@Sun.COM 			int			i;
5928598SRod.Evans@Sun.COM 			size_t			msize;
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 			/*
5950Sstevel@tonic-gate 			 * Using the executables phdr address determine the base
5960Sstevel@tonic-gate 			 * address of the input file.  NOTE, this assumes the
5970Sstevel@tonic-gate 			 * program headers and elf header are part of the same
5980Sstevel@tonic-gate 			 * mapped segment.  Although this has held for many
5990Sstevel@tonic-gate 			 * years now, it might be more flexible if the kernel
6000Sstevel@tonic-gate 			 * gave use the ELF headers start address, rather than
6010Sstevel@tonic-gate 			 * the Program headers.
6020Sstevel@tonic-gate 			 *
6030Sstevel@tonic-gate 			 * Determine from the ELF header if we're been called
6040Sstevel@tonic-gate 			 * from a shared object or dynamic executable.  If the
6050Sstevel@tonic-gate 			 * latter, then any addresses within the object are used
6060Sstevel@tonic-gate 			 * as is.  Addresses within shared objects must be added
6070Sstevel@tonic-gate 			 * to the process's base address.
6080Sstevel@tonic-gate 			 */
6090Sstevel@tonic-gate 			ehdr = (Ehdr *)((Addr)phdr - phdr->p_offset);
6100Sstevel@tonic-gate 			phsize = ehdr->e_phentsize;
6116Srie 			if (ehdr->e_type == ET_DYN)
6120Sstevel@tonic-gate 				base = (Addr)ehdr;
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate 			/*
6150Sstevel@tonic-gate 			 * Allocate a mapping array to retain mapped segment
6160Sstevel@tonic-gate 			 * information.
6170Sstevel@tonic-gate 			 */
6188598SRod.Evans@Sun.COM 			if ((fmpp = mpp = calloc(ehdr->e_phnum,
6198598SRod.Evans@Sun.COM 			    sizeof (mmapobj_result_t))) == NULL)
6200Sstevel@tonic-gate 				return (0);
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 			/*
6230Sstevel@tonic-gate 			 * Extract the needed information from the segment
6240Sstevel@tonic-gate 			 * headers.
6250Sstevel@tonic-gate 			 */
6260Sstevel@tonic-gate 			for (i = 0, pptr = phdr; i < ehdr->e_phnum; i++) {
6270Sstevel@tonic-gate 				if (pptr->p_type == PT_INTERP) {
6280Sstevel@tonic-gate 					i_offset = pptr->p_offset;
6290Sstevel@tonic-gate 					interp->i_faddr =
6300Sstevel@tonic-gate 					    (caddr_t)interp_base;
6310Sstevel@tonic-gate 				}
6320Sstevel@tonic-gate 				if ((pptr->p_type == PT_LOAD) &&
6330Sstevel@tonic-gate 				    (pptr->p_filesz || pptr->p_memsz)) {
6340Sstevel@tonic-gate 					int	perm = (PROT_READ | PROT_EXEC);
6350Sstevel@tonic-gate 					size_t	off;
6360Sstevel@tonic-gate 
6376Srie 					if (i_offset && pptr->p_filesz &&
6380Sstevel@tonic-gate 					    (i_offset >= pptr->p_offset) &&
6390Sstevel@tonic-gate 					    (i_offset <=
6400Sstevel@tonic-gate 					    (pptr->p_memsz + pptr->p_offset))) {
6410Sstevel@tonic-gate 						interp->i_name = (char *)
6420Sstevel@tonic-gate 						    pptr->p_vaddr + i_offset -
6430Sstevel@tonic-gate 						    pptr->p_offset + base;
6446Srie 						i_offset = 0;
6450Sstevel@tonic-gate 					}
6468598SRod.Evans@Sun.COM 
6478598SRod.Evans@Sun.COM 					if (pptr->p_flags & PF_W)
6480Sstevel@tonic-gate 						perm |= PROT_WRITE;
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 					/*
6510Sstevel@tonic-gate 					 * Retain segments mapping info.  Round
6520Sstevel@tonic-gate 					 * each segment to a page boundary, as
6530Sstevel@tonic-gate 					 * this insures addresses are suitable
6540Sstevel@tonic-gate 					 * for mprotect() if required.
6550Sstevel@tonic-gate 					 */
6560Sstevel@tonic-gate 					off = pptr->p_vaddr + base;
6578598SRod.Evans@Sun.COM 					if (hmpp == NULL) {
6588598SRod.Evans@Sun.COM 						hmpp = mpp;
6598598SRod.Evans@Sun.COM 						mpp->mr_addr = (caddr_t)ehdr;
6608598SRod.Evans@Sun.COM 					} else
6618598SRod.Evans@Sun.COM 						mpp->mr_addr = (caddr_t)off;
6620Sstevel@tonic-gate 
6638598SRod.Evans@Sun.COM 					off -= (size_t)(uintptr_t)mpp->mr_addr;
6648598SRod.Evans@Sun.COM 					mpp->mr_msize = pptr->p_memsz + off;
6658598SRod.Evans@Sun.COM 					mpp->mr_fsize = pptr->p_filesz + off;
6668598SRod.Evans@Sun.COM 					mpp->mr_prot = perm;
6678598SRod.Evans@Sun.COM 
6688598SRod.Evans@Sun.COM 					mpp++, mapnum++;
6691824Srie 				}
6708598SRod.Evans@Sun.COM 
6710Sstevel@tonic-gate 				pptr = (Phdr *)((ulong_t)pptr + phsize);
6720Sstevel@tonic-gate 			}
6730Sstevel@tonic-gate 
6748598SRod.Evans@Sun.COM 			mpp--;
6758598SRod.Evans@Sun.COM 			msize = (size_t)(mpp->mr_addr + mpp->mr_msize) -
6768598SRod.Evans@Sun.COM 			    S_ALIGN((size_t)fmpp->mr_addr, syspagsz);
6770Sstevel@tonic-gate 
6788598SRod.Evans@Sun.COM 			if ((fdm.fd_nname =
6798598SRod.Evans@Sun.COM 			    stravl_insert(execname, 0, 0, 0)) == NULL)
6800Sstevel@tonic-gate 				return (0);
681*12877SRod.Evans@Sun.COM 			if ((mlmp = elf_new_lmp(&lml_main, ALIST_OFF_DATA,
682*12877SRod.Evans@Sun.COM 			    &fdm, (Addr)hmpp->mr_addr, msize,
683*12877SRod.Evans@Sun.COM 			    NULL, NULL, NULL)) == NULL)
6842145Srie 				return (0);
6852145Srie 
6868598SRod.Evans@Sun.COM 			MMAPS(mlmp) = fmpp;
6878598SRod.Evans@Sun.COM 			MMAPCNT(mlmp) = mapnum;
6888598SRod.Evans@Sun.COM 			PADSTART(mlmp) = (ulong_t)fmpp->mr_addr;
6898598SRod.Evans@Sun.COM 			PADIMLEN(mlmp) = (ulong_t)fmpp->mr_addr +
6908598SRod.Evans@Sun.COM 			    (ulong_t)mpp->mr_addr + (ulong_t)mpp->mr_msize;
6910Sstevel@tonic-gate 		}
6920Sstevel@tonic-gate 	}
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	/*
6956Srie 	 * Establish the interpretors name as that defined within the initial
6966Srie 	 * object (executable).  This provides for ORIGIN processing of ld.so.1
6978598SRod.Evans@Sun.COM 	 * dependencies.  Note, the NAME() of the object remains that which was
6988598SRod.Evans@Sun.COM 	 * passed to us as the SONAME on execution.
6990Sstevel@tonic-gate 	 */
7006Srie 	if (ldsoexec == 0) {
7016Srie 		size_t	len = strlen(interp->i_name);
7026Srie 
7038598SRod.Evans@Sun.COM 		if (expand(&interp->i_name, &len, 0, 0,
70411827SRod.Evans@Sun.COM 		    (PD_TKN_ISALIST | PD_TKN_CAP), rlmp) & PD_TKN_RESOLVED)
7058598SRod.Evans@Sun.COM 			fdr.fd_flags |= FLG_FD_RESOLVED;
7068598SRod.Evans@Sun.COM 	}
7078598SRod.Evans@Sun.COM 	fdr.fd_pname = interp->i_name;
7088598SRod.Evans@Sun.COM 	(void) fullpath(rlmp, &fdr);
7098598SRod.Evans@Sun.COM 
7108598SRod.Evans@Sun.COM 	/*
7118598SRod.Evans@Sun.COM 	 * The runtime linker acts as a filtee for various dl*() functions that
7128598SRod.Evans@Sun.COM 	 * are defined in libc (and libdl).  Make sure this standard name for
7138598SRod.Evans@Sun.COM 	 * the runtime linker is also registered in the FullPathNode AVL tree.
7148598SRod.Evans@Sun.COM 	 */
7158598SRod.Evans@Sun.COM 	(void) fpavl_insert(&lml_rtld, rlmp, _rtldname, 0);
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 	/*
7186Srie 	 * Having established the true runtime linkers name, simplify the name
7196Srie 	 * for error diagnostics.
7200Sstevel@tonic-gate 	 */
7218598SRod.Evans@Sun.COM 	if ((str = strrchr(PATHNAME(rlmp), '/')) != NULL)
7226Srie 		rtldname = ++str;
7236Srie 	else
7246Srie 		rtldname = PATHNAME(rlmp);
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 	/*
7276Srie 	 * Expand the fullpath name of the application.  This typically occurs
7286Srie 	 * as a part of loading an object, but as the kernel probably mapped
7296Srie 	 * it in, complete this processing now.
7300Sstevel@tonic-gate 	 */
7318598SRod.Evans@Sun.COM 	(void) fullpath(mlmp, 0);
7320Sstevel@tonic-gate 
7336Srie 	/*
7346Srie 	 * Some troublesome programs will change the value of argv[0].  Dupping
7356Srie 	 * the process string protects us, and insures the string is left in
7366Srie 	 * any core files.
7376Srie 	 */
7388598SRod.Evans@Sun.COM 	if ((str = (char *)strdup(procname)) == NULL)
7396Srie 		return (0);
7406Srie 	procname = str;
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate 	FLAGS(mlmp) |= (FLG_RT_ISMAIN | FLG_RT_MODESET);
7430Sstevel@tonic-gate 	FLAGS1(mlmp) |= FL1_RT_USED;
744280Srie 
745280Srie 	/*
746280Srie 	 * It's the responsibility of MAIN(crt0) to call it's _init and _fini
747280Srie 	 * section, therefore null out any INIT/FINI so that this object isn't
748280Srie 	 * collected during tsort processing.  And, if the application has no
749280Srie 	 * initarray or finiarray we can economize on establishing bindings.
750280Srie 	 */
7518598SRod.Evans@Sun.COM 	INIT(mlmp) = FINI(mlmp) = NULL;
7528598SRod.Evans@Sun.COM 	if ((INITARRAY(mlmp) == NULL) && (FINIARRAY(mlmp) == NULL))
7530Sstevel@tonic-gate 		FLAGS1(mlmp) |= FL1_RT_NOINIFIN;
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate 	/*
7560Sstevel@tonic-gate 	 * Identify lddstub if necessary.
7570Sstevel@tonic-gate 	 */
7580Sstevel@tonic-gate 	if (lml_main.lm_flags & LML_FLG_TRC_LDDSTUB)
7590Sstevel@tonic-gate 		FLAGS1(mlmp) |= FL1_RT_LDDSTUB;
7600Sstevel@tonic-gate 
7616Srie 	/*
7626Srie 	 * Retain our argument information for use in dlinfo.
7636Srie 	 */
7646Srie 	argsinfo.dla_argv = argv--;
7656Srie 	argsinfo.dla_argc = (long)*argv;
7666Srie 	argsinfo.dla_envp = envp;
7676Srie 	argsinfo.dla_auxv = auxv;
7686Srie 
7696515Sraf 	(void) enter(0);
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate 	/*
7720Sstevel@tonic-gate 	 * Add our two main link-maps to the dynlm_list
7730Sstevel@tonic-gate 	 */
7749131SRod.Evans@Sun.COM 	if (aplist_append(&dynlm_list, &lml_main, AL_CNT_DYNLIST) == NULL)
7750Sstevel@tonic-gate 		return (0);
7760Sstevel@tonic-gate 
7779131SRod.Evans@Sun.COM 	if (aplist_append(&dynlm_list, &lml_rtld, AL_CNT_DYNLIST) == NULL)
7780Sstevel@tonic-gate 		return (0);
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	/*
7810Sstevel@tonic-gate 	 * Reset the link-map counts for both lists.  The init count is used to
7820Sstevel@tonic-gate 	 * track how many objects have pending init sections, this gets incre-
7830Sstevel@tonic-gate 	 * mented each time an object is relocated.  Since ld.so.1 relocates
7840Sstevel@tonic-gate 	 * itself, it's init count will remain zero.
7850Sstevel@tonic-gate 	 * The object count is used to track how many objects have pending fini
7860Sstevel@tonic-gate 	 * sections, as ld.so.1 handles its own fini we can zero its count.
7870Sstevel@tonic-gate 	 */
7880Sstevel@tonic-gate 	lml_main.lm_obj = 1;
7890Sstevel@tonic-gate 	lml_rtld.lm_obj = 0;
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 	/*
7920Sstevel@tonic-gate 	 * Initialize debugger information structure.  Some parts of this
7930Sstevel@tonic-gate 	 * structure were initialized statically.
7940Sstevel@tonic-gate 	 */
7950Sstevel@tonic-gate 	r_debug.rtd_rdebug.r_map = (Link_map *)lml_main.lm_head;
7960Sstevel@tonic-gate 	r_debug.rtd_rdebug.r_ldsomap = (Link_map *)lml_rtld.lm_head;
7970Sstevel@tonic-gate 	r_debug.rtd_rdebug.r_ldbase = r_debug.rtd_rdebug.r_ldsomap->l_addr;
7980Sstevel@tonic-gate 	r_debug.rtd_dynlmlst = &dynlm_list;
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate 	/*
8010Sstevel@tonic-gate 	 * Determine the dev/inode information for the executable to complete
8020Sstevel@tonic-gate 	 * load_so() checking for those who might dlopen(a.out).
8030Sstevel@tonic-gate 	 */
8048598SRod.Evans@Sun.COM 	if (rtld_stat(PATHNAME(mlmp), &status) == 0) {
8050Sstevel@tonic-gate 		STDEV(mlmp) = status.st_dev;
8060Sstevel@tonic-gate 		STINO(mlmp) = status.st_ino;
8070Sstevel@tonic-gate 	}
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 	/*
8100Sstevel@tonic-gate 	 * Initialize any configuration information.
8110Sstevel@tonic-gate 	 */
8120Sstevel@tonic-gate 	if (!(rtld_flags & RT_FL_NOCFG)) {
8130Sstevel@tonic-gate 		if ((features = elf_config(mlmp, (aoutdyn != 0))) == -1)
8140Sstevel@tonic-gate 			return (0);
81512650SRod.Evans@Sun.COM 	}
81611827SRod.Evans@Sun.COM 
81712650SRod.Evans@Sun.COM #if	defined(_ELF64)
81812650SRod.Evans@Sun.COM 	/*
81912650SRod.Evans@Sun.COM 	 * If this is a 64-bit process, determine whether this process has
82012650SRod.Evans@Sun.COM 	 * restricted the process address space to 32-bits.  Any dependencies
82112650SRod.Evans@Sun.COM 	 * that are restricted to a 32-bit address space can only be loaded if
82212650SRod.Evans@Sun.COM 	 * the executable has established this requirement.
82312650SRod.Evans@Sun.COM 	 */
82412650SRod.Evans@Sun.COM 	if (CAPSET(mlmp).sc_sf_1 & SF1_SUNW_ADDR32)
82512650SRod.Evans@Sun.COM 		rtld_flags2 |= RT_FL2_ADDR32;
82612650SRod.Evans@Sun.COM #endif
82712650SRod.Evans@Sun.COM 	/*
82812650SRod.Evans@Sun.COM 	 * Establish any alternative capabilities, and validate this object
82912650SRod.Evans@Sun.COM 	 * if it defines it's own capabilities information.
83012650SRod.Evans@Sun.COM 	 */
83112650SRod.Evans@Sun.COM 	if (cap_alternative() == 0)
83212650SRod.Evans@Sun.COM 		return (0);
83312650SRod.Evans@Sun.COM 
83412650SRod.Evans@Sun.COM 	if (cap_check_lmp(mlmp, &rej) == 0) {
83512650SRod.Evans@Sun.COM 		if (lml_main.lm_flags & LML_FLG_TRC_ENABLE) {
83612650SRod.Evans@Sun.COM 			/* LINTED */
83712650SRod.Evans@Sun.COM 			(void) printf(MSG_INTL(ldd_warn[rej.rej_type]),
83812650SRod.Evans@Sun.COM 			    NAME(mlmp), rej.rej_str);
83912650SRod.Evans@Sun.COM 		} else {
84012650SRod.Evans@Sun.COM 			/* LINTED */
84112650SRod.Evans@Sun.COM 			eprintf(&lml_main, ERR_FATAL,
84212650SRod.Evans@Sun.COM 			    MSG_INTL(err_reject[rej.rej_type]),
84312650SRod.Evans@Sun.COM 			    NAME(mlmp), rej.rej_str);
84411827SRod.Evans@Sun.COM 			return (0);
84512650SRod.Evans@Sun.COM 		}
8460Sstevel@tonic-gate 	}
8470Sstevel@tonic-gate 
8480Sstevel@tonic-gate 	/*
8490Sstevel@tonic-gate 	 * Establish the modes of the initial object.  These modes are
8500Sstevel@tonic-gate 	 * propagated to any preloaded objects and explicit shared library
8515950Srie 	 * dependencies.
8525950Srie 	 *
8535950Srie 	 * If we're generating a configuration file using crle(1), remove
8545950Srie 	 * any RTLD_NOW use, as we don't want to trigger any relocation proc-
8555950Srie 	 * essing during crle(1)'s first past (this would just be unnecessary
8565950Srie 	 * overhead).  Any filters are explicitly loaded, and thus RTLD_NOW is
8575950Srie 	 * not required to trigger filter loading.
8585950Srie 	 *
8595950Srie 	 * Note, RTLD_NOW may have been established during analysis of the
8605950Srie 	 * application had the application been built -z now.
8610Sstevel@tonic-gate 	 */
8620Sstevel@tonic-gate 	MODE(mlmp) |= (RTLD_NODELETE | RTLD_GLOBAL | RTLD_WORLD);
8635950Srie 
8645950Srie 	if (rtld_flags & RT_FL_CONFGEN) {
8650Sstevel@tonic-gate 		MODE(mlmp) |= RTLD_CONFGEN;
8665950Srie 		MODE(mlmp) &= ~RTLD_NOW;
8675950Srie 		rtld_flags2 &= ~RT_FL2_BINDNOW;
8685950Srie 	}
8695950Srie 
8706Srie 	if ((MODE(mlmp) & RTLD_NOW) == 0) {
8716Srie 		if (rtld_flags2 & RT_FL2_BINDNOW)
8726Srie 			MODE(mlmp) |= RTLD_NOW;
8736Srie 		else
8746Srie 			MODE(mlmp) |= RTLD_LAZY;
8756Srie 	}
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate 	/*
8780Sstevel@tonic-gate 	 * If debugging was requested initialize things now that any cache has
8791618Srie 	 * been established.  A user can specify LD_DEBUG=help to discover the
8801618Srie 	 * list of debugging tokens available without running the application.
8811618Srie 	 * However, don't allow this setting from a configuration file.
8821618Srie 	 *
8831618Srie 	 * Note, to prevent recursion issues caused by loading and binding the
8841618Srie 	 * debugging libraries themselves, a local debugging descriptor is
8851618Srie 	 * initialized.  Once the debugging setup has completed, this local
8861618Srie 	 * descriptor is copied to the global descriptor which effectively
8871618Srie 	 * enables diagnostic output.
8889340SRod.Evans@Sun.COM 	 *
8899340SRod.Evans@Sun.COM 	 * Ignore any debugging request if we're being monitored by a process
8909340SRod.Evans@Sun.COM 	 * that expects the old getpid() initialization handshake.
8910Sstevel@tonic-gate 	 */
8929340SRod.Evans@Sun.COM 	if ((rpl_debug || prm_debug) && ((rtld_flags & RT_FL_DEBUGGER) == 0)) {
8939577SRod.Evans@Sun.COM 		Dbg_desc	_dbg_desc = {0};
8949577SRod.Evans@Sun.COM 		struct timeval	total = DBG_TOTALTIME;
8959577SRod.Evans@Sun.COM 		struct timeval	delta = DBG_DELTATIME;
8961618Srie 
8971618Srie 		if (rpl_debug) {
8989406SAli.Bahrami@Sun.COM 			if (dbg_setup(rpl_debug, &_dbg_desc) == 0)
8991618Srie 				return (0);
9009406SAli.Bahrami@Sun.COM 			if (_dbg_desc.d_extra & DBG_E_HELP_EXIT)
9011618Srie 				rtldexit(&lml_main, 0);
9021618Srie 		}
9031618Srie 		if (prm_debug)
9041618Srie 			(void) dbg_setup(prm_debug, &_dbg_desc);
9051618Srie 
9061618Srie 		*dbg_desc = _dbg_desc;
9079577SRod.Evans@Sun.COM 		DBG_TOTALTIME = total;
9089577SRod.Evans@Sun.COM 		DBG_DELTATIME = delta;
9091618Srie 	}
9100Sstevel@tonic-gate 
9110Sstevel@tonic-gate 	/*
9120Sstevel@tonic-gate 	 * Now that debugging is enabled generate any diagnostics from any
9130Sstevel@tonic-gate 	 * previous events.
9140Sstevel@tonic-gate 	 */
91511827SRod.Evans@Sun.COM 	if (DBG_ENABLED) {
91611827SRod.Evans@Sun.COM 		DBG_CALL(Dbg_cap_val(&lml_main, org_scapset, alt_scapset,
91711827SRod.Evans@Sun.COM 		    M_MACH));
9181618Srie 		DBG_CALL(Dbg_file_config_dis(&lml_main, config->c_name,
9191618Srie 		    features));
9200Sstevel@tonic-gate 
9211618Srie 		DBG_CALL(Dbg_file_ldso(rlmp, envp, auxv,
9225892Sab196087 		    LIST(rlmp)->lm_lmidstr, ALIST_OFF_DATA));
9230Sstevel@tonic-gate 
9248598SRod.Evans@Sun.COM 		if (THIS_IS_ELF(mlmp)) {
9251618Srie 			DBG_CALL(Dbg_file_elf(&lml_main, PATHNAME(mlmp),
9268598SRod.Evans@Sun.COM 			    ADDR(mlmp), MSIZE(mlmp), LIST(mlmp)->lm_lmidstr,
9275892Sab196087 			    ALIST_OFF_DATA));
9280Sstevel@tonic-gate 		} else {
9291618Srie 			DBG_CALL(Dbg_file_aout(&lml_main, PATHNAME(mlmp),
9308598SRod.Evans@Sun.COM 			    ADDR(mlmp), MSIZE(mlmp), LIST(mlmp)->lm_lmidstr,
9315892Sab196087 			    ALIST_OFF_DATA));
9320Sstevel@tonic-gate 		}
9330Sstevel@tonic-gate 	}
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	/*
9360Sstevel@tonic-gate 	 * Enable auditing.
9370Sstevel@tonic-gate 	 */
9380Sstevel@tonic-gate 	if (rpl_audit || prm_audit || profile_lib) {
9390Sstevel@tonic-gate 		int		ndx;
9400Sstevel@tonic-gate 		const char	*aud[3];
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate 		aud[0] = rpl_audit;
9430Sstevel@tonic-gate 		aud[1] = prm_audit;
9440Sstevel@tonic-gate 		aud[2] = profile_lib;
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate 		/*
9470Sstevel@tonic-gate 		 * Any global auditing (set using LD_AUDIT or LD_PROFILE) that
9480Sstevel@tonic-gate 		 * can't be established is non-fatal.
9490Sstevel@tonic-gate 		 */
9508598SRod.Evans@Sun.COM 		if ((auditors = calloc(1, sizeof (Audit_desc))) == NULL)
9510Sstevel@tonic-gate 			return (0);
9520Sstevel@tonic-gate 
9530Sstevel@tonic-gate 		for (ndx = 0; ndx < 3; ndx++) {
9540Sstevel@tonic-gate 			if (aud[ndx]) {
9558598SRod.Evans@Sun.COM 				if ((auditors->ad_name =
9568598SRod.Evans@Sun.COM 				    strdup(aud[ndx])) == NULL)
9570Sstevel@tonic-gate 					return (0);
9580Sstevel@tonic-gate 				rtld_flags2 |= RT_FL2_FTL2WARN;
95999Srie 				(void) audit_setup(mlmp, auditors,
9608598SRod.Evans@Sun.COM 				    PD_FLG_EXTLOAD, NULL);
9610Sstevel@tonic-gate 				rtld_flags2 &= ~RT_FL2_FTL2WARN;
9620Sstevel@tonic-gate 			}
9630Sstevel@tonic-gate 		}
9640Sstevel@tonic-gate 		lml_main.lm_tflags |= auditors->ad_flags;
9650Sstevel@tonic-gate 	}
9660Sstevel@tonic-gate 	if (AUDITORS(mlmp)) {
9670Sstevel@tonic-gate 		/*
9680Sstevel@tonic-gate 		 * Any object required auditing (set with a DT_DEPAUDIT dynamic
9690Sstevel@tonic-gate 		 * entry) that can't be established is fatal.
9700Sstevel@tonic-gate 		 */
9714679Srie 		if (FLAGS1(mlmp) & FL1_RT_GLOBAUD) {
9724679Srie 			/*
9734679Srie 			 * If this object requires global auditing, use the
9744679Srie 			 * local auditing information to set the global
9754679Srie 			 * auditing descriptor.  The effect is that a
9764679Srie 			 * DT_DEPAUDIT act as an LD_AUDIT.
9774679Srie 			 */
9788598SRod.Evans@Sun.COM 			if ((auditors == NULL) && ((auditors = calloc(1,
9798598SRod.Evans@Sun.COM 			    sizeof (Audit_desc))) == NULL))
9804679Srie 				return (0);
9814679Srie 
9824679Srie 			auditors->ad_name = AUDITORS(mlmp)->ad_name;
9836387Srie 			if (audit_setup(mlmp, auditors, 0, NULL) == 0)
9844679Srie 				return (0);
9854679Srie 			lml_main.lm_tflags |= auditors->ad_flags;
9860Sstevel@tonic-gate 
9874679Srie 			/*
9884679Srie 			 * Clear the local auditor information.
9894679Srie 			 */
9904679Srie 			free((void *) AUDITORS(mlmp));
9918598SRod.Evans@Sun.COM 			AUDITORS(mlmp) = NULL;
9924679Srie 
9934679Srie 		} else {
9944679Srie 			/*
9954679Srie 			 * Establish any local auditing.
9964679Srie 			 */
9976387Srie 			if (audit_setup(mlmp, AUDITORS(mlmp), 0, NULL) == 0)
9984679Srie 				return (0);
9994679Srie 
10008598SRod.Evans@Sun.COM 			AFLAGS(mlmp) |= AUDITORS(mlmp)->ad_flags;
10014679Srie 			lml_main.lm_flags |= LML_FLG_LOCAUDIT;
10024679Srie 		}
10030Sstevel@tonic-gate 	}
10040Sstevel@tonic-gate 
10050Sstevel@tonic-gate 	/*
10060Sstevel@tonic-gate 	 * Explicitly add the initial object and ld.so.1 to those objects being
10070Sstevel@tonic-gate 	 * audited.  Note, although the ld.so.1 link-map isn't auditable,
10080Sstevel@tonic-gate 	 * establish a cookie for ld.so.1 as this may be bound to via the
10090Sstevel@tonic-gate 	 * dl*() family.
10100Sstevel@tonic-gate 	 */
10118598SRod.Evans@Sun.COM 	if ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_MASK) {
10120Sstevel@tonic-gate 		if (((audit_objopen(mlmp, mlmp) == 0) ||
10130Sstevel@tonic-gate 		    (audit_objopen(mlmp, rlmp) == 0)) &&
10148598SRod.Evans@Sun.COM 		    (AFLAGS(mlmp) & LML_TFLG_AUD_MASK))
10150Sstevel@tonic-gate 			return (0);
10160Sstevel@tonic-gate 	}
10170Sstevel@tonic-gate 
10180Sstevel@tonic-gate 	/*
10199340SRod.Evans@Sun.COM 	 * Map in any preloadable shared objects.  Establish the caller as the
10209340SRod.Evans@Sun.COM 	 * head of the main link-map list.  In the case of being exercised from
10219340SRod.Evans@Sun.COM 	 * lddstub, the caller gets reassigned to the first target shared object
10229340SRod.Evans@Sun.COM 	 * so as to provide intuitive diagnostics from ldd().
10239340SRod.Evans@Sun.COM 	 *
10249340SRod.Evans@Sun.COM 	 * Note, it is valid to preload a 4.x shared object with a 5.0
10259340SRod.Evans@Sun.COM 	 * executable (or visa-versa), as this functionality is required by
10269340SRod.Evans@Sun.COM 	 * ldd(1).
10270Sstevel@tonic-gate 	 */
10289340SRod.Evans@Sun.COM 	clmp = mlmp;
10299340SRod.Evans@Sun.COM 	if (rpl_preload && (preload(rpl_preload, mlmp, &clmp) == 0))
10300Sstevel@tonic-gate 		return (0);
10319340SRod.Evans@Sun.COM 	if (prm_preload && (preload(prm_preload, mlmp, &clmp) == 0))
10320Sstevel@tonic-gate 		return (0);
10330Sstevel@tonic-gate 
10340Sstevel@tonic-gate 	/*
10350Sstevel@tonic-gate 	 * Load all dependent (needed) objects.
10360Sstevel@tonic-gate 	 */
1037*12877SRod.Evans@Sun.COM 	if (analyze_lmc(&lml_main, ALIST_OFF_DATA, mlmp, mlmp, NULL) == NULL)
10380Sstevel@tonic-gate 		return (0);
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 	/*
10410Sstevel@tonic-gate 	 * Relocate all the dependencies we've just added.
10420Sstevel@tonic-gate 	 *
10430Sstevel@tonic-gate 	 * If this process has been established via crle(1), the environment
10440Sstevel@tonic-gate 	 * variable LD_CONFGEN will have been set.  crle(1) may create this
10450Sstevel@tonic-gate 	 * process twice.  The first time crle only needs to gather dependency
10460Sstevel@tonic-gate 	 * information.  The second time, is to dldump() the images.
10470Sstevel@tonic-gate 	 *
10480Sstevel@tonic-gate 	 * If we're only gathering dependencies, relocation is unnecessary.
10490Sstevel@tonic-gate 	 * As crle(1) may be building an arbitrary family of objects, they may
10500Sstevel@tonic-gate 	 * not fully relocate either.  Hence the relocation phase is not carried
10510Sstevel@tonic-gate 	 * out now, but will be called by crle(1) once all objects have been
10520Sstevel@tonic-gate 	 * loaded.
10530Sstevel@tonic-gate 	 */
10540Sstevel@tonic-gate 	if ((rtld_flags & RT_FL_CONFGEN) == 0) {
10550Sstevel@tonic-gate 
10561618Srie 		DBG_CALL(Dbg_util_nl(&lml_main, DBG_NL_STD));
10570Sstevel@tonic-gate 
10586387Srie 		if (relocate_lmc(&lml_main, ALIST_OFF_DATA, mlmp,
10596387Srie 		    mlmp, NULL) == 0)
10600Sstevel@tonic-gate 			return (0);
10610Sstevel@tonic-gate 
10620Sstevel@tonic-gate 		/*
10639340SRod.Evans@Sun.COM 		 * Inform the debuggers that basic process initialization is
10649340SRod.Evans@Sun.COM 		 * complete, and that the state of ld.so.1 (link-map lists,
10659340SRod.Evans@Sun.COM 		 * etc.) is stable.  This handshake enables the debugger to
10669340SRod.Evans@Sun.COM 		 * initialize themselves, and consequently allows the user to
10679340SRod.Evans@Sun.COM 		 * set break points in .init code.
10689340SRod.Evans@Sun.COM 		 *
10699340SRod.Evans@Sun.COM 		 * Most new debuggers use librtld_db to monitor activity events.
10709340SRod.Evans@Sun.COM 		 * Older debuggers indicated their presence by setting the
10719340SRod.Evans@Sun.COM 		 * DT_DEBUG entry in the dynamic executable (see elf_new_lm()).
10729340SRod.Evans@Sun.COM 		 * In this case, getpid() is called so that the debugger can
10739340SRod.Evans@Sun.COM 		 * catch the system call.  This old mechanism has some
10749340SRod.Evans@Sun.COM 		 * restrictions, as getpid() should not be called prior to
10759340SRod.Evans@Sun.COM 		 * basic process initialization being completed.  This
10769340SRod.Evans@Sun.COM 		 * restriction has become increasingly difficult to maintain,
10779340SRod.Evans@Sun.COM 		 * as the use of auditors, LD_DEBUG, and the initialization
10789340SRod.Evans@Sun.COM 		 * handshake with libc can result in "premature" getpid()
10799340SRod.Evans@Sun.COM 		 * calls.  The use of this getpid() handshake is expected to
10809340SRod.Evans@Sun.COM 		 * disappear at some point in the future, and there is intent
10819340SRod.Evans@Sun.COM 		 * to work towards that goal.
10820Sstevel@tonic-gate 		 */
10832454Srie 		rd_event(&lml_main, RD_DLACTIVITY, RT_CONSISTENT);
10840Sstevel@tonic-gate 		rd_event(&lml_rtld, RD_DLACTIVITY, RT_CONSISTENT);
10850Sstevel@tonic-gate 
10860Sstevel@tonic-gate 		if (rtld_flags & RT_FL_DEBUGGER) {
10870Sstevel@tonic-gate 			r_debug.rtd_rdebug.r_flags |= RD_FL_ODBG;
10880Sstevel@tonic-gate 			(void) getpid();
10890Sstevel@tonic-gate 		}
10900Sstevel@tonic-gate 	}
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate 	/*
10931824Srie 	 * Indicate preinit activity, and call any auditing routines.  These
10941824Srie 	 * routines are called before initializing any threads via libc, or
10951824Srie 	 * before collecting the complete set of .inits on the primary link-map.
10961824Srie 	 * Although most libc interfaces are encapsulated in local routines
10971824Srie 	 * within libc, they have been known to escape (ie. call a .plt).  As
10981824Srie 	 * the appcert auditor uses preinit as a trigger to establish some
10991824Srie 	 * external interfaces to the main link-maps libc, we need to activate
11001824Srie 	 * this trigger before exercising any code within libc.  Additionally,
11011824Srie 	 * I wouldn't put it past an auditor to add additional objects to the
11021824Srie 	 * primary link-map.  Hence, we collect .inits after the audit call.
11030Sstevel@tonic-gate 	 */
11040Sstevel@tonic-gate 	rd_event(&lml_main, RD_PREINIT, 0);
11050Sstevel@tonic-gate 
1106*12877SRod.Evans@Sun.COM 	if (aud_activity ||
1107*12877SRod.Evans@Sun.COM 	    ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_ACTIVITY))
11080Sstevel@tonic-gate 		audit_activity(mlmp, LA_ACT_CONSISTENT);
1109*12877SRod.Evans@Sun.COM 	if (aud_preinit ||
1110*12877SRod.Evans@Sun.COM 	    ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_PREINIT))
11110Sstevel@tonic-gate 		audit_preinit(mlmp);
11120Sstevel@tonic-gate 
11131824Srie 	/*
11141824Srie 	 * If we're creating initial configuration information, we're done
11151824Srie 	 * now that the auditing step has been called.
11161824Srie 	 */
11171824Srie 	if (rtld_flags & RT_FL_CONFGEN) {
11186515Sraf 		leave(LIST(mlmp), 0);
11191824Srie 		return (mlmp);
11201824Srie 	}
11211824Srie 
11221824Srie 	/*
11231824Srie 	 * Sort the .init sections of all objects we've added.  If we're
11241824Srie 	 * tracing we only need to execute this under ldd(1) with the -i or -u
11251824Srie 	 * options.
11261824Srie 	 */
11271824Srie 	lmflags = lml_main.lm_flags;
11281824Srie 	if (((lmflags & LML_FLG_TRC_ENABLE) == 0) ||
11291824Srie 	    (lmflags & (LML_FLG_TRC_INIT | LML_FLG_TRC_UNREF))) {
11301824Srie 		if ((tobj = tsort(mlmp, LIST(mlmp)->lm_init,
11311824Srie 		    RT_SORT_REV)) == (Rt_map **)S_ERROR)
11321824Srie 			return (0);
11331824Srie 	}
11341824Srie 
11351824Srie 	/*
11361824Srie 	 * If we are tracing we're done.  This is the one legitimate use of a
11371824Srie 	 * direct call to rtldexit() rather than return, as we don't want to
11381824Srie 	 * return and jump to the application.
11391824Srie 	 */
11401824Srie 	if (lmflags & LML_FLG_TRC_ENABLE) {
11411824Srie 		unused(&lml_main);
11421824Srie 		rtldexit(&lml_main, 0);
11431824Srie 	}
11441824Srie 
11456229Sedp 	/*
11466229Sedp 	 * Check if this instance of the linker should have a primary link
11476229Sedp 	 * map.  This flag allows multiple copies of the -same- -version-
11486229Sedp 	 * of the linker (and libc) to run in the same address space.
11496229Sedp 	 *
11506229Sedp 	 * Without this flag we only support one copy of the linker in a
11516229Sedp 	 * process because by default the linker will always try to
11526229Sedp 	 * initialize at one primary link map  The copy of libc which is
115311827SRod.Evans@Sun.COM 	 * initialized on a primary link map will initialize global TLS
11546229Sedp 	 * data which can be shared with other copies of libc in the
11556229Sedp 	 * process.  The problem is that if there is more than one copy
11566229Sedp 	 * of the linker, only one copy should link libc onto a primary
11576229Sedp 	 * link map, otherwise libc will attempt to re-initialize global
11586229Sedp 	 * TLS data.  So when a copy of the linker is loaded with this
11596229Sedp 	 * flag set, it will not initialize any primary link maps since
116011827SRod.Evans@Sun.COM 	 * presumably another copy of the linker will do this.
11616229Sedp 	 *
11626229Sedp 	 * Note that this flag only allows multiple copies of the -same-
11636229Sedp 	 * -version- of the linker (and libc) to coexist.  This approach
11646229Sedp 	 * will not work if we are trying to load different versions of
11656229Sedp 	 * the linker and libc into the same process.  The reason for
11666229Sedp 	 * this is that the format of the global TLS data may not be
11676229Sedp 	 * the same for different versions of libc.  In this case each
11686229Sedp 	 * different version of libc must have it's own primary link map
11696229Sedp 	 * and be able to maintain it's own TLS data.  The only way this
11706229Sedp 	 * can be done is by carefully managing TLS pointers on transitions
11716229Sedp 	 * between code associated with each of the different linkers.
11726229Sedp 	 * Note that this is actually what is done for processes in lx
11736229Sedp 	 * branded zones.  Although in the lx branded zone case, the
11746229Sedp 	 * other linker and libc are actually gld and glibc.  But the
11756229Sedp 	 * same general TLS management mechanism used by the lx brand
11766229Sedp 	 * would apply to any attempts to run multiple versions of the
11776229Sedp 	 * solaris linker and libc in a single process.
11786229Sedp 	 */
11796229Sedp 	if (auxflags & AF_SUN_NOPLM)
11806229Sedp 		rtld_flags2 |= RT_FL2_NOPLM;
11818598SRod.Evans@Sun.COM 
11821824Srie 	/*
11831824Srie 	 * Establish any static TLS for this primary link-map.  Note, regardless
11841824Srie 	 * of whether TLS is available, an initial handshake occurs with libc to
11851824Srie 	 * indicate we're processing the primary link-map.  Having identified
11861824Srie 	 * the primary link-map, initialize threads.
11871824Srie 	 */
11881824Srie 	if (rt_get_extern(&lml_main, mlmp) == 0)
11891824Srie 		return (0);
11901824Srie 
11916229Sedp 	if ((rtld_flags2 & RT_FL2_NOPLM) == 0) {
11926229Sedp 		if (tls_statmod(&lml_main, mlmp) == 0)
11936229Sedp 			return (0);
11946229Sedp 		rt_thr_init(&lml_main);
11956229Sedp 		rtld_flags2 |= RT_FL2_PLMSETUP;
11966229Sedp 	} else {
11976229Sedp 		rt_thr_init(&lml_main);
11986229Sedp 	}
11991824Srie 
12001824Srie 	/*
12011824Srie 	 * Fire all dependencies .init sections.  Identify any unused
12021824Srie 	 * dependencies, and leave the runtime linker - effectively calling
12031824Srie 	 * the dynamic executables entry point.
12041824Srie 	 */
12050Sstevel@tonic-gate 	call_array(PREINITARRAY(mlmp), (uint_t)PREINITARRAYSZ(mlmp), mlmp,
12064679Srie 	    SHT_PREINIT_ARRAY);
12070Sstevel@tonic-gate 
12080Sstevel@tonic-gate 	if (tobj)
12090Sstevel@tonic-gate 		call_init(tobj, DBG_INIT_SORT);
12100Sstevel@tonic-gate 
12110Sstevel@tonic-gate 	rd_event(&lml_main, RD_POSTINIT, 0);
12120Sstevel@tonic-gate 
12130Sstevel@tonic-gate 	unused(&lml_main);
12140Sstevel@tonic-gate 
12151618Srie 	DBG_CALL(Dbg_util_call_main(mlmp));
12160Sstevel@tonic-gate 
1217*12877SRod.Evans@Sun.COM 	rtld_flags |= (RT_FL_OPERATION | RT_FL_APPLIC);
1218*12877SRod.Evans@Sun.COM 
12196515Sraf 	leave(LIST(mlmp), 0);
12200Sstevel@tonic-gate 
12210Sstevel@tonic-gate 	return (mlmp);
12220Sstevel@tonic-gate }
1223