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