xref: /illumos-gate/usr/src/cmd/sgs/libld/common/order.c (revision 7a088f03b431bdffa96c3b2175964d4d38420caa)
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  * 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 	Aliste		idx;
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 list, place it on
220 	 * the list.
221 	 */
222 	osp2 = NULL;
223 	for (APLIST_TRAVERSE(ofl->ofl_ordered, idx, osp2)) {
224 		if (osp2 == osp)
225 			break;
226 	}
227 
228 	if ((osp != osp2) && (aplist_append(&(ofl->ofl_ordered),
229 	    osp, AL_CNT_OFL_ORDERED) == NULL))
230 		return ((uintptr_t)S_ERROR);
231 
232 	/*
233 	 * Output section has been found - set up it's sorting information.
234 	 */
235 	if ((osp->os_sort == NULL) &&
236 	    ((osp->os_sort = libld_calloc(1, sizeof (Sort_desc))) == NULL))
237 		return (S_ERROR);
238 
239 	st = osp->os_sort;
240 
241 	if (keylink == SHN_BEFORE) {
242 		st->st_beforecnt++;
243 	} else if (keylink == SHN_AFTER) {
244 		st->st_aftercnt++;
245 	} else {
246 		st->st_ordercnt++;
247 		isp2 = ifl->ifl_isdesc[keylink];
248 		if (isp2->is_flags & FLG_IS_DISCARD) {
249 			eprintf(ofl->ofl_lml, ERR_FATAL,
250 			    MSG_INTL(MSG_FIL_BADORDREF), ifl->ifl_name,
251 			    isp->is_name, isp->is_scnndx, isp2->is_name,
252 			    isp2->is_scnndx);
253 			return (S_ERROR);
254 		}
255 
256 		/*
257 		 * Indicate that this ordered input section will require a sort
258 		 * key created.  Propagate the key requirement through to the
259 		 * associated output section, segment and file, to trigger the
260 		 * sort key creation.  See ld_sec_validate();
261 		 */
262 		isp2->is_flags |= FLG_IS_KEY;
263 
264 		osp2 = isp2->is_osdesc;
265 		osp2->os_flags |= FLG_OS_KEY;
266 		osp2->os_sgdesc->sg_flags |= FLG_SG_KEY;
267 
268 		ofl->ofl_flags |= FLG_OF_KEY;
269 	}
270 
271 	return ((uintptr_t)osp);
272 }
273 
274 /*
275  * Part 2, Sorting processing
276  */
277 
278 /*
279  * Traverse all segments looking for section ordering information that hasn't
280  * been used.  If found give a warning message to the user.  Also, check if
281  * there are any SHF_ORDERED key sections, and if so set up sort key values.
282  */
283 void
284 ld_sec_validate(Ofl_desc *ofl)
285 {
286 	Aliste		idx1;
287 	Sg_desc		*sgp;
288 	Word 		key = 1;
289 
290 	for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
291 		Sec_order	*scop;
292 		Os_desc		*osp;
293 		Aliste		idx2;
294 
295 		for (APLIST_TRAVERSE(sgp->sg_secorder, idx2, scop)) {
296 			if ((scop->sco_flags & FLG_SGO_USED) == 0) {
297 				eprintf(ofl->ofl_lml, ERR_WARNING,
298 				    MSG_INTL(MSG_MAP_SECORDER),
299 				    sgp->sg_name, scop->sco_secname);
300 			}
301 		}
302 		if ((sgp->sg_flags & FLG_SG_KEY) == 0)
303 			continue;
304 
305 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
306 			Aliste	idx3;
307 			Is_desc	*isp;
308 
309 			if ((osp->os_flags & FLG_OS_KEY) == 0)
310 				continue;
311 
312 			for (APLIST_TRAVERSE(osp->os_isdescs, idx3, isp)) {
313 				if (isp->is_flags & FLG_IS_KEY)
314 					isp->is_keyident = key++;
315 			}
316 		}
317 	}
318 }
319 
320 static int
321 setup_sortbuf(Os_desc *osp)
322 {
323 	Sort_desc	*st = osp->os_sort;
324 	Word		num_after = 0, num_before = 0, num_order = 0;
325 	Aliste		idx;
326 	Is_desc		*isp;
327 
328 	if ((st == NULL) ||
329 	    ((st->st_ordercnt + st->st_beforecnt + st->st_aftercnt) == 0))
330 		return (0);
331 
332 	/*
333 	 * Get memory
334 	 */
335 	if (st->st_beforecnt && ((st->st_before = libld_calloc(st->st_beforecnt,
336 	    sizeof (Is_desc *))) == NULL))
337 		return (0);
338 
339 	if (st->st_ordercnt && ((st->st_order = libld_calloc(st->st_ordercnt,
340 	    sizeof (Is_desc *))) == NULL))
341 		return (0);
342 
343 	if (st->st_aftercnt && ((st->st_after = libld_calloc(st->st_aftercnt,
344 	    sizeof (Is_desc *))) == NULL))
345 		return (0);
346 
347 	/*
348 	 * Set info.
349 	 */
350 	for (APLIST_TRAVERSE(osp->os_isdescs, idx, isp)) {
351 		Word	keylink = 0;
352 
353 		if ((isp->is_flags & FLG_IS_ORDERED) == 0)
354 			continue;
355 
356 		if (isp->is_shdr->sh_flags & SHF_ORDERED)
357 			keylink = isp->is_shdr->sh_info;
358 		else if (isp->is_shdr->sh_flags & SHF_LINK_ORDER)
359 			keylink = isp->is_shdr->sh_link;
360 
361 		if (keylink == SHN_BEFORE)
362 			st->st_before[num_before++] = isp;
363 		else if (keylink == SHN_AFTER)
364 			st->st_after[num_after++] = isp;
365 		else
366 			st->st_order[num_order++] = isp;
367 	}
368 	return (1);
369 }
370 
371 static int
372 comp(const void *ss1, const void *ss2)
373 {
374 	Is_desc		*s1 = *((Is_desc **)ss1);
375 	Is_desc		*s2 = *((Is_desc **)ss2);
376 	Is_desc		*i1, *i2;
377 	Word		ndx1, ndx2;
378 
379 	if (s1->is_shdr->sh_flags & SHF_ORDERED)
380 		ndx1 = s1->is_shdr->sh_info;
381 	else
382 		ndx1 = s1->is_shdr->sh_link;
383 
384 	if (s2->is_shdr->sh_flags & SHF_ORDERED)
385 		ndx2 = s2->is_shdr->sh_info;
386 	else
387 		ndx2 = s2->is_shdr->sh_link;
388 
389 	i1 = s1->is_file->ifl_isdesc[ndx1];
390 	i2 = s2->is_file->ifl_isdesc[ndx2];
391 
392 	if (i1->is_keyident > i2->is_keyident)
393 		return (1);
394 	if (i1->is_keyident < i2->is_keyident)
395 		return (-1);
396 	return (0);
397 }
398 
399 uintptr_t
400 ld_sort_ordered(Ofl_desc *ofl)
401 {
402 	Aliste	idx1;
403 	Os_desc *osp;
404 
405 	DBG_CALL(Dbg_sec_order_list(ofl, 0));
406 
407 	/*
408 	 * Sort Sections
409 	 */
410 	for (APLIST_TRAVERSE(ofl->ofl_ordered, idx1, osp)) {
411 		int		i;
412 		APlist		*islist = NULL;
413 		Aliste		idx2;
414 		Is_desc		*isp;
415 		Sort_desc	*st = osp->os_sort;
416 
417 		if (setup_sortbuf(osp) == 0)
418 			return (S_ERROR);
419 
420 		islist = osp->os_isdescs;
421 		osp->os_isdescs = NULL;
422 
423 		/*
424 		 * Sorting.
425 		 * First Sort the ordered sections.
426 		 */
427 		if (st->st_ordercnt != 0)
428 			qsort((char *)st->st_order, st->st_ordercnt,
429 			    sizeof (Is_desc *), comp);
430 
431 		/*
432 		 * Place SHN_BEFORE at head of list
433 		 */
434 		for (i = 0; i < st->st_beforecnt; i++) {
435 			if (ld_append_isp(ofl, osp, st->st_before[i], 0) == 0)
436 				return (S_ERROR);
437 		}
438 
439 		/*
440 		 * Next come 'linked' ordered sections
441 		 */
442 		for (i = 0; i < st->st_ordercnt; i++) {
443 			if (ld_append_isp(ofl, osp, st->st_order[i], 0) == 0)
444 				return (S_ERROR);
445 		}
446 
447 		/*
448 		 * Now we list any sections which have no sorting
449 		 * specifications - in the order they were input.
450 		 *
451 		 * We use aplist_append() here instead of ld_append_isp(),
452 		 * because these items have already been inserted once, and
453 		 * we don't want any duplicate entries in osp->os_mstridescs.
454 		 */
455 		for (APLIST_TRAVERSE(islist, idx2, isp)) {
456 			if (isp->is_flags & FLG_IS_ORDERED)
457 				continue;
458 			if (aplist_append(&(osp->os_isdescs),
459 			    isp, AL_CNT_OS_ISDESCS) == NULL)
460 				return (S_ERROR);
461 		}
462 
463 		/*
464 		 * And the end of the list are the SHN_AFTER sections.
465 		 */
466 		for (i = 0; i < st->st_aftercnt; i++) {
467 			if (ld_append_isp(ofl, osp, st->st_after[i], 0) == 0)
468 				return (S_ERROR);
469 		}
470 
471 		if (islist)
472 			free(islist);
473 	}
474 	DBG_CALL(Dbg_sec_order_list(ofl, 1));
475 	return (0);
476 }
477