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