1*69112eddSAli Bahrami /* 2*69112eddSAli Bahrami * CDDL HEADER START 3*69112eddSAli Bahrami * 4*69112eddSAli Bahrami * The contents of this file are subject to the terms of the 5*69112eddSAli Bahrami * Common Development and Distribution License (the "License"). 6*69112eddSAli Bahrami * You may not use this file except in compliance with the License. 7*69112eddSAli Bahrami * 8*69112eddSAli Bahrami * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*69112eddSAli Bahrami * or http://www.opensolaris.org/os/licensing. 10*69112eddSAli Bahrami * See the License for the specific language governing permissions 11*69112eddSAli Bahrami * and limitations under the License. 12*69112eddSAli Bahrami * 13*69112eddSAli Bahrami * When distributing Covered Code, include this CDDL HEADER in each 14*69112eddSAli Bahrami * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*69112eddSAli Bahrami * If applicable, add the following below this CDDL HEADER, with the 16*69112eddSAli Bahrami * fields enclosed by brackets "[]" replaced with your own identifying 17*69112eddSAli Bahrami * information: Portions Copyright [yyyy] [name of copyright owner] 18*69112eddSAli Bahrami * 19*69112eddSAli Bahrami * CDDL HEADER END 20*69112eddSAli Bahrami */ 21*69112eddSAli Bahrami 22*69112eddSAli Bahrami /* 23*69112eddSAli Bahrami * Copyright (c) 1988 AT&T 24*69112eddSAli Bahrami * All Rights Reserved 25*69112eddSAli Bahrami * 26*69112eddSAli Bahrami * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 27*69112eddSAli Bahrami * Use is subject to license terms. 28*69112eddSAli Bahrami */ 29*69112eddSAli Bahrami 30*69112eddSAli Bahrami /* 31*69112eddSAli Bahrami * Map file parsing (Shared Core Code). 32*69112eddSAli Bahrami */ 33*69112eddSAli Bahrami #include <fcntl.h> 34*69112eddSAli Bahrami #include <stdio.h> 35*69112eddSAli Bahrami #include <unistd.h> 36*69112eddSAli Bahrami #include <sys/stat.h> 37*69112eddSAli Bahrami #include <errno.h> 38*69112eddSAli Bahrami #include <limits.h> 39*69112eddSAli Bahrami #include <dirent.h> 40*69112eddSAli Bahrami #include <ctype.h> 41*69112eddSAli Bahrami #include <debug.h> 42*69112eddSAli Bahrami #include "msg.h" 43*69112eddSAli Bahrami #include "_libld.h" 44*69112eddSAli Bahrami #include "_map.h" 45*69112eddSAli Bahrami 46*69112eddSAli Bahrami /* 47*69112eddSAli Bahrami * There are two styles of mapfile supported by the link-editor: 48*69112eddSAli Bahrami * 49*69112eddSAli Bahrami * 1) The original System V defined syntax, as augmented at Sun 50*69112eddSAli Bahrami * from Solaris 2.0 through Solaris 10. This style is also known 51*69112eddSAli Bahrami * as version 1. 52*69112eddSAli Bahrami * 53*69112eddSAli Bahrami * 2) A newer syntax, currently at version 2. 54*69112eddSAli Bahrami * 55*69112eddSAli Bahrami * The original syntax uses special characters (=, :, -, |, etc) as 56*69112eddSAli Bahrami * operators to indicate the operation being specified. Over the years, 57*69112eddSAli Bahrami * this syntax has been problematic: 58*69112eddSAli Bahrami * 59*69112eddSAli Bahrami * 1) Too cryptic: It's hard for people to remember which character 60*69112eddSAli Bahrami * means what. 61*69112eddSAli Bahrami * 62*69112eddSAli Bahrami * 2) Limited expansion potential: There only a few special characters 63*69112eddSAli Bahrami * available on the keyboard for new features, and it is difficult to 64*69112eddSAli Bahrami * add options to existing ones. 65*69112eddSAli Bahrami * 66*69112eddSAli Bahrami * Adding new features into this framework (2) have the effect of 67*69112eddSAli Bahrami * making the syntax even more cryptic (1). The newer syntax addresses 68*69112eddSAli Bahrami * these issues by moving to an extendible identifier based syntax that 69*69112eddSAli Bahrami * allows new features to be added without complicating old ones. 70*69112eddSAli Bahrami * 71*69112eddSAli Bahrami * The new syntax uses the following terminology: 72*69112eddSAli Bahrami * 73*69112eddSAli Bahrami * - Control directives are the directives that start with a '$'. 74*69112eddSAli Bahrami * They control how the mapfile is interpreted. We use the 'cdir_' 75*69112eddSAli Bahrami * prefix on functions and variables related to these directives. 76*69112eddSAli Bahrami * 77*69112eddSAli Bahrami * - Conditional Expressions are the expressions found in $if and $elif 78*69112eddSAli Bahrami * control directives. They evaluate to boolean true/false values. 79*69112eddSAli Bahrami * We use the 'cexp_' prefix for functions and variables related to 80*69112eddSAli Bahrami * these expressions. 81*69112eddSAli Bahrami * 82*69112eddSAli Bahrami * - Regular Directives are names (SYMBOL, VERSION, etc) that convey 83*69112eddSAli Bahrami * directions to the link-editor for building the output object. 84*69112eddSAli Bahrami * 85*69112eddSAli Bahrami * This file contains core code used by both mapfile styles: File management, 86*69112eddSAli Bahrami * lexical analysis, and other shared core functionality. It also contains 87*69112eddSAli Bahrami * the code for control directives, as they are intrinsically part of 88*69112eddSAli Bahrami * lexical analysis --- this is disabled when processing Sysv mapfiles. 89*69112eddSAli Bahrami */ 90*69112eddSAli Bahrami 91*69112eddSAli Bahrami /* 92*69112eddSAli Bahrami * We use a stack of cdir_level_t structs to manage $if/$elif/$else/$endif 93*69112eddSAli Bahrami * processing. At each level, we keep track of the information needed to 94*69112eddSAli Bahrami * determine whether or not to process nested input lines or skip them, 95*69112eddSAli Bahrami * along with information needed to report errors. 96*69112eddSAli Bahrami */ 97*69112eddSAli Bahrami typedef struct { 98*69112eddSAli Bahrami Lineno cdl_if_lineno; /* Line number of opening $if */ 99*69112eddSAli Bahrami Lineno cdl_else_lineno; /* 0, or line on which $else seen */ 100*69112eddSAli Bahrami int cdl_done; /* True if no longer accepts input */ 101*69112eddSAli Bahrami int cdl_pass; /* True if currently accepting input */ 102*69112eddSAli Bahrami } cdir_level_t; 103*69112eddSAli Bahrami 104*69112eddSAli Bahrami /* Operators in the expressions accepted by $if/$elif */ 105*69112eddSAli Bahrami typedef enum { 106*69112eddSAli Bahrami CEXP_OP_NONE, /* Not an operator */ 107*69112eddSAli Bahrami CEXP_OP_AND, /* && */ 108*69112eddSAli Bahrami CEXP_OP_OR, /* || */ 109*69112eddSAli Bahrami CEXP_OP_NEG, /* ! */ 110*69112eddSAli Bahrami CEXP_OP_OPAR, /* ( */ 111*69112eddSAli Bahrami CEXP_OP_CPAR /* ) */ 112*69112eddSAli Bahrami } cexp_op_t; 113*69112eddSAli Bahrami 114*69112eddSAli Bahrami /* 115*69112eddSAli Bahrami * Type of conditional expression identifier AVL tree nodes 116*69112eddSAli Bahrami */ 117*69112eddSAli Bahrami typedef struct cexp_name_node { 118*69112eddSAli Bahrami avl_node_t ceid_avlnode; /* AVL book-keeping */ 119*69112eddSAli Bahrami const char *ceid_name; /* boolean identifier name */ 120*69112eddSAli Bahrami } cexp_id_node_t; 121*69112eddSAli Bahrami 122*69112eddSAli Bahrami 123*69112eddSAli Bahrami /* 124*69112eddSAli Bahrami * Declare a "stack" type, containing a pointer to data, a count of 125*69112eddSAli Bahrami * allocated, and currently used items in the stack. The data type 126*69112eddSAli Bahrami * is specified as the _type argument. 127*69112eddSAli Bahrami */ 128*69112eddSAli Bahrami #define STACK(_type) \ 129*69112eddSAli Bahrami struct { \ 130*69112eddSAli Bahrami _type *stk_s; /* Stack array */ \ 131*69112eddSAli Bahrami size_t stk_n; /* Current stack depth */ \ 132*69112eddSAli Bahrami size_t stk_n_alloc; /* # of elements pointed at by s */ \ 133*69112eddSAli Bahrami } 134*69112eddSAli Bahrami 135*69112eddSAli Bahrami /* 136*69112eddSAli Bahrami * The following type represents a "generic" stack, where the data 137*69112eddSAli Bahrami * type is (void). This type is never instantiated. However, it has 138*69112eddSAli Bahrami * the same struct layout as any other STACK(), and is therefore a good 139*69112eddSAli Bahrami * generic type that can be used for stack_resize(). 140*69112eddSAli Bahrami */ 141*69112eddSAli Bahrami typedef STACK(void) generic_stack_t; 142*69112eddSAli Bahrami 143*69112eddSAli Bahrami /* 144*69112eddSAli Bahrami * Ensure that the stack has enough room to push one more item 145*69112eddSAli Bahrami */ 146*69112eddSAli Bahrami #define STACK_RESERVE(_stack, _n_default) \ 147*69112eddSAli Bahrami (((_stack).stk_n < (_stack).stk_n_alloc) || \ 148*69112eddSAli Bahrami stack_resize((generic_stack_t *)&(_stack).stk_s, _n_default, \ 149*69112eddSAli Bahrami sizeof (*(_stack).stk_s))) 150*69112eddSAli Bahrami 151*69112eddSAli Bahrami /* 152*69112eddSAli Bahrami * Reset a stack to empty. 153*69112eddSAli Bahrami */ 154*69112eddSAli Bahrami #define STACK_RESET(_stack) (_stack).stk_n = 0; 155*69112eddSAli Bahrami 156*69112eddSAli Bahrami /* 157*69112eddSAli Bahrami * True if stack is empty, False otherwise. 158*69112eddSAli Bahrami */ 159*69112eddSAli Bahrami #define STACK_IS_EMPTY(_stack) ((_stack).stk_n == 0) 160*69112eddSAli Bahrami 161*69112eddSAli Bahrami /* 162*69112eddSAli Bahrami * Push a value onto a stack. Caller must ensure that stack has room. 163*69112eddSAli Bahrami * This macro is intended to be used as the LHS of an assignment, the 164*69112eddSAli Bahrami * RHS of which is the value: 165*69112eddSAli Bahrami * 166*69112eddSAli Bahrami * STACK_PUSH(stack) = value; 167*69112eddSAli Bahrami */ 168*69112eddSAli Bahrami #define STACK_PUSH(_stack) (_stack).stk_s[(_stack).stk_n++] 169*69112eddSAli Bahrami 170*69112eddSAli Bahrami /* 171*69112eddSAli Bahrami * Pop a value off a stack. Caller must ensure 172*69112eddSAli Bahrami * that stack is not empty. 173*69112eddSAli Bahrami */ 174*69112eddSAli Bahrami #define STACK_POP(_stack) ((_stack).stk_s[--(_stack).stk_n]) 175*69112eddSAli Bahrami 176*69112eddSAli Bahrami /* 177*69112eddSAli Bahrami * Access top element on stack without popping. Caller must ensure 178*69112eddSAli Bahrami * that stack is not empty. 179*69112eddSAli Bahrami */ 180*69112eddSAli Bahrami #define STACK_TOP(_stack) (((_stack).stk_s)[(_stack).stk_n - 1]) 181*69112eddSAli Bahrami 182*69112eddSAli Bahrami /* 183*69112eddSAli Bahrami * Initial sizes used for the stacks: The stacks are allocated on demand 184*69112eddSAli Bahrami * to these sizes, and then doubled as necessary until they are large enough. 185*69112eddSAli Bahrami * 186*69112eddSAli Bahrami * The ideal size would be large enough that only a single allocation 187*69112eddSAli Bahrami * occurs, and our defaults should generally have that effect. However, 188*69112eddSAli Bahrami * in doing so, we run the risk of a latent error in the resize code going 189*69112eddSAli Bahrami * undetected until triggered by a large task in the field. For this reason, 190*69112eddSAli Bahrami * we set the sizes to the smallest size possible when compiled for debug. 191*69112eddSAli Bahrami */ 192*69112eddSAli Bahrami #ifdef DEBUG 193*69112eddSAli Bahrami #define CDIR_STACK_INIT 1 194*69112eddSAli Bahrami #define CEXP_OP_STACK_INIT 1 195*69112eddSAli Bahrami #define CEXP_VAL_STACK_INIT 1 196*69112eddSAli Bahrami #else 197*69112eddSAli Bahrami #define CDIR_STACK_INIT 16 198*69112eddSAli Bahrami #define CEXP_OP_STACK_INIT 8 199*69112eddSAli Bahrami #define CEXP_VAL_STACK_INIT (CEXP_OP_STACK_INIT * 2) /* 2 vals per binop */ 200*69112eddSAli Bahrami #endif 201*69112eddSAli Bahrami 202*69112eddSAli Bahrami 203*69112eddSAli Bahrami /* 204*69112eddSAli Bahrami * Persistent state maintained by map module in between calls. 205*69112eddSAli Bahrami * 206*69112eddSAli Bahrami * This is kept as static file scope data, because it is only used 207*69112eddSAli Bahrami * when libld is called by ld, and not by rtld. If that should change, 208*69112eddSAli Bahrami * the code is designed so that it can become reentrant easily: 209*69112eddSAli Bahrami * 210*69112eddSAli Bahrami * - Add a pointer to the output descriptor to a structure of this type, 211*69112eddSAli Bahrami * allocated dynamically on the first call to ld_map_parse(). 212*69112eddSAli Bahrami * - Change all references to lms to instead reference the pointer in 213*69112eddSAli Bahrami * the output descriptor. 214*69112eddSAli Bahrami * 215*69112eddSAli Bahrami * Until then, it is simpler not to expose these details. 216*69112eddSAli Bahrami */ 217*69112eddSAli Bahrami typedef struct { 218*69112eddSAli Bahrami int lms_cdir_valid; /* Allow control dir. on entry to gettoken() */ 219*69112eddSAli Bahrami STACK(cdir_level_t) lms_cdir_stack; /* Conditional input level */ 220*69112eddSAli Bahrami STACK(cexp_op_t) lms_cexp_op_stack; /* Cond. expr operators */ 221*69112eddSAli Bahrami STACK(uchar_t) lms_cexp_val_stack; /* Cond. expr values */ 222*69112eddSAli Bahrami avl_tree_t *lms_cexp_id; 223*69112eddSAli Bahrami } ld_map_state_t; 224*69112eddSAli Bahrami static ld_map_state_t lms; 225*69112eddSAli Bahrami 226*69112eddSAli Bahrami 227*69112eddSAli Bahrami /* 228*69112eddSAli Bahrami * Version 1 (SysV) syntax dispatch table for ld_map_gettoken(). For each 229*69112eddSAli Bahrami * of the 7-bit ASCII characters, determine how the lexical analyzer 230*69112eddSAli Bahrami * should behave. 231*69112eddSAli Bahrami * 232*69112eddSAli Bahrami * This table must be kept in sync with tkid_attr[] below. 233*69112eddSAli Bahrami * 234*69112eddSAli Bahrami * Identifier Note: 235*69112eddSAli Bahrami * The Linker and Libraries Guide states that the original syntax uses 236*69112eddSAli Bahrami * C identifier rules, allowing '.' to be treated as a letter. However, 237*69112eddSAli Bahrami * the implementation is considerably looser than that: Any character 238*69112eddSAli Bahrami * with an ASCII code (0-127) which is printable and not used to start 239*69112eddSAli Bahrami * another token is allowed to start an identifier, and they are terminated 240*69112eddSAli Bahrami * by any of: space, double quote, tab, newline, ':', ';', '=', or '#'. 241*69112eddSAli Bahrami * The original code has been replaced, but this table encodes the same 242*69112eddSAli Bahrami * rules, to ensure backward compatibility. 243*69112eddSAli Bahrami */ 244*69112eddSAli Bahrami static const mf_tokdisp_t gettok_dispatch_v1 = { 245*69112eddSAli Bahrami TK_OP_EOF, /* 0 - NUL */ 246*69112eddSAli Bahrami TK_OP_ILLCHR, /* 1 - SOH */ 247*69112eddSAli Bahrami TK_OP_ILLCHR, /* 2 - STX */ 248*69112eddSAli Bahrami TK_OP_ILLCHR, /* 3 - ETX */ 249*69112eddSAli Bahrami TK_OP_ILLCHR, /* 4 - EOT */ 250*69112eddSAli Bahrami TK_OP_ILLCHR, /* 5 - ENQ */ 251*69112eddSAli Bahrami TK_OP_ILLCHR, /* 6 - ACK */ 252*69112eddSAli Bahrami TK_OP_ILLCHR, /* 7 - BEL */ 253*69112eddSAli Bahrami TK_OP_ILLCHR, /* 8 - BS */ 254*69112eddSAli Bahrami TK_OP_WS, /* 9 - HT */ 255*69112eddSAli Bahrami TK_OP_NL, /* 10 - NL */ 256*69112eddSAli Bahrami TK_OP_WS, /* 11 - VT */ 257*69112eddSAli Bahrami TK_OP_WS, /* 12 - FF */ 258*69112eddSAli Bahrami TK_OP_WS, /* 13 - CR */ 259*69112eddSAli Bahrami TK_OP_ILLCHR, /* 14 - SO */ 260*69112eddSAli Bahrami TK_OP_ILLCHR, /* 15 - SI */ 261*69112eddSAli Bahrami TK_OP_ILLCHR, /* 16 - DLE */ 262*69112eddSAli Bahrami TK_OP_ILLCHR, /* 17 - DC1 */ 263*69112eddSAli Bahrami TK_OP_ILLCHR, /* 18 - DC2 */ 264*69112eddSAli Bahrami TK_OP_ILLCHR, /* 19 - DC3 */ 265*69112eddSAli Bahrami TK_OP_ILLCHR, /* 20 - DC4 */ 266*69112eddSAli Bahrami TK_OP_ILLCHR, /* 21 - NAK */ 267*69112eddSAli Bahrami TK_OP_ILLCHR, /* 22 - SYN */ 268*69112eddSAli Bahrami TK_OP_ILLCHR, /* 23 - ETB */ 269*69112eddSAli Bahrami TK_OP_ILLCHR, /* 24 - CAN */ 270*69112eddSAli Bahrami TK_OP_ILLCHR, /* 25 - EM */ 271*69112eddSAli Bahrami TK_OP_ILLCHR, /* 26 - SUB */ 272*69112eddSAli Bahrami TK_OP_ILLCHR, /* 27 - ESC */ 273*69112eddSAli Bahrami TK_OP_ILLCHR, /* 28 - FS */ 274*69112eddSAli Bahrami TK_OP_ILLCHR, /* 29 - GS */ 275*69112eddSAli Bahrami TK_OP_ILLCHR, /* 30 - RS */ 276*69112eddSAli Bahrami TK_OP_ILLCHR, /* 31 - US */ 277*69112eddSAli Bahrami TK_OP_WS, /* 32 - SP */ 278*69112eddSAli Bahrami TK_OP_ID, /* 33 - ! */ 279*69112eddSAli Bahrami TK_OP_SIMQUOTE, /* 34 - " */ 280*69112eddSAli Bahrami TK_OP_CMT, /* 35 - # */ 281*69112eddSAli Bahrami TK_OP_ID, /* 36 - $ */ 282*69112eddSAli Bahrami TK_OP_ID, /* 37 - % */ 283*69112eddSAli Bahrami TK_OP_ID, /* 38 - & */ 284*69112eddSAli Bahrami TK_OP_ID, /* 39 - ' */ 285*69112eddSAli Bahrami TK_OP_ID, /* 40 - ( */ 286*69112eddSAli Bahrami TK_OP_ID, /* 41 - ) */ 287*69112eddSAli Bahrami TK_OP_ID, /* 42 - * */ 288*69112eddSAli Bahrami TK_OP_ID, /* 43 - + */ 289*69112eddSAli Bahrami TK_OP_ID, /* 44 - , */ 290*69112eddSAli Bahrami TK_DASH, /* 45 - - */ 291*69112eddSAli Bahrami TK_OP_ID, /* 46 - . */ 292*69112eddSAli Bahrami TK_OP_ID, /* 47 - / */ 293*69112eddSAli Bahrami TK_OP_ID, /* 48 - 0 */ 294*69112eddSAli Bahrami TK_OP_ID, /* 49 - 1 */ 295*69112eddSAli Bahrami TK_OP_ID, /* 50 - 2 */ 296*69112eddSAli Bahrami TK_OP_ID, /* 51 - 3 */ 297*69112eddSAli Bahrami TK_OP_ID, /* 52 - 4 */ 298*69112eddSAli Bahrami TK_OP_ID, /* 53 - 5 */ 299*69112eddSAli Bahrami TK_OP_ID, /* 54 - 6 */ 300*69112eddSAli Bahrami TK_OP_ID, /* 55 - 7 */ 301*69112eddSAli Bahrami TK_OP_ID, /* 56 - 8 */ 302*69112eddSAli Bahrami TK_OP_ID, /* 57 - 9 */ 303*69112eddSAli Bahrami TK_COLON, /* 58 - : */ 304*69112eddSAli Bahrami TK_SEMICOLON, /* 59 - ; */ 305*69112eddSAli Bahrami TK_OP_ID, /* 60 - < */ 306*69112eddSAli Bahrami TK_EQUAL, /* 61 - = */ 307*69112eddSAli Bahrami TK_OP_ID, /* 62 - > */ 308*69112eddSAli Bahrami TK_OP_ID, /* 63 - ? */ 309*69112eddSAli Bahrami TK_ATSIGN, /* 64 - @ */ 310*69112eddSAli Bahrami TK_OP_ID, /* 65 - A */ 311*69112eddSAli Bahrami TK_OP_ID, /* 66 - B */ 312*69112eddSAli Bahrami TK_OP_ID, /* 67 - C */ 313*69112eddSAli Bahrami TK_OP_ID, /* 68 - D */ 314*69112eddSAli Bahrami TK_OP_ID, /* 69 - E */ 315*69112eddSAli Bahrami TK_OP_ID, /* 70 - F */ 316*69112eddSAli Bahrami TK_OP_ID, /* 71 - G */ 317*69112eddSAli Bahrami TK_OP_ID, /* 72 - H */ 318*69112eddSAli Bahrami TK_OP_ID, /* 73 - I */ 319*69112eddSAli Bahrami TK_OP_ID, /* 74 - J */ 320*69112eddSAli Bahrami TK_OP_ID, /* 75 - K */ 321*69112eddSAli Bahrami TK_OP_ID, /* 76 - L */ 322*69112eddSAli Bahrami TK_OP_ID, /* 77 - M */ 323*69112eddSAli Bahrami TK_OP_ID, /* 78 - N */ 324*69112eddSAli Bahrami TK_OP_ID, /* 79 - O */ 325*69112eddSAli Bahrami TK_OP_ID, /* 80 - P */ 326*69112eddSAli Bahrami TK_OP_ID, /* 81 - Q */ 327*69112eddSAli Bahrami TK_OP_ID, /* 82 - R */ 328*69112eddSAli Bahrami TK_OP_ID, /* 83 - S */ 329*69112eddSAli Bahrami TK_OP_ID, /* 84 - T */ 330*69112eddSAli Bahrami TK_OP_ID, /* 85 - U */ 331*69112eddSAli Bahrami TK_OP_ID, /* 86 - V */ 332*69112eddSAli Bahrami TK_OP_ID, /* 87 - W */ 333*69112eddSAli Bahrami TK_OP_ID, /* 88 - X */ 334*69112eddSAli Bahrami TK_OP_ID, /* 89 - Y */ 335*69112eddSAli Bahrami TK_OP_ID, /* 90 - Z */ 336*69112eddSAli Bahrami TK_OP_ID, /* 91 - [ */ 337*69112eddSAli Bahrami TK_OP_ID, /* 92 - \ */ 338*69112eddSAli Bahrami TK_OP_ID, /* 93 - ] */ 339*69112eddSAli Bahrami TK_OP_ID, /* 94 - ^ */ 340*69112eddSAli Bahrami TK_OP_ID, /* 95 - _ */ 341*69112eddSAli Bahrami TK_OP_ID, /* 96 - ` */ 342*69112eddSAli Bahrami TK_OP_ID, /* 97 - a */ 343*69112eddSAli Bahrami TK_OP_ID, /* 98 - b */ 344*69112eddSAli Bahrami TK_OP_ID, /* 99 - c */ 345*69112eddSAli Bahrami TK_OP_ID, /* 100 - d */ 346*69112eddSAli Bahrami TK_OP_ID, /* 101 - e */ 347*69112eddSAli Bahrami TK_OP_ID, /* 102 - f */ 348*69112eddSAli Bahrami TK_OP_ID, /* 103 - g */ 349*69112eddSAli Bahrami TK_OP_ID, /* 104 - h */ 350*69112eddSAli Bahrami TK_OP_ID, /* 105 - i */ 351*69112eddSAli Bahrami TK_OP_ID, /* 106 - j */ 352*69112eddSAli Bahrami TK_OP_ID, /* 107 - k */ 353*69112eddSAli Bahrami TK_OP_ID, /* 108 - l */ 354*69112eddSAli Bahrami TK_OP_ID, /* 109 - m */ 355*69112eddSAli Bahrami TK_OP_ID, /* 110 - n */ 356*69112eddSAli Bahrami TK_OP_ID, /* 111 - o */ 357*69112eddSAli Bahrami TK_OP_ID, /* 112 - p */ 358*69112eddSAli Bahrami TK_OP_ID, /* 113 - q */ 359*69112eddSAli Bahrami TK_OP_ID, /* 114 - r */ 360*69112eddSAli Bahrami TK_OP_ID, /* 115 - s */ 361*69112eddSAli Bahrami TK_OP_ID, /* 116 - t */ 362*69112eddSAli Bahrami TK_OP_ID, /* 117 - u */ 363*69112eddSAli Bahrami TK_OP_ID, /* 118 - v */ 364*69112eddSAli Bahrami TK_OP_ID, /* 119 - w */ 365*69112eddSAli Bahrami TK_OP_ID, /* 120 - x */ 366*69112eddSAli Bahrami TK_OP_ID, /* 121 - y */ 367*69112eddSAli Bahrami TK_OP_ID, /* 122 - z */ 368*69112eddSAli Bahrami TK_LEFTBKT, /* 123 - { */ 369*69112eddSAli Bahrami TK_PIPE, /* 124 - | */ 370*69112eddSAli Bahrami TK_RIGHTBKT, /* 125 - } */ 371*69112eddSAli Bahrami TK_OP_ID, /* 126 - ~ */ 372*69112eddSAli Bahrami TK_OP_ILLCHR, /* 127 - DEL */ 373*69112eddSAli Bahrami }; 374*69112eddSAli Bahrami 375*69112eddSAli Bahrami /* 376*69112eddSAli Bahrami * Version 2 syntax dispatch table for ld_map_gettoken(). For each of the 377*69112eddSAli Bahrami * 7-bit ASCII characters, determine how the lexical analyzer should behave. 378*69112eddSAli Bahrami * 379*69112eddSAli Bahrami * This table must be kept in sync with tkid_attr[] below. 380*69112eddSAli Bahrami * 381*69112eddSAli Bahrami * Identifier Note: 382*69112eddSAli Bahrami * We define a letter as being one of the character [A-Z], [a-z], or [_%/.] 383*69112eddSAli Bahrami * A digit is the numbers [0-9], or [$-]. An unquoted identifier is defined 384*69112eddSAli Bahrami * as a letter, followed by any number of letters or digits. This is a loosened 385*69112eddSAli Bahrami * version of the C definition of an identifier. The extra characters not 386*69112eddSAli Bahrami * allowed by C are common in section names and/or file paths. 387*69112eddSAli Bahrami */ 388*69112eddSAli Bahrami static const mf_tokdisp_t gettok_dispatch_v2 = { 389*69112eddSAli Bahrami TK_OP_EOF, /* 0 - NUL */ 390*69112eddSAli Bahrami TK_OP_ILLCHR, /* 1 - SOH */ 391*69112eddSAli Bahrami TK_OP_ILLCHR, /* 2 - STX */ 392*69112eddSAli Bahrami TK_OP_ILLCHR, /* 3 - ETX */ 393*69112eddSAli Bahrami TK_OP_ILLCHR, /* 4 - EOT */ 394*69112eddSAli Bahrami TK_OP_ILLCHR, /* 5 - ENQ */ 395*69112eddSAli Bahrami TK_OP_ILLCHR, /* 6 - ACK */ 396*69112eddSAli Bahrami TK_OP_ILLCHR, /* 7 - BEL */ 397*69112eddSAli Bahrami TK_OP_ILLCHR, /* 8 - BS */ 398*69112eddSAli Bahrami TK_OP_WS, /* 9 - HT */ 399*69112eddSAli Bahrami TK_OP_NL, /* 10 - NL */ 400*69112eddSAli Bahrami TK_OP_WS, /* 11 - VT */ 401*69112eddSAli Bahrami TK_OP_WS, /* 12 - FF */ 402*69112eddSAli Bahrami TK_OP_WS, /* 13 - CR */ 403*69112eddSAli Bahrami TK_OP_ILLCHR, /* 14 - SO */ 404*69112eddSAli Bahrami TK_OP_ILLCHR, /* 15 - SI */ 405*69112eddSAli Bahrami TK_OP_ILLCHR, /* 16 - DLE */ 406*69112eddSAli Bahrami TK_OP_ILLCHR, /* 17 - DC1 */ 407*69112eddSAli Bahrami TK_OP_ILLCHR, /* 18 - DC2 */ 408*69112eddSAli Bahrami TK_OP_ILLCHR, /* 19 - DC3 */ 409*69112eddSAli Bahrami TK_OP_ILLCHR, /* 20 - DC4 */ 410*69112eddSAli Bahrami TK_OP_ILLCHR, /* 21 - NAK */ 411*69112eddSAli Bahrami TK_OP_ILLCHR, /* 22 - SYN */ 412*69112eddSAli Bahrami TK_OP_ILLCHR, /* 23 - ETB */ 413*69112eddSAli Bahrami TK_OP_ILLCHR, /* 24 - CAN */ 414*69112eddSAli Bahrami TK_OP_ILLCHR, /* 25 - EM */ 415*69112eddSAli Bahrami TK_OP_ILLCHR, /* 26 - SUB */ 416*69112eddSAli Bahrami TK_OP_ILLCHR, /* 27 - ESC */ 417*69112eddSAli Bahrami TK_OP_ILLCHR, /* 28 - FS */ 418*69112eddSAli Bahrami TK_OP_ILLCHR, /* 29 - GS */ 419*69112eddSAli Bahrami TK_OP_ILLCHR, /* 30 - RS */ 420*69112eddSAli Bahrami TK_OP_ILLCHR, /* 31 - US */ 421*69112eddSAli Bahrami TK_OP_WS, /* 32 - SP */ 422*69112eddSAli Bahrami TK_BANG, /* 33 - ! */ 423*69112eddSAli Bahrami TK_OP_CQUOTE, /* 34 - " */ 424*69112eddSAli Bahrami TK_OP_CMT, /* 35 - # */ 425*69112eddSAli Bahrami TK_OP_CDIR, /* 36 - $ */ 426*69112eddSAli Bahrami TK_OP_ID, /* 37 - % */ 427*69112eddSAli Bahrami TK_OP_BADCHR, /* 38 - & */ 428*69112eddSAli Bahrami TK_OP_SIMQUOTE, /* 39 - ' */ 429*69112eddSAli Bahrami TK_OP_BADCHR, /* 40 - ( */ 430*69112eddSAli Bahrami TK_OP_BADCHR, /* 41 - ) */ 431*69112eddSAli Bahrami TK_STAR, /* 42 - * */ 432*69112eddSAli Bahrami TK_OP_CEQUAL, /* 43 - + */ 433*69112eddSAli Bahrami TK_OP_BADCHR, /* 44 - , */ 434*69112eddSAli Bahrami TK_OP_CEQUAL, /* 45 - - */ 435*69112eddSAli Bahrami TK_OP_ID, /* 46 - . */ 436*69112eddSAli Bahrami TK_OP_ID, /* 47 - / */ 437*69112eddSAli Bahrami TK_OP_NUM, /* 48 - 0 */ 438*69112eddSAli Bahrami TK_OP_NUM, /* 49 - 1 */ 439*69112eddSAli Bahrami TK_OP_NUM, /* 50 - 2 */ 440*69112eddSAli Bahrami TK_OP_NUM, /* 51 - 3 */ 441*69112eddSAli Bahrami TK_OP_NUM, /* 52 - 4 */ 442*69112eddSAli Bahrami TK_OP_NUM, /* 53 - 5 */ 443*69112eddSAli Bahrami TK_OP_NUM, /* 54 - 6 */ 444*69112eddSAli Bahrami TK_OP_NUM, /* 55 - 7 */ 445*69112eddSAli Bahrami TK_OP_NUM, /* 56 - 8 */ 446*69112eddSAli Bahrami TK_OP_NUM, /* 57 - 9 */ 447*69112eddSAli Bahrami TK_COLON, /* 58 - : */ 448*69112eddSAli Bahrami TK_SEMICOLON, /* 59 - ; */ 449*69112eddSAli Bahrami TK_OP_BADCHR, /* 60 - < */ 450*69112eddSAli Bahrami TK_EQUAL, /* 61 - = */ 451*69112eddSAli Bahrami TK_OP_BADCHR, /* 62 - > */ 452*69112eddSAli Bahrami TK_OP_BADCHR, /* 63 - ? */ 453*69112eddSAli Bahrami TK_OP_BADCHR, /* 64 - @ */ 454*69112eddSAli Bahrami TK_OP_ID, /* 65 - A */ 455*69112eddSAli Bahrami TK_OP_ID, /* 66 - B */ 456*69112eddSAli Bahrami TK_OP_ID, /* 67 - C */ 457*69112eddSAli Bahrami TK_OP_ID, /* 68 - D */ 458*69112eddSAli Bahrami TK_OP_ID, /* 69 - E */ 459*69112eddSAli Bahrami TK_OP_ID, /* 70 - F */ 460*69112eddSAli Bahrami TK_OP_ID, /* 71 - G */ 461*69112eddSAli Bahrami TK_OP_ID, /* 72 - H */ 462*69112eddSAli Bahrami TK_OP_ID, /* 73 - I */ 463*69112eddSAli Bahrami TK_OP_ID, /* 74 - J */ 464*69112eddSAli Bahrami TK_OP_ID, /* 75 - K */ 465*69112eddSAli Bahrami TK_OP_ID, /* 76 - L */ 466*69112eddSAli Bahrami TK_OP_ID, /* 77 - M */ 467*69112eddSAli Bahrami TK_OP_ID, /* 78 - N */ 468*69112eddSAli Bahrami TK_OP_ID, /* 79 - O */ 469*69112eddSAli Bahrami TK_OP_ID, /* 80 - P */ 470*69112eddSAli Bahrami TK_OP_ID, /* 81 - Q */ 471*69112eddSAli Bahrami TK_OP_ID, /* 82 - R */ 472*69112eddSAli Bahrami TK_OP_ID, /* 83 - S */ 473*69112eddSAli Bahrami TK_OP_ID, /* 84 - T */ 474*69112eddSAli Bahrami TK_OP_ID, /* 85 - U */ 475*69112eddSAli Bahrami TK_OP_ID, /* 86 - V */ 476*69112eddSAli Bahrami TK_OP_ID, /* 87 - W */ 477*69112eddSAli Bahrami TK_OP_ID, /* 88 - X */ 478*69112eddSAli Bahrami TK_OP_ID, /* 89 - Y */ 479*69112eddSAli Bahrami TK_OP_ID, /* 90 - Z */ 480*69112eddSAli Bahrami TK_OP_BADCHR, /* 91 - [ */ 481*69112eddSAli Bahrami TK_OP_BADCHR, /* 92 - \ */ 482*69112eddSAli Bahrami TK_OP_BADCHR, /* 93 - ] */ 483*69112eddSAli Bahrami TK_OP_BADCHR, /* 94 - ^ */ 484*69112eddSAli Bahrami TK_OP_ID, /* 95 - _ */ 485*69112eddSAli Bahrami TK_OP_BADCHR, /* 96 - ` */ 486*69112eddSAli Bahrami TK_OP_ID, /* 97 - a */ 487*69112eddSAli Bahrami TK_OP_ID, /* 98 - b */ 488*69112eddSAli Bahrami TK_OP_ID, /* 99 - c */ 489*69112eddSAli Bahrami TK_OP_ID, /* 100 - d */ 490*69112eddSAli Bahrami TK_OP_ID, /* 101 - e */ 491*69112eddSAli Bahrami TK_OP_ID, /* 102 - f */ 492*69112eddSAli Bahrami TK_OP_ID, /* 103 - g */ 493*69112eddSAli Bahrami TK_OP_ID, /* 104 - h */ 494*69112eddSAli Bahrami TK_OP_ID, /* 105 - i */ 495*69112eddSAli Bahrami TK_OP_ID, /* 106 - j */ 496*69112eddSAli Bahrami TK_OP_ID, /* 107 - k */ 497*69112eddSAli Bahrami TK_OP_ID, /* 108 - l */ 498*69112eddSAli Bahrami TK_OP_ID, /* 109 - m */ 499*69112eddSAli Bahrami TK_OP_ID, /* 110 - n */ 500*69112eddSAli Bahrami TK_OP_ID, /* 111 - o */ 501*69112eddSAli Bahrami TK_OP_ID, /* 112 - p */ 502*69112eddSAli Bahrami TK_OP_ID, /* 113 - q */ 503*69112eddSAli Bahrami TK_OP_ID, /* 114 - r */ 504*69112eddSAli Bahrami TK_OP_ID, /* 115 - s */ 505*69112eddSAli Bahrami TK_OP_ID, /* 116 - t */ 506*69112eddSAli Bahrami TK_OP_ID, /* 117 - u */ 507*69112eddSAli Bahrami TK_OP_ID, /* 118 - v */ 508*69112eddSAli Bahrami TK_OP_ID, /* 119 - w */ 509*69112eddSAli Bahrami TK_OP_ID, /* 120 - x */ 510*69112eddSAli Bahrami TK_OP_ID, /* 121 - y */ 511*69112eddSAli Bahrami TK_OP_ID, /* 122 - z */ 512*69112eddSAli Bahrami TK_LEFTBKT, /* 123 - { */ 513*69112eddSAli Bahrami TK_OP_BADCHR, /* 124 - | */ 514*69112eddSAli Bahrami TK_RIGHTBKT, /* 125 - } */ 515*69112eddSAli Bahrami TK_OP_BADCHR, /* 126 - ~ */ 516*69112eddSAli Bahrami TK_OP_ILLCHR, /* 127 - DEL */ 517*69112eddSAli Bahrami }; 518*69112eddSAli Bahrami 519*69112eddSAli Bahrami 520*69112eddSAli Bahrami /* 521*69112eddSAli Bahrami * Table used to identify unquoted identifiers. Each element of this array 522*69112eddSAli Bahrami * contains a bitmask indicating whether the character it represents starts, 523*69112eddSAli Bahrami * or continues an identifier, for each supported mapfile syntax version. 524*69112eddSAli Bahrami */ 525*69112eddSAli Bahrami static const char tkid_attr[128] = { 526*69112eddSAli Bahrami 0, /* 0 - NUL */ 527*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 1 - SOH */ 528*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 2 - STX */ 529*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 3 - ETX */ 530*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 4 - EOT */ 531*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 5 - ENQ */ 532*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 6 - ACK */ 533*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 7 - BEL */ 534*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 8 - BS */ 535*69112eddSAli Bahrami 0, /* 9 - HT */ 536*69112eddSAli Bahrami 0, /* 10 - NL */ 537*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 11 - VT */ 538*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 12 - FF */ 539*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 13 - CR */ 540*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 14 - SO */ 541*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 15 - SI */ 542*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 16 - DLE */ 543*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 17 - DC1 */ 544*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 18 - DC2 */ 545*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 19 - DC3 */ 546*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 20 - DC4 */ 547*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 21 - NAK */ 548*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 22 - SYN */ 549*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 23 - ETB */ 550*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 24 - CAN */ 551*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 25 - EM */ 552*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 26 - SUB */ 553*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 27 - ESC */ 554*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 28 - FS */ 555*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 29 - GS */ 556*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 30 - RS */ 557*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 31 - US */ 558*69112eddSAli Bahrami 0, /* 32 - SP */ 559*69112eddSAli Bahrami TKID_ATTR(1), /* 33 - ! */ 560*69112eddSAli Bahrami 0, /* 34 - " */ 561*69112eddSAli Bahrami 0, /* 35 - # */ 562*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR_CONT(2), /* 36 - $ */ 563*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR_CONT(2), /* 37 - % */ 564*69112eddSAli Bahrami TKID_ATTR(1), /* 38 - & */ 565*69112eddSAli Bahrami TKID_ATTR(1), /* 39 - ' */ 566*69112eddSAli Bahrami TKID_ATTR(1), /* 40 - ( */ 567*69112eddSAli Bahrami TKID_ATTR(1), /* 41 - ) */ 568*69112eddSAli Bahrami TKID_ATTR(1), /* 42 - * */ 569*69112eddSAli Bahrami TKID_ATTR(1), /* 43 - + */ 570*69112eddSAli Bahrami TKID_ATTR(1), /* 44 - , */ 571*69112eddSAli Bahrami TKID_ATTR_CONT(1) | TKID_ATTR_CONT(2), /* 45 - - */ 572*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 46 - . */ 573*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 47 - / */ 574*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR_CONT(2), /* 48 - 0 */ 575*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR_CONT(2), /* 49 - 1 */ 576*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR_CONT(2), /* 50 - 2 */ 577*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR_CONT(2), /* 51 - 3 */ 578*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR_CONT(2), /* 52 - 4 */ 579*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR_CONT(2), /* 53 - 5 */ 580*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR_CONT(2), /* 54 - 6 */ 581*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR_CONT(2), /* 55 - 7 */ 582*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR_CONT(2), /* 56 - 8 */ 583*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR_CONT(2), /* 57 - 9 */ 584*69112eddSAli Bahrami 0, /* 58 - : */ 585*69112eddSAli Bahrami 0, /* 59 - ; */ 586*69112eddSAli Bahrami TKID_ATTR(1), /* 60 - < */ 587*69112eddSAli Bahrami 0, /* 61 - = */ 588*69112eddSAli Bahrami TKID_ATTR(1), /* 62 - > */ 589*69112eddSAli Bahrami TKID_ATTR(1), /* 63 - ? */ 590*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 64 - @ */ 591*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 65 - A */ 592*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 66 - B */ 593*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 67 - C */ 594*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 68 - D */ 595*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 69 - E */ 596*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 70 - F */ 597*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 71 - G */ 598*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 72 - H */ 599*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 73 - I */ 600*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 74 - J */ 601*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 75 - K */ 602*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 76 - L */ 603*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 77 - M */ 604*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 78 - N */ 605*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 79 - O */ 606*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 80 - P */ 607*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 81 - Q */ 608*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 82 - R */ 609*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 83 - S */ 610*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 84 - T */ 611*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 85 - U */ 612*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 86 - V */ 613*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 87 - W */ 614*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 88 - X */ 615*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 89 - Y */ 616*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 90 - Z */ 617*69112eddSAli Bahrami TKID_ATTR(1), /* 91 - [ */ 618*69112eddSAli Bahrami TKID_ATTR(1), /* 92 - \ */ 619*69112eddSAli Bahrami TKID_ATTR(1), /* 93 - ] */ 620*69112eddSAli Bahrami TKID_ATTR(1), /* 94 - ^ */ 621*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 95 - _ */ 622*69112eddSAli Bahrami TKID_ATTR(1), /* 96 - ` */ 623*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 97 - a */ 624*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 98 - b */ 625*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 99 - c */ 626*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 100 - d */ 627*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 101 - e */ 628*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 102 - f */ 629*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 103 - g */ 630*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 104 - h */ 631*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 105 - i */ 632*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 106 - j */ 633*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 107 - k */ 634*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 108 - l */ 635*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 109 - m */ 636*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 110 - n */ 637*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 111 - o */ 638*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 112 - p */ 639*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 113 - q */ 640*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 114 - r */ 641*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 115 - s */ 642*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 116 - t */ 643*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 117 - u */ 644*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 118 - v */ 645*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 119 - w */ 646*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 120 - x */ 647*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 121 - y */ 648*69112eddSAli Bahrami TKID_ATTR(1) | TKID_ATTR(2), /* 122 - z */ 649*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 123 - { */ 650*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 124 - | */ 651*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 125 - } */ 652*69112eddSAli Bahrami TKID_ATTR(1), /* 126 - ~ */ 653*69112eddSAli Bahrami TKID_ATTR_CONT(1), /* 127 - DEL */ 654*69112eddSAli Bahrami }; 655*69112eddSAli Bahrami 656*69112eddSAli Bahrami 657*69112eddSAli Bahrami /* 658*69112eddSAli Bahrami * Advance the given string pointer to the next newline character, 659*69112eddSAli Bahrami * or the terminating NULL if there is none. 660*69112eddSAli Bahrami */ 661*69112eddSAli Bahrami inline static void 662*69112eddSAli Bahrami advance_to_eol(char **str) 663*69112eddSAli Bahrami { 664*69112eddSAli Bahrami char *s = *str; 665*69112eddSAli Bahrami 666*69112eddSAli Bahrami while ((*s != '\n') && (*s != '\0')) 667*69112eddSAli Bahrami s++; 668*69112eddSAli Bahrami *str = s; 669*69112eddSAli Bahrami } 670*69112eddSAli Bahrami 671*69112eddSAli Bahrami /* 672*69112eddSAli Bahrami * Insert a NULL patch at the given address 673*69112eddSAli Bahrami */ 674*69112eddSAli Bahrami inline static void 675*69112eddSAli Bahrami null_patch_set(char *str, ld_map_npatch_t *np) 676*69112eddSAli Bahrami { 677*69112eddSAli Bahrami np->np_ptr = str; 678*69112eddSAli Bahrami np->np_ch = *str; 679*69112eddSAli Bahrami *str = '\0'; 680*69112eddSAli Bahrami } 681*69112eddSAli Bahrami 682*69112eddSAli Bahrami /* 683*69112eddSAli Bahrami * Undo a NULL patch 684*69112eddSAli Bahrami */ 685*69112eddSAli Bahrami inline static void 686*69112eddSAli Bahrami null_patch_undo(ld_map_npatch_t *np) 687*69112eddSAli Bahrami { 688*69112eddSAli Bahrami *np->np_ptr = np->np_ch; 689*69112eddSAli Bahrami } 690*69112eddSAli Bahrami 691*69112eddSAli Bahrami /* 692*69112eddSAli Bahrami * Insert a NULL patch at the end of the line containing str. 693*69112eddSAli Bahrami */ 694*69112eddSAli Bahrami static void 695*69112eddSAli Bahrami null_patch_eol(char *str, ld_map_npatch_t *np) 696*69112eddSAli Bahrami { 697*69112eddSAli Bahrami advance_to_eol(&str); 698*69112eddSAli Bahrami null_patch_set(str, np); 699*69112eddSAli Bahrami } 700*69112eddSAli Bahrami 701*69112eddSAli Bahrami /* 702*69112eddSAli Bahrami * Locate the end of an unquoted identifier. 703*69112eddSAli Bahrami * 704*69112eddSAli Bahrami * entry: 705*69112eddSAli Bahrami * mf - Mapfile descriptor, positioned to first character 706*69112eddSAli Bahrami * of identifier. 707*69112eddSAli Bahrami * 708*69112eddSAli Bahrami * exit: 709*69112eddSAli Bahrami * If the item pointed at by mf is not an identifier, returns NULL. 710*69112eddSAli Bahrami * Otherwise, returns pointer to character after the last character 711*69112eddSAli Bahrami * of the identifier. 712*69112eddSAli Bahrami */ 713*69112eddSAli Bahrami inline static char * 714*69112eddSAli Bahrami ident_delimit(Mapfile *mf) 715*69112eddSAli Bahrami { 716*69112eddSAli Bahrami char *str = mf->mf_next; 717*69112eddSAli Bahrami ld_map_npatch_t np; 718*69112eddSAli Bahrami int c = *str++; 719*69112eddSAli Bahrami 720*69112eddSAli Bahrami /* If not a valid start character, report the error */ 721*69112eddSAli Bahrami if ((c & 0x80) || !(tkid_attr[c] & mf->mf_tkid_start)) { 722*69112eddSAli Bahrami null_patch_set(str, &np); 723*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_BADCHAR), str); 724*69112eddSAli Bahrami null_patch_undo(&np); 725*69112eddSAli Bahrami return (NULL); 726*69112eddSAli Bahrami } 727*69112eddSAli Bahrami 728*69112eddSAli Bahrami /* Keep going until we hit a non-continuing character */ 729*69112eddSAli Bahrami for (c = *str; !(c & 0x80) && (tkid_attr[c] & mf->mf_tkid_cont); 730*69112eddSAli Bahrami c = *++str) 731*69112eddSAli Bahrami ; 732*69112eddSAli Bahrami 733*69112eddSAli Bahrami return (str); 734*69112eddSAli Bahrami } 735*69112eddSAli Bahrami 736*69112eddSAli Bahrami /* 737*69112eddSAli Bahrami * Allocate memory for a stack. 738*69112eddSAli Bahrami * 739*69112eddSAli Bahrami * entry: 740*69112eddSAli Bahrami * stack - Pointer to stack for which memory is required, cast 741*69112eddSAli Bahrami * to the generic stack type. 742*69112eddSAli Bahrami * n_default - Size to use for initial allocation. 743*69112eddSAli Bahrami * elt_size - sizeof(elt), where elt is the actual stack data type. 744*69112eddSAli Bahrami * 745*69112eddSAli Bahrami * exit: 746*69112eddSAli Bahrami * Returns (1) on success. On error (memory allocation), a message 747*69112eddSAli Bahrami * is printed and False (0) is returned. 748*69112eddSAli Bahrami * 749*69112eddSAli Bahrami * note: 750*69112eddSAli Bahrami * The caller casts the pointer to their actual datatype-specific stack 751*69112eddSAli Bahrami * to be a (generic_stack_t *). The C language will give all stack 752*69112eddSAli Bahrami * structs the same size and layout as long as the underlying platform 753*69112eddSAli Bahrami * uses a single integral type for pointers. Hence, this cast is safe, 754*69112eddSAli Bahrami * and lets a generic routine modify data-specific types without being 755*69112eddSAli Bahrami * aware of those types. 756*69112eddSAli Bahrami */ 757*69112eddSAli Bahrami static Boolean 758*69112eddSAli Bahrami stack_resize(generic_stack_t *stack, size_t n_default, size_t elt_size) 759*69112eddSAli Bahrami { 760*69112eddSAli Bahrami size_t new_n_alloc; 761*69112eddSAli Bahrami void *newaddr; 762*69112eddSAli Bahrami 763*69112eddSAli Bahrami /* Use initial size first, and double the allocation on each call */ 764*69112eddSAli Bahrami new_n_alloc = (stack->stk_n_alloc == 0) ? 765*69112eddSAli Bahrami n_default : (stack->stk_n_alloc * 2); 766*69112eddSAli Bahrami 767*69112eddSAli Bahrami newaddr = libld_realloc(stack->stk_s, new_n_alloc * elt_size); 768*69112eddSAli Bahrami if (newaddr == NULL) 769*69112eddSAli Bahrami return (FALSE); 770*69112eddSAli Bahrami 771*69112eddSAli Bahrami stack->stk_s = newaddr; 772*69112eddSAli Bahrami stack->stk_n_alloc = new_n_alloc; 773*69112eddSAli Bahrami return (TRUE); 774*69112eddSAli Bahrami } 775*69112eddSAli Bahrami 776*69112eddSAli Bahrami /* 777*69112eddSAli Bahrami * AVL comparison function for cexp_id_node_t items. 778*69112eddSAli Bahrami * 779*69112eddSAli Bahrami * entry: 780*69112eddSAli Bahrami * n1, n2 - pointers to nodes to be compared 781*69112eddSAli Bahrami * 782*69112eddSAli Bahrami * exit: 783*69112eddSAli Bahrami * Returns -1 if (n1 < n2), 0 if they are equal, and 1 if (n1 > n2) 784*69112eddSAli Bahrami */ 785*69112eddSAli Bahrami static int 786*69112eddSAli Bahrami cexp_ident_cmp(const void *n1, const void *n2) 787*69112eddSAli Bahrami { 788*69112eddSAli Bahrami int rc; 789*69112eddSAli Bahrami 790*69112eddSAli Bahrami rc = strcmp(((cexp_id_node_t *)n1)->ceid_name, 791*69112eddSAli Bahrami ((cexp_id_node_t *)n2)->ceid_name); 792*69112eddSAli Bahrami 793*69112eddSAli Bahrami if (rc > 0) 794*69112eddSAli Bahrami return (1); 795*69112eddSAli Bahrami if (rc < 0) 796*69112eddSAli Bahrami return (-1); 797*69112eddSAli Bahrami return (0); 798*69112eddSAli Bahrami } 799*69112eddSAli Bahrami 800*69112eddSAli Bahrami 801*69112eddSAli Bahrami /* 802*69112eddSAli Bahrami * Returns True (1) if name is in the conditional expression identifier 803*69112eddSAli Bahrami * AVL tree, and False (0) otherwise. 804*69112eddSAli Bahrami */ 805*69112eddSAli Bahrami static int 806*69112eddSAli Bahrami cexp_ident_test(const char *name) 807*69112eddSAli Bahrami { 808*69112eddSAli Bahrami cexp_id_node_t node; 809*69112eddSAli Bahrami 810*69112eddSAli Bahrami node.ceid_name = name; 811*69112eddSAli Bahrami return (avl_find(lms.lms_cexp_id, &node, 0) != NULL); 812*69112eddSAli Bahrami } 813*69112eddSAli Bahrami 814*69112eddSAli Bahrami /* 815*69112eddSAli Bahrami * Add a new boolean identifier to the conditional expression identifier 816*69112eddSAli Bahrami * AVL tree. 817*69112eddSAli Bahrami * 818*69112eddSAli Bahrami * entry: 819*69112eddSAli Bahrami * mf - If non-NULL, the mapfile descriptor for the mapfile 820*69112eddSAli Bahrami * containing the $add directive. NULL if this is an 821*69112eddSAli Bahrami * initialization call. 822*69112eddSAli Bahrami * name - Name of identifier. Must point at stable storage that will 823*69112eddSAli Bahrami * not be moved or modified by the caller following this call. 824*69112eddSAli Bahrami * 825*69112eddSAli Bahrami * exit: 826*69112eddSAli Bahrami * On success, True (1) is returned and name has been entered. 827*69112eddSAli Bahrami * On failure, False (0) is returned and an error has been printed. 828*69112eddSAli Bahrami */ 829*69112eddSAli Bahrami static int 830*69112eddSAli Bahrami cexp_ident_add(Mapfile *mf, const char *name) 831*69112eddSAli Bahrami { 832*69112eddSAli Bahrami cexp_id_node_t *node; 833*69112eddSAli Bahrami 834*69112eddSAli Bahrami if (mf != NULL) { 835*69112eddSAli Bahrami DBG_CALL(Dbg_map_cexp_id(mf->mf_ofl->ofl_lml, 1, 836*69112eddSAli Bahrami mf->mf_name, mf->mf_lineno, name)); 837*69112eddSAli Bahrami 838*69112eddSAli Bahrami /* If is already known, don't do it again */ 839*69112eddSAli Bahrami if (cexp_ident_test(name)) 840*69112eddSAli Bahrami return (1); 841*69112eddSAli Bahrami } 842*69112eddSAli Bahrami 843*69112eddSAli Bahrami if ((node = libld_calloc(sizeof (*node), 1)) == NULL) 844*69112eddSAli Bahrami return (0); 845*69112eddSAli Bahrami node->ceid_name = name; 846*69112eddSAli Bahrami avl_add(lms.lms_cexp_id, node); 847*69112eddSAli Bahrami return (1); 848*69112eddSAli Bahrami } 849*69112eddSAli Bahrami 850*69112eddSAli Bahrami /* 851*69112eddSAli Bahrami * Remove a boolean identifier from the conditional expression identifier 852*69112eddSAli Bahrami * AVL tree. 853*69112eddSAli Bahrami * 854*69112eddSAli Bahrami * entry: 855*69112eddSAli Bahrami * mf - Mapfile descriptor 856*69112eddSAli Bahrami * name - Name of identifier. 857*69112eddSAli Bahrami * 858*69112eddSAli Bahrami * exit: 859*69112eddSAli Bahrami * If the name was in the tree, it has been removed. If not, 860*69112eddSAli Bahrami * then this routine quietly returns. 861*69112eddSAli Bahrami */ 862*69112eddSAli Bahrami static void 863*69112eddSAli Bahrami cexp_ident_clear(Mapfile *mf, const char *name) 864*69112eddSAli Bahrami { 865*69112eddSAli Bahrami cexp_id_node_t node; 866*69112eddSAli Bahrami cexp_id_node_t *real_node; 867*69112eddSAli Bahrami 868*69112eddSAli Bahrami DBG_CALL(Dbg_map_cexp_id(mf->mf_ofl->ofl_lml, 0, 869*69112eddSAli Bahrami mf->mf_name, mf->mf_lineno, name)); 870*69112eddSAli Bahrami 871*69112eddSAli Bahrami node.ceid_name = name; 872*69112eddSAli Bahrami real_node = avl_find(lms.lms_cexp_id, &node, 0); 873*69112eddSAli Bahrami if (real_node != NULL) 874*69112eddSAli Bahrami avl_remove(lms.lms_cexp_id, real_node); 875*69112eddSAli Bahrami } 876*69112eddSAli Bahrami 877*69112eddSAli Bahrami /* 878*69112eddSAli Bahrami * Initialize the AVL tree that holds the names of the currently defined 879*69112eddSAli Bahrami * boolean identifiers for conditional expressions ($if/$elif). 880*69112eddSAli Bahrami * 881*69112eddSAli Bahrami * entry: 882*69112eddSAli Bahrami * ofl - Output file descriptor 883*69112eddSAli Bahrami * 884*69112eddSAli Bahrami * exit: 885*69112eddSAli Bahrami * On success, TRUE (1) is returned and lms.lms_cexp_id is ready for use. 886*69112eddSAli Bahrami * On failure, FALSE (0) is returned. 887*69112eddSAli Bahrami */ 888*69112eddSAli Bahrami static Boolean 889*69112eddSAli Bahrami cexp_ident_init(void) 890*69112eddSAli Bahrami { 891*69112eddSAli Bahrami /* If already done, use it */ 892*69112eddSAli Bahrami if (lms.lms_cexp_id != NULL) 893*69112eddSAli Bahrami return (TRUE); 894*69112eddSAli Bahrami 895*69112eddSAli Bahrami lms.lms_cexp_id = libld_calloc(sizeof (*lms.lms_cexp_id), 1); 896*69112eddSAli Bahrami if (lms.lms_cexp_id == NULL) 897*69112eddSAli Bahrami return (FALSE); 898*69112eddSAli Bahrami avl_create(lms.lms_cexp_id, cexp_ident_cmp, sizeof (cexp_id_node_t), 899*69112eddSAli Bahrami SGSOFFSETOF(cexp_id_node_t, ceid_avlnode)); 900*69112eddSAli Bahrami 901*69112eddSAli Bahrami 902*69112eddSAli Bahrami /* ELFCLASS */ 903*69112eddSAli Bahrami if (cexp_ident_add(NULL, (ld_targ.t_m.m_class == ELFCLASS32) ? 904*69112eddSAli Bahrami MSG_ORIG(MSG_STR_UELF32) : MSG_ORIG(MSG_STR_UELF64)) == 0) 905*69112eddSAli Bahrami return (FALSE); 906*69112eddSAli Bahrami 907*69112eddSAli Bahrami /* Machine */ 908*69112eddSAli Bahrami switch (ld_targ.t_m.m_mach) { 909*69112eddSAli Bahrami case EM_386: 910*69112eddSAli Bahrami case EM_AMD64: 911*69112eddSAli Bahrami if (cexp_ident_add(NULL, MSG_ORIG(MSG_STR_UX86)) == 0) 912*69112eddSAli Bahrami return (FALSE); 913*69112eddSAli Bahrami break; 914*69112eddSAli Bahrami 915*69112eddSAli Bahrami case EM_SPARC: 916*69112eddSAli Bahrami case EM_SPARCV9: 917*69112eddSAli Bahrami if (cexp_ident_add(NULL, MSG_ORIG(MSG_STR_USPARC)) == 0) 918*69112eddSAli Bahrami return (FALSE); 919*69112eddSAli Bahrami break; 920*69112eddSAli Bahrami } 921*69112eddSAli Bahrami 922*69112eddSAli Bahrami /* true is always defined */ 923*69112eddSAli Bahrami if (cexp_ident_add(NULL, MSG_ORIG(MSG_STR_TRUE)) == 0) 924*69112eddSAli Bahrami return (FALSE); 925*69112eddSAli Bahrami 926*69112eddSAli Bahrami return (TRUE); 927*69112eddSAli Bahrami } 928*69112eddSAli Bahrami 929*69112eddSAli Bahrami /* 930*69112eddSAli Bahrami * Validate the string starting at mf->mf_next as being a 931*69112eddSAli Bahrami * boolean conditional expression identifier. 932*69112eddSAli Bahrami * 933*69112eddSAli Bahrami * entry: 934*69112eddSAli Bahrami * mf - Mapfile descriptor 935*69112eddSAli Bahrami * len - NULL, or address of variable to receive strlen() of identifier 936*69112eddSAli Bahrami * directive - If (len == NULL), string giving name of directive being 937*69112eddSAli Bahrami * processed. Ignored if (len != NULL). 938*69112eddSAli Bahrami * 939*69112eddSAli Bahrami * exit: 940*69112eddSAli Bahrami * On success: 941*69112eddSAli Bahrami * - If len is NULL, a NULL is inserted following the final 942*69112eddSAli Bahrami * character of the identifier, and the remainder of the string 943*69112eddSAli Bahrami * is tested to ensure it is empty, or only contains whitespace. 944*69112eddSAli Bahrami * - If len is non-NULL, *len is set to the number of characters 945*69112eddSAli Bahrami * in the identifier, and the rest of the string is not modified. 946*69112eddSAli Bahrami * - TRUE (1) is returned 947*69112eddSAli Bahrami * 948*69112eddSAli Bahrami * On failure, returns FALSE (0). 949*69112eddSAli Bahrami */ 950*69112eddSAli Bahrami static Boolean 951*69112eddSAli Bahrami cexp_ident_validate(Mapfile *mf, size_t *len, const char *directive) 952*69112eddSAli Bahrami { 953*69112eddSAli Bahrami char *tail; 954*69112eddSAli Bahrami 955*69112eddSAli Bahrami if ((tail = ident_delimit(mf)) == NULL) 956*69112eddSAli Bahrami return (FALSE); 957*69112eddSAli Bahrami 958*69112eddSAli Bahrami /* 959*69112eddSAli Bahrami * If len is non-NULL, we simple count the number of characters 960*69112eddSAli Bahrami * consumed by the identifier and are done. If len is NULL, then 961*69112eddSAli Bahrami * ensure there's nothing left but whitespace, and NULL terminate 962*69112eddSAli Bahrami * the identifier to remove it. 963*69112eddSAli Bahrami */ 964*69112eddSAli Bahrami if (len != NULL) { 965*69112eddSAli Bahrami *len = tail - mf->mf_next; 966*69112eddSAli Bahrami } else if (*tail != '\0') { 967*69112eddSAli Bahrami *tail++ = '\0'; 968*69112eddSAli Bahrami while (isspace(*tail)) 969*69112eddSAli Bahrami tail++; 970*69112eddSAli Bahrami if (*tail != '\0') { 971*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_BADEXTRA), directive); 972*69112eddSAli Bahrami return (FALSE); 973*69112eddSAli Bahrami } 974*69112eddSAli Bahrami } 975*69112eddSAli Bahrami 976*69112eddSAli Bahrami return (TRUE); 977*69112eddSAli Bahrami } 978*69112eddSAli Bahrami 979*69112eddSAli Bahrami /* 980*69112eddSAli Bahrami * Push a new operator onto the conditional expression operator stack. 981*69112eddSAli Bahrami * 982*69112eddSAli Bahrami * entry: 983*69112eddSAli Bahrami * mf - Mapfile descriptor 984*69112eddSAli Bahrami * op - Operator to push 985*69112eddSAli Bahrami * 986*69112eddSAli Bahrami * exit: 987*69112eddSAli Bahrami * On success, TRUE (1) is returned, otherwise FALSE (0). 988*69112eddSAli Bahrami */ 989*69112eddSAli Bahrami static Boolean 990*69112eddSAli Bahrami cexp_push_op(cexp_op_t op) 991*69112eddSAli Bahrami { 992*69112eddSAli Bahrami if (STACK_RESERVE(lms.lms_cexp_op_stack, CEXP_OP_STACK_INIT) == 0) 993*69112eddSAli Bahrami return (FALSE); 994*69112eddSAli Bahrami 995*69112eddSAli Bahrami STACK_PUSH(lms.lms_cexp_op_stack) = op; 996*69112eddSAli Bahrami return (TRUE); 997*69112eddSAli Bahrami } 998*69112eddSAli Bahrami 999*69112eddSAli Bahrami /* 1000*69112eddSAli Bahrami * Evaluate the basic operator (non-paren) at the top of lms.lms_cexp_op_stack, 1001*69112eddSAli Bahrami * and push the results on lms.lms_cexp_val_stack. 1002*69112eddSAli Bahrami * 1003*69112eddSAli Bahrami * exit: 1004*69112eddSAli Bahrami * On success, returns TRUE (1). On error, FALSE (0) is returned, 1005*69112eddSAli Bahrami * and the caller is responsible for issuing the error. 1006*69112eddSAli Bahrami */ 1007*69112eddSAli Bahrami static Boolean 1008*69112eddSAli Bahrami cexp_eval_op(void) 1009*69112eddSAli Bahrami { 1010*69112eddSAli Bahrami cexp_op_t op; 1011*69112eddSAli Bahrami uchar_t val; 1012*69112eddSAli Bahrami 1013*69112eddSAli Bahrami op = STACK_POP(lms.lms_cexp_op_stack); 1014*69112eddSAli Bahrami switch (op) { 1015*69112eddSAli Bahrami case CEXP_OP_AND: 1016*69112eddSAli Bahrami if (lms.lms_cexp_val_stack.stk_n < 2) 1017*69112eddSAli Bahrami return (FALSE); 1018*69112eddSAli Bahrami val = STACK_POP(lms.lms_cexp_val_stack); 1019*69112eddSAli Bahrami STACK_TOP(lms.lms_cexp_val_stack) = val && 1020*69112eddSAli Bahrami STACK_TOP(lms.lms_cexp_val_stack); 1021*69112eddSAli Bahrami break; 1022*69112eddSAli Bahrami 1023*69112eddSAli Bahrami case CEXP_OP_OR: 1024*69112eddSAli Bahrami if (lms.lms_cexp_val_stack.stk_n < 2) 1025*69112eddSAli Bahrami return (FALSE); 1026*69112eddSAli Bahrami val = STACK_POP(lms.lms_cexp_val_stack); 1027*69112eddSAli Bahrami STACK_TOP(lms.lms_cexp_val_stack) = val || 1028*69112eddSAli Bahrami STACK_TOP(lms.lms_cexp_val_stack); 1029*69112eddSAli Bahrami break; 1030*69112eddSAli Bahrami 1031*69112eddSAli Bahrami case CEXP_OP_NEG: 1032*69112eddSAli Bahrami if (lms.lms_cexp_val_stack.stk_n < 1) 1033*69112eddSAli Bahrami return (FALSE); 1034*69112eddSAli Bahrami STACK_TOP(lms.lms_cexp_val_stack) = 1035*69112eddSAli Bahrami !STACK_TOP(lms.lms_cexp_val_stack); 1036*69112eddSAli Bahrami break; 1037*69112eddSAli Bahrami default: 1038*69112eddSAli Bahrami return (FALSE); 1039*69112eddSAli Bahrami } 1040*69112eddSAli Bahrami 1041*69112eddSAli Bahrami return (TRUE); 1042*69112eddSAli Bahrami } 1043*69112eddSAli Bahrami 1044*69112eddSAli Bahrami /* 1045*69112eddSAli Bahrami * Evaluate an expression for a $if/$elif control directive. 1046*69112eddSAli Bahrami * 1047*69112eddSAli Bahrami * entry: 1048*69112eddSAli Bahrami * mf - Mapfile descriptor for NULL terminated string 1049*69112eddSAli Bahrami * containing the expression. 1050*69112eddSAli Bahrami * 1051*69112eddSAli Bahrami * exit: 1052*69112eddSAli Bahrami * The contents of str are modified by this routine. 1053*69112eddSAli Bahrami * One of the following values are returned: 1054*69112eddSAli Bahrami * -1 Syntax error encountered (an error is printed) 1055*69112eddSAli Bahrami * 0 The expression evaluates to False 1056*69112eddSAli Bahrami * 1 The expression evaluates to True. 1057*69112eddSAli Bahrami * 1058*69112eddSAli Bahrami * note: 1059*69112eddSAli Bahrami * A simplified version of Dijkstra's Shunting Yard algorithm is used 1060*69112eddSAli Bahrami * to convert this syntax into postfix form and then evaluate it. 1061*69112eddSAli Bahrami * Our version has no functions and a tiny set of operators. 1062*69112eddSAli Bahrami * 1063*69112eddSAli Bahrami * The expressions consist of boolean identifiers, which can be 1064*69112eddSAli Bahrami * combined using the following operators, listed from highest 1065*69112eddSAli Bahrami * precedence to least: 1066*69112eddSAli Bahrami * 1067*69112eddSAli Bahrami * Operator Meaning 1068*69112eddSAli Bahrami * ------------------------------------------------- 1069*69112eddSAli Bahrami * (expr) sub-expression, non-associative 1070*69112eddSAli Bahrami * ! logical negation, prefix, left associative 1071*69112eddSAli Bahrami * && || logical and/or, binary, left associative 1072*69112eddSAli Bahrami * 1073*69112eddSAli Bahrami * The operands manipulated by these operators are names, consisting of 1074*69112eddSAli Bahrami * a sequence of letters and digits. The first character must be a letter. 1075*69112eddSAli Bahrami * Underscore (_) and period (.) are also considered to be characters. 1076*69112eddSAli Bahrami * An operand is considered True if it is found in our set of known 1077*69112eddSAli Bahrami * names (lms.lms_cexp_id), and False otherwise. 1078*69112eddSAli Bahrami * 1079*69112eddSAli Bahrami * The Shunting Yard algorithm works using two stacks, one for operators, 1080*69112eddSAli Bahrami * and a second for operands. The infix input expression is tokenized from 1081*69112eddSAli Bahrami * left to right and processed in order. Issues of associativity and 1082*69112eddSAli Bahrami * precedence are managed by reducing (poping and evaluating) items with 1083*69112eddSAli Bahrami * higer precedence before pushing additional tokens with lower precedence. 1084*69112eddSAli Bahrami */ 1085*69112eddSAli Bahrami static int 1086*69112eddSAli Bahrami cexp_eval_expr(Mapfile *mf) 1087*69112eddSAli Bahrami { 1088*69112eddSAli Bahrami char *ident; 1089*69112eddSAli Bahrami size_t len; 1090*69112eddSAli Bahrami cexp_op_t new_op = CEXP_OP_AND; /* to catch binop at start */ 1091*69112eddSAli Bahrami ld_map_npatch_t np; 1092*69112eddSAli Bahrami char *str = mf->mf_next; 1093*69112eddSAli Bahrami 1094*69112eddSAli Bahrami STACK_RESET(lms.lms_cexp_op_stack); 1095*69112eddSAli Bahrami STACK_RESET(lms.lms_cexp_val_stack); 1096*69112eddSAli Bahrami 1097*69112eddSAli Bahrami for (; *str; str++) { 1098*69112eddSAli Bahrami 1099*69112eddSAli Bahrami /* Skip whitespace */ 1100*69112eddSAli Bahrami while (isspace(*str)) 1101*69112eddSAli Bahrami str++; 1102*69112eddSAli Bahrami if (!*str) 1103*69112eddSAli Bahrami break; 1104*69112eddSAli Bahrami 1105*69112eddSAli Bahrami switch (*str) { 1106*69112eddSAli Bahrami case '&': 1107*69112eddSAli Bahrami case '|': 1108*69112eddSAli Bahrami if (*(str + 1) != *str) 1109*69112eddSAli Bahrami goto token_error; 1110*69112eddSAli Bahrami if ((new_op != CEXP_OP_NONE) && 1111*69112eddSAli Bahrami (new_op != CEXP_OP_CPAR)) { 1112*69112eddSAli Bahrami mf_fatal0(mf, MSG_INTL(MSG_MAP_CEXP_BADOPUSE)); 1113*69112eddSAli Bahrami return (-1); 1114*69112eddSAli Bahrami } 1115*69112eddSAli Bahrami str++; 1116*69112eddSAli Bahrami 1117*69112eddSAli Bahrami /* 1118*69112eddSAli Bahrami * As this is a left associative binary operator, we 1119*69112eddSAli Bahrami * need to process all operators of equal or higher 1120*69112eddSAli Bahrami * precedence before pushing the new operator. 1121*69112eddSAli Bahrami */ 1122*69112eddSAli Bahrami while (!STACK_IS_EMPTY(lms.lms_cexp_op_stack)) { 1123*69112eddSAli Bahrami cexp_op_t op = STACK_TOP(lms.lms_cexp_op_stack); 1124*69112eddSAli Bahrami 1125*69112eddSAli Bahrami 1126*69112eddSAli Bahrami if ((op != CEXP_OP_AND) && (op != CEXP_OP_OR) && 1127*69112eddSAli Bahrami (op != CEXP_OP_NEG)) 1128*69112eddSAli Bahrami break; 1129*69112eddSAli Bahrami 1130*69112eddSAli Bahrami if (!cexp_eval_op()) 1131*69112eddSAli Bahrami goto semantic_error; 1132*69112eddSAli Bahrami } 1133*69112eddSAli Bahrami 1134*69112eddSAli Bahrami new_op = (*str == '&') ? CEXP_OP_AND : CEXP_OP_OR; 1135*69112eddSAli Bahrami if (!cexp_push_op(new_op)) 1136*69112eddSAli Bahrami return (-1); 1137*69112eddSAli Bahrami break; 1138*69112eddSAli Bahrami 1139*69112eddSAli Bahrami case '!': 1140*69112eddSAli Bahrami new_op = CEXP_OP_NEG; 1141*69112eddSAli Bahrami if (!cexp_push_op(new_op)) 1142*69112eddSAli Bahrami return (-1); 1143*69112eddSAli Bahrami break; 1144*69112eddSAli Bahrami 1145*69112eddSAli Bahrami case '(': 1146*69112eddSAli Bahrami new_op = CEXP_OP_OPAR; 1147*69112eddSAli Bahrami if (!cexp_push_op(new_op)) 1148*69112eddSAli Bahrami return (-1); 1149*69112eddSAli Bahrami break; 1150*69112eddSAli Bahrami 1151*69112eddSAli Bahrami case ')': 1152*69112eddSAli Bahrami new_op = CEXP_OP_CPAR; 1153*69112eddSAli Bahrami 1154*69112eddSAli Bahrami /* Evaluate the operator stack until reach '(' */ 1155*69112eddSAli Bahrami while (!STACK_IS_EMPTY(lms.lms_cexp_op_stack) && 1156*69112eddSAli Bahrami (STACK_TOP(lms.lms_cexp_op_stack) != CEXP_OP_OPAR)) 1157*69112eddSAli Bahrami if (!cexp_eval_op()) 1158*69112eddSAli Bahrami goto semantic_error; 1159*69112eddSAli Bahrami 1160*69112eddSAli Bahrami /* 1161*69112eddSAli Bahrami * If the top of operator stack is not an open paren, 1162*69112eddSAli Bahrami * when we have an error. In this case, the operator 1163*69112eddSAli Bahrami * stack will be empty due to the loop above. 1164*69112eddSAli Bahrami */ 1165*69112eddSAli Bahrami if (STACK_IS_EMPTY(lms.lms_cexp_op_stack)) 1166*69112eddSAli Bahrami goto unbalpar_error; 1167*69112eddSAli Bahrami lms.lms_cexp_op_stack.stk_n--; /* Pop OPAR */ 1168*69112eddSAli Bahrami break; 1169*69112eddSAli Bahrami 1170*69112eddSAli Bahrami default: 1171*69112eddSAli Bahrami /* Ensure there's room to push another operand */ 1172*69112eddSAli Bahrami if (STACK_RESERVE(lms.lms_cexp_val_stack, 1173*69112eddSAli Bahrami CEXP_VAL_STACK_INIT) == 0) 1174*69112eddSAli Bahrami return (0); 1175*69112eddSAli Bahrami new_op = CEXP_OP_NONE; 1176*69112eddSAli Bahrami 1177*69112eddSAli Bahrami /* 1178*69112eddSAli Bahrami * Operands cannot be numbers. However, we accept two 1179*69112eddSAli Bahrami * special cases: '0' means false, and '1' is true. 1180*69112eddSAli Bahrami * This is done to support the common C idiom of 1181*69112eddSAli Bahrami * '#if 1' and '#if 0' to conditionalize code under 1182*69112eddSAli Bahrami * development. 1183*69112eddSAli Bahrami */ 1184*69112eddSAli Bahrami if ((*str == '0') || (*str == '1')) { 1185*69112eddSAli Bahrami STACK_PUSH(lms.lms_cexp_val_stack) = 1186*69112eddSAli Bahrami (*str == '1'); 1187*69112eddSAli Bahrami break; 1188*69112eddSAli Bahrami } 1189*69112eddSAli Bahrami 1190*69112eddSAli Bahrami /* Look up the identifier */ 1191*69112eddSAli Bahrami ident = mf->mf_next = str; 1192*69112eddSAli Bahrami if (!cexp_ident_validate(mf, &len, NULL)) 1193*69112eddSAli Bahrami return (-1); 1194*69112eddSAli Bahrami str += len - 1; /* loop will advance past final ch */ 1195*69112eddSAli Bahrami null_patch_set(&ident[len], &np); 1196*69112eddSAli Bahrami STACK_PUSH(lms.lms_cexp_val_stack) = 1197*69112eddSAli Bahrami cexp_ident_test(ident); 1198*69112eddSAli Bahrami null_patch_undo(&np); 1199*69112eddSAli Bahrami 1200*69112eddSAli Bahrami break; 1201*69112eddSAli Bahrami } 1202*69112eddSAli Bahrami } 1203*69112eddSAli Bahrami 1204*69112eddSAli Bahrami /* Evaluate the operator stack until empty */ 1205*69112eddSAli Bahrami while (!STACK_IS_EMPTY(lms.lms_cexp_op_stack)) { 1206*69112eddSAli Bahrami if (STACK_TOP(lms.lms_cexp_op_stack) == CEXP_OP_OPAR) 1207*69112eddSAli Bahrami goto unbalpar_error; 1208*69112eddSAli Bahrami 1209*69112eddSAli Bahrami if (!cexp_eval_op()) 1210*69112eddSAli Bahrami goto semantic_error; 1211*69112eddSAli Bahrami } 1212*69112eddSAli Bahrami 1213*69112eddSAli Bahrami /* There should be exactly one value left */ 1214*69112eddSAli Bahrami if (lms.lms_cexp_val_stack.stk_n != 1) 1215*69112eddSAli Bahrami goto semantic_error; 1216*69112eddSAli Bahrami 1217*69112eddSAli Bahrami /* Final value is the result */ 1218*69112eddSAli Bahrami return (lms.lms_cexp_val_stack.stk_s[0]); 1219*69112eddSAli Bahrami 1220*69112eddSAli Bahrami /* Errors issued more than once are handled below, accessed via goto */ 1221*69112eddSAli Bahrami 1222*69112eddSAli Bahrami token_error: /* unexpected characters in input stream */ 1223*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_CEXP_TOKERR), str); 1224*69112eddSAli Bahrami return (-1); 1225*69112eddSAli Bahrami 1226*69112eddSAli Bahrami semantic_error: /* valid tokens, but in invalid arrangement */ 1227*69112eddSAli Bahrami mf_fatal0(mf, MSG_INTL(MSG_MAP_CEXP_SEMERR)); 1228*69112eddSAli Bahrami return (-1); 1229*69112eddSAli Bahrami 1230*69112eddSAli Bahrami unbalpar_error: /* Extra or missing parenthesis */ 1231*69112eddSAli Bahrami mf_fatal0(mf, MSG_INTL(MSG_MAP_CEXP_UNBALPAR)); 1232*69112eddSAli Bahrami return (-1); 1233*69112eddSAli Bahrami } 1234*69112eddSAli Bahrami 1235*69112eddSAli Bahrami /* 1236*69112eddSAli Bahrami * Process a mapfile control directive. These directives start with 1237*69112eddSAli Bahrami * the dollar character, and are used to manage details of the mapfile 1238*69112eddSAli Bahrami * itself, such as version and conditional input. 1239*69112eddSAli Bahrami * 1240*69112eddSAli Bahrami * entry: 1241*69112eddSAli Bahrami * mf - Mapfile descriptor 1242*69112eddSAli Bahrami * 1243*69112eddSAli Bahrami * exit: 1244*69112eddSAli Bahrami * Returns TRUE (1) for success, and FALSE (0) on error. In the 1245*69112eddSAli Bahrami * error case, a descriptive error is issued. 1246*69112eddSAli Bahrami */ 1247*69112eddSAli Bahrami static Boolean 1248*69112eddSAli Bahrami cdir_process(Mapfile *mf) 1249*69112eddSAli Bahrami { 1250*69112eddSAli Bahrami typedef enum { /* Directive types */ 1251*69112eddSAli Bahrami CDIR_T_UNKNOWN = 0, /* Unrecognized control directive */ 1252*69112eddSAli Bahrami CDIR_T_ADD, /* $add */ 1253*69112eddSAli Bahrami CDIR_T_CLEAR, /* $clear */ 1254*69112eddSAli Bahrami CDIR_T_ERROR, /* $error */ 1255*69112eddSAli Bahrami CDIR_T_VERSION, /* $mapfile_version */ 1256*69112eddSAli Bahrami CDIR_T_IF, /* $if */ 1257*69112eddSAli Bahrami CDIR_T_ELIF, /* $elif */ 1258*69112eddSAli Bahrami CDIR_T_ELSE, /* $else */ 1259*69112eddSAli Bahrami CDIR_T_ENDIF, /* $endif */ 1260*69112eddSAli Bahrami } cdir_t; 1261*69112eddSAli Bahrami 1262*69112eddSAli Bahrami typedef enum { /* Types of arguments accepted by directives */ 1263*69112eddSAli Bahrami ARG_T_NONE, /* Directive takes no arguments */ 1264*69112eddSAli Bahrami ARG_T_EXPR, /* Directive takes a conditional expression */ 1265*69112eddSAli Bahrami ARG_T_ID, /* Conditional expression identifier */ 1266*69112eddSAli Bahrami ARG_T_STR, /* Non-empty string */ 1267*69112eddSAli Bahrami ARG_T_IGN /* Ignore the argument */ 1268*69112eddSAli Bahrami } cdir_arg_t; 1269*69112eddSAli Bahrami 1270*69112eddSAli Bahrami typedef struct { 1271*69112eddSAli Bahrami const char *md_name; /* Directive name */ 1272*69112eddSAli Bahrami size_t md_size; /* strlen(md_name) */ 1273*69112eddSAli Bahrami cdir_arg_t md_arg; /* Type of arguments */ 1274*69112eddSAli Bahrami cdir_t md_op; /* CDIR_T_ code */ 1275*69112eddSAli Bahrami } cdir_match_t; 1276*69112eddSAli Bahrami 1277*69112eddSAli Bahrami /* Control Directives: The most likely items are listed first */ 1278*69112eddSAli Bahrami static cdir_match_t match_data[] = { 1279*69112eddSAli Bahrami { MSG_ORIG(MSG_STR_CDIR_IF), MSG_STR_CDIR_IF_SIZE, 1280*69112eddSAli Bahrami ARG_T_EXPR, CDIR_T_IF }, 1281*69112eddSAli Bahrami { MSG_ORIG(MSG_STR_CDIR_ENDIF), MSG_STR_CDIR_ENDIF_SIZE, 1282*69112eddSAli Bahrami ARG_T_NONE, CDIR_T_ENDIF }, 1283*69112eddSAli Bahrami { MSG_ORIG(MSG_STR_CDIR_ELSE), MSG_STR_CDIR_ELSE_SIZE, 1284*69112eddSAli Bahrami ARG_T_NONE, CDIR_T_ELSE }, 1285*69112eddSAli Bahrami { MSG_ORIG(MSG_STR_CDIR_ELIF), MSG_STR_CDIR_ELIF_SIZE, 1286*69112eddSAli Bahrami ARG_T_EXPR, CDIR_T_ELIF }, 1287*69112eddSAli Bahrami { MSG_ORIG(MSG_STR_CDIR_ERROR), MSG_STR_CDIR_ERROR_SIZE, 1288*69112eddSAli Bahrami ARG_T_STR, CDIR_T_ERROR }, 1289*69112eddSAli Bahrami { MSG_ORIG(MSG_STR_CDIR_ADD), MSG_STR_CDIR_ADD_SIZE, 1290*69112eddSAli Bahrami ARG_T_ID, CDIR_T_ADD }, 1291*69112eddSAli Bahrami { MSG_ORIG(MSG_STR_CDIR_CLEAR), MSG_STR_CDIR_CLEAR_SIZE, 1292*69112eddSAli Bahrami ARG_T_ID, CDIR_T_CLEAR }, 1293*69112eddSAli Bahrami { MSG_ORIG(MSG_STR_CDIR_MFVER), MSG_STR_CDIR_MFVER_SIZE, 1294*69112eddSAli Bahrami ARG_T_IGN, CDIR_T_VERSION }, 1295*69112eddSAli Bahrami 1296*69112eddSAli Bahrami { NULL, 0, 1297*69112eddSAli Bahrami ARG_T_IGN, CDIR_T_UNKNOWN } 1298*69112eddSAli Bahrami }; 1299*69112eddSAli Bahrami 1300*69112eddSAli Bahrami cdir_match_t *mdptr; 1301*69112eddSAli Bahrami char *tail; 1302*69112eddSAli Bahrami int expr_eval; /* Result of evaluating ARG_T_EXPR */ 1303*69112eddSAli Bahrami Mapfile arg_mf; 1304*69112eddSAli Bahrami cdir_level_t *level; 1305*69112eddSAli Bahrami int pass, parent_pass; /* Currently accepting input */ 1306*69112eddSAli Bahrami 1307*69112eddSAli Bahrami restart: 1308*69112eddSAli Bahrami /* Is the immediate context passing input? */ 1309*69112eddSAli Bahrami pass = STACK_IS_EMPTY(lms.lms_cdir_stack) || 1310*69112eddSAli Bahrami STACK_TOP(lms.lms_cdir_stack).cdl_pass; 1311*69112eddSAli Bahrami 1312*69112eddSAli Bahrami /* Is the surrounding (parent) context passing input? */ 1313*69112eddSAli Bahrami parent_pass = (lms.lms_cdir_stack.stk_n <= 1) || 1314*69112eddSAli Bahrami lms.lms_cdir_stack.stk_s[lms.lms_cdir_stack.stk_n - 2].cdl_pass; 1315*69112eddSAli Bahrami 1316*69112eddSAli Bahrami 1317*69112eddSAli Bahrami for (mdptr = match_data; mdptr->md_name; mdptr++) { 1318*69112eddSAli Bahrami /* Prefix must match, or we move on */ 1319*69112eddSAli Bahrami if (strncmp(mf->mf_next, mdptr->md_name, 1320*69112eddSAli Bahrami mdptr->md_size) != 0) 1321*69112eddSAli Bahrami continue; 1322*69112eddSAli Bahrami tail = mf->mf_next + mdptr->md_size; 1323*69112eddSAli Bahrami 1324*69112eddSAli Bahrami /* 1325*69112eddSAli Bahrami * If there isn't whitespace, or a NULL terminator following 1326*69112eddSAli Bahrami * the prefix, then even though our prefix matched, the actual 1327*69112eddSAli Bahrami * token is longer, and we don't have a match. 1328*69112eddSAli Bahrami */ 1329*69112eddSAli Bahrami if (!isspace(*tail) && (*tail != '\0')) 1330*69112eddSAli Bahrami continue; 1331*69112eddSAli Bahrami 1332*69112eddSAli Bahrami /* We have matched a valid control directive */ 1333*69112eddSAli Bahrami break; 1334*69112eddSAli Bahrami } 1335*69112eddSAli Bahrami 1336*69112eddSAli Bahrami /* Advance input to end of the current line */ 1337*69112eddSAli Bahrami advance_to_eol(&mf->mf_next); 1338*69112eddSAli Bahrami 1339*69112eddSAli Bahrami /* 1340*69112eddSAli Bahrami * Set up a temporary mapfile descriptor to reference the 1341*69112eddSAli Bahrami * argument string. The benefit of this second block, is that 1342*69112eddSAli Bahrami * we can advance the real one to the next line now, which allows 1343*69112eddSAli Bahrami * us to return at any time knowing that the input has been moved 1344*69112eddSAli Bahrami * to the proper spot. This simplifies the error cases. 1345*69112eddSAli Bahrami * 1346*69112eddSAli Bahrami * If we had a match, tail points at the start of the string. 1347*69112eddSAli Bahrami * Otherwise, we want to point at the end of the line. 1348*69112eddSAli Bahrami */ 1349*69112eddSAli Bahrami arg_mf = *mf; 1350*69112eddSAli Bahrami if (mdptr->md_name == NULL) 1351*69112eddSAli Bahrami arg_mf.mf_text = arg_mf.mf_next; 1352*69112eddSAli Bahrami else 1353*69112eddSAli Bahrami arg_mf.mf_text = arg_mf.mf_next = tail; 1354*69112eddSAli Bahrami 1355*69112eddSAli Bahrami /* 1356*69112eddSAli Bahrami * Null terminate the arguments, and advance the main mapfile 1357*69112eddSAli Bahrami * state block to the next line. 1358*69112eddSAli Bahrami */ 1359*69112eddSAli Bahrami if (*mf->mf_next == '\n') { 1360*69112eddSAli Bahrami *mf->mf_next++ = '\0'; 1361*69112eddSAli Bahrami mf->mf_lineno++; 1362*69112eddSAli Bahrami } 1363*69112eddSAli Bahrami 1364*69112eddSAli Bahrami /* Skip leading whitespace to arguments */ 1365*69112eddSAli Bahrami while (isspace(*arg_mf.mf_next)) 1366*69112eddSAli Bahrami arg_mf.mf_next++; 1367*69112eddSAli Bahrami 1368*69112eddSAli Bahrami /* Strip off any comment present on the line */ 1369*69112eddSAli Bahrami for (tail = arg_mf.mf_next; *tail; tail++) 1370*69112eddSAli Bahrami if (*tail == '#') { 1371*69112eddSAli Bahrami *tail = '\0'; 1372*69112eddSAli Bahrami break; 1373*69112eddSAli Bahrami } 1374*69112eddSAli Bahrami 1375*69112eddSAli Bahrami /* 1376*69112eddSAli Bahrami * Process the arguments as necessary depending on their type. 1377*69112eddSAli Bahrami * If this control directive is nested inside a surrounding context 1378*69112eddSAli Bahrami * that is not currently passing text, then we skip the argument 1379*69112eddSAli Bahrami * evaluation. This follows the behavior of the C preprocessor, 1380*69112eddSAli Bahrami * which only examines enough to detect the operation within 1381*69112eddSAli Bahrami * a disabled section, without issuing errors about the arguments. 1382*69112eddSAli Bahrami */ 1383*69112eddSAli Bahrami if (pass || (parent_pass && (mdptr->md_op == CDIR_T_ELIF))) { 1384*69112eddSAli Bahrami switch (mdptr->md_arg) { 1385*69112eddSAli Bahrami case ARG_T_NONE: 1386*69112eddSAli Bahrami if (*arg_mf.mf_next == '\0') 1387*69112eddSAli Bahrami break; 1388*69112eddSAli Bahrami /* Args are present, but not wanted */ 1389*69112eddSAli Bahrami mf_fatal(&arg_mf, MSG_INTL(MSG_MAP_CDIR_REQNOARG), 1390*69112eddSAli Bahrami mdptr->md_name); 1391*69112eddSAli Bahrami return (FALSE); 1392*69112eddSAli Bahrami 1393*69112eddSAli Bahrami case ARG_T_EXPR: 1394*69112eddSAli Bahrami /* Ensure that arguments are present */ 1395*69112eddSAli Bahrami if (*arg_mf.mf_next == '\0') 1396*69112eddSAli Bahrami goto error_reqarg; 1397*69112eddSAli Bahrami expr_eval = cexp_eval_expr(&arg_mf); 1398*69112eddSAli Bahrami if (expr_eval == -1) 1399*69112eddSAli Bahrami return (FALSE); 1400*69112eddSAli Bahrami break; 1401*69112eddSAli Bahrami 1402*69112eddSAli Bahrami case ARG_T_ID: 1403*69112eddSAli Bahrami /* Ensure that arguments are present */ 1404*69112eddSAli Bahrami if (*arg_mf.mf_next == '\0') 1405*69112eddSAli Bahrami goto error_reqarg; 1406*69112eddSAli Bahrami if (!cexp_ident_validate(&arg_mf, NULL, 1407*69112eddSAli Bahrami mdptr->md_name)) 1408*69112eddSAli Bahrami return (FALSE); 1409*69112eddSAli Bahrami break; 1410*69112eddSAli Bahrami 1411*69112eddSAli Bahrami case ARG_T_STR: 1412*69112eddSAli Bahrami /* Ensure that arguments are present */ 1413*69112eddSAli Bahrami if (*arg_mf.mf_next == '\0') 1414*69112eddSAli Bahrami goto error_reqarg; 1415*69112eddSAli Bahrami /* Remove trailing whitespace */ 1416*69112eddSAli Bahrami tail = arg_mf.mf_next + strlen(arg_mf.mf_next); 1417*69112eddSAli Bahrami while ((tail > arg_mf.mf_next) && 1418*69112eddSAli Bahrami isspace(*(tail -1))) 1419*69112eddSAli Bahrami tail--; 1420*69112eddSAli Bahrami *tail = '\0'; 1421*69112eddSAli Bahrami break; 1422*69112eddSAli Bahrami } 1423*69112eddSAli Bahrami } 1424*69112eddSAli Bahrami 1425*69112eddSAli Bahrami /* 1426*69112eddSAli Bahrami * Carry out the specified control directive: 1427*69112eddSAli Bahrami */ 1428*69112eddSAli Bahrami if (!STACK_IS_EMPTY(lms.lms_cdir_stack)) 1429*69112eddSAli Bahrami level = &STACK_TOP(lms.lms_cdir_stack); 1430*69112eddSAli Bahrami 1431*69112eddSAli Bahrami switch (mdptr->md_op) { 1432*69112eddSAli Bahrami case CDIR_T_UNKNOWN: /* Unrecognized control directive */ 1433*69112eddSAli Bahrami if (!pass) 1434*69112eddSAli Bahrami break; 1435*69112eddSAli Bahrami mf_fatal0(&arg_mf, MSG_INTL(MSG_MAP_CDIR_BAD)); 1436*69112eddSAli Bahrami return (FALSE); 1437*69112eddSAli Bahrami 1438*69112eddSAli Bahrami case CDIR_T_ADD: 1439*69112eddSAli Bahrami if (pass && !cexp_ident_add(&arg_mf, arg_mf.mf_next)) 1440*69112eddSAli Bahrami return (FALSE); 1441*69112eddSAli Bahrami break; 1442*69112eddSAli Bahrami 1443*69112eddSAli Bahrami case CDIR_T_CLEAR: 1444*69112eddSAli Bahrami if (pass) 1445*69112eddSAli Bahrami cexp_ident_clear(&arg_mf, arg_mf.mf_next); 1446*69112eddSAli Bahrami break; 1447*69112eddSAli Bahrami 1448*69112eddSAli Bahrami case CDIR_T_ERROR: 1449*69112eddSAli Bahrami if (!pass) 1450*69112eddSAli Bahrami break; 1451*69112eddSAli Bahrami mf_fatal(&arg_mf, MSG_INTL(MSG_MAP_CDIR_ERROR), 1452*69112eddSAli Bahrami arg_mf.mf_next); 1453*69112eddSAli Bahrami return (FALSE); 1454*69112eddSAli Bahrami 1455*69112eddSAli Bahrami case CDIR_T_VERSION: 1456*69112eddSAli Bahrami /* 1457*69112eddSAli Bahrami * A $mapfile_version control directive can only appear 1458*69112eddSAli Bahrami * as the first directive in a mapfile, and is used to 1459*69112eddSAli Bahrami * determine the syntax for the rest of the file. It's 1460*69112eddSAli Bahrami * too late to be using it here. 1461*69112eddSAli Bahrami */ 1462*69112eddSAli Bahrami if (!pass) 1463*69112eddSAli Bahrami break; 1464*69112eddSAli Bahrami mf_fatal0(&arg_mf, MSG_INTL(MSG_MAP_CDIR_REPVER)); 1465*69112eddSAli Bahrami return (FALSE); 1466*69112eddSAli Bahrami 1467*69112eddSAli Bahrami case CDIR_T_IF: 1468*69112eddSAli Bahrami /* Push a new level on the conditional input stack */ 1469*69112eddSAli Bahrami if (STACK_RESERVE(lms.lms_cdir_stack, CDIR_STACK_INIT) == 0) 1470*69112eddSAli Bahrami return (FALSE); 1471*69112eddSAli Bahrami level = &lms.lms_cdir_stack.stk_s[lms.lms_cdir_stack.stk_n++]; 1472*69112eddSAli Bahrami level->cdl_if_lineno = arg_mf.mf_lineno; 1473*69112eddSAli Bahrami level->cdl_else_lineno = 0; 1474*69112eddSAli Bahrami 1475*69112eddSAli Bahrami /* 1476*69112eddSAli Bahrami * If previous level is not passing, this level is disabled. 1477*69112eddSAli Bahrami * Otherwise, the expression value determines what happens. 1478*69112eddSAli Bahrami */ 1479*69112eddSAli Bahrami if (pass) { 1480*69112eddSAli Bahrami level->cdl_done = level->cdl_pass = expr_eval; 1481*69112eddSAli Bahrami } else { 1482*69112eddSAli Bahrami level->cdl_done = 1; 1483*69112eddSAli Bahrami level->cdl_pass = 0; 1484*69112eddSAli Bahrami } 1485*69112eddSAli Bahrami break; 1486*69112eddSAli Bahrami 1487*69112eddSAli Bahrami case CDIR_T_ELIF: 1488*69112eddSAli Bahrami /* $elif requires an open $if construct */ 1489*69112eddSAli Bahrami if (STACK_IS_EMPTY(lms.lms_cdir_stack)) { 1490*69112eddSAli Bahrami mf_fatal(&arg_mf, MSG_INTL(MSG_MAP_CDIR_NOIF), 1491*69112eddSAli Bahrami MSG_ORIG(MSG_STR_CDIR_ELIF)); 1492*69112eddSAli Bahrami return (FALSE); 1493*69112eddSAli Bahrami } 1494*69112eddSAli Bahrami 1495*69112eddSAli Bahrami /* $elif cannot follow $else */ 1496*69112eddSAli Bahrami if (level->cdl_else_lineno > 0) { 1497*69112eddSAli Bahrami mf_fatal(&arg_mf, MSG_INTL(MSG_MAP_CDIR_ELSE), 1498*69112eddSAli Bahrami MSG_ORIG(MSG_STR_CDIR_ELIF), 1499*69112eddSAli Bahrami EC_LINENO(level->cdl_else_lineno)); 1500*69112eddSAli Bahrami return (FALSE); 1501*69112eddSAli Bahrami } 1502*69112eddSAli Bahrami 1503*69112eddSAli Bahrami /* 1504*69112eddSAli Bahrami * Accept text from $elif if the level isn't already 1505*69112eddSAli Bahrami * done and the expression evaluates to true. 1506*69112eddSAli Bahrami */ 1507*69112eddSAli Bahrami level->cdl_pass = !level->cdl_done && expr_eval; 1508*69112eddSAli Bahrami if (level->cdl_pass) 1509*69112eddSAli Bahrami level->cdl_done = 1; 1510*69112eddSAli Bahrami break; 1511*69112eddSAli Bahrami 1512*69112eddSAli Bahrami case CDIR_T_ELSE: 1513*69112eddSAli Bahrami /* $else requires an open $if construct */ 1514*69112eddSAli Bahrami if (STACK_IS_EMPTY(lms.lms_cdir_stack)) { 1515*69112eddSAli Bahrami mf_fatal(&arg_mf, MSG_INTL(MSG_MAP_CDIR_NOIF), 1516*69112eddSAli Bahrami MSG_ORIG(MSG_STR_CDIR_ELSE)); 1517*69112eddSAli Bahrami return (FALSE); 1518*69112eddSAli Bahrami } 1519*69112eddSAli Bahrami 1520*69112eddSAli Bahrami /* There can only be one $else in the chain */ 1521*69112eddSAli Bahrami if (level->cdl_else_lineno > 0) { 1522*69112eddSAli Bahrami mf_fatal(&arg_mf, MSG_INTL(MSG_MAP_CDIR_ELSE), 1523*69112eddSAli Bahrami MSG_ORIG(MSG_STR_CDIR_ELSE), 1524*69112eddSAli Bahrami EC_LINENO(level->cdl_else_lineno)); 1525*69112eddSAli Bahrami return (FALSE); 1526*69112eddSAli Bahrami } 1527*69112eddSAli Bahrami level->cdl_else_lineno = arg_mf.mf_lineno; 1528*69112eddSAli Bahrami 1529*69112eddSAli Bahrami /* Accept text from $else if the level isn't already done */ 1530*69112eddSAli Bahrami level->cdl_pass = !level->cdl_done; 1531*69112eddSAli Bahrami level->cdl_done = 1; 1532*69112eddSAli Bahrami break; 1533*69112eddSAli Bahrami 1534*69112eddSAli Bahrami case CDIR_T_ENDIF: 1535*69112eddSAli Bahrami /* $endif requires an open $if construct */ 1536*69112eddSAli Bahrami if (STACK_IS_EMPTY(lms.lms_cdir_stack)) { 1537*69112eddSAli Bahrami mf_fatal(&arg_mf, MSG_INTL(MSG_MAP_CDIR_NOIF), 1538*69112eddSAli Bahrami MSG_ORIG(MSG_STR_CDIR_ENDIF)); 1539*69112eddSAli Bahrami return (FALSE); 1540*69112eddSAli Bahrami } 1541*69112eddSAli Bahrami if (--lms.lms_cdir_stack.stk_n > 0) 1542*69112eddSAli Bahrami level = &STACK_TOP(lms.lms_cdir_stack); 1543*69112eddSAli Bahrami break; 1544*69112eddSAli Bahrami 1545*69112eddSAli Bahrami default: 1546*69112eddSAli Bahrami return (FALSE); 1547*69112eddSAli Bahrami } 1548*69112eddSAli Bahrami 1549*69112eddSAli Bahrami /* Evaluating the control directive above can change pass status */ 1550*69112eddSAli Bahrami expr_eval = STACK_IS_EMPTY(lms.lms_cdir_stack) || 1551*69112eddSAli Bahrami STACK_TOP(lms.lms_cdir_stack).cdl_pass; 1552*69112eddSAli Bahrami if (expr_eval != pass) { 1553*69112eddSAli Bahrami pass = expr_eval; 1554*69112eddSAli Bahrami DBG_CALL(Dbg_map_pass(arg_mf.mf_ofl->ofl_lml, pass, 1555*69112eddSAli Bahrami arg_mf.mf_name, arg_mf.mf_lineno, mdptr->md_name)); 1556*69112eddSAli Bahrami } 1557*69112eddSAli Bahrami 1558*69112eddSAli Bahrami /* 1559*69112eddSAli Bahrami * At this point, we have processed a control directive, 1560*69112eddSAli Bahrami * updated our conditional state stack, and the input is 1561*69112eddSAli Bahrami * positioned at the start of the line following the directive. 1562*69112eddSAli Bahrami * If the current level is accepting input, then give control 1563*69112eddSAli Bahrami * back to ld_map_gettoken() to resume its normal operation. 1564*69112eddSAli Bahrami */ 1565*69112eddSAli Bahrami if (pass) 1566*69112eddSAli Bahrami return (TRUE); 1567*69112eddSAli Bahrami 1568*69112eddSAli Bahrami /* 1569*69112eddSAli Bahrami * The current level is not accepting input. Only another 1570*69112eddSAli Bahrami * control directive can change this, so read and discard input 1571*69112eddSAli Bahrami * until we encounter one of the following: 1572*69112eddSAli Bahrami * 1573*69112eddSAli Bahrami * EOF: Return and let ld_map_gettoken() report it 1574*69112eddSAli Bahrami * Control Directive: Restart this function / evaluate new directive 1575*69112eddSAli Bahrami */ 1576*69112eddSAli Bahrami while (*mf->mf_next != '\0') { 1577*69112eddSAli Bahrami /* Skip leading whitespace */ 1578*69112eddSAli Bahrami while (isspace_nonl(*mf->mf_next)) 1579*69112eddSAli Bahrami mf->mf_next++; 1580*69112eddSAli Bahrami 1581*69112eddSAli Bahrami /* 1582*69112eddSAli Bahrami * Control directives start with a '$'. If we hit 1583*69112eddSAli Bahrami * one, restart the function at this point 1584*69112eddSAli Bahrami */ 1585*69112eddSAli Bahrami if (*mf->mf_next == '$') 1586*69112eddSAli Bahrami goto restart; 1587*69112eddSAli Bahrami 1588*69112eddSAli Bahrami /* Not a control directive, so advance input to next line */ 1589*69112eddSAli Bahrami advance_to_eol(&mf->mf_next); 1590*69112eddSAli Bahrami if (*mf->mf_next == '\n') { 1591*69112eddSAli Bahrami mf->mf_lineno++; 1592*69112eddSAli Bahrami mf->mf_next++; 1593*69112eddSAli Bahrami } 1594*69112eddSAli Bahrami } 1595*69112eddSAli Bahrami 1596*69112eddSAli Bahrami assert(mf->mf_next == '\0'); 1597*69112eddSAli Bahrami return (TRUE); 1598*69112eddSAli Bahrami 1599*69112eddSAli Bahrami /* 1600*69112eddSAli Bahrami * Control directives that require an argument that is not present 1601*69112eddSAli Bahrami * jump here to report the error and exit. 1602*69112eddSAli Bahrami */ 1603*69112eddSAli Bahrami error_reqarg: 1604*69112eddSAli Bahrami mf_fatal(&arg_mf, MSG_INTL(MSG_MAP_CDIR_REQARG), mdptr->md_name); 1605*69112eddSAli Bahrami return (FALSE); 1606*69112eddSAli Bahrami 1607*69112eddSAli Bahrami } 1608*69112eddSAli Bahrami 1609*69112eddSAli Bahrami #ifndef _ELF64 1610*69112eddSAli Bahrami /* 1611*69112eddSAli Bahrami * Convert a string to lowercase. 1612*69112eddSAli Bahrami */ 1613*69112eddSAli Bahrami void 1614*69112eddSAli Bahrami ld_map_lowercase(char *str) 1615*69112eddSAli Bahrami { 1616*69112eddSAli Bahrami while (*str = tolower(*str)) 1617*69112eddSAli Bahrami str++; 1618*69112eddSAli Bahrami } 1619*69112eddSAli Bahrami #endif 1620*69112eddSAli Bahrami 1621*69112eddSAli Bahrami /* 1622*69112eddSAli Bahrami * Wrappper on strtoul()/strtoull(), adapted to return an Xword. 1623*69112eddSAli Bahrami * 1624*69112eddSAli Bahrami * entry: 1625*69112eddSAli Bahrami * str - Pointer to string to be converted. 1626*69112eddSAli Bahrami * endptr - As documented for strtoul(3C). Either NULL, or 1627*69112eddSAli Bahrami * address of pointer to receive the address of the first 1628*69112eddSAli Bahrami * unused character in str (called "final" in strtoul(3C)). 1629*69112eddSAli Bahrami * ret_value - Address of Xword variable to receive result. 1630*69112eddSAli Bahrami * 1631*69112eddSAli Bahrami * exit: 1632*69112eddSAli Bahrami * On success, *ret_value receives the result, *endptr is updated if 1633*69112eddSAli Bahrami * endptr is non-NULL, and STRTOXWORD_OK is returned. 1634*69112eddSAli Bahrami * On failure, STRTOXWORD_TOBIG is returned if an otherwise valid 1635*69112eddSAli Bahrami * value was too large, and STRTOXWORD_BAD is returned if the string 1636*69112eddSAli Bahrami * is malformed. 1637*69112eddSAli Bahrami */ 1638*69112eddSAli Bahrami ld_map_strtoxword_t 1639*69112eddSAli Bahrami ld_map_strtoxword(const char *restrict str, char **restrict endptr, 1640*69112eddSAli Bahrami Xword *ret_value) 1641*69112eddSAli Bahrami { 1642*69112eddSAli Bahrami #if defined(_ELF64) /* _ELF64 */ 1643*69112eddSAli Bahrami #define FUNC strtoull /* Function to use */ 1644*69112eddSAli Bahrami #define FUNC_MAX ULLONG_MAX /* Largest value returned by FUNC */ 1645*69112eddSAli Bahrami #define XWORD_MAX ULLONG_MAX /* Largest Xword value */ 1646*69112eddSAli Bahrami uint64_t value; /* Variable of FUNC return type */ 1647*69112eddSAli Bahrami #else /* _ELF32 */ 1648*69112eddSAli Bahrami #define FUNC strtoul 1649*69112eddSAli Bahrami #define FUNC_MAX ULONG_MAX 1650*69112eddSAli Bahrami #define XWORD_MAX UINT_MAX 1651*69112eddSAli Bahrami ulong_t value; 1652*69112eddSAli Bahrami #endif 1653*69112eddSAli Bahrami 1654*69112eddSAli Bahrami char *endptr_local; /* Used if endptr is NULL */ 1655*69112eddSAli Bahrami 1656*69112eddSAli Bahrami if (endptr == NULL) 1657*69112eddSAli Bahrami endptr = &endptr_local; 1658*69112eddSAli Bahrami 1659*69112eddSAli Bahrami errno = 0; 1660*69112eddSAli Bahrami value = FUNC(str, endptr, 0); 1661*69112eddSAli Bahrami if ((errno != 0) || (str == *endptr)) { 1662*69112eddSAli Bahrami if (value == FUNC_MAX) 1663*69112eddSAli Bahrami return (STRTOXWORD_TOOBIG); 1664*69112eddSAli Bahrami else 1665*69112eddSAli Bahrami return (STRTOXWORD_BAD); 1666*69112eddSAli Bahrami } 1667*69112eddSAli Bahrami 1668*69112eddSAli Bahrami /* 1669*69112eddSAli Bahrami * If this is a 64-bit linker building an ELFCLASS32 object, 1670*69112eddSAli Bahrami * the FUNC return type is a 64-bit value, while an Xword is 1671*69112eddSAli Bahrami * 32-bit. It is possible for FUNC to be able to convert a value 1672*69112eddSAli Bahrami * too large for our return type. 1673*69112eddSAli Bahrami */ 1674*69112eddSAli Bahrami #if FUNC_MAX != XWORD_MAX 1675*69112eddSAli Bahrami if (value > XWORD_MAX) 1676*69112eddSAli Bahrami return (STRTOXWORD_TOOBIG); 1677*69112eddSAli Bahrami #endif 1678*69112eddSAli Bahrami 1679*69112eddSAli Bahrami *ret_value = value; 1680*69112eddSAli Bahrami return (STRTOXWORD_OK); 1681*69112eddSAli Bahrami 1682*69112eddSAli Bahrami #undef FUNC 1683*69112eddSAli Bahrami #undef FUNC_MAX 1684*69112eddSAli Bahrami #undef XWORD_MAC 1685*69112eddSAli Bahrami } 1686*69112eddSAli Bahrami 1687*69112eddSAli Bahrami /* 1688*69112eddSAli Bahrami * Convert the unsigned integer value at the current mapfile input 1689*69112eddSAli Bahrami * into binary form. All numeric values in mapfiles are treated as 1690*69112eddSAli Bahrami * unsigned integers of the appropriate width for an address on the 1691*69112eddSAli Bahrami * given target. Values can be decimal, hex, or octal. 1692*69112eddSAli Bahrami * 1693*69112eddSAli Bahrami * entry: 1694*69112eddSAli Bahrami * str - String to process. 1695*69112eddSAli Bahrami * value - Address of variable to receive resulting value. 1696*69112eddSAli Bahrami * notail - If TRUE, an error is issued if non-whitespace 1697*69112eddSAli Bahrami * characters other than '#' (comment) are found following 1698*69112eddSAli Bahrami * the numeric value before the end of line. 1699*69112eddSAli Bahrami * 1700*69112eddSAli Bahrami * exit: 1701*69112eddSAli Bahrami * On success: 1702*69112eddSAli Bahrami * - *str is advanced to the next character following the value 1703*69112eddSAli Bahrami * - *value receives the value 1704*69112eddSAli Bahrami * - Returns TRUE (1). 1705*69112eddSAli Bahrami * On failure, returns FALSE (0). 1706*69112eddSAli Bahrami */ 1707*69112eddSAli Bahrami static Boolean 1708*69112eddSAli Bahrami ld_map_getint(Mapfile *mf, ld_map_tkval_t *value, Boolean notail) 1709*69112eddSAli Bahrami { 1710*69112eddSAli Bahrami ld_map_strtoxword_t s2xw_ret; 1711*69112eddSAli Bahrami ld_map_npatch_t np; 1712*69112eddSAli Bahrami char *endptr; 1713*69112eddSAli Bahrami char *errstr = mf->mf_next; 1714*69112eddSAli Bahrami 1715*69112eddSAli Bahrami value->tkv_int.tkvi_str = mf->mf_next; 1716*69112eddSAli Bahrami s2xw_ret = ld_map_strtoxword(mf->mf_next, &endptr, 1717*69112eddSAli Bahrami &value->tkv_int.tkvi_value); 1718*69112eddSAli Bahrami if (s2xw_ret != STRTOXWORD_OK) { 1719*69112eddSAli Bahrami null_patch_eol(mf->mf_next, &np); 1720*69112eddSAli Bahrami if (s2xw_ret == STRTOXWORD_TOOBIG) 1721*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_VALUELIMIT), errstr); 1722*69112eddSAli Bahrami else 1723*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_MALVALUE), errstr); 1724*69112eddSAli Bahrami null_patch_undo(&np); 1725*69112eddSAli Bahrami return (FALSE); 1726*69112eddSAli Bahrami } 1727*69112eddSAli Bahrami 1728*69112eddSAli Bahrami /* Advance position to item following value, skipping whitespace */ 1729*69112eddSAli Bahrami value->tkv_int.tkvi_cnt = endptr - mf->mf_next; 1730*69112eddSAli Bahrami mf->mf_next = endptr; 1731*69112eddSAli Bahrami while (isspace_nonl(*mf->mf_next)) 1732*69112eddSAli Bahrami mf->mf_next++; 1733*69112eddSAli Bahrami 1734*69112eddSAli Bahrami /* If requested, ensure there's nothing left */ 1735*69112eddSAli Bahrami if (notail && (*mf->mf_next != '\n') && (*mf->mf_next != '#') && 1736*69112eddSAli Bahrami (*mf->mf_next != '\0')) { 1737*69112eddSAli Bahrami null_patch_eol(mf->mf_next, &np); 1738*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_BADVALUETAIL), errstr); 1739*69112eddSAli Bahrami null_patch_undo(&np); 1740*69112eddSAli Bahrami return (FALSE); 1741*69112eddSAli Bahrami } 1742*69112eddSAli Bahrami 1743*69112eddSAli Bahrami return (TRUE); 1744*69112eddSAli Bahrami } 1745*69112eddSAli Bahrami 1746*69112eddSAli Bahrami /* 1747*69112eddSAli Bahrami * Convert a an unquoted identifier into a TK_STRING token, using the 1748*69112eddSAli Bahrami * rules for syntax version in use. Used exclusively by ld_map_gettoken(). 1749*69112eddSAli Bahrami * 1750*69112eddSAli Bahrami * entry: 1751*69112eddSAli Bahrami * mf - Mapfile descriptor, positioned to the first character of 1752*69112eddSAli Bahrami * the string. 1753*69112eddSAli Bahrami * flags - Bitmask of options to control ld_map_gettoken()s behavior 1754*69112eddSAli Bahrami * tkv- Address of pointer to variable to receive token value. 1755*69112eddSAli Bahrami * 1756*69112eddSAli Bahrami * exit: 1757*69112eddSAli Bahrami * On success, mf is advanced past the token, tkv is updated with 1758*69112eddSAli Bahrami * the string, and TK_STRING is returned. On error, TK_ERROR is returned. 1759*69112eddSAli Bahrami */ 1760*69112eddSAli Bahrami inline static Token 1761*69112eddSAli Bahrami gettoken_ident(Mapfile *mf, int flags, ld_map_tkval_t *tkv) 1762*69112eddSAli Bahrami { 1763*69112eddSAli Bahrami char *end; 1764*69112eddSAli Bahrami Token tok; 1765*69112eddSAli Bahrami ld_map_npatch_t np; 1766*69112eddSAli Bahrami 1767*69112eddSAli Bahrami tkv->tkv_str = mf->mf_next; 1768*69112eddSAli Bahrami if ((end = ident_delimit(mf)) == NULL) 1769*69112eddSAli Bahrami return (TK_ERROR); 1770*69112eddSAli Bahrami mf->mf_next = end; 1771*69112eddSAli Bahrami 1772*69112eddSAli Bahrami /* 1773*69112eddSAli Bahrami * One advantage of reading the entire mapfile into memory is that 1774*69112eddSAli Bahrami * we can access the strings within it without having to allocate 1775*69112eddSAli Bahrami * more memory or make copies. In order to do that, we need to NULL 1776*69112eddSAli Bahrami * terminate this identifier. That is going to overwrite the 1777*69112eddSAli Bahrami * following character. The problem this presents is that the next 1778*69112eddSAli Bahrami * character may well be the first character of a subsequent token. 1779*69112eddSAli Bahrami * The solution to this is: 1780*69112eddSAli Bahrami * 1781*69112eddSAli Bahrami * 1) Disallow the case where the next character is able to 1782*69112eddSAli Bahrami * start a string. This is not legal mapfile syntax anyway, 1783*69112eddSAli Bahrami * so catching it here simplifies matters. 1784*69112eddSAli Bahrami * 2) Copy the character into the special mf->mf_next_ch 1785*69112eddSAli Bahrami * 3) The next call to ld_map_gettoken() checks mf->mf_next_ch, 1786*69112eddSAli Bahrami * and if it is non-0, uses it instead of dereferencing the 1787*69112eddSAli Bahrami * mf_next pointer. 1788*69112eddSAli Bahrami */ 1789*69112eddSAli Bahrami tok = (*mf->mf_next & 0x80) ? 1790*69112eddSAli Bahrami TK_OP_ILLCHR : mf->mf_tokdisp[*mf->mf_next]; 1791*69112eddSAli Bahrami switch (tok) { 1792*69112eddSAli Bahrami case TK_OP_BADCHR: 1793*69112eddSAli Bahrami null_patch_eol(mf->mf_next, &np); 1794*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_BADCHAR), mf->mf_next); 1795*69112eddSAli Bahrami null_patch_undo(&np); 1796*69112eddSAli Bahrami return (TK_ERROR); 1797*69112eddSAli Bahrami 1798*69112eddSAli Bahrami case TK_OP_SIMQUOTE: 1799*69112eddSAli Bahrami case TK_OP_CQUOTE: 1800*69112eddSAli Bahrami case TK_OP_CDIR: 1801*69112eddSAli Bahrami case TK_OP_NUM: 1802*69112eddSAli Bahrami case TK_OP_ID: 1803*69112eddSAli Bahrami null_patch_eol(mf->mf_next, &np); 1804*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_WSNEEDED), mf->mf_next); 1805*69112eddSAli Bahrami null_patch_undo(&np); 1806*69112eddSAli Bahrami return (TK_ERROR); 1807*69112eddSAli Bahrami } 1808*69112eddSAli Bahrami 1809*69112eddSAli Bahrami /* Null terminate, saving the replaced character */ 1810*69112eddSAli Bahrami mf->mf_next_ch = *mf->mf_next; 1811*69112eddSAli Bahrami *mf->mf_next = '\0'; 1812*69112eddSAli Bahrami 1813*69112eddSAli Bahrami if (flags & TK_F_STRLC) 1814*69112eddSAli Bahrami ld_map_lowercase(tkv->tkv_str); 1815*69112eddSAli Bahrami return (TK_STRING); 1816*69112eddSAli Bahrami } 1817*69112eddSAli Bahrami 1818*69112eddSAli Bahrami /* 1819*69112eddSAli Bahrami * Convert a quoted string into a TK_STRING token, using simple 1820*69112eddSAli Bahrami * quoting rules: 1821*69112eddSAli Bahrami * - Start and end quotes must be present and match 1822*69112eddSAli Bahrami * - There are no special characters or escape sequences. 1823*69112eddSAli Bahrami * This function is used exclusively by ld_map_gettoken(). 1824*69112eddSAli Bahrami * 1825*69112eddSAli Bahrami * entry: 1826*69112eddSAli Bahrami * mf - Mapfile descriptor, positioned to the opening quote character. 1827*69112eddSAli Bahrami * flags - Bitmask of options to control ld_map_gettoken()s behavior 1828*69112eddSAli Bahrami * tkv- Address of pointer to variable to receive token value. 1829*69112eddSAli Bahrami * 1830*69112eddSAli Bahrami * exit: 1831*69112eddSAli Bahrami * On success, mf is advanced past the token, tkv is updated with 1832*69112eddSAli Bahrami * the string, and TK_STRING is returned. On error, TK_ERROR is returned. 1833*69112eddSAli Bahrami */ 1834*69112eddSAli Bahrami inline static Token 1835*69112eddSAli Bahrami gettoken_simquote_str(Mapfile *mf, int flags, ld_map_tkval_t *tkv) 1836*69112eddSAli Bahrami { 1837*69112eddSAli Bahrami char *str, *end; 1838*69112eddSAli Bahrami char quote; 1839*69112eddSAli Bahrami 1840*69112eddSAli Bahrami str = mf->mf_next++; 1841*69112eddSAli Bahrami quote = *str; 1842*69112eddSAli Bahrami end = mf->mf_next; 1843*69112eddSAli Bahrami while ((*end != '\0') && (*end != '\n') && (*end != quote)) 1844*69112eddSAli Bahrami end++; 1845*69112eddSAli Bahrami if (*end != quote) { 1846*69112eddSAli Bahrami ld_map_npatch_t np; 1847*69112eddSAli Bahrami 1848*69112eddSAli Bahrami null_patch_eol(end, &np); 1849*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_NOTERM), str); 1850*69112eddSAli Bahrami null_patch_undo(&np); 1851*69112eddSAli Bahrami return (TK_ERROR); 1852*69112eddSAli Bahrami } 1853*69112eddSAli Bahrami 1854*69112eddSAli Bahrami /* 1855*69112eddSAli Bahrami * end is pointing at the closing quote. We can turn that into NULL 1856*69112eddSAli Bahrami * termination for the string without needing to restore it later. 1857*69112eddSAli Bahrami */ 1858*69112eddSAli Bahrami *end = '\0'; 1859*69112eddSAli Bahrami mf->mf_next = end + 1; 1860*69112eddSAli Bahrami tkv->tkv_str = str + 1; /* Skip opening quote */ 1861*69112eddSAli Bahrami if (flags & TK_F_STRLC) 1862*69112eddSAli Bahrami ld_map_lowercase(tkv->tkv_str); 1863*69112eddSAli Bahrami return (TK_STRING); 1864*69112eddSAli Bahrami } 1865*69112eddSAli Bahrami 1866*69112eddSAli Bahrami /* 1867*69112eddSAli Bahrami * Convert a quoted string into a TK_STRING token, using C string literal 1868*69112eddSAli Bahrami * quoting rules: 1869*69112eddSAli Bahrami * - Start and end quotes must be present and match 1870*69112eddSAli Bahrami * - Backslash is an escape, used to introduce special characters 1871*69112eddSAli Bahrami * This function is used exclusively by ld_map_gettoken(). 1872*69112eddSAli Bahrami * 1873*69112eddSAli Bahrami * entry: 1874*69112eddSAli Bahrami * mf - Mapfile descriptor, positioned to the opening quote character. 1875*69112eddSAli Bahrami * flags - Bitmask of options to control ld_map_gettoken()s behavior 1876*69112eddSAli Bahrami * tkv- Address of pointer to variable to receive token value. 1877*69112eddSAli Bahrami * 1878*69112eddSAli Bahrami * exit: 1879*69112eddSAli Bahrami * On success, mf is advanced past the token, tkv is updated with 1880*69112eddSAli Bahrami * the string, and TK_STRING is returned. On error, TK_ERROR is returned. 1881*69112eddSAli Bahrami */ 1882*69112eddSAli Bahrami inline static Token 1883*69112eddSAli Bahrami gettoken_cquote_str(Mapfile *mf, int flags, ld_map_tkval_t *tkv) 1884*69112eddSAli Bahrami { 1885*69112eddSAli Bahrami char *str, *cur, *end; 1886*69112eddSAli Bahrami char quote; 1887*69112eddSAli Bahrami int c; 1888*69112eddSAli Bahrami 1889*69112eddSAli Bahrami /* 1890*69112eddSAli Bahrami * This function goes through the quoted string and copies 1891*69112eddSAli Bahrami * it on top of itself, replacing escape sequences with the 1892*69112eddSAli Bahrami * characters they denote. There is always enough room for this, 1893*69112eddSAli Bahrami * because escapes are multi-character sequences that are converted 1894*69112eddSAli Bahrami * to single character results. 1895*69112eddSAli Bahrami */ 1896*69112eddSAli Bahrami str = mf->mf_next++; 1897*69112eddSAli Bahrami quote = *str; 1898*69112eddSAli Bahrami cur = end = mf->mf_next; 1899*69112eddSAli Bahrami for (c = *end++; (c != '\0') && (c != '\n') && (c != quote); 1900*69112eddSAli Bahrami c = *end++) { 1901*69112eddSAli Bahrami if (c == '\\') { 1902*69112eddSAli Bahrami c = conv_translate_c_esc(&end); 1903*69112eddSAli Bahrami if (c == -1) { 1904*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_BADCESC), *end); 1905*69112eddSAli Bahrami return (TK_ERROR); 1906*69112eddSAli Bahrami } 1907*69112eddSAli Bahrami } 1908*69112eddSAli Bahrami *cur++ = c; 1909*69112eddSAli Bahrami } 1910*69112eddSAli Bahrami *cur = '\0'; /* terminate the result */ 1911*69112eddSAli Bahrami if (c != quote) { 1912*69112eddSAli Bahrami ld_map_npatch_t np; 1913*69112eddSAli Bahrami 1914*69112eddSAli Bahrami null_patch_eol(end, &np); 1915*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_NOTERM), str); 1916*69112eddSAli Bahrami null_patch_undo(&np); 1917*69112eddSAli Bahrami return (TK_ERROR); 1918*69112eddSAli Bahrami } 1919*69112eddSAli Bahrami 1920*69112eddSAli Bahrami /* end is pointing one character past the closing quote */ 1921*69112eddSAli Bahrami mf->mf_next = end; 1922*69112eddSAli Bahrami tkv->tkv_str = str + 1; /* Skip opening quote */ 1923*69112eddSAli Bahrami if (flags & TK_F_STRLC) 1924*69112eddSAli Bahrami ld_map_lowercase(tkv->tkv_str); 1925*69112eddSAli Bahrami return (TK_STRING); 1926*69112eddSAli Bahrami } 1927*69112eddSAli Bahrami 1928*69112eddSAli Bahrami /* 1929*69112eddSAli Bahrami * Get a token from the mapfile. 1930*69112eddSAli Bahrami * 1931*69112eddSAli Bahrami * entry: 1932*69112eddSAli Bahrami * mf - Mapfile descriptor 1933*69112eddSAli Bahrami * flags - Bitmask of options to control ld_map_gettoken()s behavior 1934*69112eddSAli Bahrami * tkv- Address of pointer to variable to receive token value. 1935*69112eddSAli Bahrami * 1936*69112eddSAli Bahrami * exit: 1937*69112eddSAli Bahrami * Returns one of the TK_* values, to report the result. If the resulting 1938*69112eddSAli Bahrami * token has a value (TK_STRING / TK_INT), and tkv is non-NULL, tkv 1939*69112eddSAli Bahrami * is filled in with the resulting value. 1940*69112eddSAli Bahrami */ 1941*69112eddSAli Bahrami Token 1942*69112eddSAli Bahrami ld_map_gettoken(Mapfile *mf, int flags, ld_map_tkval_t *tkv) 1943*69112eddSAli Bahrami { 1944*69112eddSAli Bahrami int cdir_allow, ch; 1945*69112eddSAli Bahrami Token tok; 1946*69112eddSAli Bahrami ld_map_npatch_t np; 1947*69112eddSAli Bahrami 1948*69112eddSAli Bahrami /* 1949*69112eddSAli Bahrami * Mapfile control directives all start with a '$' character. However, 1950*69112eddSAli Bahrami * they are only valid when they are the first thing on a line. That 1951*69112eddSAli Bahrami * happens on the first call to ld_map_gettoken() for a new a new 1952*69112eddSAli Bahrami * mapfile, as tracked with lms.lms_cdir_valid, and immediately 1953*69112eddSAli Bahrami * following each newline seen in the file. 1954*69112eddSAli Bahrami */ 1955*69112eddSAli Bahrami cdir_allow = lms.lms_cdir_valid; 1956*69112eddSAli Bahrami lms.lms_cdir_valid = 0; 1957*69112eddSAli Bahrami 1958*69112eddSAli Bahrami /* Cycle through the characters looking for tokens. */ 1959*69112eddSAli Bahrami for (;;) { 1960*69112eddSAli Bahrami /* 1961*69112eddSAli Bahrami * Process the next character. This is normally *mf->mf_next, 1962*69112eddSAli Bahrami * but if mf->mf_next_ch is non-0, then it contains the 1963*69112eddSAli Bahrami * character, and *mf->mf_next contains a NULL termination 1964*69112eddSAli Bahrami * from the TK_STRING token returned on the previous call. 1965*69112eddSAli Bahrami * 1966*69112eddSAli Bahrami * gettoken_ident() ensures that this is never done to 1967*69112eddSAli Bahrami * a character that starts a string. 1968*69112eddSAli Bahrami */ 1969*69112eddSAli Bahrami if (mf->mf_next_ch == 0) { 1970*69112eddSAli Bahrami ch = *mf->mf_next; 1971*69112eddSAli Bahrami } else { 1972*69112eddSAli Bahrami ch = mf->mf_next_ch; 1973*69112eddSAli Bahrami mf->mf_next_ch = 0; /* Reset */ 1974*69112eddSAli Bahrami } 1975*69112eddSAli Bahrami 1976*69112eddSAli Bahrami /* Map the character to a dispatch action */ 1977*69112eddSAli Bahrami tok = (ch & 0x80) ? TK_OP_ILLCHR : mf->mf_tokdisp[ch]; 1978*69112eddSAli Bahrami 1979*69112eddSAli Bahrami /* 1980*69112eddSAli Bahrami * Items that require processing are identified as OP tokens. 1981*69112eddSAli Bahrami * We process them, and return a result non-OP token. 1982*69112eddSAli Bahrami * 1983*69112eddSAli Bahrami * Non-OP tokens are single character tokens, and we return 1984*69112eddSAli Bahrami * them immediately. 1985*69112eddSAli Bahrami */ 1986*69112eddSAli Bahrami switch (tok) { 1987*69112eddSAli Bahrami case TK_OP_EOF: 1988*69112eddSAli Bahrami /* If EOFOK is set, quietly report it as TK_EOF */ 1989*69112eddSAli Bahrami if ((flags & TK_F_EOFOK) != 0) 1990*69112eddSAli Bahrami return (TK_EOF); 1991*69112eddSAli Bahrami 1992*69112eddSAli Bahrami /* Treat it as a standard error */ 1993*69112eddSAli Bahrami mf_fatal0(mf, MSG_INTL(MSG_MAP_PREMEOF)); 1994*69112eddSAli Bahrami return (TK_ERROR); 1995*69112eddSAli Bahrami 1996*69112eddSAli Bahrami case TK_OP_ILLCHR: 1997*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_ILLCHAR), ch); 1998*69112eddSAli Bahrami mf->mf_next++; 1999*69112eddSAli Bahrami return (TK_ERROR); 2000*69112eddSAli Bahrami 2001*69112eddSAli Bahrami case TK_OP_BADCHR: 2002*69112eddSAli Bahrami tk_op_badchr: 2003*69112eddSAli Bahrami null_patch_eol(mf->mf_next, &np); 2004*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_BADCHAR), mf->mf_next); 2005*69112eddSAli Bahrami null_patch_undo(&np); 2006*69112eddSAli Bahrami mf->mf_next++; 2007*69112eddSAli Bahrami return (TK_ERROR); 2008*69112eddSAli Bahrami 2009*69112eddSAli Bahrami case TK_OP_WS: /* White space */ 2010*69112eddSAli Bahrami mf->mf_next++; 2011*69112eddSAli Bahrami break; 2012*69112eddSAli Bahrami 2013*69112eddSAli Bahrami case TK_OP_NL: /* White space too, but bump line number. */ 2014*69112eddSAli Bahrami mf->mf_next++; 2015*69112eddSAli Bahrami mf->mf_lineno++; 2016*69112eddSAli Bahrami cdir_allow = 1; 2017*69112eddSAli Bahrami break; 2018*69112eddSAli Bahrami 2019*69112eddSAli Bahrami case TK_OP_SIMQUOTE: 2020*69112eddSAli Bahrami if (flags & TK_F_KEYWORD) 2021*69112eddSAli Bahrami goto tk_op_badkwquote; 2022*69112eddSAli Bahrami return (gettoken_simquote_str(mf, flags, tkv)); 2023*69112eddSAli Bahrami 2024*69112eddSAli Bahrami case TK_OP_CQUOTE: 2025*69112eddSAli Bahrami if (flags & TK_F_KEYWORD) { 2026*69112eddSAli Bahrami tk_op_badkwquote: 2027*69112eddSAli Bahrami null_patch_eol(mf->mf_next, &np); 2028*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_BADKWQUOTE), 2029*69112eddSAli Bahrami mf->mf_next); 2030*69112eddSAli Bahrami null_patch_undo(&np); 2031*69112eddSAli Bahrami mf->mf_next++; 2032*69112eddSAli Bahrami return (TK_ERROR); 2033*69112eddSAli Bahrami } 2034*69112eddSAli Bahrami return (gettoken_cquote_str(mf, flags, tkv)); 2035*69112eddSAli Bahrami 2036*69112eddSAli Bahrami case TK_OP_CMT: 2037*69112eddSAli Bahrami advance_to_eol(&mf->mf_next); 2038*69112eddSAli Bahrami break; 2039*69112eddSAli Bahrami 2040*69112eddSAli Bahrami case TK_OP_CDIR: 2041*69112eddSAli Bahrami /* 2042*69112eddSAli Bahrami * Control directives are only valid at the start 2043*69112eddSAli Bahrami * of a line. 2044*69112eddSAli Bahrami */ 2045*69112eddSAli Bahrami if (!cdir_allow) { 2046*69112eddSAli Bahrami null_patch_eol(mf->mf_next, &np); 2047*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_CDIR_NOTBOL), 2048*69112eddSAli Bahrami mf->mf_next); 2049*69112eddSAli Bahrami null_patch_undo(&np); 2050*69112eddSAli Bahrami mf->mf_next++; 2051*69112eddSAli Bahrami return (TK_ERROR); 2052*69112eddSAli Bahrami } 2053*69112eddSAli Bahrami if (!cdir_process(mf)) 2054*69112eddSAli Bahrami return (TK_ERROR); 2055*69112eddSAli Bahrami break; 2056*69112eddSAli Bahrami 2057*69112eddSAli Bahrami case TK_OP_NUM: /* Decimal, hex(0x...), or octal (0...) value */ 2058*69112eddSAli Bahrami if (!ld_map_getint(mf, tkv, FALSE)) 2059*69112eddSAli Bahrami return (TK_ERROR); 2060*69112eddSAli Bahrami return (TK_INT); 2061*69112eddSAli Bahrami 2062*69112eddSAli Bahrami case TK_OP_ID: /* Unquoted identifier */ 2063*69112eddSAli Bahrami return (gettoken_ident(mf, flags, tkv)); 2064*69112eddSAli Bahrami 2065*69112eddSAli Bahrami case TK_OP_CEQUAL: /* += or -= */ 2066*69112eddSAli Bahrami if (*(mf->mf_next + 1) != '=') 2067*69112eddSAli Bahrami goto tk_op_badchr; 2068*69112eddSAli Bahrami tok = (ch == '+') ? TK_PLUSEQ : TK_MINUSEQ; 2069*69112eddSAli Bahrami mf->mf_next += 2; 2070*69112eddSAli Bahrami return (tok); 2071*69112eddSAli Bahrami 2072*69112eddSAli Bahrami default: /* Non-OP token */ 2073*69112eddSAli Bahrami mf->mf_next++; 2074*69112eddSAli Bahrami return (tok); 2075*69112eddSAli Bahrami } 2076*69112eddSAli Bahrami } 2077*69112eddSAli Bahrami 2078*69112eddSAli Bahrami /*NOTREACHED*/ 2079*69112eddSAli Bahrami assert(0); 2080*69112eddSAli Bahrami return (TK_ERROR); 2081*69112eddSAli Bahrami } 2082*69112eddSAli Bahrami 2083*69112eddSAli Bahrami /* 2084*69112eddSAli Bahrami * Given a token and value returned by ld_map_gettoken(), return a string 2085*69112eddSAli Bahrami * representation of it suitable for use in an error message. 2086*69112eddSAli Bahrami * 2087*69112eddSAli Bahrami * entry: 2088*69112eddSAli Bahrami * tok - Token code. Must not be an OP-token 2089*69112eddSAli Bahrami * tkv - Token value 2090*69112eddSAli Bahrami */ 2091*69112eddSAli Bahrami const char * 2092*69112eddSAli Bahrami ld_map_tokenstr(Token tok, ld_map_tkval_t *tkv, Conv_inv_buf_t *inv_buf) 2093*69112eddSAli Bahrami { 2094*69112eddSAli Bahrami size_t cnt; 2095*69112eddSAli Bahrami 2096*69112eddSAli Bahrami switch (tok) { 2097*69112eddSAli Bahrami case TK_ERROR: 2098*69112eddSAli Bahrami return (MSG_ORIG(MSG_STR_ERROR)); 2099*69112eddSAli Bahrami case TK_EOF: 2100*69112eddSAli Bahrami return (MSG_ORIG(MSG_STR_EOF)); 2101*69112eddSAli Bahrami case TK_STRING: 2102*69112eddSAli Bahrami return (tkv->tkv_str); 2103*69112eddSAli Bahrami case TK_COLON: 2104*69112eddSAli Bahrami return (MSG_ORIG(MSG_QSTR_COLON)); 2105*69112eddSAli Bahrami case TK_SEMICOLON: 2106*69112eddSAli Bahrami return (MSG_ORIG(MSG_QSTR_SEMICOLON)); 2107*69112eddSAli Bahrami case TK_EQUAL: 2108*69112eddSAli Bahrami return (MSG_ORIG(MSG_QSTR_EQUAL)); 2109*69112eddSAli Bahrami case TK_PLUSEQ: 2110*69112eddSAli Bahrami return (MSG_ORIG(MSG_QSTR_PLUSEQ)); 2111*69112eddSAli Bahrami case TK_MINUSEQ: 2112*69112eddSAli Bahrami return (MSG_ORIG(MSG_QSTR_MINUSEQ)); 2113*69112eddSAli Bahrami case TK_ATSIGN: 2114*69112eddSAli Bahrami return (MSG_ORIG(MSG_QSTR_ATSIGN)); 2115*69112eddSAli Bahrami case TK_DASH: 2116*69112eddSAli Bahrami return (MSG_ORIG(MSG_QSTR_DASH)); 2117*69112eddSAli Bahrami case TK_LEFTBKT: 2118*69112eddSAli Bahrami return (MSG_ORIG(MSG_QSTR_LEFTBKT)); 2119*69112eddSAli Bahrami case TK_RIGHTBKT: 2120*69112eddSAli Bahrami return (MSG_ORIG(MSG_QSTR_RIGHTBKT)); 2121*69112eddSAli Bahrami case TK_PIPE: 2122*69112eddSAli Bahrami return (MSG_ORIG(MSG_QSTR_PIPE)); 2123*69112eddSAli Bahrami case TK_INT: 2124*69112eddSAli Bahrami cnt = tkv->tkv_int.tkvi_cnt; 2125*69112eddSAli Bahrami if (cnt >= sizeof (inv_buf->buf)) 2126*69112eddSAli Bahrami cnt = sizeof (inv_buf->buf) - 1; 2127*69112eddSAli Bahrami (void) memcpy(inv_buf->buf, tkv->tkv_int.tkvi_str, cnt); 2128*69112eddSAli Bahrami inv_buf->buf[cnt] = '\0'; 2129*69112eddSAli Bahrami return (inv_buf->buf); 2130*69112eddSAli Bahrami case TK_STAR: 2131*69112eddSAli Bahrami return (MSG_ORIG(MSG_QSTR_STAR)); 2132*69112eddSAli Bahrami case TK_BANG: 2133*69112eddSAli Bahrami return (MSG_ORIG(MSG_QSTR_BANG)); 2134*69112eddSAli Bahrami default: 2135*69112eddSAli Bahrami assert(0); 2136*69112eddSAli Bahrami break; 2137*69112eddSAli Bahrami } 2138*69112eddSAli Bahrami 2139*69112eddSAli Bahrami /*NOTREACHED*/ 2140*69112eddSAli Bahrami return (MSG_INTL(MSG_MAP_INTERR)); 2141*69112eddSAli Bahrami } 2142*69112eddSAli Bahrami 2143*69112eddSAli Bahrami /* 2144*69112eddSAli Bahrami * Advance the input to the first non-empty line, and determine 2145*69112eddSAli Bahrami * the mapfile version. The version is specified by the mapfile 2146*69112eddSAli Bahrami * using a $mapfile_version directive. The original System V 2147*69112eddSAli Bahrami * syntax lacks this directive, and we use that fact to identify 2148*69112eddSAli Bahrami * such files. SysV mapfile are implicitly defined to have version 1. 2149*69112eddSAli Bahrami * 2150*69112eddSAli Bahrami * entry: 2151*69112eddSAli Bahrami * ofl - Output file descriptor 2152*69112eddSAli Bahrami * mf - Mapfile block 2153*69112eddSAli Bahrami * 2154*69112eddSAli Bahrami * exit: 2155*69112eddSAli Bahrami * On success, updates mf->mf_version, and returns TRUE (1). 2156*69112eddSAli Bahrami * On failure, returns FALSE (0). 2157*69112eddSAli Bahrami */ 2158*69112eddSAli Bahrami static Boolean 2159*69112eddSAli Bahrami mapfile_version(Mapfile *mf) 2160*69112eddSAli Bahrami { 2161*69112eddSAli Bahrami char *line_start = mf->mf_next; 2162*69112eddSAli Bahrami Boolean cont = TRUE; 2163*69112eddSAli Bahrami Boolean status = TRUE; /* Assume success */ 2164*69112eddSAli Bahrami Token tok; 2165*69112eddSAli Bahrami 2166*69112eddSAli Bahrami mf->mf_version = MFV_SYSV; 2167*69112eddSAli Bahrami 2168*69112eddSAli Bahrami /* 2169*69112eddSAli Bahrami * Cycle through the characters looking for tokens. Although the 2170*69112eddSAli Bahrami * true version is not known yet, we use the v2 dispatch table. 2171*69112eddSAli Bahrami * It contains control directives, which we need for this search, 2172*69112eddSAli Bahrami * and the other TK_OP_ tokens we will recognize and act on are the 2173*69112eddSAli Bahrami * same for both tables. 2174*69112eddSAli Bahrami * 2175*69112eddSAli Bahrami * It is important not to process any tokens that would lead to 2176*69112eddSAli Bahrami * a non-OP token: 2177*69112eddSAli Bahrami * 2178*69112eddSAli Bahrami * - The version is required to interpret them 2179*69112eddSAli Bahrami * - Our mapfile descriptor is not fully initialized, 2180*69112eddSAli Bahrami * attempts to run that code will crash the program. 2181*69112eddSAli Bahrami */ 2182*69112eddSAli Bahrami while (cont) { 2183*69112eddSAli Bahrami /* Map the character to a dispatch action */ 2184*69112eddSAli Bahrami tok = (*mf->mf_next & 0x80) ? 2185*69112eddSAli Bahrami TK_OP_ILLCHR : gettok_dispatch_v2[*mf->mf_next]; 2186*69112eddSAli Bahrami 2187*69112eddSAli Bahrami switch (tok) { 2188*69112eddSAli Bahrami case TK_OP_WS: /* White space */ 2189*69112eddSAli Bahrami mf->mf_next++; 2190*69112eddSAli Bahrami break; 2191*69112eddSAli Bahrami 2192*69112eddSAli Bahrami case TK_OP_NL: /* White space too, but bump line number. */ 2193*69112eddSAli Bahrami mf->mf_next++; 2194*69112eddSAli Bahrami mf->mf_lineno++; 2195*69112eddSAli Bahrami break; 2196*69112eddSAli Bahrami 2197*69112eddSAli Bahrami case TK_OP_CMT: 2198*69112eddSAli Bahrami advance_to_eol(&mf->mf_next); 2199*69112eddSAli Bahrami break; 2200*69112eddSAli Bahrami 2201*69112eddSAli Bahrami case TK_OP_CDIR: 2202*69112eddSAli Bahrami /* 2203*69112eddSAli Bahrami * Control directives are only valid at the start 2204*69112eddSAli Bahrami * of a line. However, as we have not yet seen 2205*69112eddSAli Bahrami * a token, we do not need to test for this, and 2206*69112eddSAli Bahrami * can safely assume that we are at the start. 2207*69112eddSAli Bahrami */ 2208*69112eddSAli Bahrami if (!strncasecmp(mf->mf_next, 2209*69112eddSAli Bahrami MSG_ORIG(MSG_STR_CDIR_MFVER), 2210*69112eddSAli Bahrami MSG_STR_CDIR_MFVER_SIZE) && 2211*69112eddSAli Bahrami isspace_nonl(*(mf->mf_next + 2212*69112eddSAli Bahrami MSG_STR_CDIR_MFVER_SIZE))) { 2213*69112eddSAli Bahrami ld_map_tkval_t ver; 2214*69112eddSAli Bahrami 2215*69112eddSAli Bahrami mf->mf_next += MSG_STR_CDIR_MFVER_SIZE + 1; 2216*69112eddSAli Bahrami if (!ld_map_getint(mf, &ver, TRUE)) { 2217*69112eddSAli Bahrami status = cont = FALSE; 2218*69112eddSAli Bahrami break; 2219*69112eddSAli Bahrami } 2220*69112eddSAli Bahrami /* 2221*69112eddSAli Bahrami * Is it a valid version? Note that we 2222*69112eddSAli Bahrami * intentionally do not allow you to 2223*69112eddSAli Bahrami * specify version 1 using the $mapfile_version 2224*69112eddSAli Bahrami * syntax, because that's reserved to version 2225*69112eddSAli Bahrami * 2 and up. 2226*69112eddSAli Bahrami */ 2227*69112eddSAli Bahrami if ((ver.tkv_int.tkvi_value < 2) || 2228*69112eddSAli Bahrami (ver.tkv_int.tkvi_value >= MFV_NUM)) { 2229*69112eddSAli Bahrami const char *fmt; 2230*69112eddSAli Bahrami 2231*69112eddSAli Bahrami fmt = (ver.tkv_int.tkvi_value < 2) ? 2232*69112eddSAli Bahrami MSG_INTL(MSG_MAP_CDIR_BADVDIR) : 2233*69112eddSAli Bahrami MSG_INTL(MSG_MAP_CDIR_BADVER); 2234*69112eddSAli Bahrami mf_fatal(mf, fmt, 2235*69112eddSAli Bahrami EC_WORD(ver.tkv_int.tkvi_value)); 2236*69112eddSAli Bahrami status = cont = FALSE; 2237*69112eddSAli Bahrami break; 2238*69112eddSAli Bahrami } 2239*69112eddSAli Bahrami mf->mf_version = ver.tkv_int.tkvi_value; 2240*69112eddSAli Bahrami cont = FALSE; /* Version recovered. All done */ 2241*69112eddSAli Bahrami break; 2242*69112eddSAli Bahrami } 2243*69112eddSAli Bahrami /* 2244*69112eddSAli Bahrami * Not a version directive. Reset the current position 2245*69112eddSAli Bahrami * to the start of the current line and stop here. 2246*69112eddSAli Bahrami * SysV syntax applies. 2247*69112eddSAli Bahrami */ 2248*69112eddSAli Bahrami mf->mf_next = line_start; 2249*69112eddSAli Bahrami cont = FALSE; 2250*69112eddSAli Bahrami break; 2251*69112eddSAli Bahrami 2252*69112eddSAli Bahrami default: 2253*69112eddSAli Bahrami /* 2254*69112eddSAli Bahrami * If we see anything else, then stop at this point. 2255*69112eddSAli Bahrami * The file has System V syntax (version 1), and the 2256*69112eddSAli Bahrami * next token should be interpreted as such. 2257*69112eddSAli Bahrami */ 2258*69112eddSAli Bahrami cont = FALSE; 2259*69112eddSAli Bahrami break; 2260*69112eddSAli Bahrami } 2261*69112eddSAli Bahrami } 2262*69112eddSAli Bahrami 2263*69112eddSAli Bahrami return (status); 2264*69112eddSAli Bahrami } 2265*69112eddSAli Bahrami 2266*69112eddSAli Bahrami /* 2267*69112eddSAli Bahrami * Parse the mapfile. 2268*69112eddSAli Bahrami */ 2269*69112eddSAli Bahrami Boolean 2270*69112eddSAli Bahrami ld_map_parse(const char *mapfile, Ofl_desc *ofl) 2271*69112eddSAli Bahrami { 2272*69112eddSAli Bahrami struct stat stat_buf; /* stat of mapfile */ 2273*69112eddSAli Bahrami int mapfile_fd; /* descriptor for mapfile */ 2274*69112eddSAli Bahrami int err; 2275*69112eddSAli Bahrami Mapfile *mf; /* Mapfile descriptor */ 2276*69112eddSAli Bahrami size_t name_len; /* strlen(mapfile) */ 2277*69112eddSAli Bahrami 2278*69112eddSAli Bahrami /* 2279*69112eddSAli Bahrami * Determine if we're dealing with a file or a directory. 2280*69112eddSAli Bahrami */ 2281*69112eddSAli Bahrami if (stat(mapfile, &stat_buf) == -1) { 2282*69112eddSAli Bahrami err = errno; 2283*69112eddSAli Bahrami eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_STAT), 2284*69112eddSAli Bahrami mapfile, strerror(err)); 2285*69112eddSAli Bahrami return (FALSE); 2286*69112eddSAli Bahrami } 2287*69112eddSAli Bahrami if (S_ISDIR(stat_buf.st_mode)) { 2288*69112eddSAli Bahrami DIR *dirp; 2289*69112eddSAli Bahrami struct dirent *denp; 2290*69112eddSAli Bahrami 2291*69112eddSAli Bahrami /* 2292*69112eddSAli Bahrami * Open the directory and interpret each visible file as a 2293*69112eddSAli Bahrami * mapfile. 2294*69112eddSAli Bahrami */ 2295*69112eddSAli Bahrami if ((dirp = opendir(mapfile)) == NULL) 2296*69112eddSAli Bahrami return (TRUE); 2297*69112eddSAli Bahrami 2298*69112eddSAli Bahrami while ((denp = readdir(dirp)) != NULL) { 2299*69112eddSAli Bahrami char path[PATH_MAX]; 2300*69112eddSAli Bahrami 2301*69112eddSAli Bahrami /* 2302*69112eddSAli Bahrami * Ignore any hidden filenames. Construct the full 2303*69112eddSAli Bahrami * pathname to the new mapfile. 2304*69112eddSAli Bahrami */ 2305*69112eddSAli Bahrami if (*denp->d_name == '.') 2306*69112eddSAli Bahrami continue; 2307*69112eddSAli Bahrami (void) snprintf(path, PATH_MAX, MSG_ORIG(MSG_STR_PATH), 2308*69112eddSAli Bahrami mapfile, denp->d_name); 2309*69112eddSAli Bahrami if (!ld_map_parse(path, ofl)) 2310*69112eddSAli Bahrami return (FALSE); 2311*69112eddSAli Bahrami } 2312*69112eddSAli Bahrami (void) closedir(dirp); 2313*69112eddSAli Bahrami return (TRUE); 2314*69112eddSAli Bahrami } else if (!S_ISREG(stat_buf.st_mode)) { 2315*69112eddSAli Bahrami eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_NOTREG), 2316*69112eddSAli Bahrami mapfile); 2317*69112eddSAli Bahrami return (FALSE); 2318*69112eddSAli Bahrami } 2319*69112eddSAli Bahrami 2320*69112eddSAli Bahrami /* Open file */ 2321*69112eddSAli Bahrami if ((mapfile_fd = open(mapfile, O_RDONLY)) == -1) { 2322*69112eddSAli Bahrami err = errno; 2323*69112eddSAli Bahrami eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), 2324*69112eddSAli Bahrami mapfile, strerror(err)); 2325*69112eddSAli Bahrami return (FALSE); 2326*69112eddSAli Bahrami } 2327*69112eddSAli Bahrami 2328*69112eddSAli Bahrami /* 2329*69112eddSAli Bahrami * Allocate enough memory to hold the state block, mapfile name, 2330*69112eddSAli Bahrami * and mapfile text. Text has alignment 1, so it can follow the 2331*69112eddSAli Bahrami * state block without padding. 2332*69112eddSAli Bahrami */ 2333*69112eddSAli Bahrami name_len = strlen(mapfile) + 1; 2334*69112eddSAli Bahrami mf = libld_malloc(sizeof (*mf) + name_len + stat_buf.st_size + 1); 2335*69112eddSAli Bahrami if (mf == NULL) 2336*69112eddSAli Bahrami return (FALSE); 2337*69112eddSAli Bahrami mf->mf_ofl = ofl; 2338*69112eddSAli Bahrami mf->mf_name = (char *)(mf + 1); 2339*69112eddSAli Bahrami (void) strcpy(mf->mf_name, mapfile); 2340*69112eddSAli Bahrami mf->mf_text = mf->mf_name + name_len; 2341*69112eddSAli Bahrami if (read(mapfile_fd, mf->mf_text, stat_buf.st_size) != 2342*69112eddSAli Bahrami stat_buf.st_size) { 2343*69112eddSAli Bahrami err = errno; 2344*69112eddSAli Bahrami eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_READ), 2345*69112eddSAli Bahrami mapfile, strerror(err)); 2346*69112eddSAli Bahrami (void) close(mapfile_fd); 2347*69112eddSAli Bahrami return (FALSE); 2348*69112eddSAli Bahrami } 2349*69112eddSAli Bahrami (void) close(mapfile_fd); 2350*69112eddSAli Bahrami mf->mf_text[stat_buf.st_size] = '\0'; 2351*69112eddSAli Bahrami mf->mf_next = mf->mf_text; 2352*69112eddSAli Bahrami mf->mf_lineno = 1; 2353*69112eddSAli Bahrami mf->mf_next_ch = 0; /* No "lookahead" character yet */ 2354*69112eddSAli Bahrami mf->mf_ec_insndx = 0; /* Insert entrace criteria at top */ 2355*69112eddSAli Bahrami 2356*69112eddSAli Bahrami /* 2357*69112eddSAli Bahrami * Read just enough from the mapfile to determine the version, 2358*69112eddSAli Bahrami * and then dispatch to the appropriate code for further processing 2359*69112eddSAli Bahrami */ 2360*69112eddSAli Bahrami if (!mapfile_version(mf)) 2361*69112eddSAli Bahrami return (FALSE); 2362*69112eddSAli Bahrami 2363*69112eddSAli Bahrami /* 2364*69112eddSAli Bahrami * Start and continuation masks for unquoted identifier at this 2365*69112eddSAli Bahrami * mapfile version level. 2366*69112eddSAli Bahrami */ 2367*69112eddSAli Bahrami mf->mf_tkid_start = TKID_ATTR_START(mf->mf_version); 2368*69112eddSAli Bahrami mf->mf_tkid_cont = TKID_ATTR_CONT(mf->mf_version); 2369*69112eddSAli Bahrami 2370*69112eddSAli Bahrami DBG_CALL(Dbg_map_parse(ofl->ofl_lml, mapfile, mf->mf_version)); 2371*69112eddSAli Bahrami 2372*69112eddSAli Bahrami switch (mf->mf_version) { 2373*69112eddSAli Bahrami case MFV_SYSV: 2374*69112eddSAli Bahrami mf->mf_tokdisp = gettok_dispatch_v1; 2375*69112eddSAli Bahrami if (!ld_map_parse_v1(mf)) 2376*69112eddSAli Bahrami return (FALSE); 2377*69112eddSAli Bahrami break; 2378*69112eddSAli Bahrami 2379*69112eddSAli Bahrami case MFV_SOLARIS: 2380*69112eddSAli Bahrami mf->mf_tokdisp = gettok_dispatch_v2; 2381*69112eddSAli Bahrami STACK_RESET(lms.lms_cdir_stack); 2382*69112eddSAli Bahrami 2383*69112eddSAli Bahrami /* 2384*69112eddSAli Bahrami * If the conditional expression identifier tree has not been 2385*69112eddSAli Bahrami * initialized, set it up. This is only done on the first 2386*69112eddSAli Bahrami * mapfile, because the identifier control directives accumulate 2387*69112eddSAli Bahrami * across all the mapfiles. 2388*69112eddSAli Bahrami */ 2389*69112eddSAli Bahrami if ((lms.lms_cexp_id == NULL) && !cexp_ident_init()) 2390*69112eddSAli Bahrami return (FALSE); 2391*69112eddSAli Bahrami 2392*69112eddSAli Bahrami /* 2393*69112eddSAli Bahrami * Tell ld_map_gettoken() we will accept a '$' as starting a 2394*69112eddSAli Bahrami * control directive on the first call. Normally, they are 2395*69112eddSAli Bahrami * only allowed after a newline. 2396*69112eddSAli Bahrami */ 2397*69112eddSAli Bahrami lms.lms_cdir_valid = 1; 2398*69112eddSAli Bahrami 2399*69112eddSAli Bahrami if (!ld_map_parse_v2(mf)) 2400*69112eddSAli Bahrami return (FALSE); 2401*69112eddSAli Bahrami 2402*69112eddSAli Bahrami /* Did we leave any open $if control directives? */ 2403*69112eddSAli Bahrami if (!STACK_IS_EMPTY(lms.lms_cdir_stack)) { 2404*69112eddSAli Bahrami while (!STACK_IS_EMPTY(lms.lms_cdir_stack)) { 2405*69112eddSAli Bahrami cdir_level_t *level = 2406*69112eddSAli Bahrami &STACK_POP(lms.lms_cdir_stack); 2407*69112eddSAli Bahrami 2408*69112eddSAli Bahrami mf_fatal(mf, MSG_INTL(MSG_MAP_CDIR_NOEND), 2409*69112eddSAli Bahrami EC_LINENO(level->cdl_if_lineno)); 2410*69112eddSAli Bahrami } 2411*69112eddSAli Bahrami return (FALSE); 2412*69112eddSAli Bahrami } 2413*69112eddSAli Bahrami break; 2414*69112eddSAli Bahrami } 2415*69112eddSAli Bahrami 2416*69112eddSAli Bahrami return (TRUE); 2417*69112eddSAli Bahrami } 2418*69112eddSAli Bahrami 2419*69112eddSAli Bahrami /* 2420*69112eddSAli Bahrami * Sort the segment list. This is necessary if a mapfile has set explicit 2421*69112eddSAli Bahrami * virtual addresses for segments, or defined a SEGMENT_ORDER directive. 2422*69112eddSAli Bahrami * 2423*69112eddSAli Bahrami * Only PT_LOAD segments can be assigned a virtual address. These segments can 2424*69112eddSAli Bahrami * be one of two types: 2425*69112eddSAli Bahrami * 2426*69112eddSAli Bahrami * - Standard segments for text, data or bss. These segments will have been 2427*69112eddSAli Bahrami * inserted before the default text (first PT_LOAD) segment. 2428*69112eddSAli Bahrami * 2429*69112eddSAli Bahrami * - Empty (reservation) segments. These segment will have been inserted at 2430*69112eddSAli Bahrami * the end of any default PT_LOAD segments. 2431*69112eddSAli Bahrami * 2432*69112eddSAli Bahrami * Any standard segments that are assigned a virtual address will be sorted, 2433*69112eddSAli Bahrami * and as their definitions precede any default PT_LOAD segments, these segments 2434*69112eddSAli Bahrami * will be assigned sections before any defaults. 2435*69112eddSAli Bahrami * 2436*69112eddSAli Bahrami * Any reservation segments are also sorted amoung themselves, as these segments 2437*69112eddSAli Bahrami * must still follow the standard default segments. 2438*69112eddSAli Bahrami */ 2439*69112eddSAli Bahrami static Boolean 2440*69112eddSAli Bahrami sort_seg_list(Ofl_desc *ofl) 2441*69112eddSAli Bahrami { 2442*69112eddSAli Bahrami APlist *sort_segs = NULL, *load_segs = NULL; 2443*69112eddSAli Bahrami Sg_desc *sgp1; 2444*69112eddSAli Bahrami Aliste idx1; 2445*69112eddSAli Bahrami Aliste nsegs; 2446*69112eddSAli Bahrami 2447*69112eddSAli Bahrami 2448*69112eddSAli Bahrami /* 2449*69112eddSAli Bahrami * We know the number of elements in the sorted list will be 2450*69112eddSAli Bahrami * the same as the original, so use this as the initial allocation 2451*69112eddSAli Bahrami * size for the replacement aplist. 2452*69112eddSAli Bahrami */ 2453*69112eddSAli Bahrami nsegs = aplist_nitems(ofl->ofl_segs); 2454*69112eddSAli Bahrami 2455*69112eddSAli Bahrami 2456*69112eddSAli Bahrami /* Add the items below SGID_TEXT to the list */ 2457*69112eddSAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp1)) { 2458*69112eddSAli Bahrami if (sgp1->sg_id >= SGID_TEXT) 2459*69112eddSAli Bahrami break; 2460*69112eddSAli Bahrami 2461*69112eddSAli Bahrami if (aplist_append(&sort_segs, sgp1, nsegs) == NULL) 2462*69112eddSAli Bahrami return (FALSE); 2463*69112eddSAli Bahrami } 2464*69112eddSAli Bahrami 2465*69112eddSAli Bahrami /* 2466*69112eddSAli Bahrami * If there are any SEGMENT_ORDER items, add them, and set their 2467*69112eddSAli Bahrami * FLG_SG_ORDERED flag to identify them in debug output, and to 2468*69112eddSAli Bahrami * prevent them from being added again below. 2469*69112eddSAli Bahrami */ 2470*69112eddSAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_segs_order, idx1, sgp1)) { 2471*69112eddSAli Bahrami if (aplist_append(&sort_segs, sgp1, nsegs) == NULL) 2472*69112eddSAli Bahrami return (FALSE); 2473*69112eddSAli Bahrami sgp1->sg_flags |= FLG_SG_ORDERED; 2474*69112eddSAli Bahrami } 2475*69112eddSAli Bahrami 2476*69112eddSAli Bahrami /* 2477*69112eddSAli Bahrami * Add the loadable segments to another list in sorted order. 2478*69112eddSAli Bahrami */ 2479*69112eddSAli Bahrami DBG_CALL(Dbg_map_sort_title(ofl->ofl_lml, TRUE)); 2480*69112eddSAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp1)) { 2481*69112eddSAli Bahrami DBG_CALL(Dbg_map_sort_seg(ofl->ofl_lml, ELFOSABI_SOLARIS, 2482*69112eddSAli Bahrami ld_targ.t_m.m_mach, sgp1)); 2483*69112eddSAli Bahrami 2484*69112eddSAli Bahrami /* Only interested in PT_LOAD items not in SEGMENT_ORDER list */ 2485*69112eddSAli Bahrami if ((sgp1->sg_phdr.p_type != PT_LOAD) || 2486*69112eddSAli Bahrami (sgp1->sg_flags & FLG_SG_ORDERED)) 2487*69112eddSAli Bahrami continue; 2488*69112eddSAli Bahrami 2489*69112eddSAli Bahrami /* 2490*69112eddSAli Bahrami * If the loadable segment does not contain a vaddr, simply 2491*69112eddSAli Bahrami * append it to the new list. 2492*69112eddSAli Bahrami */ 2493*69112eddSAli Bahrami if ((sgp1->sg_flags & FLG_SG_P_VADDR) == 0) { 2494*69112eddSAli Bahrami if (aplist_append(&load_segs, sgp1, AL_CNT_SEGMENTS) == 2495*69112eddSAli Bahrami NULL) 2496*69112eddSAli Bahrami return (FALSE); 2497*69112eddSAli Bahrami 2498*69112eddSAli Bahrami } else { 2499*69112eddSAli Bahrami Aliste idx2; 2500*69112eddSAli Bahrami Sg_desc *sgp2; 2501*69112eddSAli Bahrami int inserted = 0; 2502*69112eddSAli Bahrami 2503*69112eddSAli Bahrami /* 2504*69112eddSAli Bahrami * Traverse the segment list we are creating, looking 2505*69112eddSAli Bahrami * for a segment that defines a vaddr. 2506*69112eddSAli Bahrami */ 2507*69112eddSAli Bahrami for (APLIST_TRAVERSE(load_segs, idx2, sgp2)) { 2508*69112eddSAli Bahrami /* 2509*69112eddSAli Bahrami * Any real segments that contain vaddr's need 2510*69112eddSAli Bahrami * to be sorted. Any reservation segments also 2511*69112eddSAli Bahrami * need to be sorted. However, any reservation 2512*69112eddSAli Bahrami * segments should be placed after any real 2513*69112eddSAli Bahrami * segments. 2514*69112eddSAli Bahrami */ 2515*69112eddSAli Bahrami if (((sgp2->sg_flags & 2516*69112eddSAli Bahrami (FLG_SG_P_VADDR | FLG_SG_EMPTY)) == 0) && 2517*69112eddSAli Bahrami (sgp1->sg_flags & FLG_SG_EMPTY)) 2518*69112eddSAli Bahrami continue; 2519*69112eddSAli Bahrami 2520*69112eddSAli Bahrami if ((sgp2->sg_flags & FLG_SG_P_VADDR) && 2521*69112eddSAli Bahrami ((sgp2->sg_flags & FLG_SG_EMPTY) == 2522*69112eddSAli Bahrami (sgp1->sg_flags & FLG_SG_EMPTY))) { 2523*69112eddSAli Bahrami if (sgp1->sg_phdr.p_vaddr == 2524*69112eddSAli Bahrami sgp2->sg_phdr.p_vaddr) { 2525*69112eddSAli Bahrami eprintf(ofl->ofl_lml, ERR_FATAL, 2526*69112eddSAli Bahrami MSG_INTL(MSG_MAP_SEGSAME), 2527*69112eddSAli Bahrami sgp1->sg_name, 2528*69112eddSAli Bahrami sgp2->sg_name); 2529*69112eddSAli Bahrami return (FALSE); 2530*69112eddSAli Bahrami } 2531*69112eddSAli Bahrami 2532*69112eddSAli Bahrami if (sgp1->sg_phdr.p_vaddr > 2533*69112eddSAli Bahrami sgp2->sg_phdr.p_vaddr) 2534*69112eddSAli Bahrami continue; 2535*69112eddSAli Bahrami } 2536*69112eddSAli Bahrami 2537*69112eddSAli Bahrami /* 2538*69112eddSAli Bahrami * Insert this segment before the segment on 2539*69112eddSAli Bahrami * the load_segs list. 2540*69112eddSAli Bahrami */ 2541*69112eddSAli Bahrami if (aplist_insert(&load_segs, sgp1, 2542*69112eddSAli Bahrami AL_CNT_SEGMENTS, idx2) == NULL) 2543*69112eddSAli Bahrami return (FALSE); 2544*69112eddSAli Bahrami inserted = 1; 2545*69112eddSAli Bahrami break; 2546*69112eddSAli Bahrami } 2547*69112eddSAli Bahrami 2548*69112eddSAli Bahrami /* 2549*69112eddSAli Bahrami * If the segment being inspected has not been inserted 2550*69112eddSAli Bahrami * in the segment list, simply append it to the list. 2551*69112eddSAli Bahrami */ 2552*69112eddSAli Bahrami if ((inserted == 0) && (aplist_append(&load_segs, 2553*69112eddSAli Bahrami sgp1, AL_CNT_SEGMENTS) == NULL)) 2554*69112eddSAli Bahrami return (FALSE); 2555*69112eddSAli Bahrami } 2556*69112eddSAli Bahrami } 2557*69112eddSAli Bahrami 2558*69112eddSAli Bahrami /* 2559*69112eddSAli Bahrami * Add the sorted loadable segments to our initial segment list. 2560*69112eddSAli Bahrami */ 2561*69112eddSAli Bahrami for (APLIST_TRAVERSE(load_segs, idx1, sgp1)) { 2562*69112eddSAli Bahrami if (aplist_append(&sort_segs, sgp1, AL_CNT_SEGMENTS) == NULL) 2563*69112eddSAli Bahrami return (FALSE); 2564*69112eddSAli Bahrami } 2565*69112eddSAli Bahrami 2566*69112eddSAli Bahrami /* 2567*69112eddSAli Bahrami * Add all other segments to our list. 2568*69112eddSAli Bahrami */ 2569*69112eddSAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp1)) { 2570*69112eddSAli Bahrami if ((sgp1->sg_id < SGID_TEXT) || 2571*69112eddSAli Bahrami (sgp1->sg_phdr.p_type == PT_LOAD) || 2572*69112eddSAli Bahrami (sgp1->sg_flags & FLG_SG_ORDERED)) 2573*69112eddSAli Bahrami continue; 2574*69112eddSAli Bahrami 2575*69112eddSAli Bahrami if (aplist_append(&sort_segs, sgp1, AL_CNT_SEGMENTS) == NULL) 2576*69112eddSAli Bahrami return (FALSE); 2577*69112eddSAli Bahrami } 2578*69112eddSAli Bahrami 2579*69112eddSAli Bahrami /* 2580*69112eddSAli Bahrami * Free the original list, and the pt_load list, and use 2581*69112eddSAli Bahrami * the new list as the segment list. 2582*69112eddSAli Bahrami */ 2583*69112eddSAli Bahrami free(ofl->ofl_segs); 2584*69112eddSAli Bahrami if (load_segs) free(load_segs); 2585*69112eddSAli Bahrami ofl->ofl_segs = sort_segs; 2586*69112eddSAli Bahrami 2587*69112eddSAli Bahrami if (DBG_ENABLED) { 2588*69112eddSAli Bahrami Dbg_map_sort_title(ofl->ofl_lml, FALSE); 2589*69112eddSAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp1)) { 2590*69112eddSAli Bahrami Dbg_map_sort_seg(ofl->ofl_lml, ELFOSABI_SOLARIS, 2591*69112eddSAli Bahrami ld_targ.t_m.m_mach, sgp1); 2592*69112eddSAli Bahrami } 2593*69112eddSAli Bahrami } 2594*69112eddSAli Bahrami 2595*69112eddSAli Bahrami return (TRUE); 2596*69112eddSAli Bahrami } 2597*69112eddSAli Bahrami 2598*69112eddSAli Bahrami /* 2599*69112eddSAli Bahrami * After all mapfiles have been processed, this routine is used to 2600*69112eddSAli Bahrami * finish any remaining mapfile related work. 2601*69112eddSAli Bahrami * 2602*69112eddSAli Bahrami * exit: 2603*69112eddSAli Bahrami * Returns TRUE on success, and FALSE on failure. 2604*69112eddSAli Bahrami */ 2605*69112eddSAli Bahrami Boolean 2606*69112eddSAli Bahrami ld_map_post_process(Ofl_desc *ofl) 2607*69112eddSAli Bahrami { 2608*69112eddSAli Bahrami Aliste idx, idx2; 2609*69112eddSAli Bahrami Is_desc *isp; 2610*69112eddSAli Bahrami Sg_desc *sgp; 2611*69112eddSAli Bahrami Ent_desc *enp; 2612*69112eddSAli Bahrami Sg_desc *first_seg = NULL; 2613*69112eddSAli Bahrami 2614*69112eddSAli Bahrami 2615*69112eddSAli Bahrami DBG_CALL(Dbg_map_post_title(ofl->ofl_lml)); 2616*69112eddSAli Bahrami 2617*69112eddSAli Bahrami /* 2618*69112eddSAli Bahrami * Per-segment processing: 2619*69112eddSAli Bahrami * - Identify segments with explicit virtual address 2620*69112eddSAli Bahrami * - Details of input and output section order 2621*69112eddSAli Bahrami */ 2622*69112eddSAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_segs, idx, sgp)) { 2623*69112eddSAli Bahrami /* 2624*69112eddSAli Bahrami * We are looking for segments. Program headers that represent 2625*69112eddSAli Bahrami * segments are required to have a non-NULL name pointer, 2626*69112eddSAli Bahrami * while that those that do not are required to have a 2627*69112eddSAli Bahrami * NULL name pointer. 2628*69112eddSAli Bahrami */ 2629*69112eddSAli Bahrami if (sgp->sg_name == NULL) 2630*69112eddSAli Bahrami continue; 2631*69112eddSAli Bahrami 2632*69112eddSAli Bahrami /* Remember the first non-disabled segment */ 2633*69112eddSAli Bahrami if ((first_seg == NULL) && !(sgp->sg_flags & FLG_SG_DISABLED)) 2634*69112eddSAli Bahrami first_seg = sgp; 2635*69112eddSAli Bahrami 2636*69112eddSAli Bahrami /* 2637*69112eddSAli Bahrami * If a segment has an explicit virtual address, we will 2638*69112eddSAli Bahrami * need to sort the segments. 2639*69112eddSAli Bahrami */ 2640*69112eddSAli Bahrami if (sgp->sg_flags & FLG_SG_P_VADDR) 2641*69112eddSAli Bahrami ofl->ofl_flags1 |= FLG_OF1_VADDR; 2642*69112eddSAli Bahrami 2643*69112eddSAli Bahrami /* 2644*69112eddSAli Bahrami * The FLG_OF_OS_ORDER flag enables the code that does 2645*69112eddSAli Bahrami * output section ordering. Set if the segment has 2646*69112eddSAli Bahrami * a non-empty output section order list. 2647*69112eddSAli Bahrami */ 2648*69112eddSAli Bahrami if (alist_nitems(sgp->sg_os_order) > 0) 2649*69112eddSAli Bahrami ofl->ofl_flags |= FLG_OF_OS_ORDER; 2650*69112eddSAli Bahrami 2651*69112eddSAli Bahrami /* 2652*69112eddSAli Bahrami * The version 1 and version 2 syntaxes for input section 2653*69112eddSAli Bahrami * ordering are different and incompatible enough that we 2654*69112eddSAli Bahrami * only allow the use of one or the other for a given segment: 2655*69112eddSAli Bahrami * 2656*69112eddSAli Bahrami * v1) The version 1 syntax has the user set the ?O flag on 2657*69112eddSAli Bahrami * the segment. If this is done, all input sections placed 2658*69112eddSAli Bahrami * via an entrance criteria that has a section name are to 2659*69112eddSAli Bahrami * be sorted, using the order of the entrance criteria 2660*69112eddSAli Bahrami * as the sort key. 2661*69112eddSAli Bahrami * 2662*69112eddSAli Bahrami * v2) The version 2 syntax has the user specify a name for 2663*69112eddSAli Bahrami * the entry criteria, and then provide a list of entry 2664*69112eddSAli Bahrami * criteria names via the IS_ORDER segment attribute. 2665*69112eddSAli Bahrami * Sections placed via the criteria listed in IS_ORDER 2666*69112eddSAli Bahrami * are sorted, and the others are not. 2667*69112eddSAli Bahrami * 2668*69112eddSAli Bahrami * Regardless of the syntax version used, the section sorting 2669*69112eddSAli Bahrami * code expects the following: 2670*69112eddSAli Bahrami * 2671*69112eddSAli Bahrami * - Segments requiring input section sorting have the 2672*69112eddSAli Bahrami * FLG_SG_IS_ORDER flag set 2673*69112eddSAli Bahrami * 2674*69112eddSAli Bahrami * - Entrance criteria referencing the segment that 2675*69112eddSAli Bahrami * participate in input section sorting have a non-zero 2676*69112eddSAli Bahrami * sort key in their ec_ordndx field. 2677*69112eddSAli Bahrami * 2678*69112eddSAli Bahrami * At this point, the following are true: 2679*69112eddSAli Bahrami * 2680*69112eddSAli Bahrami * - All entrance criteria have ec_ordndx set to 0. 2681*69112eddSAli Bahrami * - Segments that require the version 1 behavior have 2682*69112eddSAli Bahrami * the FLG_SG_IS_ORDER flag set, and the segments 2683*69112eddSAli Bahrami * sg_is_order list is empty. 2684*69112eddSAli Bahrami * - Segments that require the version 2 behavior do not 2685*69112eddSAli Bahrami * have FLG_SG_IS_ORDER set, and the sg_is_order list is 2686*69112eddSAli Bahrami * non-empty. This list contains the names of the entrance 2687*69112eddSAli Bahrami * criteria that will participate in input section sorting, 2688*69112eddSAli Bahrami * and their relative order in the list provides the 2689*69112eddSAli Bahrami * sort key to use. 2690*69112eddSAli Bahrami * 2691*69112eddSAli Bahrami * We must detect these two cases, set the FLG_SG_IS_ORDER 2692*69112eddSAli Bahrami * flag as necessary, and fill in all entrance criteria 2693*69112eddSAli Bahrami * sort keys. If any input section sorting is to be done, 2694*69112eddSAli Bahrami * we also set the FLG_OF_IS_ORDER flag on the output descriptor 2695*69112eddSAli Bahrami * to enable the code that does that work. 2696*69112eddSAli Bahrami */ 2697*69112eddSAli Bahrami 2698*69112eddSAli Bahrami /* Version 1: ?O flag? */ 2699*69112eddSAli Bahrami if (sgp->sg_flags & FLG_SG_IS_ORDER) { 2700*69112eddSAli Bahrami Word index = 0; 2701*69112eddSAli Bahrami 2702*69112eddSAli Bahrami ofl->ofl_flags |= FLG_OF_IS_ORDER; 2703*69112eddSAli Bahrami DBG_CALL(Dbg_map_ent_ord_title(ofl->ofl_lml, 2704*69112eddSAli Bahrami sgp->sg_name)); 2705*69112eddSAli Bahrami 2706*69112eddSAli Bahrami /* 2707*69112eddSAli Bahrami * Give each user defined entrance criteria for this 2708*69112eddSAli Bahrami * segment that specifies a section name a 2709*69112eddSAli Bahrami * monotonically increasing sort key. 2710*69112eddSAli Bahrami */ 2711*69112eddSAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_ents, idx2, enp)) 2712*69112eddSAli Bahrami if ((enp->ec_segment == sgp) && 2713*69112eddSAli Bahrami (enp->ec_is_name != NULL) && 2714*69112eddSAli Bahrami ((enp->ec_flags & FLG_EC_BUILTIN) == 0)) 2715*69112eddSAli Bahrami enp->ec_ordndx = ++index; 2716*69112eddSAli Bahrami continue; 2717*69112eddSAli Bahrami } 2718*69112eddSAli Bahrami 2719*69112eddSAli Bahrami /* Version 2: SEGMENT IS_ORDER list? */ 2720*69112eddSAli Bahrami if (aplist_nitems(sgp->sg_is_order) > 0) { 2721*69112eddSAli Bahrami Word index = 0; 2722*69112eddSAli Bahrami 2723*69112eddSAli Bahrami ofl->ofl_flags |= FLG_OF_IS_ORDER; 2724*69112eddSAli Bahrami DBG_CALL(Dbg_map_ent_ord_title(ofl->ofl_lml, 2725*69112eddSAli Bahrami sgp->sg_name)); 2726*69112eddSAli Bahrami 2727*69112eddSAli Bahrami /* 2728*69112eddSAli Bahrami * Give each entrance criteria in the sg_is_order 2729*69112eddSAli Bahrami * list a monotonically increasing sort key. 2730*69112eddSAli Bahrami */ 2731*69112eddSAli Bahrami for (APLIST_TRAVERSE(sgp->sg_is_order, idx2, enp)) { 2732*69112eddSAli Bahrami enp->ec_ordndx = ++index; 2733*69112eddSAli Bahrami enp->ec_segment->sg_flags |= FLG_SG_IS_ORDER; 2734*69112eddSAli Bahrami } 2735*69112eddSAli Bahrami } 2736*69112eddSAli Bahrami } 2737*69112eddSAli Bahrami 2738*69112eddSAli Bahrami /* Sort the segment descriptors if necessary */ 2739*69112eddSAli Bahrami if (((ofl->ofl_flags1 & FLG_OF1_VADDR) || 2740*69112eddSAli Bahrami (aplist_nitems(ofl->ofl_segs_order) > 0)) && 2741*69112eddSAli Bahrami !sort_seg_list(ofl)) 2742*69112eddSAli Bahrami return (FALSE); 2743*69112eddSAli Bahrami 2744*69112eddSAli Bahrami /* 2745*69112eddSAli Bahrami * If the output file is a static file without an interpreter, and 2746*69112eddSAli Bahrami * if any virtual address is specified, then set the NOHDR flag for 2747*69112eddSAli Bahrami * backward compatibility. 2748*69112eddSAli Bahrami */ 2749*69112eddSAli Bahrami if (!(ofl->ofl_flags & (FLG_OF_DYNAMIC | FLG_OF_RELOBJ)) && 2750*69112eddSAli Bahrami !(ofl->ofl_osinterp) && (ofl->ofl_flags1 & FLG_OF1_VADDR)) 2751*69112eddSAli Bahrami ofl->ofl_dtflags_1 |= DF_1_NOHDR; 2752*69112eddSAli Bahrami 2753*69112eddSAli Bahrami if (ofl->ofl_flags & FLG_OF_RELOBJ) { 2754*69112eddSAli Bahrami /* 2755*69112eddSAli Bahrami * NOHDR has no effect on a relocatable file. 2756*69112eddSAli Bahrami * Make sure this flag isn't set. 2757*69112eddSAli Bahrami */ 2758*69112eddSAli Bahrami ofl->ofl_dtflags_1 &= ~DF_1_NOHDR; 2759*69112eddSAli Bahrami } else if (first_seg != NULL) { 2760*69112eddSAli Bahrami /* 2761*69112eddSAli Bahrami * DF_1_NOHDR might have been set globally by the HDR_NOALLOC 2762*69112eddSAli Bahrami * directive. If not, then we want to check the per-segment 2763*69112eddSAli Bahrami * flag for the first loadable segment and propagate it 2764*69112eddSAli Bahrami * if set. 2765*69112eddSAli Bahrami */ 2766*69112eddSAli Bahrami if ((ofl->ofl_dtflags_1 & DF_1_NOHDR) == 0) { 2767*69112eddSAli Bahrami /* 2768*69112eddSAli Bahrami * If we sorted the segments, the first segment 2769*69112eddSAli Bahrami * may have changed. 2770*69112eddSAli Bahrami */ 2771*69112eddSAli Bahrami if ((ofl->ofl_flags1 & FLG_OF1_VADDR) || 2772*69112eddSAli Bahrami (aplist_nitems(ofl->ofl_segs_order) > 0)) { 2773*69112eddSAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_segs, idx, sgp)) { 2774*69112eddSAli Bahrami if (sgp->sg_name == NULL) 2775*69112eddSAli Bahrami continue; 2776*69112eddSAli Bahrami if ((sgp->sg_flags & FLG_SG_DISABLED) == 2777*69112eddSAli Bahrami 0) { 2778*69112eddSAli Bahrami first_seg = sgp; 2779*69112eddSAli Bahrami break; 2780*69112eddSAli Bahrami } 2781*69112eddSAli Bahrami } 2782*69112eddSAli Bahrami } 2783*69112eddSAli Bahrami 2784*69112eddSAli Bahrami /* 2785*69112eddSAli Bahrami * If the per-segment NOHDR flag is set on our first 2786*69112eddSAli Bahrami * segment, then make it take effect. 2787*69112eddSAli Bahrami */ 2788*69112eddSAli Bahrami if (first_seg->sg_flags & FLG_SG_NOHDR) 2789*69112eddSAli Bahrami ofl->ofl_dtflags_1 |= DF_1_NOHDR; 2790*69112eddSAli Bahrami } 2791*69112eddSAli Bahrami 2792*69112eddSAli Bahrami /* 2793*69112eddSAli Bahrami * For executable and shared objects, the first segment must 2794*69112eddSAli Bahrami * be loadable unless NOHDR was specified, because the ELF 2795*69112eddSAli Bahrami * header must simultaneously lie at offset 0 of the file and 2796*69112eddSAli Bahrami * be included in the first loadable segment. This isn't 2797*69112eddSAli Bahrami * possible if some other segment type starts the file 2798*69112eddSAli Bahrami */ 2799*69112eddSAli Bahrami if (!(ofl->ofl_dtflags_1 & DF_1_NOHDR) && 2800*69112eddSAli Bahrami (first_seg->sg_phdr.p_type != PT_LOAD)) { 2801*69112eddSAli Bahrami Conv_inv_buf_t inv_buf; 2802*69112eddSAli Bahrami 2803*69112eddSAli Bahrami eprintf(ofl->ofl_lml, ERR_FATAL, 2804*69112eddSAli Bahrami MSG_INTL(MSG_SEG_FIRNOTLOAD), 2805*69112eddSAli Bahrami conv_phdr_type(ELFOSABI_SOLARIS, ld_targ.t_m.m_mach, 2806*69112eddSAli Bahrami first_seg->sg_phdr.p_type, 0, &inv_buf), 2807*69112eddSAli Bahrami first_seg->sg_name); 2808*69112eddSAli Bahrami return (FALSE); 2809*69112eddSAli Bahrami } 2810*69112eddSAli Bahrami } 2811*69112eddSAli Bahrami 2812*69112eddSAli Bahrami /* 2813*69112eddSAli Bahrami * Mapfiles may have been used to create symbol definitions 2814*69112eddSAli Bahrami * with backing storage. Although the backing storage is 2815*69112eddSAli Bahrami * associated with an input section, the association of the 2816*69112eddSAli Bahrami * section to an output section (and segment) is initially 2817*69112eddSAli Bahrami * deferred. Now that all mapfile processing is complete, any 2818*69112eddSAli Bahrami * entrance criteria requirements have been processed, and 2819*69112eddSAli Bahrami * these backing storage sections can be associated with the 2820*69112eddSAli Bahrami * appropriate output section (and segment). 2821*69112eddSAli Bahrami */ 2822*69112eddSAli Bahrami if (ofl->ofl_maptext || ofl->ofl_mapdata) 2823*69112eddSAli Bahrami DBG_CALL(Dbg_sec_backing(ofl->ofl_lml)); 2824*69112eddSAli Bahrami 2825*69112eddSAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_maptext, idx, isp)) { 2826*69112eddSAli Bahrami if (ld_place_section(ofl, isp, NULL, 2827*69112eddSAli Bahrami ld_targ.t_id.id_text, NULL) == (Os_desc *)S_ERROR) 2828*69112eddSAli Bahrami return (FALSE); 2829*69112eddSAli Bahrami } 2830*69112eddSAli Bahrami 2831*69112eddSAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_mapdata, idx, isp)) { 2832*69112eddSAli Bahrami if (ld_place_section(ofl, isp, NULL, 2833*69112eddSAli Bahrami ld_targ.t_id.id_data, NULL) == (Os_desc *)S_ERROR) 2834*69112eddSAli Bahrami return (FALSE); 2835*69112eddSAli Bahrami } 2836*69112eddSAli Bahrami 2837*69112eddSAli Bahrami return (TRUE); 2838*69112eddSAli Bahrami } 2839