xref: /illumos-gate/usr/src/cmd/sgs/libld/common/entry.c (revision 0bc0887e)
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 (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
27  */
28 
29 #define	ELF_TARGET_AMD64
30 
31 #include	<stdio.h>
32 #include	<memory.h>
33 #include	<debug.h>
34 #include	"msg.h"
35 #include	"_libld.h"
36 
37 /*
38  * The link-editor uses a segment descriptor list to describe the program
39  * headers, and related output segments, it can potentially create. This
40  * list is initially seeded using the templates contained in the sg_desc
41  * array below. Additional segments may be added using a mapfile.
42  *
43  * The entries in sg_desc must be put in the order defined by the
44  * Segment_id enum.
45  *
46  * The entries in sg_desc are initialized using the SG_DESC_INIT macro
47  * for two reasons:
48  *
49  *	1) The first field of the Sg_desc struct is a program header
50  *		entry. ELF32_Phdr and ELF64_Phdr have the same fields,
51  *		but their order is different. Use of a macro allows us
52  *		to handle this transparently.
53  *	2) Most of the fields in the Sg_desc entries are set to 0.
54  *		Use of a macro allows us to hide the clutter.
55  *
56  * If a given program header can be referenced via an entrance criteria
57  * (i.e. can serve as a segment), then it must be given a unique sg_name.
58  * Program headers that cannot be a segment (PHDR, INTERP, DYNAMIC, etc)
59  * must have a NULL sg_name --- their program header type identifies them.
60  */
61 #ifdef _ELF64
62 #define	SG_DESC_INIT(id, p_type, p_flags, sg_name, sg_flags) \
63 	{ id, { p_type, p_flags, 0, 0, 0, 0, 0, 0}, \
64 	    sg_name, 0, 0, NULL, NULL, NULL, sg_flags, NULL, 0, NULL}
65 #else
66 #define	SG_DESC_INIT(id, p_type, p_flags, sg_name, sg_flags) \
67 	{ id, { p_type, 0, 0, 0, 0, 0, p_flags, 0}, \
68 	    sg_name, 0, 0, NULL, NULL, NULL, sg_flags, NULL, 0, NULL}
69 #endif
70 
71 /*
72  * Predefined segment descriptors:
73  *
74  * The C language guarantees that a structure containing only fields of
75  * identical type is indistinguishable from a simple array containing
76  * the same number of items of the same type. They will have the same
77  * size, alignment, and internal layout:
78  *
79  * -	A pointer to one is equivalent to a pointer to the other, and you
80  *	can cast safely between them.
81  *
82  * -	You can put both into a union, and access the elements within
83  *	either way (by index, or by name).
84  *
85  * We use this fact here to create an "array" of predefined segment
86  * descriptors, assigning each one a mnemonic name that can be used to point
87  * at it from a predefined entrance criteria descriptor (below). These
88  * segments are positioned in the default order that will result in the
89  * output object, unless a mapfile alters things.
90  */
91 typedef struct {
92 	Sg_desc	psg_phdr;
93 	Sg_desc psg_interp;
94 	Sg_desc psg_sunwcap;
95 	Sg_desc psg_text;
96 	Sg_desc psg_data;
97 	Sg_desc psg_bss;
98 #if	defined(_ELF64)
99 	Sg_desc	psg_lrodata;	/* (amd64-only) */
100 	Sg_desc psg_ldata;	/* (amd64-only) */
101 #endif
102 	Sg_desc	psg_dynamic;
103 	Sg_desc	psg_sunwdtrace;
104 	Sg_desc	psg_tls;
105 	Sg_desc	psg_unwind;
106 	Sg_desc	psg_sunwstack;
107 	Sg_desc	psg_note;
108 	Sg_desc	psg_extra;
109 } predef_seg_t;
110 
111 static const size_t predef_seg_nelts =
112 	(sizeof (predef_seg_t) / sizeof (Sg_desc));
113 
114 static predef_seg_t sg_desc = {
115 	/* psg_phdr */
116 	SG_DESC_INIT(SGID_PHDR, PT_PHDR, PF_R + PF_X, NULL,
117 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
118 
119 	/* psg_interp */
120 	SG_DESC_INIT(SGID_INTERP, PT_INTERP, PF_R, NULL,
121 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
122 
123 	/* psg_sunwcap */
124 	SG_DESC_INIT(SGID_SUNWCAP, PT_SUNWCAP, PF_R, NULL,
125 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
126 
127 	/* psg_text */
128 	SG_DESC_INIT(SGID_TEXT, PT_LOAD, PF_R + PF_X, MSG_ORIG(MSG_ENT_TEXT),
129 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
130 
131 	/* psg_data */
132 	SG_DESC_INIT(SGID_DATA, PT_LOAD, 0, MSG_ORIG(MSG_ENT_DATA),
133 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
134 
135 	/* psg_bss */
136 	SG_DESC_INIT(SGID_BSS, PT_LOAD, 0, MSG_ORIG(MSG_ENT_BSS),
137 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS | FLG_SG_DISABLED)),
138 
139 #if	defined(_ELF64)
140 	/* psg_lrodata (amd64-only ) */
141 	SG_DESC_INIT(SGID_LRODATA, PT_LOAD, PF_R, MSG_ORIG(MSG_ENT_LRODATA),
142 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
143 
144 	/* psg_ldata (amd64-only ) */
145 	SG_DESC_INIT(SGID_LDATA, PT_LOAD, 0, MSG_ORIG(MSG_ENT_LDATA),
146 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
147 #endif
148 	/* psg_dynamic */
149 	SG_DESC_INIT(SGID_DYN, PT_DYNAMIC, 0, NULL,
150 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
151 
152 	/* psg_sunwdtrace */
153 	SG_DESC_INIT(SGID_DTRACE, PT_SUNWDTRACE, 0, NULL,
154 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
155 
156 	/* psg_tls */
157 	SG_DESC_INIT(SGID_TLS, PT_TLS, PF_R, NULL,
158 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
159 
160 	/* psg_unwind */
161 	SG_DESC_INIT(SGID_UNWIND, PT_SUNW_UNWIND, PF_R, NULL,
162 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
163 
164 	/* psg_sunwstack */
165 	SG_DESC_INIT(SGID_SUNWSTACK, PT_SUNWSTACK, 0, NULL,
166 	    (FLG_SG_P_TYPE | FLG_SG_P_FLAGS | FLG_SG_DISABLED)),
167 
168 	/* psg_note */
169 	SG_DESC_INIT(SGID_NOTE, PT_NOTE, 0, MSG_ORIG(MSG_ENT_NOTE),
170 	    FLG_SG_P_TYPE),
171 
172 	/*
173 	 * psg_extra
174 	 *
175 	 * This segment is referenced by the final entrance criteria descriptor
176 	 * to catch any segment not otherwise placed. It cannot be disabled
177 	 * via a mapfile.
178 	 */
179 	SG_DESC_INIT(SGID_EXTRA, PT_NULL, 0, MSG_ORIG(MSG_ENT_EXTRA),
180 	    (FLG_SG_P_TYPE | FLG_SG_NODISABLE))
181 };
182 #undef SG_DESC_INIT
183 
184 /*
185  * The processing of input files by the link-editor involves matching the
186  * input file sections against an ordered list of entrance criteria
187  * descriptors. The following template defines the built in entrance criteria
188  * list. This list can be augmented using a mapfile. Each entrance criteria
189  * is associated with a segment descriptor, providing the means for mapping
190  * input sections to output segments.
191  *
192  * As with the segment descriptors, the EC_DESC_INIT macro is used
193  * to reduce boilerplate clutter.
194  */
195 #define	EC_DESC_INIT(ec_is_name, ec_type, ec_attrmask, ec_attrbits, \
196     _seg_field, ec_flags) \
197 	{ NULL, NULL, ec_is_name, ec_type, ec_attrmask, ec_attrbits, \
198 	    &sg_desc.psg_ ## _seg_field, 0, FLG_EC_BUILTIN | ec_flags }
199 
200 static const Ent_desc	ent_desc[] = {
201 	EC_DESC_INIT(NULL, SHT_NOTE, 0, 0, note, 0),
202 
203 #if	defined(_ELF64)		/* (amd64-only) */
204 	EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
205 	    SHF_ALLOC + SHF_AMD64_LARGE, lrodata, 0),
206 #endif
207 	EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE, SHF_ALLOC, text, 0),
208 
209 	/*
210 	 * Explicitly assign the .tdata section to bss.  The design of TLS
211 	 * provides for initialized data being assigned to a .tdata section,
212 	 * and uninitialized data being assigned to a .tbss section.  These
213 	 * sections should be laid out adjacent to each other, with little or
214 	 * no gap between them.  A PT_TLS program header is created that
215 	 * defines the address range of the two sections.  This header is
216 	 * passed to libc to instantiate the appropriate thread allocation.
217 	 *
218 	 * By default a separate bss segment is disabled, however users can
219 	 * trigger the creation of a bss segment with a mapfile.  By default,
220 	 * all bss sections are assigned to the data segment, and the section
221 	 * identifiers of .tdata and .tbss ensure that these two sections are
222 	 * adjacent to each other.
223 	 *
224 	 * However, if a bss segment is enabled, the adjacency of the .tdata
225 	 * and .tbss sections can only be retained by having an explicit .tdata
226 	 * entrance criteria.
227 	 */
228 	EC_DESC_INIT(MSG_ORIG(MSG_SCN_TDATA), 0, SHF_ALLOC + SHF_WRITE,
229 	    SHF_ALLOC + SHF_WRITE, bss, 0),
230 
231 	EC_DESC_INIT(NULL, SHT_NOBITS, SHF_ALLOC + SHF_WRITE,
232 	    SHF_ALLOC + SHF_WRITE, bss, 0),
233 
234 #if	defined(_ELF64)		/* (amd64-only) */
235 	EC_DESC_INIT(NULL, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
236 	    SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, data, 0),
237 
238 	EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
239 	    SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, ldata, 0),
240 #endif
241 	EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE,
242 	    data, 0),
243 
244 	/*
245 	 * Final catchall rule sends remaining sections to "extra"
246 	 * NULL segment, which has been tagged as FLG_SG_NODISABLE,
247 	 * and which will therefore always accept them.
248 	 */
249 	EC_DESC_INIT(NULL, 0, 0, 0, extra, FLG_EC_CATCHALL)
250 };
251 #undef EC_DESC_INIT
252 
253 /*
254  * AVL comparison function for Sg_desc items in ofl_segs_avl.
255  *
256  * entry:
257  *	n1, n2 - pointers to nodes to be compared
258  *
259  * exit:
260  *	Returns -1 if (n1 < n2), 0 if they are equal, and 1 if (n1 > n2)
261  */
262 static int
ofl_segs_avl_cmp(const void * n1,const void * n2)263 ofl_segs_avl_cmp(const void *n1, const void *n2)
264 {
265 	int		rc;
266 
267 	rc = strcmp(((Sg_desc *)n1)->sg_name, ((Sg_desc *)n2)->sg_name);
268 
269 	if (rc > 0)
270 		return (1);
271 	if (rc < 0)
272 		return (-1);
273 	return (0);
274 }
275 
276 /*
277  * AVL comparison function for Ent_desc items in ofl_ents_avl.
278  *
279  * entry:
280  *	n1, n2 - pointers to nodes to be compared
281  *
282  * exit:
283  *	Returns -1 if (n1 < n2), 0 if they are equal, and 1 if (n1 > n2)
284  */
285 static int
ofl_ents_avl_cmp(const void * n1,const void * n2)286 ofl_ents_avl_cmp(const void *n1, const void *n2)
287 {
288 	int		rc;
289 
290 	/*
291 	 * There are entrance criteria nodes with NULL pointer names,
292 	 * but they are never entered into the AVL tree. Hence, we can
293 	 * assume that both nodes have names.
294 	 */
295 	rc = strcmp(((Ent_desc *)n1)->ec_name, ((Ent_desc *)n2)->ec_name);
296 
297 	if (rc > 0)
298 		return (1);
299 	if (rc < 0)
300 		return (-1);
301 	return (0);
302 }
303 
304 /*
305  * Lookup a segment descriptor by name.
306  *
307  * entry:
308  *	ofl - Output descriptor
309  *	name - Name of desired segment
310  *
311  * exit:
312  *	On success, returns pointer to descriptor. On failure, returns NULL.
313  */
314 Sg_desc *
ld_seg_lookup(Ofl_desc * ofl,const char * name,avl_index_t * where)315 ld_seg_lookup(Ofl_desc *ofl, const char *name, avl_index_t *where)
316 {
317 	Sg_desc		sg;
318 
319 	sg.sg_name = name;
320 	return (avl_find(&ofl->ofl_segs_avl, &sg, where));
321 }
322 
323 
324 /*
325  * Look up an entrance criteria record by name
326  *
327  * entry:
328  *	mf - Mapfile descriptor
329  *	name - Name of entrance criteria to locate
330  *
331  * exit:
332  *	On success, a pointer to the entrace criteria record is
333  *	returned. On failure, NULL is returned.
334  *
335  * note:
336  *	Entrance criteria are not required to have names. Only
337  *	named entrance criteria can be looked up via this method.
338  */
339 Ent_desc *
ld_ent_lookup(Ofl_desc * ofl,const char * name,avl_index_t * where)340 ld_ent_lookup(Ofl_desc *ofl, const char *name, avl_index_t *where)
341 {
342 	Ent_desc	en;
343 
344 	en.ec_name = name;
345 	return (avl_find(&ofl->ofl_ents_avl, &en, where));
346 }
347 
348 /*
349  * Initialize new entrance and segment descriptors and add them as lists to
350  * the output file descriptor.
351  */
352 uintptr_t
ld_ent_setup(Ofl_desc * ofl,Xword segalign)353 ld_ent_setup(Ofl_desc *ofl, Xword segalign)
354 {
355 	Ent_desc	*enp;
356 	predef_seg_t	*psegs;
357 	Sg_desc		*sgp;
358 	size_t		idx;
359 
360 	/*
361 	 * Initialize the elf library.
362 	 */
363 	if (elf_version(EV_CURRENT) == EV_NONE) {
364 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ELF_LIBELF),
365 		    EV_CURRENT);
366 		return (S_ERROR);
367 	}
368 
369 	/*
370 	 * Initialize internal Global Symbol Table AVL tree
371 	 */
372 	avl_create(&ofl->ofl_symavl, &ld_sym_avl_comp, sizeof (Sym_avlnode),
373 	    SGSOFFSETOF(Sym_avlnode, sav_node));
374 
375 	/* Initialize segment AVL tree */
376 	avl_create(&ofl->ofl_segs_avl, ofl_segs_avl_cmp,
377 	    sizeof (Sg_desc), SGSOFFSETOF(Sg_desc, sg_avlnode));
378 
379 	/* Initialize entrance criteria AVL tree */
380 	avl_create(&ofl->ofl_ents_avl, ofl_ents_avl_cmp, sizeof (Ent_desc),
381 	    SGSOFFSETOF(Ent_desc, ec_avlnode));
382 
383 
384 	/*
385 	 * Allocate and initialize writable copies of both the entrance and
386 	 * segment descriptors.
387 	 *
388 	 * Note that on non-amd64 targets, this allocates a few more
389 	 * elements than are needed. For now, we are willing to overallocate
390 	 * a small amount to simplify the code.
391 	 */
392 	if ((psegs = libld_malloc(sizeof (sg_desc))) == NULL)
393 		return (S_ERROR);
394 	(void) memcpy(psegs, &sg_desc, sizeof (sg_desc));
395 	sgp = (Sg_desc *) psegs;
396 
397 	/*
398 	 * The data segment and stack permissions can differ:
399 	 *
400 	 *	- Architectural/ABI per-platform differences
401 	 *	- Whether the object is built statically or dynamically
402 	 *
403 	 * Those segments so affected have their program header flags
404 	 * set here at runtime, rather than in the sg_desc templates above.
405 	 */
406 	psegs->psg_data.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
407 	psegs->psg_bss.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
408 	psegs->psg_dynamic.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
409 	psegs->psg_sunwdtrace.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
410 #if	defined(_ELF64)
411 	psegs->psg_ldata.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
412 	psegs->psg_sunwdtrace.sg_phdr.p_flags |= PF_X;
413 #endif
414 	psegs->psg_sunwstack.sg_phdr.p_flags = ld_targ.t_m.m_stack_perm;
415 	if ((ofl->ofl_flags & FLG_OF_DYNAMIC) == 0)
416 		psegs->psg_data.sg_phdr.p_flags |= PF_X;
417 
418 	/*
419 	 * Traverse the new entrance descriptor list converting the segment
420 	 * pointer entries to the absolute address within the new segment
421 	 * descriptor list.  Add each entrance descriptor to the output file
422 	 * list.
423 	 */
424 	if ((enp = libld_malloc(sizeof (ent_desc))) == NULL)
425 		return (S_ERROR);
426 	(void) memcpy(enp, ent_desc, sizeof (ent_desc));
427 	for (idx = 0; idx < (sizeof (ent_desc) / sizeof (ent_desc[0])); idx++,
428 	    enp++) {
429 
430 #if	defined(_ELF64)
431 		/* Don't use the amd64 entry conditions for non-amd64 targets */
432 		if ((enp->ec_attrmask & SHF_AMD64_LARGE) &&
433 		    (ld_targ.t_m.m_mach != EM_AMD64))
434 			continue;
435 #endif
436 		if (aplist_append(&ofl->ofl_ents, enp,
437 		    AL_CNT_OFL_ENTRANCE) == NULL)
438 			return (S_ERROR);
439 
440 		/*
441 		 * The segment pointer is currently pointing at a template
442 		 * segment descriptor in sg_desc. Compute its array index,
443 		 * and then use that index to compute the address of the
444 		 * corresponding descriptor in the writable copy.
445 		 */
446 		enp->ec_segment =
447 		    &sgp[(enp->ec_segment - (Sg_desc *) &sg_desc)];
448 	}
449 
450 	/*
451 	 * Add each segment descriptor to the segment descriptor list. The
452 	 * ones with non-NULL sg_name are also entered into the AVL tree.
453 	 * For each loadable segment initialize a default alignment. Note
454 	 * that ld(1) and ld.so.1 initialize this differently.
455 	 */
456 	for (idx = 0; idx < predef_seg_nelts; idx++, sgp++) {
457 		Phdr	*phdr = &(sgp->sg_phdr);
458 
459 #if	defined(_ELF64)
460 		/* Ignore amd64 segment templates for non-amd64 targets */
461 		switch (sgp->sg_id) {
462 		case SGID_LRODATA:
463 		case SGID_LDATA:
464 			if ((ld_targ.t_m.m_mach != EM_AMD64))
465 				continue;
466 		}
467 #endif
468 		if (phdr->p_type == PT_LOAD)
469 			phdr->p_align = segalign;
470 
471 		if ((aplist_append(&ofl->ofl_segs, sgp,
472 		    AL_CNT_SEGMENTS)) == NULL)
473 			return (S_ERROR);
474 
475 #ifndef NDEBUG			/* assert() is enabled */
476 		/*
477 		 * Enforce the segment name rule: Any segment that can
478 		 * be referenced by an entrance descriptor must have
479 		 * a name. Any segment that cannot, must have a NULL
480 		 * name pointer.
481 		 */
482 		switch (phdr->p_type) {
483 		case PT_LOAD:
484 		case PT_NOTE:
485 		case PT_NULL:
486 			assert(sgp->sg_name != NULL);
487 			break;
488 		default:
489 			assert(sgp->sg_name == NULL);
490 			break;
491 		}
492 #endif
493 
494 		/*
495 		 * Add named segment descriptors to the AVL tree to
496 		 * provide O(logN) lookups.
497 		 */
498 		if (sgp->sg_name != NULL)
499 			avl_add(&ofl->ofl_segs_avl, sgp);
500 	}
501 
502 	return (1);
503 }
504