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