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