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