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