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