map.c revision 92a0208178405fef708b0283ffcaa02fbc3468ff
080575042aba2197b425ebfd52061dea061a9aa1xy/*
080575042aba2197b425ebfd52061dea061a9aa1xy * CDDL HEADER START
080575042aba2197b425ebfd52061dea061a9aa1xy *
080575042aba2197b425ebfd52061dea061a9aa1xy * The contents of this file are subject to the terms of the
080575042aba2197b425ebfd52061dea061a9aa1xy * Common Development and Distribution License (the "License").
080575042aba2197b425ebfd52061dea061a9aa1xy * You may not use this file except in compliance with the License.
080575042aba2197b425ebfd52061dea061a9aa1xy *
080575042aba2197b425ebfd52061dea061a9aa1xy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d5c3073dbbd835e1e9b7dca0c6c770cf3cc20afachenlu chen - Sun Microsystems - Beijing China * or http://www.opensolaris.org/os/licensing.
080575042aba2197b425ebfd52061dea061a9aa1xy * See the License for the specific language governing permissions
080575042aba2197b425ebfd52061dea061a9aa1xy * and limitations under the License.
080575042aba2197b425ebfd52061dea061a9aa1xy *
080575042aba2197b425ebfd52061dea061a9aa1xy * When distributing Covered Code, include this CDDL HEADER in each
080575042aba2197b425ebfd52061dea061a9aa1xy * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
080575042aba2197b425ebfd52061dea061a9aa1xy * If applicable, add the following below this CDDL HEADER, with the
080575042aba2197b425ebfd52061dea061a9aa1xy * fields enclosed by brackets "[]" replaced with your own identifying
080575042aba2197b425ebfd52061dea061a9aa1xy * information: Portions Copyright [yyyy] [name of copyright owner]
080575042aba2197b425ebfd52061dea061a9aa1xy *
080575042aba2197b425ebfd52061dea061a9aa1xy * CDDL HEADER END
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy
d5c3073dbbd835e1e9b7dca0c6c770cf3cc20afachenlu chen - Sun Microsystems - Beijing China/*
193974072f41a843678abf5f61979c748687e66bSherry Moore * Copyright (c) 1988 AT&T
080575042aba2197b425ebfd52061dea061a9aa1xy * All Rights Reserved
080575042aba2197b425ebfd52061dea061a9aa1xy *
080575042aba2197b425ebfd52061dea061a9aa1xy * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
080575042aba2197b425ebfd52061dea061a9aa1xy * Use is subject to license terms.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy/*
080575042aba2197b425ebfd52061dea061a9aa1xy * Map file parsing.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy#include <fcntl.h>
080575042aba2197b425ebfd52061dea061a9aa1xy#include <string.h>
080575042aba2197b425ebfd52061dea061a9aa1xy#include <stdio.h>
080575042aba2197b425ebfd52061dea061a9aa1xy#include <unistd.h>
080575042aba2197b425ebfd52061dea061a9aa1xy#include <sys/stat.h>
080575042aba2197b425ebfd52061dea061a9aa1xy#include <errno.h>
080575042aba2197b425ebfd52061dea061a9aa1xy#include <limits.h>
080575042aba2197b425ebfd52061dea061a9aa1xy#include <dirent.h>
080575042aba2197b425ebfd52061dea061a9aa1xy#include <ctype.h>
080575042aba2197b425ebfd52061dea061a9aa1xy#include <elfcap.h>
080575042aba2197b425ebfd52061dea061a9aa1xy#include <debug.h>
080575042aba2197b425ebfd52061dea061a9aa1xy#include "msg.h"
080575042aba2197b425ebfd52061dea061a9aa1xy#include "_libld.h"
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy#if defined(_ELF64)
080575042aba2197b425ebfd52061dea061a9aa1xy#define STRTOADDR strtoull
080575042aba2197b425ebfd52061dea061a9aa1xy#define XWORD_MAX ULLONG_MAX
080575042aba2197b425ebfd52061dea061a9aa1xy#else /* Elf32 */
080575042aba2197b425ebfd52061dea061a9aa1xy#define STRTOADDR strtoul
080575042aba2197b425ebfd52061dea061a9aa1xy#define XWORD_MAX UINT_MAX
080575042aba2197b425ebfd52061dea061a9aa1xy#endif /* _ELF64 */
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy/* Possible return values from gettoken */
080575042aba2197b425ebfd52061dea061a9aa1xytypedef enum {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng TK_ERROR = -1, /* Error in lexical analysis */
080575042aba2197b425ebfd52061dea061a9aa1xy TK_STRING = 0,
080575042aba2197b425ebfd52061dea061a9aa1xy TK_COLON = 1,
080575042aba2197b425ebfd52061dea061a9aa1xy TK_SEMICOLON = 2,
080575042aba2197b425ebfd52061dea061a9aa1xy TK_EQUAL = 3,
47b7744cbea59975a6b583125b7ed1ff2ac45313yy TK_ATSIGN = 4,
080575042aba2197b425ebfd52061dea061a9aa1xy TK_DASH = 5,
080575042aba2197b425ebfd52061dea061a9aa1xy TK_LEFTBKT = 6,
080575042aba2197b425ebfd52061dea061a9aa1xy TK_RIGHTBKT = 7,
080575042aba2197b425ebfd52061dea061a9aa1xy TK_PIPE = 8,
080575042aba2197b425ebfd52061dea061a9aa1xy TK_EOF = 9
080575042aba2197b425ebfd52061dea061a9aa1xy} Token;
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy
c7770590c6dc06be2588a5c21427e2d823baa989mxstatic char *Mapspace; /* Malloc space holding map file. */
080575042aba2197b425ebfd52061dea061a9aa1xystatic ulong_t Line_num; /* Current map file line number. */
080575042aba2197b425ebfd52061dea061a9aa1xystatic char *Start_tok; /* First character of current token. */
9b6541b318d01d0d83bfb98699a7f09e35f37951glstatic char *nextchr; /* Next char in mapfile to examine. */
9b6541b318d01d0d83bfb98699a7f09e35f37951gl
9b6541b318d01d0d83bfb98699a7f09e35f37951gl/*
9b6541b318d01d0d83bfb98699a7f09e35f37951gl * Convert a string to lowercase.
25f2d433de915875c8393f0b0dc14aa155997ad0xy */
080575042aba2197b425ebfd52061dea061a9aa1xystatic void
d5c3073dbbd835e1e9b7dca0c6c770cf3cc20afachenlu chen - Sun Microsystems - Beijing Chinalowercase(char *str)
d5c3073dbbd835e1e9b7dca0c6c770cf3cc20afachenlu chen - Sun Microsystems - Beijing China{
d5c3073dbbd835e1e9b7dca0c6c770cf3cc20afachenlu chen - Sun Microsystems - Beijing China while (*str = tolower(*str))
d5c3073dbbd835e1e9b7dca0c6c770cf3cc20afachenlu chen - Sun Microsystems - Beijing China str++;
d5c3073dbbd835e1e9b7dca0c6c770cf3cc20afachenlu chen - Sun Microsystems - Beijing China}
d5c3073dbbd835e1e9b7dca0c6c770cf3cc20afachenlu chen - Sun Microsystems - Beijing China
d5c3073dbbd835e1e9b7dca0c6c770cf3cc20afachenlu chen - Sun Microsystems - Beijing China/*
080575042aba2197b425ebfd52061dea061a9aa1xy * Get a token from the mapfile.
080575042aba2197b425ebfd52061dea061a9aa1xy *
080575042aba2197b425ebfd52061dea061a9aa1xy * entry:
080575042aba2197b425ebfd52061dea061a9aa1xy * ofl - Output file descriptor
0c56b8d9d1c30af2e78d0a6fd8a6a70aa5310099changqing li - Sun Microsystems - Beijing China * mapfile - Name of mapfile
080575042aba2197b425ebfd52061dea061a9aa1xy * eof_ok - If False, end of file causes a premature EOF error to be
c7770590c6dc06be2588a5c21427e2d823baa989mx * issued. If True, TK_EOF is returned quietly.
43a176879122f7764767ab85eb539f89d65cdd67Miles Xu, Sun Microsystems */
43a176879122f7764767ab85eb539f89d65cdd67Miles Xu, Sun Microsystemsstatic Token
4d7379630d53d9992780329b674af8c85935e858xiangtao you - Sun Microsystems - Beijing Chinagettoken(Ofl_desc *ofl, const char *mapfile, int eof_ok)
4d7379630d53d9992780329b674af8c85935e858xiangtao you - Sun Microsystems - Beijing China{
c7770590c6dc06be2588a5c21427e2d823baa989mx static char oldchr = '\0'; /* Char at end of current token. */
4d7379630d53d9992780329b674af8c85935e858xiangtao you - Sun Microsystems - Beijing China char *end; /* End of the current token. */
4d7379630d53d9992780329b674af8c85935e858xiangtao you - Sun Microsystems - Beijing China
080575042aba2197b425ebfd52061dea061a9aa1xy /* Cycle through the characters looking for tokens. */
080575042aba2197b425ebfd52061dea061a9aa1xy for (;;) {
080575042aba2197b425ebfd52061dea061a9aa1xy if (oldchr != '\0') {
080575042aba2197b425ebfd52061dea061a9aa1xy *nextchr = oldchr;
080575042aba2197b425ebfd52061dea061a9aa1xy oldchr = '\0';
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy if (!isascii(*nextchr) ||
080575042aba2197b425ebfd52061dea061a9aa1xy (!isprint(*nextchr) && !isspace(*nextchr) &&
080575042aba2197b425ebfd52061dea061a9aa1xy (*nextchr != '\0'))) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_ILLCHAR), mapfile,
25f2d433de915875c8393f0b0dc14aa155997ad0xy EC_XWORD(Line_num), *((uchar_t *)nextchr));
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (TK_ERROR);
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy switch (*nextchr) {
25f2d433de915875c8393f0b0dc14aa155997ad0xy case '\0': /* End of file. */
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (!eof_ok)
25f2d433de915875c8393f0b0dc14aa155997ad0xy eprintf(ofl->ofl_lml, ERR_FATAL,
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_PREMEOF), mapfile,
25f2d433de915875c8393f0b0dc14aa155997ad0xy EC_XWORD(Line_num));
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (TK_EOF);
25f2d433de915875c8393f0b0dc14aa155997ad0xy
0c56b8d9d1c30af2e78d0a6fd8a6a70aa5310099changqing li - Sun Microsystems - Beijing China case ' ': /* White space. */
25f2d433de915875c8393f0b0dc14aa155997ad0xy case '\t':
25f2d433de915875c8393f0b0dc14aa155997ad0xy nextchr++;
25f2d433de915875c8393f0b0dc14aa155997ad0xy break;
25f2d433de915875c8393f0b0dc14aa155997ad0xy case '\n': /* White space too, but bump line number. */
25f2d433de915875c8393f0b0dc14aa155997ad0xy nextchr++;
25f2d433de915875c8393f0b0dc14aa155997ad0xy Line_num++;
25f2d433de915875c8393f0b0dc14aa155997ad0xy break;
25f2d433de915875c8393f0b0dc14aa155997ad0xy case '#': /* Comment. */
25f2d433de915875c8393f0b0dc14aa155997ad0xy while (*nextchr != '\n' && *nextchr != '\0')
25f2d433de915875c8393f0b0dc14aa155997ad0xy nextchr++;
25f2d433de915875c8393f0b0dc14aa155997ad0xy break;
25f2d433de915875c8393f0b0dc14aa155997ad0xy case ':':
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc nextchr++;
0c56b8d9d1c30af2e78d0a6fd8a6a70aa5310099changqing li - Sun Microsystems - Beijing China return (TK_COLON);
25f2d433de915875c8393f0b0dc14aa155997ad0xy case ';':
25f2d433de915875c8393f0b0dc14aa155997ad0xy nextchr++;
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (TK_SEMICOLON);
25f2d433de915875c8393f0b0dc14aa155997ad0xy case '=':
47b7744cbea59975a6b583125b7ed1ff2ac45313yy nextchr++;
1bc1c72171ee0c5d77203ddffb90219d991bd6e8guoqing zhu - Sun Microsystems - Beijing China return (TK_EQUAL);
1bc1c72171ee0c5d77203ddffb90219d991bd6e8guoqing zhu - Sun Microsystems - Beijing China case '@':
1bc1c72171ee0c5d77203ddffb90219d991bd6e8guoqing zhu - Sun Microsystems - Beijing China nextchr++;
1bc1c72171ee0c5d77203ddffb90219d991bd6e8guoqing zhu - Sun Microsystems - Beijing China return (TK_ATSIGN);
47b7744cbea59975a6b583125b7ed1ff2ac45313yy case '-':
47b7744cbea59975a6b583125b7ed1ff2ac45313yy nextchr++;
47b7744cbea59975a6b583125b7ed1ff2ac45313yy return (TK_DASH);
47b7744cbea59975a6b583125b7ed1ff2ac45313yy case '|':
47b7744cbea59975a6b583125b7ed1ff2ac45313yy nextchr++;
47b7744cbea59975a6b583125b7ed1ff2ac45313yy return (TK_PIPE);
47b7744cbea59975a6b583125b7ed1ff2ac45313yy case '{':
47b7744cbea59975a6b583125b7ed1ff2ac45313yy nextchr++;
47b7744cbea59975a6b583125b7ed1ff2ac45313yy return (TK_LEFTBKT);
47b7744cbea59975a6b583125b7ed1ff2ac45313yy case '}':
47b7744cbea59975a6b583125b7ed1ff2ac45313yy nextchr++;
47b7744cbea59975a6b583125b7ed1ff2ac45313yy return (TK_RIGHTBKT);
47b7744cbea59975a6b583125b7ed1ff2ac45313yy case '"':
47b7744cbea59975a6b583125b7ed1ff2ac45313yy Start_tok = ++nextchr;
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (((end = strpbrk(nextchr,
47b7744cbea59975a6b583125b7ed1ff2ac45313yy MSG_ORIG(MSG_MAP_TOK_1))) == NULL) ||
47b7744cbea59975a6b583125b7ed1ff2ac45313yy (*end != '"')) {
47b7744cbea59975a6b583125b7ed1ff2ac45313yy eprintf(ofl->ofl_lml, ERR_FATAL,
47b7744cbea59975a6b583125b7ed1ff2ac45313yy MSG_INTL(MSG_MAP_NOTERM), mapfile,
47b7744cbea59975a6b583125b7ed1ff2ac45313yy EC_XWORD(Line_num));
47b7744cbea59975a6b583125b7ed1ff2ac45313yy return (TK_ERROR);
47b7744cbea59975a6b583125b7ed1ff2ac45313yy }
47b7744cbea59975a6b583125b7ed1ff2ac45313yy *end = '\0';
25f2d433de915875c8393f0b0dc14aa155997ad0xy nextchr = end + 1;
47b7744cbea59975a6b583125b7ed1ff2ac45313yy return (TK_STRING);
c7770590c6dc06be2588a5c21427e2d823baa989mx default: /* string. */
25f2d433de915875c8393f0b0dc14aa155997ad0xy Start_tok = nextchr; /* CSTYLED */
25f2d433de915875c8393f0b0dc14aa155997ad0xy end = strpbrk(nextchr, MSG_ORIG(MSG_MAP_TOK_2));
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (end == NULL)
25f2d433de915875c8393f0b0dc14aa155997ad0xy nextchr = Start_tok + strlen(Start_tok);
080575042aba2197b425ebfd52061dea061a9aa1xy else {
25f2d433de915875c8393f0b0dc14aa155997ad0xy nextchr = end;
25f2d433de915875c8393f0b0dc14aa155997ad0xy oldchr = *nextchr;
6ad5fc39c6f3b123ae5588d60fc8dfe068e07bfcsv *nextchr = '\0';
c7770590c6dc06be2588a5c21427e2d823baa989mx }
3d15c084da89e6f689f1804f3e2e600e5376c4e1chenlu chen - Sun Microsystems - Beijing China return (TK_STRING);
080575042aba2197b425ebfd52061dea061a9aa1xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems}
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems/*
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems * Process a hardware/software capabilities segment declaration definition.
080575042aba2197b425ebfd52061dea061a9aa1xy * hwcap_1 = val,... [ OVERRIDE ]
080575042aba2197b425ebfd52061dea061a9aa1xy * sfcap_1 = val,... [ OVERRIDE ]
080575042aba2197b425ebfd52061dea061a9aa1xy *
080575042aba2197b425ebfd52061dea061a9aa1xy * The values can be defined as a list of machine specify tokens, or numerics.
080575042aba2197b425ebfd52061dea061a9aa1xy * Tokens are representations of the sys/auxv_$MACH.h capabilities, for example:
080575042aba2197b425ebfd52061dea061a9aa1xy *
080575042aba2197b425ebfd52061dea061a9aa1xy * #define AV_386_FPU 0x0001 is represented as FPU
080575042aba2197b425ebfd52061dea061a9aa1xy * #define AV_386_TSC 0x0002 " " " " TSC
080575042aba2197b425ebfd52061dea061a9aa1xy *
080575042aba2197b425ebfd52061dea061a9aa1xy * Or, the above two capabilities could be represented as V0x3. Note, the
080575042aba2197b425ebfd52061dea061a9aa1xy * OVERRIDE flag is used to insure that only those values provided via this
080575042aba2197b425ebfd52061dea061a9aa1xy * mapfile entry are recorded in the final image, ie. this overrides any
080575042aba2197b425ebfd52061dea061a9aa1xy * hardware capabilities that may be defined in the objects read as part of this
080575042aba2197b425ebfd52061dea061a9aa1xy * link-edit. Specifying:
c7770590c6dc06be2588a5c21427e2d823baa989mx *
080575042aba2197b425ebfd52061dea061a9aa1xy * V0x0 OVERRIDE
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems *
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems * effectively removes any capabilities information from the final image.
080575042aba2197b425ebfd52061dea061a9aa1xy */
ae6aa22afeb444ae208c287e7227a4a7c877f17aVenugopal Iyerstatic uintptr_t
ae6aa22afeb444ae208c287e7227a4a7c877f17aVenugopal Iyermap_cap(const char *mapfile, Word type, Ofl_desc *ofl)
080575042aba2197b425ebfd52061dea061a9aa1xy{
080575042aba2197b425ebfd52061dea061a9aa1xy Token tok; /* Current token. */
080575042aba2197b425ebfd52061dea061a9aa1xy Xword number;
080575042aba2197b425ebfd52061dea061a9aa1xy int used = 0;
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy while ((tok = gettoken(ofl, mapfile, 0)) != TK_SEMICOLON) {
080575042aba2197b425ebfd52061dea061a9aa1xy if (tok != TK_STRING) {
080575042aba2197b425ebfd52061dea061a9aa1xy if (tok != TK_ERROR)
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_EXPSEGATT), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy lowercase(Start_tok);
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * First, determine if the token represents the reserved
080575042aba2197b425ebfd52061dea061a9aa1xy * OVERRIDE keyword.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy if (strncmp(Start_tok, MSG_ORIG(MSG_MAP_OVERRIDE),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_MAP_OVERRIDE_SIZE) == 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy if (type == CA_SUNW_HW_1)
25f2d433de915875c8393f0b0dc14aa155997ad0xy ofl->ofl_flags1 |= FLG_OF1_OVHWCAP;
25f2d433de915875c8393f0b0dc14aa155997ad0xy else
25f2d433de915875c8393f0b0dc14aa155997ad0xy ofl->ofl_flags1 |= FLG_OF1_OVSFCAP;
25f2d433de915875c8393f0b0dc14aa155997ad0xy used++;
25f2d433de915875c8393f0b0dc14aa155997ad0xy continue;
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy
25f2d433de915875c8393f0b0dc14aa155997ad0xy /*
25f2d433de915875c8393f0b0dc14aa155997ad0xy * Next, determine if the token represents a machine specific
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini * hardware capability, or a generic software capability.
25f2d433de915875c8393f0b0dc14aa155997ad0xy */
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (type == CA_SUNW_HW_1) {
9b6541b318d01d0d83bfb98699a7f09e35f37951gl if ((number = (Xword)elfcap_hw1_from_str(
080575042aba2197b425ebfd52061dea061a9aa1xy ELFCAP_STYLE_LC, Start_tok,
080575042aba2197b425ebfd52061dea061a9aa1xy ld_targ.t_m.m_mach)) != 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy ofl->ofl_hwcap_1 |= number;
080575042aba2197b425ebfd52061dea061a9aa1xy used++;
080575042aba2197b425ebfd52061dea061a9aa1xy continue;
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy } else {
080575042aba2197b425ebfd52061dea061a9aa1xy if ((number = (Xword)elfcap_sf1_from_str(
080575042aba2197b425ebfd52061dea061a9aa1xy ELFCAP_STYLE_LC, Start_tok,
080575042aba2197b425ebfd52061dea061a9aa1xy ld_targ.t_m.m_mach)) != 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy ofl->ofl_sfcap_1 |= number;
080575042aba2197b425ebfd52061dea061a9aa1xy used++;
080575042aba2197b425ebfd52061dea061a9aa1xy continue;
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * Next, determine if the token represents a numeric value.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy if (Start_tok[0] == 'v') {
080575042aba2197b425ebfd52061dea061a9aa1xy char *end_tok;
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy errno = 0;
080575042aba2197b425ebfd52061dea061a9aa1xy number = (Xword)strtoul(&Start_tok[1], &end_tok, 0);
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (errno) {
25f2d433de915875c8393f0b0dc14aa155997ad0xy int err = errno;
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc eprintf(ofl->ofl_lml, ERR_FATAL,
caf05df5c10c960028f122b1b02a3f7d8f892c31Miles Xu, Sun Microsystems MSG_INTL(MSG_MAP_BADCAPVAL),
caf05df5c10c960028f122b1b02a3f7d8f892c31Miles Xu, Sun Microsystems mapfile, EC_XWORD(Line_num), Start_tok,
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc strerror(err));
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc return (S_ERROR);
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc }
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc if (end_tok != strchr(Start_tok, '\0')) {
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_BADCAPVAL), mapfile,
c7770590c6dc06be2588a5c21427e2d823baa989mx EC_XWORD(Line_num), Start_tok,
c7770590c6dc06be2588a5c21427e2d823baa989mx MSG_INTL(MSG_MAP_NOBADFRM));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy
7941757c1241fe30e30f921910595c8ac6af9ef1xy if (type == CA_SUNW_HW_1)
7941757c1241fe30e30f921910595c8ac6af9ef1xy ofl->ofl_hwcap_1 |= number;
080575042aba2197b425ebfd52061dea061a9aa1xy else
080575042aba2197b425ebfd52061dea061a9aa1xy ofl->ofl_sfcap_1 |= number;
080575042aba2197b425ebfd52061dea061a9aa1xy used++;
080575042aba2197b425ebfd52061dea061a9aa1xy continue;
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * We have an unknown token.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy used++;
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_MAP_UNKCAPATTR),
080575042aba2197b425ebfd52061dea061a9aa1xy mapfile, EC_XWORD(Line_num), Start_tok);
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
ea6b684a18957883cb91b3d22a9d989f986e5a32yy
ea6b684a18957883cb91b3d22a9d989f986e5a32yy /*
ea6b684a18957883cb91b3d22a9d989f986e5a32yy * Catch any empty declarations, and indicate any software capabilities
ea6b684a18957883cb91b3d22a9d989f986e5a32yy * have been initialized if necessary.
ea6b684a18957883cb91b3d22a9d989f986e5a32yy */
080575042aba2197b425ebfd52061dea061a9aa1xy if (used == 0) {
c7770590c6dc06be2588a5c21427e2d823baa989mx eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_MAP_EMPTYCAP),
c7770590c6dc06be2588a5c21427e2d823baa989mx mapfile, EC_XWORD(Line_num));
c7770590c6dc06be2588a5c21427e2d823baa989mx } else if (type == CA_SUNW_SF_1) {
c7770590c6dc06be2588a5c21427e2d823baa989mx Lword badsf1;
c7770590c6dc06be2588a5c21427e2d823baa989mx
46ebaa55cce1df60528a191312d12199d38a4493Miles Xu, Sun Microsystems /*
46ebaa55cce1df60528a191312d12199d38a4493Miles Xu, Sun Microsystems * Note, hardware capabilities, beyond the tokens that are
46ebaa55cce1df60528a191312d12199d38a4493Miles Xu, Sun Microsystems * presently known, can be accepted using the V0xXXX notation,
46ebaa55cce1df60528a191312d12199d38a4493Miles Xu, Sun Microsystems * and as these simply get or'd into the output image, we allow
080575042aba2197b425ebfd52061dea061a9aa1xy * any values to be supplied. Software capability tokens
080575042aba2197b425ebfd52061dea061a9aa1xy * however, have an algorithm of acceptance and update (see
080575042aba2197b425ebfd52061dea061a9aa1xy * sf1_cap() in files.c). Therefore only allow software
080575042aba2197b425ebfd52061dea061a9aa1xy * capabilities that are known.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy if ((badsf1 = (ofl->ofl_sfcap_1 & ~SF1_SUNW_MASK)) != 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_WARNING,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_BADSF1), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num), EC_LWORD(badsf1));
080575042aba2197b425ebfd52061dea061a9aa1xy ofl->ofl_sfcap_1 &= SF1_SUNW_MASK;
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy if (ofl->ofl_sfcap_1 == SF1_SUNW_FPUSED) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_WARNING,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_FIL_BADSF1), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num), EC_LWORD(SF1_SUNW_FPUSED));
080575042aba2197b425ebfd52061dea061a9aa1xy ofl->ofl_sfcap_1 = 0;
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy return (1);
080575042aba2197b425ebfd52061dea061a9aa1xy}
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy/*
080575042aba2197b425ebfd52061dea061a9aa1xy * Common segment error checking.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xystatic Boolean
080575042aba2197b425ebfd52061dea061a9aa1xyseg_check(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl, Boolean b_type,
080575042aba2197b425ebfd52061dea061a9aa1xy Word p_type)
080575042aba2197b425ebfd52061dea061a9aa1xy{
080575042aba2197b425ebfd52061dea061a9aa1xy if (b_type) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_MAP_MOREONCE),
080575042aba2197b425ebfd52061dea061a9aa1xy mapfile, EC_XWORD(Line_num), MSG_INTL(MSG_MAP_SEGTYP));
080575042aba2197b425ebfd52061dea061a9aa1xy return (FALSE);
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy if ((sgp->sg_flags & FLG_SG_TYPE) && (sgp->sg_phdr.p_type != p_type)) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_MAP_REDEFATT),
080575042aba2197b425ebfd52061dea061a9aa1xy mapfile, EC_XWORD(Line_num), MSG_INTL(MSG_MAP_SEGTYP),
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_name);
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy return (TRUE);
080575042aba2197b425ebfd52061dea061a9aa1xy}
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy/*
080575042aba2197b425ebfd52061dea061a9aa1xy * Process a mapfile segment declaration definition.
080575042aba2197b425ebfd52061dea061a9aa1xy * segment_name = segment_attribute;
080575042aba2197b425ebfd52061dea061a9aa1xy * segment_attribute : segment_type segment_flags virtual_addr
080575042aba2197b425ebfd52061dea061a9aa1xy * physical_addr length alignment
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xystatic uintptr_t
080575042aba2197b425ebfd52061dea061a9aa1xymap_equal(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl)
080575042aba2197b425ebfd52061dea061a9aa1xy{
080575042aba2197b425ebfd52061dea061a9aa1xy Token tok; /* Current token. */
080575042aba2197b425ebfd52061dea061a9aa1xy Boolean b_type = FALSE; /* True if seg types found. */
080575042aba2197b425ebfd52061dea061a9aa1xy Boolean b_flags = FALSE; /* True if seg flags found. */
080575042aba2197b425ebfd52061dea061a9aa1xy Boolean b_len = FALSE; /* True if seg length found. */
080575042aba2197b425ebfd52061dea061a9aa1xy Boolean b_round = FALSE; /* True if seg rounding found. */
080575042aba2197b425ebfd52061dea061a9aa1xy Boolean b_vaddr = FALSE; /* True if seg virtual addr found. */
080575042aba2197b425ebfd52061dea061a9aa1xy Boolean b_paddr = FALSE; /* True if seg physical addr found. */
080575042aba2197b425ebfd52061dea061a9aa1xy Boolean b_align = FALSE; /* True if seg alignment found. */
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy while ((tok = gettoken(ofl, mapfile, 0)) != TK_SEMICOLON) {
080575042aba2197b425ebfd52061dea061a9aa1xy if (tok != TK_STRING) {
080575042aba2197b425ebfd52061dea061a9aa1xy if (tok != TK_ERROR)
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_EXPSEGATT), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy lowercase(Start_tok);
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * Segment type. Users are permitted to define PT_LOAD,
080575042aba2197b425ebfd52061dea061a9aa1xy * PT_NOTE, PT_STACK and PT_NULL segments. Other segment types
080575042aba2197b425ebfd52061dea061a9aa1xy * are only defined in seg_desc[].
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_LOAD)) == 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy if ((b_type = seg_check(mapfile, sgp, ofl, b_type,
080575042aba2197b425ebfd52061dea061a9aa1xy PT_LOAD)) == FALSE)
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_phdr.p_type = PT_LOAD;
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_flags |= FLG_SG_TYPE;
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy } else if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_STACK)) == 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy if ((b_type = seg_check(mapfile, sgp, ofl, b_type,
080575042aba2197b425ebfd52061dea061a9aa1xy PT_SUNWSTACK)) == FALSE)
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_phdr.p_type = PT_SUNWSTACK;
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_flags |= (FLG_SG_TYPE | FLG_SG_EMPTY);
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy } else if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_NULL)) == 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy if ((b_type = seg_check(mapfile, sgp, ofl, b_type,
080575042aba2197b425ebfd52061dea061a9aa1xy PT_NULL)) == FALSE)
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_phdr.p_type = PT_NULL;
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_flags |= FLG_SG_TYPE;
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy } else if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_NOTE)) == 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy if ((b_type = seg_check(mapfile, sgp, ofl, b_type,
080575042aba2197b425ebfd52061dea061a9aa1xy PT_NOTE)) == FALSE)
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng sgp->sg_phdr.p_type = PT_NOTE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng sgp->sg_flags |= FLG_SG_TYPE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Segment Flags. */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else if (*Start_tok == '?') {
080575042aba2197b425ebfd52061dea061a9aa1xy Word tmp_flags = 0;
080575042aba2197b425ebfd52061dea061a9aa1xy char *flag_tok = Start_tok + 1;
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy if (b_flags) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_MOREONCE), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGFLAG));
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * If ? has nothing following leave the flags cleared,
080575042aba2197b425ebfd52061dea061a9aa1xy * otherwise or in any flags specified.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy if (*flag_tok) {
080575042aba2197b425ebfd52061dea061a9aa1xy while (*flag_tok) {
080575042aba2197b425ebfd52061dea061a9aa1xy switch (*flag_tok) {
080575042aba2197b425ebfd52061dea061a9aa1xy case 'r':
080575042aba2197b425ebfd52061dea061a9aa1xy tmp_flags |= PF_R;
080575042aba2197b425ebfd52061dea061a9aa1xy break;
080575042aba2197b425ebfd52061dea061a9aa1xy case 'w':
080575042aba2197b425ebfd52061dea061a9aa1xy tmp_flags |= PF_W;
080575042aba2197b425ebfd52061dea061a9aa1xy break;
080575042aba2197b425ebfd52061dea061a9aa1xy case 'x':
080575042aba2197b425ebfd52061dea061a9aa1xy tmp_flags |= PF_X;
080575042aba2197b425ebfd52061dea061a9aa1xy break;
080575042aba2197b425ebfd52061dea061a9aa1xy case 'e':
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_flags |= FLG_SG_EMPTY;
080575042aba2197b425ebfd52061dea061a9aa1xy break;
080575042aba2197b425ebfd52061dea061a9aa1xy case 'o':
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_flags |= FLG_SG_ORDER;
25f2d433de915875c8393f0b0dc14aa155997ad0xy ofl->ofl_flags |=
080575042aba2197b425ebfd52061dea061a9aa1xy FLG_OF_SEGORDER;
080575042aba2197b425ebfd52061dea061a9aa1xy break;
080575042aba2197b425ebfd52061dea061a9aa1xy case 'n':
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_flags |= FLG_SG_NOHDR;
080575042aba2197b425ebfd52061dea061a9aa1xy break;
080575042aba2197b425ebfd52061dea061a9aa1xy default:
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_UNKSEGFLG),
080575042aba2197b425ebfd52061dea061a9aa1xy mapfile, EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy *flag_tok);
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy flag_tok++;
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * Warn when changing flags except when we're
080575042aba2197b425ebfd52061dea061a9aa1xy * adding or removing "X" from a RW PT_LOAD
080575042aba2197b425ebfd52061dea061a9aa1xy * segment.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy if ((sgp->sg_flags & FLG_SG_FLAGS) &&
080575042aba2197b425ebfd52061dea061a9aa1xy (sgp->sg_phdr.p_flags != tmp_flags) &&
080575042aba2197b425ebfd52061dea061a9aa1xy !(sgp->sg_phdr.p_type == PT_LOAD &&
ea6b684a18957883cb91b3d22a9d989f986e5a32yy (tmp_flags & (PF_R|PF_W)) == (PF_R|PF_W) &&
ea6b684a18957883cb91b3d22a9d989f986e5a32yy (tmp_flags ^ sgp->sg_phdr.p_flags) == PF_X)) {
ea6b684a18957883cb91b3d22a9d989f986e5a32yy eprintf(ofl->ofl_lml, ERR_WARNING,
0f70fbf80d71251e7928b3122fb4848c2f92a5c6xy MSG_INTL(MSG_MAP_REDEFATT), mapfile,
0f70fbf80d71251e7928b3122fb4848c2f92a5c6xy EC_XWORD(Line_num),
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems MSG_INTL(MSG_MAP_SEGFLAG), sgp->sg_name);
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems }
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems sgp->sg_flags |= FLG_SG_FLAGS;
0f70fbf80d71251e7928b3122fb4848c2f92a5c6xy sgp->sg_phdr.p_flags = tmp_flags;
0f70fbf80d71251e7928b3122fb4848c2f92a5c6xy b_flags = TRUE;
0f70fbf80d71251e7928b3122fb4848c2f92a5c6xy }
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy /* Segment address, length, alignment or rounding number. */
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy else if ((Start_tok[0] == 'l') || (Start_tok[0] == 'v') ||
080575042aba2197b425ebfd52061dea061a9aa1xy (Start_tok[0] == 'a') || (Start_tok[0] == 'p') ||
080575042aba2197b425ebfd52061dea061a9aa1xy (Start_tok[0] == 'r')) {
080575042aba2197b425ebfd52061dea061a9aa1xy char *end_tok;
080575042aba2197b425ebfd52061dea061a9aa1xy Xword number;
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy if ((number = (Xword)STRTOADDR(&Start_tok[1], &end_tok,
080575042aba2197b425ebfd52061dea061a9aa1xy 0)) >= XWORD_MAX) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGADDR), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num), Start_tok,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_EXCLIMIT));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (end_tok != strchr(Start_tok, '\0')) {
25f2d433de915875c8393f0b0dc14aa155997ad0xy eprintf(ofl->ofl_lml, ERR_FATAL,
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_SEGADDR), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num), Start_tok,
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_NOBADFRM));
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (S_ERROR);
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy
080575042aba2197b425ebfd52061dea061a9aa1xy switch (*Start_tok) {
080575042aba2197b425ebfd52061dea061a9aa1xy case 'l':
080575042aba2197b425ebfd52061dea061a9aa1xy if (b_len) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_MOREONCE),
080575042aba2197b425ebfd52061dea061a9aa1xy mapfile, EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGLEN));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy if ((sgp->sg_flags & FLG_SG_LENGTH) &&
080575042aba2197b425ebfd52061dea061a9aa1xy (sgp->sg_length != number))
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_WARNING,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_REDEFATT),
080575042aba2197b425ebfd52061dea061a9aa1xy mapfile, EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGLEN),
25f2d433de915875c8393f0b0dc14aa155997ad0xy sgp->sg_name);
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_length = number;
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_flags |= FLG_SG_LENGTH;
080575042aba2197b425ebfd52061dea061a9aa1xy b_len = TRUE;
080575042aba2197b425ebfd52061dea061a9aa1xy break;
080575042aba2197b425ebfd52061dea061a9aa1xy case 'r':
080575042aba2197b425ebfd52061dea061a9aa1xy if (b_round) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_MOREONCE),
25f2d433de915875c8393f0b0dc14aa155997ad0xy mapfile, EC_XWORD(Line_num),
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_SEGROUND));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy if ((sgp->sg_flags & FLG_SG_ROUND) &&
25f2d433de915875c8393f0b0dc14aa155997ad0xy (sgp->sg_round != number))
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_WARNING,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_REDEFATT),
080575042aba2197b425ebfd52061dea061a9aa1xy mapfile, EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGROUND),
25f2d433de915875c8393f0b0dc14aa155997ad0xy sgp->sg_name);
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems sgp->sg_round = number;
25f2d433de915875c8393f0b0dc14aa155997ad0xy sgp->sg_flags |= FLG_SG_ROUND;
080575042aba2197b425ebfd52061dea061a9aa1xy b_round = TRUE;
080575042aba2197b425ebfd52061dea061a9aa1xy break;
25f2d433de915875c8393f0b0dc14aa155997ad0xy case 'v':
080575042aba2197b425ebfd52061dea061a9aa1xy if (b_vaddr) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_MOREONCE),
080575042aba2197b425ebfd52061dea061a9aa1xy mapfile, EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGVADDR));
ea6b684a18957883cb91b3d22a9d989f986e5a32yy return (S_ERROR);
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
080575042aba2197b425ebfd52061dea061a9aa1xy if ((sgp->sg_flags & FLG_SG_VADDR) &&
ea6b684a18957883cb91b3d22a9d989f986e5a32yy (sgp->sg_phdr.p_vaddr != number))
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems eprintf(ofl->ofl_lml, ERR_WARNING,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_REDEFATT),
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems mapfile, EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGVADDR),
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_name);
080575042aba2197b425ebfd52061dea061a9aa1xy /* LINTED */
25f2d433de915875c8393f0b0dc14aa155997ad0xy sgp->sg_phdr.p_vaddr = (Addr)number;
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_flags |= FLG_SG_VADDR;
25f2d433de915875c8393f0b0dc14aa155997ad0xy ofl->ofl_flags1 |= FLG_OF1_VADDR;
080575042aba2197b425ebfd52061dea061a9aa1xy b_vaddr = TRUE;
080575042aba2197b425ebfd52061dea061a9aa1xy break;
25f2d433de915875c8393f0b0dc14aa155997ad0xy case 'p':
080575042aba2197b425ebfd52061dea061a9aa1xy if (b_paddr) {
c7770590c6dc06be2588a5c21427e2d823baa989mx eprintf(ofl->ofl_lml, ERR_FATAL,
7941757c1241fe30e30f921910595c8ac6af9ef1xy MSG_INTL(MSG_MAP_MOREONCE),
7941757c1241fe30e30f921910595c8ac6af9ef1xy mapfile, EC_XWORD(Line_num),
7941757c1241fe30e30f921910595c8ac6af9ef1xy MSG_INTL(MSG_MAP_SEGPHYS));
7941757c1241fe30e30f921910595c8ac6af9ef1xy return (S_ERROR);
c7770590c6dc06be2588a5c21427e2d823baa989mx }
c7770590c6dc06be2588a5c21427e2d823baa989mx if ((sgp->sg_flags & FLG_SG_PADDR) &&
c7770590c6dc06be2588a5c21427e2d823baa989mx (sgp->sg_phdr.p_paddr != number))
c7770590c6dc06be2588a5c21427e2d823baa989mx eprintf(ofl->ofl_lml, ERR_WARNING,
c7770590c6dc06be2588a5c21427e2d823baa989mx MSG_INTL(MSG_MAP_REDEFATT),
7941757c1241fe30e30f921910595c8ac6af9ef1xy mapfile, EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGPHYS),
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_name);
080575042aba2197b425ebfd52061dea061a9aa1xy /* LINTED */
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_phdr.p_paddr = (Addr)number;
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_flags |= FLG_SG_PADDR;
080575042aba2197b425ebfd52061dea061a9aa1xy b_paddr = TRUE;
080575042aba2197b425ebfd52061dea061a9aa1xy break;
080575042aba2197b425ebfd52061dea061a9aa1xy case 'a':
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (b_align) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_MOREONCE),
080575042aba2197b425ebfd52061dea061a9aa1xy mapfile, EC_XWORD(Line_num),
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_SEGALIGN));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy if ((sgp->sg_flags & FLG_SG_ALIGN) &&
25f2d433de915875c8393f0b0dc14aa155997ad0xy (sgp->sg_phdr.p_align != number))
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_WARNING,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_REDEFATT),
46ebaa55cce1df60528a191312d12199d38a4493Miles Xu, Sun Microsystems mapfile, EC_XWORD(Line_num),
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_SEGALIGN),
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_name);
080575042aba2197b425ebfd52061dea061a9aa1xy /* LINTED */
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_phdr.p_align = (Xword)number;
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_flags |= FLG_SG_ALIGN;
080575042aba2197b425ebfd52061dea061a9aa1xy b_align = TRUE;
25f2d433de915875c8393f0b0dc14aa155997ad0xy break;
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy } else {
25f2d433de915875c8393f0b0dc14aa155997ad0xy eprintf(ofl->ofl_lml, ERR_FATAL,
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_UNKSEGATT), mapfile,
25f2d433de915875c8393f0b0dc14aa155997ad0xy EC_XWORD(Line_num), Start_tok);
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (S_ERROR);
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * Empty segments can be used to define PT_LOAD segment reservations, or
25f2d433de915875c8393f0b0dc14aa155997ad0xy * to reserve PT_NULL program headers.
080575042aba2197b425ebfd52061dea061a9aa1xy *
080575042aba2197b425ebfd52061dea061a9aa1xy * PT_LOAD reservations are only allowed within executables, as the
080575042aba2197b425ebfd52061dea061a9aa1xy * reservation must be established through exec() as part of initial
080575042aba2197b425ebfd52061dea061a9aa1xy * process loading. In addition, PT_LOAD reservations must have an
25f2d433de915875c8393f0b0dc14aa155997ad0xy * associated address and size.
25f2d433de915875c8393f0b0dc14aa155997ad0xy *
25f2d433de915875c8393f0b0dc14aa155997ad0xy * PT_NULL program headers are established for later use by applications
25f2d433de915875c8393f0b0dc14aa155997ad0xy * such as the post-optimizer. PT_NULL headers should have no other
080575042aba2197b425ebfd52061dea061a9aa1xy * attributes assigned.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy if ((sgp->sg_flags & FLG_SG_EMPTY) &&
080575042aba2197b425ebfd52061dea061a9aa1xy (sgp->sg_phdr.p_type != PT_SUNWSTACK)) {
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * Any style of empty segment should have no permissions.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy if (sgp->sg_phdr.p_flags != 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGEMNOPERM), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy EC_WORD(sgp->sg_phdr.p_flags));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy
47b7744cbea59975a6b583125b7ed1ff2ac45313yy if (sgp->sg_phdr.p_type == PT_LOAD) {
080575042aba2197b425ebfd52061dea061a9aa1xy if ((ofl->ofl_flags & FLG_OF_EXEC) == 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGEMPEXE), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
47b7744cbea59975a6b583125b7ed1ff2ac45313yy if ((sgp->sg_flags & (FLG_SG_LENGTH | FLG_SG_VADDR)) !=
080575042aba2197b425ebfd52061dea061a9aa1xy (FLG_SG_LENGTH | FLG_SG_VADDR)) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGEMPATT), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy } else if (sgp->sg_phdr.p_type == PT_NULL) {
080575042aba2197b425ebfd52061dea061a9aa1xy if ((sgp->sg_flags & (FLG_SG_LENGTH | FLG_SG_VADDR)) &&
080575042aba2197b425ebfd52061dea061a9aa1xy ((sgp->sg_length != 0) ||
080575042aba2197b425ebfd52061dea061a9aa1xy (sgp->sg_phdr.p_vaddr != 0))) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGEMPNOATT), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy } else {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_WARNING,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGEMPLOAD), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num));
47b7744cbea59975a6b583125b7ed1ff2ac45313yy sgp->sg_phdr.p_type = PT_LOAD;
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * All segment attributes have now been scanned. Certain flags do not
080575042aba2197b425ebfd52061dea061a9aa1xy * make sense if this is not a loadable segment, fix if necessary.
47b7744cbea59975a6b583125b7ed1ff2ac45313yy * Note, if the segment is of type PT_NULL it must be new, and any
080575042aba2197b425ebfd52061dea061a9aa1xy * defaults will be applied back in ld_map_parse().
080575042aba2197b425ebfd52061dea061a9aa1xy * When clearing an attribute leave the flag set as an indicator for
080575042aba2197b425ebfd52061dea061a9aa1xy * later entries re-specifying the same segment.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy if ((sgp->sg_phdr.p_type != PT_NULL) &&
080575042aba2197b425ebfd52061dea061a9aa1xy (sgp->sg_phdr.p_type != PT_LOAD)) {
080575042aba2197b425ebfd52061dea061a9aa1xy const char *fmt;
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy if (sgp->sg_phdr.p_type == PT_SUNWSTACK)
080575042aba2197b425ebfd52061dea061a9aa1xy fmt = MSG_INTL(MSG_MAP_NOSTACK1);
25f2d433de915875c8393f0b0dc14aa155997ad0xy else
080575042aba2197b425ebfd52061dea061a9aa1xy fmt = MSG_INTL(MSG_MAP_NONLOAD);
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy if ((sgp->sg_flags & FLG_SG_FLAGS) &&
080575042aba2197b425ebfd52061dea061a9aa1xy (sgp->sg_phdr.p_type != PT_SUNWSTACK)) {
080575042aba2197b425ebfd52061dea061a9aa1xy if (sgp->sg_phdr.p_flags != 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_WARNING,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_NONLOAD), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGFLAG));
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_phdr.p_flags = 0;
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy if (sgp->sg_flags & FLG_SG_LENGTH)
080575042aba2197b425ebfd52061dea061a9aa1xy if (sgp->sg_length != 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_WARNING,
080575042aba2197b425ebfd52061dea061a9aa1xy fmt, mapfile, EC_XWORD(Line_num),
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_SEGLEN));
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_length = 0;
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy if (sgp->sg_flags & FLG_SG_ROUND)
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (sgp->sg_round != 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_WARNING,
080575042aba2197b425ebfd52061dea061a9aa1xy fmt, mapfile, EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGROUND));
c7770590c6dc06be2588a5c21427e2d823baa989mx sgp->sg_round = 0;
080575042aba2197b425ebfd52061dea061a9aa1xy }
c7770590c6dc06be2588a5c21427e2d823baa989mx if (sgp->sg_flags & FLG_SG_VADDR) {
080575042aba2197b425ebfd52061dea061a9aa1xy if (sgp->sg_phdr.p_vaddr != 0) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_WARNING,
080575042aba2197b425ebfd52061dea061a9aa1xy fmt, mapfile, EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SEGVADDR));
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_phdr.p_vaddr = 0;
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (sgp->sg_flags & FLG_SG_PADDR)
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (sgp->sg_phdr.p_paddr != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng eprintf(ofl->ofl_lml, ERR_WARNING,
25f2d433de915875c8393f0b0dc14aa155997ad0xy fmt, mapfile, EC_XWORD(Line_num),
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_SEGPHYS));
25f2d433de915875c8393f0b0dc14aa155997ad0xy sgp->sg_phdr.p_paddr = 0;
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (sgp->sg_flags & FLG_SG_ALIGN)
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (sgp->sg_phdr.p_align != 0) {
25f2d433de915875c8393f0b0dc14aa155997ad0xy eprintf(ofl->ofl_lml, ERR_WARNING,
25f2d433de915875c8393f0b0dc14aa155997ad0xy fmt, mapfile, EC_XWORD(Line_num),
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng MSG_INTL(MSG_MAP_SEGALIGN));
25f2d433de915875c8393f0b0dc14aa155997ad0xy sgp->sg_phdr.p_align = 0;
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (1);
25f2d433de915875c8393f0b0dc14aa155997ad0xy}
25f2d433de915875c8393f0b0dc14aa155997ad0xy
25f2d433de915875c8393f0b0dc14aa155997ad0xy
25f2d433de915875c8393f0b0dc14aa155997ad0xy/*
25f2d433de915875c8393f0b0dc14aa155997ad0xy * Process a mapfile mapping directives definition.
25f2d433de915875c8393f0b0dc14aa155997ad0xy * segment_name : section_attribute [ : file_name ]
25f2d433de915875c8393f0b0dc14aa155997ad0xy * segment_attribute : section_name section_type section_flags;
25f2d433de915875c8393f0b0dc14aa155997ad0xy */
25f2d433de915875c8393f0b0dc14aa155997ad0xystatic uintptr_t
25f2d433de915875c8393f0b0dc14aa155997ad0xymap_colon(Ofl_desc *ofl, const char *mapfile, Ent_desc *enp)
43a176879122f7764767ab85eb539f89d65cdd67Miles Xu, Sun Microsystems{
25f2d433de915875c8393f0b0dc14aa155997ad0xy Token tok; /* Current token. */
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy Boolean b_name = FALSE;
080575042aba2197b425ebfd52061dea061a9aa1xy Boolean b_type = FALSE;
080575042aba2197b425ebfd52061dea061a9aa1xy Boolean b_attr = FALSE;
080575042aba2197b425ebfd52061dea061a9aa1xy Boolean b_bang = FALSE;
080575042aba2197b425ebfd52061dea061a9aa1xy static Xword index = 0;
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems
080575042aba2197b425ebfd52061dea061a9aa1xy
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng while (((tok = gettoken(ofl, mapfile, 0)) != TK_COLON) &&
080575042aba2197b425ebfd52061dea061a9aa1xy (tok != TK_SEMICOLON)) {
080575042aba2197b425ebfd52061dea061a9aa1xy if ((tok == TK_ERROR) || (tok == TK_EOF))
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy /* Segment type. */
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy if (*Start_tok == '$') {
080575042aba2197b425ebfd52061dea061a9aa1xy if (b_type) {
080575042aba2197b425ebfd52061dea061a9aa1xy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_MOREONCE), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SECTYP));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
080575042aba2197b425ebfd52061dea061a9aa1xy b_type = TRUE;
080575042aba2197b425ebfd52061dea061a9aa1xy Start_tok++;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng lowercase(Start_tok);
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems if (strcmp(Start_tok, MSG_ORIG(MSG_STR_PROGBITS)) == 0)
25f2d433de915875c8393f0b0dc14aa155997ad0xy enp->ec_type = SHT_PROGBITS;
25f2d433de915875c8393f0b0dc14aa155997ad0xy else if (strcmp(Start_tok,
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_ORIG(MSG_STR_SYMTAB)) == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng enp->ec_type = SHT_SYMTAB;
25f2d433de915875c8393f0b0dc14aa155997ad0xy else if (strcmp(Start_tok,
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_ORIG(MSG_STR_DYNSYM)) == 0)
25f2d433de915875c8393f0b0dc14aa155997ad0xy enp->ec_type = SHT_DYNSYM;
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems else if (strcmp(Start_tok,
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems MSG_ORIG(MSG_STR_STRTAB)) == 0)
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems enp->ec_type = SHT_STRTAB;
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems else if ((strcmp(Start_tok,
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems MSG_ORIG(MSG_STR_REL)) == 0) ||
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems (strcmp(Start_tok, MSG_ORIG(MSG_STR_RELA)) == 0))
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems enp->ec_type = ld_targ.t_m.m_rel_sht_type;
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems else if (strcmp(Start_tok, MSG_ORIG(MSG_STR_HASH)) == 0)
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems enp->ec_type = SHT_HASH;
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems else if (strcmp(Start_tok, MSG_ORIG(MSG_STR_LIB)) == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng enp->ec_type = SHT_SHLIB;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else if (strcmp(Start_tok,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng MSG_ORIG(MSG_STR_LD_DYNAMIC)) == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng enp->ec_type = SHT_DYNAMIC;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else if (strcmp(Start_tok, MSG_ORIG(MSG_STR_NOTE)) == 0)
25f2d433de915875c8393f0b0dc14aa155997ad0xy enp->ec_type = SHT_NOTE;
25f2d433de915875c8393f0b0dc14aa155997ad0xy else if (strcmp(Start_tok,
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_ORIG(MSG_STR_NOBITS)) == 0)
25f2d433de915875c8393f0b0dc14aa155997ad0xy enp->ec_type = SHT_NOBITS;
25f2d433de915875c8393f0b0dc14aa155997ad0xy else {
25f2d433de915875c8393f0b0dc14aa155997ad0xy eprintf(ofl->ofl_lml, ERR_FATAL,
46ebaa55cce1df60528a191312d12199d38a4493Miles Xu, Sun Microsystems MSG_INTL(MSG_MAP_UNKSECTYP), mapfile,
25f2d433de915875c8393f0b0dc14aa155997ad0xy EC_XWORD(Line_num), Start_tok);
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (S_ERROR);
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy
25f2d433de915875c8393f0b0dc14aa155997ad0xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * Segment flags.
080575042aba2197b425ebfd52061dea061a9aa1xy * If a segment flag is specified then the appropriate bit is
080575042aba2197b425ebfd52061dea061a9aa1xy * set in the ec_attrmask, the ec_attrbits fields determine
080575042aba2197b425ebfd52061dea061a9aa1xy * whether the attrmask fields must be tested true or false
080575042aba2197b425ebfd52061dea061a9aa1xy * ie. for ?A the attrmask is set and the attrbit is set,
080575042aba2197b425ebfd52061dea061a9aa1xy * for ?!A the attrmask is set and the attrbit is clear.
080575042aba2197b425ebfd52061dea061a9aa1xy */
25f2d433de915875c8393f0b0dc14aa155997ad0xy } else if (*Start_tok == '?') {
080575042aba2197b425ebfd52061dea061a9aa1xy if (b_attr) {
0f70fbf80d71251e7928b3122fb4848c2f92a5c6xy eprintf(ofl->ofl_lml, ERR_FATAL,
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems MSG_INTL(MSG_MAP_MOREONCE), mapfile,
25f2d433de915875c8393f0b0dc14aa155997ad0xy EC_XWORD(Line_num),
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_SECFLAG));
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy b_attr = TRUE;
d5c3073dbbd835e1e9b7dca0c6c770cf3cc20afachenlu chen - Sun Microsystems - Beijing China b_bang = FALSE;
25f2d433de915875c8393f0b0dc14aa155997ad0xy Start_tok++;
25f2d433de915875c8393f0b0dc14aa155997ad0xy lowercase(Start_tok);
25f2d433de915875c8393f0b0dc14aa155997ad0xy for (; *Start_tok != '\0'; Start_tok++)
a2e9a8308e6b9832ce4d7b848660483fc31d1dc7cc switch (*Start_tok) {
7941757c1241fe30e30f921910595c8ac6af9ef1xy case '!':
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (b_bang) {
25f2d433de915875c8393f0b0dc14aa155997ad0xy eprintf(ofl->ofl_lml, ERR_FATAL,
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_BADFLAG),
25f2d433de915875c8393f0b0dc14aa155997ad0xy mapfile, EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy Start_tok);
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (S_ERROR);
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems }
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems b_bang = TRUE;
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems break;
25f2d433de915875c8393f0b0dc14aa155997ad0xy case 'a':
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (enp->ec_attrmask & SHF_ALLOC) {
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems eprintf(ofl->ofl_lml, ERR_FATAL,
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_BADFLAG),
25f2d433de915875c8393f0b0dc14aa155997ad0xy mapfile, EC_XWORD(Line_num),
25f2d433de915875c8393f0b0dc14aa155997ad0xy Start_tok);
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (S_ERROR);
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy enp->ec_attrmask |= SHF_ALLOC;
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (!b_bang)
25f2d433de915875c8393f0b0dc14aa155997ad0xy enp->ec_attrbits |= SHF_ALLOC;
25f2d433de915875c8393f0b0dc14aa155997ad0xy b_bang = FALSE;
25f2d433de915875c8393f0b0dc14aa155997ad0xy break;
25f2d433de915875c8393f0b0dc14aa155997ad0xy case 'w':
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (enp->ec_attrmask & SHF_WRITE) {
25f2d433de915875c8393f0b0dc14aa155997ad0xy eprintf(ofl->ofl_lml, ERR_FATAL,
ede5269ebe7fa3787cc9b58c3781b639c578f93dchenlu chen - Sun Microsystems - Beijing China MSG_INTL(MSG_MAP_BADFLAG),
25f2d433de915875c8393f0b0dc14aa155997ad0xy mapfile, EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy Start_tok);
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (S_ERROR);
25f2d433de915875c8393f0b0dc14aa155997ad0xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy enp->ec_attrmask |= SHF_WRITE;
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (!b_bang)
25f2d433de915875c8393f0b0dc14aa155997ad0xy enp->ec_attrbits |= SHF_WRITE;
080575042aba2197b425ebfd52061dea061a9aa1xy b_bang = FALSE;
25f2d433de915875c8393f0b0dc14aa155997ad0xy break;
1bc1c72171ee0c5d77203ddffb90219d991bd6e8guoqing zhu - Sun Microsystems - Beijing China case 'x':
1bc1c72171ee0c5d77203ddffb90219d991bd6e8guoqing zhu - Sun Microsystems - Beijing China if (enp->ec_attrmask & SHF_EXECINSTR) {
1bc1c72171ee0c5d77203ddffb90219d991bd6e8guoqing zhu - Sun Microsystems - Beijing China eprintf(ofl->ofl_lml, ERR_FATAL,
1bc1c72171ee0c5d77203ddffb90219d991bd6e8guoqing zhu - Sun Microsystems - Beijing China MSG_INTL(MSG_MAP_BADFLAG),
1bc1c72171ee0c5d77203ddffb90219d991bd6e8guoqing zhu - Sun Microsystems - Beijing China mapfile, EC_XWORD(Line_num),
1bc1c72171ee0c5d77203ddffb90219d991bd6e8guoqing zhu - Sun Microsystems - Beijing China Start_tok);
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc return (S_ERROR);
caf05df5c10c960028f122b1b02a3f7d8f892c31Miles Xu, Sun Microsystems }
592a4d85662412bade15f3d9e9e0cbcf8514348ccc enp->ec_attrmask |= SHF_EXECINSTR;
592a4d85662412bade15f3d9e9e0cbcf8514348ccc if (!b_bang)
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc enp->ec_attrbits |=
25f2d433de915875c8393f0b0dc14aa155997ad0xy SHF_EXECINSTR;
25f2d433de915875c8393f0b0dc14aa155997ad0xy b_bang = FALSE;
25f2d433de915875c8393f0b0dc14aa155997ad0xy break;
7941757c1241fe30e30f921910595c8ac6af9ef1xy default:
25f2d433de915875c8393f0b0dc14aa155997ad0xy eprintf(ofl->ofl_lml, ERR_FATAL,
25f2d433de915875c8393f0b0dc14aa155997ad0xy MSG_INTL(MSG_MAP_BADFLAG),
25f2d433de915875c8393f0b0dc14aa155997ad0xy mapfile, EC_XWORD(Line_num),
25f2d433de915875c8393f0b0dc14aa155997ad0xy Start_tok);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (S_ERROR);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
47b7744cbea59975a6b583125b7ed1ff2ac45313yy /*
47b7744cbea59975a6b583125b7ed1ff2ac45313yy * Section name.
47b7744cbea59975a6b583125b7ed1ff2ac45313yy */
47b7744cbea59975a6b583125b7ed1ff2ac45313yy } else {
47b7744cbea59975a6b583125b7ed1ff2ac45313yy if (b_name) {
47b7744cbea59975a6b583125b7ed1ff2ac45313yy eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_MOREONCE), mapfile,
25f2d433de915875c8393f0b0dc14aa155997ad0xy EC_XWORD(Line_num),
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SECNAME));
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
25f2d433de915875c8393f0b0dc14aa155997ad0xy b_name = TRUE;
080575042aba2197b425ebfd52061dea061a9aa1xy if ((enp->ec_name =
25f2d433de915875c8393f0b0dc14aa155997ad0xy libld_malloc(strlen(Start_tok) + 1)) == 0)
7941757c1241fe30e30f921910595c8ac6af9ef1xy return (S_ERROR);
7941757c1241fe30e30f921910595c8ac6af9ef1xy (void) strcpy((char *)enp->ec_name, Start_tok);
080575042aba2197b425ebfd52061dea061a9aa1xy /*
25f2d433de915875c8393f0b0dc14aa155997ad0xy * get the index for text reordering
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy /* LINTED */
080575042aba2197b425ebfd52061dea061a9aa1xy enp->ec_ndx = (Word)++index;
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy }
080575042aba2197b425ebfd52061dea061a9aa1xy if (tok == TK_COLON) {
080575042aba2197b425ebfd52061dea061a9aa1xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * File names.
9b6541b318d01d0d83bfb98699a7f09e35f37951gl */
080575042aba2197b425ebfd52061dea061a9aa1xy while ((tok = gettoken(ofl, mapfile, 0)) != TK_SEMICOLON) {
080575042aba2197b425ebfd52061dea061a9aa1xy char *file;
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy if (tok != TK_STRING) {
080575042aba2197b425ebfd52061dea061a9aa1xy if (tok != TK_ERROR)
0c56b8d9d1c30af2e78d0a6fd8a6a70aa5310099changqing li - Sun Microsystems - Beijing China eprintf(ofl->ofl_lml, ERR_FATAL,
0c56b8d9d1c30af2e78d0a6fd8a6a70aa5310099changqing li - Sun Microsystems - Beijing China MSG_INTL(MSG_MAP_MALFORM), mapfile,
0c56b8d9d1c30af2e78d0a6fd8a6a70aa5310099changqing li - Sun Microsystems - Beijing China EC_XWORD(Line_num));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy }
43a176879122f7764767ab85eb539f89d65cdd67Miles Xu, Sun Microsystems if ((file =
080575042aba2197b425ebfd52061dea061a9aa1xy libld_malloc(strlen(Start_tok) + 1)) == 0)
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy (void) strcpy(file, Start_tok);
c7770590c6dc06be2588a5c21427e2d823baa989mx if (list_appendc(&(enp->ec_files), file) == 0)
c7770590c6dc06be2588a5c21427e2d823baa989mx return (S_ERROR);
c7770590c6dc06be2588a5c21427e2d823baa989mx }
c7770590c6dc06be2588a5c21427e2d823baa989mx }
3d15c084da89e6f689f1804f3e2e600e5376c4e1chenlu chen - Sun Microsystems - Beijing China return (1);
080575042aba2197b425ebfd52061dea061a9aa1xy}
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy/*
080575042aba2197b425ebfd52061dea061a9aa1xy * Obtain a pseudo input file descriptor to assign to a mapfile. This is
080575042aba2197b425ebfd52061dea061a9aa1xy * required any time a symbol is generated. First traverse the input file
080575042aba2197b425ebfd52061dea061a9aa1xy * descriptors looking for a match. As all mapfile processing occurs before
080575042aba2197b425ebfd52061dea061a9aa1xy * any real input file processing this list is going to be small and we don't
25f2d433de915875c8393f0b0dc14aa155997ad0xy * need to do any filename clash checking.
25f2d433de915875c8393f0b0dc14aa155997ad0xy */
25f2d433de915875c8393f0b0dc14aa155997ad0xystatic Ifl_desc *
25f2d433de915875c8393f0b0dc14aa155997ad0xymap_ifl(const char *mapfile, Ofl_desc *ofl)
25f2d433de915875c8393f0b0dc14aa155997ad0xy{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng Ifl_desc *ifl;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng Listnode *lnp;
4914a7d0d1ee59f8cc21b19bfd7979cb65681eacyy
4914a7d0d1ee59f8cc21b19bfd7979cb65681eacyy for (LIST_TRAVERSE(&ofl->ofl_objs, lnp, ifl))
4914a7d0d1ee59f8cc21b19bfd7979cb65681eacyy if (strcmp(ifl->ifl_name, mapfile) == 0)
4914a7d0d1ee59f8cc21b19bfd7979cb65681eacyy return (ifl);
4914a7d0d1ee59f8cc21b19bfd7979cb65681eacyy
4914a7d0d1ee59f8cc21b19bfd7979cb65681eacyy if ((ifl = libld_calloc(sizeof (Ifl_desc), 1)) == 0)
4914a7d0d1ee59f8cc21b19bfd7979cb65681eacyy return ((Ifl_desc *)S_ERROR);
4914a7d0d1ee59f8cc21b19bfd7979cb65681eacyy ifl->ifl_name = mapfile;
4914a7d0d1ee59f8cc21b19bfd7979cb65681eacyy ifl->ifl_flags = (FLG_IF_MAPFILE | FLG_IF_NEEDED | FLG_IF_FILEREF);
9b6541b318d01d0d83bfb98699a7f09e35f37951gl if ((ifl->ifl_ehdr = libld_calloc(sizeof (Ehdr), 1)) == 0)
9b6541b318d01d0d83bfb98699a7f09e35f37951gl return ((Ifl_desc *)S_ERROR);
9b6541b318d01d0d83bfb98699a7f09e35f37951gl ifl->ifl_ehdr->e_type = ET_REL;
9b6541b318d01d0d83bfb98699a7f09e35f37951gl
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc if (list_appendc(&ofl->ofl_objs, ifl) == 0)
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc return ((Ifl_desc *)S_ERROR);
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc else
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc return (ifl);
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc}
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc/*
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini * Process a mapfile size symbol definition.
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini * segment_name @ symbol_name;
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini */
4045d94132614e1de2073685a6cdd4fbd86bec33sowministatic uintptr_t
4045d94132614e1de2073685a6cdd4fbd86bec33sowminimap_atsign(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl)
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini{
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini Sym *sym; /* New symbol pointer */
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini Sym_desc *sdp; /* New symbol node pointer */
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini Ifl_desc *ifl; /* Dummy input file structure */
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini Token tok; /* Current token. */
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini avl_index_t where;
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini if ((tok = gettoken(ofl, mapfile, 0)) != TK_STRING) {
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini if (tok != TK_ERROR)
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini eprintf(ofl->ofl_lml, ERR_FATAL,
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini MSG_INTL(MSG_MAP_EXPSYM_1), mapfile,
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini EC_XWORD(Line_num));
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini return (S_ERROR);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini }
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini if (sgp->sg_sizesym != NULL) {
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_MAP_SEGSIZE),
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini mapfile, EC_XWORD(Line_num), sgp->sg_name);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini return (S_ERROR);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini }
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini /*
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini * Make sure we have a pseudo file descriptor to associate to the
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini * symbol.
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini */
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini if ((ifl = map_ifl(mapfile, ofl)) == (Ifl_desc *)S_ERROR)
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini return (S_ERROR);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
25f2d433de915875c8393f0b0dc14aa155997ad0xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * Make sure the symbol doesn't already exist. It is possible that the
080575042aba2197b425ebfd52061dea061a9aa1xy * symbol has been scoped or versioned, in which case it does exist
080575042aba2197b425ebfd52061dea061a9aa1xy * but we can freely update it here.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy if ((sdp = ld_sym_find(Start_tok, SYM_NOHASH, &where, ofl)) == NULL) {
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems char *name;
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems Word hval;
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems
080575042aba2197b425ebfd52061dea061a9aa1xy if ((name = libld_malloc(strlen(Start_tok) + 1)) == 0)
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems (void) strcpy(name, Start_tok);
25f2d433de915875c8393f0b0dc14aa155997ad0xy
25f2d433de915875c8393f0b0dc14aa155997ad0xy if ((sym = libld_calloc(sizeof (Sym), 1)) == 0)
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
080575042aba2197b425ebfd52061dea061a9aa1xy sym->st_shndx = SHN_ABS;
25f2d433de915875c8393f0b0dc14aa155997ad0xy sym->st_size = 0;
25f2d433de915875c8393f0b0dc14aa155997ad0xy sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
25f2d433de915875c8393f0b0dc14aa155997ad0xy
080575042aba2197b425ebfd52061dea061a9aa1xy DBG_CALL(Dbg_map_size_new(ofl->ofl_lml, name));
ae6aa22afeb444ae208c287e7227a4a7c877f17aVenugopal Iyer /* LINTED */
25f2d433de915875c8393f0b0dc14aa155997ad0xy hval = (Word)elf_hash(name);
080575042aba2197b425ebfd52061dea061a9aa1xy if ((sdp = ld_sym_enter(name, sym, hval, ifl, ofl, 0, SHN_ABS,
080575042aba2197b425ebfd52061dea061a9aa1xy (FLG_SY_SPECSEC | FLG_SY_GLOBREF), 0, &where)) ==
25f2d433de915875c8393f0b0dc14aa155997ad0xy (Sym_desc *)S_ERROR)
25f2d433de915875c8393f0b0dc14aa155997ad0xy return (S_ERROR);
25f2d433de915875c8393f0b0dc14aa155997ad0xy sdp->sd_flags &= ~FLG_SY_CLEAN;
080575042aba2197b425ebfd52061dea061a9aa1xy DBG_CALL(Dbg_map_symbol(ofl, sdp));
25f2d433de915875c8393f0b0dc14aa155997ad0xy } else {
25f2d433de915875c8393f0b0dc14aa155997ad0xy sym = sdp->sd_sym;
25f2d433de915875c8393f0b0dc14aa155997ad0xy
25f2d433de915875c8393f0b0dc14aa155997ad0xy if (sym->st_shndx == SHN_UNDEF) {
25f2d433de915875c8393f0b0dc14aa155997ad0xy sdp->sd_shndx = sym->st_shndx = SHN_ABS;
080575042aba2197b425ebfd52061dea061a9aa1xy sdp->sd_flags |= FLG_SY_SPECSEC;
caf05df5c10c960028f122b1b02a3f7d8f892c31Miles Xu, Sun Microsystems sym->st_size = 0;
080575042aba2197b425ebfd52061dea061a9aa1xy sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
9b6541b318d01d0d83bfb98699a7f09e35f37951gl
9b6541b318d01d0d83bfb98699a7f09e35f37951gl sdp->sd_flags &= ~FLG_SY_MAPREF;
9b6541b318d01d0d83bfb98699a7f09e35f37951gl
837c1ac4e72b7d86278cca88b1075af557f7d161Stephen Hanson DBG_CALL(Dbg_map_size_old(ofl, sdp));
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc } else {
9ce7e93c0e8e6d2b400f40e9c5742b1d6682611ecc eprintf(ofl->ofl_lml, ERR_FATAL,
080575042aba2197b425ebfd52061dea061a9aa1xy MSG_INTL(MSG_MAP_SYMDEF1), mapfile,
080575042aba2197b425ebfd52061dea061a9aa1xy EC_XWORD(Line_num), demangle(sdp->sd_name),
080575042aba2197b425ebfd52061dea061a9aa1xy sdp->sd_file->ifl_name,
0f70fbf80d71251e7928b3122fb4848c2f92a5c6xy MSG_INTL(MSG_MAP_DIFF_SYMMUL));
080575042aba2197b425ebfd52061dea061a9aa1xy return (S_ERROR);
54e0d7a5e8285a3f01a0db8db1246ac7cac94d81Miles Xu, Sun Microsystems }
ea6b684a18957883cb91b3d22a9d989f986e5a32yy }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
080575042aba2197b425ebfd52061dea061a9aa1xy /*
080575042aba2197b425ebfd52061dea061a9aa1xy * Assign the symbol to the segment.
080575042aba2197b425ebfd52061dea061a9aa1xy */
080575042aba2197b425ebfd52061dea061a9aa1xy sgp->sg_sizesym = sdp;
080575042aba2197b425ebfd52061dea061a9aa1xy
080575042aba2197b425ebfd52061dea061a9aa1xy if (gettoken(ofl, mapfile, 0) != TK_SEMICOLON) {
if (tok != TK_ERROR)
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_EXPSCOL), mapfile,
EC_XWORD(Line_num));
return (S_ERROR);
}
return (1);
}
static uintptr_t
map_pipe(Ofl_desc *ofl, const char *mapfile, Sg_desc *sgp)
{
char *sec_name; /* section name */
Token tok; /* current token. */
Sec_order *sc_order;
static Word index = 0; /* used to maintain a increasing */
/* index for section ordering. */
if ((tok = gettoken(ofl, mapfile, 0)) != TK_STRING) {
if (tok != TK_ERROR)
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_EXPSEC), mapfile,
EC_XWORD(Line_num));
return (S_ERROR);
}
if ((sec_name = libld_malloc(strlen(Start_tok) + 1)) == 0)
return (S_ERROR);
(void) strcpy(sec_name, Start_tok);
if ((sc_order = libld_malloc(sizeof (Sec_order))) == 0)
return (S_ERROR);
sc_order->sco_secname = sec_name;
sc_order->sco_index = ++index;
if (aplist_append(&sgp->sg_secorder, sc_order,
AL_CNT_SG_SECORDER) == NULL)
return (S_ERROR);
ofl->ofl_flags |= FLG_OF_SECORDER;
DBG_CALL(Dbg_map_pipe(ofl->ofl_lml, sgp, sec_name, index));
if ((tok = gettoken(ofl, mapfile, 0)) != TK_SEMICOLON) {
if (tok != TK_ERROR)
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_EXPSCOL), mapfile,
EC_XWORD(Line_num));
return (S_ERROR);
}
return (1);
}
/*
* Process a mapfile library specification definition.
* shared_object_name - shared object definition
* shared object definition : [ shared object type [ = SONAME ]]
* [ versions ];
*/
static uintptr_t
map_dash(const char *mapfile, char *name, Ofl_desc *ofl)
{
char *version;
Token tok;
Sdf_desc *sdf;
Sdv_desc *sdv;
enum {
MD_NONE = 0,
MD_SPECVERS,
MD_ADDVERS,
MD_NEEDED
} dolkey = MD_NONE;
/*
* If a shared object definition for this file already exists use it,
* otherwise allocate a new descriptor.
*/
if ((sdf = sdf_find(name, &ofl->ofl_socntl)) == 0) {
if ((sdf = sdf_add(name, &ofl->ofl_socntl)) ==
(Sdf_desc *)S_ERROR)
return (S_ERROR);
sdf->sdf_rfile = mapfile;
}
/*
* Get the shared object descriptor string.
*/
while ((tok = gettoken(ofl, mapfile, 0)) != TK_SEMICOLON) {
if ((tok != TK_STRING) && (tok != TK_EQUAL)) {
if (tok != TK_ERROR)
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_EXPSO), mapfile,
EC_XWORD(Line_num));
return (S_ERROR);
}
/*
* Determine if the library type is accompanied with a SONAME
* definition.
*/
if (tok == TK_EQUAL) {
if ((tok = gettoken(ofl, mapfile, 0)) != TK_STRING) {
if (tok != TK_ERROR)
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_EXPSO), mapfile,
EC_XWORD(Line_num));
return (S_ERROR);
}
switch (dolkey) {
case MD_NEEDED:
if (sdf->sdf_flags & FLG_SDF_SONAME) {
eprintf(ofl->ofl_lml, ERR_WARNING,
MSG_INTL(MSG_MAP_MULSONAME),
mapfile, EC_XWORD(Line_num), name,
sdf->sdf_soname, Start_tok);
dolkey = MD_NONE;
continue;
}
if ((sdf->sdf_soname =
libld_malloc(strlen(Start_tok) + 1)) == 0)
return (S_ERROR);
(void) strcpy((char *)sdf->sdf_soname,
Start_tok);
sdf->sdf_flags |= FLG_SDF_SONAME;
break;
case MD_SPECVERS:
case MD_ADDVERS:
if ((sdv = libld_calloc(
sizeof (Sdv_desc), 1)) == 0)
return (S_ERROR);
if (dolkey == MD_SPECVERS)
sdf->sdf_flags |= FLG_SDF_SPECVER;
else
sdf->sdf_flags |= FLG_SDF_ADDVER;
if ((sdf->sdf_flags & (FLG_SDF_SPECVER |
FLG_SDF_ADDVER)) == (FLG_SDF_SPECVER |
FLG_SDF_ADDVER)) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_INCOMPFLG),
mapfile, EC_XWORD(Line_num),
sdf->sdf_name);
return (S_ERROR);
}
if ((version =
libld_malloc(strlen(Start_tok) + 1)) == 0)
return (S_ERROR);
(void) strcpy(version, Start_tok);
sdv->sdv_name = version;
sdv->sdv_ref = mapfile;
if (list_appendc(&sdf->sdf_verneed, sdv) == 0)
return (S_ERROR);
break;
case MD_NONE:
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_UNEXTOK), mapfile,
EC_XWORD(Line_num), '=');
return (S_ERROR);
}
dolkey = MD_NONE;
continue;
}
/*
* A shared object type has been specified. This may also be
* accompanied by an SONAME redefinition (see above).
*/
if (*Start_tok == '$') {
if (dolkey != MD_NONE) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_UNEXTOK), mapfile,
EC_XWORD(Line_num), '$');
return (S_ERROR);
}
Start_tok++;
lowercase(Start_tok);
if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_NEED)) == 0)
dolkey = MD_NEEDED;
else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_SPECVERS)) == 0)
dolkey = MD_SPECVERS;
else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_ADDVERS)) == 0)
dolkey = MD_ADDVERS;
else {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_UNKSOTYP), mapfile,
EC_XWORD(Line_num), Start_tok);
return (S_ERROR);
}
continue;
}
/*
* shared object version requirement.
*/
if ((version = libld_malloc(strlen(Start_tok) + 1)) == 0)
return (S_ERROR);
(void) strcpy(version, Start_tok);
if ((sdv = libld_calloc(sizeof (Sdv_desc), 1)) == 0)
return (S_ERROR);
sdv->sdv_name = version;
sdv->sdv_ref = mapfile;
sdf->sdf_flags |= FLG_SDF_SELECT;
if (list_appendc(&sdf->sdf_vers, sdv) == 0)
return (S_ERROR);
}
DBG_CALL(Dbg_map_dash(ofl->ofl_lml, name, sdf));
return (1);
}
/*
* Process a symbol definition. Historically, this originated from processing
* a version definition. However, this has evolved into a generic means of
* defining symbol references and definitions (see Defining Additional Symbols
* in the Linker and Libraries guide for the complete syntax).
*
* [ name ] {
* scope:
* symbol [ = [ type ] [ value ] [ size ] [ attribute ] ];
* } [ dependency ];
*
*/
#define FLG_SCOPE_HIDD 0 /* symbol defined hidden/local */
#define FLG_SCOPE_DFLT 1 /* symbol defined default/global */
#define FLG_SCOPE_PROT 2 /* symbol defined protected/symbolic */
#define FLG_SCOPE_EXPT 3 /* symbol defined exported */
#define FLG_SCOPE_SNGL 4 /* symbol defined singleton */
#define FLG_SCOPE_ELIM 5 /* symbol defined eliminate */
static uintptr_t
map_version(const char *mapfile, char *name, Ofl_desc *ofl)
{
Token tok;
Sym *sym;
int scope = FLG_SCOPE_DFLT, errcnt = 0;
Ver_desc *vdp;
Word hash;
Ifl_desc *ifl;
avl_index_t where;
/*
* If we're generating segments within the image then any symbol
* reductions will be processed (ie. applied to relocations and symbol
* table entries). Otherwise (when creating a relocatable object) any
* versioning information is simply recorded for use in a later
* (segment generating) link-edit.
*/
if (ofl->ofl_flags & FLG_OF_RELOBJ)
ofl->ofl_flags |= FLG_OF_VERDEF;
/*
* If this is a new mapfile reference generate an input file descriptor
* to represent it. Otherwise this must simply be a new version within
* the mapfile we've previously been processing, in this case continue
* to use the original input file descriptor.
*/
if ((ifl = map_ifl(mapfile, ofl)) == (Ifl_desc *)S_ERROR)
return (S_ERROR);
/*
* If no version descriptors have yet been set up, initialize a base
* version to represent the output file itself. This `base' version
* catches any internally generated symbols (_end, _etext, etc.) and
* serves to initialize the output version descriptor count.
*/
if (ofl->ofl_vercnt == 0) {
if (ld_vers_base(ofl) == (Ver_desc *)S_ERROR)
return (S_ERROR);
}
/*
* If this definition has an associated version name then generate a
* new version descriptor and an associated version symbol index table.
*/
if (name) {
ofl->ofl_flags |= FLG_OF_VERDEF;
/*
* Traverse the present version descriptor list to see if there
* is already one of the same name, otherwise create a new one.
*/
/* LINTED */
hash = (Word)elf_hash(name);
if ((vdp = ld_vers_find(name, hash, &ofl->ofl_verdesc)) == 0) {
if ((vdp = ld_vers_desc(name, hash,
&ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR)
return (S_ERROR);
}
/*
* Initialize any new version with an index, the file from which
* it was first referenced, and a WEAK flag (indicates that
* there are no symbols assigned to it yet).
*/
if (vdp->vd_ndx == 0) {
/* LINTED */
vdp->vd_ndx = (Half)++ofl->ofl_vercnt;
vdp->vd_file = ifl;
vdp->vd_flags = VER_FLG_WEAK;
}
} else {
/*
* If a version definition hasn't been specified assign any
* symbols to the base version.
*/
vdp = (Ver_desc *)ofl->ofl_verdesc.head->data;
}
/*
* Scan the mapfile entry picking out scoping and symbol definitions.
*/
while ((tok = gettoken(ofl, mapfile, 0)) != TK_RIGHTBKT) {
Sym_desc * sdp;
Word shndx = SHN_UNDEF;
uchar_t type = STT_NOTYPE;
Addr value = 0, size = 0;
char *_name, *filtee = 0;
Word sym_flags = 0;
Half sym_flags1 = 0;
uint_t filter = 0, novalue = 1, dftflag;
const char *conflict;
if ((tok != TK_STRING) && (tok != TK_COLON)) {
if (tok == TK_ERROR)
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_EXPSYM_2), mapfile,
EC_XWORD(Line_num));
if ((tok == TK_ERROR) || (tok == TK_EOF))
return (S_ERROR);
errcnt++;
continue;
}
if ((_name = libld_malloc(strlen(Start_tok) + 1)) == 0)
return (S_ERROR);
(void) strcpy(_name, Start_tok);
if (tok != TK_COLON) {
tok = gettoken(ofl, mapfile, 0);
if ((tok == TK_ERROR) || (tok == TK_EOF)) {
errcnt++;
continue;
}
}
/*
* Turn off the WEAK flag to indicate that definitions are
* associated with this version. It would probably be more
* accurate to only remove this flag with the specification of
* global symbols, however setting it here allows enough slop
* to compensate for the various user inputs we've seen so far.
* Only if a closed version is specified (i.e., "SUNW_1.x {};")
* will a user get a weak version (which is how we document the
* creation of weak versions).
*/
vdp->vd_flags &= ~VER_FLG_WEAK;
switch (tok) {
case TK_COLON:
/*
* Establish a new scope. All symbols added by this
* mapfile are actually global entries, and are assigned
* the scope that is presently in effect.
*
* If a protected/symbolic scope is detected, remember
* this. If a protected/symbolic scope is the only
* scope defined in this (or any other mapfiles), then
* the mode -Bsymbolic is established.
*/
if ((strcmp(MSG_ORIG(MSG_MAP_DEFAULT), _name) == 0) ||
(strcmp(MSG_ORIG(MSG_MAP_GLOBAL), _name) == 0)) {
scope = FLG_SCOPE_DFLT;
ofl->ofl_flags |= FLG_OF_MAPGLOB;
} else if ((strcmp(MSG_ORIG(MSG_MAP_HIDDEN),
_name) == 0) ||
(strcmp(MSG_ORIG(MSG_STR_LOCAL), _name) == 0)) {
scope = FLG_SCOPE_HIDD;
} else if ((strcmp(MSG_ORIG(MSG_MAP_PROTECTED),
_name) == 0) ||
(strcmp(MSG_ORIG(MSG_STR_SYMBOLIC), _name) == 0)) {
scope = FLG_SCOPE_PROT;
ofl->ofl_flags |= FLG_OF_MAPSYMB;
} else if (strcmp(MSG_ORIG(MSG_STR_EXPORTED),
_name) == 0) {
scope = FLG_SCOPE_EXPT;
} else if (strcmp(MSG_ORIG(MSG_STR_SINGLETON),
_name) == 0) {
scope = FLG_SCOPE_SNGL;
ofl->ofl_flags |= FLG_OF_MAPGLOB;
} else if (strcmp(MSG_ORIG(MSG_STR_ELIMINATE),
_name) == 0) {
scope = FLG_SCOPE_ELIM;
} else {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_UNKSYMSCO), mapfile,
EC_XWORD(Line_num), _name);
errcnt++;
}
continue;
case TK_EQUAL:
/*
* A full blown symbol definition follows.
* Determine the symbol type and any virtual address or
* alignment specified and then fall through to process
* the entire symbols information.
*/
while ((tok = gettoken(ofl, mapfile, 0)) !=
TK_SEMICOLON) {
if ((tok == TK_ERROR) || (tok == TK_EOF))
return (S_ERROR);
/*
* If we had previously seen a filter or
* auxiliary filter requirement, the next string
* is the filtee itself.
*/
if (filter) {
if (filtee) {
/* BEGIN CSTYLED */
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_MULTFILTEE),
mapfile, EC_XWORD(Line_num),
_name);
errcnt++;
continue;
/* END CSTYLED */
}
if ((filtee = libld_malloc(
strlen(Start_tok) + 1)) == 0)
return (S_ERROR);
(void) strcpy(filtee, Start_tok);
filter = 0;
continue;
}
/*
* Determine any Value or Size attributes.
*/
lowercase(Start_tok);
if (Start_tok[0] == 'v' ||
Start_tok[0] == 's') {
char *end_tok;
Lword number;
if ((number = (Lword)STRTOADDR(
&Start_tok[1], &end_tok, 0)) ==
XWORD_MAX) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_SEGADDR),
mapfile, EC_XWORD(Line_num),
Start_tok,
MSG_INTL(MSG_MAP_EXCLIMIT));
errcnt++;
continue;
}
if (end_tok !=
strchr(Start_tok, '\0')) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_SEGADDR),
mapfile, EC_XWORD(Line_num),
Start_tok,
MSG_INTL(MSG_MAP_NOBADFRM));
errcnt++;
continue;
}
switch (*Start_tok) {
case 'v':
/* BEGIN CSTYLED */
if (value) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_MOREONCE),
mapfile, EC_XWORD(Line_num),
MSG_INTL(MSG_MAP_SYMVAL));
errcnt++;
continue;
}
/* LINTED */
value = (Addr)number;
novalue = 0;
break;
/* END CSTYLED */
case 's':
/* BEGIN CSTYLED */
if (size) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_MOREONCE),
mapfile, EC_XWORD(Line_num),
MSG_INTL(MSG_MAP_SYMSIZE));
errcnt++;
continue;
}
/* LINTED */
size = (Addr)number;
break;
/* END CSTYLED */
}
} else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_FUNCTION)) == 0) {
shndx = SHN_ABS;
sym_flags |= FLG_SY_SPECSEC;
type = STT_FUNC;
} else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_DATA)) == 0) {
shndx = SHN_ABS;
sym_flags |= FLG_SY_SPECSEC;
type = STT_OBJECT;
} else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_COMMON)) == 0) {
shndx = SHN_COMMON;
sym_flags |= FLG_SY_SPECSEC;
type = STT_OBJECT;
} else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_PARENT)) == 0) {
sym_flags |= FLG_SY_PARENT;
ofl->ofl_flags |= FLG_OF_SYMINFO;
} else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_EXTERN)) == 0) {
sym_flags |= FLG_SY_EXTERN;
ofl->ofl_flags |= FLG_OF_SYMINFO;
} else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_DIRECT)) == 0) {
sym_flags1 |= FLG_SY1_DIR;
ofl->ofl_flags |= FLG_OF_SYMINFO;
} else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_NODIRECT)) == 0) {
sym_flags1 |= FLG_SY1_NDIR;
ofl->ofl_flags |= FLG_OF_SYMINFO;
ofl->ofl_flags1 |= FLG_OF1_NDIRECT;
} else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_FILTER)) == 0) {
dftflag = filter = FLG_SY_STDFLTR;
sym_flags |= FLG_SY_STDFLTR;
ofl->ofl_flags |= FLG_OF_SYMINFO;
continue;
} else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_AUXILIARY)) == 0) {
dftflag = filter = FLG_SY_AUXFLTR;
sym_flags |= FLG_SY_AUXFLTR;
ofl->ofl_flags |= FLG_OF_SYMINFO;
continue;
} else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_INTERPOSE)) == 0) {
if (!(ofl->ofl_flags & FLG_OF_EXEC)) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_NOINTPOSE),
mapfile,
EC_XWORD(Line_num));
errcnt++;
continue;
}
sym_flags |= FLG_SY_INTPOSE;
ofl->ofl_flags |= FLG_OF_SYMINFO;
ofl->ofl_dtflags_1 |= DF_1_SYMINTPOSE;
continue;
} else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_DYNSORT)) == 0) {
sym_flags |= FLG_SY_DYNSORT;
sym_flags &= ~FLG_SY_NODYNSORT;
continue;
} else if (strcmp(Start_tok,
MSG_ORIG(MSG_MAP_NODYNSORT)) == 0) {
sym_flags &= ~FLG_SY_DYNSORT;
sym_flags |= FLG_SY_NODYNSORT;
continue;
} else {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_UNKSYMDEF),
mapfile, EC_XWORD(Line_num),
Start_tok);
errcnt++;
continue;
}
}
/* FALLTHROUGH */
case TK_SEMICOLON:
/*
* The special auto-reduction directive `*' can be
* specified in hidden/local, and eliminate scope. This
* directive indicates that all symbols processed that
* are not explicitly defined to be global are to be
* reduced to hidden/local scope in, or eliminated from,
* the output image.
*
* An auto-reduction directive also implies that a
* version definition be created, as the user has
* effectively defined an interface.
*/
if (*_name == '*') {
if (scope == FLG_SCOPE_HIDD)
ofl->ofl_flags |=
(FLG_OF_VERDEF | FLG_OF_AUTOLCL);
else if (scope == FLG_SCOPE_ELIM) {
ofl->ofl_flags |=
(FLG_OF_VERDEF | FLG_OF_AUTOELM);
}
continue;
}
/*
* Add the new symbol. It should be noted that all
* symbols added by the mapfile start out with global
* scope, thus they will fall through the normal symbol
* resolution process. Symbols defined as locals will
* be reduced in scope after all input file processing.
*/
/* LINTED */
hash = (Word)elf_hash(_name);
DBG_CALL(Dbg_map_version(ofl->ofl_lml, name, _name,
scope));
if ((sdp = ld_sym_find(_name, hash, &where,
ofl)) == NULL) {
if ((sym = libld_calloc(sizeof (Sym), 1)) == 0)
return (S_ERROR);
/*
* Make sure any parent or external declarations
* fall back to references.
*/
if (sym_flags &
(FLG_SY_PARENT | FLG_SY_EXTERN)) {
/*
* Turn it into a reference by setting
* the section index to UNDEF.
*/
sym->st_shndx = shndx = SHN_UNDEF;
/*
* It is wrong to to specify size
* or value for an external symbol.
*/
if ((novalue == 0) || (size != 0)) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_NOEXVLSZ),
mapfile,
EC_XWORD(Line_num));
errcnt++;
continue;
}
} else {
sym->st_shndx = (Half)shndx;
}
sym->st_value = value;
sym->st_size = size;
sym->st_info = ELF_ST_INFO(STB_GLOBAL, type);
if ((sdp = ld_sym_enter(_name, sym, hash, ifl,
ofl, 0, shndx, sym_flags, sym_flags1,
&where)) == (Sym_desc *)S_ERROR)
return (S_ERROR);
sdp->sd_flags &= ~FLG_SY_CLEAN;
/*
* Identify any references. FLG_SY_MAPREF is
* turned off once a relocatable object with
* the same symbol is found, thus the existence
* of FLG_SY_MAPREF at symbol validation is
* used to flag undefined/misspelled entries.
*/
if (sym->st_shndx == SHN_UNDEF)
sdp->sd_flags |=
(FLG_SY_MAPREF | FLG_SY_GLOBREF);
} else {
conflict = NULL;
sym = sdp->sd_sym;
/*
* If this symbol already exists, make sure this
* definition doesn't conflict with the former.
* Provided it doesn't, multiple definitions
* from different mapfiles can augment each
* other.
*/
/* BEGIN CSTYLED */
if (sym->st_value) {
if (value && (sym->st_value != value))
conflict =
MSG_INTL(MSG_MAP_DIFF_SYMVAL);
} else {
sym->st_value = value;
}
if (sym->st_size) {
if (size && (sym->st_size != size))
conflict = MSG_INTL(MSG_MAP_DIFF_SYMSZ);
} else {
sym->st_size = size;
}
if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) {
if ((type != STT_NOTYPE) &&
(ELF_ST_TYPE(sym->st_info) != type))
conflict =
MSG_INTL(MSG_MAP_DIFF_SYMTYP);
} else {
sym->st_info =
ELF_ST_INFO(STB_GLOBAL, type);
}
if (sym->st_shndx != SHN_UNDEF) {
if ((shndx != SHN_UNDEF) &&
(sym->st_shndx != shndx))
conflict =
MSG_INTL(MSG_MAP_DIFF_SYMNDX);
} else {
sdp->sd_shndx = sym->st_shndx = shndx;
}
/* END CSTYLED */
if ((sdp->sd_flags1 & MSK_SY1_GLOBAL) &&
(sdp->sd_aux->sa_overndx !=
VER_NDX_GLOBAL) &&
(vdp->vd_ndx != VER_NDX_GLOBAL) &&
(sdp->sd_aux->sa_overndx != vdp->vd_ndx)) {
conflict =
MSG_INTL(MSG_MAP_DIFF_SYMVER);
}
if (conflict) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_SYMDEF1), mapfile,
EC_XWORD(Line_num), demangle(_name),
sdp->sd_file->ifl_name, conflict);
errcnt++;
continue;
}
/*
* If this mapfile entry supplies a definition,
* indicate that the symbol is now used.
*/
if (shndx != SHN_UNDEF)
sdp->sd_flags |= FLG_SY_MAPUSED;
}
/*
* A symbol declaration that defines a size but no
* value is processed as a request to create an
* associated backing section. The intent behind this
* functionality is to provide OBJT definitions within
* filters that are not ABS. ABS symbols don't allow
* copy-relocations to be established to filter OBJT
* definitions.
*/
if ((shndx == SHN_ABS) && size && novalue) {
/* Create backing section if not there */
if (sdp->sd_isc == NULL) {
Is_desc *isp;
if (type == STT_OBJECT) {
if ((isp = ld_make_data(ofl,
size)) ==
(Is_desc *)S_ERROR)
return (S_ERROR);
} else {
if ((isp = ld_make_text(ofl,
size)) ==
(Is_desc *)S_ERROR)
return (S_ERROR);
}
sdp->sd_isc = isp;
isp->is_file = ifl;
}
/*
* Now that backing storage has been created,
* associate the symbol descriptor. Remove the
* symbols special section tag so that it will
* be assigned the correct section index as part
* of update symbol processing.
*/
sdp->sd_flags &= ~FLG_SY_SPECSEC;
sym_flags &= ~FLG_SY_SPECSEC;
}
/*
* Indicate the new symbols scope. Although the
* symbols st_other field will eventually be updated as
* part of writing out the final symbol, update the
* st_other field here to trigger better diagnostics
* during symbol validation (for example, undefined
* references that are defined symbolic in a mapfile).
*/
if (scope == FLG_SCOPE_HIDD) {
/*
* This symbol needs to be reduced to local.
*/
if (ofl->ofl_flags & FLG_OF_REDLSYM) {
sdp->sd_flags1 |=
(FLG_SY1_HIDDEN | FLG_SY1_ELIM);
sdp->sd_sym->st_other = STV_ELIMINATE;
} else {
sdp->sd_flags1 |= FLG_SY1_HIDDEN;
sdp->sd_sym->st_other = STV_HIDDEN;
}
} else if (scope == FLG_SCOPE_ELIM) {
/*
* This symbol needs to be eliminated. Note,
* the symbol is also tagged as local to trigger
* any necessary relocation processing prior
* to the symbol being eliminated.
*/
sdp->sd_flags1 |=
(FLG_SY1_HIDDEN | FLG_SY1_ELIM);
sdp->sd_sym->st_other = STV_ELIMINATE;
} else {
/*
* This symbol is explicitly defined to remain
* global.
*/
sdp->sd_flags |= sym_flags;
sdp->sd_flags1 |= sym_flags1;
/*
* Qualify any global scope.
*/
if (scope == FLG_SCOPE_SNGL) {
sdp->sd_flags1 |=
(FLG_SY1_SINGLE | FLG_SY1_NDIR);
sdp->sd_sym->st_other = STV_SINGLETON;
} else if (scope == FLG_SCOPE_PROT) {
sdp->sd_flags1 |= FLG_SY1_PROTECT;
sdp->sd_sym->st_other = STV_PROTECTED;
} else if (scope == FLG_SCOPE_EXPT) {
sdp->sd_flags1 |= FLG_SY1_EXPORT;
sdp->sd_sym->st_other = STV_EXPORTED;
} else
sdp->sd_flags1 |= FLG_SY1_DEFAULT;
/*
* Record the present version index for later
* potential versioning.
*/
if ((sdp->sd_aux->sa_overndx == 0) ||
(sdp->sd_aux->sa_overndx == VER_NDX_GLOBAL))
sdp->sd_aux->sa_overndx = vdp->vd_ndx;
vdp->vd_flags |= FLG_VER_REFER;
}
conflict = NULL;
/*
* Carry out some validity checks to ensure incompatible
* symbol characteristics have not been defined.
* These checks are carried out after symbols are added
* or resolved, to catch single instance, and
* multi-instance definition inconsistencies.
*/
if ((sdp->sd_flags1 &
(FLG_SY1_HIDDEN | FLG_SY1_ELIM)) &&
((scope != FLG_SCOPE_HIDD) &&
(scope != FLG_SCOPE_ELIM))) {
conflict = MSG_INTL(MSG_MAP_DIFF_SYMLCL);
} else if (((sdp->sd_flags1 & FLG_SY1_SINGLE) ||
(sdp->sd_flags1 & FLG_SY1_EXPORT)) &&
((scope != FLG_SCOPE_DFLT) &&
(scope != FLG_SCOPE_EXPT) &&
(scope != FLG_SCOPE_SNGL))) {
conflict = MSG_INTL(MSG_MAP_DIFF_SYMGLOB);
} else if ((sdp->sd_flags1 & FLG_SY1_PROTECT) &&
((scope != FLG_SCOPE_DFLT) &&
(scope != FLG_SCOPE_PROT))) {
conflict = MSG_INTL(MSG_MAP_DIFF_SYMPROT);
} else if ((sdp->sd_flags1 & FLG_SY1_NDIR) &&
(scope == FLG_SCOPE_PROT)) {
conflict = MSG_INTL(MSG_MAP_DIFF_PROTNDIR);
} else if ((sdp->sd_flags1 & FLG_SY1_DIR) &&
(scope == FLG_SCOPE_SNGL)) {
conflict = MSG_INTL(MSG_MAP_DIFF_SNGLDIR);
}
if (conflict) {
/*
* Select the conflict message from either a
* single instance or multi-instance definition.
*/
if (sdp->sd_file->ifl_name == mapfile) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_SYMDEF2), mapfile,
EC_XWORD(Line_num), demangle(_name),
conflict);
} else {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_SYMDEF1), mapfile,
EC_XWORD(Line_num), demangle(_name),
sdp->sd_file->ifl_name, conflict);
}
errcnt++;
continue;
}
/*
* Indicate that this symbol has been explicitly
* contributed from a mapfile.
*/
sdp->sd_flags1 |= (FLG_SY1_MAPFILE | FLG_SY1_EXPDEF);
/*
* If we've encountered a symbol definition simulate
* that an input file has been processed - this allows
* things like filters to be created purely from a
* mapfile.
*/
if (type != STT_NOTYPE)
ofl->ofl_objscnt++;
DBG_CALL(Dbg_map_symbol(ofl, sdp));
/*
* If this symbol has an associated filtee, record the
* filtee string and associate the string index with the
* symbol. This is used later to associate the syminfo
* information with the necessary .dynamic entry.
*/
if (filter && (filtee == 0)) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_NOFILTER), mapfile,
EC_XWORD(Line_num), _name);
errcnt++;
continue;
}
if (filtee) {
Dfltr_desc * dftp;
Sfltr_desc sft;
Aliste idx, _idx, nitems;
/*
* Make sure we don't duplicate any filtee
* strings, and create a new descriptor if
* necessary.
*/
idx = nitems = alist_nitems(ofl->ofl_dtsfltrs);
for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, _idx,
dftp)) {
if ((dftflag != dftp->dft_flag) ||
(strcmp(dftp->dft_str, filtee)))
continue;
idx = _idx;
break;
}
if (idx == nitems) {
Dfltr_desc dft;
dft.dft_str = filtee;
dft.dft_flag = dftflag;
dft.dft_ndx = 0;
/*
* The following append puts the new
* item at the offset contained in
* idx, because we know idx contains
* the index of the next available slot.
*/
if (alist_append(&ofl->ofl_dtsfltrs,
&dft, sizeof (Dfltr_desc),
AL_CNT_OFL_DTSFLTRS) == NULL)
return (S_ERROR);
}
/*
* Create a new filter descriptor for this
* symbol.
*/
sft.sft_sdp = sdp;
sft.sft_idx = idx;
if (alist_append(&ofl->ofl_symfltrs,
&sft, sizeof (Sfltr_desc),
AL_CNT_OFL_SYMFLTRS) == NULL)
return (S_ERROR);
}
break;
default:
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_EXPSCOL), mapfile,
EC_XWORD(Line_num));
errcnt++;
continue;
}
}
if (errcnt)
return (S_ERROR);
/*
* Determine if any version references are provided after the close
* bracket.
*/
while ((tok = gettoken(ofl, mapfile, 0)) != TK_SEMICOLON) {
Ver_desc *_vdp;
char *_name;
if (tok != TK_STRING) {
if (tok != TK_ERROR)
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_EXPVERS), mapfile,
EC_XWORD(Line_num));
return (S_ERROR);
}
name = Start_tok;
if (vdp->vd_ndx == VER_NDX_GLOBAL) {
eprintf(ofl->ofl_lml, ERR_WARNING,
MSG_INTL(MSG_MAP_UNEXDEP), mapfile,
EC_XWORD(Line_num), name);
continue;
}
/*
* Generate a new version descriptor if it doesn't already
* exist.
*/
/* LINTED */
hash = (Word)elf_hash(name);
if ((_vdp = ld_vers_find(name, hash, &ofl->ofl_verdesc)) == 0) {
if ((_name = libld_malloc(strlen(name) + 1)) == 0)
return (S_ERROR);
(void) strcpy(_name, name);
if ((_vdp = ld_vers_desc(_name, hash,
&ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR)
return (S_ERROR);
}
/*
* Add the new version descriptor to the parent version
* descriptors reference list. Indicate the version descriptors
* first reference (used for error disgnostics if undefined
* version dependencies remain).
*/
if (ld_vers_find(name, hash, &vdp->vd_deps) == 0)
if (list_appendc(&vdp->vd_deps, _vdp) == 0)
return (S_ERROR);
if (_vdp->vd_ref == 0)
_vdp->vd_ref = vdp;
}
return (1);
}
/*
* Sort the segment list by increasing virtual address.
*/
uintptr_t
ld_sort_seg_list(Ofl_desc *ofl)
{
List seg1, seg2;
Listnode *lnp1, *lnp2, *lnp3;
Sg_desc *sgp1, *sgp2;
seg1.head = seg1.tail = seg2.head = seg2.tail = NULL;
/*
* Add the .phdr and .interp segments to our list. These segments must
* occur before any PT_LOAD segments (refer exec/elf/elf.c). Also add
* the capabilities segment. This isn't essential, but the capabilities
* section is one of the first in an object.
*/
for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
Word type = sgp1->sg_phdr.p_type;
if ((type == PT_PHDR) || (type == PT_INTERP) ||
(type == PT_SUNWCAP)) {
if (list_appendc(&seg1, sgp1) == 0)
return (S_ERROR);
}
}
/*
* Add the loadable segments to another list in sorted order.
*/
for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
DBG_CALL(Dbg_map_sort_orig(ofl->ofl_lml, sgp1));
if (sgp1->sg_phdr.p_type != PT_LOAD)
continue;
if (!(sgp1->sg_flags & FLG_SG_VADDR) ||
(sgp1->sg_flags & FLG_SG_EMPTY)) {
if (list_appendc(&seg2, sgp1) == 0)
return (S_ERROR);
} else {
if (seg2.head == NULL) {
if (list_appendc(&seg2, sgp1) == 0)
return (S_ERROR);
continue;
}
lnp3 = NULL;
for (LIST_TRAVERSE(&seg2, lnp2, sgp2)) {
if (!(sgp2->sg_flags & FLG_SG_VADDR) ||
(sgp2->sg_flags & FLG_SG_EMPTY)) {
if (lnp3 == NULL) {
if (list_prependc(&seg2,
sgp1) == 0)
return (S_ERROR);
} else {
if (list_insertc(&seg2,
sgp1, lnp3) == 0)
return (S_ERROR);
}
lnp3 = NULL;
break;
}
if (sgp1->sg_phdr.p_vaddr <
sgp2->sg_phdr.p_vaddr) {
if (lnp3 == NULL) {
if (list_prependc(&seg2,
sgp1) == 0)
return (S_ERROR);
} else {
if (list_insertc(&seg2,
sgp1, lnp3) == 0)
return (S_ERROR);
}
lnp3 = NULL;
break;
} else if (sgp1->sg_phdr.p_vaddr >
sgp2->sg_phdr.p_vaddr) {
lnp3 = lnp2;
} else {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_SEGSAME),
sgp1->sg_name, sgp2->sg_name);
return (S_ERROR);
}
}
if (lnp3 != NULL)
if (list_appendc(&seg2, sgp1) == 0)
return (S_ERROR);
}
}
/*
* Add the sorted loadable segments to our list.
*/
for (LIST_TRAVERSE(&seg2, lnp1, sgp1)) {
if (list_appendc(&seg1, sgp1) == 0)
return (S_ERROR);
}
/*
* Add all other segments to our list.
*/
for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
Word type = sgp1->sg_phdr.p_type;
if ((type != PT_PHDR) && (type != PT_INTERP) &&
(type != PT_SUNWCAP) && (type != PT_LOAD)) {
if (list_appendc(&seg1, sgp1) == 0)
return (S_ERROR);
}
}
ofl->ofl_segs.head = ofl->ofl_segs.tail = NULL;
/*
* Now rebuild the original list and process all of the
* segment/section ordering information if present.
*/
for (LIST_TRAVERSE(&seg1, lnp1, sgp1)) {
DBG_CALL(Dbg_map_sort_fini(ofl->ofl_lml, sgp1));
if (list_appendc(&ofl->ofl_segs, sgp1) == 0)
return (S_ERROR);
}
return (1);
}
/*
* Parse the mapfile.
*/
uintptr_t
ld_map_parse(const char *mapfile, Ofl_desc *ofl)
{
struct stat stat_buf; /* stat of mapfile */
int mapfile_fd; /* descriptor for mapfile */
Listnode *lnp1; /* node pointer */
Listnode *lnp2; /* node pointer */
Sg_desc *sgp1; /* seg descriptor being manipulated */
Sg_desc *sgp2; /* temp segment descriptor pointer */
Ent_desc *enp; /* Segment entrance criteria. */
Token tok; /* current token. */
Listnode *e_next = NULL;
/* next place for entrance criterion */
Boolean new_segment; /* If true, defines new segment. */
char *name;
static int num_stack = 0; /* number of stack segment */
int err;
DBG_CALL(Dbg_map_parse(ofl->ofl_lml, mapfile));
/*
* Determine if we're dealing with a file or a directory.
*/
if (stat(mapfile, &stat_buf) == -1) {
err = errno;
eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_STAT),
mapfile, strerror(err));
return (S_ERROR);
}
if (S_ISDIR(stat_buf.st_mode)) {
DIR *dirp;
struct dirent *denp;
/*
* Open the directory and interpret each visible file as a
* mapfile.
*/
if ((dirp = opendir(mapfile)) == 0)
return (1);
while ((denp = readdir(dirp)) != NULL) {
char path[PATH_MAX];
/*
* Ignore any hidden filenames. Construct the full
* pathname to the new mapfile.
*/
if (*denp->d_name == '.')
continue;
(void) snprintf(path, PATH_MAX, MSG_ORIG(MSG_STR_PATH),
mapfile, denp->d_name);
if (ld_map_parse(path, ofl) == S_ERROR)
return (S_ERROR);
}
(void) closedir(dirp);
return (1);
} else if (!S_ISREG(stat_buf.st_mode)) {
eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_NOTREG),
mapfile);
return (S_ERROR);
}
/*
* We read the entire mapfile into memory.
*/
if ((Mapspace = libld_malloc(stat_buf.st_size + 1)) == 0)
return (S_ERROR);
if ((mapfile_fd = open(mapfile, O_RDONLY)) == -1) {
err = errno;
eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
mapfile, strerror(err));
return (S_ERROR);
}
if (read(mapfile_fd, Mapspace, stat_buf.st_size) != stat_buf.st_size) {
err = errno;
eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_READ),
mapfile, strerror(err));
return (S_ERROR);
}
Mapspace[stat_buf.st_size] = '\0';
nextchr = Mapspace;
/*
* Set up any global variables, the line number counter and file name.
*/
Line_num = 1;
/*
* We now parse the mapfile until the gettoken routine returns EOF.
*/
while ((tok = gettoken(ofl, mapfile, 1)) != TK_EOF) {
int ndx = -1;
/*
* Don't know which segment yet.
*/
sgp1 = NULL;
/*
* At this point we are at the beginning of a line, and the
* variable `Start_tok' points to the first string on the line.
* All mapfile entries start with some string token except it
* is possible for a scoping definition to start with `{'.
*/
if (tok == TK_LEFTBKT) {
if (map_version(mapfile, (char *)0, ofl) == S_ERROR)
return (S_ERROR);
continue;
}
if (tok != TK_STRING) {
if (tok != TK_ERROR)
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_EXPSEGNAM), mapfile,
EC_XWORD(Line_num));
return (S_ERROR);
}
/*
* Save the initial token.
*/
if ((name = libld_malloc(strlen(Start_tok) + 1)) == 0)
return (S_ERROR);
(void) strcpy(name, Start_tok);
/*
* Now check the second character on the line. The special `-'
* and `{' characters do not involve any segment manipulation so
* we handle them first.
*/
tok = gettoken(ofl, mapfile, 0);
if ((tok == TK_ERROR) || (tok == TK_EOF))
return (S_ERROR);
if (tok == TK_DASH) {
if (map_dash(mapfile, name, ofl) == S_ERROR)
return (S_ERROR);
continue;
}
if (tok == TK_LEFTBKT) {
if (map_version(mapfile, name, ofl) == S_ERROR)
return (S_ERROR);
continue;
}
/*
* If we're here we need to interpret the first string as a
* segment name. Find the segment named in the token.
*/
for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp2)) {
ndx++;
if (strcmp(sgp2->sg_name, name) == 0) {
sgp1 = sgp2;
sgp2->sg_flags &= ~FLG_SG_DISABLED;
new_segment = FALSE;
break;
}
}
/*
* If the second token is a '|' then we had better
* of found a segment. It is illegal to perform
* section within segment ordering before the segment
* has been declared.
*/
if (tok == TK_PIPE) {
if (sgp1 == NULL) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_SECINSEG), mapfile,
EC_XWORD(Line_num), name);
return (S_ERROR);
} else {
if (map_pipe(ofl, mapfile, sgp1) == S_ERROR)
return (S_ERROR);
continue;
}
}
/*
* If segment is still NULL then it does not exist. Create a
* new segment, and leave its values as 0 so that map_equal()
* can detect changing attributes.
*/
if (sgp1 == NULL) {
if ((sgp1 = libld_calloc(sizeof (Sg_desc),
1)) == 0)
return (S_ERROR);
sgp1->sg_phdr.p_type = PT_NULL;
sgp1->sg_name = name;
new_segment = TRUE;
ndx = -1;
}
if ((strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_INTERP)) == 0) ||
(strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_LD_DYNAMIC)) ==
0)) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_SEGRESV), mapfile,
EC_XWORD(Line_num));
return (S_ERROR);
}
/*
* Now check the second token from the input line.
*/
if (tok == TK_EQUAL) {
if (strcmp(sgp1->sg_name,
MSG_ORIG(MSG_STR_HWCAP_1)) == 0) {
if (map_cap(mapfile, CA_SUNW_HW_1,
ofl) == S_ERROR)
return (S_ERROR);
DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml,
CA_SUNW_HW_1, ofl->ofl_hwcap_1,
ld_targ.t_m.m_mach));
continue;
} else if (strcmp(sgp1->sg_name,
MSG_ORIG(MSG_STR_SFCAP_1)) == 0) {
if (map_cap(mapfile, CA_SUNW_SF_1,
ofl) == S_ERROR)
return (S_ERROR);
DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml,
CA_SUNW_SF_1, ofl->ofl_sfcap_1,
ld_targ.t_m.m_mach));
continue;
} else {
if (map_equal(mapfile, sgp1, ofl) == S_ERROR)
return (S_ERROR);
ofl->ofl_flags |= FLG_OF_SEGSORT;
DBG_CALL(Dbg_map_set_equal(new_segment));
}
} else if (tok == TK_COLON) {
/*
* If this is an existing segment reservation, sections
* can't be assigned to it.
*/
if ((new_segment == FALSE) &&
(sgp1->sg_flags & FLG_SG_EMPTY)) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_SEGEMPSEC), mapfile,
EC_XWORD(Line_num));
return (S_ERROR);
}
/*
* We are looking at a new entrance criteria line.
* Note that entrance criteria are added in the order
* they are found in the map file, but are placed
* before any default criteria.
*/
if ((enp = libld_calloc(sizeof (Ent_desc), 1)) == 0)
return (S_ERROR);
enp->ec_segment = sgp1;
if (e_next == NULL) {
if ((e_next = list_prependc(&ofl->ofl_ents,
enp)) == 0)
return (S_ERROR);
} else {
if ((e_next = list_insertc(&ofl->ofl_ents,
enp, e_next)) == 0)
return (S_ERROR);
}
if (map_colon(ofl, mapfile, enp) == S_ERROR)
return (S_ERROR);
ofl->ofl_flags |= FLG_OF_SEGSORT;
DBG_CALL(Dbg_map_ent(ofl->ofl_lml, new_segment,
enp, ofl));
} else if (tok == TK_ATSIGN) {
if (map_atsign(mapfile, sgp1, ofl) == S_ERROR)
return (S_ERROR);
DBG_CALL(Dbg_map_set_atsign(new_segment));
} else if (tok != TK_ERROR) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_EXPEQU), mapfile,
EC_XWORD(Line_num));
return (S_ERROR);
}
/*
* Having completed parsing an entry in the map file determine
* if the segment to which it applies is new.
*/
if (new_segment) {
int src_type, dst_type;
/*
* If specific fields have not been supplied via
* map_equal(), make sure defaults are supplied.
*/
if (((sgp1->sg_flags & FLG_SG_TYPE) == 0) &&
(sgp1->sg_phdr.p_type == PT_NULL)) {
/*
* Default to a loadable segment.
*/
sgp1->sg_phdr.p_type = PT_LOAD;
sgp1->sg_flags |= FLG_SG_TYPE;
}
if (sgp1->sg_phdr.p_type == PT_LOAD) {
if ((sgp1->sg_flags & FLG_SG_FLAGS) == 0) {
/*
* Default to read/write and execute.
*/
sgp1->sg_phdr.p_flags =
PF_R + PF_W + PF_X;
sgp1->sg_flags |= FLG_SG_FLAGS;
}
if ((sgp1->sg_flags & FLG_SG_ALIGN) == 0) {
/*
* Default to segment alignment
*/
sgp1->sg_phdr.p_align =
ld_targ.t_m.m_segm_align;
sgp1->sg_flags |= FLG_SG_ALIGN;
}
}
/*
* Determine where the new segment should be inserted
* in the seg_desc[] list. Presently the user can
* only add a LOAD or NOTE segment. Note that these
* segments must be added after any PT_PHDR and
* PT_INTERP (refer Generic ABI, Page 5-4).
*/
switch (sgp1->sg_phdr.p_type) {
case PT_LOAD:
case PT_NULL:
if (sgp1->sg_flags & FLG_SG_EMPTY)
src_type = 4;
else
src_type = 3;
break;
case PT_SUNWSTACK:
src_type = 8;
if (++num_stack >= 2) {
/*
* Currently the number of sunw_stack
* segment is limited to 1.
*/
eprintf(ofl->ofl_lml, ERR_WARNING,
MSG_INTL(MSG_MAP_NOSTACK2),
mapfile, EC_XWORD(Line_num));
continue;
}
break;
case PT_NOTE:
src_type = 9;
break;
default:
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_UNKSEGTYP), mapfile,
EC_XWORD(Line_num),
EC_WORD(sgp1->sg_phdr.p_type));
return (S_ERROR);
}
lnp2 = NULL;
for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp2)) {
ndx++;
switch (sgp2->sg_phdr.p_type) {
case PT_PHDR:
dst_type = 0;
break;
case PT_INTERP:
dst_type = 1;
break;
case PT_SUNWCAP:
dst_type = 2;
break;
case PT_LOAD:
dst_type = 3;
break;
case PT_DYNAMIC:
dst_type = 5;
break;
case PT_SUNWDTRACE:
dst_type = 6;
break;
case PT_SHLIB:
dst_type = 7;
break;
case PT_SUNWSTACK:
dst_type = 8;
break;
case PT_NOTE:
dst_type = 9;
break;
case PT_SUNWBSS:
dst_type = 10;
break;
case PT_TLS:
dst_type = 11;
break;
case PT_NULL:
dst_type = 12;
break;
default:
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_UNKSEGTYP),
mapfile, EC_XWORD(Line_num),
EC_WORD(sgp2->sg_phdr.p_type));
return (S_ERROR);
}
if (src_type <= dst_type) {
if (lnp2 == NULL) {
if (list_prependc(
&ofl->ofl_segs, sgp1) == 0)
return (S_ERROR);
} else {
if (list_insertc(&ofl->ofl_segs,
sgp1, lnp2) == 0)
return (S_ERROR);
}
break;
}
lnp2 = lnp1;
}
}
DBG_CALL(Dbg_map_seg(ofl, ndx, sgp1));
}
/*
* If the output file is a static file without an interpreter, and
* if any virtual address is specified, then set the ?N flag for
* backward compatibility.
*/
if (!(ofl->ofl_flags & FLG_OF_DYNAMIC) &&
!(ofl->ofl_flags & FLG_OF_RELOBJ) &&
!(ofl->ofl_osinterp) &&
(ofl->ofl_flags1 & FLG_OF1_VADDR))
ofl->ofl_dtflags_1 |= DF_1_NOHDR;
/*
* If the output file is a relocatable file, then ?N has no effect.
* Make sure this flag isn't set.
*/
if (ofl->ofl_flags & FLG_OF_RELOBJ)
ofl->ofl_dtflags_1 &= ~DF_1_NOHDR;
return (1);
}