xref: /illumos-gate/usr/src/cmd/sgs/libld/common/map.c (revision f48205be61a214698b763ff550ab9e657525104c)
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 |= SHF_EXECINSTR;
899 					b_bang = FALSE;
900 					break;
901 				default:
902 					eprintf(ofl->ofl_lml, ERR_FATAL,
903 					    MSG_INTL(MSG_MAP_BADFLAG),
904 					    mapfile, EC_XWORD(Line_num),
905 					    Start_tok);
906 					return (S_ERROR);
907 				}
908 		/*
909 		 * Section name.
910 		 */
911 		} else {
912 			if (b_name) {
913 				eprintf(ofl->ofl_lml, ERR_FATAL,
914 				    MSG_INTL(MSG_MAP_MOREONCE), mapfile,
915 				    EC_XWORD(Line_num),
916 				    MSG_INTL(MSG_MAP_SECNAME));
917 				return (S_ERROR);
918 			}
919 			b_name = TRUE;
920 			if ((enp->ec_name =
921 			    libld_malloc(strlen(Start_tok) + 1)) == 0)
922 				return (S_ERROR);
923 			(void) strcpy((char *)enp->ec_name, Start_tok);
924 			/*
925 			 * get the index for text reordering
926 			 */
927 			/* LINTED */
928 			enp->ec_ndx = (Word)++index;
929 		}
930 	}
931 	if (tok == TK_COLON) {
932 		/*
933 		 * File names.
934 		 */
935 		while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
936 			char	*file;
937 
938 			/* LINTED */
939 			if (tok == (Token)S_ERROR)
940 				return (S_ERROR);
941 			if (tok == TK_EOF) {
942 				eprintf(ofl->ofl_lml, ERR_FATAL,
943 				    MSG_INTL(MSG_MAP_PREMEOF), mapfile,
944 				    EC_XWORD(Line_num));
945 				return (S_ERROR);
946 			}
947 			if (tok != TK_STRING) {
948 				eprintf(ofl->ofl_lml, ERR_FATAL,
949 				    MSG_INTL(MSG_MAP_MALFORM), mapfile,
950 				    EC_XWORD(Line_num));
951 				return (S_ERROR);
952 			}
953 			if ((file =
954 			    libld_malloc(strlen(Start_tok) + 1)) == 0)
955 				return (S_ERROR);
956 			(void) strcpy(file, Start_tok);
957 			if (list_appendc(&(enp->ec_files), file) == 0)
958 				return (S_ERROR);
959 		}
960 	}
961 	return (1);
962 }
963 
964 /*
965  * Obtain a pseudo input file descriptor to assign to a mapfile.  This is
966  * required any time a symbol is generated.  First traverse the input file
967  * descriptors looking for a match.  As all mapfile processing occurs before
968  * any real input file processing this list is going to be small and we don't
969  * need to do any filename clash checking.
970  */
971 static Ifl_desc *
972 map_ifl(const char *mapfile, Ofl_desc *ofl)
973 {
974 	Ifl_desc	*ifl;
975 	Listnode	*lnp;
976 
977 	for (LIST_TRAVERSE(&ofl->ofl_objs, lnp, ifl))
978 		if (strcmp(ifl->ifl_name, mapfile) == 0)
979 			return (ifl);
980 
981 	if ((ifl = libld_calloc(sizeof (Ifl_desc), 1)) == 0)
982 		return ((Ifl_desc *)S_ERROR);
983 	ifl->ifl_name = mapfile;
984 	ifl->ifl_flags = (FLG_IF_MAPFILE | FLG_IF_NEEDED | FLG_IF_FILEREF);
985 	if ((ifl->ifl_ehdr = libld_calloc(sizeof (Ehdr), 1)) == 0)
986 		return ((Ifl_desc *)S_ERROR);
987 	ifl->ifl_ehdr->e_type = ET_REL;
988 
989 	if (list_appendc(&ofl->ofl_objs, ifl) == 0)
990 		return ((Ifl_desc *)S_ERROR);
991 	else
992 		return (ifl);
993 }
994 
995 /*
996  * Process a mapfile size symbol definition.
997  * 	segment_name @ symbol_name;
998  */
999 static uintptr_t
1000 map_atsign(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl)
1001 {
1002 	Sym		*sym;		/* New symbol pointer */
1003 	Sym_desc	*sdp;		/* New symbol node pointer */
1004 	Ifl_desc	*ifl;		/* Dummy input file structure */
1005 	Token		tok;		/* Current token. */
1006 	avl_index_t	where;
1007 
1008 	if ((tok = gettoken(ofl, mapfile)) != TK_STRING) {
1009 		/* LINTED */
1010 		if (tok != (Token)S_ERROR)
1011 			eprintf(ofl->ofl_lml, ERR_FATAL,
1012 			    MSG_INTL(MSG_MAP_EXPSYM_1), mapfile,
1013 			    EC_XWORD(Line_num));
1014 		return (S_ERROR);
1015 	}
1016 
1017 	if (sgp->sg_sizesym != NULL) {
1018 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_MAP_SEGSIZE),
1019 		    mapfile, EC_XWORD(Line_num), sgp->sg_name);
1020 		return (S_ERROR);
1021 	}
1022 
1023 	/*
1024 	 * Make sure we have a pseudo file descriptor to associate to the
1025 	 * symbol.
1026 	 */
1027 	if ((ifl = map_ifl(mapfile, ofl)) == (Ifl_desc *)S_ERROR)
1028 		return (S_ERROR);
1029 
1030 	/*
1031 	 * Make sure the symbol doesn't already exist.  It is possible that the
1032 	 * symbol has been scoped or versioned, in which case it does exist
1033 	 * but we can freely update it here.
1034 	 */
1035 	if ((sdp = ld_sym_find(Start_tok, SYM_NOHASH, &where, ofl)) == NULL) {
1036 		char	*name;
1037 		Word hval;
1038 
1039 		if ((name = libld_malloc(strlen(Start_tok) + 1)) == 0)
1040 			return (S_ERROR);
1041 		(void) strcpy(name, Start_tok);
1042 
1043 		if ((sym = libld_calloc(sizeof (Sym), 1)) == 0)
1044 			return (S_ERROR);
1045 		sym->st_shndx = SHN_ABS;
1046 		sym->st_size = 0;
1047 		sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
1048 
1049 		DBG_CALL(Dbg_map_size_new(ofl->ofl_lml, name));
1050 		/* LINTED */
1051 		hval = (Word)elf_hash(name);
1052 		if ((sdp = ld_sym_enter(name, sym, hval, ifl, ofl, 0, SHN_ABS,
1053 		    (FLG_SY_SPECSEC | FLG_SY_GLOBREF), 0, &where)) ==
1054 		    (Sym_desc *)S_ERROR)
1055 			return (S_ERROR);
1056 		sdp->sd_flags &= ~FLG_SY_CLEAN;
1057 		DBG_CALL(Dbg_map_symbol(ofl, sdp));
1058 	} else {
1059 		sym = sdp->sd_sym;
1060 
1061 		if (sym->st_shndx == SHN_UNDEF) {
1062 			sdp->sd_shndx = sym->st_shndx = SHN_ABS;
1063 			sdp->sd_flags |= FLG_SY_SPECSEC;
1064 			sym->st_size = 0;
1065 			sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
1066 
1067 			sdp->sd_flags &= ~FLG_SY_MAPREF;
1068 
1069 			DBG_CALL(Dbg_map_size_old(ofl, sdp));
1070 		} else {
1071 			eprintf(ofl->ofl_lml, ERR_FATAL,
1072 			    MSG_INTL(MSG_MAP_SYMDEF), mapfile,
1073 			    EC_XWORD(Line_num), demangle(sdp->sd_name),
1074 			    sdp->sd_file->ifl_name);
1075 			return (S_ERROR);
1076 		}
1077 	}
1078 
1079 	/*
1080 	 * Assign the symbol to the segment.
1081 	 */
1082 	sgp->sg_sizesym = sdp;
1083 
1084 	if (gettoken(ofl, mapfile) != TK_SEMICOLON) {
1085 		/* LINTED */
1086 		if (tok != (Token)S_ERROR)
1087 			eprintf(ofl->ofl_lml, ERR_FATAL,
1088 			    MSG_INTL(MSG_MAP_EXPSCOL), mapfile,
1089 			    EC_XWORD(Line_num));
1090 		return (S_ERROR);
1091 	} else
1092 		return (1);
1093 }
1094 
1095 
1096 static uintptr_t
1097 map_pipe(Ofl_desc *ofl, const char *mapfile, Sg_desc *sgp)
1098 {
1099 	char		*sec_name;	/* section name */
1100 	Token		tok;		/* current token. */
1101 	Sec_order	*sc_order;
1102 	static Word	index = 0;	/* used to maintain a increasing */
1103 					/* 	index for section ordering. */
1104 
1105 	if ((tok = gettoken(ofl, mapfile)) != TK_STRING) {
1106 		/* LINTED */
1107 		if (tok != (Token)S_ERROR)
1108 			eprintf(ofl->ofl_lml, ERR_FATAL,
1109 			    MSG_INTL(MSG_MAP_EXPSEC), mapfile,
1110 			    EC_XWORD(Line_num));
1111 		return (S_ERROR);
1112 	}
1113 
1114 	if ((sec_name = libld_malloc(strlen(Start_tok) + 1)) == 0)
1115 		return (S_ERROR);
1116 	(void) strcpy(sec_name, Start_tok);
1117 
1118 	if ((sc_order = libld_malloc(sizeof (Sec_order))) == 0)
1119 		return (S_ERROR);
1120 
1121 	sc_order->sco_secname = sec_name;
1122 	sc_order->sco_index = ++index;
1123 
1124 	if (alist_append(&(sgp->sg_secorder), &sc_order,
1125 	    sizeof (Sec_order *), AL_CNT_SECORDER) == 0)
1126 		return (S_ERROR);
1127 
1128 	DBG_CALL(Dbg_map_pipe(ofl->ofl_lml, sgp, sec_name, index));
1129 
1130 	if ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
1131 		/* LINTED */
1132 		if (tok != (Token)S_ERROR)
1133 			eprintf(ofl->ofl_lml, ERR_FATAL,
1134 			    MSG_INTL(MSG_MAP_EXPSCOL), mapfile,
1135 			    EC_XWORD(Line_num));
1136 		return (S_ERROR);
1137 	}
1138 
1139 	return (1);
1140 }
1141 
1142 
1143 /*
1144  * Process a mapfile library specification definition.
1145  * 	shared_object_name - shared object definition
1146  *	shared object definition : [ shared object type [ = SONAME ]]
1147  *					[ versions ];
1148  */
1149 static uintptr_t
1150 map_dash(const char *mapfile, char *name, Ofl_desc *ofl)
1151 {
1152 	char		*version;
1153 	Token		tok;
1154 	Sdf_desc	*sdf;
1155 	Sdv_desc	*sdv;
1156 	enum {
1157 	    MD_NONE = 0,
1158 	    MD_SPECVERS,
1159 	    MD_ADDVERS,
1160 	    MD_NEEDED
1161 	}		dolkey = MD_NONE;
1162 
1163 
1164 	/*
1165 	 * If a shared object definition for this file already exists use it,
1166 	 * otherwise allocate a new descriptor.
1167 	 */
1168 	if ((sdf = sdf_find(name, &ofl->ofl_socntl)) == 0) {
1169 		if ((sdf = sdf_add(name, &ofl->ofl_socntl)) ==
1170 		    (Sdf_desc *)S_ERROR)
1171 			return (S_ERROR);
1172 		sdf->sdf_rfile = mapfile;
1173 	}
1174 
1175 	/*
1176 	 * Get the shared object descriptor string.
1177 	 */
1178 	while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
1179 		/* LINTED */
1180 		if (tok == (Token)S_ERROR)
1181 			return (S_ERROR);
1182 		if (tok == TK_EOF) {
1183 			eprintf(ofl->ofl_lml, ERR_FATAL,
1184 			    MSG_INTL(MSG_MAP_PREMEOF), mapfile,
1185 			    EC_XWORD(Line_num));
1186 			return (S_ERROR);
1187 		}
1188 		if ((tok != TK_STRING) && (tok != TK_EQUAL)) {
1189 			eprintf(ofl->ofl_lml, ERR_FATAL,
1190 			    MSG_INTL(MSG_MAP_EXPSO), mapfile,
1191 			    EC_XWORD(Line_num));
1192 			return (S_ERROR);
1193 		}
1194 
1195 		/*
1196 		 * Determine if the library type is accompanied with a SONAME
1197 		 * definition.
1198 		 */
1199 		if (tok == TK_EQUAL) {
1200 			if ((tok = gettoken(ofl, mapfile)) != TK_STRING) {
1201 				/* LINTED */
1202 				if (tok == (Token)S_ERROR)
1203 					return (S_ERROR);
1204 				else {
1205 					eprintf(ofl->ofl_lml, ERR_FATAL,
1206 					    MSG_INTL(MSG_MAP_EXPSO), mapfile,
1207 					    EC_XWORD(Line_num));
1208 					return (S_ERROR);
1209 				}
1210 			}
1211 			switch (dolkey) {
1212 			case MD_NEEDED:
1213 				if (sdf->sdf_flags & FLG_SDF_SONAME) {
1214 					eprintf(ofl->ofl_lml, ERR_WARNING,
1215 					    MSG_INTL(MSG_MAP_MULSONAME),
1216 					    mapfile, EC_XWORD(Line_num), name,
1217 					    sdf->sdf_soname, Start_tok);
1218 					dolkey = MD_NONE;
1219 					continue;
1220 				}
1221 				if ((sdf->sdf_soname =
1222 				    libld_malloc(strlen(Start_tok) + 1)) == 0)
1223 					return (S_ERROR);
1224 				(void) strcpy((char *)sdf->sdf_soname,
1225 					Start_tok);
1226 				sdf->sdf_flags |= FLG_SDF_SONAME;
1227 				break;
1228 			case MD_SPECVERS:
1229 			case MD_ADDVERS:
1230 				if ((sdv = libld_calloc(
1231 				    sizeof (Sdv_desc), 1)) == 0)
1232 					return (S_ERROR);
1233 
1234 				if (dolkey == MD_SPECVERS)
1235 					sdf->sdf_flags |= FLG_SDF_SPECVER;
1236 				else
1237 					sdf->sdf_flags |= FLG_SDF_ADDVER;
1238 
1239 				if ((sdf->sdf_flags & (FLG_SDF_SPECVER |
1240 				    FLG_SDF_ADDVER)) == (FLG_SDF_SPECVER |
1241 				    FLG_SDF_ADDVER)) {
1242 					eprintf(ofl->ofl_lml, ERR_FATAL,
1243 					    MSG_INTL(MSG_MAP_INCOMFLG),
1244 					    mapfile, EC_XWORD(Line_num),
1245 					    sdf->sdf_name);
1246 					return (S_ERROR);
1247 				}
1248 				if ((version =
1249 				    libld_malloc(strlen(Start_tok) + 1)) == 0)
1250 					return (S_ERROR);
1251 				(void) strcpy(version, Start_tok);
1252 				sdv->sdv_name = version;
1253 				sdv->sdv_ref = mapfile;
1254 				if (list_appendc(&sdf->sdf_verneed, sdv) == 0)
1255 					return (S_ERROR);
1256 				break;
1257 			case MD_NONE:
1258 				eprintf(ofl->ofl_lml, ERR_FATAL,
1259 				    MSG_INTL(MSG_MAP_UNEXTOK), mapfile,
1260 					EC_XWORD(Line_num), '=');
1261 				return (S_ERROR);
1262 			}
1263 			dolkey = MD_NONE;
1264 			continue;
1265 		}
1266 
1267 		/*
1268 		 * A shared object type has been specified.  This may also be
1269 		 * accompanied by an SONAME redefinition (see above).
1270 		 */
1271 		if (*Start_tok == '$') {
1272 			if (dolkey != MD_NONE) {
1273 				eprintf(ofl->ofl_lml, ERR_FATAL,
1274 				    MSG_INTL(MSG_MAP_UNEXTOK), mapfile,
1275 				    EC_XWORD(Line_num), '$');
1276 				return (S_ERROR);
1277 			}
1278 			Start_tok++;
1279 			lowercase(Start_tok);
1280 			if (strcmp(Start_tok,
1281 			    MSG_ORIG(MSG_MAP_NEED)) == 0)
1282 				dolkey = MD_NEEDED;
1283 			else if (strcmp(Start_tok,
1284 			    MSG_ORIG(MSG_MAP_SPECVERS)) == 0)
1285 				dolkey = MD_SPECVERS;
1286 			else if (strcmp(Start_tok,
1287 			    MSG_ORIG(MSG_MAP_ADDVERS)) == 0)
1288 				dolkey = MD_ADDVERS;
1289 			else {
1290 				eprintf(ofl->ofl_lml, ERR_FATAL,
1291 				    MSG_INTL(MSG_MAP_UNKSOTYP), mapfile,
1292 				    EC_XWORD(Line_num), Start_tok);
1293 				return (S_ERROR);
1294 			}
1295 			continue;
1296 		}
1297 
1298 		/*
1299 		 * shared object version requirement.
1300 		 */
1301 		if ((version = libld_malloc(strlen(Start_tok) + 1)) == 0)
1302 			return (S_ERROR);
1303 		(void) strcpy(version, Start_tok);
1304 		if ((sdv = libld_calloc(sizeof (Sdv_desc), 1)) == 0)
1305 			return (S_ERROR);
1306 		sdv->sdv_name = version;
1307 		sdv->sdv_ref = mapfile;
1308 		sdf->sdf_flags |= FLG_SDF_SELECT;
1309 		if (list_appendc(&sdf->sdf_vers, sdv) == 0)
1310 			return (S_ERROR);
1311 	}
1312 
1313 	DBG_CALL(Dbg_map_dash(ofl->ofl_lml, name, sdf));
1314 	return (1);
1315 }
1316 
1317 
1318 /*
1319  * Process a symbol definition.  Historically, this originated from processing
1320  * a version definition.  However, this has evolved into a generic means of
1321  * defining symbol references and definitions (see Defining Additional Symbols
1322  * in the Linker and Libraries guide for the complete syntax).
1323  *
1324  * [ name ] {
1325  *	scope:
1326  *		 symbol [ = [ type ] [ value ] [ size ] [ attribute ] ];
1327  * } [ dependency ];
1328  *
1329  */
1330 #define	SYMNO		50		/* Symbol block allocation amount */
1331 #define	FLG_SCOPE_LOCL	0		/* local scope flag */
1332 #define	FLG_SCOPE_GLOB	1		/* global scope flag */
1333 #define	FLG_SCOPE_SYMB	2		/* symbolic scope flag */
1334 #define	FLG_SCOPE_ELIM	3		/* eliminate symbol from symtabs */
1335 
1336 static uintptr_t
1337 map_version(const char *mapfile, char *name, Ofl_desc *ofl)
1338 {
1339 	Token		tok;
1340 	Sym		*sym;
1341 	int		scope = FLG_SCOPE_GLOB;
1342 	Ver_desc	*vdp;
1343 	Word		hash;
1344 	Ifl_desc	*ifl;
1345 	avl_index_t	where;
1346 
1347 	/*
1348 	 * If we're generating segments within the image then any symbol
1349 	 * reductions will be processed (ie. applied to relocations and symbol
1350 	 * table entries).  Otherwise (when creating a relocatable object) any
1351 	 * versioning information is simply recorded for use in a later
1352 	 * (segment generating) link-edit.
1353 	 */
1354 	if (ofl->ofl_flags & FLG_OF_RELOBJ)
1355 		ofl->ofl_flags |= FLG_OF_VERDEF;
1356 
1357 	/*
1358 	 * If this is a new mapfile reference generate an input file descriptor
1359 	 * to represent it.  Otherwise this must simply be a new version within
1360 	 * the mapfile we've previously been processing, in this case continue
1361 	 * to use the original input file descriptor.
1362 	 */
1363 	if ((ifl = map_ifl(mapfile, ofl)) == (Ifl_desc *)S_ERROR)
1364 		return (S_ERROR);
1365 
1366 	/*
1367 	 * If no version descriptors have yet been set up, initialize a base
1368 	 * version to represent the output file itself.  This `base' version
1369 	 * catches any internally generated symbols (_end, _etext, etc.) and
1370 	 * serves to initialize the output version descriptor count.
1371 	 */
1372 	if (ofl->ofl_vercnt == 0) {
1373 		if (ld_vers_base(ofl) == (Ver_desc *)S_ERROR)
1374 			return (S_ERROR);
1375 	}
1376 
1377 	/*
1378 	 * If this definition has an associated version name then generate a
1379 	 * new version descriptor and an associated version symbol index table.
1380 	 */
1381 	if (name) {
1382 		ofl->ofl_flags |= FLG_OF_VERDEF;
1383 
1384 		/*
1385 		 * Traverse the present version descriptor list to see if there
1386 		 * is already one of the same name, otherwise create a new one.
1387 		 */
1388 		/* LINTED */
1389 		hash = (Word)elf_hash(name);
1390 		if ((vdp = ld_vers_find(name, hash, &ofl->ofl_verdesc)) == 0) {
1391 			if ((vdp = ld_vers_desc(name, hash,
1392 			    &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR)
1393 				return (S_ERROR);
1394 		}
1395 
1396 		/*
1397 		 * Initialize any new version with an index, the file from which
1398 		 * it was first referenced, and a WEAK flag (indicates that
1399 		 * there are no symbols assigned to it yet).
1400 		 */
1401 		if (vdp->vd_ndx == 0) {
1402 			/* LINTED */
1403 			vdp->vd_ndx = (Half)++ofl->ofl_vercnt;
1404 			vdp->vd_file = ifl;
1405 			vdp->vd_flags = VER_FLG_WEAK;
1406 		}
1407 	} else {
1408 		/*
1409 		 * If a version definition hasn't been specified assign any
1410 		 * symbols to the base version.
1411 		 */
1412 		vdp = (Ver_desc *)ofl->ofl_verdesc.head->data;
1413 	}
1414 
1415 	/*
1416 	 * Scan the mapfile entry picking out scoping and symbol definitions.
1417 	 */
1418 	while ((tok = gettoken(ofl, mapfile)) != TK_RIGHTBKT) {
1419 		Sym_desc * 	sdp;
1420 		Word		shndx = SHN_UNDEF;
1421 		uchar_t 	type = STT_NOTYPE;
1422 		Addr		value = 0, size = 0;
1423 		char		*_name, *filtee = 0;
1424 		Word		sym_flags = 0;
1425 		Half		sym_flags1 = 0;
1426 		uint_t		filter = 0, novalue = 1, dftflag;
1427 
1428 		if ((tok != TK_STRING) && (tok != TK_COLON)) {
1429 			eprintf(ofl->ofl_lml, ERR_FATAL,
1430 			    MSG_INTL(MSG_MAP_EXPSYM_2), mapfile,
1431 			    EC_XWORD(Line_num));
1432 			return (S_ERROR);
1433 		}
1434 
1435 		if ((_name = libld_malloc(strlen(Start_tok) + 1)) == 0)
1436 			return (S_ERROR);
1437 		(void) strcpy(_name, Start_tok);
1438 
1439 		if ((tok != TK_COLON) &&
1440 		    /* LINTED */
1441 		    (tok = gettoken(ofl, mapfile)) == (Token)S_ERROR)
1442 			return (S_ERROR);
1443 
1444 		/*
1445 		 * Turn off the WEAK flag to indicate that definitions are
1446 		 * associated with this version.  It would probably be more
1447 		 * accurate to only remove this flag with the specification of
1448 		 * global symbols, however setting it here allows enough slop
1449 		 * to compensate for the various user inputs we've seen so far.
1450 		 * Only if a closed version is specified (i.e., "SUNW_1.x {};")
1451 		 * will a user get a weak version (which is how we document the
1452 		 * creation of weak versions).
1453 		 */
1454 		vdp->vd_flags &= ~VER_FLG_WEAK;
1455 
1456 		switch (tok) {
1457 		case TK_COLON:
1458 			/*
1459 			 * Establish a new scope.  All symbols added by this
1460 			 * mapfile are actually global entries. They will be
1461 			 * reduced to locals during sym_update().  If a symbolic
1462 			 * scope is detected, remember this.  If a symbolic
1463 			 * scope is the only scope defined in this (or any other
1464 			 * mapfiles), then -Bsymbolic is established.
1465 			 */
1466 			if ((strcmp(MSG_ORIG(MSG_STR_LOCAL),
1467 			    _name) == 0) ||
1468 			    (strcmp(MSG_ORIG(MSG_MAP_HIDDEN), _name) == 0)) {
1469 				scope = FLG_SCOPE_LOCL;
1470 			} else if ((strcmp(MSG_ORIG(MSG_MAP_GLOBAL),
1471 			    _name) == 0) ||
1472 			    (strcmp(MSG_ORIG(MSG_MAP_DEFAULT), _name) == 0)) {
1473 				scope = FLG_SCOPE_GLOB;
1474 				ofl->ofl_flags |= FLG_OF_MAPGLOB;
1475 			} else if ((strcmp(MSG_ORIG(MSG_STR_SYMBOLIC),
1476 			    _name) == 0) ||
1477 			    (strcmp(MSG_ORIG(MSG_MAP_PROTECTED), _name) == 0)) {
1478 				scope = FLG_SCOPE_SYMB;
1479 				ofl->ofl_flags |= FLG_OF_MAPSYMB;
1480 			} else if (strcmp(MSG_ORIG(MSG_STR_ELIMINATE),
1481 			    _name) == 0)
1482 				scope = FLG_SCOPE_ELIM;
1483 			else {
1484 				eprintf(ofl->ofl_lml, ERR_FATAL,
1485 				    MSG_INTL(MSG_MAP_UNKSYMSCO), mapfile,
1486 				    EC_XWORD(Line_num), _name);
1487 				return (S_ERROR);
1488 			}
1489 			continue;
1490 
1491 		case TK_EQUAL:
1492 			/*
1493 			 * A full blown symbol definition follows.
1494 			 * Determine the symbol type and any virtual address or
1495 			 * alignment specified and then fall through to process
1496 			 * the entire symbols information.
1497 			 */
1498 			while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
1499 				/*
1500 				 * If we had previously seen a filter or
1501 				 * auxiliary filter requirement, the next string
1502 				 * is the filtee itself.
1503 				 */
1504 				if (filter) {
1505 					if (filtee) {
1506 					    eprintf(ofl->ofl_lml, ERR_FATAL,
1507 						MSG_INTL(MSG_MAP_MULTFILTEE),
1508 						mapfile, EC_XWORD(Line_num),
1509 						_name);
1510 					    return (S_ERROR);
1511 					}
1512 					if ((filtee = libld_malloc(
1513 					    strlen(Start_tok) + 1)) == 0)
1514 						return (S_ERROR);
1515 					(void) strcpy(filtee, Start_tok);
1516 					filter = 0;
1517 					continue;
1518 				}
1519 
1520 				/*
1521 				 * Determine any Value or Size attributes.
1522 				 */
1523 				lowercase(Start_tok);
1524 
1525 				if (Start_tok[0] == 'v' ||
1526 				    Start_tok[0] == 's') {
1527 					char		*end_tok;
1528 					Lword		number;
1529 
1530 					if ((number = (Lword)STRTOADDR(
1531 					    &Start_tok[1], &end_tok, 0)) ==
1532 					    XWORD_MAX) {
1533 						eprintf(ofl->ofl_lml, ERR_FATAL,
1534 						    MSG_INTL(MSG_MAP_SEGADDR),
1535 						    mapfile, EC_XWORD(Line_num),
1536 						    Start_tok,
1537 						    MSG_INTL(MSG_MAP_EXCLIMIT));
1538 						return (S_ERROR);
1539 					}
1540 
1541 					if (end_tok !=
1542 					    strchr(Start_tok, '\0')) {
1543 						eprintf(ofl->ofl_lml, ERR_FATAL,
1544 						    MSG_INTL(MSG_MAP_SEGADDR),
1545 						    mapfile, EC_XWORD(Line_num),
1546 						    Start_tok,
1547 						    MSG_INTL(MSG_MAP_NOBADFRM));
1548 						return (S_ERROR);
1549 					}
1550 
1551 					switch (*Start_tok) {
1552 					case 'v':
1553 					    if (value) {
1554 						eprintf(ofl->ofl_lml, ERR_FATAL,
1555 						    MSG_INTL(MSG_MAP_MOREONCE),
1556 						    mapfile, EC_XWORD(Line_num),
1557 						    MSG_INTL(MSG_MAP_SYMVAL));
1558 						return (S_ERROR);
1559 					    }
1560 					    /* LINTED */
1561 					    value = (Addr)number;
1562 					    novalue = 0;
1563 					    break;
1564 					case 's':
1565 					    if (size) {
1566 						eprintf(ofl->ofl_lml, ERR_FATAL,
1567 						    MSG_INTL(MSG_MAP_MOREONCE),
1568 						    mapfile, EC_XWORD(Line_num),
1569 						    MSG_INTL(MSG_MAP_SYMSIZE));
1570 						return (S_ERROR);
1571 					    }
1572 					    /* LINTED */
1573 					    size = (Addr)number;
1574 					    break;
1575 					}
1576 
1577 				} else if (strcmp(Start_tok,
1578 				    MSG_ORIG(MSG_MAP_FUNCTION)) == 0) {
1579 					shndx = SHN_ABS;
1580 					sym_flags |= FLG_SY_SPECSEC;
1581 					type = STT_FUNC;
1582 				} else if (strcmp(Start_tok,
1583 				    MSG_ORIG(MSG_MAP_DATA)) == 0) {
1584 					shndx = SHN_ABS;
1585 					sym_flags |= FLG_SY_SPECSEC;
1586 					type = STT_OBJECT;
1587 				} else if (strcmp(Start_tok,
1588 				    MSG_ORIG(MSG_MAP_COMMON)) == 0) {
1589 					shndx = SHN_COMMON;
1590 					sym_flags |= FLG_SY_SPECSEC;
1591 					type = STT_OBJECT;
1592 				} else if (strcmp(Start_tok,
1593 				    MSG_ORIG(MSG_MAP_PARENT)) == 0) {
1594 					sym_flags |= FLG_SY_PARENT;
1595 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1596 				} else if (strcmp(Start_tok,
1597 				    MSG_ORIG(MSG_MAP_EXTERN)) == 0) {
1598 					sym_flags |= FLG_SY_EXTERN;
1599 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1600 				} else if (strcmp(Start_tok,
1601 				    MSG_ORIG(MSG_MAP_DIRECT)) == 0) {
1602 					sym_flags1 |= FLG_SY1_DIR;
1603 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1604 				} else if (strcmp(Start_tok,
1605 				    MSG_ORIG(MSG_MAP_NODIRECT)) == 0) {
1606 					if (scope == FLG_SCOPE_SYMB) {
1607 						eprintf(ofl->ofl_lml, ERR_FATAL,
1608 						    MSG_INTL(MSG_MAP_PROTNDIR),
1609 						    mapfile,
1610 						    EC_XWORD(Line_num));
1611 						return (S_ERROR);
1612 					}
1613 					sym_flags1 |= FLG_SY1_NDIR;
1614 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1615 					ofl->ofl_flags1 |= FLG_OF1_NDIRECT;
1616 					ofl->ofl_dtflags_1 |= DF_1_NODIRECT;
1617 				} else if (strcmp(Start_tok,
1618 				    MSG_ORIG(MSG_MAP_FILTER)) == 0) {
1619 					dftflag = filter = FLG_SY_STDFLTR;
1620 					sym_flags |= FLG_SY_STDFLTR;
1621 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1622 					continue;
1623 				} else if (strcmp(Start_tok,
1624 				    MSG_ORIG(MSG_MAP_AUXILIARY)) == 0) {
1625 					dftflag = filter = FLG_SY_AUXFLTR;
1626 					sym_flags |= FLG_SY_AUXFLTR;
1627 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1628 					continue;
1629 				} else if (strcmp(Start_tok,
1630 				    MSG_ORIG(MSG_MAP_INTERPOSE)) == 0) {
1631 					if (!(ofl->ofl_flags & FLG_OF_EXEC)) {
1632 						eprintf(ofl->ofl_lml, ERR_FATAL,
1633 						    MSG_INTL(MSG_MAP_NOINTPOSE),
1634 						    mapfile,
1635 						    EC_XWORD(Line_num));
1636 						return (S_ERROR);
1637 					}
1638 					sym_flags |= FLG_SY_INTPOSE;
1639 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1640 					ofl->ofl_dtflags_1 |= DF_1_SYMINTPOSE;
1641 					continue;
1642 				} else if (strcmp(Start_tok,
1643 				    MSG_ORIG(MSG_MAP_DYNSORT)) == 0) {
1644 					sym_flags |= FLG_SY_DYNSORT;
1645 					sym_flags &= ~FLG_SY_NODYNSORT;
1646 					continue;
1647 				} else if (strcmp(Start_tok,
1648 				    MSG_ORIG(MSG_MAP_NODYNSORT)) == 0) {
1649 					sym_flags &= ~FLG_SY_DYNSORT;
1650 					sym_flags |= FLG_SY_NODYNSORT;
1651 					continue;
1652 				} else {
1653 					eprintf(ofl->ofl_lml, ERR_FATAL,
1654 					    MSG_INTL(MSG_MAP_UNKSYMDEF),
1655 					    mapfile, EC_XWORD(Line_num),
1656 					    Start_tok);
1657 					return (S_ERROR);
1658 				}
1659 			}
1660 			/* FALLTHROUGH */
1661 
1662 		case TK_SEMICOLON:
1663 			/*
1664 			 * The special auto-reduction directive `*' can be
1665 			 * specified in local scope and indicates that all
1666 			 * symbols processed that are not explicitly defined to
1667 			 * be global are to be reduced to local scope in the
1668 			 * output image.  This also implies that a version
1669 			 * definition is created as the user has effectively
1670 			 * defined an interface.
1671 			 */
1672 			if (*_name == '*') {
1673 				if (scope == FLG_SCOPE_LOCL)
1674 					ofl->ofl_flags |=
1675 					    (FLG_OF_AUTOLCL | FLG_OF_VERDEF);
1676 				else if (scope == FLG_SCOPE_ELIM) {
1677 					ofl->ofl_flags |= FLG_OF_VERDEF;
1678 					ofl->ofl_flags1 |= FLG_OF1_AUTOELM;
1679 				}
1680 				continue;
1681 			}
1682 
1683 			/*
1684 			 * Add the new symbol.  It should be noted that all
1685 			 * symbols added by the mapfile start out with global
1686 			 * scope, thus they will fall through the normal symbol
1687 			 * resolution process.  Symbols defined as locals will
1688 			 * be reduced in scope after all input file processing.
1689 			 */
1690 			/* LINTED */
1691 			hash = (Word)elf_hash(_name);
1692 			DBG_CALL(Dbg_map_version(ofl->ofl_lml, name, _name,
1693 			    scope));
1694 			if ((sdp = ld_sym_find(_name, hash, &where,
1695 			    ofl)) == NULL) {
1696 				if ((sym = libld_calloc(sizeof (Sym), 1)) == 0)
1697 					return (S_ERROR);
1698 
1699 				/*
1700 				 * Make sure any parent or external declarations
1701 				 * fall back to references.
1702 				 */
1703 				if (sym_flags &
1704 				    (FLG_SY_PARENT | FLG_SY_EXTERN)) {
1705 					/*
1706 					 * Turn it into a reference by setting
1707 					 * the section index to UNDEF.
1708 					 */
1709 					sym->st_shndx = shndx = SHN_UNDEF;
1710 
1711 					/*
1712 					 * It is wrong to to specify size
1713 					 * or value for an external symbol.
1714 					 */
1715 					if ((novalue == 0) || (size != 0)) {
1716 						eprintf(ofl->ofl_lml, ERR_FATAL,
1717 						    MSG_INTL(MSG_MAP_NOEXVLSZ),
1718 						    mapfile,
1719 						    EC_XWORD(Line_num));
1720 						return (S_ERROR);
1721 					}
1722 				} else {
1723 					sym->st_shndx = (Half)shndx;
1724 				}
1725 
1726 				sym->st_value = value;
1727 				sym->st_size = size;
1728 				sym->st_info = ELF_ST_INFO(STB_GLOBAL, type);
1729 
1730 				if ((sdp = ld_sym_enter(_name, sym, hash, ifl,
1731 				    ofl, 0, shndx, sym_flags, sym_flags1,
1732 				    &where)) == (Sym_desc *)S_ERROR)
1733 					return (S_ERROR);
1734 
1735 				sdp->sd_flags &= ~FLG_SY_CLEAN;
1736 
1737 				/*
1738 				 * Identify any references.  FLG_SY_MAPREF is
1739 				 * turned off once a relocatable object with
1740 				 * the same symbol is found, thus the existance
1741 				 * of FLG_SY_MAPREF at symbol validation is
1742 				 * used to flag undefined/mispelt entries.
1743 				 */
1744 				if (sym->st_shndx == SHN_UNDEF)
1745 					sdp->sd_flags |=
1746 					    (FLG_SY_MAPREF | FLG_SY_GLOBREF);
1747 
1748 			} else {
1749 				int	conflict = 0;
1750 
1751 				sym = sdp->sd_sym;
1752 
1753 				/*
1754 				 * If this symbol already exists, make sure this
1755 				 * definition doesn't conflict with the former.
1756 				 * Provided it doesn't, multiple definitions can
1757 				 * augment each other.
1758 				 */
1759 				if (sym->st_value) {
1760 					if (value && (sym->st_value != value))
1761 						conflict = 1;
1762 				} else
1763 					sym->st_value = value;
1764 
1765 				if (sym->st_size) {
1766 					if (size && (sym->st_size != size))
1767 						conflict = 2;
1768 				} else
1769 					sym->st_size = size;
1770 
1771 				if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) {
1772 					if ((type != STT_NOTYPE) &&
1773 					    (ELF_ST_TYPE(sym->st_info) != type))
1774 						conflict = 3;
1775 				} else
1776 					sym->st_info =
1777 					    ELF_ST_INFO(STB_GLOBAL, type);
1778 
1779 				if (sym->st_shndx != SHN_UNDEF) {
1780 					if ((shndx != SHN_UNDEF) &&
1781 					    (sym->st_shndx != shndx))
1782 						conflict = 4;
1783 				} else
1784 					sdp->sd_shndx = sym->st_shndx = shndx;
1785 
1786 				if ((sdp->sd_flags1 & FLG_SY1_LOCL) &&
1787 				    ((scope != FLG_SCOPE_LOCL) &&
1788 				    (scope != FLG_SCOPE_ELIM)))
1789 					conflict = 5;
1790 				if ((sdp->sd_flags1 & FLG_SY1_GLOB) &&
1791 				    (scope != FLG_SCOPE_GLOB) &&
1792 				    (scope != FLG_SCOPE_SYMB))
1793 					conflict = 6;
1794 				if ((sdp->sd_flags1 & FLG_SY1_GLOB) &&
1795 				    (sdp->sd_aux->sa_overndx !=
1796 				    VER_NDX_GLOBAL) &&
1797 				    (vdp->vd_ndx != VER_NDX_GLOBAL) &&
1798 				    (sdp->sd_aux->sa_overndx != vdp->vd_ndx))
1799 					conflict = 7;
1800 
1801 				if (conflict) {
1802 					eprintf(ofl->ofl_lml, ERR_FATAL,
1803 					    MSG_INTL(MSG_MAP_SYMDEF), mapfile,
1804 					    EC_XWORD(Line_num), demangle(_name),
1805 					    sdp->sd_file->ifl_name);
1806 					return (S_ERROR);
1807 				}
1808 
1809 				/*
1810 				 * If this mapfile entry supplies a definition,
1811 				 * indicate that the symbol is now used.
1812 				 */
1813 				if (shndx != SHN_UNDEF)
1814 					sdp->sd_flags |= FLG_SY_MAPUSED;
1815 			}
1816 
1817 			/*
1818 			 * A symbol declaration that defines a size but no
1819 			 * value is processed as a request to create an
1820 			 * associated backing section.  The intent behind this
1821 			 * functionality is to provide OBJT definitions within
1822 			 * filters that are not ABS.  ABS symbols don't allow
1823 			 * copy-relocations to be established to filter OBJT
1824 			 * definitions.
1825 			 */
1826 			if ((shndx == SHN_ABS) && size && novalue &&
1827 			    (sdp->sd_isc == 0)) {
1828 				Is_desc	*isp;
1829 
1830 				if (type == STT_OBJECT) {
1831 					if ((isp = ld_make_data(ofl,
1832 					    size)) == (Is_desc *)S_ERROR)
1833 						return (S_ERROR);
1834 				} else {
1835 					if ((isp = ld_make_text(ofl,
1836 					    size)) == (Is_desc *)S_ERROR)
1837 						return (S_ERROR);
1838 				}
1839 
1840 				/*
1841 				 * Now that backing storage has been created,
1842 				 * associate the symbol descriptor.  Remove the
1843 				 * symbols special section tag so that it will
1844 				 * be assigned the correct section index as part
1845 				 * of update symbol processing.
1846 				 */
1847 				sdp->sd_flags &= ~FLG_SY_SPECSEC;
1848 				sym_flags &= ~FLG_SY_SPECSEC;
1849 				sdp->sd_isc = isp;
1850 				isp->is_file = ifl;
1851 			}
1852 
1853 			/*
1854 			 * Indicate the new symbols scope.
1855 			 */
1856 			if (scope == FLG_SCOPE_LOCL) {
1857 				sdp->sd_flags1 |= FLG_SY1_LOCL;
1858 				sdp->sd_sym->st_other = STV_HIDDEN;
1859 				if (ofl->ofl_flags1 & FLG_OF1_REDLSYM)
1860 					sdp->sd_flags1 |= FLG_SY1_ELIM;
1861 
1862 			} else if (scope == FLG_SCOPE_ELIM) {
1863 				sdp->sd_flags1 |= (FLG_SY1_LOCL | FLG_SY1_ELIM);
1864 				sdp->sd_sym->st_other = STV_HIDDEN;
1865 			} else {
1866 				sdp->sd_flags |= sym_flags;
1867 				sdp->sd_flags1 |= (sym_flags1 | FLG_SY1_GLOB);
1868 
1869 				if (scope == FLG_SCOPE_SYMB) {
1870 					sdp->sd_flags1 |= FLG_SY1_PROT;
1871 					sdp->sd_sym->st_other = STV_PROTECTED;
1872 				}
1873 
1874 				/*
1875 				 * Record the present version index for later
1876 				 * potential versioning.
1877 				 */
1878 				if ((sdp->sd_aux->sa_overndx == 0) ||
1879 				    (sdp->sd_aux->sa_overndx == VER_NDX_GLOBAL))
1880 					sdp->sd_aux->sa_overndx = vdp->vd_ndx;
1881 				vdp->vd_flags |= FLG_VER_REFER;
1882 			}
1883 
1884 			/*
1885 			 * If we've encountered a symbol definition simulate
1886 			 * that an input file has been processed - this allows
1887 			 * things like filters to be created purely from a
1888 			 * mapfile.
1889 			 */
1890 			if (type != STT_NOTYPE)
1891 				ofl->ofl_objscnt++;
1892 			DBG_CALL(Dbg_map_symbol(ofl, sdp));
1893 
1894 			/*
1895 			 * If this symbol has an associated filtee, record the
1896 			 * filtee string and associate the string index with the
1897 			 * symbol.  This is used later to associate the syminfo
1898 			 * information with the necessary .dynamic entry.
1899 			 */
1900 			if (filter && (filtee == 0)) {
1901 				eprintf(ofl->ofl_lml, ERR_FATAL,
1902 				    MSG_INTL(MSG_MAP_NOFILTER), mapfile,
1903 				    EC_XWORD(Line_num), _name);
1904 				return (S_ERROR);
1905 			}
1906 
1907 			if (filtee) {
1908 				Dfltr_desc *	dftp;
1909 				Sfltr_desc	sft;
1910 				Aliste		off = 0, _off;
1911 
1912 				/*
1913 				 * Make sure we don't duplicate any filtee
1914 				 * strings, and create a new descriptor if
1915 				 * necessary.
1916 				 */
1917 				for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, _off,
1918 				    dftp)) {
1919 					if ((dftflag != dftp->dft_flag) ||
1920 					    (strcmp(dftp->dft_str, filtee)))
1921 						continue;
1922 					off = _off;
1923 					break;
1924 				}
1925 				if (off == 0) {
1926 					Dfltr_desc	dft;
1927 
1928 					dft.dft_str = filtee;
1929 					dft.dft_flag = dftflag;
1930 					dft.dft_ndx = 0;
1931 
1932 					if ((dftp =
1933 					    alist_append(&(ofl->ofl_dtsfltrs),
1934 					    &dft, sizeof (Dfltr_desc),
1935 					    AL_CNT_DFLTR)) == 0)
1936 						return (S_ERROR);
1937 
1938 					off = (Aliste)((char *)dftp -
1939 					    (char *)ofl->ofl_dtsfltrs);
1940 				}
1941 
1942 				/*
1943 				 * Create a new filter descriptor for this
1944 				 * symbol.
1945 				 */
1946 				sft.sft_sdp = sdp;
1947 				sft.sft_off = off;
1948 
1949 				if (alist_append(&(ofl->ofl_symfltrs),
1950 				    &sft, sizeof (Sfltr_desc),
1951 				    AL_CNT_SFLTR) == 0)
1952 					return (S_ERROR);
1953 			}
1954 			break;
1955 
1956 		default:
1957 			eprintf(ofl->ofl_lml, ERR_FATAL,
1958 			    MSG_INTL(MSG_MAP_EXPSCOL), mapfile,
1959 			    EC_XWORD(Line_num));
1960 			return (S_ERROR);
1961 		}
1962 	}
1963 
1964 	/*
1965 	 * Determine if any version references are provided after the close
1966 	 * bracket.
1967 	 */
1968 	while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
1969 		Ver_desc	*_vdp;
1970 		char		*_name;
1971 
1972 		if (tok != TK_STRING) {
1973 			/* LINTED */
1974 			if (tok != (Token)S_ERROR)
1975 				eprintf(ofl->ofl_lml, ERR_FATAL,
1976 				    MSG_INTL(MSG_MAP_EXPVERS), mapfile,
1977 				    EC_XWORD(Line_num));
1978 			return (S_ERROR);
1979 		}
1980 
1981 		name = Start_tok;
1982 		if (vdp->vd_ndx == VER_NDX_GLOBAL) {
1983 			eprintf(ofl->ofl_lml, ERR_WARNING,
1984 			    MSG_INTL(MSG_MAP_UNEXDEP), mapfile,
1985 			    EC_XWORD(Line_num), name);
1986 			continue;
1987 		}
1988 
1989 		/*
1990 		 * Generate a new version descriptor if it doesn't already
1991 		 * exist.
1992 		 */
1993 		/* LINTED */
1994 		hash = (Word)elf_hash(name);
1995 		if ((_vdp = ld_vers_find(name, hash, &ofl->ofl_verdesc)) == 0) {
1996 			if ((_name = libld_malloc(strlen(name) + 1)) == 0)
1997 				return (S_ERROR);
1998 			(void) strcpy(_name, name);
1999 
2000 			if ((_vdp = ld_vers_desc(_name, hash,
2001 			    &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR)
2002 				return (S_ERROR);
2003 		}
2004 
2005 		/*
2006 		 * Add the new version descriptor to the parent version
2007 		 * descriptors reference list.  Indicate the version descriptors
2008 		 * first reference (used for error disgnostics if undefined
2009 		 * version dependencies remain).
2010 		 */
2011 		if (ld_vers_find(name, hash, &vdp->vd_deps) == 0)
2012 			if (list_appendc(&vdp->vd_deps, _vdp) == 0)
2013 				return (S_ERROR);
2014 
2015 		if (_vdp->vd_ref == 0)
2016 			_vdp->vd_ref = vdp;
2017 	}
2018 	return (1);
2019 }
2020 
2021 /*
2022  * Sort the segment list by increasing virtual address.
2023  */
2024 uintptr_t
2025 ld_sort_seg_list(Ofl_desc *ofl)
2026 {
2027 	List 		seg1, seg2;
2028 	Listnode	*lnp1, *lnp2, *lnp3;
2029 	Sg_desc		*sgp1, *sgp2;
2030 
2031 	seg1.head = seg1.tail = seg2.head = seg2.tail = NULL;
2032 
2033 	/*
2034 	 * Add the .phdr and .interp segments to our list.  These segments must
2035 	 * occur before any PT_LOAD segments (refer exec/elf/elf.c).  Also add
2036 	 * the capabilities segment.  This isn't essential, but the capabilities
2037 	 * section is one of the first in an object.
2038 	 */
2039 	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
2040 		Word	type = sgp1->sg_phdr.p_type;
2041 
2042 		if ((type == PT_PHDR) || (type == PT_INTERP) ||
2043 		    (type == PT_SUNWCAP)) {
2044 			if (list_appendc(&seg1, sgp1) == 0)
2045 				return (S_ERROR);
2046 		}
2047 	}
2048 
2049 	/*
2050 	 * Add the loadable segments to another list in sorted order.
2051 	 */
2052 	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
2053 		DBG_CALL(Dbg_map_sort_orig(ofl->ofl_lml, sgp1));
2054 
2055 		if (sgp1->sg_phdr.p_type != PT_LOAD)
2056 			continue;
2057 
2058 		if (!(sgp1->sg_flags & FLG_SG_VADDR) ||
2059 		    (sgp1->sg_flags & FLG_SG_EMPTY)) {
2060 			if (list_appendc(&seg2, sgp1) == 0)
2061 				return (S_ERROR);
2062 		} else {
2063 			if (seg2.head == NULL) {
2064 				if (list_appendc(&seg2, sgp1) == 0)
2065 					return (S_ERROR);
2066 				continue;
2067 			}
2068 			lnp3 = NULL;
2069 			for (LIST_TRAVERSE(&seg2, lnp2, sgp2)) {
2070 				if (!(sgp2->sg_flags & FLG_SG_VADDR) ||
2071 				    (sgp2->sg_flags & FLG_SG_EMPTY)) {
2072 					if (lnp3 == NULL) {
2073 						if (list_prependc(&seg2,
2074 						    sgp1) == 0)
2075 							return (S_ERROR);
2076 					} else {
2077 						if (list_insertc(&seg2,
2078 						    sgp1, lnp3) == 0)
2079 							return (S_ERROR);
2080 					}
2081 					lnp3 = NULL;
2082 					break;
2083 				}
2084 				if (sgp1->sg_phdr.p_vaddr <
2085 				    sgp2->sg_phdr.p_vaddr) {
2086 					if (lnp3 == NULL) {
2087 						if (list_prependc(&seg2,
2088 						    sgp1) == 0)
2089 							return (S_ERROR);
2090 					} else {
2091 						if (list_insertc(&seg2,
2092 						    sgp1, lnp3) == 0)
2093 							return (S_ERROR);
2094 					}
2095 					lnp3 = NULL;
2096 					break;
2097 				} else if (sgp1->sg_phdr.p_vaddr >
2098 				    sgp2->sg_phdr.p_vaddr) {
2099 					lnp3 = lnp2;
2100 				} else {
2101 					eprintf(ofl->ofl_lml, ERR_FATAL,
2102 					    MSG_INTL(MSG_MAP_SEGSAME),
2103 					    sgp1->sg_name, sgp2->sg_name);
2104 					return (S_ERROR);
2105 				}
2106 			}
2107 			if (lnp3 != NULL)
2108 				if (list_appendc(&seg2, sgp1) == 0)
2109 					return (S_ERROR);
2110 		}
2111 	}
2112 
2113 	/*
2114 	 * Add the sorted loadable segments to our list.
2115 	 */
2116 	for (LIST_TRAVERSE(&seg2, lnp1, sgp1)) {
2117 		if (list_appendc(&seg1, sgp1) == 0)
2118 			return (S_ERROR);
2119 	}
2120 
2121 	/*
2122 	 * Add all other segments to our list.
2123 	 */
2124 	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
2125 		Word	type = sgp1->sg_phdr.p_type;
2126 
2127 		if ((type != PT_PHDR) && (type != PT_INTERP) &&
2128 		    (type != PT_SUNWCAP) && (type != PT_LOAD)) {
2129 			if (list_appendc(&seg1, sgp1) == 0)
2130 				return (S_ERROR);
2131 		}
2132 	}
2133 	ofl->ofl_segs.head = ofl->ofl_segs.tail = NULL;
2134 
2135 	/*
2136 	 * Now rebuild the original list and process all of the
2137 	 * segment/section ordering information if present.
2138 	 */
2139 	for (LIST_TRAVERSE(&seg1, lnp1, sgp1)) {
2140 		DBG_CALL(Dbg_map_sort_fini(ofl->ofl_lml, sgp1));
2141 		if (list_appendc(&ofl->ofl_segs, sgp1) == 0)
2142 			return (S_ERROR);
2143 	}
2144 	return (1);
2145 }
2146 
2147 /*
2148  * Parse the mapfile.
2149  */
2150 uintptr_t
2151 ld_map_parse(const char *mapfile, Ofl_desc *ofl)
2152 {
2153 	struct stat	stat_buf;	/* stat of mapfile */
2154 	int		mapfile_fd;	/* descriptor for mapfile */
2155 	Listnode	*lnp1;		/* node pointer */
2156 	Listnode	*lnp2;		/* node pointer */
2157 	Sg_desc		*sgp1;		/* seg descriptor being manipulated */
2158 	Sg_desc		*sgp2;		/* temp segment descriptor pointer */
2159 	Ent_desc	*enp;		/* Segment entrance criteria. */
2160 	Token		tok;		/* current token. */
2161 	Listnode	*e_next = NULL;
2162 					/* next place for entrance criterion */
2163 	Boolean		new_segment;	/* If true, defines new segment. */
2164 	char		*name;
2165 	static	int	num_stack = 0;	/* number of stack segment */
2166 	int		err;
2167 
2168 	DBG_CALL(Dbg_map_parse(ofl->ofl_lml, mapfile));
2169 
2170 	/*
2171 	 * Determine if we're dealing with a file or a directory.
2172 	 */
2173 	if (stat(mapfile, &stat_buf) == -1) {
2174 		err = errno;
2175 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_STAT),
2176 		    mapfile, strerror(err));
2177 		return (S_ERROR);
2178 	}
2179 	if (S_ISDIR(stat_buf.st_mode)) {
2180 		DIR		*dirp;
2181 		struct dirent	*denp;
2182 
2183 		/*
2184 		 * Open the directory and interpret each visible file as a
2185 		 * mapfile.
2186 		 */
2187 		if ((dirp = opendir(mapfile)) == 0)
2188 			return (1);
2189 
2190 		while ((denp = readdir(dirp)) != NULL) {
2191 			char	path[PATH_MAX];
2192 
2193 			/*
2194 			 * Ignore any hidden filenames.  Construct the full
2195 			 * pathname to the new mapfile.
2196 			 */
2197 			if (*denp->d_name == '.')
2198 				continue;
2199 			(void) snprintf(path, PATH_MAX, MSG_ORIG(MSG_STR_PATH),
2200 			    mapfile, denp->d_name);
2201 			if (ld_map_parse(path, ofl) == S_ERROR)
2202 				return (S_ERROR);
2203 		}
2204 		(void) closedir(dirp);
2205 		return (1);
2206 	} else if (!S_ISREG(stat_buf.st_mode)) {
2207 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_NOTREG),
2208 		    mapfile);
2209 		return (S_ERROR);
2210 	}
2211 
2212 	/*
2213 	 * We read the entire mapfile into memory.
2214 	 */
2215 	if ((Mapspace = libld_malloc(stat_buf.st_size + 1)) == 0)
2216 		return (S_ERROR);
2217 	if ((mapfile_fd = open(mapfile, O_RDONLY)) == -1) {
2218 		err = errno;
2219 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
2220 		    mapfile, strerror(err));
2221 		return (S_ERROR);
2222 	}
2223 
2224 	if (read(mapfile_fd, Mapspace, stat_buf.st_size) != stat_buf.st_size) {
2225 		err = errno;
2226 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_READ),
2227 		    mapfile, strerror(err));
2228 		return (S_ERROR);
2229 	}
2230 	Mapspace[stat_buf.st_size] = '\0';
2231 	nextchr = Mapspace;
2232 
2233 	/*
2234 	 * Set up any global variables, the line number counter and file name.
2235 	 */
2236 	Line_num = 1;
2237 
2238 	/*
2239 	 * We now parse the mapfile until the gettoken routine returns EOF.
2240 	 */
2241 	while ((tok = gettoken(ofl, mapfile)) != TK_EOF) {
2242 		int	ndx = -1;
2243 
2244 		/*
2245 		 * Don't know which segment yet.
2246 		 */
2247 		sgp1 = NULL;
2248 
2249 		/*
2250 		 * At this point we are at the beginning of a line, and the
2251 		 * variable `Start_tok' points to the first string on the line.
2252 		 * All mapfile entries start with some string token except it
2253 		 * is possible for a scoping definition to start with `{'.
2254 		 */
2255 		if (tok == TK_LEFTBKT) {
2256 			if (map_version(mapfile, (char *)0, ofl) == S_ERROR)
2257 				return (S_ERROR);
2258 			continue;
2259 		}
2260 		if (tok != TK_STRING) {
2261 			/* LINTED */
2262 			if (tok != (Token)S_ERROR)
2263 				eprintf(ofl->ofl_lml, ERR_FATAL,
2264 				    MSG_INTL(MSG_MAP_EXPSEGNAM), mapfile,
2265 				    EC_XWORD(Line_num));
2266 			return (S_ERROR);
2267 		}
2268 
2269 		/*
2270 		 * Save the initial token.
2271 		 */
2272 		if ((name = libld_malloc(strlen(Start_tok) + 1)) == 0)
2273 			return (S_ERROR);
2274 		(void) strcpy(name, Start_tok);
2275 
2276 		/*
2277 		 * Now check the second character on the line.  The special `-'
2278 		 * and `{' characters do not involve any segment manipulation so
2279 		 * we handle them first.
2280 		 */
2281 		if ((tok = gettoken(ofl, mapfile)) == TK_DASH) {
2282 			if (map_dash(mapfile, name, ofl) == S_ERROR)
2283 				return (S_ERROR);
2284 			continue;
2285 		}
2286 		if (tok == TK_LEFTBKT) {
2287 			if (map_version(mapfile, name, ofl) == S_ERROR)
2288 				return (S_ERROR);
2289 			continue;
2290 		}
2291 
2292 		/*
2293 		 * If we're here we need to interpret the first string as a
2294 		 * segment name.  Find the segment named in the token.
2295 		 */
2296 		for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp2)) {
2297 			ndx++;
2298 			if (strcmp(sgp2->sg_name, name) == 0) {
2299 				sgp1 = sgp2;
2300 				sgp2->sg_flags &= ~FLG_SG_DISABLED;
2301 				new_segment = FALSE;
2302 				break;
2303 			}
2304 		}
2305 
2306 		/*
2307 		 * If the second token is a '|' then we had better
2308 		 * of found a segment.  It is illegal to perform
2309 		 * section within segment ordering before the segment
2310 		 * has been declared.
2311 		 */
2312 		if (tok == TK_PIPE) {
2313 			if (sgp1 == NULL) {
2314 				eprintf(ofl->ofl_lml, ERR_FATAL,
2315 				    MSG_INTL(MSG_MAP_SECINSEG), mapfile,
2316 				    EC_XWORD(Line_num), name);
2317 				return (S_ERROR);
2318 			} else {
2319 				if (map_pipe(ofl, mapfile, sgp1) == S_ERROR)
2320 					return (S_ERROR);
2321 				continue;
2322 			}
2323 		}
2324 
2325 		/*
2326 		 * If segment is still NULL then it does not exist.  Create a
2327 		 * new segment, and leave its values as 0 so that map_equal()
2328 		 * can detect changing attributes.
2329 		 */
2330 		if (sgp1 == NULL) {
2331 			if ((sgp1 = libld_calloc(sizeof (Sg_desc),
2332 			    1)) == 0)
2333 				return (S_ERROR);
2334 			sgp1->sg_phdr.p_type = PT_NULL;
2335 			sgp1->sg_name = name;
2336 			new_segment = TRUE;
2337 			ndx = -1;
2338 		}
2339 
2340 		if ((strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_INTERP)) == 0) ||
2341 		    (strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_LD_DYNAMIC)) ==
2342 		    0)) {
2343 			eprintf(ofl->ofl_lml, ERR_FATAL,
2344 			    MSG_INTL(MSG_MAP_SEGRESV), mapfile,
2345 			    EC_XWORD(Line_num));
2346 			return (S_ERROR);
2347 		}
2348 
2349 		/*
2350 		 * Now check the second token from the input line.
2351 		 */
2352 		if (tok == TK_EQUAL) {
2353 			if (strcmp(sgp1->sg_name,
2354 			    MSG_ORIG(MSG_STR_HWCAP_1)) == 0) {
2355 				if (map_cap(mapfile, CA_SUNW_HW_1,
2356 				    ofl) == S_ERROR)
2357 					return (S_ERROR);
2358 				DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml,
2359 				    CA_SUNW_HW_1, ofl->ofl_hwcap_1, M_MACH));
2360 				continue;
2361 
2362 			} else if (strcmp(sgp1->sg_name,
2363 			    MSG_ORIG(MSG_STR_SFCAP_1)) == 0) {
2364 				if (map_cap(mapfile, CA_SUNW_SF_1,
2365 				    ofl) == S_ERROR)
2366 					return (S_ERROR);
2367 				DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml,
2368 				    CA_SUNW_SF_1, ofl->ofl_sfcap_1, M_MACH));
2369 				continue;
2370 
2371 			} else {
2372 				if (map_equal(mapfile, sgp1, ofl) == S_ERROR)
2373 					return (S_ERROR);
2374 				ofl->ofl_flags |= FLG_OF_SEGSORT;
2375 				DBG_CALL(Dbg_map_set_equal(new_segment));
2376 			}
2377 		} else if (tok == TK_COLON) {
2378 			/*
2379 			 * If this is an existing segment reservation, sections
2380 			 * can't be assigned to it.
2381 			 */
2382 			if ((new_segment == FALSE) &&
2383 			    (sgp1->sg_flags & FLG_SG_EMPTY)) {
2384 				eprintf(ofl->ofl_lml, ERR_FATAL,
2385 				    MSG_INTL(MSG_MAP_SEGEMPSEC), mapfile,
2386 				    EC_XWORD(Line_num));
2387 				return (S_ERROR);
2388 			}
2389 
2390 			/*
2391 			 * We are looking at a new entrance criteria line.
2392 			 * Note that entrance criteria are added in the order
2393 			 * they are found in the map file, but are placed
2394 			 * before any default criteria.
2395 			 */
2396 			if ((enp = libld_calloc(sizeof (Ent_desc), 1)) == 0)
2397 				return (S_ERROR);
2398 			enp->ec_segment = sgp1;
2399 			if (e_next == NULL) {
2400 				if ((e_next = list_prependc(&ofl->ofl_ents,
2401 				    enp)) == 0)
2402 					return (S_ERROR);
2403 			} else {
2404 				if ((e_next = list_insertc(&ofl->ofl_ents,
2405 				    enp, e_next)) == 0)
2406 					return (S_ERROR);
2407 			}
2408 
2409 			if (map_colon(ofl, mapfile, enp) == S_ERROR)
2410 				return (S_ERROR);
2411 			ofl->ofl_flags |= FLG_OF_SEGSORT;
2412 			DBG_CALL(Dbg_map_ent(ofl->ofl_lml, new_segment,
2413 			    enp, ofl));
2414 		} else if (tok == TK_ATSIGN) {
2415 			if (map_atsign(mapfile, sgp1, ofl) == S_ERROR)
2416 				return (S_ERROR);
2417 			DBG_CALL(Dbg_map_set_atsign(new_segment));
2418 		} else {
2419 			/* LINTED */
2420 			if (tok != (Token)S_ERROR) {
2421 				eprintf(ofl->ofl_lml, ERR_FATAL,
2422 				    MSG_INTL(MSG_MAP_EXPEQU), mapfile,
2423 				    EC_XWORD(Line_num));
2424 				return (S_ERROR);
2425 			}
2426 		}
2427 
2428 		/*
2429 		 * Having completed parsing an entry in the map file determine
2430 		 * if the segment to which it applies is new.
2431 		 */
2432 		if (new_segment) {
2433 			int	src_type, dst_type;
2434 
2435 			/*
2436 			 * If specific fields have not been supplied via
2437 			 * map_equal(), make sure defaults are supplied.
2438 			 */
2439 			if (((sgp1->sg_flags & FLG_SG_TYPE) == 0) &&
2440 			    (sgp1->sg_phdr.p_type == PT_NULL)) {
2441 				sgp1->sg_phdr.p_type = PT_LOAD;
2442 				sgp1->sg_flags |= FLG_SG_TYPE;
2443 			}
2444 			if ((sgp1->sg_phdr.p_type == PT_LOAD) &&
2445 				(!(sgp1->sg_flags & FLG_SG_FLAGS))) {
2446 				sgp1->sg_phdr.p_flags = PF_R + PF_W + PF_X;
2447 				sgp1->sg_flags |= FLG_SG_FLAGS;
2448 			}
2449 
2450 			/*
2451 			 * Determine where the new segment should be inserted
2452 			 * in the seg_desc[] list.  Presently the user can
2453 			 * only add a LOAD or NOTE segment.  Note that these
2454 			 * segments must be added after any PT_PHDR and
2455 			 * PT_INTERP (refer Generic ABI, Page 5-4).
2456 			 */
2457 			switch (sgp1->sg_phdr.p_type) {
2458 			case PT_LOAD:
2459 			case PT_NULL:
2460 				if (sgp1->sg_flags & FLG_SG_EMPTY)
2461 					src_type = 4;
2462 				else
2463 					src_type = 3;
2464 				break;
2465 			case PT_SUNWSTACK:
2466 				src_type = 8;
2467 				if (++num_stack >= 2) {
2468 					/*
2469 					 * Currently the number of sunw_stack
2470 					 * segment is limited to 1.
2471 					 */
2472 					eprintf(ofl->ofl_lml, ERR_WARNING,
2473 					    MSG_INTL(MSG_MAP_NOSTACK2),
2474 					    mapfile, EC_XWORD(Line_num));
2475 					continue;
2476 				}
2477 				break;
2478 			case PT_NOTE:
2479 				src_type = 9;
2480 				break;
2481 			default:
2482 				eprintf(ofl->ofl_lml, ERR_FATAL,
2483 				    MSG_INTL(MSG_MAP_UNKSEGTYP), mapfile,
2484 				    EC_XWORD(Line_num),
2485 				    EC_WORD(sgp1->sg_phdr.p_type));
2486 				return (S_ERROR);
2487 			}
2488 			lnp2 = NULL;
2489 			for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp2)) {
2490 				ndx++;
2491 				switch (sgp2->sg_phdr.p_type) {
2492 				case PT_PHDR:
2493 					dst_type = 0;
2494 					break;
2495 				case PT_INTERP:
2496 					dst_type = 1;
2497 					break;
2498 				case PT_SUNWCAP:
2499 					dst_type = 2;
2500 					break;
2501 				case PT_LOAD:
2502 					dst_type = 3;
2503 					break;
2504 				case PT_DYNAMIC:
2505 					dst_type = 5;
2506 					break;
2507 				case PT_SUNWDTRACE:
2508 					dst_type = 6;
2509 					break;
2510 				case PT_SHLIB:
2511 					dst_type = 7;
2512 					break;
2513 				case PT_SUNWSTACK:
2514 					dst_type = 8;
2515 					break;
2516 				case PT_NOTE:
2517 					dst_type = 9;
2518 					break;
2519 				case PT_SUNWBSS:
2520 					dst_type = 10;
2521 					break;
2522 				case PT_TLS:
2523 					dst_type = 11;
2524 					break;
2525 				case PT_NULL:
2526 					dst_type = 12;
2527 					break;
2528 				default:
2529 					eprintf(ofl->ofl_lml, ERR_FATAL,
2530 					    MSG_INTL(MSG_MAP_UNKSEGTYP),
2531 					    mapfile, EC_XWORD(Line_num),
2532 					    EC_WORD(sgp2->sg_phdr.p_type));
2533 					return (S_ERROR);
2534 				}
2535 				if (src_type <= dst_type) {
2536 					if (lnp2 == NULL) {
2537 						if (list_prependc(
2538 						    &ofl->ofl_segs, sgp1) == 0)
2539 							return (S_ERROR);
2540 					} else {
2541 						if (list_insertc(&ofl->ofl_segs,
2542 						    sgp1, lnp2) == 0)
2543 							return (S_ERROR);
2544 					}
2545 					break;
2546 				}
2547 				lnp2 = lnp1;
2548 			}
2549 		}
2550 		DBG_CALL(Dbg_map_seg(ofl, ndx, sgp1));
2551 	}
2552 
2553 	/*
2554 	 * If the output file is a static file without an interpreter, and
2555 	 * if any virtual address is specified, then set the ?N flag for
2556 	 * backward compatiblity.
2557 	 */
2558 	if (!(ofl->ofl_flags & FLG_OF_DYNAMIC) &&
2559 	    !(ofl->ofl_flags & FLG_OF_RELOBJ) &&
2560 	    !(ofl->ofl_osinterp) &&
2561 	    (ofl->ofl_flags1 & FLG_OF1_VADDR))
2562 		ofl->ofl_dtflags_1 |= DF_1_NOHDR;
2563 
2564 	/*
2565 	 * If the output file is a relocatable file, then ?N has no effect.
2566 	 * Make sure this flag isn't set.
2567 	 */
2568 	if (ofl->ofl_flags & FLG_OF_RELOBJ)
2569 		ofl->ofl_dtflags_1 &= ~DF_1_NOHDR;
2570 
2571 	return (1);
2572 }
2573