xref: /illumos-gate/usr/src/cmd/sgs/libld/common/map_support.c (revision 08855964b9970604433f7b19dcd71cf5af5e5f14)
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 2010 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 
30 /*
31  * Copyright 2019 Joyent, Inc.
32  * Copyright 2022 Oxide Computer Company
33  */
34 
35 /*
36  * Map file parsing (Shared Support Code).
37  */
38 #include	<stdio.h>
39 #include	<errno.h>
40 #include	"msg.h"
41 #include	"_libld.h"
42 #include	"_map.h"
43 
44 /*
45  * Given a NULL terminated array of structures of arbitrary type, where
46  * each struct contains (among other fields) a character pointer field
47  * giving that struct a unique name, return the address of the struct
48  * that matches the given name.
49  *
50  * entry:
51  *	name - "Keyword" name to be found.
52  *	array - Base address of array
53  *	name_offset - Offset of the name field within the struct
54  *		type used by this array, as generated via
55  *		SGSOFFSETOF().
56  *	elt_size - sizeof the basic array element type
57  *
58  * exit:
59  *	Using a case insensitive comparison, name is compared to the
60  *	name of each element of the array. The address of the first
61  *	match found is returned. If the desired name is not found,
62  *	NULL is returned.
63  *
64  * note:
65  *	This routine is completely type-unsafe. The upside is that this
66  *	single routine is able to search arrays of arbitrary type, leaving
67  *	the caller free to structure their array in any way that is convenient
68  *	to solve the problem at hand.
69  */
70 #ifndef _ELF64
71 void *
72 ld_map_kwfind(const char *name, void *array, size_t name_offset,
73     size_t elt_size)
74 {
75 	for (; ; array = elt_size + (char *)array) {
76 		/* LINTED E_BAD_PTR_CAST_ALIGN */
77 		const char *arr_name = *((const char **)
78 		    (name_offset + (const char *) array));
79 
80 		if (arr_name == NULL)
81 			return (NULL);
82 
83 		if (strcasecmp(name, arr_name) == 0)
84 			return (array);
85 	}
86 
87 	/*NOTREACHED*/
88 }
89 #endif
90 
91 /*
92  * Given the same NULL terminated array accepted by ld_map_kwfind(), format
93  * the strings into a comma separated list of names.
94  *
95  * entry:
96  *	array - Base address of array
97  *	name_offset - Offset of the name field within the struct
98  *		type used by this array, as generated via
99  *		SGSOFFSETOF().
100  *	elt_size - sizeof the basic array element type
101  *	buf - Buffer to receive output
102  *	bufsize - sizeof(buf)
103  *
104  * exit:
105  *	As many of the names as will fit are formatted into buf. If all the
106  *	names do not fit, the remainder are quietly clipped. The caller must
107  *	ensure that there is sufficient room. buf is returned, for convenience
108  *	in using this function as an argument for printing.
109  */
110 #ifndef _ELF64
111 char *
112 ld_map_kwnames(void *array, size_t name_offset, size_t elt_size, char *buf,
113     size_t bufsize)
114 {
115 	size_t	cnt = 0;
116 	size_t	len;
117 	char	*str = buf;
118 
119 	for (; bufsize > 1; array = elt_size + (char *)array, cnt++) {
120 		/* LINTED E_BAD_PTR_CAST_ALIGN */
121 		const char *arr_name = *((const char **)
122 		    (name_offset + (const char *) array));
123 
124 		if (arr_name == NULL)
125 			break;
126 
127 		if (cnt > 0) {
128 			if (bufsize < 3)
129 				break;
130 			*str++ = ',';
131 			*str++ = ' ';
132 			bufsize -= 2;
133 			*(str + 1) = '\0';
134 		}
135 
136 		len = strlcpy(str, arr_name, bufsize);
137 		if (len >= bufsize)
138 			break;
139 		str += len;
140 		bufsize -= len;
141 	}
142 
143 	return (buf);
144 }
145 #endif
146 
147 /*
148  * Create a pseudo input file descriptor to represent the specified Mapfile.
149  * An input descriptor is required any time a symbol is generated.
150  *
151  * entry:
152  *	mf - Mapfile descriptor.
153  *
154  * exit:
155  *	If an input descriptor was already created for this mapfile
156  *	by a previous call, it is returned. Otherwise, a new descriptor
157  *	is created, entered into the mapfile descriptor, and returned.
158  *
159  *	Success is indicated by a non-NULL return value, failure by NULL.
160  */
161 Ifl_desc *
162 ld_map_ifl(Mapfile *mf)
163 {
164 	Ifl_desc	*ifl;
165 
166 	/*
167 	 * If we've already created a pseudo input descriptor for this
168 	 * mapfile, reuse it.
169 	 */
170 	if (mf->mf_ifl != NULL)
171 		return (mf->mf_ifl);
172 
173 	if ((ifl = libld_calloc(1, sizeof (Ifl_desc))) == NULL)
174 		return (NULL);
175 	ifl->ifl_name = mf->mf_name;
176 	ifl->ifl_flags = (FLG_IF_MAPFILE | FLG_IF_NEEDED | FLG_IF_FILEREF);
177 	if ((ifl->ifl_ehdr = libld_calloc(1, sizeof (Ehdr))) == NULL)
178 		return (NULL);
179 	ifl->ifl_ehdr->e_type = ET_REL;
180 
181 	if (aplist_append(&mf->mf_ofl->ofl_objs, ifl, AL_CNT_OFL_OBJS) == NULL)
182 		return (NULL);
183 
184 	mf->mf_ifl = ifl;
185 	return (mf->mf_ifl);
186 }
187 
188 /*
189  * Given a capability tag type, set the override bit in the output descriptor.
190  * This prevents the use of capability values of that type from the input
191  * objects.
192  */
193 void
194 ld_map_cap_set_ovflag(Mapfile *mf, Word type)
195 {
196 	/*
197 	 * Map capability tag to the corresponding output descriptor
198 	 * override flag.
199 	 */
200 	static ofl_flag_t override_flag[CA_SUNW_NUM] = {
201 		0,			/* CA_SUNW_NULL */
202 		FLG_OF1_OVHWCAP1,	/* CA_SUNW_HW_1 */
203 		FLG_OF1_OVSFCAP1,	/* CA_SUNW_SF_1 */
204 		FLG_OF1_OVHWCAP2,	/* CA_SUNW_HW_2 */
205 		FLG_OF1_OVPLATCAP,	/* CA_SUNW_PLAT */
206 		FLG_OF1_OVMACHCAP,	/* CA_SUNW_MACH */
207 		FLG_OF1_OVIDCAP,	/* CA_SUNW_ID */
208 		FLG_OF1_OVHWCAP3	/* CA_SUNW_HW_3 */
209 	};
210 #if CA_SUNW_NUM != (CA_SUNW_HW_3 + 1)
211 #error "CA_SUNW_NUM has grown"
212 #endif
213 	mf->mf_ofl->ofl_flags1 |= override_flag[type];
214 }
215 
216 /*
217  * Sanity check the given capability bitmask.
218  */
219 Boolean
220 ld_map_cap_sanitize(Mapfile *mf, Word type, Capmask *capmask)
221 {
222 	elfcap_mask_t	mask;
223 
224 	switch (type) {
225 	case CA_SUNW_SF_1:
226 		/*
227 		 * Unlike hardware capabilities, we do not allow setting
228 		 * software capability bits that do not have known definitions.
229 		 * Software capability tokens have to be validated as a unit
230 		 * as the bits can affect each others meaning (see sf1_cap()
231 		 * in files.c).
232 		 */
233 		if ((mask = (capmask->cm_val & ~SF1_SUNW_MASK)) != 0) {
234 			mf_warn(mf, MSG_INTL(MSG_MAP_BADSF1),
235 			    EC_XWORD(mask));
236 			capmask->cm_val &= SF1_SUNW_MASK;
237 		}
238 		if ((capmask->cm_val &
239 		    (SF1_SUNW_FPKNWN | SF1_SUNW_FPUSED)) == SF1_SUNW_FPUSED) {
240 			mf_warn(mf, MSG_INTL(MSG_MAP_BADSF1),
241 			    EC_XWORD(SF1_SUNW_FPUSED));
242 			capmask->cm_val &= ~SF1_SUNW_FPUSED;
243 		}
244 #if	!defined(_ELF64)
245 		/*
246 		 * The SF1_SUNW_ADDR32 software capability is only meaningful
247 		 * when building a 64-bit object.  Warn the user, and remove the
248 		 * setting, if we're building a 32-bit object.
249 		 */
250 		if (capmask->cm_val & SF1_SUNW_ADDR32) {
251 			mf_warn0(mf, MSG_INTL(MSG_MAP_INADDR32SF1));
252 			capmask->cm_val &= ~SF1_SUNW_ADDR32;
253 		}
254 #endif
255 	}
256 
257 	return (TRUE);
258 }
259 
260 /*
261  * Return the shared object control definition structure (ofl_socntl)
262  * for the specified object, creating one if necessary.
263  *
264  * entry:
265  *	mf - Mapfile descriptor
266  *	obj_name - Name of object
267  *
268  * exit:
269  *	Returns the pointer to the definition structure, or NULL on error.
270  */
271 Sdf_desc *
272 ld_map_dv(Mapfile *mf, const char *obj_name)
273 {
274 	Sdf_desc	*sdf;
275 
276 	/*
277 	 * If a shared object definition for this file already exists use it,
278 	 * otherwise allocate a new descriptor.
279 	 */
280 	if ((sdf = sdf_find(obj_name, mf->mf_ofl->ofl_socntl)) == NULL) {
281 		if ((sdf = sdf_add(obj_name, &mf->mf_ofl->ofl_socntl)) ==
282 		    (Sdf_desc *)S_ERROR)
283 			return (NULL);
284 		sdf->sdf_rfile = mf->mf_name;
285 	}
286 
287 	DBG_CALL(Dbg_map_dv(mf->mf_ofl->ofl_lml, sdf->sdf_name,
288 	    mf->mf_lineno));
289 	return (sdf);
290 }
291 
292 
293 Boolean
294 ld_map_dv_entry(Mapfile *mf, Sdf_desc *sdf, Boolean require,
295     const char *version)
296 {
297 	Sdv_desc	sdv;
298 
299 	sdv.sdv_name = version;
300 	sdv.sdv_ref = mf->mf_name;
301 	sdv.sdv_flags = 0;
302 
303 
304 	if (require) {
305 		/*
306 		 * Add a VERNEED entry for the specified version
307 		 * from this object:
308 		 *
309 		 *	MapfileVersion	Syntax
310 		 *	----------------------------------------
311 		 *	1		obj - $ADDVERS=version;
312 		 *	2		DEPENDENCY obj { REQUIRE=version };
313 		 */
314 		sdf->sdf_flags |= FLG_SDF_ADDVER;
315 
316 		if (alist_append(&sdf->sdf_verneed, &sdv, sizeof (Sdv_desc),
317 		    AL_CNT_SDF_VERSIONS) == NULL)
318 			return (FALSE);
319 	} else {		/* Allow */
320 		/*
321 		 * Allow linking to symbols found in this version, or
322 		 * from the versions it inherits from.
323 		 *
324 		 *	MapfileVersion	Syntax
325 		 *	----------------------------------------
326 		 *	1		obj - version;
327 		 *	2		DEPENDENCY obj { ALLOW=version };
328 		 */
329 		sdf->sdf_flags |= FLG_SDF_SELECT;
330 
331 		if (alist_append(&sdf->sdf_vers, &sdv, sizeof (Sdv_desc),
332 		    AL_CNT_SDF_VERSIONS) == NULL)
333 			return (FALSE);
334 	}
335 
336 	DBG_CALL(Dbg_map_dv_entry(mf->mf_ofl->ofl_lml, mf->mf_lineno,
337 	    require, version));
338 
339 	return (TRUE);
340 }
341 
342 /*
343  * Given a segment descriptor, return its index.
344  *
345  * entry:
346  *	mf - Mapfile descriptor
347  *	sgp - Segment for which index is desired
348  *
349  * exit:
350  *	Index of segment is returned.
351  */
352 Xword
353 ld_map_seg_index(Mapfile *mf, Sg_desc *sgp)
354 {
355 	Aliste		idx;
356 	Sg_desc		*sgp2;
357 	Ofl_desc	*ofl = mf->mf_ofl;
358 
359 	for (APLIST_TRAVERSE(ofl->ofl_segs, idx, sgp2))
360 		if (sgp == sgp2)
361 			break;
362 
363 	return (idx);
364 }
365 
366 /*
367  * Add a section name to the output section sort list for the given
368  * segment.
369  *
370  * entry:
371  *	mf - Mapfile descriptor
372  *	sgp - Segment in question
373  *	sec_name - Name of section to be added.
374  *
375  * exit:
376  *	Returns TRUE for success, FALSE for failure.
377  */
378 Boolean
379 ld_map_seg_os_order_add(Mapfile *mf, Sg_desc *sgp, const char *sec_name)
380 {
381 	Aliste		idx;
382 	Sec_order	*scop;
383 
384 	/*
385 	 * Make sure it's not already on the list
386 	 */
387 	for (ALIST_TRAVERSE(sgp->sg_os_order, idx, scop))
388 		if (strcmp(scop->sco_secname, sec_name) == 0) {
389 			mf_fatal(mf, MSG_INTL(MSG_MAP_DUP_OS_ORD), sec_name);
390 			return (FALSE);
391 		}
392 
393 
394 	scop = alist_append(&sgp->sg_os_order, NULL, sizeof (Sec_order),
395 	    AL_CNT_SG_SECORDER);
396 	if (scop == NULL)
397 		return (FALSE);
398 
399 	scop->sco_secname = sec_name;
400 
401 	DBG_CALL(Dbg_map_seg_os_order(mf->mf_ofl->ofl_lml, sgp, sec_name,
402 	    alist_nitems(sgp->sg_os_order), mf->mf_lineno));
403 
404 	/*
405 	 * Output section ordering is a relatively expensive operation,
406 	 * and one that is generally not used. In order to avoid needless
407 	 * work, the FLG_OF_OS_ORDER must be set when it will be needed.
408 	 * The section we just added needs this flag to be set. However,
409 	 * it is possible that a subsequent mapfile directive may come
410 	 * along and clear the order list, making it unnecessary.
411 	 *
412 	 * Instead of setting it here, we do a final pass over the segments
413 	 * in ld_map_finalize() and set it there if a segment with sorting
414 	 * requirements is seen.
415 	 */
416 
417 	return (TRUE);
418 }
419 
420 /*
421  * Add a size symbol to a segment
422  *
423  * entry:
424  *	mf - Mapfile descriptor
425  *	sgp - Segment descriptor
426  *	eq_tol - Type of assignment: TK_EQUAL, or TK_PLUSEQ
427  *	symname - Name of symbol. Must be in stable static storage
428  *		that can be retained.
429  *
430  * exit:
431  *	On success, the symbol has been added and TRUE is returned.
432  *	Otherwise an error is reported and FALSE is returned.
433  */
434 Boolean
435 ld_map_seg_size_symbol(Mapfile *mf, Sg_desc *sgp, Token eq_tok,
436     const char *symname)
437 {
438 	Sym		*sym;		/* New symbol pointer */
439 	Sym_desc	*sdp;		/* New symbol node pointer */
440 	Ifl_desc	*ifl;		/* Dummy input file structure */
441 	avl_index_t	where;
442 	Ofl_desc	*ofl = mf->mf_ofl;
443 
444 	/*
445 	 * We don't allow resetting the list of size symbols, so if the
446 	 * operator is TK_EQUAL and the list is not empty, issue an error.
447 	 *
448 	 * If we want to lift this restriction, we would have to save the
449 	 * size symbols and enter them from ld_map_post_process(). Doing that
450 	 * well would require a significant overhead in saved error reporting
451 	 * state, and interactions with the same symbols created by symbol
452 	 * directives. As size symbols are of little practical use, and are
453 	 * maintained primarily for backward compatibility with SysV, we have
454 	 * decided not to do that, but to create the symbols as the mapfiles
455 	 * are processed, and to disallow later attempts to remove them.
456 	 */
457 	if ((eq_tok == TK_EQUAL) && (aplist_nitems(sgp->sg_sizesym) > 0)) {
458 		mf_fatal(mf, MSG_INTL(MSG_MAP_SEGSIZE), sgp->sg_name);
459 		return (FALSE);
460 	}
461 
462 	/*
463 	 * Make sure we have a pseudo file descriptor to associate to the
464 	 * symbol.
465 	 */
466 	if ((ifl = ld_map_ifl(mf)) == NULL)
467 		return (FALSE);
468 
469 	/*
470 	 * Make sure the symbol doesn't already exist.  It is possible that the
471 	 * symbol has been scoped or versioned, in which case it does exist
472 	 * but we can freely update it here.
473 	 */
474 	if ((sdp = ld_sym_find(symname, SYM_NOHASH, &where, ofl)) == NULL) {
475 		Word hval;
476 
477 		if ((sym = libld_calloc(1, sizeof (Sym))) == NULL)
478 			return (FALSE);
479 		sym->st_shndx = SHN_ABS;
480 		sym->st_size = 0;
481 		sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
482 
483 		DBG_CALL(Dbg_map_size_new(ofl->ofl_lml, symname,
484 		    sgp->sg_name, mf->mf_lineno));
485 		/* LINTED */
486 		hval = (Word)elf_hash(symname);
487 		if ((sdp = ld_sym_enter(symname, sym, hval, ifl, ofl, 0,
488 		    SHN_ABS, (FLG_SY_SPECSEC | FLG_SY_GLOBREF), &where)) ==
489 		    (Sym_desc *)S_ERROR)
490 			return (FALSE);
491 		sdp->sd_flags &= ~FLG_SY_CLEAN;
492 		DBG_CALL(Dbg_map_symbol(ofl, sdp));
493 	} else {
494 		sym = sdp->sd_sym;
495 
496 		if (sym->st_shndx == SHN_UNDEF) {
497 			sdp->sd_shndx = sym->st_shndx = SHN_ABS;
498 			sdp->sd_flags |= FLG_SY_SPECSEC;
499 			sym->st_size = 0;
500 			sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
501 
502 			sdp->sd_flags &= ~FLG_SY_MAPREF;
503 
504 			DBG_CALL(Dbg_map_size_old(ofl, sdp,
505 			    sgp->sg_name, mf->mf_lineno));
506 		} else {
507 			mf_fatal(mf, MSG_INTL(MSG_MAP_SYMDEF1),
508 			    demangle(sdp->sd_name), sdp->sd_file->ifl_name,
509 			    MSG_INTL(MSG_MAP_DIFF_SYMMUL));
510 			return (FALSE);
511 		}
512 	}
513 
514 	/*
515 	 * Assign the symbol to the segment.
516 	 */
517 	if (aplist_append(&sgp->sg_sizesym, sdp, AL_CNT_SG_SIZESYM) == NULL)
518 		return (FALSE);
519 
520 	return (TRUE);
521 }
522 
523 /*
524  * Allocate a zeroed segment descriptor.
525  *
526  * exit:
527  *	Returns pointer to the descriptor on success, NULL on failure.
528  *	The contents of the returned descriptor have been zeroed.
529  *	The returned descriptor is not added to the segment list
530  *	(ofl_segs). That is done using ld_map_seg_insert().
531  */
532 Sg_desc *
533 ld_map_seg_alloc(const char *name, Word p_type, sg_flags_t sg_flags)
534 {
535 	Sg_desc	*sgp;
536 
537 	if ((sgp = libld_calloc(1, sizeof (Sg_desc))) == NULL)
538 		return (NULL);
539 	sgp->sg_phdr.p_type = p_type;
540 	sgp->sg_name = name;
541 	sgp->sg_flags = sg_flags;
542 
543 	return (sgp);
544 }
545 
546 /*
547  * Return the PT_SUNWSTACK segment descriptor from the ofl_segs list.
548  * This segment is part of the default set and cannot be removed, so
549  * this routine will always succeed.
550  *
551  * exit:
552  *	The descriptor is located, a DBG_STATE_MOD_BEFORE debug
553  *	message issued, the FLG_SG_DISABLED flag is cleared, and the
554  *	descriptor pointer returned.
555  */
556 Sg_desc *
557 ld_map_seg_stack(Mapfile *mf)
558 {
559 	Ofl_desc	*ofl = mf->mf_ofl;
560 	Sg_desc		*sgp;
561 	Aliste		idx;
562 
563 	/*
564 	 * The stack is established by exec(), using the executable's program
565 	 * headers, before any sharable objects are loaded. If there is a
566 	 * PT_SUNWSTACK program header, exec() will act on it. As such, stack
567 	 * program headers are normally only applicable to executables.
568 	 *
569 	 * However, ELF allows a sharable object with an interpreter to
570 	 * be executed directly, and in this extremely rare case, the
571 	 * PT_SUNWSTACK program header would have meaning. Rather than
572 	 * second guess user intent, we simply create it on demand for any
573 	 * dynamic object, trusting that the user has a good reason for it.
574 	 */
575 	for (APLIST_TRAVERSE(ofl->ofl_segs, idx, sgp))
576 		if (sgp->sg_phdr.p_type == PT_SUNWSTACK) {
577 			DBG_CALL(Dbg_map_seg(mf->mf_ofl, DBG_STATE_MOD_BEFORE,
578 			    idx, sgp, mf->mf_lineno));
579 			sgp->sg_flags &= ~FLG_SG_DISABLED;
580 			return (sgp);
581 		}
582 
583 	/*NOTREACHED*/
584 	return (NULL);
585 }
586 
587 /*
588  * Finish the initialization of a new segment descriptor allocated by
589  * ld_map_seg_alloc(), and enter it into the segment list.
590  *
591  * entry:
592  *	mf - Mapfile descriptor
593  *	seg_type - One of DBG_SEG_NEW or DBG_SEG_NEW_IMPLICIT
594  *	ins_head - If TRUE, the new segment goes at the front of
595  *		others of its type. If FALSE, it goes at the end.
596  *	sgp - Segment descriptor to enter.
597  *	where - Insertion point, initialized by a previous (failed) call to
598  *		ld_seg_lookup(). Ignored if the segment has a NULL sg_name.
599  *
600  * exit:
601  *	On success, returns SEG_INS_OK. A non-fatal error is indicated with
602  *	a return value of SEG_INS_SKIP, in which case the descriptor is
603  *	not entered, but the user is expected to discard it and continue
604  *	running. On failure, returns SEG_INS_FAIL.
605  *
606  * note:
607  *	This routine will modify the contents of the descriptor referenced
608  *	by sgp_tmpl before allocating the new descriptor. The caller must
609  *	not expect it to be unmodified.
610  */
611 ld_map_seg_ins_t
612 ld_map_seg_insert(Mapfile *mf, dbg_state_t dbg_state, Sg_desc *sgp,
613     avl_index_t where)
614 {
615 	Ofl_desc	*ofl = mf->mf_ofl;
616 	Aliste		idx;
617 	Sg_desc		*sgp2;		/* temp segment descriptor pointer */
618 	int		ins_head;
619 	Xword		sg_ndx;
620 
621 	/*
622 	 * If specific fields have not been supplied via
623 	 * map_equal(), make sure defaults are supplied.
624 	 */
625 	if (((sgp->sg_flags & FLG_SG_P_TYPE) == 0) &&
626 	    (sgp->sg_phdr.p_type == PT_NULL)) {
627 		/*
628 		 * Default to a loadable segment.
629 		 */
630 		sgp->sg_phdr.p_type = PT_LOAD;
631 		sgp->sg_flags |= FLG_SG_P_TYPE;
632 	}
633 	if (sgp->sg_phdr.p_type == PT_LOAD) {
634 		if ((sgp->sg_flags & FLG_SG_P_FLAGS) == 0) {
635 			/*
636 			 * Default to read/write and execute.
637 			 */
638 			sgp->sg_phdr.p_flags = PF_R + PF_W + PF_X;
639 			sgp->sg_flags |= FLG_SG_P_FLAGS;
640 		}
641 		if ((sgp->sg_flags & FLG_SG_P_ALIGN) == 0) {
642 			/*
643 			 * Default to segment alignment
644 			 */
645 			sgp->sg_phdr.p_align = ld_targ.t_m.m_segm_align;
646 			sgp->sg_flags |= FLG_SG_P_ALIGN;
647 		}
648 	}
649 
650 	/*
651 	 * Determine where the new item should be inserted in
652 	 * the segment descriptor list.
653 	 */
654 	switch (sgp->sg_phdr.p_type) {
655 	case PT_LOAD:
656 		if (sgp->sg_flags & FLG_SG_EMPTY)
657 			sgp->sg_id = SGID_TEXT_EMPTY;
658 		else
659 			sgp->sg_id = SGID_TEXT;
660 		break;
661 	case PT_NULL:
662 		if (sgp->sg_flags & FLG_SG_EMPTY)
663 			sgp->sg_id = SGID_NULL_EMPTY;
664 		else
665 			sgp->sg_id = SGID_NULL;
666 		break;
667 	case PT_NOTE:
668 		sgp->sg_id = SGID_NOTE;
669 		break;
670 	default:
671 		mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSEGTYP),
672 		    EC_WORD(sgp->sg_phdr.p_type));
673 		return (SEG_INS_FAIL);
674 	}
675 
676 	/*
677 	 * Add the descriptor to the segment list. In the v1 syntax,
678 	 * new sections are added at the head of their type, while in
679 	 * the newer syntax, they go at the end of their type.
680 	 */
681 	sg_ndx = 0;
682 	ins_head = (mf->mf_version == MFV_SYSV);
683 	for (APLIST_TRAVERSE(ofl->ofl_segs, idx, sgp2)) {
684 		if (ins_head) {	/* Insert before the others of its type */
685 			if (sgp->sg_id > sgp2->sg_id) {
686 				sg_ndx++;
687 				continue;
688 			}
689 		} else {	/* Insert after the others of its type */
690 			if (sgp->sg_id >= sgp2->sg_id) {
691 				sg_ndx++;
692 				continue;
693 			}
694 		}
695 		break;
696 	}
697 	if (aplist_insert(&ofl->ofl_segs, sgp, AL_CNT_SEGMENTS, idx) == NULL)
698 		return (SEG_INS_FAIL);
699 	if (sgp->sg_name != NULL)
700 		avl_insert(&ofl->ofl_segs_avl, sgp, where);
701 
702 	DBG_CALL(Dbg_map_seg(ofl, dbg_state, sg_ndx, sgp, mf->mf_lineno));
703 	return (SEG_INS_OK);
704 }
705 
706 /*
707  * Add an entrance criteria record for the specified segment
708  *
709  * entry:
710  *	mf - Mapfile descriptor
711  *	sgp - Segment for which a new entrance criteria record is needed
712  *	name - NULL, or name by which the entrance criteria can be referenced.
713  *
714  * exit:
715  *	On success, a pointer to the new entrace criteria record is
716  *	returned, the contents of which have been zeroed. On failure,
717  *	NULL is returned.
718  */
719 Ent_desc *
720 ld_map_seg_ent_add(Mapfile *mf, Sg_desc *sgp, const char *name)
721 {
722 	Ent_desc	*enp;
723 	avl_index_t	where;
724 	Ofl_desc	*ofl = mf->mf_ofl;
725 
726 	if ((name != NULL) &&
727 	    (ld_ent_lookup(mf->mf_ofl, name, &where) != NULL)) {
728 		mf_fatal(mf, MSG_INTL(MSG_MAP_DUPNAMENT), name);
729 		return (NULL);
730 	}
731 
732 	/* Allocate and initialize the entrace criteria descriptor */
733 	if ((enp = libld_calloc(1, sizeof (*enp))) == NULL)
734 		return (NULL);
735 	enp->ec_name = name;
736 	enp->ec_segment = sgp;	 /* Tie criteria to segment */
737 
738 
739 	/*
740 	 * Insert into the APlist. The mf_ec_insndx field for each mapfile
741 	 * starts at 0, and is incremented with each insertion. This means
742 	 * that the entrance criteria for each mapfile go to the head of
743 	 * the list, but that within a single mapfile, they are inserted in
744 	 * the order they are seen.
745 	 */
746 	if (aplist_insert(&ofl->ofl_ents, enp, AL_CNT_OFL_ENTRANCE,
747 	    mf->mf_ec_insndx) == NULL)
748 		return (NULL);
749 	mf->mf_ec_insndx++;
750 
751 	/*
752 	 * If the entrance criteria is named insert it into the AVL tree
753 	 * as well. This provides O(logN) lookups by name.
754 	 */
755 	if (name != NULL)
756 		avl_insert(&ofl->ofl_ents_avl, enp, where);
757 
758 	return (enp);
759 }
760 
761 Boolean
762 ld_map_seg_ent_files(Mapfile *mf, Ent_desc *enp, Word ecf_type, const char *str)
763 {
764 	Ent_desc_file	edf;
765 
766 	/*
767 	 * The v1 sysv syntax can let an empty string get in, consisting of
768 	 * just a '*' where the '*' is interpreted as 'basename'.
769 	 */
770 	if (str[0] == '\0') {
771 		mf_fatal0(mf, MSG_INTL(MSG_MAP_MALFORM));
772 		return (FALSE);
773 	}
774 
775 	/* Basename or objname string must not contain a path separator (/) */
776 	if ((ecf_type != TYP_ECF_PATH) && (strchr(str, '/') != NULL)) {
777 		const char *msg = (ecf_type == TYP_ECF_BASENAME) ?
778 		    MSG_INTL(MSG_MAP_BADBNAME) : MSG_INTL(MSG_MAP_BADONAME);
779 
780 		mf_fatal(mf, msg, str);
781 		return (FALSE);
782 	}
783 
784 	edf.edf_flags = ecf_type;
785 	edf.edf_name = str;
786 	edf.edf_name_len = strlen(edf.edf_name);
787 
788 	/* Does it have an archive member suffix? */
789 	if ((edf.edf_name[edf.edf_name_len - 1] == ')') &&
790 	    (strrchr(edf.edf_name, '(') != NULL))
791 		edf.edf_flags |= FLG_ECF_ARMEMBER;
792 
793 	if (alist_append(&enp->ec_files, &edf, sizeof (edf),
794 	    AL_CNT_EC_FILES) == NULL)
795 		return (FALSE);
796 
797 	/*
798 	 * Note that an entrance criteria requiring file name matching exists
799 	 * in the system. This is used by ld_place_path_info_init() to
800 	 * skip Place_pathinfo initialization in cases where there are
801 	 * no entrance criteria that will use the results.
802 	 */
803 	mf->mf_ofl->ofl_flags |= FLG_OF_EC_FILES;
804 
805 	return (TRUE);
806 }
807 
808 /*
809  * Prepare an ld_map_ver_t structure for a new mapfile defined version.
810  *
811  * exit:
812  *	Returns TRUE for success, FALSE for failure.
813  */
814 Boolean
815 ld_map_sym_ver_init(Mapfile *mf, char *name, ld_map_ver_t *mv)
816 {
817 	Word		hash;
818 	Ofl_desc	*ofl = mf->mf_ofl;
819 
820 	mv->mv_name = name;
821 	mv->mv_scope = FLG_SCOPE_DFLT;
822 	mv->mv_errcnt = 0;
823 
824 	/*
825 	 * If we're generating segments within the image then any symbol
826 	 * reductions will be processed (ie. applied to relocations and symbol
827 	 * table entries).  Otherwise (when creating a relocatable object) any
828 	 * versioning information is simply recorded for use in a later
829 	 * (segment generating) link-edit.
830 	 */
831 	if (ofl->ofl_flags & FLG_OF_RELOBJ)
832 		ofl->ofl_flags |= FLG_OF_VERDEF;
833 
834 	/*
835 	 * If no version descriptors have yet been set up, initialize a base
836 	 * version to represent the output file itself.  This `base' version
837 	 * catches any internally generated symbols (_end, _etext, etc.) and
838 	 * serves to initialize the output version descriptor count.
839 	 */
840 	if (ofl->ofl_vercnt == 0) {
841 		if (ld_vers_base(ofl) == (Ver_desc *)S_ERROR)
842 			return (FALSE);
843 	}
844 
845 	/*
846 	 * If this definition has an associated version name then generate a
847 	 * new version descriptor and an associated version symbol index table.
848 	 */
849 	if (name) {
850 		ofl->ofl_flags |= FLG_OF_VERDEF;
851 
852 		/*
853 		 * Traverse the present version descriptor list to see if there
854 		 * is already one of the same name, otherwise create a new one.
855 		 */
856 		/* LINTED */
857 		hash = (Word)elf_hash(name);
858 		if (((mv->mv_vdp = ld_vers_find(name, hash,
859 		    ofl->ofl_verdesc)) == NULL) &&
860 		    ((mv->mv_vdp = ld_vers_desc(name, hash,
861 		    &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR))
862 			return (FALSE);
863 
864 		/*
865 		 * Initialize any new version with an index, the file from
866 		 * which it was first referenced, and a WEAK flag (indicates
867 		 * that there are no symbols assigned to it yet).
868 		 */
869 		if (mv->mv_vdp->vd_ndx == 0) {
870 			/* LINTED */
871 			mv->mv_vdp->vd_ndx = (Half)++ofl->ofl_vercnt;
872 			mv->mv_vdp->vd_file = ld_map_ifl(mf);
873 			mv->mv_vdp->vd_flags = VER_FLG_WEAK;
874 		}
875 	} else {
876 		/*
877 		 * If a version definition hasn't been specified assign any
878 		 * symbols to the base version.
879 		 */
880 		mv->mv_vdp = (Ver_desc *)ofl->ofl_verdesc->apl_data[0];
881 	}
882 
883 	return (TRUE);
884 }
885 
886 /*
887  * Change the current scope for the given version.
888  *
889  * entry:
890  *	mf - Mapfile descriptor
891  *	scope_name - Name for new scope
892  *	mv - Information related to version being defined
893  *
894  * exit:
895  *	On success, mv is updated to change the current scope.
896  *	On failure, mv->errcnt is incremented, and mv is otherwise unaltered.
897  */
898 void
899 ld_map_sym_scope(Mapfile *mf, const char *scope_name, ld_map_ver_t *mv)
900 {
901 	typedef struct {
902 		const char	*name;		/* scope keyword string */
903 		ld_map_scope_t	type;		/* Resulting type */
904 		ofl_flag_t	ofl_flags;	/* 0, or ofl flags to add */
905 	} scope_t;
906 
907 	/*
908 	 * Valid symbol scope keywords
909 	 *
910 	 * All symbols added by a mapfile are actually global entries, and
911 	 * are assigned the scope that is presently in effect.
912 	 *
913 	 * If a protected/symbolic scope is detected, remember this. If
914 	 * a protected/symbolic scope is the only scope defined in this
915 	 * (or any other mapfiles), then the mode -Bsymbolic is established.
916 	 */
917 	static scope_t scope_list[] = {
918 		{ MSG_ORIG(MSG_MAPKW_DEFAULT), FLG_SCOPE_DFLT, FLG_OF_MAPGLOB },
919 		{ MSG_ORIG(MSG_MAPKW_ELIMINATE), FLG_SCOPE_ELIM, 0 },
920 		{ MSG_ORIG(MSG_MAPKW_EXPORTED), FLG_SCOPE_EXPT, 0 },
921 		{ MSG_ORIG(MSG_MAPKW_HIDDEN), FLG_SCOPE_HIDD, 0 },
922 		{ MSG_ORIG(MSG_MAPKW_GLOBAL), FLG_SCOPE_DFLT, FLG_OF_MAPGLOB },
923 		{ MSG_ORIG(MSG_MAPKW_LOCAL), FLG_SCOPE_HIDD, 0 },
924 		{ MSG_ORIG(MSG_MAPKW_PROTECTED),
925 		    FLG_SCOPE_PROT, FLG_OF_MAPSYMB },
926 		{ MSG_ORIG(MSG_MAPKW_SINGLETON),
927 		    FLG_SCOPE_SNGL, FLG_OF_MAPGLOB },
928 		{ MSG_ORIG(MSG_MAPKW_SYMBOLIC),
929 		    FLG_SCOPE_PROT, FLG_OF_MAPSYMB },
930 
931 		/* List must be null terminated */
932 		{ 0 }
933 	};
934 
935 	/*
936 	 * Size of buffer needed to format the names in scope_list[]. Must
937 	 * be kept in sync with scope_list.
938 	 */
939 	static size_t scope_list_bufsize =
940 	    KW_NAME_SIZE(MSG_MAPKW_DEFAULT) +
941 	    KW_NAME_SIZE(MSG_MAPKW_ELIMINATE) +
942 	    KW_NAME_SIZE(MSG_MAPKW_EXPORTED) +
943 	    KW_NAME_SIZE(MSG_MAPKW_HIDDEN) +
944 	    KW_NAME_SIZE(MSG_MAPKW_GLOBAL) +
945 	    KW_NAME_SIZE(MSG_MAPKW_LOCAL) +
946 	    KW_NAME_SIZE(MSG_MAPKW_PROTECTED) +
947 	    KW_NAME_SIZE(MSG_MAPKW_SINGLETON) +
948 	    KW_NAME_SIZE(MSG_MAPKW_SYMBOLIC);
949 
950 	scope_t	*scope;
951 
952 	scope = ld_map_kwfind(scope_name, scope_list,
953 	    SGSOFFSETOF(scope_t, name), sizeof (scope_list[0]));
954 	if (scope == NULL) {
955 		char buf[VLA_SIZE(scope_list_bufsize)];
956 
957 		mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMSCOPE),
958 		    ld_map_kwnames(scope_list, SGSOFFSETOF(scope_t, name),
959 		    sizeof (scope[0]), buf, scope_list_bufsize), scope_name);
960 		mv->mv_errcnt++;
961 		return;
962 	}
963 
964 	mv->mv_scope = scope->type;
965 	mf->mf_ofl->ofl_flags |= scope->ofl_flags;
966 }
967 
968 /*
969  * Process the special auto-reduction directive ('*'). It can be specified
970  * in hidden/local, and eliminate scope. This directive indicates that all
971  * symbols processed that are not explicitly defined to be global are to be
972  * reduced to hidden/local scope in, or eliminated from, the output image.
973  *
974  * An auto-reduction directive also implies that a version definition must
975  * be created, as the user has effectively defined an interface.
976  */
977 void
978 ld_map_sym_autoreduce(Mapfile *mf, ld_map_ver_t *mv)
979 {
980 	switch (mv->mv_scope) {
981 	case FLG_SCOPE_HIDD:
982 		mf->mf_ofl->ofl_flags |= (FLG_OF_VERDEF | FLG_OF_AUTOLCL);
983 		break;
984 	case FLG_SCOPE_ELIM:
985 		mf->mf_ofl->ofl_flags |= (FLG_OF_VERDEF | FLG_OF_AUTOELM);
986 		break;
987 	default:
988 		/*
989 		 * Auto reduction has been applied to a scope that doesn't
990 		 * support it. This should be a fatal error, but we limit
991 		 * it to a warning for version 1 mapfiles. For years, we
992 		 * quietly ignored this case, so there may be mapfiles in
993 		 * production use that we do not wish to break.
994 		 */
995 		if (mf->mf_version == 1) {
996 			mf_warn0(mf, MSG_INTL(MSG_MAP_BADAUTORED));
997 		} else {
998 			mf_fatal0(mf, MSG_INTL(MSG_MAP_BADAUTORED));
999 			mv->mv_errcnt++;
1000 		}
1001 	}
1002 }
1003 
1004 /*
1005  * Add a standard or auxiliary filter to the given symbol
1006  *
1007  * entry:
1008  *	mf - Mapfile descriptor
1009  *	mv - Information related to version being defined
1010  *	ms - Information related to symbol being defined
1011  *	dft_flag - One of FLG_SY_STDFLTR or FLG_SY_AUXFLTR,
1012  *		specifying the type of filter.
1013  *	filtee - String giving filtee to be added
1014  *
1015  * exit:
1016  *	On success, the filtee is added. On failure, mv->errcnt is
1017  *	incremented, and mv/ms are otherwise unaltered.
1018  */
1019 void
1020 ld_map_sym_filtee(Mapfile *mf, ld_map_ver_t *mv, ld_map_sym_t *ms,
1021     Word dft_flag, const char *filtee)
1022 {
1023 	/*
1024 	 * A given symbol can only be tied to a single filter, be it
1025 	 * a standard filter, or auxiliary.
1026 	 */
1027 	if (ms->ms_filtee) {
1028 		mf_fatal0(mf, MSG_INTL(MSG_MAP_MULTFILTEE));
1029 		mv->mv_errcnt++;
1030 		return;
1031 	}
1032 
1033 	/* Symbol filtering is only for sharable objects */
1034 	if (!(mf->mf_ofl->ofl_flags & FLG_OF_SHAROBJ)) {
1035 		mf_fatal0(mf, MSG_INTL(MSG_MAP_FLTR_ONLYAVL));
1036 		mv->mv_errcnt++;
1037 		return;
1038 	}
1039 
1040 	ms->ms_filtee = filtee;
1041 	ms->ms_dft_flag = dft_flag;
1042 	ms->ms_sdflags |= dft_flag;
1043 	mf->mf_ofl->ofl_flags |= FLG_OF_SYMINFO;
1044 }
1045 
1046 /*
1047  * Enter a mapfile defined symbol into the given version
1048  *
1049  * entry:
1050  *	mf - Mapfile descriptor
1051  *	ms - Information related to symbol being added to version
1052  *
1053  * exit:
1054  *	On success, returns TRUE. On failure that requires an immediate
1055  *	halt, returns FALSE.
1056  *
1057  *	On failure that requires eventual halt, but for which it would
1058  *	be OK to continue parsing in hopes of flushing out additional
1059  *	problems, increments mv->mv_errcnt, and returns TRUE.
1060  */
1061 Boolean
1062 ld_map_sym_enter(Mapfile *mf, ld_map_ver_t *mv, ld_map_sym_t *ms, Ass_desc *ma)
1063 {
1064 	Ofl_desc	*ofl = mf->mf_ofl;
1065 	Word		hash;
1066 	avl_index_t	where;
1067 	Sym		*sym;
1068 	Sym_desc	*sdp;
1069 	const char	*conflict;
1070 
1071 	/*
1072 	 * Add the new symbol.  It should be noted that all
1073 	 * symbols added by the mapfile start out with global
1074 	 * scope, thus they will fall through the normal symbol
1075 	 * resolution process.  Symbols defined as locals will
1076 	 * be reduced in scope after all input file processing.
1077 	 */
1078 	/* LINTED */
1079 	hash = (Word)elf_hash(ms->ms_name);
1080 	DBG_CALL(Dbg_map_version(ofl->ofl_lml, mv->mv_name, ms->ms_name,
1081 	    mv->mv_scope));
1082 
1083 	/*
1084 	 * Make sure that any parent or external declarations fall back to
1085 	 * references.
1086 	 */
1087 	if (ms->ms_sdflags & (FLG_SY_PARENT | FLG_SY_EXTERN)) {
1088 		/*
1089 		 * Turn it into a reference by setting the section index
1090 		 * to UNDEF.
1091 		 */
1092 		ms->ms_shndx = SHN_UNDEF;
1093 
1094 		/*
1095 		 * It is wrong to specify size or value for an external symbol.
1096 		 */
1097 		if (ms->ms_value_set || (ms->ms_size != 0)) {
1098 			mf_fatal0(mf, MSG_INTL(MSG_MAP_NOEXVLSZ));
1099 			mv->mv_errcnt++;
1100 			return (TRUE);
1101 		}
1102 	}
1103 
1104 	if ((sdp = ld_sym_find(ms->ms_name, hash, &where, ofl)) == NULL) {
1105 		if ((sym = libld_calloc(1, sizeof (Sym))) == NULL)
1106 			return (FALSE);
1107 
1108 		sym->st_shndx = (Half)ms->ms_shndx;
1109 		sym->st_value = ms->ms_value;
1110 		sym->st_size = ms->ms_size;
1111 		sym->st_info = ELF_ST_INFO(STB_GLOBAL, ms->ms_type);
1112 
1113 		if ((sdp = ld_sym_enter(ms->ms_name, sym, hash,
1114 		    ld_map_ifl(mf), ofl, 0, ms->ms_shndx, ms->ms_sdflags,
1115 		    &where)) == (Sym_desc *)S_ERROR)
1116 			return (FALSE);
1117 
1118 		sdp->sd_flags &= ~FLG_SY_CLEAN;
1119 
1120 		/*
1121 		 * Identify any references.  FLG_SY_MAPREF is
1122 		 * turned off once a relocatable object with
1123 		 * the same symbol is found, thus the existence
1124 		 * of FLG_SY_MAPREF at symbol validation is
1125 		 * used to flag undefined/misspelled entries.
1126 		 */
1127 		if (sym->st_shndx == SHN_UNDEF)
1128 			sdp->sd_flags |= (FLG_SY_MAPREF | FLG_SY_GLOBREF);
1129 
1130 		if (ma != NULL && ma->ass_enabled != 0) {
1131 			Ass_desc *m;
1132 
1133 			/*
1134 			 * Mark the symbol so we can issue guidance more
1135 			 * easily
1136 			 */
1137 			sdp->sd_flags |= FLG_SY_MAPASSRT;
1138 
1139 			if ((m = libld_calloc(1, sizeof (Ass_desc))) == NULL)
1140 				return (FALSE);
1141 			memcpy(m, ma, sizeof (Ass_desc));
1142 			m->ass_sdp = sdp;
1143 			sdp->sd_ass = m;
1144 
1145 			if (aplist_append(&ofl->ofl_symasserts, m,
1146 			    AL_CNT_MAPASSERT) == NULL) {
1147 				return (FALSE);
1148 			}
1149 		}
1150 	} else {
1151 		conflict = NULL;
1152 		sym = sdp->sd_sym;
1153 
1154 		/*
1155 		 * If this symbol already exists, make sure this
1156 		 * definition doesn't conflict with the former.
1157 		 * Provided it doesn't, multiple definitions
1158 		 * from different mapfiles can augment each
1159 		 * other.
1160 		 */
1161 		if (sym->st_value) {
1162 			if (ms->ms_value && (sym->st_value != ms->ms_value))
1163 				conflict = MSG_INTL(MSG_MAP_DIFF_SYMVAL);
1164 		} else {
1165 			sym->st_value = ms->ms_value;
1166 		}
1167 		if (sym->st_size) {
1168 			if (ms->ms_size_set && (sym->st_size != ms->ms_size))
1169 				conflict = MSG_INTL(MSG_MAP_DIFF_SYMSZ);
1170 		} else {
1171 			sym->st_size = ms->ms_size;
1172 		}
1173 		if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) {
1174 			if ((ms->ms_type != STT_NOTYPE) &&
1175 			    (ELF_ST_TYPE(sym->st_info) != ms->ms_type))
1176 				conflict = MSG_INTL(MSG_MAP_DIFF_SYMTYP);
1177 		} else {
1178 			sym->st_info = ELF_ST_INFO(STB_GLOBAL, ms->ms_type);
1179 		}
1180 		if (sym->st_shndx != SHN_UNDEF) {
1181 			if ((ms->ms_shndx != SHN_UNDEF) &&
1182 			    (sym->st_shndx != ms->ms_shndx))
1183 				conflict = MSG_INTL(MSG_MAP_DIFF_SYMNDX);
1184 		} else {
1185 			sym->st_shndx = sdp->sd_shndx = ms->ms_shndx;
1186 		}
1187 
1188 		if ((sdp->sd_flags & MSK_SY_GLOBAL) &&
1189 		    (sdp->sd_aux->sa_overndx != VER_NDX_GLOBAL) &&
1190 		    (mv->mv_vdp->vd_ndx != VER_NDX_GLOBAL) &&
1191 		    (sdp->sd_aux->sa_overndx != mv->mv_vdp->vd_ndx)) {
1192 			conflict = MSG_INTL(MSG_MAP_DIFF_SYMVER);
1193 		}
1194 
1195 		if (conflict) {
1196 			mf_fatal(mf, MSG_INTL(MSG_MAP_SYMDEF1),
1197 			    demangle(ms->ms_name),
1198 			    sdp->sd_file->ifl_name, conflict);
1199 			mv->mv_errcnt++;
1200 			return (TRUE);
1201 		}
1202 
1203 		/*
1204 		 * If this mapfile entry supplies a definition,
1205 		 * indicate that the symbol is now used.
1206 		 */
1207 		if (ms->ms_shndx != SHN_UNDEF)
1208 			sdp->sd_flags |= FLG_SY_MAPUSED;
1209 	}
1210 
1211 	/*
1212 	 * A symbol declaration that defines a size but no
1213 	 * value is processed as a request to create an
1214 	 * associated backing section.  The intent behind this
1215 	 * functionality is to provide OBJT definitions within
1216 	 * filters that are not ABS.  ABS symbols don't allow
1217 	 * copy-relocations to be established to filter OBJT
1218 	 * definitions.
1219 	 */
1220 	if ((ms->ms_shndx == SHN_ABS) && ms->ms_size_set && !ms->ms_value_set) {
1221 		/* Create backing section if not there */
1222 		if (sdp->sd_isc == NULL) {
1223 			Is_desc	*isp;
1224 
1225 			if (ms->ms_type == STT_OBJECT) {
1226 				if ((isp = ld_make_data(ofl, ms->ms_size)) ==
1227 				    (Is_desc *)S_ERROR)
1228 					return (FALSE);
1229 			} else {
1230 				if ((isp = ld_make_text(ofl, ms->ms_size)) ==
1231 				    (Is_desc *)S_ERROR)
1232 					return (FALSE);
1233 			}
1234 
1235 			sdp->sd_isc = isp;
1236 			isp->is_file = ld_map_ifl(mf);
1237 		}
1238 
1239 		/*
1240 		 * Now that backing storage has been created,
1241 		 * associate the symbol descriptor.  Remove the
1242 		 * symbols special section tag so that it will
1243 		 * be assigned the correct section index as part
1244 		 * of update symbol processing.
1245 		 */
1246 		sdp->sd_flags &= ~FLG_SY_SPECSEC;
1247 		ms->ms_sdflags &= ~FLG_SY_SPECSEC;
1248 	}
1249 
1250 	/*
1251 	 * Indicate the new symbols scope.  Although the
1252 	 * symbols st_other field will eventually be updated as
1253 	 * part of writing out the final symbol, update the
1254 	 * st_other field here to trigger better diagnostics
1255 	 * during symbol validation (for example, undefined
1256 	 * references that are defined symbolic in a mapfile).
1257 	 */
1258 	if (mv->mv_scope == FLG_SCOPE_HIDD) {
1259 		/*
1260 		 * This symbol needs to be reduced to local.
1261 		 */
1262 		if (ofl->ofl_flags & FLG_OF_REDLSYM) {
1263 			sdp->sd_flags |= (FLG_SY_HIDDEN | FLG_SY_ELIM);
1264 			sdp->sd_sym->st_other = STV_ELIMINATE;
1265 		} else {
1266 			sdp->sd_flags |= FLG_SY_HIDDEN;
1267 			sdp->sd_sym->st_other = STV_HIDDEN;
1268 		}
1269 	} else if (mv->mv_scope == FLG_SCOPE_ELIM) {
1270 		/*
1271 		 * This symbol needs to be eliminated.  Note,
1272 		 * the symbol is also tagged as local to trigger
1273 		 * any necessary relocation processing prior
1274 		 * to the symbol being eliminated.
1275 		 */
1276 		sdp->sd_flags |= (FLG_SY_HIDDEN | FLG_SY_ELIM);
1277 		sdp->sd_sym->st_other = STV_ELIMINATE;
1278 
1279 	} else {
1280 		/*
1281 		 * This symbol is explicitly defined to remain
1282 		 * global.
1283 		 */
1284 		sdp->sd_flags |= ms->ms_sdflags;
1285 
1286 		/*
1287 		 * Qualify any global scope.
1288 		 */
1289 		if (mv->mv_scope == FLG_SCOPE_SNGL) {
1290 			sdp->sd_flags |= (FLG_SY_SINGLE | FLG_SY_NDIR);
1291 			sdp->sd_sym->st_other = STV_SINGLETON;
1292 		} else if (mv->mv_scope == FLG_SCOPE_PROT) {
1293 			sdp->sd_flags |= FLG_SY_PROTECT;
1294 			sdp->sd_sym->st_other = STV_PROTECTED;
1295 		} else if (mv->mv_scope == FLG_SCOPE_EXPT) {
1296 			sdp->sd_flags |= FLG_SY_EXPORT;
1297 			sdp->sd_sym->st_other = STV_EXPORTED;
1298 		} else
1299 			sdp->sd_flags |= FLG_SY_DEFAULT;
1300 
1301 		/*
1302 		 * Record the present version index for later
1303 		 * potential versioning.
1304 		 */
1305 		if ((sdp->sd_aux->sa_overndx == 0) ||
1306 		    (sdp->sd_aux->sa_overndx == VER_NDX_GLOBAL))
1307 			sdp->sd_aux->sa_overndx = mv->mv_vdp->vd_ndx;
1308 		mv->mv_vdp->vd_flags |= FLG_VER_REFER;
1309 	}
1310 
1311 	conflict = NULL;
1312 
1313 	/*
1314 	 * Carry out some validity checks to ensure incompatible
1315 	 * symbol characteristics have not been defined.
1316 	 * These checks are carried out after symbols are added
1317 	 * or resolved, to catch single instance, and
1318 	 * multi-instance definition inconsistencies.
1319 	 */
1320 	if ((sdp->sd_flags & (FLG_SY_HIDDEN | FLG_SY_ELIM)) &&
1321 	    ((mv->mv_scope != FLG_SCOPE_HIDD) &&
1322 	    (mv->mv_scope != FLG_SCOPE_ELIM))) {
1323 		conflict = MSG_INTL(MSG_MAP_DIFF_SYMLCL);
1324 
1325 	} else if ((sdp->sd_flags &
1326 	    (FLG_SY_SINGLE | FLG_SY_EXPORT)) &&
1327 	    ((mv->mv_scope != FLG_SCOPE_DFLT) &&
1328 	    (mv->mv_scope != FLG_SCOPE_EXPT) &&
1329 	    (mv->mv_scope != FLG_SCOPE_SNGL))) {
1330 		conflict = MSG_INTL(MSG_MAP_DIFF_SYMGLOB);
1331 
1332 	} else if ((sdp->sd_flags & FLG_SY_PROTECT) &&
1333 	    ((mv->mv_scope != FLG_SCOPE_DFLT) &&
1334 	    (mv->mv_scope != FLG_SCOPE_PROT))) {
1335 		conflict = MSG_INTL(MSG_MAP_DIFF_SYMPROT);
1336 
1337 	} else if ((sdp->sd_flags & FLG_SY_NDIR) &&
1338 	    (mv->mv_scope == FLG_SCOPE_PROT)) {
1339 		conflict = MSG_INTL(MSG_MAP_DIFF_PROTNDIR);
1340 
1341 	} else if ((sdp->sd_flags & FLG_SY_DIR) &&
1342 	    (mv->mv_scope == FLG_SCOPE_SNGL)) {
1343 		conflict = MSG_INTL(MSG_MAP_DIFF_SNGLDIR);
1344 	}
1345 
1346 	if (conflict) {
1347 		/*
1348 		 * Select the conflict message from either a
1349 		 * single instance or multi-instance definition.
1350 		 */
1351 		if (sdp->sd_file->ifl_name == mf->mf_name) {
1352 			mf_fatal(mf, MSG_INTL(MSG_MAP_SYMDEF2),
1353 			    demangle(ms->ms_name), conflict);
1354 		} else {
1355 			mf_fatal(mf, MSG_INTL(MSG_MAP_SYMDEF1),
1356 			    demangle(ms->ms_name),
1357 			    sdp->sd_file->ifl_name, conflict);
1358 		}
1359 		mv->mv_errcnt++;
1360 		return (TRUE);
1361 	}
1362 
1363 	/*
1364 	 * Indicate that this symbol has been explicitly
1365 	 * contributed from a mapfile.
1366 	 */
1367 	sdp->sd_flags |= (FLG_SY_MAPFILE | FLG_SY_EXPDEF);
1368 
1369 	/*
1370 	 * If we've encountered a symbol definition simulate
1371 	 * that an input file has been processed - this allows
1372 	 * things like filters to be created purely from a
1373 	 * mapfile.
1374 	 */
1375 	if (ms->ms_type != STT_NOTYPE)
1376 		ofl->ofl_objscnt++;
1377 	DBG_CALL(Dbg_map_symbol(ofl, sdp));
1378 
1379 	/*
1380 	 * If this symbol has an associated filtee, record the
1381 	 * filtee string and associate the string index with the
1382 	 * symbol.  This is used later to associate the syminfo
1383 	 * information with the necessary .dynamic entry.
1384 	 */
1385 	if (ms->ms_filtee) {
1386 		Dfltr_desc *	dftp;
1387 		Sfltr_desc	sft;
1388 		Aliste		idx, _idx, nitems;
1389 
1390 		/*
1391 		 * Make sure we don't duplicate any filtee
1392 		 * strings, and create a new descriptor if
1393 		 * necessary.
1394 		 */
1395 		idx = nitems = alist_nitems(ofl->ofl_dtsfltrs);
1396 		for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, _idx, dftp)) {
1397 			if ((ms->ms_dft_flag != dftp->dft_flag) ||
1398 			    (strcmp(dftp->dft_str, ms->ms_filtee)))
1399 				continue;
1400 			idx = _idx;
1401 			break;
1402 		}
1403 		if (idx == nitems) {
1404 			Dfltr_desc	dft;
1405 
1406 			dft.dft_str = ms->ms_filtee;
1407 			dft.dft_flag = ms->ms_dft_flag;
1408 			dft.dft_ndx = 0;
1409 
1410 			/*
1411 			 * The following append puts the new
1412 			 * item at the offset contained in
1413 			 * idx, because we know idx contains
1414 			 * the index of the next available slot.
1415 			 */
1416 			if (alist_append(&ofl->ofl_dtsfltrs, &dft,
1417 			    sizeof (Dfltr_desc), AL_CNT_OFL_DTSFLTRS) == NULL)
1418 				return (FALSE);
1419 		}
1420 
1421 		/*
1422 		 * Create a new filter descriptor for this
1423 		 * symbol.
1424 		 */
1425 		sft.sft_sdp = sdp;
1426 		sft.sft_idx = idx;
1427 
1428 		if (alist_append(&ofl->ofl_symfltrs, &sft, sizeof (Sfltr_desc),
1429 		    AL_CNT_OFL_SYMFLTRS) == NULL)
1430 			return (FALSE);
1431 	}
1432 
1433 	return (TRUE);
1434 }
1435 
1436 /*
1437  * In both the version 1 and version 2 syntaxes, a version definition
1438  * can have 0 or more inherited versions following the closing '}',
1439  * terminated by a ';'.
1440  *
1441  * Add the inherited names, and return when the terminator is seen.
1442  */
1443 Boolean
1444 ld_map_sym_ver_fini(Mapfile *mf, ld_map_ver_t *mv)
1445 {
1446 	Token		tok;
1447 	ld_map_tkval_t	tkv;		/* Value of token */
1448 	Boolean		done = FALSE;
1449 	Conv_inv_buf_t	inv_buf;
1450 	const char	*name;
1451 	Ver_desc	*vdp;
1452 	Word		hash;
1453 
1454 	/*
1455 	 * Read version names until we encounter the ';' terminator.
1456 	 */
1457 	while (!done) {
1458 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
1459 		case TK_ERROR:
1460 			return (FALSE);
1461 
1462 		case TK_STRING:
1463 			name = tkv.tkv_str;
1464 
1465 			/* The unnamed global scope can't inherit */
1466 			if (mv->mv_vdp->vd_ndx == VER_NDX_GLOBAL) {
1467 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNEXINHERIT),
1468 				    name);
1469 				return (FALSE);
1470 			}
1471 
1472 			/*
1473 			 * Generate a new version descriptor if it doesn't
1474 			 * already exist.
1475 			 */
1476 			/* LINTED */
1477 			hash = (Word)elf_hash(name);
1478 			vdp = ld_vers_find(name, hash, mf->mf_ofl->ofl_verdesc);
1479 			if ((vdp == NULL) && ((vdp = ld_vers_desc(name, hash,
1480 			    &mf->mf_ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR))
1481 				return (FALSE);
1482 
1483 			/*
1484 			 * Add the new version descriptor to the parent version
1485 			 * descriptors reference list.  Indicate the version
1486 			 * descriptors first reference (used for error diags
1487 			 * if undefined version dependencies remain).
1488 			 */
1489 			if (ld_vers_find(name, hash, mv->mv_vdp->vd_deps) ==
1490 			    NULL)
1491 				if (aplist_append(&mv->mv_vdp->vd_deps, vdp,
1492 				    AL_CNT_VERDESCS) == NULL)
1493 					return (FALSE);
1494 
1495 			if (vdp->vd_ref == NULL)
1496 				vdp->vd_ref = mv->mv_vdp;
1497 			break;
1498 
1499 		case TK_SEMICOLON:
1500 			done = TRUE;
1501 			break;
1502 
1503 		default:
1504 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMEND),
1505 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
1506 			return (FALSE);
1507 		}
1508 	}
1509 
1510 	return (TRUE);
1511 }
1512