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