xref: /titanic_44/usr/src/cmd/sgs/libld/common/map.c (revision 1b34bc4aa5ecbd590d45845d21c8478049df6dcf)
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 2008 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 /*
32  * Map file parsing.
33  */
34 #include	<fcntl.h>
35 #include	<string.h>
36 #include	<stdio.h>
37 #include	<unistd.h>
38 #include	<sys/stat.h>
39 #include	<errno.h>
40 #include	<limits.h>
41 #include	<dirent.h>
42 #include	<ctype.h>
43 #include	<elfcap.h>
44 #include	<debug.h>
45 #include	"msg.h"
46 #include	"_libld.h"
47 
48 #if	defined(_ELF64)
49 #define	STRTOADDR	strtoull
50 #define	XWORD_MAX	ULLONG_MAX
51 #else	/* Elf32 */
52 #define	STRTOADDR	strtoul
53 #define	XWORD_MAX	UINT_MAX
54 #endif	/* _ELF64 */
55 
56 typedef enum {
57 	TK_STRING,	TK_COLON,	TK_SEMICOLON,	TK_EQUAL,
58 	TK_ATSIGN,	TK_DASH,	TK_LEFTBKT,	TK_RIGHTBKT,
59 	TK_PIPE,	TK_EOF
60 } Token;			/* Possible return values from gettoken. */
61 
62 
63 static char	*Mapspace;	/* Malloc space holding map file. */
64 static ulong_t	Line_num;	/* Current map file line number. */
65 static char	*Start_tok;	/* First character of current token. */
66 static char	*nextchr;	/* Next char in mapfile to examine. */
67 
68 /*
69  * Convert a string to lowercase.
70  */
71 static void
72 lowercase(char *str)
73 {
74 	while (*str = tolower(*str))
75 		str++;
76 }
77 
78 /*
79  * Get a token from the mapfile.
80  */
81 static Token
82 gettoken(Ofl_desc *ofl, const char *mapfile)
83 {
84 	static char	oldchr = '\0';	/* Char at end of current token. */
85 	char		*end;		/* End of the current token. */
86 
87 	/* Cycle through the characters looking for tokens. */
88 	for (;;) {
89 		if (oldchr != '\0') {
90 			*nextchr = oldchr;
91 			oldchr = '\0';
92 		}
93 		if (!isascii(*nextchr) ||
94 		    (!isprint(*nextchr) && !isspace(*nextchr) &&
95 		    (*nextchr != '\0'))) {
96 			eprintf(ofl->ofl_lml, ERR_FATAL,
97 			    MSG_INTL(MSG_MAP_ILLCHAR), mapfile,
98 			    EC_XWORD(Line_num), *((uchar_t *)nextchr));
99 			/* LINTED */
100 			return ((Token)S_ERROR);
101 		}
102 		switch (*nextchr) {
103 		case '\0':	/* End of file. */
104 			return (TK_EOF);
105 		case ' ':	/* White space. */
106 		case '\t':
107 			nextchr++;
108 			break;
109 		case '\n':	/* White space too, but bump line number. */
110 			nextchr++;
111 			Line_num++;
112 			break;
113 		case '#':	/* Comment. */
114 			while (*nextchr != '\n' && *nextchr != '\0')
115 				nextchr++;
116 			break;
117 		case ':':
118 			nextchr++;
119 			return (TK_COLON);
120 		case ';':
121 			nextchr++;
122 			return (TK_SEMICOLON);
123 		case '=':
124 			nextchr++;
125 			return (TK_EQUAL);
126 		case '@':
127 			nextchr++;
128 			return (TK_ATSIGN);
129 		case '-':
130 			nextchr++;
131 			return (TK_DASH);
132 		case '|':
133 			nextchr++;
134 			return (TK_PIPE);
135 		case '{':
136 			nextchr++;
137 			return (TK_LEFTBKT);
138 		case '}':
139 			nextchr++;
140 			return (TK_RIGHTBKT);
141 		case '"':
142 			Start_tok = ++nextchr;
143 			if (((end = strpbrk(nextchr,
144 			    MSG_ORIG(MSG_MAP_TOK_1))) == NULL) ||
145 			    (*end != '"')) {
146 				eprintf(ofl->ofl_lml, ERR_FATAL,
147 				    MSG_INTL(MSG_MAP_NOTERM), mapfile,
148 				    EC_XWORD(Line_num));
149 				/* LINTED */
150 				return ((Token)S_ERROR);
151 			}
152 			*end = '\0';
153 			nextchr = end + 1;
154 			return (TK_STRING);
155 		default:	/* string. */
156 			Start_tok = nextchr;		/* CSTYLED */
157 			end = strpbrk(nextchr, MSG_ORIG(MSG_MAP_TOK_2));
158 			if (end == NULL)
159 				nextchr = Start_tok + strlen(Start_tok);
160 			else {
161 				nextchr = end;
162 				oldchr = *nextchr;
163 				*nextchr = '\0';
164 			}
165 			return (TK_STRING);
166 		}
167 	}
168 }
169 
170 /*
171  * Process a hardware/software capabilities segment declaration definition.
172  *	hwcap_1	= val,... [ OVERRIDE ]
173  *	sfcap_1	= val,... [ OVERRIDE ]
174  *
175  * The values can be defined as a list of machine specify tokens, or numerics.
176  * Tokens are representations of the sys/auxv_$MACH.h capabilities, for example:
177  *
178  *	#define AV_386_FPU 0x0001	is represented as	FPU
179  *	#define AV_386_TSC 0x0002	 "    "    "   " 	TSC
180  *
181  * Or, the above two capabilities could be represented as V0x3.  Note, the
182  * OVERRIDE flag is used to insure that only those values provided via this
183  * mapfile entry are recorded in the final image, ie. this overrides any
184  * hardware capabilities that may be defined in the objects read as part of this
185  * link-edit.  Specifying:
186  *
187  *	V0x0 OVERRIDE
188  *
189  * effectively removes any capabilities information from the final image.
190  */
191 static uintptr_t
192 map_cap(const char *mapfile, Word type, Ofl_desc *ofl)
193 {
194 	Token	tok;			/* Current token. */
195 	Xword	number;
196 	int	used = 0;
197 
198 	while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
199 		/* LINTED */
200 		if (tok == (Token)S_ERROR)
201 			return (S_ERROR);
202 		if (tok == TK_EOF) {
203 			eprintf(ofl->ofl_lml, ERR_FATAL,
204 			    MSG_INTL(MSG_MAP_PREMEOF), mapfile,
205 			    EC_XWORD(Line_num));
206 			return (S_ERROR);
207 		}
208 		if (tok != TK_STRING) {
209 			eprintf(ofl->ofl_lml, ERR_FATAL,
210 			    MSG_INTL(MSG_MAP_EXPSEGATT), mapfile,
211 			    EC_XWORD(Line_num));
212 			return (S_ERROR);
213 		}
214 
215 		lowercase(Start_tok);
216 
217 		/*
218 		 * First, determine if the token represents the reserved
219 		 * OVERRIDE keyword.
220 		 */
221 		if (strncmp(Start_tok, MSG_ORIG(MSG_MAP_OVERRIDE),
222 		    MSG_MAP_OVERRIDE_SIZE) == 0) {
223 			if (type == CA_SUNW_HW_1)
224 				ofl->ofl_flags1 |= FLG_OF1_OVHWCAP;
225 			else
226 				ofl->ofl_flags1 |= FLG_OF1_OVSFCAP;
227 			used++;
228 			continue;
229 		}
230 
231 		/*
232 		 * Next, determine if the token represents a machine specific
233 		 * hardware capability, or a generic software capability.
234 		 */
235 		if (type == CA_SUNW_HW_1) {
236 			if ((number = (Xword)elfcap_hw1_from_str(
237 			    ELFCAP_STYLE_LC, Start_tok,
238 			    ld_targ.t_m.m_mach)) != 0) {
239 				ofl->ofl_hwcap_1 |= number;
240 				used++;
241 				continue;
242 			}
243 		} else {
244 			if ((number = (Xword)elfcap_sf1_from_str(
245 			    ELFCAP_STYLE_LC, Start_tok,
246 			    ld_targ.t_m.m_mach)) != 0) {
247 				ofl->ofl_sfcap_1 |= number;
248 				used++;
249 				continue;
250 			}
251 		}
252 
253 		/*
254 		 * Next, determine if the token represents a numeric value.
255 		 */
256 		if (Start_tok[0] == 'v') {
257 			char		*end_tok;
258 
259 			errno = 0;
260 			number = (Xword)strtoul(&Start_tok[1], &end_tok, 0);
261 			if (errno) {
262 				int	err = errno;
263 				eprintf(ofl->ofl_lml, ERR_FATAL,
264 				    MSG_INTL(MSG_MAP_BADCAPVAL),
265 				    mapfile, EC_XWORD(Line_num), Start_tok,
266 				    strerror(err));
267 				return (S_ERROR);
268 			}
269 			if (end_tok != strchr(Start_tok, '\0')) {
270 				eprintf(ofl->ofl_lml, ERR_FATAL,
271 				    MSG_INTL(MSG_MAP_BADCAPVAL), mapfile,
272 				    EC_XWORD(Line_num), Start_tok,
273 				    MSG_INTL(MSG_MAP_NOBADFRM));
274 				return (S_ERROR);
275 			}
276 
277 			if (type == CA_SUNW_HW_1)
278 				ofl->ofl_hwcap_1 |= number;
279 			else
280 				ofl->ofl_sfcap_1 |= number;
281 			used++;
282 			continue;
283 		}
284 
285 		/*
286 		 * We have an unknown token.
287 		 */
288 		used++;
289 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_MAP_UNKCAPATTR),
290 		    mapfile, EC_XWORD(Line_num), Start_tok);
291 		return (S_ERROR);
292 	}
293 
294 	/*
295 	 * Catch any empty declarations, and indicate any software capabilities
296 	 * have been initialized if necessary.
297 	 */
298 	if (used == 0) {
299 		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_MAP_EMPTYCAP),
300 		    mapfile, EC_XWORD(Line_num));
301 	} else if (type == CA_SUNW_SF_1) {
302 		Lword	badsf1;
303 
304 		/*
305 		 * Note, hardware capabilities, beyond the tokens that are
306 		 * presently known, can be accepted using the V0xXXX notation,
307 		 * and as these simply get or'd into the output image, we allow
308 		 * any values to be supplied.  Software capability tokens
309 		 * however, have an algorithm of acceptance and update (see
310 		 * sf1_cap() in files.c).  Therefore only allow software
311 		 * capabilities that are known.
312 		 */
313 		if ((badsf1 = (ofl->ofl_sfcap_1 & ~SF1_SUNW_MASK)) != 0) {
314 			eprintf(ofl->ofl_lml, ERR_WARNING,
315 			    MSG_INTL(MSG_MAP_BADSF1), mapfile,
316 			    EC_XWORD(Line_num), EC_LWORD(badsf1));
317 			ofl->ofl_sfcap_1 &= SF1_SUNW_MASK;
318 		}
319 		if (ofl->ofl_sfcap_1 == SF1_SUNW_FPUSED) {
320 			eprintf(ofl->ofl_lml, ERR_WARNING,
321 			    MSG_INTL(MSG_FIL_BADSF1), mapfile,
322 			    EC_XWORD(Line_num), EC_LWORD(SF1_SUNW_FPUSED));
323 			ofl->ofl_sfcap_1 = 0;
324 		}
325 	}
326 	return (1);
327 }
328 
329 /*
330  * Common segment error checking.
331  */
332 static Boolean
333 seg_check(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl, Boolean b_type,
334     Word p_type)
335 {
336 	if (b_type) {
337 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_MAP_MOREONCE),
338 		    mapfile, EC_XWORD(Line_num), MSG_INTL(MSG_MAP_SEGTYP));
339 		return (FALSE);
340 	}
341 	if ((sgp->sg_flags & FLG_SG_TYPE) && (sgp->sg_phdr.p_type != p_type)) {
342 		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_MAP_REDEFATT),
343 		    mapfile, EC_XWORD(Line_num), MSG_INTL(MSG_MAP_SEGTYP),
344 		    sgp->sg_name);
345 	}
346 	return (TRUE);
347 }
348 
349 /*
350  * Process a mapfile segment declaration definition.
351  *	segment_name	= segment_attribute;
352  * 	segment_attribute : segment_type  segment_flags  virtual_addr
353  *			    physical_addr  length alignment
354  */
355 static uintptr_t
356 map_equal(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl)
357 {
358 	Token	tok;			/* Current token. */
359 	Boolean	b_type  = FALSE;	/* True if seg types found. */
360 	Boolean	b_flags = FALSE;	/* True if seg flags found. */
361 	Boolean	b_len   = FALSE;	/* True if seg length found. */
362 	Boolean	b_round = FALSE;	/* True if seg rounding found. */
363 	Boolean	b_vaddr = FALSE;	/* True if seg virtual addr found. */
364 	Boolean	b_paddr = FALSE;	/* True if seg physical addr found. */
365 	Boolean	b_align = FALSE;	/* True if seg alignment found. */
366 
367 	while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
368 		/* LINTED */
369 		if (tok == (Token)S_ERROR)
370 			return (S_ERROR);
371 		if (tok == TK_EOF) {
372 			eprintf(ofl->ofl_lml, ERR_FATAL,
373 			    MSG_INTL(MSG_MAP_PREMEOF), mapfile,
374 			    EC_XWORD(Line_num));
375 			return (S_ERROR);
376 		}
377 		if (tok != TK_STRING) {
378 			eprintf(ofl->ofl_lml, ERR_FATAL,
379 			    MSG_INTL(MSG_MAP_EXPSEGATT), mapfile,
380 			    EC_XWORD(Line_num));
381 			return (S_ERROR);
382 		}
383 
384 		lowercase(Start_tok);
385 
386 		/*
387 		 * Segment type.  Users are permitted to define PT_LOAD,
388 		 * PT_NOTE, PT_STACK and PT_NULL segments.  Other segment types
389 		 * are only defined in seg_desc[].
390 		 */
391 		if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_LOAD)) == 0) {
392 			if ((b_type = seg_check(mapfile, sgp, ofl, b_type,
393 			    PT_LOAD)) == FALSE)
394 				return (S_ERROR);
395 
396 			sgp->sg_phdr.p_type = PT_LOAD;
397 			sgp->sg_flags |= FLG_SG_TYPE;
398 
399 		} else if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_STACK)) == 0) {
400 			if ((b_type = seg_check(mapfile, sgp, ofl, b_type,
401 			    PT_SUNWSTACK)) == FALSE)
402 				return (S_ERROR);
403 
404 			sgp->sg_phdr.p_type = PT_SUNWSTACK;
405 			sgp->sg_flags |= (FLG_SG_TYPE | FLG_SG_EMPTY);
406 
407 		} else if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_NULL)) == 0) {
408 			if ((b_type = seg_check(mapfile, sgp, ofl, b_type,
409 			    PT_NULL)) == FALSE)
410 				return (S_ERROR);
411 
412 			sgp->sg_phdr.p_type = PT_NULL;
413 			sgp->sg_flags |= FLG_SG_TYPE;
414 
415 		} else if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_NOTE)) == 0) {
416 			if ((b_type = seg_check(mapfile, sgp, ofl, b_type,
417 			    PT_NOTE)) == FALSE)
418 				return (S_ERROR);
419 
420 			sgp->sg_phdr.p_type = PT_NOTE;
421 			sgp->sg_flags |= FLG_SG_TYPE;
422 		}
423 
424 		/* Segment Flags. */
425 
426 		else if (*Start_tok == '?') {
427 			Word	tmp_flags = 0;
428 			char	*flag_tok = Start_tok + 1;
429 
430 			if (b_flags) {
431 				eprintf(ofl->ofl_lml, ERR_FATAL,
432 				    MSG_INTL(MSG_MAP_MOREONCE), mapfile,
433 				    EC_XWORD(Line_num),
434 				    MSG_INTL(MSG_MAP_SEGFLAG));
435 				return (S_ERROR);
436 			}
437 
438 			/*
439 			 * If ? has nothing following leave the flags cleared,
440 			 * otherwise or in any flags specified.
441 			 */
442 			if (*flag_tok) {
443 				while (*flag_tok) {
444 					switch (*flag_tok) {
445 					case 'r':
446 						tmp_flags |= PF_R;
447 						break;
448 					case 'w':
449 						tmp_flags |= PF_W;
450 						break;
451 					case 'x':
452 						tmp_flags |= PF_X;
453 						break;
454 					case 'e':
455 						sgp->sg_flags |= FLG_SG_EMPTY;
456 						break;
457 					case 'o':
458 						sgp->sg_flags |= FLG_SG_ORDER;
459 						ofl->ofl_flags |=
460 						    FLG_OF_SEGORDER;
461 						break;
462 					case 'n':
463 						sgp->sg_flags |= FLG_SG_NOHDR;
464 						break;
465 					default:
466 						eprintf(ofl->ofl_lml, ERR_FATAL,
467 						    MSG_INTL(MSG_MAP_UNKSEGFLG),
468 						    mapfile, EC_XWORD(Line_num),
469 						    *flag_tok);
470 						return (S_ERROR);
471 					}
472 					flag_tok++;
473 				}
474 			}
475 			/*
476 			 * Warn when changing flags except when we're
477 			 * adding or removing "X" from a RW PT_LOAD
478 			 * segment.
479 			 */
480 			if ((sgp->sg_flags & FLG_SG_FLAGS) &&
481 			    (sgp->sg_phdr.p_flags != tmp_flags) &&
482 			    !(sgp->sg_phdr.p_type == PT_LOAD &&
483 			    (tmp_flags & (PF_R|PF_W)) == (PF_R|PF_W) &&
484 			    (tmp_flags ^ sgp->sg_phdr.p_flags) == PF_X)) {
485 				eprintf(ofl->ofl_lml, ERR_WARNING,
486 				    MSG_INTL(MSG_MAP_REDEFATT), mapfile,
487 				    EC_XWORD(Line_num),
488 				    MSG_INTL(MSG_MAP_SEGFLAG), sgp->sg_name);
489 			}
490 			sgp->sg_flags |= FLG_SG_FLAGS;
491 			sgp->sg_phdr.p_flags = tmp_flags;
492 			b_flags = TRUE;
493 		}
494 
495 
496 		/* Segment address, length, alignment or rounding number. */
497 
498 		else if ((Start_tok[0] == 'l') || (Start_tok[0] == 'v') ||
499 		    (Start_tok[0] == 'a') || (Start_tok[0] == 'p') ||
500 		    (Start_tok[0] == 'r')) {
501 			char		*end_tok;
502 			Xword		number;
503 
504 			if ((number = (Xword)STRTOADDR(&Start_tok[1], &end_tok,
505 			    0))	>= XWORD_MAX) {
506 				eprintf(ofl->ofl_lml, ERR_FATAL,
507 				    MSG_INTL(MSG_MAP_SEGADDR), mapfile,
508 				    EC_XWORD(Line_num), Start_tok,
509 				    MSG_INTL(MSG_MAP_EXCLIMIT));
510 				return (S_ERROR);
511 			}
512 
513 			if (end_tok != strchr(Start_tok, '\0')) {
514 				eprintf(ofl->ofl_lml, ERR_FATAL,
515 				    MSG_INTL(MSG_MAP_SEGADDR), mapfile,
516 				    EC_XWORD(Line_num), Start_tok,
517 				    MSG_INTL(MSG_MAP_NOBADFRM));
518 				return (S_ERROR);
519 			}
520 
521 			switch (*Start_tok) {
522 			case 'l':
523 				if (b_len) {
524 					eprintf(ofl->ofl_lml, ERR_FATAL,
525 					    MSG_INTL(MSG_MAP_MOREONCE),
526 					    mapfile, EC_XWORD(Line_num),
527 					    MSG_INTL(MSG_MAP_SEGLEN));
528 					return (S_ERROR);
529 				}
530 				if ((sgp->sg_flags & FLG_SG_LENGTH) &&
531 				    (sgp->sg_length != number))
532 					eprintf(ofl->ofl_lml, ERR_WARNING,
533 					    MSG_INTL(MSG_MAP_REDEFATT),
534 					    mapfile, EC_XWORD(Line_num),
535 					    MSG_INTL(MSG_MAP_SEGLEN),
536 					    sgp->sg_name);
537 				sgp->sg_length = number;
538 				sgp->sg_flags |= FLG_SG_LENGTH;
539 				b_len = TRUE;
540 				break;
541 			case 'r':
542 				if (b_round) {
543 					eprintf(ofl->ofl_lml, ERR_FATAL,
544 					    MSG_INTL(MSG_MAP_MOREONCE),
545 					    mapfile, EC_XWORD(Line_num),
546 					    MSG_INTL(MSG_MAP_SEGROUND));
547 					return (S_ERROR);
548 				}
549 				if ((sgp->sg_flags & FLG_SG_ROUND) &&
550 				    (sgp->sg_round != number))
551 					eprintf(ofl->ofl_lml, ERR_WARNING,
552 					    MSG_INTL(MSG_MAP_REDEFATT),
553 					    mapfile, EC_XWORD(Line_num),
554 					    MSG_INTL(MSG_MAP_SEGROUND),
555 					    sgp->sg_name);
556 				sgp->sg_round = number;
557 				sgp->sg_flags |= FLG_SG_ROUND;
558 				b_round = TRUE;
559 				break;
560 			case 'v':
561 				if (b_vaddr) {
562 					eprintf(ofl->ofl_lml, ERR_FATAL,
563 					    MSG_INTL(MSG_MAP_MOREONCE),
564 					    mapfile, EC_XWORD(Line_num),
565 					    MSG_INTL(MSG_MAP_SEGVADDR));
566 					return (S_ERROR);
567 				}
568 				if ((sgp->sg_flags & FLG_SG_VADDR) &&
569 				    (sgp->sg_phdr.p_vaddr != number))
570 					eprintf(ofl->ofl_lml, ERR_WARNING,
571 					    MSG_INTL(MSG_MAP_REDEFATT),
572 					    mapfile, EC_XWORD(Line_num),
573 					    MSG_INTL(MSG_MAP_SEGVADDR),
574 					    sgp->sg_name);
575 				/* LINTED */
576 				sgp->sg_phdr.p_vaddr = (Addr)number;
577 				sgp->sg_flags |= FLG_SG_VADDR;
578 				ofl->ofl_flags1 |= FLG_OF1_VADDR;
579 				b_vaddr = TRUE;
580 				break;
581 			case 'p':
582 				if (b_paddr) {
583 					eprintf(ofl->ofl_lml, ERR_FATAL,
584 					    MSG_INTL(MSG_MAP_MOREONCE),
585 					    mapfile, EC_XWORD(Line_num),
586 					    MSG_INTL(MSG_MAP_SEGPHYS));
587 					return (S_ERROR);
588 				}
589 				if ((sgp->sg_flags & FLG_SG_PADDR) &&
590 				    (sgp->sg_phdr.p_paddr != number))
591 					eprintf(ofl->ofl_lml, ERR_WARNING,
592 					    MSG_INTL(MSG_MAP_REDEFATT),
593 					    mapfile, EC_XWORD(Line_num),
594 					    MSG_INTL(MSG_MAP_SEGPHYS),
595 					    sgp->sg_name);
596 				/* LINTED */
597 				sgp->sg_phdr.p_paddr = (Addr)number;
598 				sgp->sg_flags |= FLG_SG_PADDR;
599 				b_paddr = TRUE;
600 				break;
601 			case 'a':
602 				if (b_align) {
603 					eprintf(ofl->ofl_lml, ERR_FATAL,
604 					    MSG_INTL(MSG_MAP_MOREONCE),
605 					    mapfile, EC_XWORD(Line_num),
606 					    MSG_INTL(MSG_MAP_SEGALIGN));
607 					return (S_ERROR);
608 				}
609 				if ((sgp->sg_flags & FLG_SG_ALIGN) &&
610 				    (sgp->sg_phdr.p_align != number))
611 					eprintf(ofl->ofl_lml, ERR_WARNING,
612 					    MSG_INTL(MSG_MAP_REDEFATT),
613 					    mapfile, EC_XWORD(Line_num),
614 					    MSG_INTL(MSG_MAP_SEGALIGN),
615 					    sgp->sg_name);
616 				/* LINTED */
617 				sgp->sg_phdr.p_align = (Xword)number;
618 				sgp->sg_flags |= FLG_SG_ALIGN;
619 				b_align = TRUE;
620 				break;
621 			}
622 		} else {
623 			eprintf(ofl->ofl_lml, ERR_FATAL,
624 			    MSG_INTL(MSG_MAP_UNKSEGATT), mapfile,
625 			    EC_XWORD(Line_num), Start_tok);
626 			return (S_ERROR);
627 		}
628 	}
629 
630 	/*
631 	 * Empty segments can be used to define PT_LOAD segment reservations, or
632 	 * to reserve PT_NULL program headers.
633 	 *
634 	 * PT_LOAD reservations are only allowed within executables, as the
635 	 * reservation must be established through exec() as part of initial
636 	 * process loading.  In addition, PT_LOAD reservations must have an
637 	 * associated address and size.
638 	 *
639 	 * PT_NULL program headers are established for later use by applications
640 	 * such as the post-optimizer.  PT_NULL headers should have no other
641 	 * attributes assigned.
642 	 */
643 	if ((sgp->sg_flags & FLG_SG_EMPTY) &&
644 	    (sgp->sg_phdr.p_type != PT_SUNWSTACK)) {
645 
646 		/*
647 		 * Any style of empty segment should have no permissions.
648 		 */
649 		if (sgp->sg_phdr.p_flags != 0) {
650 			eprintf(ofl->ofl_lml, ERR_FATAL,
651 			    MSG_INTL(MSG_MAP_SEGEMNOPERM), mapfile,
652 			    EC_XWORD(Line_num),
653 			    EC_WORD(sgp->sg_phdr.p_flags));
654 			return (S_ERROR);
655 		}
656 
657 		if (sgp->sg_phdr.p_type == PT_LOAD) {
658 			if ((ofl->ofl_flags & FLG_OF_EXEC) == 0) {
659 				eprintf(ofl->ofl_lml, ERR_FATAL,
660 				    MSG_INTL(MSG_MAP_SEGEMPEXE), mapfile,
661 				    EC_XWORD(Line_num));
662 				return (S_ERROR);
663 			}
664 			if ((sgp->sg_flags & (FLG_SG_LENGTH | FLG_SG_VADDR)) !=
665 			    (FLG_SG_LENGTH | FLG_SG_VADDR)) {
666 				eprintf(ofl->ofl_lml, ERR_FATAL,
667 				    MSG_INTL(MSG_MAP_SEGEMPATT), mapfile,
668 				    EC_XWORD(Line_num));
669 				return (S_ERROR);
670 			}
671 		} else if (sgp->sg_phdr.p_type == PT_NULL) {
672 			if ((sgp->sg_flags & (FLG_SG_LENGTH | FLG_SG_VADDR)) &&
673 			    ((sgp->sg_length != 0) ||
674 			    (sgp->sg_phdr.p_vaddr != 0))) {
675 				eprintf(ofl->ofl_lml, ERR_FATAL,
676 				    MSG_INTL(MSG_MAP_SEGEMPNOATT), mapfile,
677 				    EC_XWORD(Line_num));
678 				return (S_ERROR);
679 			}
680 		} else {
681 			eprintf(ofl->ofl_lml, ERR_WARNING,
682 			    MSG_INTL(MSG_MAP_SEGEMPLOAD), mapfile,
683 			    EC_XWORD(Line_num));
684 			sgp->sg_phdr.p_type = PT_LOAD;
685 		}
686 	}
687 
688 	/*
689 	 * All segment attributes have now been scanned.  Certain flags do not
690 	 * make sense if this is not a loadable segment, fix if necessary.
691 	 * Note, if the segment is of type PT_NULL it must be new, and any
692 	 * defaults will be applied back in ld_map_parse().
693 	 * When clearing an attribute leave the flag set as an indicator for
694 	 * later entries re-specifying the same segment.
695 	 */
696 	if ((sgp->sg_phdr.p_type != PT_NULL) &&
697 	    (sgp->sg_phdr.p_type != PT_LOAD)) {
698 		const char	*fmt;
699 
700 		if (sgp->sg_phdr.p_type == PT_SUNWSTACK)
701 			fmt = MSG_INTL(MSG_MAP_NOSTACK1);
702 		else
703 			fmt = MSG_INTL(MSG_MAP_NONLOAD);
704 
705 		if ((sgp->sg_flags & FLG_SG_FLAGS) &&
706 		    (sgp->sg_phdr.p_type != PT_SUNWSTACK)) {
707 			if (sgp->sg_phdr.p_flags != 0) {
708 				eprintf(ofl->ofl_lml, ERR_WARNING,
709 				    MSG_INTL(MSG_MAP_NONLOAD), mapfile,
710 				    EC_XWORD(Line_num),
711 				    MSG_INTL(MSG_MAP_SEGFLAG));
712 				sgp->sg_phdr.p_flags = 0;
713 			}
714 		}
715 		if (sgp->sg_flags & FLG_SG_LENGTH)
716 			if (sgp->sg_length != 0) {
717 				eprintf(ofl->ofl_lml, ERR_WARNING,
718 				    fmt, mapfile, EC_XWORD(Line_num),
719 				    MSG_INTL(MSG_MAP_SEGLEN));
720 				sgp->sg_length = 0;
721 			}
722 		if (sgp->sg_flags & FLG_SG_ROUND)
723 			if (sgp->sg_round != 0) {
724 				eprintf(ofl->ofl_lml, ERR_WARNING,
725 				    fmt, mapfile, EC_XWORD(Line_num),
726 				    MSG_INTL(MSG_MAP_SEGROUND));
727 				sgp->sg_round = 0;
728 			}
729 		if (sgp->sg_flags & FLG_SG_VADDR) {
730 			if (sgp->sg_phdr.p_vaddr != 0) {
731 				eprintf(ofl->ofl_lml, ERR_WARNING,
732 				    fmt, mapfile, EC_XWORD(Line_num),
733 				    MSG_INTL(MSG_MAP_SEGVADDR));
734 				sgp->sg_phdr.p_vaddr = 0;
735 			}
736 		}
737 		if (sgp->sg_flags & FLG_SG_PADDR)
738 			if (sgp->sg_phdr.p_paddr != 0) {
739 				eprintf(ofl->ofl_lml, ERR_WARNING,
740 				    fmt, mapfile, EC_XWORD(Line_num),
741 				    MSG_INTL(MSG_MAP_SEGPHYS));
742 				sgp->sg_phdr.p_paddr = 0;
743 			}
744 		if (sgp->sg_flags & FLG_SG_ALIGN)
745 			if (sgp->sg_phdr.p_align != 0) {
746 				eprintf(ofl->ofl_lml, ERR_WARNING,
747 				    fmt, mapfile, EC_XWORD(Line_num),
748 				    MSG_INTL(MSG_MAP_SEGALIGN));
749 				sgp->sg_phdr.p_align = 0;
750 			}
751 	}
752 	return (1);
753 }
754 
755 
756 /*
757  * Process a mapfile mapping directives definition.
758  * 	segment_name : section_attribute [ : file_name ]
759  * 	segment_attribute : section_name section_type section_flags;
760  */
761 static uintptr_t
762 map_colon(Ofl_desc *ofl, const char *mapfile, Ent_desc *enp)
763 {
764 	Token		tok;		/* Current token. */
765 
766 	Boolean		b_name = FALSE;
767 	Boolean		b_type = FALSE;
768 	Boolean		b_attr = FALSE;
769 	Boolean		b_bang = FALSE;
770 	static	Xword	index = 0;
771 
772 
773 	while (((tok = gettoken(ofl, mapfile)) != TK_COLON) &&
774 	    (tok != TK_SEMICOLON)) {
775 		/* LINTED */
776 		if (tok == (Token)S_ERROR)
777 			return (S_ERROR);
778 		if (tok == TK_EOF) {
779 			eprintf(ofl->ofl_lml, ERR_FATAL,
780 			    MSG_INTL(MSG_MAP_PREMEOF), mapfile,
781 			    EC_XWORD(Line_num));
782 			return (S_ERROR);
783 		}
784 
785 		/* Segment type. */
786 
787 		if (*Start_tok == '$') {
788 			if (b_type) {
789 				eprintf(ofl->ofl_lml, ERR_FATAL,
790 				    MSG_INTL(MSG_MAP_MOREONCE), mapfile,
791 				    EC_XWORD(Line_num),
792 				    MSG_INTL(MSG_MAP_SECTYP));
793 				return (S_ERROR);
794 			}
795 			b_type = TRUE;
796 			Start_tok++;
797 			lowercase(Start_tok);
798 			if (strcmp(Start_tok, MSG_ORIG(MSG_STR_PROGBITS)) == 0)
799 				enp->ec_type = SHT_PROGBITS;
800 			else if (strcmp(Start_tok,
801 			    MSG_ORIG(MSG_STR_SYMTAB)) == 0)
802 				enp->ec_type = SHT_SYMTAB;
803 			else if (strcmp(Start_tok,
804 			    MSG_ORIG(MSG_STR_DYNSYM)) == 0)
805 				enp->ec_type = SHT_DYNSYM;
806 			else if (strcmp(Start_tok,
807 			    MSG_ORIG(MSG_STR_STRTAB)) == 0)
808 				enp->ec_type = SHT_STRTAB;
809 			else if ((strcmp(Start_tok,
810 			    MSG_ORIG(MSG_STR_REL)) == 0) ||
811 			    (strcmp(Start_tok, MSG_ORIG(MSG_STR_RELA)) == 0))
812 				enp->ec_type = ld_targ.t_m.m_rel_sht_type;
813 			else if (strcmp(Start_tok, MSG_ORIG(MSG_STR_HASH)) == 0)
814 				enp->ec_type = SHT_HASH;
815 			else if (strcmp(Start_tok, MSG_ORIG(MSG_STR_LIB)) == 0)
816 				enp->ec_type = SHT_SHLIB;
817 			else if (strcmp(Start_tok,
818 			    MSG_ORIG(MSG_STR_LD_DYNAMIC)) == 0)
819 				enp->ec_type = SHT_DYNAMIC;
820 			else if (strcmp(Start_tok, MSG_ORIG(MSG_STR_NOTE)) == 0)
821 				enp->ec_type = SHT_NOTE;
822 			else if (strcmp(Start_tok,
823 			    MSG_ORIG(MSG_STR_NOBITS)) == 0)
824 				enp->ec_type = SHT_NOBITS;
825 			else {
826 				eprintf(ofl->ofl_lml, ERR_FATAL,
827 				    MSG_INTL(MSG_MAP_UNKSECTYP), mapfile,
828 				    EC_XWORD(Line_num), Start_tok);
829 				return (S_ERROR);
830 			}
831 
832 		/*
833 		 * Segment flags.
834 		 * If a segment flag is specified then the appropriate bit is
835 		 * set in the ec_attrmask, the ec_attrbits fields determine
836 		 * whether the attrmask fields must be tested true or false
837 		 * ie.	for  ?A the attrmask is set and the attrbit is set,
838 		 *	for ?!A the attrmask is set and the attrbit is clear.
839 		 */
840 		} else if (*Start_tok == '?') {
841 			if (b_attr) {
842 				eprintf(ofl->ofl_lml, ERR_FATAL,
843 				    MSG_INTL(MSG_MAP_MOREONCE), mapfile,
844 				    EC_XWORD(Line_num),
845 				    MSG_INTL(MSG_MAP_SECFLAG));
846 				return (S_ERROR);
847 			}
848 			b_attr = TRUE;
849 			b_bang = FALSE;
850 			Start_tok++;
851 			lowercase(Start_tok);
852 			for (; *Start_tok != '\0'; Start_tok++)
853 				switch (*Start_tok) {
854 				case '!':
855 					if (b_bang) {
856 						eprintf(ofl->ofl_lml, ERR_FATAL,
857 						    MSG_INTL(MSG_MAP_BADFLAG),
858 						    mapfile, EC_XWORD(Line_num),
859 						    Start_tok);
860 						return (S_ERROR);
861 					}
862 					b_bang = TRUE;
863 					break;
864 				case 'a':
865 					if (enp->ec_attrmask & SHF_ALLOC) {
866 						eprintf(ofl->ofl_lml, ERR_FATAL,
867 						    MSG_INTL(MSG_MAP_BADFLAG),
868 						    mapfile, EC_XWORD(Line_num),
869 						    Start_tok);
870 						return (S_ERROR);
871 					}
872 					enp->ec_attrmask |= SHF_ALLOC;
873 					if (!b_bang)
874 						enp->ec_attrbits |= SHF_ALLOC;
875 					b_bang = FALSE;
876 					break;
877 				case 'w':
878 					if (enp->ec_attrmask & SHF_WRITE) {
879 						eprintf(ofl->ofl_lml, ERR_FATAL,
880 						    MSG_INTL(MSG_MAP_BADFLAG),
881 						    mapfile, EC_XWORD(Line_num),
882 						    Start_tok);
883 						return (S_ERROR);
884 					}
885 					enp->ec_attrmask |= SHF_WRITE;
886 					if (!b_bang)
887 						enp->ec_attrbits |= SHF_WRITE;
888 					b_bang = FALSE;
889 					break;
890 				case 'x':
891 					if (enp->ec_attrmask & SHF_EXECINSTR) {
892 						eprintf(ofl->ofl_lml, ERR_FATAL,
893 						    MSG_INTL(MSG_MAP_BADFLAG),
894 						    mapfile, EC_XWORD(Line_num),
895 						    Start_tok);
896 						return (S_ERROR);
897 					}
898 					enp->ec_attrmask |= SHF_EXECINSTR;
899 					if (!b_bang)
900 						enp->ec_attrbits |=
901 						    SHF_EXECINSTR;
902 					b_bang = FALSE;
903 					break;
904 				default:
905 					eprintf(ofl->ofl_lml, ERR_FATAL,
906 					    MSG_INTL(MSG_MAP_BADFLAG),
907 					    mapfile, EC_XWORD(Line_num),
908 					    Start_tok);
909 					return (S_ERROR);
910 				}
911 		/*
912 		 * Section name.
913 		 */
914 		} else {
915 			if (b_name) {
916 				eprintf(ofl->ofl_lml, ERR_FATAL,
917 				    MSG_INTL(MSG_MAP_MOREONCE), mapfile,
918 				    EC_XWORD(Line_num),
919 				    MSG_INTL(MSG_MAP_SECNAME));
920 				return (S_ERROR);
921 			}
922 			b_name = TRUE;
923 			if ((enp->ec_name =
924 			    libld_malloc(strlen(Start_tok) + 1)) == 0)
925 				return (S_ERROR);
926 			(void) strcpy((char *)enp->ec_name, Start_tok);
927 			/*
928 			 * get the index for text reordering
929 			 */
930 			/* LINTED */
931 			enp->ec_ndx = (Word)++index;
932 		}
933 	}
934 	if (tok == TK_COLON) {
935 		/*
936 		 * File names.
937 		 */
938 		while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
939 			char	*file;
940 
941 			/* LINTED */
942 			if (tok == (Token)S_ERROR)
943 				return (S_ERROR);
944 			if (tok == TK_EOF) {
945 				eprintf(ofl->ofl_lml, ERR_FATAL,
946 				    MSG_INTL(MSG_MAP_PREMEOF), mapfile,
947 				    EC_XWORD(Line_num));
948 				return (S_ERROR);
949 			}
950 			if (tok != TK_STRING) {
951 				eprintf(ofl->ofl_lml, ERR_FATAL,
952 				    MSG_INTL(MSG_MAP_MALFORM), mapfile,
953 				    EC_XWORD(Line_num));
954 				return (S_ERROR);
955 			}
956 			if ((file =
957 			    libld_malloc(strlen(Start_tok) + 1)) == 0)
958 				return (S_ERROR);
959 			(void) strcpy(file, Start_tok);
960 			if (list_appendc(&(enp->ec_files), file) == 0)
961 				return (S_ERROR);
962 		}
963 	}
964 	return (1);
965 }
966 
967 /*
968  * Obtain a pseudo input file descriptor to assign to a mapfile.  This is
969  * required any time a symbol is generated.  First traverse the input file
970  * descriptors looking for a match.  As all mapfile processing occurs before
971  * any real input file processing this list is going to be small and we don't
972  * need to do any filename clash checking.
973  */
974 static Ifl_desc *
975 map_ifl(const char *mapfile, Ofl_desc *ofl)
976 {
977 	Ifl_desc	*ifl;
978 	Listnode	*lnp;
979 
980 	for (LIST_TRAVERSE(&ofl->ofl_objs, lnp, ifl))
981 		if (strcmp(ifl->ifl_name, mapfile) == 0)
982 			return (ifl);
983 
984 	if ((ifl = libld_calloc(sizeof (Ifl_desc), 1)) == 0)
985 		return ((Ifl_desc *)S_ERROR);
986 	ifl->ifl_name = mapfile;
987 	ifl->ifl_flags = (FLG_IF_MAPFILE | FLG_IF_NEEDED | FLG_IF_FILEREF);
988 	if ((ifl->ifl_ehdr = libld_calloc(sizeof (Ehdr), 1)) == 0)
989 		return ((Ifl_desc *)S_ERROR);
990 	ifl->ifl_ehdr->e_type = ET_REL;
991 
992 	if (list_appendc(&ofl->ofl_objs, ifl) == 0)
993 		return ((Ifl_desc *)S_ERROR);
994 	else
995 		return (ifl);
996 }
997 
998 /*
999  * Process a mapfile size symbol definition.
1000  * 	segment_name @ symbol_name;
1001  */
1002 static uintptr_t
1003 map_atsign(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl)
1004 {
1005 	Sym		*sym;		/* New symbol pointer */
1006 	Sym_desc	*sdp;		/* New symbol node pointer */
1007 	Ifl_desc	*ifl;		/* Dummy input file structure */
1008 	Token		tok;		/* Current token. */
1009 	avl_index_t	where;
1010 
1011 	if ((tok = gettoken(ofl, mapfile)) != TK_STRING) {
1012 		/* LINTED */
1013 		if (tok != (Token)S_ERROR)
1014 			eprintf(ofl->ofl_lml, ERR_FATAL,
1015 			    MSG_INTL(MSG_MAP_EXPSYM_1), mapfile,
1016 			    EC_XWORD(Line_num));
1017 		return (S_ERROR);
1018 	}
1019 
1020 	if (sgp->sg_sizesym != NULL) {
1021 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_MAP_SEGSIZE),
1022 		    mapfile, EC_XWORD(Line_num), sgp->sg_name);
1023 		return (S_ERROR);
1024 	}
1025 
1026 	/*
1027 	 * Make sure we have a pseudo file descriptor to associate to the
1028 	 * symbol.
1029 	 */
1030 	if ((ifl = map_ifl(mapfile, ofl)) == (Ifl_desc *)S_ERROR)
1031 		return (S_ERROR);
1032 
1033 	/*
1034 	 * Make sure the symbol doesn't already exist.  It is possible that the
1035 	 * symbol has been scoped or versioned, in which case it does exist
1036 	 * but we can freely update it here.
1037 	 */
1038 	if ((sdp = ld_sym_find(Start_tok, SYM_NOHASH, &where, ofl)) == NULL) {
1039 		char	*name;
1040 		Word hval;
1041 
1042 		if ((name = libld_malloc(strlen(Start_tok) + 1)) == 0)
1043 			return (S_ERROR);
1044 		(void) strcpy(name, Start_tok);
1045 
1046 		if ((sym = libld_calloc(sizeof (Sym), 1)) == 0)
1047 			return (S_ERROR);
1048 		sym->st_shndx = SHN_ABS;
1049 		sym->st_size = 0;
1050 		sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
1051 
1052 		DBG_CALL(Dbg_map_size_new(ofl->ofl_lml, name));
1053 		/* LINTED */
1054 		hval = (Word)elf_hash(name);
1055 		if ((sdp = ld_sym_enter(name, sym, hval, ifl, ofl, 0, SHN_ABS,
1056 		    (FLG_SY_SPECSEC | FLG_SY_GLOBREF), 0, &where)) ==
1057 		    (Sym_desc *)S_ERROR)
1058 			return (S_ERROR);
1059 		sdp->sd_flags &= ~FLG_SY_CLEAN;
1060 		DBG_CALL(Dbg_map_symbol(ofl, sdp));
1061 	} else {
1062 		sym = sdp->sd_sym;
1063 
1064 		if (sym->st_shndx == SHN_UNDEF) {
1065 			sdp->sd_shndx = sym->st_shndx = SHN_ABS;
1066 			sdp->sd_flags |= FLG_SY_SPECSEC;
1067 			sym->st_size = 0;
1068 			sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
1069 
1070 			sdp->sd_flags &= ~FLG_SY_MAPREF;
1071 
1072 			DBG_CALL(Dbg_map_size_old(ofl, sdp));
1073 		} else {
1074 			eprintf(ofl->ofl_lml, ERR_FATAL,
1075 			    MSG_INTL(MSG_MAP_SYMDEF1), mapfile,
1076 			    EC_XWORD(Line_num), demangle(sdp->sd_name),
1077 			    sdp->sd_file->ifl_name,
1078 			    MSG_INTL(MSG_MAP_DIFF_SYMMUL));
1079 			return (S_ERROR);
1080 		}
1081 	}
1082 
1083 	/*
1084 	 * Assign the symbol to the segment.
1085 	 */
1086 	sgp->sg_sizesym = sdp;
1087 
1088 	if (gettoken(ofl, mapfile) != TK_SEMICOLON) {
1089 		/* LINTED */
1090 		if (tok != (Token)S_ERROR)
1091 			eprintf(ofl->ofl_lml, ERR_FATAL,
1092 			    MSG_INTL(MSG_MAP_EXPSCOL), mapfile,
1093 			    EC_XWORD(Line_num));
1094 		return (S_ERROR);
1095 	} else
1096 		return (1);
1097 }
1098 
1099 
1100 static uintptr_t
1101 map_pipe(Ofl_desc *ofl, const char *mapfile, Sg_desc *sgp)
1102 {
1103 	char		*sec_name;	/* section name */
1104 	Token		tok;		/* current token. */
1105 	Sec_order	*sc_order;
1106 	static Word	index = 0;	/* used to maintain a increasing */
1107 					/* 	index for section ordering. */
1108 
1109 	if ((tok = gettoken(ofl, mapfile)) != TK_STRING) {
1110 		/* LINTED */
1111 		if (tok != (Token)S_ERROR)
1112 			eprintf(ofl->ofl_lml, ERR_FATAL,
1113 			    MSG_INTL(MSG_MAP_EXPSEC), mapfile,
1114 			    EC_XWORD(Line_num));
1115 		return (S_ERROR);
1116 	}
1117 
1118 	if ((sec_name = libld_malloc(strlen(Start_tok) + 1)) == 0)
1119 		return (S_ERROR);
1120 	(void) strcpy(sec_name, Start_tok);
1121 
1122 	if ((sc_order = libld_malloc(sizeof (Sec_order))) == 0)
1123 		return (S_ERROR);
1124 
1125 	sc_order->sco_secname = sec_name;
1126 	sc_order->sco_index = ++index;
1127 
1128 	if (aplist_append(&sgp->sg_secorder, sc_order,
1129 	    AL_CNT_SG_SECORDER) == NULL)
1130 		return (S_ERROR);
1131 
1132 	DBG_CALL(Dbg_map_pipe(ofl->ofl_lml, sgp, sec_name, index));
1133 
1134 	if ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
1135 		/* LINTED */
1136 		if (tok != (Token)S_ERROR)
1137 			eprintf(ofl->ofl_lml, ERR_FATAL,
1138 			    MSG_INTL(MSG_MAP_EXPSCOL), mapfile,
1139 			    EC_XWORD(Line_num));
1140 		return (S_ERROR);
1141 	}
1142 
1143 	return (1);
1144 }
1145 
1146 
1147 /*
1148  * Process a mapfile library specification definition.
1149  * 	shared_object_name - shared object definition
1150  *	shared object definition : [ shared object type [ = SONAME ]]
1151  *					[ versions ];
1152  */
1153 static uintptr_t
1154 map_dash(const char *mapfile, char *name, Ofl_desc *ofl)
1155 {
1156 	char		*version;
1157 	Token		tok;
1158 	Sdf_desc	*sdf;
1159 	Sdv_desc	*sdv;
1160 	enum {
1161 	    MD_NONE = 0,
1162 	    MD_SPECVERS,
1163 	    MD_ADDVERS,
1164 	    MD_NEEDED
1165 	}		dolkey = MD_NONE;
1166 
1167 
1168 	/*
1169 	 * If a shared object definition for this file already exists use it,
1170 	 * otherwise allocate a new descriptor.
1171 	 */
1172 	if ((sdf = sdf_find(name, &ofl->ofl_socntl)) == 0) {
1173 		if ((sdf = sdf_add(name, &ofl->ofl_socntl)) ==
1174 		    (Sdf_desc *)S_ERROR)
1175 			return (S_ERROR);
1176 		sdf->sdf_rfile = mapfile;
1177 	}
1178 
1179 	/*
1180 	 * Get the shared object descriptor string.
1181 	 */
1182 	while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
1183 		/* LINTED */
1184 		if (tok == (Token)S_ERROR)
1185 			return (S_ERROR);
1186 		if (tok == TK_EOF) {
1187 			eprintf(ofl->ofl_lml, ERR_FATAL,
1188 			    MSG_INTL(MSG_MAP_PREMEOF), mapfile,
1189 			    EC_XWORD(Line_num));
1190 			return (S_ERROR);
1191 		}
1192 		if ((tok != TK_STRING) && (tok != TK_EQUAL)) {
1193 			eprintf(ofl->ofl_lml, ERR_FATAL,
1194 			    MSG_INTL(MSG_MAP_EXPSO), mapfile,
1195 			    EC_XWORD(Line_num));
1196 			return (S_ERROR);
1197 		}
1198 
1199 		/*
1200 		 * Determine if the library type is accompanied with a SONAME
1201 		 * definition.
1202 		 */
1203 		if (tok == TK_EQUAL) {
1204 			if ((tok = gettoken(ofl, mapfile)) != TK_STRING) {
1205 				/* LINTED */
1206 				if (tok == (Token)S_ERROR)
1207 					return (S_ERROR);
1208 				else {
1209 					eprintf(ofl->ofl_lml, ERR_FATAL,
1210 					    MSG_INTL(MSG_MAP_EXPSO), mapfile,
1211 					    EC_XWORD(Line_num));
1212 					return (S_ERROR);
1213 				}
1214 			}
1215 			switch (dolkey) {
1216 			case MD_NEEDED:
1217 				if (sdf->sdf_flags & FLG_SDF_SONAME) {
1218 					eprintf(ofl->ofl_lml, ERR_WARNING,
1219 					    MSG_INTL(MSG_MAP_MULSONAME),
1220 					    mapfile, EC_XWORD(Line_num), name,
1221 					    sdf->sdf_soname, Start_tok);
1222 					dolkey = MD_NONE;
1223 					continue;
1224 				}
1225 				if ((sdf->sdf_soname =
1226 				    libld_malloc(strlen(Start_tok) + 1)) == 0)
1227 					return (S_ERROR);
1228 				(void) strcpy((char *)sdf->sdf_soname,
1229 				    Start_tok);
1230 				sdf->sdf_flags |= FLG_SDF_SONAME;
1231 				break;
1232 			case MD_SPECVERS:
1233 			case MD_ADDVERS:
1234 				if ((sdv = libld_calloc(
1235 				    sizeof (Sdv_desc), 1)) == 0)
1236 					return (S_ERROR);
1237 
1238 				if (dolkey == MD_SPECVERS)
1239 					sdf->sdf_flags |= FLG_SDF_SPECVER;
1240 				else
1241 					sdf->sdf_flags |= FLG_SDF_ADDVER;
1242 
1243 				if ((sdf->sdf_flags & (FLG_SDF_SPECVER |
1244 				    FLG_SDF_ADDVER)) == (FLG_SDF_SPECVER |
1245 				    FLG_SDF_ADDVER)) {
1246 					eprintf(ofl->ofl_lml, ERR_FATAL,
1247 					    MSG_INTL(MSG_MAP_INCOMFLG),
1248 					    mapfile, EC_XWORD(Line_num),
1249 					    sdf->sdf_name);
1250 					return (S_ERROR);
1251 				}
1252 				if ((version =
1253 				    libld_malloc(strlen(Start_tok) + 1)) == 0)
1254 					return (S_ERROR);
1255 				(void) strcpy(version, Start_tok);
1256 				sdv->sdv_name = version;
1257 				sdv->sdv_ref = mapfile;
1258 				if (list_appendc(&sdf->sdf_verneed, sdv) == 0)
1259 					return (S_ERROR);
1260 				break;
1261 			case MD_NONE:
1262 				eprintf(ofl->ofl_lml, ERR_FATAL,
1263 				    MSG_INTL(MSG_MAP_UNEXTOK), mapfile,
1264 				    EC_XWORD(Line_num), '=');
1265 				return (S_ERROR);
1266 			}
1267 			dolkey = MD_NONE;
1268 			continue;
1269 		}
1270 
1271 		/*
1272 		 * A shared object type has been specified.  This may also be
1273 		 * accompanied by an SONAME redefinition (see above).
1274 		 */
1275 		if (*Start_tok == '$') {
1276 			if (dolkey != MD_NONE) {
1277 				eprintf(ofl->ofl_lml, ERR_FATAL,
1278 				    MSG_INTL(MSG_MAP_UNEXTOK), mapfile,
1279 				    EC_XWORD(Line_num), '$');
1280 				return (S_ERROR);
1281 			}
1282 			Start_tok++;
1283 			lowercase(Start_tok);
1284 			if (strcmp(Start_tok,
1285 			    MSG_ORIG(MSG_MAP_NEED)) == 0)
1286 				dolkey = MD_NEEDED;
1287 			else if (strcmp(Start_tok,
1288 			    MSG_ORIG(MSG_MAP_SPECVERS)) == 0)
1289 				dolkey = MD_SPECVERS;
1290 			else if (strcmp(Start_tok,
1291 			    MSG_ORIG(MSG_MAP_ADDVERS)) == 0)
1292 				dolkey = MD_ADDVERS;
1293 			else {
1294 				eprintf(ofl->ofl_lml, ERR_FATAL,
1295 				    MSG_INTL(MSG_MAP_UNKSOTYP), mapfile,
1296 				    EC_XWORD(Line_num), Start_tok);
1297 				return (S_ERROR);
1298 			}
1299 			continue;
1300 		}
1301 
1302 		/*
1303 		 * shared object version requirement.
1304 		 */
1305 		if ((version = libld_malloc(strlen(Start_tok) + 1)) == 0)
1306 			return (S_ERROR);
1307 		(void) strcpy(version, Start_tok);
1308 		if ((sdv = libld_calloc(sizeof (Sdv_desc), 1)) == 0)
1309 			return (S_ERROR);
1310 		sdv->sdv_name = version;
1311 		sdv->sdv_ref = mapfile;
1312 		sdf->sdf_flags |= FLG_SDF_SELECT;
1313 		if (list_appendc(&sdf->sdf_vers, sdv) == 0)
1314 			return (S_ERROR);
1315 	}
1316 
1317 	DBG_CALL(Dbg_map_dash(ofl->ofl_lml, name, sdf));
1318 	return (1);
1319 }
1320 
1321 
1322 /*
1323  * Process a symbol definition.  Historically, this originated from processing
1324  * a version definition.  However, this has evolved into a generic means of
1325  * defining symbol references and definitions (see Defining Additional Symbols
1326  * in the Linker and Libraries guide for the complete syntax).
1327  *
1328  * [ name ] {
1329  *	scope:
1330  *		 symbol [ = [ type ] [ value ] [ size ] [ attribute ] ];
1331  * } [ dependency ];
1332  *
1333  */
1334 #define	FLG_SCOPE_HIDD	0		/* symbol defined hidden/local */
1335 #define	FLG_SCOPE_DFLT	1		/* symbol defined default/global */
1336 #define	FLG_SCOPE_PROT	2		/* symbol defined protected/symbolic */
1337 #define	FLG_SCOPE_EXPT	3		/* symbol defined exported */
1338 #define	FLG_SCOPE_SNGL	4		/* symbol defined singleton */
1339 #define	FLG_SCOPE_ELIM	5		/* symbol defined eliminate */
1340 
1341 static uintptr_t
1342 map_version(const char *mapfile, char *name, Ofl_desc *ofl)
1343 {
1344 	Token		tok;
1345 	Sym		*sym;
1346 	int		scope = FLG_SCOPE_DFLT, errcnt = 0;
1347 	Ver_desc	*vdp;
1348 	Word		hash;
1349 	Ifl_desc	*ifl;
1350 	avl_index_t	where;
1351 
1352 	/*
1353 	 * If we're generating segments within the image then any symbol
1354 	 * reductions will be processed (ie. applied to relocations and symbol
1355 	 * table entries).  Otherwise (when creating a relocatable object) any
1356 	 * versioning information is simply recorded for use in a later
1357 	 * (segment generating) link-edit.
1358 	 */
1359 	if (ofl->ofl_flags & FLG_OF_RELOBJ)
1360 		ofl->ofl_flags |= FLG_OF_VERDEF;
1361 
1362 	/*
1363 	 * If this is a new mapfile reference generate an input file descriptor
1364 	 * to represent it.  Otherwise this must simply be a new version within
1365 	 * the mapfile we've previously been processing, in this case continue
1366 	 * to use the original input file descriptor.
1367 	 */
1368 	if ((ifl = map_ifl(mapfile, ofl)) == (Ifl_desc *)S_ERROR)
1369 		return (S_ERROR);
1370 
1371 	/*
1372 	 * If no version descriptors have yet been set up, initialize a base
1373 	 * version to represent the output file itself.  This `base' version
1374 	 * catches any internally generated symbols (_end, _etext, etc.) and
1375 	 * serves to initialize the output version descriptor count.
1376 	 */
1377 	if (ofl->ofl_vercnt == 0) {
1378 		if (ld_vers_base(ofl) == (Ver_desc *)S_ERROR)
1379 			return (S_ERROR);
1380 	}
1381 
1382 	/*
1383 	 * If this definition has an associated version name then generate a
1384 	 * new version descriptor and an associated version symbol index table.
1385 	 */
1386 	if (name) {
1387 		ofl->ofl_flags |= FLG_OF_VERDEF;
1388 
1389 		/*
1390 		 * Traverse the present version descriptor list to see if there
1391 		 * is already one of the same name, otherwise create a new one.
1392 		 */
1393 		/* LINTED */
1394 		hash = (Word)elf_hash(name);
1395 		if ((vdp = ld_vers_find(name, hash, &ofl->ofl_verdesc)) == 0) {
1396 			if ((vdp = ld_vers_desc(name, hash,
1397 			    &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR)
1398 				return (S_ERROR);
1399 		}
1400 
1401 		/*
1402 		 * Initialize any new version with an index, the file from which
1403 		 * it was first referenced, and a WEAK flag (indicates that
1404 		 * there are no symbols assigned to it yet).
1405 		 */
1406 		if (vdp->vd_ndx == 0) {
1407 			/* LINTED */
1408 			vdp->vd_ndx = (Half)++ofl->ofl_vercnt;
1409 			vdp->vd_file = ifl;
1410 			vdp->vd_flags = VER_FLG_WEAK;
1411 		}
1412 	} else {
1413 		/*
1414 		 * If a version definition hasn't been specified assign any
1415 		 * symbols to the base version.
1416 		 */
1417 		vdp = (Ver_desc *)ofl->ofl_verdesc.head->data;
1418 	}
1419 
1420 	/*
1421 	 * Scan the mapfile entry picking out scoping and symbol definitions.
1422 	 */
1423 	while ((tok = gettoken(ofl, mapfile)) != TK_RIGHTBKT) {
1424 		Sym_desc * 	sdp;
1425 		Word		shndx = SHN_UNDEF;
1426 		uchar_t 	type = STT_NOTYPE;
1427 		Addr		value = 0, size = 0;
1428 		char		*_name, *filtee = 0;
1429 		Word		sym_flags = 0;
1430 		Half		sym_flags1 = 0;
1431 		uint_t		filter = 0, novalue = 1, dftflag;
1432 		const char	*conflict;
1433 
1434 		if ((tok != TK_STRING) && (tok != TK_COLON)) {
1435 			eprintf(ofl->ofl_lml, ERR_FATAL,
1436 			    MSG_INTL(MSG_MAP_EXPSYM_2), mapfile,
1437 			    EC_XWORD(Line_num));
1438 			errcnt++;
1439 			continue;
1440 		}
1441 
1442 		if ((_name = libld_malloc(strlen(Start_tok) + 1)) == 0)
1443 			return (S_ERROR);
1444 		(void) strcpy(_name, Start_tok);
1445 
1446 		if ((tok != TK_COLON) &&
1447 		    /* LINTED */
1448 		    (tok = gettoken(ofl, mapfile)) == (Token)S_ERROR) {
1449 			errcnt++;
1450 			continue;
1451 		}
1452 
1453 		/*
1454 		 * Turn off the WEAK flag to indicate that definitions are
1455 		 * associated with this version.  It would probably be more
1456 		 * accurate to only remove this flag with the specification of
1457 		 * global symbols, however setting it here allows enough slop
1458 		 * to compensate for the various user inputs we've seen so far.
1459 		 * Only if a closed version is specified (i.e., "SUNW_1.x {};")
1460 		 * will a user get a weak version (which is how we document the
1461 		 * creation of weak versions).
1462 		 */
1463 		vdp->vd_flags &= ~VER_FLG_WEAK;
1464 
1465 		switch (tok) {
1466 		case TK_COLON:
1467 			/*
1468 			 * Establish a new scope.  All symbols added by this
1469 			 * mapfile are actually global entries, and are assigned
1470 			 * the scope that is presently in effect.
1471 			 *
1472 			 * If a protected/symbolic scope is detected, remember
1473 			 * this.  If a protected/symbolic scope is the only
1474 			 * scope defined in this (or any other mapfiles), then
1475 			 * the mode -Bsymbolic is established.
1476 			 */
1477 			if ((strcmp(MSG_ORIG(MSG_MAP_DEFAULT), _name) == 0) ||
1478 			    (strcmp(MSG_ORIG(MSG_MAP_GLOBAL), _name) == 0)) {
1479 				scope = FLG_SCOPE_DFLT;
1480 				ofl->ofl_flags |= FLG_OF_MAPGLOB;
1481 
1482 			} else if ((strcmp(MSG_ORIG(MSG_MAP_HIDDEN),
1483 			    _name) == 0) ||
1484 			    (strcmp(MSG_ORIG(MSG_STR_LOCAL), _name) == 0)) {
1485 				scope = FLG_SCOPE_HIDD;
1486 
1487 			} else if ((strcmp(MSG_ORIG(MSG_MAP_PROTECTED),
1488 			    _name) == 0) ||
1489 			    (strcmp(MSG_ORIG(MSG_STR_SYMBOLIC), _name) == 0)) {
1490 				scope = FLG_SCOPE_PROT;
1491 				ofl->ofl_flags |= FLG_OF_MAPSYMB;
1492 
1493 			} else if (strcmp(MSG_ORIG(MSG_STR_EXPORTED),
1494 			    _name) == 0) {
1495 				scope = FLG_SCOPE_EXPT;
1496 
1497 			} else if (strcmp(MSG_ORIG(MSG_STR_SINGLETON),
1498 			    _name) == 0) {
1499 				scope = FLG_SCOPE_SNGL;
1500 				ofl->ofl_flags |= FLG_OF_MAPGLOB;
1501 
1502 			} else if (strcmp(MSG_ORIG(MSG_STR_ELIMINATE),
1503 			    _name) == 0) {
1504 				scope = FLG_SCOPE_ELIM;
1505 
1506 			} else {
1507 				eprintf(ofl->ofl_lml, ERR_FATAL,
1508 				    MSG_INTL(MSG_MAP_UNKSYMSCO), mapfile,
1509 				    EC_XWORD(Line_num), _name);
1510 				errcnt++;
1511 			}
1512 			continue;
1513 
1514 		case TK_EQUAL:
1515 			/*
1516 			 * A full blown symbol definition follows.
1517 			 * Determine the symbol type and any virtual address or
1518 			 * alignment specified and then fall through to process
1519 			 * the entire symbols information.
1520 			 */
1521 			while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
1522 				/*
1523 				 * If we had previously seen a filter or
1524 				 * auxiliary filter requirement, the next string
1525 				 * is the filtee itself.
1526 				 */
1527 				if (filter) {
1528 					if (filtee) {
1529 					    /* BEGIN CSTYLED */
1530 					    eprintf(ofl->ofl_lml, ERR_FATAL,
1531 						MSG_INTL(MSG_MAP_MULTFILTEE),
1532 						mapfile, EC_XWORD(Line_num),
1533 						_name);
1534 					    errcnt++;
1535 					    continue;
1536 					    /* END CSTYLED */
1537 					}
1538 					if ((filtee = libld_malloc(
1539 					    strlen(Start_tok) + 1)) == 0)
1540 						return (S_ERROR);
1541 					(void) strcpy(filtee, Start_tok);
1542 					filter = 0;
1543 					continue;
1544 				}
1545 
1546 				/*
1547 				 * Determine any Value or Size attributes.
1548 				 */
1549 				lowercase(Start_tok);
1550 
1551 				if (Start_tok[0] == 'v' ||
1552 				    Start_tok[0] == 's') {
1553 					char		*end_tok;
1554 					Lword		number;
1555 
1556 					if ((number = (Lword)STRTOADDR(
1557 					    &Start_tok[1], &end_tok, 0)) ==
1558 					    XWORD_MAX) {
1559 						eprintf(ofl->ofl_lml, ERR_FATAL,
1560 						    MSG_INTL(MSG_MAP_SEGADDR),
1561 						    mapfile, EC_XWORD(Line_num),
1562 						    Start_tok,
1563 						    MSG_INTL(MSG_MAP_EXCLIMIT));
1564 						errcnt++;
1565 						continue;
1566 					}
1567 
1568 					if (end_tok !=
1569 					    strchr(Start_tok, '\0')) {
1570 						eprintf(ofl->ofl_lml, ERR_FATAL,
1571 						    MSG_INTL(MSG_MAP_SEGADDR),
1572 						    mapfile, EC_XWORD(Line_num),
1573 						    Start_tok,
1574 						    MSG_INTL(MSG_MAP_NOBADFRM));
1575 						errcnt++;
1576 						continue;
1577 					}
1578 
1579 					switch (*Start_tok) {
1580 					case 'v':
1581 					    /* BEGIN CSTYLED */
1582 					    if (value) {
1583 						eprintf(ofl->ofl_lml, ERR_FATAL,
1584 						    MSG_INTL(MSG_MAP_MOREONCE),
1585 						    mapfile, EC_XWORD(Line_num),
1586 						    MSG_INTL(MSG_MAP_SYMVAL));
1587 						errcnt++;
1588 						continue;
1589 					    }
1590 					    /* LINTED */
1591 					    value = (Addr)number;
1592 					    novalue = 0;
1593 					    break;
1594 					    /* END CSTYLED */
1595 					case 's':
1596 					    /* BEGIN CSTYLED */
1597 					    if (size) {
1598 						eprintf(ofl->ofl_lml, ERR_FATAL,
1599 						    MSG_INTL(MSG_MAP_MOREONCE),
1600 						    mapfile, EC_XWORD(Line_num),
1601 						    MSG_INTL(MSG_MAP_SYMSIZE));
1602 						errcnt++;
1603 						continue;
1604 					    }
1605 					    /* LINTED */
1606 					    size = (Addr)number;
1607 					    break;
1608 					    /* END CSTYLED */
1609 					}
1610 
1611 				} else if (strcmp(Start_tok,
1612 				    MSG_ORIG(MSG_MAP_FUNCTION)) == 0) {
1613 					shndx = SHN_ABS;
1614 					sym_flags |= FLG_SY_SPECSEC;
1615 					type = STT_FUNC;
1616 				} else if (strcmp(Start_tok,
1617 				    MSG_ORIG(MSG_MAP_DATA)) == 0) {
1618 					shndx = SHN_ABS;
1619 					sym_flags |= FLG_SY_SPECSEC;
1620 					type = STT_OBJECT;
1621 				} else if (strcmp(Start_tok,
1622 				    MSG_ORIG(MSG_MAP_COMMON)) == 0) {
1623 					shndx = SHN_COMMON;
1624 					sym_flags |= FLG_SY_SPECSEC;
1625 					type = STT_OBJECT;
1626 				} else if (strcmp(Start_tok,
1627 				    MSG_ORIG(MSG_MAP_PARENT)) == 0) {
1628 					sym_flags |= FLG_SY_PARENT;
1629 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1630 				} else if (strcmp(Start_tok,
1631 				    MSG_ORIG(MSG_MAP_EXTERN)) == 0) {
1632 					sym_flags |= FLG_SY_EXTERN;
1633 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1634 				} else if (strcmp(Start_tok,
1635 				    MSG_ORIG(MSG_MAP_DIRECT)) == 0) {
1636 					sym_flags1 |= FLG_SY1_DIR;
1637 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1638 				} else if (strcmp(Start_tok,
1639 				    MSG_ORIG(MSG_MAP_NODIRECT)) == 0) {
1640 					sym_flags1 |= FLG_SY1_NDIR;
1641 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1642 					ofl->ofl_flags1 |= FLG_OF1_NDIRECT;
1643 				} else if (strcmp(Start_tok,
1644 				    MSG_ORIG(MSG_MAP_FILTER)) == 0) {
1645 					dftflag = filter = FLG_SY_STDFLTR;
1646 					sym_flags |= FLG_SY_STDFLTR;
1647 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1648 					continue;
1649 				} else if (strcmp(Start_tok,
1650 				    MSG_ORIG(MSG_MAP_AUXILIARY)) == 0) {
1651 					dftflag = filter = FLG_SY_AUXFLTR;
1652 					sym_flags |= FLG_SY_AUXFLTR;
1653 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1654 					continue;
1655 				} else if (strcmp(Start_tok,
1656 				    MSG_ORIG(MSG_MAP_INTERPOSE)) == 0) {
1657 					if (!(ofl->ofl_flags & FLG_OF_EXEC)) {
1658 						eprintf(ofl->ofl_lml, ERR_FATAL,
1659 						    MSG_INTL(MSG_MAP_NOINTPOSE),
1660 						    mapfile,
1661 						    EC_XWORD(Line_num));
1662 						errcnt++;
1663 						continue;
1664 					}
1665 					sym_flags |= FLG_SY_INTPOSE;
1666 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1667 					ofl->ofl_dtflags_1 |= DF_1_SYMINTPOSE;
1668 					continue;
1669 				} else if (strcmp(Start_tok,
1670 				    MSG_ORIG(MSG_MAP_DYNSORT)) == 0) {
1671 					sym_flags |= FLG_SY_DYNSORT;
1672 					sym_flags &= ~FLG_SY_NODYNSORT;
1673 					continue;
1674 				} else if (strcmp(Start_tok,
1675 				    MSG_ORIG(MSG_MAP_NODYNSORT)) == 0) {
1676 					sym_flags &= ~FLG_SY_DYNSORT;
1677 					sym_flags |= FLG_SY_NODYNSORT;
1678 					continue;
1679 				} else {
1680 					eprintf(ofl->ofl_lml, ERR_FATAL,
1681 					    MSG_INTL(MSG_MAP_UNKSYMDEF),
1682 					    mapfile, EC_XWORD(Line_num),
1683 					    Start_tok);
1684 					errcnt++;
1685 					continue;
1686 				}
1687 			}
1688 			/* FALLTHROUGH */
1689 
1690 		case TK_SEMICOLON:
1691 			/*
1692 			 * The special auto-reduction directive `*' can be
1693 			 * specified in hidden/local, and eliminate scope.  This
1694 			 * directive indicates that all symbols processed that
1695 			 * are not explicitly defined to be global are to be
1696 			 * reduced to hidden/local scope in, or eliminated from,
1697 			 * the output image.
1698 			 *
1699 			 * An auto-reduction directive also implies that a
1700 			 * version definition be created, as the user has
1701 			 * effectively defined an interface.
1702 			 */
1703 			if (*_name == '*') {
1704 				if (scope == FLG_SCOPE_HIDD)
1705 					ofl->ofl_flags |=
1706 					    (FLG_OF_VERDEF | FLG_OF_AUTOLCL);
1707 				else if (scope == FLG_SCOPE_ELIM) {
1708 					ofl->ofl_flags |= FLG_OF_VERDEF;
1709 					ofl->ofl_flags1 |= FLG_OF1_AUTOELM;
1710 				}
1711 				continue;
1712 			}
1713 
1714 			/*
1715 			 * Add the new symbol.  It should be noted that all
1716 			 * symbols added by the mapfile start out with global
1717 			 * scope, thus they will fall through the normal symbol
1718 			 * resolution process.  Symbols defined as locals will
1719 			 * be reduced in scope after all input file processing.
1720 			 */
1721 			/* LINTED */
1722 			hash = (Word)elf_hash(_name);
1723 			DBG_CALL(Dbg_map_version(ofl->ofl_lml, name, _name,
1724 			    scope));
1725 			if ((sdp = ld_sym_find(_name, hash, &where,
1726 			    ofl)) == NULL) {
1727 				if ((sym = libld_calloc(sizeof (Sym), 1)) == 0)
1728 					return (S_ERROR);
1729 
1730 				/*
1731 				 * Make sure any parent or external declarations
1732 				 * fall back to references.
1733 				 */
1734 				if (sym_flags &
1735 				    (FLG_SY_PARENT | FLG_SY_EXTERN)) {
1736 					/*
1737 					 * Turn it into a reference by setting
1738 					 * the section index to UNDEF.
1739 					 */
1740 					sym->st_shndx = shndx = SHN_UNDEF;
1741 
1742 					/*
1743 					 * It is wrong to to specify size
1744 					 * or value for an external symbol.
1745 					 */
1746 					if ((novalue == 0) || (size != 0)) {
1747 						eprintf(ofl->ofl_lml, ERR_FATAL,
1748 						    MSG_INTL(MSG_MAP_NOEXVLSZ),
1749 						    mapfile,
1750 						    EC_XWORD(Line_num));
1751 						errcnt++;
1752 						continue;
1753 					}
1754 				} else {
1755 					sym->st_shndx = (Half)shndx;
1756 				}
1757 
1758 				sym->st_value = value;
1759 				sym->st_size = size;
1760 				sym->st_info = ELF_ST_INFO(STB_GLOBAL, type);
1761 
1762 				if ((sdp = ld_sym_enter(_name, sym, hash, ifl,
1763 				    ofl, 0, shndx, sym_flags, sym_flags1,
1764 				    &where)) == (Sym_desc *)S_ERROR)
1765 					return (S_ERROR);
1766 
1767 				sdp->sd_flags &= ~FLG_SY_CLEAN;
1768 
1769 				/*
1770 				 * Identify any references.  FLG_SY_MAPREF is
1771 				 * turned off once a relocatable object with
1772 				 * the same symbol is found, thus the existence
1773 				 * of FLG_SY_MAPREF at symbol validation is
1774 				 * used to flag undefined/misspelled entries.
1775 				 */
1776 				if (sym->st_shndx == SHN_UNDEF)
1777 					sdp->sd_flags |=
1778 					    (FLG_SY_MAPREF | FLG_SY_GLOBREF);
1779 
1780 			} else {
1781 				conflict = NULL;
1782 				sym = sdp->sd_sym;
1783 
1784 				/*
1785 				 * If this symbol already exists, make sure this
1786 				 * definition doesn't conflict with the former.
1787 				 * Provided it doesn't, multiple definitions
1788 				 * from different mapfiles can augment each
1789 				 * other.
1790 				 */
1791 				/* BEGIN CSTYLED */
1792 				if (sym->st_value) {
1793 				    if (value && (sym->st_value != value))
1794 					conflict =
1795 					    MSG_INTL(MSG_MAP_DIFF_SYMVAL);
1796 				} else {
1797 					sym->st_value = value;
1798 				}
1799 				if (sym->st_size) {
1800 				    if (size && (sym->st_size != size))
1801 					conflict = MSG_INTL(MSG_MAP_DIFF_SYMSZ);
1802 				} else {
1803 					sym->st_size = size;
1804 				}
1805 				if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) {
1806 				    if ((type != STT_NOTYPE) &&
1807 					(ELF_ST_TYPE(sym->st_info) != type))
1808 					    conflict =
1809 						MSG_INTL(MSG_MAP_DIFF_SYMTYP);
1810 				} else {
1811 					sym->st_info =
1812 					    ELF_ST_INFO(STB_GLOBAL, type);
1813 				}
1814 				if (sym->st_shndx != SHN_UNDEF) {
1815 				    if ((shndx != SHN_UNDEF) &&
1816 					(sym->st_shndx != shndx))
1817 					    conflict =
1818 						MSG_INTL(MSG_MAP_DIFF_SYMNDX);
1819 				} else {
1820 					sdp->sd_shndx = sym->st_shndx = shndx;
1821 				}
1822 				/* END CSTYLED */
1823 
1824 				if ((sdp->sd_flags1 & MSK_SY1_GLOBAL) &&
1825 				    (sdp->sd_aux->sa_overndx !=
1826 				    VER_NDX_GLOBAL) &&
1827 				    (vdp->vd_ndx != VER_NDX_GLOBAL) &&
1828 				    (sdp->sd_aux->sa_overndx != vdp->vd_ndx)) {
1829 					conflict =
1830 					    MSG_INTL(MSG_MAP_DIFF_SYMVER);
1831 				}
1832 
1833 				if (conflict) {
1834 					eprintf(ofl->ofl_lml, ERR_FATAL,
1835 					    MSG_INTL(MSG_MAP_SYMDEF1), mapfile,
1836 					    EC_XWORD(Line_num), demangle(_name),
1837 					    sdp->sd_file->ifl_name, conflict);
1838 					errcnt++;
1839 					continue;
1840 				}
1841 
1842 				/*
1843 				 * If this mapfile entry supplies a definition,
1844 				 * indicate that the symbol is now used.
1845 				 */
1846 				if (shndx != SHN_UNDEF)
1847 					sdp->sd_flags |= FLG_SY_MAPUSED;
1848 			}
1849 
1850 			/*
1851 			 * A symbol declaration that defines a size but no
1852 			 * value is processed as a request to create an
1853 			 * associated backing section.  The intent behind this
1854 			 * functionality is to provide OBJT definitions within
1855 			 * filters that are not ABS.  ABS symbols don't allow
1856 			 * copy-relocations to be established to filter OBJT
1857 			 * definitions.
1858 			 */
1859 			if ((shndx == SHN_ABS) && size && novalue &&
1860 			    (sdp->sd_isc == 0)) {
1861 				Is_desc	*isp;
1862 
1863 				if (type == STT_OBJECT) {
1864 					if ((isp = ld_make_data(ofl,
1865 					    size)) == (Is_desc *)S_ERROR)
1866 						return (S_ERROR);
1867 				} else {
1868 					if ((isp = ld_make_text(ofl,
1869 					    size)) == (Is_desc *)S_ERROR)
1870 						return (S_ERROR);
1871 				}
1872 
1873 				/*
1874 				 * Now that backing storage has been created,
1875 				 * associate the symbol descriptor.  Remove the
1876 				 * symbols special section tag so that it will
1877 				 * be assigned the correct section index as part
1878 				 * of update symbol processing.
1879 				 */
1880 				sdp->sd_flags &= ~FLG_SY_SPECSEC;
1881 				sym_flags &= ~FLG_SY_SPECSEC;
1882 				sdp->sd_isc = isp;
1883 				isp->is_file = ifl;
1884 			}
1885 
1886 			/*
1887 			 * Indicate the new symbols scope.  Although the
1888 			 * symbols st_other field will eventually be updated as
1889 			 * part of writing out the final symbol, update the
1890 			 * st_other field here to trigger better diagnostics
1891 			 * during symbol validation (for example, undefined
1892 			 * references that are defined symbolic in a mapfile).
1893 			 */
1894 			if (scope == FLG_SCOPE_HIDD) {
1895 				/*
1896 				 * This symbol needs to be reduced to local.
1897 				 */
1898 				if (ofl->ofl_flags1 & FLG_OF1_REDLSYM) {
1899 					sdp->sd_flags1 |=
1900 					    (FLG_SY1_HIDDEN | FLG_SY1_ELIM);
1901 					sdp->sd_sym->st_other = STV_ELIMINATE;
1902 				} else {
1903 					sdp->sd_flags1 |= FLG_SY1_HIDDEN;
1904 					sdp->sd_sym->st_other = STV_HIDDEN;
1905 				}
1906 			} else if (scope == FLG_SCOPE_ELIM) {
1907 				/*
1908 				 * This symbol needs to be eliminated.  Note,
1909 				 * the symbol is also tagged as local to trigger
1910 				 * any necessary relocation processing prior
1911 				 * to the symbol being eliminated.
1912 				 */
1913 				sdp->sd_flags1 |=
1914 				    (FLG_SY1_HIDDEN | FLG_SY1_ELIM);
1915 				sdp->sd_sym->st_other = STV_ELIMINATE;
1916 
1917 			} else {
1918 				/*
1919 				 * This symbol is explicitly defined to remain
1920 				 * global.
1921 				 */
1922 				sdp->sd_flags |= sym_flags;
1923 				sdp->sd_flags1 |= sym_flags1;
1924 
1925 				/*
1926 				 * Qualify any global scope.
1927 				 */
1928 				if (scope == FLG_SCOPE_SNGL) {
1929 					sdp->sd_flags1 |=
1930 					    (FLG_SY1_SINGLE | FLG_SY1_NDIR);
1931 					sdp->sd_sym->st_other = STV_SINGLETON;
1932 				} else if (scope == FLG_SCOPE_PROT) {
1933 					sdp->sd_flags1 |= FLG_SY1_PROTECT;
1934 					sdp->sd_sym->st_other = STV_PROTECTED;
1935 				} else if (scope == FLG_SCOPE_EXPT) {
1936 					sdp->sd_flags1 |= FLG_SY1_EXPORT;
1937 					sdp->sd_sym->st_other = STV_EXPORTED;
1938 				} else
1939 					sdp->sd_flags1 |= FLG_SY1_DEFAULT;
1940 
1941 				/*
1942 				 * Record the present version index for later
1943 				 * potential versioning.
1944 				 */
1945 				if ((sdp->sd_aux->sa_overndx == 0) ||
1946 				    (sdp->sd_aux->sa_overndx == VER_NDX_GLOBAL))
1947 					sdp->sd_aux->sa_overndx = vdp->vd_ndx;
1948 				vdp->vd_flags |= FLG_VER_REFER;
1949 			}
1950 
1951 			conflict = NULL;
1952 
1953 			/*
1954 			 * Carry out some validity checks to ensure incompatible
1955 			 * symbol characteristics have not been defined.
1956 			 * These checks are carried out after symbols are added
1957 			 * or resolved, to catch single instance, and
1958 			 * multi-instance definition inconsistencies.
1959 			 */
1960 			if ((sdp->sd_flags1 &
1961 			    (FLG_SY1_HIDDEN | FLG_SY1_ELIM)) &&
1962 			    ((scope != FLG_SCOPE_HIDD) &&
1963 			    (scope != FLG_SCOPE_ELIM))) {
1964 				conflict = MSG_INTL(MSG_MAP_DIFF_SYMLCL);
1965 
1966 			} else if (((sdp->sd_flags1 & FLG_SY1_SINGLE) ||
1967 			    (sdp->sd_flags1 & FLG_SY1_EXPORT)) &&
1968 			    ((scope != FLG_SCOPE_DFLT) &&
1969 			    (scope != FLG_SCOPE_EXPT) &&
1970 			    (scope != FLG_SCOPE_SNGL))) {
1971 				conflict = MSG_INTL(MSG_MAP_DIFF_SYMGLOB);
1972 
1973 			} else if ((sdp->sd_flags1 & FLG_SY1_PROTECT) &&
1974 			    ((scope != FLG_SCOPE_DFLT) &&
1975 			    (scope != FLG_SCOPE_PROT))) {
1976 				conflict = MSG_INTL(MSG_MAP_DIFF_SYMPROT);
1977 
1978 			} else if ((sdp->sd_flags1 & FLG_SY1_NDIR) &&
1979 			    (scope == FLG_SCOPE_PROT)) {
1980 				conflict = MSG_INTL(MSG_MAP_DIFF_PROTNDIR);
1981 
1982 			} else if ((sdp->sd_flags1 & FLG_SY1_DIR) &&
1983 			    (scope == FLG_SCOPE_SNGL)) {
1984 				conflict = MSG_INTL(MSG_MAP_DIFF_SNGLDIR);
1985 			}
1986 
1987 			if (conflict) {
1988 				/*
1989 				 * Select the conflict message from either a
1990 				 * single instance or multi-instance definition.
1991 				 */
1992 				if (sdp->sd_file->ifl_name == mapfile) {
1993 					eprintf(ofl->ofl_lml, ERR_FATAL,
1994 					    MSG_INTL(MSG_MAP_SYMDEF2), mapfile,
1995 					    EC_XWORD(Line_num), demangle(_name),
1996 					    conflict);
1997 				} else {
1998 					eprintf(ofl->ofl_lml, ERR_FATAL,
1999 					    MSG_INTL(MSG_MAP_SYMDEF1), mapfile,
2000 					    EC_XWORD(Line_num), demangle(_name),
2001 					    sdp->sd_file->ifl_name, conflict);
2002 				}
2003 				errcnt++;
2004 				continue;
2005 			}
2006 
2007 			/*
2008 			 * Indicate that this symbol has been explicitly
2009 			 * contributed from a mapfile.
2010 			 */
2011 			sdp->sd_flags1 |= (FLG_SY1_MAPFILE | FLG_SY1_EXPDEF);
2012 
2013 			/*
2014 			 * If we've encountered a symbol definition simulate
2015 			 * that an input file has been processed - this allows
2016 			 * things like filters to be created purely from a
2017 			 * mapfile.
2018 			 */
2019 			if (type != STT_NOTYPE)
2020 				ofl->ofl_objscnt++;
2021 			DBG_CALL(Dbg_map_symbol(ofl, sdp));
2022 
2023 			/*
2024 			 * If this symbol has an associated filtee, record the
2025 			 * filtee string and associate the string index with the
2026 			 * symbol.  This is used later to associate the syminfo
2027 			 * information with the necessary .dynamic entry.
2028 			 */
2029 			if (filter && (filtee == 0)) {
2030 				eprintf(ofl->ofl_lml, ERR_FATAL,
2031 				    MSG_INTL(MSG_MAP_NOFILTER), mapfile,
2032 				    EC_XWORD(Line_num), _name);
2033 				errcnt++;
2034 				continue;
2035 			}
2036 
2037 			if (filtee) {
2038 				Dfltr_desc *	dftp;
2039 				Sfltr_desc	sft;
2040 				Aliste		idx, _idx, nitems;
2041 
2042 				/*
2043 				 * Make sure we don't duplicate any filtee
2044 				 * strings, and create a new descriptor if
2045 				 * necessary.
2046 				 */
2047 				idx = nitems = alist_nitems(ofl->ofl_dtsfltrs);
2048 				for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, _idx,
2049 				    dftp)) {
2050 					if ((dftflag != dftp->dft_flag) ||
2051 					    (strcmp(dftp->dft_str, filtee)))
2052 						continue;
2053 					idx = _idx;
2054 					break;
2055 				}
2056 				if (idx == nitems) {
2057 					Dfltr_desc	dft;
2058 
2059 					dft.dft_str = filtee;
2060 					dft.dft_flag = dftflag;
2061 					dft.dft_ndx = 0;
2062 
2063 					/*
2064 					 * The following append puts the new
2065 					 * item at the offset contained in
2066 					 * idx, because we know idx contains
2067 					 * the index of the next available slot.
2068 					 */
2069 					if (alist_append(&ofl->ofl_dtsfltrs,
2070 					    &dft, sizeof (Dfltr_desc),
2071 					    AL_CNT_OFL_DTSFLTRS) == NULL)
2072 						return (S_ERROR);
2073 				}
2074 
2075 				/*
2076 				 * Create a new filter descriptor for this
2077 				 * symbol.
2078 				 */
2079 				sft.sft_sdp = sdp;
2080 				sft.sft_idx = idx;
2081 
2082 				if (alist_append(&ofl->ofl_symfltrs,
2083 				    &sft, sizeof (Sfltr_desc),
2084 				    AL_CNT_OFL_SYMFLTRS) == NULL)
2085 					return (S_ERROR);
2086 			}
2087 			break;
2088 
2089 		default:
2090 			eprintf(ofl->ofl_lml, ERR_FATAL,
2091 			    MSG_INTL(MSG_MAP_EXPSCOL), mapfile,
2092 			    EC_XWORD(Line_num));
2093 			errcnt++;
2094 			continue;
2095 		}
2096 	}
2097 
2098 	if (errcnt)
2099 		return (S_ERROR);
2100 
2101 	/*
2102 	 * Determine if any version references are provided after the close
2103 	 * bracket.
2104 	 */
2105 	while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
2106 		Ver_desc	*_vdp;
2107 		char		*_name;
2108 
2109 		if (tok != TK_STRING) {
2110 			/* LINTED */
2111 			if (tok != (Token)S_ERROR)
2112 				eprintf(ofl->ofl_lml, ERR_FATAL,
2113 				    MSG_INTL(MSG_MAP_EXPVERS), mapfile,
2114 				    EC_XWORD(Line_num));
2115 			return (S_ERROR);
2116 		}
2117 
2118 		name = Start_tok;
2119 		if (vdp->vd_ndx == VER_NDX_GLOBAL) {
2120 			eprintf(ofl->ofl_lml, ERR_WARNING,
2121 			    MSG_INTL(MSG_MAP_UNEXDEP), mapfile,
2122 			    EC_XWORD(Line_num), name);
2123 			continue;
2124 		}
2125 
2126 		/*
2127 		 * Generate a new version descriptor if it doesn't already
2128 		 * exist.
2129 		 */
2130 		/* LINTED */
2131 		hash = (Word)elf_hash(name);
2132 		if ((_vdp = ld_vers_find(name, hash, &ofl->ofl_verdesc)) == 0) {
2133 			if ((_name = libld_malloc(strlen(name) + 1)) == 0)
2134 				return (S_ERROR);
2135 			(void) strcpy(_name, name);
2136 
2137 			if ((_vdp = ld_vers_desc(_name, hash,
2138 			    &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR)
2139 				return (S_ERROR);
2140 		}
2141 
2142 		/*
2143 		 * Add the new version descriptor to the parent version
2144 		 * descriptors reference list.  Indicate the version descriptors
2145 		 * first reference (used for error disgnostics if undefined
2146 		 * version dependencies remain).
2147 		 */
2148 		if (ld_vers_find(name, hash, &vdp->vd_deps) == 0)
2149 			if (list_appendc(&vdp->vd_deps, _vdp) == 0)
2150 				return (S_ERROR);
2151 
2152 		if (_vdp->vd_ref == 0)
2153 			_vdp->vd_ref = vdp;
2154 	}
2155 	return (1);
2156 }
2157 
2158 /*
2159  * Sort the segment list by increasing virtual address.
2160  */
2161 uintptr_t
2162 ld_sort_seg_list(Ofl_desc *ofl)
2163 {
2164 	List 		seg1, seg2;
2165 	Listnode	*lnp1, *lnp2, *lnp3;
2166 	Sg_desc		*sgp1, *sgp2;
2167 
2168 	seg1.head = seg1.tail = seg2.head = seg2.tail = NULL;
2169 
2170 	/*
2171 	 * Add the .phdr and .interp segments to our list.  These segments must
2172 	 * occur before any PT_LOAD segments (refer exec/elf/elf.c).  Also add
2173 	 * the capabilities segment.  This isn't essential, but the capabilities
2174 	 * section is one of the first in an object.
2175 	 */
2176 	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
2177 		Word	type = sgp1->sg_phdr.p_type;
2178 
2179 		if ((type == PT_PHDR) || (type == PT_INTERP) ||
2180 		    (type == PT_SUNWCAP)) {
2181 			if (list_appendc(&seg1, sgp1) == 0)
2182 				return (S_ERROR);
2183 		}
2184 	}
2185 
2186 	/*
2187 	 * Add the loadable segments to another list in sorted order.
2188 	 */
2189 	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
2190 		DBG_CALL(Dbg_map_sort_orig(ofl->ofl_lml, sgp1));
2191 
2192 		if (sgp1->sg_phdr.p_type != PT_LOAD)
2193 			continue;
2194 
2195 		if (!(sgp1->sg_flags & FLG_SG_VADDR) ||
2196 		    (sgp1->sg_flags & FLG_SG_EMPTY)) {
2197 			if (list_appendc(&seg2, sgp1) == 0)
2198 				return (S_ERROR);
2199 		} else {
2200 			if (seg2.head == NULL) {
2201 				if (list_appendc(&seg2, sgp1) == 0)
2202 					return (S_ERROR);
2203 				continue;
2204 			}
2205 			lnp3 = NULL;
2206 			for (LIST_TRAVERSE(&seg2, lnp2, sgp2)) {
2207 				if (!(sgp2->sg_flags & FLG_SG_VADDR) ||
2208 				    (sgp2->sg_flags & FLG_SG_EMPTY)) {
2209 					if (lnp3 == NULL) {
2210 						if (list_prependc(&seg2,
2211 						    sgp1) == 0)
2212 							return (S_ERROR);
2213 					} else {
2214 						if (list_insertc(&seg2,
2215 						    sgp1, lnp3) == 0)
2216 							return (S_ERROR);
2217 					}
2218 					lnp3 = NULL;
2219 					break;
2220 				}
2221 				if (sgp1->sg_phdr.p_vaddr <
2222 				    sgp2->sg_phdr.p_vaddr) {
2223 					if (lnp3 == NULL) {
2224 						if (list_prependc(&seg2,
2225 						    sgp1) == 0)
2226 							return (S_ERROR);
2227 					} else {
2228 						if (list_insertc(&seg2,
2229 						    sgp1, lnp3) == 0)
2230 							return (S_ERROR);
2231 					}
2232 					lnp3 = NULL;
2233 					break;
2234 				} else if (sgp1->sg_phdr.p_vaddr >
2235 				    sgp2->sg_phdr.p_vaddr) {
2236 					lnp3 = lnp2;
2237 				} else {
2238 					eprintf(ofl->ofl_lml, ERR_FATAL,
2239 					    MSG_INTL(MSG_MAP_SEGSAME),
2240 					    sgp1->sg_name, sgp2->sg_name);
2241 					return (S_ERROR);
2242 				}
2243 			}
2244 			if (lnp3 != NULL)
2245 				if (list_appendc(&seg2, sgp1) == 0)
2246 					return (S_ERROR);
2247 		}
2248 	}
2249 
2250 	/*
2251 	 * Add the sorted loadable segments to our list.
2252 	 */
2253 	for (LIST_TRAVERSE(&seg2, lnp1, sgp1)) {
2254 		if (list_appendc(&seg1, sgp1) == 0)
2255 			return (S_ERROR);
2256 	}
2257 
2258 	/*
2259 	 * Add all other segments to our list.
2260 	 */
2261 	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
2262 		Word	type = sgp1->sg_phdr.p_type;
2263 
2264 		if ((type != PT_PHDR) && (type != PT_INTERP) &&
2265 		    (type != PT_SUNWCAP) && (type != PT_LOAD)) {
2266 			if (list_appendc(&seg1, sgp1) == 0)
2267 				return (S_ERROR);
2268 		}
2269 	}
2270 	ofl->ofl_segs.head = ofl->ofl_segs.tail = NULL;
2271 
2272 	/*
2273 	 * Now rebuild the original list and process all of the
2274 	 * segment/section ordering information if present.
2275 	 */
2276 	for (LIST_TRAVERSE(&seg1, lnp1, sgp1)) {
2277 		DBG_CALL(Dbg_map_sort_fini(ofl->ofl_lml, sgp1));
2278 		if (list_appendc(&ofl->ofl_segs, sgp1) == 0)
2279 			return (S_ERROR);
2280 	}
2281 	return (1);
2282 }
2283 
2284 /*
2285  * Parse the mapfile.
2286  */
2287 uintptr_t
2288 ld_map_parse(const char *mapfile, Ofl_desc *ofl)
2289 {
2290 	struct stat	stat_buf;	/* stat of mapfile */
2291 	int		mapfile_fd;	/* descriptor for mapfile */
2292 	Listnode	*lnp1;		/* node pointer */
2293 	Listnode	*lnp2;		/* node pointer */
2294 	Sg_desc		*sgp1;		/* seg descriptor being manipulated */
2295 	Sg_desc		*sgp2;		/* temp segment descriptor pointer */
2296 	Ent_desc	*enp;		/* Segment entrance criteria. */
2297 	Token		tok;		/* current token. */
2298 	Listnode	*e_next = NULL;
2299 					/* next place for entrance criterion */
2300 	Boolean		new_segment;	/* If true, defines new segment. */
2301 	char		*name;
2302 	static	int	num_stack = 0;	/* number of stack segment */
2303 	int		err;
2304 
2305 	DBG_CALL(Dbg_map_parse(ofl->ofl_lml, mapfile));
2306 
2307 	/*
2308 	 * Determine if we're dealing with a file or a directory.
2309 	 */
2310 	if (stat(mapfile, &stat_buf) == -1) {
2311 		err = errno;
2312 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_STAT),
2313 		    mapfile, strerror(err));
2314 		return (S_ERROR);
2315 	}
2316 	if (S_ISDIR(stat_buf.st_mode)) {
2317 		DIR		*dirp;
2318 		struct dirent	*denp;
2319 
2320 		/*
2321 		 * Open the directory and interpret each visible file as a
2322 		 * mapfile.
2323 		 */
2324 		if ((dirp = opendir(mapfile)) == 0)
2325 			return (1);
2326 
2327 		while ((denp = readdir(dirp)) != NULL) {
2328 			char	path[PATH_MAX];
2329 
2330 			/*
2331 			 * Ignore any hidden filenames.  Construct the full
2332 			 * pathname to the new mapfile.
2333 			 */
2334 			if (*denp->d_name == '.')
2335 				continue;
2336 			(void) snprintf(path, PATH_MAX, MSG_ORIG(MSG_STR_PATH),
2337 			    mapfile, denp->d_name);
2338 			if (ld_map_parse(path, ofl) == S_ERROR)
2339 				return (S_ERROR);
2340 		}
2341 		(void) closedir(dirp);
2342 		return (1);
2343 	} else if (!S_ISREG(stat_buf.st_mode)) {
2344 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_NOTREG),
2345 		    mapfile);
2346 		return (S_ERROR);
2347 	}
2348 
2349 	/*
2350 	 * We read the entire mapfile into memory.
2351 	 */
2352 	if ((Mapspace = libld_malloc(stat_buf.st_size + 1)) == 0)
2353 		return (S_ERROR);
2354 	if ((mapfile_fd = open(mapfile, O_RDONLY)) == -1) {
2355 		err = errno;
2356 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
2357 		    mapfile, strerror(err));
2358 		return (S_ERROR);
2359 	}
2360 
2361 	if (read(mapfile_fd, Mapspace, stat_buf.st_size) != stat_buf.st_size) {
2362 		err = errno;
2363 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_READ),
2364 		    mapfile, strerror(err));
2365 		return (S_ERROR);
2366 	}
2367 	Mapspace[stat_buf.st_size] = '\0';
2368 	nextchr = Mapspace;
2369 
2370 	/*
2371 	 * Set up any global variables, the line number counter and file name.
2372 	 */
2373 	Line_num = 1;
2374 
2375 	/*
2376 	 * We now parse the mapfile until the gettoken routine returns EOF.
2377 	 */
2378 	while ((tok = gettoken(ofl, mapfile)) != TK_EOF) {
2379 		int	ndx = -1;
2380 
2381 		/*
2382 		 * Don't know which segment yet.
2383 		 */
2384 		sgp1 = NULL;
2385 
2386 		/*
2387 		 * At this point we are at the beginning of a line, and the
2388 		 * variable `Start_tok' points to the first string on the line.
2389 		 * All mapfile entries start with some string token except it
2390 		 * is possible for a scoping definition to start with `{'.
2391 		 */
2392 		if (tok == TK_LEFTBKT) {
2393 			if (map_version(mapfile, (char *)0, ofl) == S_ERROR)
2394 				return (S_ERROR);
2395 			continue;
2396 		}
2397 		if (tok != TK_STRING) {
2398 			/* LINTED */
2399 			if (tok != (Token)S_ERROR)
2400 				eprintf(ofl->ofl_lml, ERR_FATAL,
2401 				    MSG_INTL(MSG_MAP_EXPSEGNAM), mapfile,
2402 				    EC_XWORD(Line_num));
2403 			return (S_ERROR);
2404 		}
2405 
2406 		/*
2407 		 * Save the initial token.
2408 		 */
2409 		if ((name = libld_malloc(strlen(Start_tok) + 1)) == 0)
2410 			return (S_ERROR);
2411 		(void) strcpy(name, Start_tok);
2412 
2413 		/*
2414 		 * Now check the second character on the line.  The special `-'
2415 		 * and `{' characters do not involve any segment manipulation so
2416 		 * we handle them first.
2417 		 */
2418 		if ((tok = gettoken(ofl, mapfile)) == TK_DASH) {
2419 			if (map_dash(mapfile, name, ofl) == S_ERROR)
2420 				return (S_ERROR);
2421 			continue;
2422 		}
2423 		if (tok == TK_LEFTBKT) {
2424 			if (map_version(mapfile, name, ofl) == S_ERROR)
2425 				return (S_ERROR);
2426 			continue;
2427 		}
2428 
2429 		/*
2430 		 * If we're here we need to interpret the first string as a
2431 		 * segment name.  Find the segment named in the token.
2432 		 */
2433 		for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp2)) {
2434 			ndx++;
2435 			if (strcmp(sgp2->sg_name, name) == 0) {
2436 				sgp1 = sgp2;
2437 				sgp2->sg_flags &= ~FLG_SG_DISABLED;
2438 				new_segment = FALSE;
2439 				break;
2440 			}
2441 		}
2442 
2443 		/*
2444 		 * If the second token is a '|' then we had better
2445 		 * of found a segment.  It is illegal to perform
2446 		 * section within segment ordering before the segment
2447 		 * has been declared.
2448 		 */
2449 		if (tok == TK_PIPE) {
2450 			if (sgp1 == NULL) {
2451 				eprintf(ofl->ofl_lml, ERR_FATAL,
2452 				    MSG_INTL(MSG_MAP_SECINSEG), mapfile,
2453 				    EC_XWORD(Line_num), name);
2454 				return (S_ERROR);
2455 			} else {
2456 				if (map_pipe(ofl, mapfile, sgp1) == S_ERROR)
2457 					return (S_ERROR);
2458 				continue;
2459 			}
2460 		}
2461 
2462 		/*
2463 		 * If segment is still NULL then it does not exist.  Create a
2464 		 * new segment, and leave its values as 0 so that map_equal()
2465 		 * can detect changing attributes.
2466 		 */
2467 		if (sgp1 == NULL) {
2468 			if ((sgp1 = libld_calloc(sizeof (Sg_desc),
2469 			    1)) == 0)
2470 				return (S_ERROR);
2471 			sgp1->sg_phdr.p_type = PT_NULL;
2472 			sgp1->sg_name = name;
2473 			new_segment = TRUE;
2474 			ndx = -1;
2475 		}
2476 
2477 		if ((strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_INTERP)) == 0) ||
2478 		    (strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_LD_DYNAMIC)) ==
2479 		    0)) {
2480 			eprintf(ofl->ofl_lml, ERR_FATAL,
2481 			    MSG_INTL(MSG_MAP_SEGRESV), mapfile,
2482 			    EC_XWORD(Line_num));
2483 			return (S_ERROR);
2484 		}
2485 
2486 		/*
2487 		 * Now check the second token from the input line.
2488 		 */
2489 		if (tok == TK_EQUAL) {
2490 			if (strcmp(sgp1->sg_name,
2491 			    MSG_ORIG(MSG_STR_HWCAP_1)) == 0) {
2492 				if (map_cap(mapfile, CA_SUNW_HW_1,
2493 				    ofl) == S_ERROR)
2494 					return (S_ERROR);
2495 				DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml,
2496 				    CA_SUNW_HW_1, ofl->ofl_hwcap_1,
2497 				    ld_targ.t_m.m_mach));
2498 				continue;
2499 
2500 			} else if (strcmp(sgp1->sg_name,
2501 			    MSG_ORIG(MSG_STR_SFCAP_1)) == 0) {
2502 				if (map_cap(mapfile, CA_SUNW_SF_1,
2503 				    ofl) == S_ERROR)
2504 					return (S_ERROR);
2505 				DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml,
2506 				    CA_SUNW_SF_1, ofl->ofl_sfcap_1,
2507 				    ld_targ.t_m.m_mach));
2508 				continue;
2509 
2510 			} else {
2511 				if (map_equal(mapfile, sgp1, ofl) == S_ERROR)
2512 					return (S_ERROR);
2513 				ofl->ofl_flags |= FLG_OF_SEGSORT;
2514 				DBG_CALL(Dbg_map_set_equal(new_segment));
2515 			}
2516 		} else if (tok == TK_COLON) {
2517 			/*
2518 			 * If this is an existing segment reservation, sections
2519 			 * can't be assigned to it.
2520 			 */
2521 			if ((new_segment == FALSE) &&
2522 			    (sgp1->sg_flags & FLG_SG_EMPTY)) {
2523 				eprintf(ofl->ofl_lml, ERR_FATAL,
2524 				    MSG_INTL(MSG_MAP_SEGEMPSEC), mapfile,
2525 				    EC_XWORD(Line_num));
2526 				return (S_ERROR);
2527 			}
2528 
2529 			/*
2530 			 * We are looking at a new entrance criteria line.
2531 			 * Note that entrance criteria are added in the order
2532 			 * they are found in the map file, but are placed
2533 			 * before any default criteria.
2534 			 */
2535 			if ((enp = libld_calloc(sizeof (Ent_desc), 1)) == 0)
2536 				return (S_ERROR);
2537 			enp->ec_segment = sgp1;
2538 			if (e_next == NULL) {
2539 				if ((e_next = list_prependc(&ofl->ofl_ents,
2540 				    enp)) == 0)
2541 					return (S_ERROR);
2542 			} else {
2543 				if ((e_next = list_insertc(&ofl->ofl_ents,
2544 				    enp, e_next)) == 0)
2545 					return (S_ERROR);
2546 			}
2547 
2548 			if (map_colon(ofl, mapfile, enp) == S_ERROR)
2549 				return (S_ERROR);
2550 			ofl->ofl_flags |= FLG_OF_SEGSORT;
2551 			DBG_CALL(Dbg_map_ent(ofl->ofl_lml, new_segment,
2552 			    enp, ofl));
2553 		} else if (tok == TK_ATSIGN) {
2554 			if (map_atsign(mapfile, sgp1, ofl) == S_ERROR)
2555 				return (S_ERROR);
2556 			DBG_CALL(Dbg_map_set_atsign(new_segment));
2557 		} else {
2558 			/* LINTED */
2559 			if (tok != (Token)S_ERROR) {
2560 				eprintf(ofl->ofl_lml, ERR_FATAL,
2561 				    MSG_INTL(MSG_MAP_EXPEQU), mapfile,
2562 				    EC_XWORD(Line_num));
2563 				return (S_ERROR);
2564 			}
2565 		}
2566 
2567 		/*
2568 		 * Having completed parsing an entry in the map file determine
2569 		 * if the segment to which it applies is new.
2570 		 */
2571 		if (new_segment) {
2572 			int	src_type, dst_type;
2573 
2574 			/*
2575 			 * If specific fields have not been supplied via
2576 			 * map_equal(), make sure defaults are supplied.
2577 			 */
2578 			if (((sgp1->sg_flags & FLG_SG_TYPE) == 0) &&
2579 			    (sgp1->sg_phdr.p_type == PT_NULL)) {
2580 				/*
2581 				 * Default to a loadable segment.
2582 				 */
2583 				sgp1->sg_phdr.p_type = PT_LOAD;
2584 				sgp1->sg_flags |= FLG_SG_TYPE;
2585 			}
2586 			if (sgp1->sg_phdr.p_type == PT_LOAD) {
2587 				if ((sgp1->sg_flags & FLG_SG_FLAGS) == 0) {
2588 					/*
2589 					 * Default to read/write and execute.
2590 					 */
2591 					sgp1->sg_phdr.p_flags =
2592 					    PF_R + PF_W + PF_X;
2593 					sgp1->sg_flags |= FLG_SG_FLAGS;
2594 				}
2595 				if ((sgp1->sg_flags & FLG_SG_ALIGN) == 0) {
2596 					/*
2597 					 * Default to segment alignment
2598 					 */
2599 					sgp1->sg_phdr.p_align =
2600 					    ld_targ.t_m.m_segm_align;
2601 					sgp1->sg_flags |= FLG_SG_ALIGN;
2602 				}
2603 			}
2604 
2605 			/*
2606 			 * Determine where the new segment should be inserted
2607 			 * in the seg_desc[] list.  Presently the user can
2608 			 * only add a LOAD or NOTE segment.  Note that these
2609 			 * segments must be added after any PT_PHDR and
2610 			 * PT_INTERP (refer Generic ABI, Page 5-4).
2611 			 */
2612 			switch (sgp1->sg_phdr.p_type) {
2613 			case PT_LOAD:
2614 			case PT_NULL:
2615 				if (sgp1->sg_flags & FLG_SG_EMPTY)
2616 					src_type = 4;
2617 				else
2618 					src_type = 3;
2619 				break;
2620 			case PT_SUNWSTACK:
2621 				src_type = 8;
2622 				if (++num_stack >= 2) {
2623 					/*
2624 					 * Currently the number of sunw_stack
2625 					 * segment is limited to 1.
2626 					 */
2627 					eprintf(ofl->ofl_lml, ERR_WARNING,
2628 					    MSG_INTL(MSG_MAP_NOSTACK2),
2629 					    mapfile, EC_XWORD(Line_num));
2630 					continue;
2631 				}
2632 				break;
2633 			case PT_NOTE:
2634 				src_type = 9;
2635 				break;
2636 			default:
2637 				eprintf(ofl->ofl_lml, ERR_FATAL,
2638 				    MSG_INTL(MSG_MAP_UNKSEGTYP), mapfile,
2639 				    EC_XWORD(Line_num),
2640 				    EC_WORD(sgp1->sg_phdr.p_type));
2641 				return (S_ERROR);
2642 			}
2643 			lnp2 = NULL;
2644 			for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp2)) {
2645 				ndx++;
2646 				switch (sgp2->sg_phdr.p_type) {
2647 				case PT_PHDR:
2648 					dst_type = 0;
2649 					break;
2650 				case PT_INTERP:
2651 					dst_type = 1;
2652 					break;
2653 				case PT_SUNWCAP:
2654 					dst_type = 2;
2655 					break;
2656 				case PT_LOAD:
2657 					dst_type = 3;
2658 					break;
2659 				case PT_DYNAMIC:
2660 					dst_type = 5;
2661 					break;
2662 				case PT_SUNWDTRACE:
2663 					dst_type = 6;
2664 					break;
2665 				case PT_SHLIB:
2666 					dst_type = 7;
2667 					break;
2668 				case PT_SUNWSTACK:
2669 					dst_type = 8;
2670 					break;
2671 				case PT_NOTE:
2672 					dst_type = 9;
2673 					break;
2674 				case PT_SUNWBSS:
2675 					dst_type = 10;
2676 					break;
2677 				case PT_TLS:
2678 					dst_type = 11;
2679 					break;
2680 				case PT_NULL:
2681 					dst_type = 12;
2682 					break;
2683 				default:
2684 					eprintf(ofl->ofl_lml, ERR_FATAL,
2685 					    MSG_INTL(MSG_MAP_UNKSEGTYP),
2686 					    mapfile, EC_XWORD(Line_num),
2687 					    EC_WORD(sgp2->sg_phdr.p_type));
2688 					return (S_ERROR);
2689 				}
2690 				if (src_type <= dst_type) {
2691 					if (lnp2 == NULL) {
2692 						if (list_prependc(
2693 						    &ofl->ofl_segs, sgp1) == 0)
2694 							return (S_ERROR);
2695 					} else {
2696 						if (list_insertc(&ofl->ofl_segs,
2697 						    sgp1, lnp2) == 0)
2698 							return (S_ERROR);
2699 					}
2700 					break;
2701 				}
2702 				lnp2 = lnp1;
2703 			}
2704 		}
2705 		DBG_CALL(Dbg_map_seg(ofl, ndx, sgp1));
2706 	}
2707 
2708 	/*
2709 	 * If the output file is a static file without an interpreter, and
2710 	 * if any virtual address is specified, then set the ?N flag for
2711 	 * backward compatibility.
2712 	 */
2713 	if (!(ofl->ofl_flags & FLG_OF_DYNAMIC) &&
2714 	    !(ofl->ofl_flags & FLG_OF_RELOBJ) &&
2715 	    !(ofl->ofl_osinterp) &&
2716 	    (ofl->ofl_flags1 & FLG_OF1_VADDR))
2717 		ofl->ofl_dtflags_1 |= DF_1_NOHDR;
2718 
2719 	/*
2720 	 * If the output file is a relocatable file, then ?N has no effect.
2721 	 * Make sure this flag isn't set.
2722 	 */
2723 	if (ofl->ofl_flags & FLG_OF_RELOBJ)
2724 		ofl->ofl_dtflags_1 &= ~DF_1_NOHDR;
2725 
2726 	return (1);
2727 }
2728