xref: /titanic_44/usr/src/cmd/sgs/libld/common/order.c (revision 8475e04352e630e4bd0f59a283286ee2475a14ce)
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 2008 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  * Part 1, Input processing.
39  */
40 /*
41  * Get the head section number
42  */
43 static Word
44 is_keylink_ok(Ifl_desc *ifl, Word keylink, Word limit)
45 {
46 	if ((keylink != SHN_BEFORE) && (keylink != SHN_AFTER)) {
47 		/*
48 		 * Range Check
49 		 */
50 		if ((keylink == 0) || (keylink >= limit)) {
51 			return (DBG_ORDER_LINK_OUTRANGE);
52 		}
53 
54 		/*
55 		 * The section pointed by keylink should not be an
56 		 * ordered section.
57 		 */
58 		if (ifl->ifl_isdesc[keylink]->is_shdr->sh_flags &
59 		    ALL_SHF_ORDER) {
60 			return (DBG_ORDER_INFO_ORDER);
61 		}
62 	}
63 	return (0);
64 }
65 
66 static Word
67 get_shfordered_dest(Ofl_desc *ofl, Ifl_desc *ifl, Word ndx, Word limit)
68 {
69 	Word t1_link = ndx, t2_link, ret_link;
70 	Is_desc *isp, *isp1, *isp2;
71 	int error = 0;
72 
73 	/*
74 	 * Check the sh_info of myself.
75 	 */
76 	isp = ifl->ifl_isdesc[ndx];
77 
78 	isp1 = isp;
79 	ret_link = t2_link = isp1->is_shdr->sh_link;
80 	t1_link = ndx;
81 	do {
82 		/*
83 		 * Check the validitiy of the link
84 		 */
85 		if (t2_link == 0 || t2_link >= limit) {
86 			error = DBG_ORDER_LINK_OUTRANGE;
87 			break;
88 		}
89 		isp2 = ifl->ifl_isdesc[t2_link];
90 
91 		/*
92 		 * Pointing to a bad ordered section ?
93 		 */
94 		if ((isp2->is_flags & FLG_IS_ORDERED) == 0) {
95 			error = DBG_ORDER_LINK_ERROR;
96 			break;
97 		}
98 
99 		/*
100 		 * Check sh_flag
101 		 */
102 		if (isp1->is_shdr->sh_flags != isp2->is_shdr->sh_flags) {
103 			error = DBG_ORDER_FLAGS;
104 			break;
105 		}
106 
107 		/*
108 		 * Check the validity of sh_info field.
109 		 */
110 		if ((error = is_keylink_ok(ifl,
111 		    isp->is_shdr->sh_info, limit)) != 0) {
112 			break;
113 		}
114 
115 		/*
116 		 * Can I break ?
117 		 */
118 		if (t1_link == t2_link)
119 			break;
120 
121 		/*
122 		 * Get the next link
123 		 */
124 		t1_link = t2_link;
125 		isp1 = ifl->ifl_isdesc[t1_link];
126 		ret_link = t2_link = isp1->is_shdr->sh_link;
127 
128 		/*
129 		 * Cyclic ?
130 		 */
131 		if (t2_link == ndx) {
132 			error = DBG_ORDER_CYCLIC;
133 			break;
134 		}
135 	/* CONSTANTCONDITION */
136 	} while (1);
137 
138 	if (error != 0) {
139 		ret_link = 0;
140 		DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error));
141 	}
142 	return (ret_link);
143 }
144 
145 /*
146  * Called from process_elf().
147  * This routine does the input processing of the ordered sections.
148  */
149 uintptr_t
150 ld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx, Word limit)
151 {
152 	Is_desc *	isp2, * isp = ifl->ifl_isdesc[ndx];
153 	Xword		shflags = isp->is_shdr->sh_flags;
154 	uint_t		keylink;
155 	Os_desc *	osp2, * osp;
156 	Word		dest_ndx;
157 	Sort_desc *	st;
158 	Listnode *	lnp;
159 	int		error = 0;
160 
161 	/*
162 	 * I might have been checked and marked error already.
163 	 */
164 	if ((isp->is_flags & FLG_IS_ORDERED) == 0)
165 		return (0);
166 
167 	if (shflags & SHF_ORDERED)
168 		keylink = isp->is_shdr->sh_info;
169 	else if (shflags & SHF_LINK_ORDER)
170 		keylink = isp->is_shdr->sh_link;
171 	else
172 		keylink = 0;
173 
174 	if ((error = is_keylink_ok(ifl, keylink, limit)) != 0) {
175 		DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error));
176 		isp->is_flags &= ~FLG_IS_ORDERED;
177 		if (isp->is_osdesc == NULL) {
178 			return ((uintptr_t)ld_place_section(ofl, isp,
179 			    isp->is_keyident, 0));
180 		}
181 		return ((uintptr_t)isp->is_osdesc);
182 	}
183 
184 	/*
185 	 * If SHF_ORDERED is in effect, search for our destination section based
186 	 * off of sh_link, otherwise follow the default rules for the
187 	 * destination section.
188 	 */
189 	if (shflags & SHF_ORDERED) {
190 		if ((dest_ndx = get_shfordered_dest(ofl, ifl,
191 		    ndx, limit)) == 0) {
192 			isp->is_flags &= ~FLG_IS_ORDERED;
193 			if (isp->is_osdesc == NULL) {
194 				return ((uintptr_t)ld_place_section(ofl, isp,
195 				    isp->is_keyident, 0));
196 			}
197 			return ((uintptr_t)isp->is_osdesc);
198 		}
199 	} else {
200 		/*
201 		 * SHF_LINK_ORDER coalesces into default sections, set dest_ndx
202 		 * to NULL to trigger this.
203 		 */
204 		dest_ndx = 0;
205 	}
206 
207 	/*
208 	 * Place the section into it's output section.
209 	 */
210 	if ((osp = isp->is_osdesc) == NULL) {
211 		if ((osp = ld_place_section(ofl, isp, isp->is_keyident,
212 		    dest_ndx)) == (Os_desc *)S_ERROR)
213 			return ((uintptr_t)S_ERROR);
214 		if (!osp)
215 			return (0);
216 	}
217 
218 	/*
219 	 * If the output section is not yet on the ordered
220 	 * list - place it on the list.
221 	 */
222 	osp2 = NULL;
223 	for (LIST_TRAVERSE(&ofl->ofl_ordered, lnp, osp2)) {
224 		if (osp2 == osp)
225 			break;
226 	}
227 
228 	if (osp != osp2) {
229 		if (list_appendc(&(ofl->ofl_ordered), osp) == 0)
230 			return ((uintptr_t)S_ERROR);
231 	}
232 
233 	/*
234 	 * Output section has been found - set up it's
235 	 * sorting information.
236 	 */
237 	if (osp->os_sort == 0) {
238 		if ((osp->os_sort = libld_calloc(1, sizeof (Sort_desc))) == 0)
239 			return (S_ERROR);
240 	}
241 	st = osp->os_sort;
242 
243 	if (keylink == SHN_BEFORE) {
244 		st->st_beforecnt++;
245 	} else if (keylink == SHN_AFTER) {
246 		st->st_aftercnt++;
247 	} else {
248 		st->st_ordercnt++;
249 		isp2 = ifl->ifl_isdesc[keylink];
250 		if (isp2->is_flags & FLG_IS_DISCARD) {
251 			eprintf(ofl->ofl_lml, ERR_FATAL,
252 			    MSG_INTL(MSG_FIL_BADORDREF), ifl->ifl_name,
253 			    isp->is_name, isp->is_scnndx, isp2->is_name,
254 			    isp2->is_scnndx);
255 			return (S_ERROR);
256 		}
257 
258 		/*
259 		 * Indicate that this ordered input section will require a sort
260 		 * key created.  Propagate the key requirement through to the
261 		 * associated output section, segment and file, to trigger the
262 		 * sort key creation.  See ld_sec_validate();
263 		 */
264 		isp2->is_flags |= FLG_IS_KEY;
265 
266 		osp2 = isp2->is_osdesc;
267 		osp2->os_flags |= FLG_OS_KEY;
268 		osp2->os_sgdesc->sg_flags |= FLG_SG_KEY;
269 
270 		ofl->ofl_flags |= FLG_OF_KEY;
271 	}
272 
273 	return ((uintptr_t)osp);
274 }
275 
276 /*
277  * Part 2, Sorting processing
278  */
279 
280 /*
281  * Traverse all segments looking for section ordering information that hasn't
282  * been used.  If found give a warning message to the user.  Also, check if
283  * there are any SHF_ORDERED key sections, and if so set up sort key values.
284  */
285 void
286 ld_sec_validate(Ofl_desc *ofl)
287 {
288 	Listnode	*lnp1;
289 	Sg_desc		*sgp;
290 	Word 		key = 1;
291 
292 	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) {
293 		Sec_order	*scop;
294 		Os_desc		*osp;
295 		Aliste		idx;
296 
297 		for (APLIST_TRAVERSE(sgp->sg_secorder, idx, scop)) {
298 			if ((scop->sco_flags & FLG_SGO_USED) == 0) {
299 				eprintf(ofl->ofl_lml, ERR_WARNING,
300 				    MSG_INTL(MSG_MAP_SECORDER),
301 				    sgp->sg_name, scop->sco_secname);
302 			}
303 		}
304 		if ((sgp->sg_flags & FLG_SG_KEY) == 0)
305 			continue;
306 
307 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx, osp)) {
308 			Listnode	*lnp2;
309 			Is_desc		*isp;
310 
311 			if ((osp->os_flags & FLG_OS_KEY) == 0)
312 				continue;
313 
314 			for (LIST_TRAVERSE(&(osp->os_isdescs), lnp2, isp)) {
315 				if (isp->is_flags & FLG_IS_KEY)
316 					isp->is_keyident = key++;
317 			}
318 		}
319 	}
320 }
321 
322 static int
323 setup_sortbuf(Os_desc *osp)
324 {
325 	Sort_desc	*st = osp->os_sort;
326 	Word		num_after = 0, num_before = 0, num_order = 0;
327 	Listnode	*lnp1;
328 	Is_desc		*isp;
329 
330 	if ((st == NULL) ||
331 	    ((st->st_ordercnt + st->st_beforecnt + st->st_aftercnt) == 0))
332 		return (0);
333 
334 	/*
335 	 * Get memory
336 	 */
337 	if (st->st_beforecnt != 0) {
338 		if ((st->st_before =
339 		    libld_calloc(st->st_beforecnt, sizeof (Is_desc *))) == 0)
340 			return (0);
341 	}
342 	if (st->st_ordercnt != 0) {
343 		if ((st->st_order =
344 		    libld_calloc(st->st_ordercnt, sizeof (Is_desc *))) == 0)
345 			return (0);
346 	}
347 	if (st->st_aftercnt != 0) {
348 		if ((st->st_after =
349 		    libld_calloc(st->st_aftercnt, sizeof (Is_desc *))) == 0)
350 			return (0);
351 	}
352 
353 	/*
354 	 * Set info.
355 	 */
356 	for (LIST_TRAVERSE(&(osp->os_isdescs), lnp1, isp)) {
357 		Word	keylink = 0;
358 
359 		if ((isp->is_flags & FLG_IS_ORDERED) == 0)
360 			continue;
361 
362 		if (isp->is_shdr->sh_flags & SHF_ORDERED)
363 			keylink = isp->is_shdr->sh_info;
364 		else if (isp->is_shdr->sh_flags & SHF_LINK_ORDER)
365 			keylink = isp->is_shdr->sh_link;
366 
367 		if (keylink == SHN_BEFORE)
368 			st->st_before[num_before++] = isp;
369 		else if (keylink == SHN_AFTER)
370 			st->st_after[num_after++] = isp;
371 		else
372 			st->st_order[num_order++] = isp;
373 	}
374 	return (1);
375 }
376 
377 static int
378 comp(const void *ss1, const void *ss2)
379 {
380 	Is_desc		*s1 = *((Is_desc **)ss1);
381 	Is_desc		*s2 = *((Is_desc **)ss2);
382 	Is_desc		*i1, *i2;
383 	Word		ndx1, ndx2;
384 
385 	if (s1->is_shdr->sh_flags & SHF_ORDERED)
386 		ndx1 = s1->is_shdr->sh_info;
387 	else
388 		ndx1 = s1->is_shdr->sh_link;
389 
390 	if (s2->is_shdr->sh_flags & SHF_ORDERED)
391 		ndx2 = s2->is_shdr->sh_info;
392 	else
393 		ndx2 = s2->is_shdr->sh_link;
394 
395 	i1 = s1->is_file->ifl_isdesc[ndx1];
396 	i2 = s2->is_file->ifl_isdesc[ndx2];
397 
398 	if (i1->is_keyident > i2->is_keyident)
399 		return (1);
400 	if (i1->is_keyident < i2->is_keyident)
401 		return (-1);
402 	return (0);
403 }
404 
405 uintptr_t
406 ld_sort_ordered(Ofl_desc *ofl)
407 {
408 	Listnode *lnp1;
409 	Os_desc *osp;
410 
411 	DBG_CALL(Dbg_sec_order_list(ofl, 0));
412 
413 	/*
414 	 * Sort Sections
415 	 */
416 	for (LIST_TRAVERSE(&ofl->ofl_ordered, lnp1, osp)) {
417 		int		i;
418 		List		islist;
419 		Listnode *	lnp2;
420 		Is_desc *	isp;
421 		Sort_desc *	st = osp->os_sort;
422 
423 		if (setup_sortbuf(osp) == 0)
424 			return (S_ERROR);
425 
426 		islist = osp->os_isdescs;
427 		osp->os_isdescs.head = 0;
428 		osp->os_isdescs.tail = 0;
429 
430 		/*
431 		 * Sorting.
432 		 * First Sort the ordered sections.
433 		 */
434 		if (st->st_ordercnt != 0)
435 			qsort((char *)st->st_order, st->st_ordercnt,
436 			    sizeof (Is_desc *), comp);
437 
438 		/*
439 		 * Place SHN_BEFORE at head of list
440 		 */
441 		for (i = 0; i < st->st_beforecnt; i++) {
442 			if (ld_append_isp(ofl, osp, st->st_before[i], 0) == 0)
443 				return (S_ERROR);
444 		}
445 
446 		/*
447 		 * Next come 'linked' ordered sections
448 		 */
449 		for (i = 0; i < st->st_ordercnt; i++) {
450 			if (ld_append_isp(ofl, osp, st->st_order[i], 0) == 0)
451 				return (S_ERROR);
452 		}
453 
454 		/*
455 		 * Now we list any sections which have no sorting
456 		 * specifications - in the order they were input.
457 		 *
458 		 * We use list_appendc() here instead of ld_append_isp(),
459 		 * because these items have already been inserted once, and
460 		 * we don't want any duplicate entries in osp->os_mstridescs.
461 		 */
462 		for (LIST_TRAVERSE(&islist, lnp2, isp)) {
463 			if (isp->is_flags & FLG_IS_ORDERED)
464 				continue;
465 			if (list_appendc(&(osp->os_isdescs),
466 			    isp) == 0)
467 				return (S_ERROR);
468 		}
469 
470 		/*
471 		 * And the end of the list are the SHN_AFTER sections.
472 		 */
473 		for (i = 0; i < st->st_aftercnt; i++) {
474 			if (ld_append_isp(ofl, osp, st->st_after[i], 0) == 0)
475 				return (S_ERROR);
476 		}
477 	}
478 	DBG_CALL(Dbg_sec_order_list(ofl, 1));
479 	return (0);
480 }
481