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