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