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