_setup.c revision 4321:a8930ec16e52
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 (c) 1988 AT&T
24 *	  All Rights Reserved
25 *
26 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
27 * Use is subject to license terms.
28 */
29#pragma ident	"%Z%%M%	%I%	%E% SMI"
30
31/*
32 * SPARC specific setup routine  -  relocate ld.so's symbols, setup its
33 * environment, map in loadable sections of the executable.
34 *
35 * Takes base address ld.so was loaded at, address of ld.so's dynamic
36 * structure, address of process environment pointers, address of auxiliary
37 * vector and * argv[0] (process name).
38 * If errors occur, send process signal - otherwise
39 * return executable's entry point to the bootstrap routine.
40 */
41#include	"_synonyms.h"
42
43#include	<signal.h>
44#include	<stdlib.h>
45#include	<fcntl.h>
46#include	<stdio.h>
47#include	<sys/auxv.h>
48#include	<sys/types.h>
49#include	<sys/stat.h>
50#include	<link.h>
51#include	<dlfcn.h>
52#include	"_rtld.h"
53#include	"_audit.h"
54#include	"msg.h"
55#ifdef A_OUT
56#include	"_a.out.h"
57#endif /* A_OUT */
58
59extern int	_end;
60extern int	_etext;
61extern void	_init(void);
62
63
64/* VARARGS */
65unsigned long
66_setup(Boot * ebp, Dyn * ld_dyn)
67{
68	unsigned long	reladdr, relacount, ld_base = 0;
69	unsigned long	relaent = 0;
70	unsigned long	strtab, soname, interp_base = 0;
71	char		*_rt_name, **_envp, **_argv;
72	int		_syspagsz = 0, fd = -1, dz_fd = FD_UNAVAIL;
73	uint_t		_flags = 0, hwcap_1 = 0;
74	Dyn *		dyn_ptr;
75	Phdr *		phdr = 0;
76	Rt_map *	lmp;
77	auxv_t		*auxv, *_auxv;
78	uid_t		uid = (uid_t)-1, euid = (uid_t)-1;
79	gid_t		gid = (gid_t)-1, egid = (gid_t)-1;
80	char		*_platform = 0, *_execname = 0;
81	int		auxflags = -1;
82#ifdef	A_OUT
83	void *		aoutdyn = 0;
84#endif	/* A_OUT */
85
86	/*
87	 * Scan the bootstrap structure to pick up the basics.
88	 */
89	for (; ebp->eb_tag != EB_NULL; ebp++)
90		switch (ebp->eb_tag) {
91		case EB_DYNAMIC:
92#ifdef A_OUT
93			aoutdyn = (struct link_dynamic *)ebp->eb_un.eb_val;
94#endif /* A_OUT */
95			break;
96		case EB_LDSO_BASE:
97			ld_base = (unsigned long)ebp->eb_un.eb_val;
98			break;
99		case EB_ARGV:
100			_argv = (char **)ebp->eb_un.eb_ptr;
101			break;
102		case EB_ENVP:
103			_envp = (char **)ebp->eb_un.eb_ptr;
104			break;
105		case EB_AUXV:
106			_auxv = (auxv_t *)ebp->eb_un.eb_ptr;
107			break;
108		case EB_DEVZERO:
109			dz_fd = (int)ebp->eb_un.eb_val;
110			break;
111		case EB_PAGESIZE:
112			_syspagsz = (int)ebp->eb_un.eb_val;
113			break;
114		}
115
116	/*
117	 * Search the aux. vector for the information passed by exec.
118	 */
119	for (auxv = _auxv; auxv->a_type != AT_NULL; auxv++) {
120		switch (auxv->a_type) {
121		case AT_EXECFD:
122			/* this is the old exec that passes a file descriptor */
123			fd = (int)auxv->a_un.a_val;
124			break;
125		case AT_FLAGS:
126			/* processor flags (MAU available, etc) */
127			_flags = auxv->a_un.a_val;
128			break;
129		case AT_PAGESZ:
130			/* system page size */
131			_syspagsz = (int)auxv->a_un.a_val;
132			break;
133		case AT_PHDR:
134			/* address of the segment table */
135			phdr = (Phdr *)auxv->a_un.a_ptr;
136			break;
137		case AT_BASE:
138			/* interpreter base address */
139			if (ld_base == 0)
140				ld_base = auxv->a_un.a_val;
141			interp_base = auxv->a_un.a_val;
142			break;
143		case AT_SUN_UID:
144			/* effective user id for the executable */
145			euid = (uid_t)auxv->a_un.a_val;
146			break;
147		case AT_SUN_RUID:
148			/* real user id for the executable */
149			uid = (uid_t)auxv->a_un.a_val;
150			break;
151		case AT_SUN_GID:
152			/* effective group id for the executable */
153			egid = (gid_t)auxv->a_un.a_val;
154			break;
155		case AT_SUN_RGID:
156			/* real group id for the executable */
157			gid = (gid_t)auxv->a_un.a_val;
158			break;
159#ifdef	AT_SUN_PLATFORM			/* Defined on SunOS 5.5 & greater. */
160		case AT_SUN_PLATFORM:
161			/* platform name */
162			_platform = auxv->a_un.a_ptr;
163			break;
164#endif
165#ifdef	AT_SUN_EXECNAME			/* Defined on SunOS 5.6 & greater. */
166		case AT_SUN_EXECNAME:
167			/* full pathname of execed object */
168			_execname = auxv->a_un.a_ptr;
169			break;
170#endif
171#ifdef	AT_SUN_AUXFLAGS			/* At the behest of PSARC 2002/188 */
172		case AT_SUN_AUXFLAGS:
173			auxflags = (int)auxv->a_un.a_val;
174			break;
175#endif
176#ifdef	AT_SUN_HWCAP			/* Hardware capabilities */
177		case AT_SUN_HWCAP:
178			hwcap_1 = (uint_t)auxv->a_un.a_val;
179			break;
180#endif
181		}
182	}
183
184	/*
185	 * Get needed info from ld.so's dynamic structure.
186	 */
187	/* LINTED */
188	dyn_ptr = (Dyn *)((char *)ld_dyn + ld_base);
189	for (ld_dyn = dyn_ptr; ld_dyn->d_tag != DT_NULL; ld_dyn++) {
190		switch (ld_dyn->d_tag) {
191		case DT_RELA:
192			reladdr = ld_dyn->d_un.d_ptr + ld_base;
193			break;
194		case DT_RELACOUNT:
195			relacount = ld_dyn->d_un.d_val;
196			break;
197		case DT_RELAENT:
198			relaent = ld_dyn->d_un.d_val;
199			break;
200		case DT_STRTAB:
201			strtab = ld_dyn->d_un.d_ptr + ld_base;
202			break;
203		case DT_SONAME:
204			soname = ld_dyn->d_un.d_val;
205			break;
206		}
207	}
208	_rt_name = (char *)strtab + soname;
209
210	/*
211	 * If we don't have a RELAENT, just assume
212	 * the size.
213	 */
214	if (relaent == 0)
215		relaent = sizeof (Rela);
216
217	/*
218	 * Because ld.so.1 is built with -Bsymbolic there should only be
219	 * RELATIVE and JMPSLOT relocations.  Process all relatives first.
220	 */
221	for (; relacount; relacount--) {
222		ulong_t	roffset;
223
224		roffset = ((Rela *)reladdr)->r_offset + ld_base;
225		*((ulong_t *)roffset) = ld_base +
226		    (long)(((Rela *)reladdr)->r_addend);
227		reladdr += relaent;
228	}
229
230	/*
231	 * Continue with generic startup processing.
232	 */
233	if ((lmp = setup((char **)_envp, (auxv_t *)_auxv, _flags, _platform,
234	    _syspagsz, _rt_name, dyn_ptr, ld_base, interp_base, fd, phdr,
235	    _execname, _argv, dz_fd, uid, euid, gid, egid,
236#ifdef	A_OUT
237	    aoutdyn, auxflags, hwcap_1)) == (Rt_map *)0) {
238#else
239	    NULL, auxflags, hwcap_1)) == NULL) {
240#endif	/* A_OUT */
241		rtldexit(&lml_main, 1);
242	}
243
244	return (LM_ENTRY_PT(lmp)());
245}
246