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