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