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