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