xref: /titanic_50/usr/src/cmd/sgs/libld/common/order.c (revision bd670b35a010421b6e1a5536c34453a827007c81)
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 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Processing of SHF_ORDERED sections.
29  */
30 #include	<stdio.h>
31 #include	<fcntl.h>
32 #include	<link.h>
33 #include	<debug.h>
34 #include	"msg.h"
35 #include	"_libld.h"
36 
37 /*
38  * Section Ordering History/Background:
39  *
40  * There are two forms of section ordering, SHF_ORDERED, and SHF_LINK_ORDER.
41  *
42  * SHF_ORDERED was invented at Sun in order to support the PowerPC port
43  * of Solaris 2.6, which used it for sorting tag words which describe
44  * the state of callee saves registers for given PC ranges. It was defined
45  * in the OS specific ELF section flag range. Some other values were defined
46  * at the same time:
47  *	SHF_EXCLUDE - Section is to be excluded from executables or shared
48  *		objects, and only kept in relocatable object output.
49  *	SHN_BEFORE/SHN_AFTER - Sections are placed before/after all other
50  *		sections, in the order they are encountered by the linker.
51  * Although initially conceived to support the PowerPC, the functionality
52  * was implemented for all platforms, and was later used to manage C++
53  * exceptions and stack unwinding. The PowerPC port was discontinued after
54  * one release, but SHF_ORDERED lives on.
55  *
56  * SHF_LINK_ORDER was invented later by the wider ELF community, and is
57  * therefore assigned a value in the generic ELF section flag range. It is
58  * essentially a simpler version of SHF_ORDERED, dispensing with some
59  * unnecessary features. The Solaris implementation of SHF_LINK_ORDER uses
60  * SHF_EXCLUDE, and SHF_BEFORE/SHN_AFTER as well, but it appears that these
61  * are still Solaris-only extensions not used by other implementations.
62  * SHF_LINK_ORDER has superseded SHF_ORDERED. The older mechanism is
63  * supported for the benefit of old pre-existing objects.
64  *
65  * -----
66  *
67  * SHF_ORDERED offers two distinct and separate abilities:
68  *
69  *	(1) To specify the output section
70  *	(2) To optionally be sorted relative to other sorted sections,
71  *		using a non-sorted section as a sort key.
72  *
73  * To  do this, it uses both the sh_link, and sh_info fields:
74  *
75  *    sh_link
76  *	Specifies the output section to receive this input section.
77  *	The sh_link field of an SHF_ORDERED section forms a linked list of
78  *	sections, all of which must have identical section header flags
79  *	(including SHF_ORDERED). The list is terminated by a final section
80  *	with a sh_link that points at itself. All input sections in this list
81  *	are assigned to the output section of the final section in the list.
82  *	Hence, if a section points at itself, the effect is that it gets
83  *	assigned to an output section in the usual default manner (i.e. an
84  *	output section with the same name as the input). However, it can
85  *	point at any arbitrary other section. This is a way to put a section
86  *	with one name into an output section with a different name. It should
87  *	be noted that this is of little value overall, because the link-editor
88  *	already supports a more general feature for directing input sections
89  *	to output sections: An input section named .text%foo will be sent to
90  *	an output section named ".text", and this works for all sections,
91  *	not just ordered ones.
92  *
93  *    sh_info
94  *	If sh_info is in the range (1 <= value < shnum), then this input section
95  *	is added to the group of sorted sections. The section referenced by
96  *	sh_info must be unsorted, and is used as the sort key.
97  *
98  *	If sh_info is SHN_BEFORE or SHN_AFTER, it is put in the pre/post group,
99  *	in the order it arrives (the before/after classes are not sorted).
100  *
101  *	If sh_info is "invalid" (typically 0), then this section is added to
102  *	the group of non-sorted sections, and goes into the output file in the
103  *	order it arrives. This is not a valuable feature, as the same effect
104  *	can be achieved more simply by not setting SHF_ORDERED at all.
105  *
106  * SHF_LINK_ORDER is a simplification of SHF_ORDERED. It uses sh_link to specify
107  * the section to use as a sort key and sh_info is set to 0. The standard
108  * ".text%foo" mechanism is used to direct input sections to output sections,
109  * and unordered sections indicate that by not setting SHF_LINK_ORDER.
110  */
111 
112 
113 /*
114  * A "keyshndx" is the section index for the unordered section that should
115  * be used as a sort key for a ordered section. Verify that the given
116  * keyshndx is valid.
117  *
118  * exit:
119  *	Returns 0 if the keyshndx is valid. A non-zero DBG_ORDER_ code is
120  *	returned if the keyshndx is not valid to describe the problem.
121  */
122 inline static Word
123 is_keyshndx_ok(Ifl_desc *ifl, Word keyshndx)
124 {
125 	if ((keyshndx == SHN_BEFORE) || (keyshndx == SHN_AFTER))
126 		return (0);
127 
128 	/*
129 	 * Validate the key range.
130 	 */
131 	if ((keyshndx == 0) || (keyshndx >= ifl->ifl_shnum))
132 		return (DBG_ORDER_LINK_OUTRANGE);
133 
134 	/*
135 	 * The section pointed to by keyshndx should not be an ordered section.
136 	 * Strictly speaking, we could test for SHF_ORDERED here instead of
137 	 * ALL_SHF_ORDER as the two ordering flags are not supposed to be
138 	 * mixed. Using ALL_SHF_ORDER costs the same and ensures that such
139 	 * mixing doesn't go undetected.
140 	 */
141 	if (ifl->ifl_isdesc[keyshndx]->is_shdr->sh_flags & ALL_SHF_ORDER)
142 		return (DBG_ORDER_INFO_ORDER);
143 
144 	return (0);
145 }
146 
147 /*
148  * The sh_link field of an SHF_ORDERED section forms a linked list of
149  * sections. The list is terminated by a final section with a sh_link
150  * that points at itself. Given the index of an SHF_ORDERED section, find
151  * the index of the final section in the list.
152  *
153  * entry:
154  *	ofl - Output file descriptor
155  *	ifl - Input file descriptor
156  *	ndx - Section index of SHF_ORDERED section
157  *	alt_os_name - Address of pointer to string. If the final section
158  *		name is different than the section given by ndx, *alt_os_name
159  *		will be updated with the name of the final section. The caller
160  *		should initialize *alt_os_name to NULL before calling
161  *		this routine.
162  *
163  * exit:
164  *	On success: If the final section is different than the section
165  *	given by ndx, then *alt_os_name is set to its name. TRUE is returned.
166  *
167  *	On failure, FALSE is returned.
168  */
169 static Boolean
170 validate_shf_ordered_dest(Ofl_desc *ofl, Ifl_desc *ifl, Word ndx,
171     const char **alt_os_name)
172 {
173 	Word	shnum = ifl->ifl_shnum;
174 	Word	isp1_ndx, isp2_ndx;
175 	Is_desc	*isp1, *isp2;
176 	int	error = 0;
177 	size_t	iter = 0;
178 
179 	/*
180 	 * Traverse the list until we find the termination, or encounter
181 	 * an invalid condition in the object that prevents ordering.
182 	 */
183 	isp1_ndx = ndx;
184 	isp1 = ifl->ifl_isdesc[ndx];
185 	do {
186 		/*
187 		 * Obtain index of next section in list. Ensure it is in range.
188 		 */
189 		isp2_ndx = isp1->is_shdr->sh_link;
190 		if ((isp2_ndx == 0) || (isp2_ndx >= shnum)) {
191 			error = DBG_ORDER_LINK_OUTRANGE;
192 			break;
193 		}
194 		isp2 = ifl->ifl_isdesc[isp2_ndx];
195 
196 		/* The section flags must match exactly */
197 		if (isp1->is_shdr->sh_flags != isp2->is_shdr->sh_flags) {
198 			/*
199 			 * The case where the next section in the list does
200 			 * not have the same ordered flag set as the original
201 			 * ordered section gets a unique error code. This
202 			 * provides more accurate/useful debugging diagnostics.
203 			 */
204 			error = ((isp2->is_flags & FLG_IS_ORDERED) == 0) ?
205 			    DBG_ORDER_LINK_ERROR : DBG_ORDER_FLAGS;
206 			break;
207 		}
208 
209 		/*
210 		 * The sh_info field specifies the section index of an
211 		 * unorderd section which will be used as a sort key.
212 		 * Ensure it is in range. If not, we terminate the list
213 		 * at the current node instead of continuing on.
214 		 */
215 		if ((error = is_keyshndx_ok(ifl, isp2->is_shdr->sh_info)) != 0)
216 			break;
217 
218 		/* If the section points at itself, it terminates the list */
219 		if (isp1_ndx == isp2_ndx)
220 			break;
221 
222 		/*
223 		 * Advance to next section in list
224 		 */
225 		isp1_ndx = isp2_ndx;
226 		isp1 = isp2;
227 
228 		/*
229 		 * If we loop more times than the input file has sections,
230 		 * we have encountered a malformed object in which the list
231 		 * of SHF_ORDERED sections has a cycle. This can only happen
232 		 * if the compiler generating the object has a bad bug.
233 		 */
234 		if (++iter >= shnum) {
235 			error = DBG_ORDER_CYCLIC;
236 			break;
237 		}
238 	/* CONSTANTCONDITION */
239 	} while (1);
240 
241 	/*
242 	 * If we have found a problem, issue a debug diagnostic and map
243 	 * the output section to 0. This indicates that the section should
244 	 * remove the ordering flag and treat it as a standard section.
245 	 */
246 	if (error != 0) {
247 		isp2_ndx = 0;
248 		DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error));
249 	}
250 
251 	/* Report success */
252 	if (isp2_ndx != 0) {
253 		/*
254 		 * If the destination section is different than the input
255 		 * section, then set *alt_os_name to the destination name.
256 		 */
257 		if (isp2_ndx != ndx)
258 			*alt_os_name = ifl->ifl_isdesc[isp2_ndx]->is_name;
259 		return (TRUE);
260 	}
261 
262 	/* If we get here, there is no valid destination */
263 	return (FALSE);
264 }
265 
266 /*
267  * Called when an ordered section has a problem that prevents ordering.
268  * The order flag is removed, and then the section is placed as an
269  * unsorted section.
270  */
271 static uintptr_t
272 place_unordered(Ofl_desc *ofl, Is_desc *isp)
273 {
274 	isp->is_flags &= ~FLG_IS_ORDERED;
275 	if (isp->is_osdesc == NULL)
276 		return ((uintptr_t)ld_place_section(ofl, isp,
277 		    isp->is_keyident, NULL));
278 	return ((uintptr_t)isp->is_osdesc);
279 }
280 
281 /*
282  * Process ordered input section. Called from process_elf() after
283  * all the non-ordered sections have been placed.
284  *
285  * entry:
286  *	ofl - Output file descriptor
287  *	ifl - Input file descriptor
288  *	ndx - Section index of SHF_ORDERED section
289  *
290  * exit:
291  */
292 uintptr_t
293 ld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx)
294 {
295 	Is_desc		*isp2, *isp = ifl->ifl_isdesc[ndx];
296 	Xword		shflags = isp->is_shdr->sh_flags;
297 	const char	*alt_os_name = NULL;
298 	Word		keyshndx;
299 	Os_desc		*osp;
300 	int		error = 0;
301 
302 	/*
303 	 * Obtain the sort key section index for this ordered section.
304 	 * SHF_ORDERED uses sh_info, while SHF_LINK_ORDER uses sh_link.
305 	 * In order for this function to be called, one of SHF_ORDERED
306 	 * or SHF_LINK_ORDER must be set. Testing for one implies the
307 	 * state of the other.
308 	 */
309 	keyshndx = (shflags & SHF_ORDERED) ?
310 	    isp->is_shdr->sh_info : isp->is_shdr->sh_link;
311 
312 	/*
313 	 * Validate the sort key section index. If something is wrong,
314 	 * fall back to treating it as a non-ordered section.
315 	 */
316 	if ((error = is_keyshndx_ok(ifl, keyshndx)) != 0) {
317 		DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error));
318 		return (place_unordered(ofl, isp));
319 	}
320 
321 	/*
322 	 * If SHF_ORDERED is in effect, validate the destination section
323 	 * name given by sh_link, and set alt_os_name to the name of the
324 	 * destination if it differs from the section being processed.
325 	 */
326 	if ((shflags & SHF_ORDERED) &&
327 	    (validate_shf_ordered_dest(ofl, ifl, ndx, &alt_os_name) == FALSE))
328 		return (place_unordered(ofl, isp));
329 
330 	/*
331 	 * Place the section into its output section. It's possible that this
332 	 * section is discarded (possibly because it's defined COMDAT), in
333 	 * which case we're done.
334 	 */
335 	if ((osp = isp->is_osdesc) == NULL) {
336 		osp = ld_place_section(ofl, isp, isp->is_keyident, alt_os_name);
337 		if ((osp == (Os_desc *)S_ERROR) || (osp == NULL))
338 			return ((uintptr_t)osp);
339 	}
340 
341 	/*
342 	 * If the output section is not yet on the ordered list, place it on
343 	 * the list.
344 	 */
345 	if (aplist_test(&ofl->ofl_ordered, osp, AL_CNT_OFL_ORDERED) ==
346 	    ALE_ALLOCFAIL)
347 		return ((uintptr_t)S_ERROR);
348 
349 	/*
350 	 * Output section has been found - set up its sorting information.
351 	 */
352 	if ((keyshndx != SHN_BEFORE) && (keyshndx != SHN_AFTER)) {
353 		Os_desc		*osp2;
354 
355 		isp2 = ifl->ifl_isdesc[keyshndx];
356 		if (isp2->is_flags & FLG_IS_DISCARD) {
357 			eprintf(ofl->ofl_lml, ERR_FATAL,
358 			    MSG_INTL(MSG_FIL_BADORDREF), ifl->ifl_name,
359 			    EC_WORD(isp->is_scnndx), isp->is_name,
360 			    EC_WORD(isp2->is_scnndx), isp2->is_name);
361 			return (S_ERROR);
362 		}
363 
364 		/*
365 		 * Indicate that this ordered input section will require a
366 		 * sort key.  Propagate the key requirement through to the
367 		 * associated output section, segment and file, to trigger
368 		 * the sort key creation.  See ld_sec_validate();
369 		 */
370 		isp2->is_flags |= FLG_IS_KEY;
371 
372 		osp2 = isp2->is_osdesc;
373 		osp2->os_flags |= FLG_OS_KEY;
374 		osp2->os_sgdesc->sg_flags |= FLG_SG_KEY;
375 
376 		ofl->ofl_flags |= FLG_OF_KEY;
377 	}
378 
379 	return ((uintptr_t)osp);
380 }
381 
382 /*
383  * Traverse all segments looking for section ordering information that hasn't
384  * been used.  If found give a warning message to the user.  Also, check if
385  * there are any ordered key sections, and if so set up sort key values.
386  */
387 void
388 ld_sec_validate(Ofl_desc *ofl)
389 {
390 	Aliste		idx1;
391 	Sg_desc		*sgp;
392 	Word 		key = 1;
393 
394 	for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
395 		Sec_order	*scop;
396 		Os_desc		*osp;
397 		Aliste		idx2;
398 
399 		for (APLIST_TRAVERSE(sgp->sg_secorder, idx2, scop)) {
400 			if ((scop->sco_flags & FLG_SGO_USED) == 0) {
401 				eprintf(ofl->ofl_lml, ERR_WARNING,
402 				    MSG_INTL(MSG_MAP_SECORDER),
403 				    sgp->sg_name, scop->sco_secname);
404 			}
405 		}
406 		if ((sgp->sg_flags & FLG_SG_KEY) == 0)
407 			continue;
408 
409 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
410 			Aliste	idx3;
411 			Is_desc	*isp;
412 
413 			if ((osp->os_flags & FLG_OS_KEY) == 0)
414 				continue;
415 
416 			/*
417 			 * The input sections used as sort keys are required
418 			 * to be unordered, so we only have to look at the
419 			 * DEFAULT list of input sections.
420 			 */
421 			for (APLIST_TRAVERSE(osp->os_isdescs[OS_ISD_DEFAULT],
422 			    idx3, isp)) {
423 				if (isp->is_flags & FLG_IS_KEY)
424 					isp->is_keyident = key++;
425 			}
426 		}
427 	}
428 }
429 
430 static int
431 comp(const void *ss1, const void *ss2)
432 {
433 	Is_desc		*s1 = *((Is_desc **)ss1);
434 	Is_desc		*s2 = *((Is_desc **)ss2);
435 	Is_desc		*i1, *i2;
436 	Word		ndx1, ndx2;
437 
438 	if (s1->is_shdr->sh_flags & SHF_ORDERED)
439 		ndx1 = s1->is_shdr->sh_info;
440 	else
441 		ndx1 = s1->is_shdr->sh_link;
442 
443 	if (s2->is_shdr->sh_flags & SHF_ORDERED)
444 		ndx2 = s2->is_shdr->sh_info;
445 	else
446 		ndx2 = s2->is_shdr->sh_link;
447 
448 	i1 = s1->is_file->ifl_isdesc[ndx1];
449 	i2 = s2->is_file->ifl_isdesc[ndx2];
450 
451 	if (i1->is_keyident > i2->is_keyident)
452 		return (1);
453 	if (i1->is_keyident < i2->is_keyident)
454 		return (-1);
455 	return (0);
456 }
457 
458 /*
459  * Sort ordered input sections
460  */
461 uintptr_t
462 ld_sort_ordered(Ofl_desc *ofl)
463 {
464 	Aliste	idx1;
465 	Os_desc *osp;
466 
467 	DBG_CALL(Dbg_sec_order_list(ofl, 0));
468 
469 	for (APLIST_TRAVERSE(ofl->ofl_ordered, idx1, osp)) {
470 		APlist	*ap_list = osp->os_isdescs[OS_ISD_ORDERED];
471 		Aliste	apl_nitems = aplist_nitems(ap_list);
472 
473 		/*
474 		 * If this output section has a non-empty list of ordered
475 		 * input sections, sort their APlist in place into their
476 		 * final order.
477 		 */
478 		if (apl_nitems != 0)
479 			qsort((char *)ap_list->apl_data, apl_nitems,
480 			    sizeof (Is_desc *), comp);
481 	}
482 	DBG_CALL(Dbg_sec_order_list(ofl, 1));
483 	return (0);
484 }
485