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