map.c revision 1682:79d68fa5aedd
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 2006 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 list
1292 * 	version name {
1293 *		local:
1294 *		hidden:
1295 *		    symbol { =	(FUNC | OBJECT)
1296 *				(PARENT | EXTERN)
1297 *				($ABS | $COMMON) A V
1298 *			   };
1299 *			*;
1300 *		global:
1301 *		default:
1302 *		symbolic:
1303 *		protected:
1304 *		    symbol { =	(FUNC | OBJECT)
1305 *				(PARENT | EXTERN)
1306 *				(DIRECT | NODIRECT)
1307 *				([FILTER | AUXILIARY] name)
1308 *				($ABS | $COMMON) A V
1309 *			   };
1310 *	} [references];
1311 */
1312#define	SYMNO		50		/* Symbol block allocation amount */
1313#define	FLG_SCOPE_LOCL	0		/* local scope flag */
1314#define	FLG_SCOPE_GLOB	1		/* global scope flag */
1315#define	FLG_SCOPE_SYMB	2		/* symbolic scope flag */
1316#define	FLG_SCOPE_ELIM	3		/* eliminate symbol from symtabs */
1317
1318static uintptr_t
1319map_version(const char *mapfile, char *name, Ofl_desc *ofl)
1320{
1321	Token		tok;
1322	Sym		*sym;
1323	int		scope = FLG_SCOPE_GLOB;
1324	Ver_desc	*vdp;
1325	Word		hash;
1326	Ifl_desc	*ifl;
1327	avl_index_t	where;
1328
1329	/*
1330	 * If we're generating segments within the image then any symbol
1331	 * reductions will be processed (ie. applied to relocations and symbol
1332	 * table entries).  Otherwise (when creating a relocatable object) any
1333	 * versioning information is simply recorded for use in a later
1334	 * (segment generating) link-edit.
1335	 */
1336	if (ofl->ofl_flags & FLG_OF_RELOBJ)
1337		ofl->ofl_flags |= FLG_OF_VERDEF;
1338
1339	/*
1340	 * If this is a new mapfile reference generate an input file descriptor
1341	 * to represent it.  Otherwise this must simply be a new version within
1342	 * the mapfile we've previously been processing, in this case continue
1343	 * to use the original input file descriptor.
1344	 */
1345	if ((ifl = map_ifl(mapfile, ofl)) == (Ifl_desc *)S_ERROR)
1346		return (S_ERROR);
1347
1348	/*
1349	 * If no version descriptors have yet been set up, initialize a base
1350	 * version to represent the output file itself.  This `base' version
1351	 * catches any internally generated symbols (_end, _etext, etc.) and
1352	 * serves to initialize the output version descriptor count.
1353	 */
1354	if (ofl->ofl_vercnt == 0) {
1355		if (ld_vers_base(ofl) == (Ver_desc *)S_ERROR)
1356			return (S_ERROR);
1357	}
1358
1359	/*
1360	 * If this definition has an associated version name then generate a
1361	 * new version descriptor and an associated version symbol index table.
1362	 */
1363	if (name) {
1364		ofl->ofl_flags |= FLG_OF_VERDEF;
1365
1366		/*
1367		 * Traverse the present version descriptor list to see if there
1368		 * is already one of the same name, otherwise create a new one.
1369		 */
1370		/* LINTED */
1371		hash = (Word)elf_hash(name);
1372		if ((vdp = ld_vers_find(name, hash, &ofl->ofl_verdesc)) == 0) {
1373			if ((vdp = ld_vers_desc(name, hash,
1374			    &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR)
1375				return (S_ERROR);
1376		}
1377
1378		/*
1379		 * Initialize any new version with an index, the file from which
1380		 * it was first referenced, and a WEAK flag (indicates that
1381		 * there are no symbols assigned to it yet).
1382		 */
1383		if (vdp->vd_ndx == 0) {
1384			/* LINTED */
1385			vdp->vd_ndx = (Half)++ofl->ofl_vercnt;
1386			vdp->vd_file = ifl;
1387			vdp->vd_flags = VER_FLG_WEAK;
1388		}
1389	} else {
1390		/*
1391		 * If a version definition hasn't been specified assign any
1392		 * symbols to the base version.
1393		 */
1394		vdp = (Ver_desc *)ofl->ofl_verdesc.head->data;
1395	}
1396
1397	/*
1398	 * Scan the mapfile entry picking out scoping and symbol definitions.
1399	 */
1400	while ((tok = gettoken(ofl, mapfile)) != TK_RIGHTBKT) {
1401		Sym_desc * 	sdp;
1402		Word		shndx = SHN_UNDEF;
1403		uchar_t 	type = STT_NOTYPE;
1404		Addr		value = 0, size = 0;
1405		char		*_name, *filtee = 0;
1406		Word		sym_flags = 0;
1407		Half		sym_flags1 = 0;
1408		uint_t		filter = 0, dftflag;
1409
1410		if ((tok != TK_STRING) && (tok != TK_COLON)) {
1411			eprintf(ofl->ofl_lml, ERR_FATAL,
1412			    MSG_INTL(MSG_MAP_EXPSYM_2), mapfile,
1413			    EC_XWORD(Line_num));
1414			return (S_ERROR);
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		    /* LINTED */
1423		    (tok = gettoken(ofl, mapfile)) == (Token)S_ERROR)
1424			return (S_ERROR);
1425
1426		/*
1427		 * Turn off the WEAK flag to indicate that definitions are
1428		 * associated with this version.  It would probably be more
1429		 * accurate to only remove this flag with the specification of
1430		 * global symbols, however setting it here allows enough slop
1431		 * to compensate for the various user inputs we've seen so far.
1432		 * Only if a closed version is specified (i.e., "SUNW_1.x {};")
1433		 * will a user get a weak version (which is how we document the
1434		 * creation of weak versions).
1435		 */
1436		vdp->vd_flags &= ~VER_FLG_WEAK;
1437
1438		switch (tok) {
1439		case TK_COLON:
1440			/*
1441			 * Establish a new scope.  All symbols added by this
1442			 * mapfile are actually global entries. They will be
1443			 * reduced to locals during sym_update().
1444			 */
1445			if ((strcmp(MSG_ORIG(MSG_STR_LOCAL),
1446			    _name) == 0) ||
1447			    (strcmp(MSG_ORIG(MSG_MAP_HIDDEN), _name) == 0))
1448				scope = FLG_SCOPE_LOCL;
1449			else if ((strcmp(MSG_ORIG(MSG_MAP_GLOBAL),
1450			    _name) == 0) ||
1451			    (strcmp(MSG_ORIG(MSG_MAP_DEFAULT), _name) == 0))
1452				scope = FLG_SCOPE_GLOB;
1453			else if ((strcmp(MSG_ORIG(MSG_STR_SYMBOLIC),
1454			    _name) == 0) ||
1455			    (strcmp(MSG_ORIG(MSG_MAP_PROTECTED), _name) == 0))
1456				scope = FLG_SCOPE_SYMB;
1457			else if (strcmp(MSG_ORIG(MSG_STR_ELIMINATE), _name)
1458			    == 0)
1459				scope = FLG_SCOPE_ELIM;
1460			else {
1461				eprintf(ofl->ofl_lml, ERR_FATAL,
1462				    MSG_INTL(MSG_MAP_UNKSYMSCO), mapfile,
1463				    EC_XWORD(Line_num), _name);
1464				return (S_ERROR);
1465			}
1466			continue;
1467
1468		case TK_EQUAL:
1469			/*
1470			 * A full blown symbol definition follows.
1471			 * Determine the symbol type and any virtual address or
1472			 * alignment specified and then fall through to process
1473			 * the entire symbols information.
1474			 */
1475			while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
1476				/*
1477				 * If we had previously seen a filter or
1478				 * auxiliary filter requirement, the next string
1479				 * is the filtee itself.
1480				 */
1481				if (filter) {
1482					if (filtee) {
1483					    eprintf(ofl->ofl_lml, ERR_FATAL,
1484						MSG_INTL(MSG_MAP_MULTFILTEE),
1485						mapfile, EC_XWORD(Line_num),
1486						_name);
1487					    return (S_ERROR);
1488					}
1489					if ((filtee = libld_malloc(
1490					    strlen(Start_tok) + 1)) == 0)
1491						return (S_ERROR);
1492					(void) strcpy(filtee, Start_tok);
1493					filter = 0;
1494					continue;
1495				}
1496
1497				/*
1498				 * Determine any Value or Size attributes.
1499				 */
1500				lowercase(Start_tok);
1501				if (Start_tok[0] == 'v' ||
1502				    Start_tok[0] == 's') {
1503					char		*end_tok;
1504					Lword		number;
1505
1506					if ((number = (Lword)STRTOADDR(
1507					    &Start_tok[1], &end_tok, 0)) ==
1508					    XWORD_MAX) {
1509						eprintf(ofl->ofl_lml, ERR_FATAL,
1510						    MSG_INTL(MSG_MAP_SEGADDR),
1511						    mapfile, EC_XWORD(Line_num),
1512						    Start_tok,
1513						    MSG_INTL(MSG_MAP_EXCLIMIT));
1514						return (S_ERROR);
1515					}
1516
1517					if (end_tok !=
1518					    strchr(Start_tok, '\0')) {
1519						eprintf(ofl->ofl_lml, ERR_FATAL,
1520						    MSG_INTL(MSG_MAP_SEGADDR),
1521						    mapfile, EC_XWORD(Line_num),
1522						    Start_tok,
1523						    MSG_INTL(MSG_MAP_NOBADFRM));
1524						return (S_ERROR);
1525					}
1526
1527					switch (*Start_tok) {
1528					case 'v':
1529					    if (value) {
1530						eprintf(ofl->ofl_lml, ERR_FATAL,
1531						    MSG_INTL(MSG_MAP_MOREONCE),
1532						    mapfile, EC_XWORD(Line_num),
1533						    MSG_INTL(MSG_MAP_SYMVAL));
1534						return (S_ERROR);
1535					    }
1536					    /* LINTED */
1537					    value = (Addr)number;
1538					    break;
1539					case 's':
1540					    if (size) {
1541						eprintf(ofl->ofl_lml, ERR_FATAL,
1542						    MSG_INTL(MSG_MAP_MOREONCE),
1543						    mapfile, EC_XWORD(Line_num),
1544						    MSG_INTL(MSG_MAP_SYMSIZE));
1545						return (S_ERROR);
1546					    }
1547					    /* LINTED */
1548					    size = (Addr)number;
1549					    break;
1550					}
1551
1552				} else if (strcmp(Start_tok,
1553				    MSG_ORIG(MSG_MAP_FUNCTION)) == 0) {
1554					shndx = SHN_ABS;
1555					sym_flags |= FLG_SY_SPECSEC;
1556					type = STT_FUNC;
1557				} else if (strcmp(Start_tok,
1558				    MSG_ORIG(MSG_MAP_DATA)) == 0) {
1559					shndx = SHN_ABS;
1560					sym_flags |= FLG_SY_SPECSEC;
1561					type = STT_OBJECT;
1562				} else if (strcmp(Start_tok,
1563				    MSG_ORIG(MSG_MAP_COMMON)) == 0) {
1564					shndx = SHN_COMMON;
1565					sym_flags |= FLG_SY_SPECSEC;
1566					type = STT_OBJECT;
1567				} else if (strcmp(Start_tok,
1568				    MSG_ORIG(MSG_MAP_PARENT)) == 0) {
1569					sym_flags |= FLG_SY_PARENT;
1570					ofl->ofl_flags |= FLG_OF_SYMINFO;
1571				} else if (strcmp(Start_tok,
1572				    MSG_ORIG(MSG_MAP_EXTERN)) == 0) {
1573					sym_flags |= FLG_SY_EXTERN;
1574					ofl->ofl_flags |= FLG_OF_SYMINFO;
1575				} else if (strcmp(Start_tok,
1576				    MSG_ORIG(MSG_MAP_DIRECT)) == 0) {
1577					sym_flags1 |= FLG_SY1_DIR;
1578					ofl->ofl_flags |= FLG_OF_SYMINFO;
1579				} else if (strcmp(Start_tok,
1580				    MSG_ORIG(MSG_MAP_NODIRECT)) == 0) {
1581					sym_flags1 |= FLG_SY1_NDIR;
1582					ofl->ofl_flags |= FLG_OF_SYMINFO;
1583					ofl->ofl_flags1 |= FLG_OF1_NDIRECT;
1584					ofl->ofl_dtflags_1 |= DF_1_NODIRECT;
1585				} else if (strcmp(Start_tok,
1586				    MSG_ORIG(MSG_MAP_FILTER)) == 0) {
1587					dftflag = filter = FLG_SY_STDFLTR;
1588					sym_flags |= FLG_SY_STDFLTR;
1589					ofl->ofl_flags |= FLG_OF_SYMINFO;
1590					continue;
1591				} else if (strcmp(Start_tok,
1592				    MSG_ORIG(MSG_MAP_AUXILIARY)) == 0) {
1593					dftflag = filter = FLG_SY_AUXFLTR;
1594					sym_flags |= FLG_SY_AUXFLTR;
1595					ofl->ofl_flags |= FLG_OF_SYMINFO;
1596					continue;
1597				} else {
1598					eprintf(ofl->ofl_lml, ERR_FATAL,
1599					    MSG_INTL(MSG_MAP_UNKSYMDEF),
1600					    mapfile, EC_XWORD(Line_num),
1601					    Start_tok);
1602					return (S_ERROR);
1603				}
1604			}
1605			/* FALLTHROUGH */
1606
1607		case TK_SEMICOLON:
1608			/*
1609			 * The special auto-reduction directive `*' can be
1610			 * specified in local scope and indicates that all
1611			 * symbols processed that are not explicitly defined to
1612			 * be global are to be reduced to local scope in the
1613			 * output image.  This also applies that a version
1614			 * definition is created as the user has effectively
1615			 * defined an interface.
1616			 */
1617			if (*_name == '*') {
1618				if (scope == FLG_SCOPE_LOCL)
1619					ofl->ofl_flags |=
1620					    (FLG_OF_AUTOLCL | FLG_OF_VERDEF);
1621				else if (scope == FLG_SCOPE_ELIM) {
1622					ofl->ofl_flags |= FLG_OF_VERDEF;
1623					ofl->ofl_flags1 |= FLG_OF1_AUTOELM;
1624				}
1625				continue;
1626			}
1627
1628			/*
1629			 * Add the new symbol.  It should be noted that all
1630			 * symbols added by the mapfile start out with global
1631			 * scope, thus they will fall through the normal symbol
1632			 * resolution process.  Symbols defined as locals will
1633			 * be reduced in scope after all input file processing.
1634			 */
1635			/* LINTED */
1636			hash = (Word)elf_hash(_name);
1637			DBG_CALL(Dbg_map_version(ofl->ofl_lml, name, _name,
1638			    scope));
1639			if ((sdp = ld_sym_find(_name, hash, &where,
1640			    ofl)) == NULL) {
1641				if ((sym = libld_calloc(sizeof (Sym), 1)) == 0)
1642					return (S_ERROR);
1643
1644				/*
1645				 * Make sure any parent or external declarations
1646				 * fall back to references.
1647				 */
1648				if (sym_flags & (FLG_SY_PARENT | FLG_SY_EXTERN))
1649					sym->st_shndx = shndx = SHN_UNDEF;
1650				else
1651					sym->st_shndx = (Half)shndx;
1652
1653				sym->st_value = value;
1654				sym->st_size = size;
1655				sym->st_info = ELF_ST_INFO(STB_GLOBAL, type);
1656
1657				if ((sdp = ld_sym_enter(_name, sym, hash, ifl,
1658				    ofl, 0, shndx, sym_flags, sym_flags1,
1659				    &where)) == (Sym_desc *)S_ERROR)
1660					return (S_ERROR);
1661
1662				sdp->sd_flags &= ~FLG_SY_CLEAN;
1663
1664				/*
1665				 * Identify any references.  FLG_SY_MAPREF is
1666				 * turned off once a relocatable object with
1667				 * the same symbol is found, thus the existance
1668				 * of FLG_SY_MAPREF at symbol validation is
1669				 * used to flag undefined/mispelt entries.
1670				 */
1671				if (sym->st_shndx == SHN_UNDEF)
1672					sdp->sd_flags |=
1673					    (FLG_SY_MAPREF | FLG_SY_GLOBREF);
1674
1675			} else {
1676				int	conflict = 0;
1677
1678				sym = sdp->sd_sym;
1679
1680				/*
1681				 * If this symbol already exists, make sure this
1682				 * definition doesn't conflict with the former.
1683				 * Provided it doesn't, multiple definitions can
1684				 * augment each other.
1685				 */
1686				if (sym->st_value) {
1687					if (value && (sym->st_value != value))
1688						conflict = 1;
1689				} else
1690					sym->st_value = value;
1691
1692				if (sym->st_size) {
1693					if (size && (sym->st_size != size))
1694						conflict = 2;
1695				} else
1696					sym->st_size = size;
1697
1698				if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) {
1699					if ((type != STT_NOTYPE) &&
1700					    (ELF_ST_TYPE(sym->st_info) != type))
1701						conflict = 3;
1702				} else
1703					sym->st_info =
1704					    ELF_ST_INFO(STB_GLOBAL, type);
1705
1706				if (sym->st_shndx != SHN_UNDEF) {
1707					if ((shndx != SHN_UNDEF) &&
1708					    (sym->st_shndx != shndx))
1709						conflict = 4;
1710				} else
1711					sdp->sd_shndx = sym->st_shndx = shndx;
1712
1713				if ((sdp->sd_flags1 & FLG_SY1_LOCL) &&
1714				    ((scope != FLG_SCOPE_LOCL) &&
1715				    (scope != FLG_SCOPE_ELIM)))
1716					conflict = 5;
1717				if ((sdp->sd_flags1 & FLG_SY1_GLOB) &&
1718				    (scope != FLG_SCOPE_GLOB) &&
1719				    (scope != FLG_SCOPE_SYMB))
1720					conflict = 6;
1721				if ((sdp->sd_flags1 & FLG_SY1_GLOB) &&
1722				    (sdp->sd_aux->sa_overndx !=
1723				    VER_NDX_GLOBAL) &&
1724				    (vdp->vd_ndx != VER_NDX_GLOBAL) &&
1725				    (sdp->sd_aux->sa_overndx != vdp->vd_ndx))
1726					conflict = 7;
1727
1728				if (conflict) {
1729					eprintf(ofl->ofl_lml, ERR_FATAL,
1730					    MSG_INTL(MSG_MAP_SYMDEF), mapfile,
1731					    EC_XWORD(Line_num), demangle(_name),
1732					    sdp->sd_file->ifl_name);
1733					return (S_ERROR);
1734				}
1735
1736				/*
1737				 * If this mapfile entry supplies a definition,
1738				 * indicate that the symbol is now used.
1739				 */
1740				if (shndx != SHN_UNDEF)
1741					sdp->sd_flags |= FLG_SY_MAPUSED;
1742			}
1743
1744			/*
1745			 * Indicate the new symbols scope.
1746			 */
1747			if (scope == FLG_SCOPE_LOCL) {
1748				sdp->sd_flags1 |= FLG_SY1_LOCL;
1749				sdp->sd_sym->st_other = STV_HIDDEN;
1750				if (ofl->ofl_flags1 & FLG_OF1_REDLSYM)
1751					sdp->sd_flags1 |= FLG_SY1_ELIM;
1752
1753			} else if (scope == FLG_SCOPE_ELIM) {
1754				sdp->sd_flags1 |= (FLG_SY1_LOCL | FLG_SY1_ELIM);
1755				sdp->sd_sym->st_other = STV_HIDDEN;
1756			} else {
1757				sdp->sd_flags |= sym_flags;
1758				sdp->sd_flags1 |= (sym_flags1 | FLG_SY1_GLOB);
1759
1760				if (scope == FLG_SCOPE_SYMB) {
1761					sdp->sd_flags1 |= FLG_SY1_PROT;
1762					sdp->sd_sym->st_other = STV_PROTECTED;
1763				}
1764
1765				/*
1766				 * Record the present version index for later
1767				 * potential versioning.
1768				 */
1769				if ((sdp->sd_aux->sa_overndx == 0) ||
1770				    (sdp->sd_aux->sa_overndx == VER_NDX_GLOBAL))
1771					sdp->sd_aux->sa_overndx = vdp->vd_ndx;
1772				vdp->vd_flags |= FLG_VER_REFER;
1773			}
1774
1775			/*
1776			 * If we've encountered a symbol definition simulate
1777			 * that an input file has been processed - this allows
1778			 * things like filters to be created purely from a
1779			 * mapfile.
1780			 */
1781			if (type != STT_NOTYPE)
1782				ofl->ofl_objscnt++;
1783			DBG_CALL(Dbg_map_symbol(ofl, sdp));
1784
1785			/*
1786			 * If this symbol has an associated filtee, record the
1787			 * filtee string and associate the string index with the
1788			 * symbol.  This is used later to associate the syminfo
1789			 * information with the necessary .dynamic entry.
1790			 */
1791			if (filter && (filtee == 0)) {
1792				eprintf(ofl->ofl_lml, ERR_FATAL,
1793				    MSG_INTL(MSG_MAP_NOFILTER), mapfile,
1794				    EC_XWORD(Line_num), _name);
1795				return (S_ERROR);
1796			}
1797
1798			if (filtee) {
1799				Dfltr_desc *	dftp;
1800				Sfltr_desc	sft;
1801				Aliste		off = 0, _off;
1802
1803				/*
1804				 * Make sure we don't duplicate any filtee
1805				 * strings, and create a new descriptor if
1806				 * necessary.
1807				 */
1808				for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, _off,
1809				    dftp)) {
1810					if ((dftflag != dftp->dft_flag) ||
1811					    (strcmp(dftp->dft_str, filtee)))
1812						continue;
1813					off = _off;
1814					break;
1815				}
1816				if (off == 0) {
1817					Dfltr_desc	dft;
1818
1819					dft.dft_str = filtee;
1820					dft.dft_flag = dftflag;
1821					dft.dft_ndx = 0;
1822
1823					if ((dftp =
1824					    alist_append(&(ofl->ofl_dtsfltrs),
1825					    &dft, sizeof (Dfltr_desc),
1826					    AL_CNT_DFLTR)) == 0)
1827						return (S_ERROR);
1828
1829					off = (Aliste)((char *)dftp -
1830					    (char *)ofl->ofl_dtsfltrs);
1831				}
1832
1833				/*
1834				 * Create a new filter descriptor for this
1835				 * symbol.
1836				 */
1837				sft.sft_sdp = sdp;
1838				sft.sft_off = off;
1839
1840				if (alist_append(&(ofl->ofl_symfltrs),
1841				    &sft, sizeof (Sfltr_desc),
1842				    AL_CNT_SFLTR) == 0)
1843					return (S_ERROR);
1844			}
1845			break;
1846
1847		default:
1848			eprintf(ofl->ofl_lml, ERR_FATAL,
1849			    MSG_INTL(MSG_MAP_EXPSCOL), mapfile,
1850			    EC_XWORD(Line_num));
1851			return (S_ERROR);
1852		}
1853	}
1854
1855	/*
1856	 * Determine if any version references are provided after the close
1857	 * bracket.
1858	 */
1859	while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) {
1860		Ver_desc	*_vdp;
1861		char		*_name;
1862
1863		if (tok != TK_STRING) {
1864			/* LINTED */
1865			if (tok != (Token)S_ERROR)
1866				eprintf(ofl->ofl_lml, ERR_FATAL,
1867				    MSG_INTL(MSG_MAP_EXPVERS), mapfile,
1868				    EC_XWORD(Line_num));
1869			return (S_ERROR);
1870		}
1871
1872		name = Start_tok;
1873		if (vdp->vd_ndx == VER_NDX_GLOBAL) {
1874			eprintf(ofl->ofl_lml, ERR_WARNING,
1875			    MSG_INTL(MSG_MAP_UNEXDEP), mapfile,
1876			    EC_XWORD(Line_num), name);
1877			continue;
1878		}
1879
1880		/*
1881		 * Generate a new version descriptor if it doesn't already
1882		 * exist.
1883		 */
1884		/* LINTED */
1885		hash = (Word)elf_hash(name);
1886		if ((_vdp = ld_vers_find(name, hash, &ofl->ofl_verdesc)) == 0) {
1887			if ((_name = libld_malloc(strlen(name) + 1)) == 0)
1888				return (S_ERROR);
1889			(void) strcpy(_name, name);
1890
1891			if ((_vdp = ld_vers_desc(_name, hash,
1892			    &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR)
1893				return (S_ERROR);
1894		}
1895
1896		/*
1897		 * Add the new version descriptor to the parent version
1898		 * descriptors reference list.  Indicate the version descriptors
1899		 * first reference (used for error disgnostics if undefined
1900		 * version dependencies remain).
1901		 */
1902		if (ld_vers_find(name, hash, &vdp->vd_deps) == 0)
1903			if (list_appendc(&vdp->vd_deps, _vdp) == 0)
1904				return (S_ERROR);
1905
1906		if (_vdp->vd_ref == 0)
1907			_vdp->vd_ref = vdp;
1908	}
1909	return (1);
1910}
1911
1912/*
1913 * Sort the segment list by increasing virtual address.
1914 */
1915uintptr_t
1916ld_sort_seg_list(Ofl_desc *ofl)
1917{
1918	List 		seg1, seg2;
1919	Listnode	*lnp1, *lnp2, *lnp3;
1920	Sg_desc		*sgp1, *sgp2;
1921
1922	seg1.head = seg1.tail = seg2.head = seg2.tail = NULL;
1923
1924	/*
1925	 * Add the .phdr and .interp segments to our list. These segments must
1926	 * occur before any PT_LOAD segments (refer exec/elf/elf.c).
1927	 */
1928	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
1929		Word	type = sgp1->sg_phdr.p_type;
1930
1931		if ((type == PT_PHDR) || (type == PT_INTERP))
1932			if (list_appendc(&seg1, sgp1) == 0)
1933				return (S_ERROR);
1934	}
1935
1936	/*
1937	 * Add the loadable segments to another list in sorted order.
1938	 */
1939	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
1940		DBG_CALL(Dbg_map_sort_orig(ofl->ofl_lml, sgp1));
1941		if (sgp1->sg_phdr.p_type != PT_LOAD)
1942			continue;
1943		if (!(sgp1->sg_flags & FLG_SG_VADDR) ||
1944		    (sgp1->sg_flags & FLG_SG_EMPTY)) {
1945			if (list_appendc(&seg2, sgp1) == 0)
1946				return (S_ERROR);
1947		} else {
1948			if (seg2.head == NULL) {
1949				if (list_appendc(&seg2, sgp1) == 0)
1950					return (S_ERROR);
1951				continue;
1952			}
1953			lnp3 = NULL;
1954			for (LIST_TRAVERSE(&seg2, lnp2, sgp2)) {
1955				if (!(sgp2->sg_flags & FLG_SG_VADDR) ||
1956				    (sgp2->sg_flags & FLG_SG_EMPTY)) {
1957					if (lnp3 == NULL) {
1958						if (list_prependc(&seg2,
1959						    sgp1) == 0)
1960							return (S_ERROR);
1961					} else {
1962						if (list_insertc(&seg2,
1963						    sgp1, lnp3) == 0)
1964							return (S_ERROR);
1965					}
1966					lnp3 = NULL;
1967					break;
1968				}
1969				if (sgp1->sg_phdr.p_vaddr <
1970				    sgp2->sg_phdr.p_vaddr) {
1971					if (lnp3 == NULL) {
1972						if (list_prependc(&seg2,
1973						    sgp1) == 0)
1974							return (S_ERROR);
1975					} else {
1976						if (list_insertc(&seg2,
1977						    sgp1, lnp3) == 0)
1978							return (S_ERROR);
1979					}
1980					lnp3 = NULL;
1981					break;
1982				} else if (sgp1->sg_phdr.p_vaddr >
1983				    sgp2->sg_phdr.p_vaddr) {
1984					lnp3 = lnp2;
1985				} else {
1986					eprintf(ofl->ofl_lml, ERR_FATAL,
1987					    MSG_INTL(MSG_MAP_SEGSAME),
1988					    sgp1->sg_name, sgp2->sg_name);
1989					return (S_ERROR);
1990				}
1991			}
1992			if (lnp3 != NULL)
1993				if (list_appendc(&seg2, sgp1) == 0)
1994					return (S_ERROR);
1995		}
1996	}
1997
1998	/*
1999	 * add the sorted loadable segments to our list
2000	 */
2001	for (LIST_TRAVERSE(&seg2, lnp1, sgp1)) {
2002		if (list_appendc(&seg1, sgp1) == 0)
2003			return (S_ERROR);
2004	}
2005
2006	/*
2007	 * add all other segments to our list
2008	 */
2009	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
2010		Word	type = sgp1->sg_phdr.p_type;
2011
2012		if ((type != PT_PHDR) && (type != PT_INTERP) &&
2013		    (type != PT_LOAD))
2014			if (list_appendc(&seg1, sgp1) == 0)
2015				return (S_ERROR);
2016	}
2017	ofl->ofl_segs.head = ofl->ofl_segs.tail = NULL;
2018
2019	/*
2020	 * Now rebuild the original list and process all of the
2021	 * segment/section ordering information if present.
2022	 */
2023	for (LIST_TRAVERSE(&seg1, lnp1, sgp1)) {
2024		DBG_CALL(Dbg_map_sort_fini(ofl->ofl_lml, sgp1));
2025		if (list_appendc(&ofl->ofl_segs, sgp1) == 0)
2026			return (S_ERROR);
2027	}
2028	return (1);
2029}
2030
2031
2032
2033/*
2034 * Parse the mapfile.
2035 */
2036uintptr_t
2037ld_map_parse(const char *mapfile, Ofl_desc *ofl)
2038{
2039	struct stat	stat_buf;	/* stat of mapfile */
2040	int		mapfile_fd;	/* descriptor for mapfile */
2041	Listnode	*lnp1;		/* node pointer */
2042	Listnode	*lnp2;		/* node pointer */
2043	Sg_desc		*sgp1;		/* seg descriptor being manipulated */
2044	Sg_desc		*sgp2;		/* temp segment descriptor pointer */
2045	Ent_desc	*enp;		/* Segment entrance criteria. */
2046	Token		tok;		/* current token. */
2047	Listnode	*e_next = NULL;
2048					/* next place for entrance criterion */
2049	Boolean		new_segment;	/* If true, defines new segment. */
2050	char		*name;
2051	static	int	num_stack = 0;	/* number of stack segment */
2052	int		err;
2053
2054	DBG_CALL(Dbg_map_parse(ofl->ofl_lml, mapfile));
2055
2056	/*
2057	 * Determine if we're dealing with a file or a directory.
2058	 */
2059	if (stat(mapfile, &stat_buf) == -1) {
2060		err = errno;
2061		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_STAT),
2062		    mapfile, strerror(err));
2063		return (S_ERROR);
2064	}
2065	if (S_ISDIR(stat_buf.st_mode)) {
2066		DIR		*dirp;
2067		struct dirent	*denp;
2068
2069		/*
2070		 * Open the directory and interpret each visible file as a
2071		 * mapfile.
2072		 */
2073		if ((dirp = opendir(mapfile)) == 0)
2074			return (1);
2075
2076		while ((denp = readdir(dirp)) != NULL) {
2077			char	path[PATH_MAX];
2078
2079			/*
2080			 * Ignore any hidden filenames.  Construct the full
2081			 * pathname to the new mapfile.
2082			 */
2083			if (*denp->d_name == '.')
2084				continue;
2085			(void) snprintf(path, PATH_MAX, MSG_ORIG(MSG_STR_PATH),
2086			    mapfile, denp->d_name);
2087			if (ld_map_parse(path, ofl) == S_ERROR)
2088				return (S_ERROR);
2089		}
2090		(void) closedir(dirp);
2091		return (1);
2092	} else if (!S_ISREG(stat_buf.st_mode)) {
2093		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_NOTREG),
2094		    mapfile);
2095		return (S_ERROR);
2096	}
2097
2098	/*
2099	 * We read the entire mapfile into memory.
2100	 */
2101	if ((Mapspace = libld_malloc(stat_buf.st_size + 1)) == 0)
2102		return (S_ERROR);
2103	if ((mapfile_fd = open(mapfile, O_RDONLY)) == -1) {
2104		err = errno;
2105		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
2106		    mapfile, strerror(err));
2107		return (S_ERROR);
2108	}
2109
2110	if (read(mapfile_fd, Mapspace, stat_buf.st_size) != stat_buf.st_size) {
2111		err = errno;
2112		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_READ),
2113		    mapfile, strerror(err));
2114		return (S_ERROR);
2115	}
2116	Mapspace[stat_buf.st_size] = '\0';
2117	nextchr = Mapspace;
2118
2119	/*
2120	 * Set up any global variables, the line number counter and file name.
2121	 */
2122	Line_num = 1;
2123
2124	/*
2125	 * We now parse the mapfile until the gettoken routine returns EOF.
2126	 */
2127	while ((tok = gettoken(ofl, mapfile)) != TK_EOF) {
2128		int	ndx = -1;
2129
2130		/*
2131		 * Don't know which segment yet.
2132		 */
2133		sgp1 = NULL;
2134
2135		/*
2136		 * At this point we are at the beginning of a line, and the
2137		 * variable `Start_tok' points to the first string on the line.
2138		 * All mapfile entries start with some string token except it
2139		 * is possible for a scoping definition to start with `{'.
2140		 */
2141		if (tok == TK_LEFTBKT) {
2142			if (map_version(mapfile, (char *)0, ofl) == S_ERROR)
2143				return (S_ERROR);
2144			continue;
2145		}
2146		if (tok != TK_STRING) {
2147			/* LINTED */
2148			if (tok != (Token)S_ERROR)
2149				eprintf(ofl->ofl_lml, ERR_FATAL,
2150				    MSG_INTL(MSG_MAP_EXPSEGNAM), mapfile,
2151				    EC_XWORD(Line_num));
2152			return (S_ERROR);
2153		}
2154
2155		/*
2156		 * Save the initial token.
2157		 */
2158		if ((name = libld_malloc(strlen(Start_tok) + 1)) == 0)
2159			return (S_ERROR);
2160		(void) strcpy(name, Start_tok);
2161
2162		/*
2163		 * Now check the second character on the line.  The special `-'
2164		 * and `{' characters do not involve any segment manipulation so
2165		 * we handle them first.
2166		 */
2167		if ((tok = gettoken(ofl, mapfile)) == TK_DASH) {
2168			if (map_dash(mapfile, name, ofl) == S_ERROR)
2169				return (S_ERROR);
2170			continue;
2171		}
2172		if (tok == TK_LEFTBKT) {
2173			if (map_version(mapfile, name, ofl) == S_ERROR)
2174				return (S_ERROR);
2175			continue;
2176		}
2177
2178		/*
2179		 * If we're here we need to interpret the first string as a
2180		 * segment name.  Find the segment named in the token.
2181		 */
2182		for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp2)) {
2183			ndx++;
2184			if (strcmp(sgp2->sg_name, name) == 0) {
2185				sgp1 = sgp2;
2186				sgp2->sg_flags &= ~FLG_SG_DISABLED;
2187				new_segment = FALSE;
2188				break;
2189			}
2190		}
2191
2192		/*
2193		 * If the second token is a '|' then we had better
2194		 * of found a segment.  It is illegal to perform
2195		 * section within segment ordering before the segment
2196		 * has been declared.
2197		 */
2198		if (tok == TK_PIPE) {
2199			if (sgp1 == NULL) {
2200				eprintf(ofl->ofl_lml, ERR_FATAL,
2201				    MSG_INTL(MSG_MAP_SECINSEG), mapfile,
2202				    EC_XWORD(Line_num), name);
2203				return (S_ERROR);
2204			} else {
2205				if (map_pipe(ofl, mapfile, sgp1) == S_ERROR)
2206					return (S_ERROR);
2207				continue;
2208			}
2209		}
2210
2211		/*
2212		 * If segment is still NULL then it does not exist.  Create a
2213		 * new segment, and leave its values as 0 so that map_equal()
2214		 * can detect changing attributes.
2215		 */
2216		if (sgp1 == NULL) {
2217			if ((sgp1 = libld_calloc(sizeof (Sg_desc),
2218			    1)) == 0)
2219				return (S_ERROR);
2220			sgp1->sg_phdr.p_type = PT_NULL;
2221			sgp1->sg_name = name;
2222			new_segment = TRUE;
2223			ndx = -1;
2224		}
2225
2226		if ((strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_INTERP)) == 0) ||
2227		    (strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_LD_DYNAMIC)) ==
2228		    0)) {
2229			eprintf(ofl->ofl_lml, ERR_FATAL,
2230			    MSG_INTL(MSG_MAP_SEGRESV), mapfile,
2231			    EC_XWORD(Line_num));
2232			return (S_ERROR);
2233		}
2234
2235		/*
2236		 * Now check the second token from the input line.
2237		 */
2238		if (tok == TK_EQUAL) {
2239			if (strcmp(sgp1->sg_name,
2240			    MSG_ORIG(MSG_STR_HWCAP_1)) == 0) {
2241				if (map_cap(mapfile, CA_SUNW_HW_1,
2242				    ofl) == S_ERROR)
2243					return (S_ERROR);
2244				DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml,
2245				    CA_SUNW_HW_1, ofl->ofl_hwcap_1, M_MACH));
2246
2247			} else if (strcmp(sgp1->sg_name,
2248			    MSG_ORIG(MSG_STR_SFCAP_1)) == 0) {
2249				if (map_cap(mapfile, CA_SUNW_SF_1,
2250				    ofl) == S_ERROR)
2251					return (S_ERROR);
2252				DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml,
2253				    CA_SUNW_SF_1, ofl->ofl_sfcap_1, M_MACH));
2254
2255			} else {
2256				if (map_equal(mapfile, sgp1, ofl) == S_ERROR)
2257					return (S_ERROR);
2258				ofl->ofl_flags |= FLG_OF_SEGSORT;
2259				DBG_CALL(Dbg_map_set_equal(new_segment));
2260			}
2261		} else if (tok == TK_COLON) {
2262			/*
2263			 * If this is an existing segment reservation, sections
2264			 * can't be assigned to it.
2265			 */
2266			if ((new_segment == FALSE) &&
2267			    (sgp1->sg_flags & FLG_SG_EMPTY)) {
2268				eprintf(ofl->ofl_lml, ERR_FATAL,
2269				    MSG_INTL(MSG_MAP_SEGEMPSEC), mapfile,
2270				    EC_XWORD(Line_num));
2271				return (S_ERROR);
2272			}
2273
2274			/*
2275			 * We are looking at a new entrance criteria line.
2276			 * Note that entrance criteria are added in the order
2277			 * they are found in the map file, but are placed
2278			 * before any default criteria.
2279			 */
2280			if ((enp = libld_calloc(sizeof (Ent_desc), 1)) == 0)
2281				return (S_ERROR);
2282			enp->ec_segment = sgp1;
2283			if (e_next == NULL) {
2284				if ((e_next = list_prependc(&ofl->ofl_ents,
2285				    enp)) == 0)
2286					return (S_ERROR);
2287			} else {
2288				if ((e_next = list_insertc(&ofl->ofl_ents,
2289				    enp, e_next)) == 0)
2290					return (S_ERROR);
2291			}
2292
2293			if (map_colon(ofl, mapfile, enp) == S_ERROR)
2294				return (S_ERROR);
2295			ofl->ofl_flags |= FLG_OF_SEGSORT;
2296			DBG_CALL(Dbg_map_ent(ofl->ofl_lml, new_segment,
2297			    enp, ofl));
2298		} else if (tok == TK_ATSIGN) {
2299			if (map_atsign(mapfile, sgp1, ofl) == S_ERROR)
2300				return (S_ERROR);
2301			DBG_CALL(Dbg_map_set_atsign(new_segment));
2302		} else {
2303			/* LINTED */
2304			if (tok != (Token)S_ERROR) {
2305				eprintf(ofl->ofl_lml, ERR_FATAL,
2306				    MSG_INTL(MSG_MAP_EXPEQU), mapfile,
2307				    EC_XWORD(Line_num));
2308				return (S_ERROR);
2309			}
2310		}
2311
2312		/*
2313		 * Having completed parsing an entry in the map file determine
2314		 * if the segment to which it applies is new.
2315		 */
2316		if (new_segment) {
2317			int	src_type, dst_type;
2318
2319			/*
2320			 * If specific fields have not been supplied via
2321			 * map_equal(), make sure defaults are supplied.
2322			 */
2323			if (sgp1->sg_phdr.p_type == PT_NULL) {
2324				sgp1->sg_phdr.p_type = PT_LOAD;
2325				sgp1->sg_flags |= FLG_SG_TYPE;
2326			}
2327			if ((sgp1->sg_phdr.p_type == PT_LOAD) &&
2328				(!(sgp1->sg_flags & FLG_SG_FLAGS))) {
2329				sgp1->sg_phdr.p_flags = PF_R + PF_W + PF_X;
2330				sgp1->sg_flags |= FLG_SG_FLAGS;
2331			}
2332
2333			/*
2334			 * Determine where the new segment should be inserted
2335			 * in the seg_desc[] list.  Presently the user can
2336			 * only add a LOAD or NOTE segment.  Note that these
2337			 * segments must be added after any PT_PHDR and
2338			 * PT_INTERP (refer Generic ABI, Page 5-4).
2339			 */
2340			switch (sgp1->sg_phdr.p_type) {
2341			case PT_LOAD:
2342				if (sgp1->sg_flags & FLG_SG_EMPTY)
2343					src_type = 4;
2344				else
2345					src_type = 3;
2346				break;
2347			case PT_SUNWSTACK:
2348				src_type = 8;
2349				if (++num_stack >= 2) {
2350					/*
2351					 * Currently the number of sunw_stack
2352					 * segment is limited to 1.
2353					 */
2354					eprintf(ofl->ofl_lml, ERR_WARNING,
2355					    MSG_INTL(MSG_MAP_NOSTACK2),
2356					    mapfile, EC_XWORD(Line_num));
2357					continue;
2358				}
2359				break;
2360			case PT_NOTE:
2361				src_type = 9;
2362				break;
2363			default:
2364				eprintf(ofl->ofl_lml, ERR_FATAL,
2365				    MSG_INTL(MSG_MAP_UNKSEGTYP), mapfile,
2366				    EC_XWORD(Line_num),
2367				    EC_WORD(sgp1->sg_phdr.p_type));
2368				return (S_ERROR);
2369			}
2370			lnp2 = NULL;
2371			for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp2)) {
2372				ndx++;
2373				switch (sgp2->sg_phdr.p_type) {
2374				case PT_PHDR:
2375					dst_type = 0;
2376					break;
2377				case PT_INTERP:
2378					dst_type = 1;
2379					break;
2380				case PT_SUNWCAP:
2381					dst_type = 2;
2382					break;
2383				case PT_LOAD:
2384					dst_type = 3;
2385					break;
2386				case PT_DYNAMIC:
2387					dst_type = 5;
2388					break;
2389				case PT_SUNWDTRACE:
2390					dst_type = 6;
2391					break;
2392				case PT_SHLIB:
2393					dst_type = 7;
2394					break;
2395				case PT_SUNWSTACK:
2396					dst_type = 8;
2397					break;
2398				case PT_NOTE:
2399					dst_type = 9;
2400					break;
2401				case PT_SUNWBSS:
2402					dst_type = 10;
2403					break;
2404				case PT_TLS:
2405					dst_type = 11;
2406					break;
2407				case PT_NULL:
2408					dst_type = 12;
2409					break;
2410				default:
2411					eprintf(ofl->ofl_lml, ERR_FATAL,
2412					    MSG_INTL(MSG_MAP_UNKSEGTYP),
2413					    mapfile, EC_XWORD(Line_num),
2414					    EC_WORD(sgp2->sg_phdr.p_type));
2415					return (S_ERROR);
2416				}
2417				if (src_type <= dst_type) {
2418					if (lnp2 == NULL) {
2419						if (list_prependc(
2420						    &ofl->ofl_segs, sgp1) == 0)
2421							return (S_ERROR);
2422					} else {
2423						if (list_insertc(&ofl->ofl_segs,
2424						    sgp1, lnp2) == 0)
2425							return (S_ERROR);
2426					}
2427					break;
2428				}
2429				lnp2 = lnp1;
2430			}
2431		}
2432		DBG_CALL(Dbg_map_seg(ofl, ndx, sgp1));
2433	}
2434
2435	/*
2436	 * If the output file is a static file without an interpreter
2437	 * and if any virtual address is specified, then assume $n flag
2438	 * for backward compatiblity.
2439	 */
2440	if (!(ofl->ofl_flags & FLG_OF_DYNAMIC) &&
2441	    !(ofl->ofl_flags & FLG_OF_RELOBJ) &&
2442	    !(ofl->ofl_osinterp) &&
2443	    (ofl->ofl_flags1 & FLG_OF1_VADDR))
2444		ofl->ofl_flags1 |= FLG_OF1_NOHDR;
2445
2446	/*
2447	 * If the output file is a relocatable file,
2448	 * then ?N have no effect. Knock it off.
2449	 */
2450	if (ofl->ofl_flags & FLG_OF_RELOBJ)
2451		ofl->ofl_flags1 &= ~FLG_OF1_NOHDR;
2452
2453	return (1);
2454}
2455