entry.c revision 1682:79d68fa5aedd
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 2006 Sun Microsystems, Inc.  All rights reserved.
27 * Use is subject to license terms.
28 */
29#pragma ident	"%Z%%M%	%I%	%E% SMI"
30
31#include	<stdio.h>
32#include	<memory.h>
33#include	<debug.h>
34#include	"msg.h"
35#include	"_libld.h"
36
37
38/*
39 * The loader uses a `segment descriptor' list to describe the output
40 * segments it can potentially create.   Additional segments may be added
41 * using a map file.
42 */
43#if	defined(_ELF64)
44/* Phdr packing changes under Elf64 */
45static Sg_desc sg_desc[LD_NUM] = {
46	{{PT_PHDR, PF_R + PF_X, 0, 0, 0, 0, 0, 0},
47		MSG_ORIG(MSG_ENT_PHDR), 0, 0, NULL, NULL,
48		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
49	{{PT_INTERP, PF_R, 0, 0, 0, 0, 0, 0},
50		MSG_ORIG(MSG_ENT_INTERP), 0, 0, NULL, NULL,
51		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
52	{{PT_SUNWCAP, PF_R, 0, 0, 0, 0, 0, 0},
53		MSG_ORIG(MSG_ENT_SUNWCAP), 0, 0, NULL, NULL,
54		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
55	{{PT_LOAD, PF_R + PF_X, 0, 0, 0, 0, 0, 0},
56		MSG_ORIG(MSG_ENT_TEXT), 0, 0, NULL, NULL,
57		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
58	{{PT_LOAD, M_DATASEG_PERM, 0, 0, 0, 0, 0, 0},
59		MSG_ORIG(MSG_ENT_DATA), 0, 0, NULL, NULL,
60		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
61	{{PT_LOAD, M_DATASEG_PERM, 0, 0, 0, 0, 0, 0},
62		MSG_ORIG(MSG_ENT_BSS), 0, 0, NULL, NULL,
63		(FLG_SG_TYPE | FLG_SG_FLAGS | FLG_SG_DISABLED), NULL, 0, 0},
64#if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
65	{{PT_LOAD, PF_R, 0, 0, 0, 0, 0, 0},
66		MSG_ORIG(MSG_ENT_LRODATA), 0, 0, NULL, NULL,
67		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
68	{{PT_LOAD, M_DATASEG_PERM, 0, 0, 0, 0, 0, 0},
69		MSG_ORIG(MSG_ENT_LDATA), 0, 0, NULL, NULL,
70		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
71#endif
72	{{PT_DYNAMIC, M_DATASEG_PERM, 0, 0, 0, 0, 0, 0},
73		MSG_ORIG(MSG_ENT_DYNAMIC), 0, 0, NULL, NULL,
74		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
75	{{PT_SUNWDTRACE, M_DATASEG_PERM | PF_X, 0, 0, 0, 0, 0, 0},
76		MSG_ORIG(MSG_ENT_DTRACE), 0, 0, NULL, NULL,
77		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
78	{{PT_NOTE, 0, 0, 0, 0, 0, 0, 0},
79		MSG_ORIG(MSG_ENT_NOTE), 0, 0, NULL, NULL,
80		FLG_SG_TYPE, NULL, 0, 0},
81	{{PT_SUNWBSS, 0, 0, 0, 0, 0, 0, 0},
82		MSG_ORIG(MSG_ENT_SUNWBSS), 0, 0, NULL, NULL,
83		FLG_SG_TYPE, NULL, 0, 0},
84	{{PT_TLS, PF_R, 0, 0, 0, 0, 0, 0},
85		MSG_ORIG(MSG_ENT_TLS), 0, 0, NULL, NULL,
86		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
87#if	defined(__i386) || defined(__amd64)
88	{{PT_SUNW_UNWIND, PF_R, 0, 0, 0, 0, 0, 0},
89		MSG_ORIG(MSG_ENT_UNWIND), 0, 0, NULL, NULL,
90		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
91#endif
92	{{PT_NULL, 0, 0, 0, 0, 0, 0, 0},
93		MSG_ORIG(MSG_STR_EMPTY), 0, 0, NULL, NULL,
94		FLG_SG_TYPE, NULL, 0, 0}
95};
96#else  /* Elf32 */
97static Sg_desc sg_desc[LD_NUM] = {
98	{{PT_PHDR, 0, 0, 0, 0, 0, PF_R + PF_X, 0},
99		MSG_ORIG(MSG_ENT_PHDR), 0, 0, NULL, NULL,
100		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
101	{{PT_INTERP, 0, 0, 0, 0, 0, PF_R, 0},
102		MSG_ORIG(MSG_ENT_INTERP), 0, 0, NULL, NULL,
103		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
104	{{PT_SUNWCAP, 0, 0, 0, 0, 0, PF_R, 0},
105		MSG_ORIG(MSG_ENT_SUNWCAP), 0, 0, NULL, NULL,
106		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
107	{{PT_LOAD, 0, 0, 0, 0, 0, PF_R + PF_X, 0},
108		MSG_ORIG(MSG_ENT_TEXT), 0, 0, NULL, NULL,
109		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
110	{{PT_LOAD, 0, 0, 0, 0, 0, M_DATASEG_PERM, 0},
111		MSG_ORIG(MSG_ENT_DATA), 0, 0, NULL, NULL,
112		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
113	{{PT_LOAD, 0, 0, 0, 0, 0, M_DATASEG_PERM, 0},
114		MSG_ORIG(MSG_ENT_BSS), 0, 0, NULL, NULL,
115		(FLG_SG_TYPE | FLG_SG_FLAGS | FLG_SG_DISABLED), NULL, 0, 0},
116	{{PT_DYNAMIC, 0, 0, 0, 0, 0, M_DATASEG_PERM, 0},
117		MSG_ORIG(MSG_ENT_DYNAMIC), 0, 0, NULL, NULL,
118		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
119	{{PT_SUNWDTRACE, 0, 0, 0, 0, 0, M_DATASEG_PERM, 0},
120		MSG_ORIG(MSG_ENT_DTRACE), 0, 0, NULL, NULL,
121		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
122	{{PT_NOTE, 0, 0, 0, 0, 0, 0, 0},
123		MSG_ORIG(MSG_ENT_NOTE), 0, 0, NULL, NULL,
124		FLG_SG_TYPE, NULL, 0, 0},
125	{{PT_SUNWBSS, 0, 0, 0, 0, 0, 0, 0},
126		MSG_ORIG(MSG_ENT_SUNWBSS), 0, 0, NULL, NULL,
127		FLG_SG_TYPE, NULL, 0, 0},
128	{{PT_TLS, PF_R, 0, 0, 0, 0, 0, 0},
129		MSG_ORIG(MSG_ENT_TLS), 0, 0, NULL, NULL,
130		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
131	{{PT_NULL, 0, 0, 0, 0, 0, 0, 0},
132		MSG_ORIG(MSG_STR_EMPTY), 0, 0, NULL, NULL,
133		FLG_SG_TYPE, NULL, 0, 0}
134};
135#endif /* Elfxx */
136
137
138/*
139 * The input processing of the loader involves matching the sections of its
140 * input files to an `entrance descriptor definition'.  The entrance criteria
141 * is different for either a static or dynamic linkage, and may even be
142 * modified further using a map file.  Each entrance criteria is associated
143 * with a segment descriptor, thus a mapping of input sections to output
144 * segments is maintained.
145 */
146static const Ent_desc	ent_desc[] = {
147	{{NULL, NULL}, MSG_ORIG(MSG_SCN_SUNWBSS), NULL,
148		SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE,
149		(Sg_desc *)LD_SUNWBSS, 0, FALSE},
150	{{NULL, NULL}, NULL, SHT_NOTE, 0, 0,
151		(Sg_desc *)LD_NOTE, 0, FALSE},
152#if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
153	{{NULL, NULL}, MSG_ORIG(MSG_SCN_LRODATA), NULL,
154		SHF_ALLOC + SHF_AMD64_LARGE, SHF_ALLOC + SHF_AMD64_LARGE,
155		(Sg_desc *)LD_LRODATA, 0, FALSE},
156#endif
157	{{NULL, NULL}, NULL, NULL,
158		SHF_ALLOC + SHF_WRITE, SHF_ALLOC,
159		(Sg_desc *)LD_TEXT, 0, FALSE},
160	{{NULL, NULL}, NULL, SHT_NOBITS,
161		SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE,
162		(Sg_desc *)LD_BSS, 0, FALSE},
163#if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
164	{{NULL, NULL}, NULL, SHT_NOBITS,
165		SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
166		SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
167		(Sg_desc *)LD_DATA, 0, FALSE},
168	{{NULL, NULL}, NULL, NULL,
169		SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
170		SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
171		(Sg_desc *)LD_LDATA, 0, FALSE},
172#endif
173	{{NULL, NULL}, NULL, NULL,
174		SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE,
175		(Sg_desc *)LD_DATA, 0, FALSE},
176	{{NULL, NULL}, NULL, 0, 0, 0,
177		(Sg_desc *)LD_EXTRA, 0, FALSE}
178};
179
180/*
181 * Initialize new entrance and segment descriptors and add them as lists to
182 * the output file descriptor.
183 */
184uintptr_t
185ld_ent_setup(Ofl_desc * ofl, Xword segalign)
186{
187	Ent_desc *	enp;
188	Sg_desc *	sgp;
189	size_t		size;
190
191	/*
192	 * Initialize the elf library.
193	 */
194	if (elf_version(EV_CURRENT) == EV_NONE) {
195		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_ELF_LIBELF),
196		    EV_CURRENT);
197		return (S_ERROR);
198	}
199
200	/*
201	 * Initialize internal Global Symbol Table AVL tree
202	 */
203	avl_create(&ofl->ofl_symavl, &ld_sym_avl_comp, sizeof (Sym_avlnode),
204	    SGSOFFSETOF(Sym_avlnode, sav_node));
205
206	/*
207	 * The datasegment permissions can differ depending on whether
208	 * this object is built statically or dynamically.
209	 */
210	if (ofl->ofl_flags & FLG_OF_DYNAMIC) {
211		sg_desc[LD_DATA].sg_phdr.p_flags = M_DATASEG_PERM;
212		sg_desc[LD_SUNWBSS].sg_phdr.p_flags = M_DATASEG_PERM;
213	} else {
214		sg_desc[LD_DATA].sg_phdr.p_flags = M_DATASEG_PERM | PF_X;
215	}
216
217	/*
218	 * Allocate and initialize writable copies of both the entrance and
219	 * segment descriptors.
220	 */
221	if ((sgp = libld_malloc(sizeof (sg_desc))) == 0)
222		return (S_ERROR);
223	(void) memcpy(sgp, sg_desc, sizeof (sg_desc));
224	if ((enp = libld_malloc(sizeof (ent_desc))) == 0)
225		return (S_ERROR);
226	(void) memcpy(enp, ent_desc, sizeof (ent_desc));
227
228	/*
229	 * Traverse the new entrance descriptor list converting the segment
230	 * pointer entries to the absolute address within the new segment
231	 * descriptor list.  Add each entrance descriptor to the output file
232	 * list.
233	 */
234	for (size = 0; size < sizeof (ent_desc); size += sizeof (Ent_desc)) {
235		enp->ec_segment = &sgp[(long)enp->ec_segment];
236		if ((list_appendc(&ofl->ofl_ents, enp)) == 0)
237			return (S_ERROR);
238		enp++;
239	}
240
241	/*
242	 * Traverse the new segment descriptor list adding each entry to the
243	 * segment descriptor list.  For each loadable segment initialize
244	 * a default alignment (ld(1) and ld.so.1 initialize this differently).
245	 */
246	for (size = 0; size < sizeof (sg_desc); size += sizeof (Sg_desc)) {
247
248		Phdr *	phdr = &(sgp->sg_phdr);
249
250		if ((list_appendc(&ofl->ofl_segs, sgp)) == 0)
251			return (S_ERROR);
252		if (phdr->p_type == PT_LOAD)
253			phdr->p_align = segalign;
254
255		sgp++;
256	}
257	return (1);
258}
259