place.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 (c) 1988 AT&T
24 *	  All Rights Reserved
25 *
26 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
27 * Use is subject to license terms.
28 */
29#pragma ident	"%Z%%M%	%I%	%E% SMI"
30
31/*
32 * Map file parsing and input section to output segment mapping.
33 */
34#include	<stdio.h>
35#include	<string.h>
36#include	<debug.h>
37#include	"msg.h"
38#include	"_libld.h"
39
40/*
41 * Each time a section is placed, the function set_addralign()
42 * is called.  This function performs:
43 *
44 *  .	if the section is from an external file, check if this is empty or not.
45 *	If not, we know the segment this section will belong needs a program
46 *	header. (Of course, the program is needed only if this section falls
47 *	into a loadable segment.)
48 *  .	compute the Least Common Multiplier for setting the segment alignment.
49 */
50static void
51set_addralign(Ofl_desc *ofl, Os_desc *osp, Is_desc *isp)
52{
53	Shdr *		shdr = isp->is_shdr;
54
55	/*
56	 * If this section has data or will be assigned data
57	 * later, mark this segment not-empty.
58	 */
59	if ((shdr->sh_size != 0) ||
60	    ((isp->is_flags & FLG_IS_EXTERNAL) == 0))
61		osp->os_sgdesc->sg_flags |= FLG_SG_PHREQ;
62
63	if ((ofl->ofl_flags1 & FLG_OF1_NOHDR) &&
64	    (osp->os_sgdesc->sg_phdr).p_type != PT_LOAD)
65		return;
66
67	osp->os_sgdesc->sg_addralign =
68	    ld_lcm(osp->os_sgdesc->sg_addralign, shdr->sh_addralign);
69}
70
71/*
72 * Place a section into the appropriate segment.
73 */
74Os_desc *
75ld_place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link)
76{
77	Listnode *	lnp1, * lnp2;
78	Ent_desc *	enp;
79	Sg_desc	*	sgp;
80	Os_desc		**ospp, *osp;
81	Aliste		off1, off2;
82	int		os_ndx;
83	Shdr *		shdr = isp->is_shdr;
84	Xword		shflagmask, shflags = shdr->sh_flags;
85	Ifl_desc *	ifl = isp->is_file;
86
87	/*
88	 * Define any sections that must be thought of as referenced.  These
89	 * sections may not be referenced externaly in a manner ld(1) can
90	 * discover, but they must be retained (ie. not removed by -zignore).
91	 */
92	static const Msg RefSecs[] = {
93		MSG_SCN_INIT,		/* MSG_ORIG(MSG_SCN_INIT) */
94		MSG_SCN_FINI,		/* MSG_ORIG(MSG_SCN_FINI) */
95		MSG_SCN_EX_RANGES,	/* MSG_ORIG(MSG_SCN_EX_RANGES) */
96		MSG_SCN_EX_SHARED,	/* MSG_ORIG(MSG_SCN_EX_SHARED) */
97		MSG_SCN_CTORS,		/* MSG_ORIG(MSG_SCN_CTORS) */
98		MSG_SCN_DTORS,		/* MSG_ORIG(MSG_SCN_DTORS) */
99		MSG_SCN_EHFRAME,	/* MSG_ORIG(MSG_SCN_EHFRAME) */
100		MSG_SCN_EHFRAME_HDR,	/* MSG_ORIG(MSG_SCN_EHFRAME_HDR) */
101		MSG_SCN_JCR,		/* MSG_ORIG(MSG_SCN_JCR) */
102		0
103	};
104
105	DBG_CALL(Dbg_sec_in(ofl->ofl_lml, isp));
106
107	if ((shflags & SHF_GROUP) || (shdr->sh_type == SHT_GROUP)) {
108		Group_desc *	gdesc;
109
110		if ((gdesc = ld_get_group(ofl, isp)) == (Group_desc *)S_ERROR)
111			return ((Os_desc *)S_ERROR);
112
113		if (gdesc) {
114			DBG_CALL(Dbg_sec_group(ofl->ofl_lml, isp, gdesc));
115
116			/*
117			 * If this group is marked as discarded, then this
118			 * section needs to be discarded.
119			 */
120			if (gdesc->gd_flags & GRP_FLG_DISCARD) {
121				isp->is_flags |= FLG_IS_DISCARD;
122				return ((Os_desc *)0);
123			}
124		}
125
126		/*
127		 * SHT_GROUP sections can only be included into relocatable
128		 * objects.
129		 */
130		if (shdr->sh_type == SHT_GROUP) {
131			if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
132				isp->is_flags |= FLG_IS_DISCARD;
133				return ((Os_desc *)0);
134			}
135		}
136	}
137
138	/*
139	 * Always assign SHF_TLS sections to the DATA segment (and then the
140	 * PT_TLS embedded inside of there).
141	 */
142	if (shflags & SHF_TLS)
143		shflags |= SHF_WRITE;
144
145	/*
146	 * Traverse the entrance criteria list searching for a segment that
147	 * matches the input section we have.  If an entrance criterion is set
148	 * then there must be an exact match.  If we complete the loop without
149	 * finding a segment, then sgp will be NULL.
150	 */
151	sgp = NULL;
152	for (LIST_TRAVERSE(&ofl->ofl_ents, lnp1, enp)) {
153		if (enp->ec_segment &&
154		    (enp->ec_segment->sg_flags & FLG_SG_DISABLED))
155			continue;
156		if (enp->ec_type && (enp->ec_type != shdr->sh_type))
157			continue;
158		if (enp->ec_attrmask &&
159		    /* LINTED */
160		    (enp->ec_attrmask & enp->ec_attrbits) !=
161		    (enp->ec_attrmask & shflags))
162			continue;
163		if (enp->ec_name && (strcmp(enp->ec_name, isp->is_name) != 0))
164			continue;
165		if (enp->ec_files.head) {
166			char	*file;
167			int	found = 0;
168
169			if (isp->is_file == 0)
170				continue;
171
172			for (LIST_TRAVERSE(&(enp->ec_files), lnp2, file)) {
173				const char	*name = isp->is_file->ifl_name;
174
175				if (file[0] == '*') {
176					const char	*basename;
177
178					basename = strrchr(name, '/');
179					if (basename == NULL)
180						basename = name;
181					else if (basename[1] != '\0')
182						basename++;
183
184					if (strcmp(&file[1], basename) == 0) {
185						found++;
186						break;
187					}
188				} else {
189					if (strcmp(file, name) == 0) {
190						found++;
191						break;
192					}
193				}
194			}
195			if (!found)
196				continue;
197		}
198		break;
199	}
200
201	if ((sgp = enp->ec_segment) == 0)
202		sgp = ((Ent_desc *)(ofl->ofl_ents.tail->data))->ec_segment;
203
204	isp->is_basename = isp->is_name;
205
206	/*
207	 * Strip out the % from the section name in all cases except when '-r'
208	 * is used without '-M', and '-r' is used with '-M' without
209	 * the ?O flag.
210	 */
211	if (((ofl->ofl_flags & FLG_OF_RELOBJ) &&
212	    (sgp->sg_flags & FLG_SG_ORDER)) ||
213	    !(ofl->ofl_flags & FLG_OF_RELOBJ)) {
214		char	*cp;
215
216		if ((cp = strchr(isp->is_name, '%')) != NULL) {
217			char	*name;
218			size_t	size = (size_t)(cp - isp->is_name);
219
220			if ((name = libld_malloc(size + 1)) == 0)
221				return ((Os_desc *)S_ERROR);
222			(void) strncpy(name, isp->is_name, size);
223			cp = name + size;
224			*cp = '\0';
225			isp->is_name = name;
226		}
227		isp->is_txtndx = enp->ec_ndx;
228	}
229
230	/*
231	 * Assign a hash value now that the section name has been finalized.
232	 */
233	isp->is_namehash = sgs_str_hash(isp->is_name);
234
235	if (sgp->sg_flags & FLG_SG_ORDER)
236		enp->ec_flags |= FLG_EC_USED;
237
238	/*
239	 * If the link is not 0, then the input section is going to be appended
240	 * to the output section.  The append occurs at the input section
241	 * pointed to by the link.
242	 */
243	if (link != 0) {
244		osp = isp->is_file->ifl_isdesc[link]->is_osdesc;
245
246		/*
247		 * If this is a COMDAT section, then see if this
248		 * section is a keeper and/or if it is to be discarded.
249		 */
250		if (shdr->sh_type == SHT_SUNW_COMDAT) {
251			Listnode *	clist;
252			Is_desc *	cisp;
253
254			for (LIST_TRAVERSE(&(osp->os_comdats), clist, cisp)) {
255				if (strcmp(isp->is_basename, cisp->is_basename))
256					continue;
257
258				isp->is_flags |= FLG_IS_DISCARD;
259				DBG_CALL(Dbg_sec_discarded(ofl->ofl_lml,
260				    isp, cisp));
261				return (0);
262			}
263
264			/*
265			 * This is a new COMDAT section - so keep it.
266			 */
267			if (list_appendc(&(osp->os_comdats), isp) == 0)
268				return ((Os_desc *)S_ERROR);
269		}
270
271		/*
272		 * Set alignment
273		 */
274		set_addralign(ofl, osp, isp);
275
276		if (list_appendc(&(osp->os_isdescs), isp) == 0)
277			return ((Os_desc *)S_ERROR);
278
279		isp->is_osdesc = osp;
280		sgp = osp->os_sgdesc;
281
282		DBG_CALL(Dbg_sec_added(ofl->ofl_lml, osp, sgp));
283		return (osp);
284	}
285
286	/*
287	 * Determine if section ordering is turned on.  If so, return the
288	 * appropriate os_txtndx.  This information is derived from the
289	 * Sg_desc->sg_segorder list that was built up from the Mapfile.
290	 */
291	os_ndx = 0;
292	if (sgp->sg_secorder) {
293		Aliste		off;
294		Sec_order	**scopp;
295
296		for (ALIST_TRAVERSE(sgp->sg_secorder, off, scopp)) {
297			Sec_order	*scop = *scopp;
298
299			if (strcmp(scop->sco_secname, isp->is_name) == 0) {
300				scop->sco_flags |= FLG_SGO_USED;
301				os_ndx = scop->sco_index;
302				break;
303			}
304		}
305	}
306
307	/*
308	 * Setup the masks to flagout when matching sections
309	 */
310	shflagmask = ALL_SHF_ORDER;
311	if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0)
312		shflagmask = ALL_SHF_IGNORE;
313
314	/*
315	 * Traverse the input section list for the output section we have been
316	 * assigned.  If we find a matching section simply add this new section.
317	 */
318	off2 = 0;
319	for (ALIST_TRAVERSE(sgp->sg_osdescs, off1, ospp)) {
320		Shdr	*_shdr;
321
322		osp = *ospp;
323		_shdr = osp->os_shdr;
324
325		if ((ident == osp->os_scnsymndx) && (ident != M_ID_REL) &&
326		    (isp->is_namehash == osp->os_namehash) &&
327		    (shdr->sh_type != SHT_GROUP) &&
328		    (shdr->sh_type != SHT_SUNW_dof) &&
329		    ((shdr->sh_type == _shdr->sh_type) ||
330		    ((shdr->sh_type == SHT_SUNW_COMDAT) &&
331		    (_shdr->sh_type == SHT_PROGBITS))) &&
332		    ((shflags & ~shflagmask) ==
333		    (_shdr->sh_flags & ~shflagmask)) &&
334		    (strcmp(isp->is_name, osp->os_name) == 0)) {
335			/*
336			 * If this is a COMDAT section, determine if this
337			 * section is a keeper, and/or if it is to be discarded.
338			 */
339			if (shdr->sh_type == SHT_SUNW_COMDAT) {
340				Listnode *	clist;
341				Is_desc *	cisp;
342
343				for (LIST_TRAVERSE(&(osp->os_comdats),
344				    clist, cisp)) {
345					if (strcmp(isp->is_basename,
346					    cisp->is_basename))
347						continue;
348
349					isp->is_flags |= FLG_IS_DISCARD;
350					DBG_CALL(Dbg_sec_discarded(ofl->ofl_lml,
351					    isp, cisp));
352					return (0);
353				}
354
355				/*
356				 * This is a new COMDAT section - so keep it.
357				 */
358				if (list_appendc(&(osp->os_comdats), isp) == 0)
359					return ((Os_desc *)S_ERROR);
360			}
361
362			/*
363			 * Set alignment
364			 */
365			set_addralign(ofl, osp, isp);
366
367			/*
368			 * If this section is a non-empty TLS section indicate
369			 * that a PT_TLS program header is required.
370			 */
371			if ((shflags & SHF_TLS) && shdr->sh_size &&
372			    ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0))
373				ofl->ofl_flags |= FLG_OF_TLSPHDR;
374
375			/*
376			 * If is_txtndx is 0 then this section was not
377			 * seen in mapfile, so put it at the end.
378			 * If is_txtndx is not 0 and ?O is turned on
379			 * then check to see where this section should
380			 * be inserted.
381			 */
382			if ((sgp->sg_flags & FLG_SG_ORDER) && isp->is_txtndx) {
383				Listnode *	tlist;
384
385				tlist = list_where(&(osp->os_isdescs),
386				    isp->is_txtndx);
387				if (tlist != NULL) {
388					if (list_insertc(&(osp->os_isdescs),
389					    isp, tlist) == 0)
390						return ((Os_desc *)S_ERROR);
391				} else {
392					if (list_prependc(&(osp->os_isdescs),
393					    isp) == 0)
394						return ((Os_desc *)S_ERROR);
395				}
396			} else
397				if (list_appendc(&(osp->os_isdescs), isp) == 0)
398					return ((Os_desc *)S_ERROR);
399
400			isp->is_osdesc = osp;
401
402			/*
403			 * If this input section and file is associated to an
404			 * artificially referenced output section, make sure
405			 * they are marked as referenced also. This insures this
406			 * input section and file isn't eliminated when -zignore
407			 * is in effect.
408			 * See -zignore comments when creating a new output
409			 * section below.
410			 */
411			if (((ifl &&
412			    (ifl->ifl_flags & FLG_IF_IGNORE)) || DBG_ENABLED) &&
413			    (osp->os_flags & FLG_OS_SECTREF)) {
414				isp->is_flags |= FLG_IS_SECTREF;
415				if (ifl)
416					ifl->ifl_flags |= FLG_IF_FILEREF;
417			}
418
419			DBG_CALL(Dbg_sec_added(ofl->ofl_lml, osp, sgp));
420			return (osp);
421		}
422
423		/*
424		 * Do we need to worry about section ordering?
425		 */
426		if (os_ndx) {
427			if (osp->os_txtndx) {
428				if (os_ndx < osp->os_txtndx)
429					/* insert section here. */
430					break;
431				else {
432					off2 = off1;
433					continue;
434				}
435			} else {
436				/* insert section here. */
437				break;
438			}
439		} else if (osp->os_txtndx) {
440			off2 = off1;
441			continue;
442		}
443
444		/*
445		 * If the new sections identifier is less than that of the
446		 * present input section we need to insert the new section
447		 * at this point.
448		 */
449		if (ident < osp->os_scnsymndx)
450			break;
451
452		off2 = off1;
453	}
454
455	/*
456	 * We are adding a new output section.  Update the section header
457	 * count and associated string size.
458	 */
459	ofl->ofl_shdrcnt++;
460	if (st_insert(ofl->ofl_shdrsttab, isp->is_name) == -1)
461		return ((Os_desc *)S_ERROR);
462
463	/*
464	 * Create a new output section descriptor.
465	 */
466	if ((osp = libld_calloc(sizeof (Os_desc), 1)) == 0)
467		return ((Os_desc *)S_ERROR);
468	if ((osp->os_shdr = libld_calloc(sizeof (Shdr), 1)) == 0)
469		return ((Os_desc *)S_ERROR);
470
471	/*
472	 * We convert COMDAT sections to PROGBITS if this is the first
473	 * section of a output section.
474	 */
475	if (shdr->sh_type == SHT_SUNW_COMDAT) {
476		Shdr *	tshdr;
477
478		if ((tshdr = libld_malloc(sizeof (Shdr))) == 0)
479			return ((Os_desc *)S_ERROR);
480		*tshdr = *shdr;
481		isp->is_shdr = shdr = tshdr;
482		shdr->sh_type = SHT_PROGBITS;
483		if (list_appendc(&(osp->os_comdats), isp) == 0)
484			return ((Os_desc *)S_ERROR);
485	}
486
487	osp->os_shdr->sh_type = shdr->sh_type;
488	osp->os_shdr->sh_flags = shdr->sh_flags;
489	osp->os_shdr->sh_entsize = shdr->sh_entsize;
490	osp->os_name = isp->is_name;
491	osp->os_namehash = isp->is_namehash;
492	osp->os_txtndx = os_ndx;
493	osp->os_sgdesc = sgp;
494
495	if (ifl && (shdr->sh_type == SHT_PROGBITS)) {
496		/*
497		 * Try to preserved the intended meaning of sh_link/sh_info.
498		 * See the translate_link() in update.c.
499		 */
500		osp->os_shdr->sh_link = shdr->sh_link;
501		if (shdr->sh_flags & SHF_INFO_LINK)
502			osp->os_shdr->sh_info = shdr->sh_info;
503	}
504
505	/*
506	 * When -zignore is in effect, user supplied sections and files that are
507	 * not referenced from other sections, are eliminated from the object
508	 * being produced.  Some sections, although unreferenced, are special,
509	 * and must not be eliminated.  Determine if this new output section is
510	 * one of those special sections, and if so mark it artificially as
511	 * referenced.  Any input section and file associated to this output
512	 * section is also be marked as referenced, and thus won't be eliminated
513	 * from the final output.
514	 */
515	if (ifl && ((ofl->ofl_flags1 & FLG_OF1_IGNPRC) || DBG_ENABLED)) {
516		const Msg	*refsec;
517
518		for (refsec = RefSecs; *refsec; refsec++) {
519			if (strcmp(osp->os_name, MSG_ORIG(*refsec)) == 0) {
520				osp->os_flags |= FLG_OS_SECTREF;
521
522				if ((ifl->ifl_flags & FLG_IF_IGNORE) ||
523				    DBG_ENABLED) {
524					isp->is_flags |= FLG_IS_SECTREF;
525					ifl->ifl_flags |= FLG_IF_FILEREF;
526				}
527				break;
528			}
529		}
530	}
531
532	/*
533	 * Setions of SHT_GROUP are added to the ofl->ofl_osgroups
534	 * list - so that they can be updated as a group later.
535	 */
536	if (shdr->sh_type == SHT_GROUP) {
537		if (list_appendc(&ofl->ofl_osgroups, osp) == 0)
538			return ((Os_desc *)S_ERROR);
539	}
540
541	/*
542	 * If this section is a non-empty TLS section indicate that a PT_TLS
543	 * program header is required.
544	 */
545	if ((shflags & SHF_TLS) && shdr->sh_size &&
546	    ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0))
547		ofl->ofl_flags |= FLG_OF_TLSPHDR;
548
549	/*
550	 * If a non-allocatable section is going to be put into a loadable
551	 * segment then turn on the allocate bit for this section and warn the
552	 * user that we have done so.  This could only happen through the use
553	 * of a mapfile.
554	 */
555	if ((sgp->sg_phdr.p_type == PT_LOAD) &&
556	    ((osp->os_shdr->sh_flags & SHF_ALLOC) == 0)) {
557		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_SCN_NONALLOC),
558		    ofl->ofl_name, osp->os_name);
559		osp->os_shdr->sh_flags |= SHF_ALLOC;
560	}
561
562	/*
563	 * Retain this sections identifier for future comparisons when placing
564	 * a section (after all sections have been processed this variable will
565	 * be used to hold the sections symbol index as we don't need to retain
566	 * the identifier any more).
567	 */
568	osp->os_scnsymndx = ident;
569
570	/*
571	 * Set alignment
572	 */
573	set_addralign(ofl, osp, isp);
574
575	if (list_appendc(&(osp->os_isdescs), isp) == 0)
576		return ((Os_desc *)S_ERROR);
577
578	DBG_CALL(Dbg_sec_created(ofl->ofl_lml, osp, sgp));
579	isp->is_osdesc = osp;
580
581	if (off2) {
582		/*
583		 * Insert the new section after the section identified by off2.
584		 */
585		off2 += sizeof (Os_desc *);
586		if (alist_insert(&(sgp->sg_osdescs), &osp,
587		    sizeof (Os_desc *), AL_CNT_OSDESC, off2) == 0)
588			return ((Os_desc *)S_ERROR);
589	} else {
590		/*
591		 * Prepend this section to the section list.
592		 */
593		if (alist_insert(&(sgp->sg_osdescs), &osp,
594		    sizeof (Os_desc *), AL_CNT_OSDESC, ALO_DATA) == 0)
595			return ((Os_desc *)S_ERROR);
596	}
597	return (osp);
598}
599