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