map.c revision d579eb63ae5b8d8c65917b341e8c19a4df710606
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Map file parsing.
*/
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <dirent.h>
#include <ctype.h>
#include <elfcap.h>
#include <debug.h>
#include "msg.h"
#include "_libld.h"
#if defined(_ELF64)
#define XWORD_MAX ULLONG_MAX
#else /* Elf32 */
#endif /* _ELF64 */
typedef enum {
} Token; /* Possible return values from gettoken. */
static char *Mapspace; /* Malloc space holding map file. */
static char *Start_tok; /* First character of current token. */
static char *nextchr; /* Next char in mapfile to examine. */
/*
* Convert a string to lowercase.
*/
static void
{
str++;
}
/*
* Get a token from the mapfile.
*/
static Token
{
char *end; /* End of the current token. */
/* Cycle through the characters looking for tokens. */
for (;;) {
if (oldchr != '\0') {
oldchr = '\0';
}
(*nextchr != '\0'))) {
/* LINTED */
}
switch (*nextchr) {
case '\0': /* End of file. */
return (TK_EOF);
case ' ': /* White space. */
case '\t':
nextchr++;
break;
case '\n': /* White space too, but bump line number. */
nextchr++;
Line_num++;
break;
case '#': /* Comment. */
nextchr++;
break;
case ':':
nextchr++;
return (TK_COLON);
case ';':
nextchr++;
return (TK_SEMICOLON);
case '=':
nextchr++;
return (TK_EQUAL);
case '@':
nextchr++;
return (TK_ATSIGN);
case '-':
nextchr++;
return (TK_DASH);
case '|':
nextchr++;
return (TK_PIPE);
case '{':
nextchr++;
return (TK_LEFTBKT);
case '}':
nextchr++;
return (TK_RIGHTBKT);
case '"':
(*end != '"')) {
/* LINTED */
}
*end = '\0';
return (TK_STRING);
default: /* string. */
else {
*nextchr = '\0';
}
return (TK_STRING);
}
}
}
/*
* hwcap_1 = val,... [ OVERRIDE ]
* sfcap_1 = val,... [ OVERRIDE ]
*
* The values can be defined as a list of machine specify tokens, or numerics.
*
* #define AV_386_FPU 0x0001 is represented as FPU
* #define AV_386_TSC 0x0002 " " " " TSC
*
* Or, the above two capabilities could be represented as V0x3. Note, the
* OVERRIDE flag is used to insure that only those values provided via this
* mapfile entry are recorded in the final image, ie. this overrides any
* hardware capabilities that may be defined in the objects read as part of this
* link-edit. Specifying:
*
* V0x0 OVERRIDE
*
* effectively removes any capabilities information from the final image.
*/
static uintptr_t
{
int used = 0;
/* LINTED */
return (S_ERROR);
return (S_ERROR);
}
return (S_ERROR);
}
/*
* First, determine if the token represents the reserved
* OVERRIDE keyword.
*/
MSG_MAP_OVERRIDE_SIZE) == 0) {
if (type == CA_SUNW_HW_1)
else
used++;
continue;
}
/*
* Next, determine if the token represents a machine specific
* hardware capability, or a generic software capability.
*/
if (type == CA_SUNW_HW_1) {
M_MACH)) != 0) {
used++;
continue;
}
} else {
M_MACH)) != 0) {
used++;
continue;
}
}
/*
* Next, determine if the token represents a numeric value.
*/
if (Start_tok[0] == 'v') {
char *end_tok;
errno = 0;
if (errno) {
return (S_ERROR);
}
return (S_ERROR);
}
if (type == CA_SUNW_HW_1)
else
used++;
continue;
}
/*
* We have an unknown token.
*/
used++;
return (S_ERROR);
}
/*
* Catch any empty declarations, and indicate any software capabilities
* have been initialized if necessary.
*/
if (used == 0) {
} else if (type == CA_SUNW_SF_1) {
/*
* Note, hardware capabilities, beyond the tokens that are
* presently known, can be accepted using the V0xXXX notation,
* and as these simply get or'd into the output image, we allow
* any values to be supplied. Software capability tokens
* however, have an algorithm of acceptance and update (see
* sf1_cap() in files.c). Therefore only allow software
* capabilities that are known.
*/
}
ofl->ofl_sfcap_1 = 0;
}
}
return (1);
}
/*
* Process a mapfile segment declaration definition.
* segment_name = segment_attribute;
* segment_attribute : segment_type segment_flags virtual_addr
* physical_addr length alignment
*/
static uintptr_t
{
/* LINTED */
return (S_ERROR);
return (S_ERROR);
}
return (S_ERROR);
}
/*
* Segment type. Presently there can only be multiple
* PT_LOAD and PT_NOTE segments, other segment types are
* only defined in seg_desc[].
*/
if (b_type) {
return (S_ERROR);
}
if (b_type) {
return (S_ERROR);
}
if (b_type) {
return (S_ERROR);
}
}
/* Segment Flags. */
else if (*Start_tok == '?') {
if (b_flags) {
return (S_ERROR);
}
/*
* If ? has nothing following leave the flags cleared,
* otherwise or in any flags specified.
*/
if (*flag_tok) {
while (*flag_tok) {
switch (*flag_tok) {
case 'r':
break;
case 'w':
break;
case 'x':
break;
case 'e':
break;
case 'o':
break;
case 'n':
break;
default:
*flag_tok);
return (S_ERROR);
}
flag_tok++;
}
}
/*
* Warn when changing flags except when we're
* adding or removing "X" from a RW PT_LOAD
* segment.
*/
}
}
/* Segment address, length, alignment or rounding number. */
(Start_tok[0] == 'r')) {
char *end_tok;
0)) >= XWORD_MAX) {
return (S_ERROR);
}
return (S_ERROR);
}
switch (*Start_tok) {
case 'l':
if (b_len) {
return (S_ERROR);
}
break;
case 'r':
if (b_round) {
return (S_ERROR);
}
break;
case 'v':
if (b_vaddr) {
return (S_ERROR);
}
/* LINTED */
break;
case 'p':
if (b_paddr) {
return (S_ERROR);
}
/* LINTED */
break;
case 'a':
if (b_align) {
return (S_ERROR);
}
/* LINTED */
break;
}
} else {
return (S_ERROR);
}
}
/*
* Segment reservations are only allowable for executables. In addition
* they must have an associated address, size, no permisions,
* and are only meaningful for LOAD segments (the last failure
* we can correct, hence the warning condition).
*/
return (S_ERROR);
}
return (S_ERROR);
}
(FLG_SG_LENGTH | FLG_SG_VADDR)) {
return (S_ERROR);
}
}
}
/*
* All segment attributes have now been scanned. Certain flags do not
* make sense if this is not a loadable segment, fix if necessary.
* Note, if the segment is of type PT_NULL it must be new, and any
* defaults will be applied back in ld_map_parse().
* When clearing an attribute leave the flag set as an indicator for
* later entries re-specifying the same segment.
*/
const char *fmt;
else
}
}
}
}
}
}
}
}
}
return (1);
}
/*
* Process a mapfile mapping directives definition.
* segment_name : section_attribute [ : file_name ]
* segment_attribute : section_name section_type section_flags;
*/
static uintptr_t
{
(tok != TK_SEMICOLON)) {
/* LINTED */
return (S_ERROR);
return (S_ERROR);
}
/* Segment type. */
if (*Start_tok == '$') {
if (b_type) {
return (S_ERROR);
}
Start_tok++;
MSG_ORIG(MSG_STR_SYMTAB)) == 0)
MSG_ORIG(MSG_STR_DYNSYM)) == 0)
MSG_ORIG(MSG_STR_STRTAB)) == 0)
MSG_ORIG(MSG_STR_REL)) == 0) ||
MSG_ORIG(MSG_STR_LD_DYNAMIC)) == 0)
MSG_ORIG(MSG_STR_NOBITS)) == 0)
else {
return (S_ERROR);
}
/*
* Segment flags.
* If a segment flag is specified then the appropriate bit is
* set in the ec_attrmask, the ec_attrbits fields determine
* whether the attrmask fields must be tested true or false
* ie. for ?A the attrmask is set and the attrbit is set,
* for ?!A the attrmask is set and the attrbit is clear.
*/
} else if (*Start_tok == '?') {
if (b_attr) {
return (S_ERROR);
}
Start_tok++;
switch (*Start_tok) {
case '!':
if (b_bang) {
return (S_ERROR);
}
break;
case 'a':
return (S_ERROR);
}
if (!b_bang)
break;
case 'w':
return (S_ERROR);
}
if (!b_bang)
break;
case 'x':
return (S_ERROR);
}
if (!b_bang)
break;
default:
return (S_ERROR);
}
/*
* Section name.
*/
} else {
if (b_name) {
return (S_ERROR);
}
return (S_ERROR);
/*
* get the index for text reordering
*/
/* LINTED */
}
}
/*
* File names.
*/
char *file;
/* LINTED */
return (S_ERROR);
return (S_ERROR);
}
return (S_ERROR);
}
if ((file =
return (S_ERROR);
return (S_ERROR);
}
}
return (1);
}
/*
* Obtain a pseudo input file descriptor to assign to a mapfile. This is
* required any time a symbol is generated. First traverse the input file
* descriptors looking for a match. As all mapfile processing occurs before
* any real input file processing this list is going to be small and we don't
* need to do any filename clash checking.
*/
static Ifl_desc *
{
return (ifl);
else
return (ifl);
}
/*
* Process a mapfile size symbol definition.
* segment_name @ symbol_name;
*/
static uintptr_t
{
/* LINTED */
return (S_ERROR);
}
return (S_ERROR);
}
/*
* Make sure we have a pseudo file descriptor to associate to the
* symbol.
*/
return (S_ERROR);
/*
* Make sure the symbol doesn't already exist. It is possible that the
* symbol has been scoped or versioned, in which case it does exist
* but we can freely update it here.
*/
char *name;
return (S_ERROR);
return (S_ERROR);
/* LINTED */
return (S_ERROR);
} else {
} else {
return (S_ERROR);
}
}
/*
* Assign the symbol to the segment.
*/
/* LINTED */
return (S_ERROR);
} else
return (1);
}
static uintptr_t
{
char *sec_name; /* section name */
/* index for section ordering. */
/* LINTED */
return (S_ERROR);
}
return (S_ERROR);
return (S_ERROR);
sizeof (Sec_order *), AL_CNT_SECORDER) == 0)
return (S_ERROR);
/* LINTED */
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
{
char *version;
enum {
MD_NONE = 0,
/*
* If a shared object definition for this file already exists use it,
* otherwise allocate a new descriptor.
*/
return (S_ERROR);
}
/*
* Get the shared object descriptor string.
*/
/* LINTED */
return (S_ERROR);
return (S_ERROR);
}
return (S_ERROR);
}
/*
* Determine if the library type is accompanied with a SONAME
* definition.
*/
/* LINTED */
return (S_ERROR);
else {
return (S_ERROR);
}
}
switch (dolkey) {
case MD_NEEDED:
continue;
}
if ((sdf->sdf_soname =
return (S_ERROR);
break;
case MD_SPECVERS:
case MD_ADDVERS:
if ((sdv = libld_calloc(
sizeof (Sdv_desc), 1)) == 0)
return (S_ERROR);
if (dolkey == MD_SPECVERS)
else
FLG_SDF_ADDVER)) == (FLG_SDF_SPECVER |
FLG_SDF_ADDVER)) {
return (S_ERROR);
}
if ((version =
return (S_ERROR);
return (S_ERROR);
break;
case MD_NONE:
return (S_ERROR);
}
continue;
}
/*
* A shared object type has been specified. This may also be
* accompanied by an SONAME redefinition (see above).
*/
if (*Start_tok == '$') {
return (S_ERROR);
}
Start_tok++;
MSG_ORIG(MSG_MAP_NEED)) == 0)
MSG_ORIG(MSG_MAP_SPECVERS)) == 0)
MSG_ORIG(MSG_MAP_ADDVERS)) == 0)
dolkey = MD_ADDVERS;
else {
return (S_ERROR);
}
continue;
}
/*
* shared object version requirement.
*/
return (S_ERROR);
return (S_ERROR);
return (S_ERROR);
}
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_LOCL 0 /* local scope flag */
static uintptr_t
{
int scope = FLG_SCOPE_GLOB;
/*
* 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 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.
*/
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) {
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) {
/*
* Traverse the present version descriptor list to see if there
* is already one of the same name, otherwise create a new one.
*/
/* LINTED */
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).
*/
/* LINTED */
}
} else {
/*
* If a version definition hasn't been specified assign any
* symbols to the base version.
*/
}
/*
* Scan the mapfile entry picking out scoping and symbol definitions.
*/
Half sym_flags1 = 0;
return (S_ERROR);
}
return (S_ERROR);
/* LINTED */
return (S_ERROR);
/*
* 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).
*/
switch (tok) {
case TK_COLON:
/*
* Establish a new scope. All symbols added by this
* mapfile are actually global entries. They will be
* reduced to locals during sym_update(). If a symbolic
* scope is detected, remember this. If a symbolic
* scope is the only scope defined in this (or any other
* mapfiles), then -Bsymbolic is established.
*/
_name) == 0) ||
_name) == 0) ||
_name) == 0) ||
_name) == 0)
else {
return (S_ERROR);
}
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.
*/
/*
* If we had previously seen a filter or
* auxiliary filter requirement, the next string
* is the filtee itself.
*/
if (filter) {
if (filtee) {
_name);
return (S_ERROR);
}
if ((filtee = libld_malloc(
return (S_ERROR);
filter = 0;
continue;
}
/*
* Determine any Value or Size attributes.
*/
if (Start_tok[0] == 'v' ||
Start_tok[0] == 's') {
char *end_tok;
XWORD_MAX) {
return (S_ERROR);
}
if (end_tok !=
return (S_ERROR);
}
switch (*Start_tok) {
case 'v':
if (value) {
return (S_ERROR);
}
/* LINTED */
novalue = 0;
break;
case 's':
if (size) {
return (S_ERROR);
}
/* LINTED */
break;
}
MSG_ORIG(MSG_MAP_FUNCTION)) == 0) {
MSG_ORIG(MSG_MAP_DATA)) == 0) {
type = STT_OBJECT;
MSG_ORIG(MSG_MAP_COMMON)) == 0) {
shndx = SHN_COMMON;
type = STT_OBJECT;
MSG_ORIG(MSG_MAP_PARENT)) == 0) {
MSG_ORIG(MSG_MAP_EXTERN)) == 0) {
MSG_ORIG(MSG_MAP_DIRECT)) == 0) {
MSG_ORIG(MSG_MAP_NODIRECT)) == 0) {
if (scope == FLG_SCOPE_SYMB) {
return (S_ERROR);
}
MSG_ORIG(MSG_MAP_FILTER)) == 0) {
continue;
MSG_ORIG(MSG_MAP_AUXILIARY)) == 0) {
continue;
MSG_ORIG(MSG_MAP_INTERPOSE)) == 0) {
return (S_ERROR);
}
continue;
MSG_ORIG(MSG_MAP_DYNSORT)) == 0) {
continue;
MSG_ORIG(MSG_MAP_NODYNSORT)) == 0) {
sym_flags &= ~FLG_SY_DYNSORT;
continue;
} else {
return (S_ERROR);
}
}
/* FALLTHROUGH */
case TK_SEMICOLON:
/*
* The special auto-reduction directive `*' can be
* specified in local scope and indicates that all
* symbols processed that are not explicitly defined to
* be global are to be reduced to local scope in the
* output image. This also implies that a version
* definition is created as the user has effectively
* defined an interface.
*/
if (*_name == '*') {
if (scope == FLG_SCOPE_LOCL)
else if (scope == FLG_SCOPE_ELIM) {
}
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 */
scope));
return (S_ERROR);
/*
* Make sure any parent or external declarations
* fall back to references.
*/
else
return (S_ERROR);
/*
* Identify any references. FLG_SY_MAPREF is
* turned off once a relocatable object with
* the same symbol is found, thus the existance
* of FLG_SY_MAPREF at symbol validation is
*/
} else {
int conflict = 0;
/*
* If this symbol already exists, make sure this
* definition doesn't conflict with the former.
* Provided it doesn't, multiple definitions can
* augment each other.
*/
conflict = 1;
} else
conflict = 2;
} else
if ((type != STT_NOTYPE) &&
conflict = 3;
} else
conflict = 4;
} else
((scope != FLG_SCOPE_LOCL) &&
(scope != FLG_SCOPE_ELIM)))
conflict = 5;
(scope != FLG_SCOPE_GLOB) &&
(scope != FLG_SCOPE_SYMB))
conflict = 6;
VER_NDX_GLOBAL) &&
conflict = 7;
if (conflict) {
return (S_ERROR);
}
/*
* If this mapfile entry supplies a definition,
* indicate that the symbol is now used.
*/
}
/*
* 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 (type == STT_OBJECT) {
return (S_ERROR);
} else {
return (S_ERROR);
}
/*
* 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.
*/
sym_flags &= ~FLG_SY_SPECSEC;
}
/*
* Indicate the new symbols scope.
*/
if (scope == FLG_SCOPE_LOCL) {
} else if (scope == FLG_SCOPE_ELIM) {
} else {
if (scope == FLG_SCOPE_SYMB) {
}
/*
* Record the present version index for later
* potential versioning.
*/
}
/*
* 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++;
/*
* 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.
*/
return (S_ERROR);
}
if (filtee) {
Dfltr_desc * dftp;
/*
* Make sure we don't duplicate any filtee
* strings, and create a new descriptor if
* necessary.
*/
dftp)) {
continue;
break;
}
if (off == 0) {
if ((dftp =
&dft, sizeof (Dfltr_desc),
AL_CNT_DFLTR)) == 0)
return (S_ERROR);
(char *)ofl->ofl_dtsfltrs);
}
/*
* Create a new filter descriptor for this
* symbol.
*/
&sft, sizeof (Sfltr_desc),
AL_CNT_SFLTR) == 0)
return (S_ERROR);
}
break;
default:
return (S_ERROR);
}
}
/*
* Determine if any version references are provided after the close
* bracket.
*/
char *_name;
/* LINTED */
return (S_ERROR);
}
continue;
}
/*
* Generate a new version descriptor if it doesn't already
* exist.
*/
/* LINTED */
return (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).
*/
return (S_ERROR);
}
return (1);
}
/*
* Sort the segment list by increasing virtual address.
*/
{
/*
* Add the .phdr and .interp segments to our list. These segments must
*/
return (S_ERROR);
}
/*
* Add the loadable segments to another list in sorted order.
*/
continue;
return (S_ERROR);
} else {
return (S_ERROR);
continue;
}
if (list_prependc(&seg2,
sgp1) == 0)
return (S_ERROR);
} else {
if (list_insertc(&seg2,
return (S_ERROR);
}
break;
}
if (list_prependc(&seg2,
sgp1) == 0)
return (S_ERROR);
} else {
if (list_insertc(&seg2,
return (S_ERROR);
}
break;
} else {
return (S_ERROR);
}
}
return (S_ERROR);
}
}
/*
* add the sorted loadable segments to our list
*/
return (S_ERROR);
}
/*
* add all other segments to our list
*/
return (S_ERROR);
}
/*
* Now rebuild the original list and process all of the
*/
return (S_ERROR);
}
return (1);
}
/*
* Parse the mapfile.
*/
{
int mapfile_fd; /* descriptor for mapfile */
/* next place for entrance criterion */
char *name;
static int num_stack = 0; /* number of stack segment */
int err;
/*
* Determine if we're dealing with a file or a directory.
*/
return (S_ERROR);
}
/*
* Open the directory and interpret each visible file as a
* mapfile.
*/
return (1);
/*
* Ignore any hidden filenames. Construct the full
* pathname to the new mapfile.
*/
continue;
return (S_ERROR);
}
return (1);
mapfile);
return (S_ERROR);
}
/*
* We read the entire mapfile into memory.
*/
return (S_ERROR);
return (S_ERROR);
}
return (S_ERROR);
}
/*
* 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.
*/
int ndx = -1;
/*
* Don't know which segment yet.
*/
/*
* 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) {
return (S_ERROR);
continue;
}
/* LINTED */
return (S_ERROR);
}
/*
* Save the initial token.
*/
return (S_ERROR);
/*
* Now check the second character on the line. The special `-'
* and `{' characters do not involve any segment manipulation so
* we handle them first.
*/
return (S_ERROR);
continue;
}
if (tok == TK_LEFTBKT) {
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.
*/
ndx++;
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.
*/
return (S_ERROR);
} else {
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.
*/
1)) == 0)
return (S_ERROR);
new_segment = TRUE;
ndx = -1;
}
0)) {
return (S_ERROR);
}
/*
* Now check the second token from the input line.
*/
MSG_ORIG(MSG_STR_HWCAP_1)) == 0) {
return (S_ERROR);
MSG_ORIG(MSG_STR_SFCAP_1)) == 0) {
return (S_ERROR);
} else {
return (S_ERROR);
}
/*
* If this is an existing segment reservation, sections
* can't be assigned to it.
*/
if ((new_segment == FALSE) &&
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.
*/
return (S_ERROR);
enp)) == 0)
return (S_ERROR);
} else {
return (S_ERROR);
}
return (S_ERROR);
return (S_ERROR);
} else {
/* LINTED */
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) {
/*
* If specific fields have not been supplied via
* map_equal(), make sure defaults are supplied.
*/
}
}
/*
* 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).
*/
case PT_LOAD:
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.
*/
continue;
}
break;
case PT_NOTE:
src_type = 9;
break;
default:
return (S_ERROR);
}
ndx++;
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:
return (S_ERROR);
}
if (list_prependc(
return (S_ERROR);
} else {
return (S_ERROR);
}
break;
}
}
}
}
/*
* If the output file is a static file without an interpreter
* and if any virtual address is specified, then assume $n flag
* for backward compatiblity.
*/
!(ofl->ofl_osinterp) &&
/*
* If the output file is a relocatable file,
* then ?N have no effect. Knock it off.
*/
return (1);
}