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