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