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