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_support.c
+++ new/usr/src/cmd/sgs/libld/common/map_support.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
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
21 21
22 22 /*
23 23 * Copyright (c) 1988 AT&T
24 24 * All Rights Reserved
25 25 *
26 26 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
27 27 * Use is subject to license terms.
28 28 */
29 29
30 30 /*
31 - * Copyright (c) 2013, Joyent, Inc. All rights reserved.
31 + * Copyright 2019 Joyent, Inc.
32 32 */
33 33
34 34 /*
35 35 * Map file parsing (Shared Support Code).
36 36 */
37 37 #include <stdio.h>
38 38 #include <errno.h>
39 39 #include "msg.h"
40 40 #include "_libld.h"
41 41 #include "_map.h"
42 42
43 43 /*
44 44 * Given a NULL terminated array of structures of arbitrary type, where
45 45 * each struct contains (among other fields) a character pointer field
46 46 * giving that struct a unique name, return the address of the struct
47 47 * that matches the given name.
48 48 *
49 49 * entry:
50 50 * name - "Keyword" name to be found.
51 51 * array - Base address of array
52 52 * name_offset - Offset of the name field within the struct
53 53 * type used by this array, as generated via
54 54 * SGSOFFSETOF().
55 55 * elt_size - sizeof the basic array element type
56 56 *
57 57 * exit:
58 58 * Using a case insensitive comparison, name is compared to the
59 59 * name of each element of the array. The address of the first
60 60 * match found is returned. If the desired name is not found,
61 61 * NULL is returned.
62 62 *
63 63 * note:
64 64 * This routine is completely type-unsafe. The upside is that this
65 65 * single routine is able to search arrays of arbitrary type, leaving
66 66 * the caller free to structure their array in any way that is convenient
67 67 * to solve the problem at hand.
68 68 */
69 69 #ifndef _ELF64
70 70 void *
71 71 ld_map_kwfind(const char *name, void *array, size_t name_offset,
72 72 size_t elt_size)
73 73 {
74 74 for (; ; array = elt_size + (char *)array) {
75 75 /* LINTED E_BAD_PTR_CAST_ALIGN */
76 76 const char *arr_name = *((const char **)
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
77 77 (name_offset + (const char *) array));
78 78
79 79 if (arr_name == NULL)
80 80 return (NULL);
81 81
82 82 if (strcasecmp(name, arr_name) == 0)
83 83 return (array);
84 84 }
85 85
86 86 /*NOTREACHED*/
87 - assert(0);
88 - return (NULL);
89 87 }
90 88 #endif
91 89
92 90 /*
93 91 * Given the same NULL terminated array accepted by ld_map_kwfind(), format
94 92 * the strings into a comma separated list of names.
95 93 *
96 94 * entry:
97 95 * array - Base address of array
98 96 * name_offset - Offset of the name field within the struct
99 97 * type used by this array, as generated via
100 98 * SGSOFFSETOF().
101 99 * elt_size - sizeof the basic array element type
102 100 * buf - Buffer to receive output
103 101 * bufsize - sizeof(buf)
104 102 *
105 103 * exit:
106 104 * As many of the names as will fit are formatted into buf. If all the
107 105 * names do not fit, the remainder are quietly clipped. The caller must
108 106 * ensure that there is sufficient room. buf is returned, for convenience
109 107 * in using this function as an argument for printing.
110 108 */
111 109 #ifndef _ELF64
112 110 char *
113 111 ld_map_kwnames(void *array, size_t name_offset, size_t elt_size, char *buf,
114 112 size_t bufsize)
115 113 {
116 114 size_t cnt = 0;
117 115 size_t len;
118 116 char *str = buf;
119 117
120 118 for (; bufsize > 1; array = elt_size + (char *)array, cnt++) {
121 119 /* LINTED E_BAD_PTR_CAST_ALIGN */
122 120 const char *arr_name = *((const char **)
123 121 (name_offset + (const char *) array));
124 122
125 123 if (arr_name == NULL)
126 124 break;
127 125
128 126 if (cnt > 0) {
129 127 if (bufsize < 3)
130 128 break;
131 129 *str++ = ',';
132 130 *str++ = ' ';
133 131 bufsize -= 2;
134 132 *(str + 1) = '\0';
135 133 }
136 134
137 135 len = strlcpy(str, arr_name, bufsize);
138 136 if (len >= bufsize)
139 137 break;
140 138 str += len;
141 139 bufsize -= len;
142 140 }
143 141
144 142 return (buf);
145 143 }
146 144 #endif
147 145
148 146 /*
149 147 * Create a pseudo input file descriptor to represent the specified Mapfile.
150 148 * An input descriptor is required any time a symbol is generated.
151 149 *
152 150 * entry:
153 151 * mf - Mapfile descriptor.
154 152 *
155 153 * exit:
156 154 * If an input descriptor was already created for this mapfile
157 155 * by a previous call, it is returned. Otherwise, a new descriptor
158 156 * is created, entered into the mapfile descriptor, and returned.
159 157 *
160 158 * Success is indicated by a non-NULL return value, failure by NULL.
161 159 */
162 160 Ifl_desc *
163 161 ld_map_ifl(Mapfile *mf)
164 162 {
165 163 Ifl_desc *ifl;
166 164
167 165 /*
168 166 * If we've already created a pseudo input descriptor for this
169 167 * mapfile, reuse it.
170 168 */
171 169 if (mf->mf_ifl != NULL)
172 170 return (mf->mf_ifl);
173 171
174 172 if ((ifl = libld_calloc(sizeof (Ifl_desc), 1)) == NULL)
175 173 return (NULL);
176 174 ifl->ifl_name = mf->mf_name;
177 175 ifl->ifl_flags = (FLG_IF_MAPFILE | FLG_IF_NEEDED | FLG_IF_FILEREF);
178 176 if ((ifl->ifl_ehdr = libld_calloc(sizeof (Ehdr), 1)) == NULL)
179 177 return (NULL);
180 178 ifl->ifl_ehdr->e_type = ET_REL;
181 179
182 180 if (aplist_append(&mf->mf_ofl->ofl_objs, ifl, AL_CNT_OFL_OBJS) == NULL)
183 181 return (NULL);
184 182
185 183 mf->mf_ifl = ifl;
186 184 return (mf->mf_ifl);
187 185 }
188 186
189 187 /*
190 188 * Given a capability tag type, set the override bit in the output descriptor.
191 189 * This prevents the use of capability values of that type from the input
↓ open down ↓ |
93 lines elided |
↑ open up ↑ |
192 190 * objects.
193 191 */
194 192 void
195 193 ld_map_cap_set_ovflag(Mapfile *mf, Word type)
196 194 {
197 195 /*
198 196 * Map capability tag to the corresponding output descriptor
199 197 * override flag.
200 198 */
201 199 static ofl_flag_t override_flag[CA_SUNW_NUM] = {
202 - 0, /* CA_SUNW_NULL */
200 + 0, /* CA_SUNW_NULL */
203 201 FLG_OF1_OVHWCAP1, /* CA_SUNW_HW_1 */
204 202 FLG_OF1_OVSFCAP1, /* CA_SUNW_SF_1 */
205 203 FLG_OF1_OVHWCAP2, /* CA_SUNW_HW_2 */
206 204 FLG_OF1_OVPLATCAP, /* CA_SUNW_PLAT */
207 205 FLG_OF1_OVMACHCAP, /* CA_SUNW_MACH */
208 206 FLG_OF1_OVIDCAP /* CA_SUNW_ID */
209 207 };
210 208 #if CA_SUNW_NUM != (CA_SUNW_ID + 1)
211 209 #error "CA_SUNW_NUM has grown"
212 210 #endif
213 211 mf->mf_ofl->ofl_flags1 |= override_flag[type];
214 212 }
215 213
216 214 /*
217 215 * Sanity check the given capability bitmask.
218 216 */
219 217 Boolean
220 218 ld_map_cap_sanitize(Mapfile *mf, Word type, Capmask *capmask)
221 219 {
222 220 elfcap_mask_t mask;
223 221
224 222 switch (type) {
225 223 case CA_SUNW_SF_1:
226 224 /*
227 225 * Unlike hardware capabilities, we do not allow setting
228 226 * software capability bits that do not have known definitions.
229 227 * Software capability tokens have to be validated as a unit
230 228 * as the bits can affect each others meaning (see sf1_cap()
231 229 * in files.c).
232 230 */
233 231 if ((mask = (capmask->cm_val & ~SF1_SUNW_MASK)) != 0) {
234 232 mf_warn(mf, MSG_INTL(MSG_MAP_BADSF1),
235 233 EC_XWORD(mask));
236 234 capmask->cm_val &= SF1_SUNW_MASK;
237 235 }
238 236 if ((capmask->cm_val &
239 237 (SF1_SUNW_FPKNWN | SF1_SUNW_FPUSED)) == SF1_SUNW_FPUSED) {
240 238 mf_warn(mf, MSG_INTL(MSG_MAP_BADSF1),
241 239 EC_XWORD(SF1_SUNW_FPUSED));
242 240 capmask->cm_val &= ~SF1_SUNW_FPUSED;
243 241 }
244 242 #if !defined(_ELF64)
245 243 /*
246 244 * The SF1_SUNW_ADDR32 software capability is only meaningful
247 245 * when building a 64-bit object. Warn the user, and remove the
248 246 * setting, if we're building a 32-bit object.
249 247 */
250 248 if (capmask->cm_val & SF1_SUNW_ADDR32) {
251 249 mf_warn0(mf, MSG_INTL(MSG_MAP_INADDR32SF1));
252 250 capmask->cm_val &= ~SF1_SUNW_ADDR32;
253 251 }
254 252 #endif
255 253 }
256 254
257 255 return (TRUE);
258 256 }
259 257
260 258 /*
261 259 * Return the shared object control definition structure (ofl_socntl)
262 260 * for the specified object, creating one if necessary.
263 261 *
264 262 * entry:
265 263 * mf - Mapfile descriptor
266 264 * obj_name - Name of object
267 265 *
268 266 * exit:
269 267 * Returns the pointer to the definition structure, or NULL on error.
270 268 */
271 269 Sdf_desc *
272 270 ld_map_dv(Mapfile *mf, const char *obj_name)
273 271 {
274 272 Sdf_desc *sdf;
275 273
276 274 /*
277 275 * If a shared object definition for this file already exists use it,
278 276 * otherwise allocate a new descriptor.
279 277 */
280 278 if ((sdf = sdf_find(obj_name, mf->mf_ofl->ofl_socntl)) == NULL) {
281 279 if ((sdf = sdf_add(obj_name, &mf->mf_ofl->ofl_socntl)) ==
282 280 (Sdf_desc *)S_ERROR)
283 281 return (NULL);
284 282 sdf->sdf_rfile = mf->mf_name;
285 283 }
286 284
287 285 DBG_CALL(Dbg_map_dv(mf->mf_ofl->ofl_lml, sdf->sdf_name,
288 286 mf->mf_lineno));
289 287 return (sdf);
290 288 }
291 289
292 290
293 291 Boolean
294 292 ld_map_dv_entry(Mapfile *mf, Sdf_desc *sdf, Boolean require,
295 293 const char *version)
296 294 {
297 295 Sdv_desc sdv;
298 296
299 297 sdv.sdv_name = version;
300 298 sdv.sdv_ref = mf->mf_name;
301 299 sdv.sdv_flags = 0;
302 300
303 301
304 302 if (require) {
305 303 /*
306 304 * Add a VERNEED entry for the specified version
307 305 * from this object:
308 306 *
309 307 * MapfileVersion Syntax
310 308 * ----------------------------------------
311 309 * 1 obj - $ADDVERS=version;
312 310 * 2 DEPENDENCY obj { REQUIRE=version };
313 311 */
314 312 sdf->sdf_flags |= FLG_SDF_ADDVER;
315 313
316 314 if (alist_append(&sdf->sdf_verneed, &sdv, sizeof (Sdv_desc),
317 315 AL_CNT_SDF_VERSIONS) == NULL)
318 316 return (FALSE);
319 317 } else { /* Allow */
320 318 /*
321 319 * Allow linking to symbols found in this version, or
322 320 * from the versions it inherits from.
323 321 *
324 322 * MapfileVersion Syntax
325 323 * ----------------------------------------
326 324 * 1 obj - version;
327 325 * 2 DEPENDENCY obj { ALLOW=version };
328 326 */
329 327 sdf->sdf_flags |= FLG_SDF_SELECT;
330 328
331 329 if (alist_append(&sdf->sdf_vers, &sdv, sizeof (Sdv_desc),
332 330 AL_CNT_SDF_VERSIONS) == NULL)
333 331 return (FALSE);
334 332 }
335 333
336 334 DBG_CALL(Dbg_map_dv_entry(mf->mf_ofl->ofl_lml, mf->mf_lineno,
337 335 require, version));
338 336
339 337 return (TRUE);
340 338 }
341 339
342 340 /*
343 341 * Given a segment descriptor, return its index.
344 342 *
345 343 * entry:
346 344 * mf - Mapfile descriptor
347 345 * sgp - Segment for which index is desired
348 346 *
349 347 * exit:
350 348 * Index of segment is returned.
351 349 */
352 350 Xword
353 351 ld_map_seg_index(Mapfile *mf, Sg_desc *sgp)
354 352 {
355 353 Aliste idx;
356 354 Sg_desc *sgp2;
357 355 Ofl_desc *ofl = mf->mf_ofl;
358 356
359 357 for (APLIST_TRAVERSE(ofl->ofl_segs, idx, sgp2))
360 358 if (sgp == sgp2)
361 359 break;
362 360
363 361 return (idx);
364 362 }
365 363
366 364 /*
367 365 * Add a section name to the output section sort list for the given
368 366 * segment.
369 367 *
370 368 * entry:
371 369 * mf - Mapfile descriptor
372 370 * sgp - Segment in question
373 371 * sec_name - Name of section to be added.
374 372 *
375 373 * exit:
376 374 * Returns TRUE for success, FALSE for failure.
377 375 */
378 376 Boolean
379 377 ld_map_seg_os_order_add(Mapfile *mf, Sg_desc *sgp, const char *sec_name)
380 378 {
381 379 Aliste idx;
382 380 Sec_order *scop;
383 381
384 382 /*
385 383 * Make sure it's not already on the list
386 384 */
387 385 for (ALIST_TRAVERSE(sgp->sg_os_order, idx, scop))
388 386 if (strcmp(scop->sco_secname, sec_name) == 0) {
389 387 mf_fatal(mf, MSG_INTL(MSG_MAP_DUP_OS_ORD), sec_name);
390 388 return (FALSE);
391 389 }
392 390
393 391
394 392 scop = alist_append(&sgp->sg_os_order, NULL, sizeof (Sec_order),
395 393 AL_CNT_SG_SECORDER);
396 394 if (scop == NULL)
397 395 return (FALSE);
398 396
399 397 scop->sco_secname = sec_name;
400 398
401 399 DBG_CALL(Dbg_map_seg_os_order(mf->mf_ofl->ofl_lml, sgp, sec_name,
402 400 alist_nitems(sgp->sg_os_order), mf->mf_lineno));
403 401
404 402 /*
405 403 * Output section ordering is a relatively expensive operation,
406 404 * and one that is generally not used. In order to avoid needless
407 405 * work, the FLG_OF_OS_ORDER must be set when it will be needed.
408 406 * The section we just added needs this flag to be set. However,
409 407 * it is possible that a subsequent mapfile directive may come
410 408 * along and clear the order list, making it unnecessary.
411 409 *
412 410 * Instead of setting it here, we do a final pass over the segments
413 411 * in ld_map_finalize() and set it there if a segment with sorting
414 412 * requirements is seen.
415 413 */
416 414
417 415 return (TRUE);
418 416 }
419 417
420 418 /*
421 419 * Add a size symbol to a segment
422 420 *
423 421 * entry:
424 422 * mf - Mapfile descriptor
425 423 * sgp - Segment descriptor
426 424 * eq_tol - Type of assignment: TK_EQUAL, or TK_PLUSEQ
427 425 * symname - Name of symbol. Must be in stable static storage
428 426 * that can be retained.
429 427 *
430 428 * exit:
431 429 * On success, the symbol has been added and TRUE is returned.
432 430 * Otherwise an error is reported and FALSE is returned.
433 431 */
434 432 Boolean
435 433 ld_map_seg_size_symbol(Mapfile *mf, Sg_desc *sgp, Token eq_tok,
436 434 const char *symname)
437 435 {
438 436 Sym *sym; /* New symbol pointer */
439 437 Sym_desc *sdp; /* New symbol node pointer */
440 438 Ifl_desc *ifl; /* Dummy input file structure */
441 439 avl_index_t where;
442 440 Ofl_desc *ofl = mf->mf_ofl;
443 441
444 442 /*
445 443 * We don't allow resetting the list of size symbols, so if the
446 444 * operator is TK_EQUAL and the list is not empty, issue an error.
447 445 *
448 446 * If we want to lift this restriction, we would have to save the
449 447 * size symbols and enter them from ld_map_post_process(). Doing that
450 448 * well would require a significant overhead in saved error reporting
451 449 * state, and interactions with the same symbols created by symbol
452 450 * directives. As size symbols are of little practical use, and are
453 451 * maintained primarily for backward compatibility with SysV, we have
454 452 * decided not to do that, but to create the symbols as the mapfiles
455 453 * are processed, and to disallow later attempts to remove them.
456 454 */
457 455 if ((eq_tok == TK_EQUAL) && (aplist_nitems(sgp->sg_sizesym) > 0)) {
458 456 mf_fatal(mf, MSG_INTL(MSG_MAP_SEGSIZE), sgp->sg_name);
459 457 return (FALSE);
460 458 }
461 459
462 460 /*
463 461 * Make sure we have a pseudo file descriptor to associate to the
464 462 * symbol.
465 463 */
466 464 if ((ifl = ld_map_ifl(mf)) == NULL)
467 465 return (FALSE);
468 466
469 467 /*
470 468 * Make sure the symbol doesn't already exist. It is possible that the
471 469 * symbol has been scoped or versioned, in which case it does exist
472 470 * but we can freely update it here.
473 471 */
474 472 if ((sdp = ld_sym_find(symname, SYM_NOHASH, &where, ofl)) == NULL) {
475 473 Word hval;
476 474
477 475 if ((sym = libld_calloc(sizeof (Sym), 1)) == NULL)
478 476 return (FALSE);
479 477 sym->st_shndx = SHN_ABS;
480 478 sym->st_size = 0;
481 479 sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
482 480
483 481 DBG_CALL(Dbg_map_size_new(ofl->ofl_lml, symname,
484 482 sgp->sg_name, mf->mf_lineno));
485 483 /* LINTED */
486 484 hval = (Word)elf_hash(symname);
487 485 if ((sdp = ld_sym_enter(symname, sym, hval, ifl, ofl, 0,
488 486 SHN_ABS, (FLG_SY_SPECSEC | FLG_SY_GLOBREF), &where)) ==
489 487 (Sym_desc *)S_ERROR)
490 488 return (FALSE);
491 489 sdp->sd_flags &= ~FLG_SY_CLEAN;
492 490 DBG_CALL(Dbg_map_symbol(ofl, sdp));
493 491 } else {
494 492 sym = sdp->sd_sym;
495 493
496 494 if (sym->st_shndx == SHN_UNDEF) {
497 495 sdp->sd_shndx = sym->st_shndx = SHN_ABS;
498 496 sdp->sd_flags |= FLG_SY_SPECSEC;
499 497 sym->st_size = 0;
500 498 sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
501 499
502 500 sdp->sd_flags &= ~FLG_SY_MAPREF;
503 501
504 502 DBG_CALL(Dbg_map_size_old(ofl, sdp,
505 503 sgp->sg_name, mf->mf_lineno));
506 504 } else {
507 505 mf_fatal(mf, MSG_INTL(MSG_MAP_SYMDEF1),
508 506 demangle(sdp->sd_name), sdp->sd_file->ifl_name,
509 507 MSG_INTL(MSG_MAP_DIFF_SYMMUL));
510 508 return (FALSE);
511 509 }
512 510 }
513 511
514 512 /*
515 513 * Assign the symbol to the segment.
516 514 */
517 515 if (aplist_append(&sgp->sg_sizesym, sdp, AL_CNT_SG_SIZESYM) == NULL)
518 516 return (FALSE);
519 517
520 518 return (TRUE);
521 519 }
522 520
523 521 /*
524 522 * Allocate a zeroed segment descriptor.
525 523 *
526 524 * exit:
527 525 * Returns pointer to the descriptor on success, NULL on failure.
528 526 * The contents of the returned descriptor have been zeroed.
529 527 * The returned descriptor is not added to the segment list
530 528 * (ofl_segs). That is done using ld_map_seg_insert().
531 529 */
532 530 Sg_desc *
533 531 ld_map_seg_alloc(const char *name, Word p_type, sg_flags_t sg_flags)
534 532 {
535 533 Sg_desc *sgp;
536 534
537 535 if ((sgp = libld_calloc(sizeof (Sg_desc), 1)) == NULL)
538 536 return (NULL);
539 537 sgp->sg_phdr.p_type = p_type;
540 538 sgp->sg_name = name;
541 539 sgp->sg_flags = sg_flags;
542 540
543 541 return (sgp);
544 542 }
545 543
546 544 /*
547 545 * Return the PT_SUNWSTACK segment descriptor from the ofl_segs list.
548 546 * This segment is part of the default set and cannot be removed, so
549 547 * this routine will always succeed.
550 548 *
551 549 * exit:
552 550 * The descriptor is located, a DBG_STATE_MOD_BEFORE debug
553 551 * message issued, the FLG_SG_DISABLED flag is cleared, and the
554 552 * descriptor pointer returned.
555 553 */
556 554 Sg_desc *
557 555 ld_map_seg_stack(Mapfile *mf)
558 556 {
559 557 Ofl_desc *ofl = mf->mf_ofl;
560 558 Sg_desc *sgp;
561 559 Aliste idx;
562 560
563 561 /*
564 562 * The stack is established by exec(), using the executable's program
565 563 * headers, before any sharable objects are loaded. If there is a
566 564 * PT_SUNWSTACK program header, exec() will act on it. As such, stack
567 565 * program headers are normally only applicable to executables.
568 566 *
569 567 * However, ELF allows a sharable object with an interpreter to
570 568 * be executed directly, and in this extremely rare case, the
571 569 * PT_SUNWSTACK program header would have meaning. Rather than
572 570 * second guess user intent, we simply create it on demand for any
573 571 * dynamic object, trusting that the user has a good reason for it.
574 572 */
575 573 for (APLIST_TRAVERSE(ofl->ofl_segs, idx, sgp))
576 574 if (sgp->sg_phdr.p_type == PT_SUNWSTACK) {
577 575 DBG_CALL(Dbg_map_seg(mf->mf_ofl, DBG_STATE_MOD_BEFORE,
578 576 idx, sgp, mf->mf_lineno));
579 577 sgp->sg_flags &= ~FLG_SG_DISABLED;
580 578 return (sgp);
581 579 }
582 580
583 581 /*NOTREACHED*/
584 582 return (NULL);
585 583 }
586 584
587 585 /*
588 586 * Finish the initialization of a new segment descriptor allocated by
589 587 * ld_map_seg_alloc(), and enter it into the segment list.
590 588 *
591 589 * entry:
592 590 * mf - Mapfile descriptor
593 591 * seg_type - One of DBG_SEG_NEW or DBG_SEG_NEW_IMPLICIT
594 592 * ins_head - If TRUE, the new segment goes at the front of
595 593 * others of its type. If FALSE, it goes at the end.
596 594 * sgp - Segment descriptor to enter.
597 595 * where - Insertion point, initialized by a previous (failed) call to
598 596 * ld_seg_lookup(). Ignored if the segment has a NULL sg_name.
599 597 *
600 598 * exit:
601 599 * On success, returns SEG_INS_OK. A non-fatal error is indicated with
602 600 * a return value of SEG_INS_SKIP, in which case the descriptor is
603 601 * not entered, but the user is expected to discard it and continue
604 602 * running. On failure, returns SEG_INS_FAIL.
605 603 *
606 604 * note:
607 605 * This routine will modify the contents of the descriptor referenced
608 606 * by sgp_tmpl before allocating the new descriptor. The caller must
609 607 * not expect it to be unmodified.
610 608 */
611 609 ld_map_seg_ins_t
612 610 ld_map_seg_insert(Mapfile *mf, dbg_state_t dbg_state, Sg_desc *sgp,
613 611 avl_index_t where)
614 612 {
615 613 Ofl_desc *ofl = mf->mf_ofl;
616 614 Aliste idx;
617 615 Sg_desc *sgp2; /* temp segment descriptor pointer */
618 616 int ins_head;
619 617 Xword sg_ndx;
620 618
621 619 /*
622 620 * If specific fields have not been supplied via
623 621 * map_equal(), make sure defaults are supplied.
624 622 */
625 623 if (((sgp->sg_flags & FLG_SG_P_TYPE) == 0) &&
626 624 (sgp->sg_phdr.p_type == PT_NULL)) {
627 625 /*
628 626 * Default to a loadable segment.
629 627 */
630 628 sgp->sg_phdr.p_type = PT_LOAD;
631 629 sgp->sg_flags |= FLG_SG_P_TYPE;
632 630 }
633 631 if (sgp->sg_phdr.p_type == PT_LOAD) {
634 632 if ((sgp->sg_flags & FLG_SG_P_FLAGS) == 0) {
635 633 /*
636 634 * Default to read/write and execute.
637 635 */
638 636 sgp->sg_phdr.p_flags = PF_R + PF_W + PF_X;
639 637 sgp->sg_flags |= FLG_SG_P_FLAGS;
640 638 }
641 639 if ((sgp->sg_flags & FLG_SG_P_ALIGN) == 0) {
642 640 /*
643 641 * Default to segment alignment
644 642 */
645 643 sgp->sg_phdr.p_align = ld_targ.t_m.m_segm_align;
646 644 sgp->sg_flags |= FLG_SG_P_ALIGN;
647 645 }
648 646 }
649 647
650 648 /*
651 649 * Determine where the new item should be inserted in
652 650 * the segment descriptor list.
653 651 */
654 652 switch (sgp->sg_phdr.p_type) {
655 653 case PT_LOAD:
656 654 if (sgp->sg_flags & FLG_SG_EMPTY)
657 655 sgp->sg_id = SGID_TEXT_EMPTY;
658 656 else
659 657 sgp->sg_id = SGID_TEXT;
660 658 break;
661 659 case PT_NULL:
662 660 if (sgp->sg_flags & FLG_SG_EMPTY)
663 661 sgp->sg_id = SGID_NULL_EMPTY;
664 662 else
665 663 sgp->sg_id = SGID_NULL;
666 664 break;
667 665 case PT_NOTE:
668 666 sgp->sg_id = SGID_NOTE;
669 667 break;
670 668 default:
671 669 mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSEGTYP),
672 670 EC_WORD(sgp->sg_phdr.p_type));
673 671 return (SEG_INS_FAIL);
674 672 }
675 673
676 674 /*
677 675 * Add the descriptor to the segment list. In the v1 syntax,
678 676 * new sections are added at the head of their type, while in
679 677 * the newer syntax, they go at the end of their type.
680 678 */
681 679 sg_ndx = 0;
682 680 ins_head = (mf->mf_version == MFV_SYSV);
683 681 for (APLIST_TRAVERSE(ofl->ofl_segs, idx, sgp2)) {
684 682 if (ins_head) { /* Insert before the others of its type */
685 683 if (sgp->sg_id > sgp2->sg_id) {
686 684 sg_ndx++;
687 685 continue;
688 686 }
689 687 } else { /* Insert after the others of its type */
690 688 if (sgp->sg_id >= sgp2->sg_id) {
691 689 sg_ndx++;
692 690 continue;
693 691 }
694 692 }
695 693 break;
696 694 }
697 695 if (aplist_insert(&ofl->ofl_segs, sgp, AL_CNT_SEGMENTS, idx) == NULL)
698 696 return (SEG_INS_FAIL);
699 697 if (sgp->sg_name != NULL)
700 698 avl_insert(&ofl->ofl_segs_avl, sgp, where);
701 699
702 700 DBG_CALL(Dbg_map_seg(ofl, dbg_state, sg_ndx, sgp, mf->mf_lineno));
703 701 return (SEG_INS_OK);
704 702 }
705 703
706 704 /*
707 705 * Add an entrance criteria record for the specified segment
708 706 *
709 707 * entry:
710 708 * mf - Mapfile descriptor
711 709 * sgp - Segment for which a new entrance criteria record is needed
712 710 * name - NULL, or name by which the entrance criteria can be referenced.
713 711 *
714 712 * exit:
715 713 * On success, a pointer to the new entrace criteria record is
716 714 * returned, the contents of which have been zeroed. On failure,
717 715 * NULL is returned.
718 716 */
719 717 Ent_desc *
720 718 ld_map_seg_ent_add(Mapfile *mf, Sg_desc *sgp, const char *name)
721 719 {
722 720 Ent_desc *enp;
723 721 avl_index_t where;
724 722 Ofl_desc *ofl = mf->mf_ofl;
725 723
726 724 if ((name != NULL) &&
727 725 (ld_ent_lookup(mf->mf_ofl, name, &where) != NULL)) {
728 726 mf_fatal(mf, MSG_INTL(MSG_MAP_DUPNAMENT), name);
729 727 return (NULL);
730 728 }
731 729
732 730 /* Allocate and initialize the entrace criteria descriptor */
733 731 if ((enp = libld_calloc(1, sizeof (*enp))) == NULL)
734 732 return (NULL);
735 733 enp->ec_name = name;
736 734 enp->ec_segment = sgp; /* Tie criteria to segment */
737 735
738 736
739 737 /*
740 738 * Insert into the APlist. The mf_ec_insndx field for each mapfile
741 739 * starts at 0, and is incremented with each insertion. This means
742 740 * that the entrance criteria for each mapfile go to the head of
743 741 * the list, but that within a single mapfile, they are inserted in
744 742 * the order they are seen.
745 743 */
746 744 if (aplist_insert(&ofl->ofl_ents, enp, AL_CNT_OFL_ENTRANCE,
747 745 mf->mf_ec_insndx) == NULL)
748 746 return (NULL);
749 747 mf->mf_ec_insndx++;
750 748
751 749 /*
752 750 * If the entrance criteria is named insert it into the AVL tree
753 751 * as well. This provides O(logN) lookups by name.
754 752 */
755 753 if (name != NULL)
756 754 avl_insert(&ofl->ofl_ents_avl, enp, where);
757 755
758 756 return (enp);
759 757 }
760 758
761 759 Boolean
762 760 ld_map_seg_ent_files(Mapfile *mf, Ent_desc *enp, Word ecf_type, const char *str)
763 761 {
764 762 Ent_desc_file edf;
765 763
766 764 /*
767 765 * The v1 sysv syntax can let an empty string get in, consisting of
768 766 * just a '*' where the '*' is interpreted as 'basename'.
769 767 */
770 768 if (str[0] == '\0') {
771 769 mf_fatal0(mf, MSG_INTL(MSG_MAP_MALFORM));
772 770 return (FALSE);
773 771 }
774 772
775 773 /* Basename or objname string must not contain a path separator (/) */
776 774 if ((ecf_type != TYP_ECF_PATH) && (strchr(str, '/') != NULL)) {
777 775 const char *msg = (ecf_type == TYP_ECF_BASENAME) ?
778 776 MSG_INTL(MSG_MAP_BADBNAME) : MSG_INTL(MSG_MAP_BADONAME);
779 777
780 778 mf_fatal(mf, msg, str);
781 779 return (FALSE);
782 780 }
783 781
784 782 edf.edf_flags = ecf_type;
785 783 edf.edf_name = str;
786 784 edf.edf_name_len = strlen(edf.edf_name);
787 785
788 786 /* Does it have an archive member suffix? */
789 787 if ((edf.edf_name[edf.edf_name_len - 1] == ')') &&
790 788 (strrchr(edf.edf_name, '(') != NULL))
791 789 edf.edf_flags |= FLG_ECF_ARMEMBER;
792 790
793 791 if (alist_append(&enp->ec_files, &edf, sizeof (edf),
794 792 AL_CNT_EC_FILES) == NULL)
795 793 return (FALSE);
796 794
797 795 /*
798 796 * Note that an entrance criteria requiring file name matching exists
799 797 * in the system. This is used by ld_place_path_info_init() to
800 798 * skip Place_pathinfo initialization in cases where there are
801 799 * no entrance criteria that will use the results.
802 800 */
803 801 mf->mf_ofl->ofl_flags |= FLG_OF_EC_FILES;
804 802
805 803 return (TRUE);
806 804 }
807 805
808 806 /*
809 807 * Prepare an ld_map_ver_t structure for a new mapfile defined version.
810 808 *
811 809 * exit:
812 810 * Returns TRUE for success, FALSE for failure.
813 811 */
814 812 Boolean
815 813 ld_map_sym_ver_init(Mapfile *mf, char *name, ld_map_ver_t *mv)
816 814 {
817 815 Word hash;
818 816 Ofl_desc *ofl = mf->mf_ofl;
819 817
820 818 mv->mv_name = name;
821 819 mv->mv_scope = FLG_SCOPE_DFLT;
822 820 mv->mv_errcnt = 0;
823 821
824 822 /*
825 823 * If we're generating segments within the image then any symbol
826 824 * reductions will be processed (ie. applied to relocations and symbol
827 825 * table entries). Otherwise (when creating a relocatable object) any
828 826 * versioning information is simply recorded for use in a later
829 827 * (segment generating) link-edit.
830 828 */
831 829 if (ofl->ofl_flags & FLG_OF_RELOBJ)
832 830 ofl->ofl_flags |= FLG_OF_VERDEF;
833 831
834 832 /*
835 833 * If no version descriptors have yet been set up, initialize a base
836 834 * version to represent the output file itself. This `base' version
837 835 * catches any internally generated symbols (_end, _etext, etc.) and
838 836 * serves to initialize the output version descriptor count.
839 837 */
840 838 if (ofl->ofl_vercnt == 0) {
841 839 if (ld_vers_base(ofl) == (Ver_desc *)S_ERROR)
842 840 return (FALSE);
843 841 }
844 842
845 843 /*
846 844 * If this definition has an associated version name then generate a
847 845 * new version descriptor and an associated version symbol index table.
848 846 */
849 847 if (name) {
850 848 ofl->ofl_flags |= FLG_OF_VERDEF;
851 849
852 850 /*
853 851 * Traverse the present version descriptor list to see if there
854 852 * is already one of the same name, otherwise create a new one.
855 853 */
856 854 /* LINTED */
857 855 hash = (Word)elf_hash(name);
858 856 if (((mv->mv_vdp = ld_vers_find(name, hash,
859 857 ofl->ofl_verdesc)) == NULL) &&
860 858 ((mv->mv_vdp = ld_vers_desc(name, hash,
861 859 &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR))
862 860 return (FALSE);
863 861
864 862 /*
865 863 * Initialize any new version with an index, the file from
866 864 * which it was first referenced, and a WEAK flag (indicates
867 865 * that there are no symbols assigned to it yet).
868 866 */
869 867 if (mv->mv_vdp->vd_ndx == 0) {
870 868 /* LINTED */
871 869 mv->mv_vdp->vd_ndx = (Half)++ofl->ofl_vercnt;
872 870 mv->mv_vdp->vd_file = ld_map_ifl(mf);
873 871 mv->mv_vdp->vd_flags = VER_FLG_WEAK;
874 872 }
875 873 } else {
876 874 /*
877 875 * If a version definition hasn't been specified assign any
878 876 * symbols to the base version.
879 877 */
880 878 mv->mv_vdp = (Ver_desc *)ofl->ofl_verdesc->apl_data[0];
881 879 }
882 880
883 881 return (TRUE);
884 882 }
885 883
886 884 /*
887 885 * Change the current scope for the given version.
888 886 *
889 887 * entry:
890 888 * mf - Mapfile descriptor
891 889 * scope_name - Name for new scope
892 890 * mv - Information related to version being defined
893 891 *
894 892 * exit:
895 893 * On success, mv is updated to change the current scope.
896 894 * On failure, mv->errcnt is incremented, and mv is otherwise unaltered.
897 895 */
898 896 void
899 897 ld_map_sym_scope(Mapfile *mf, const char *scope_name, ld_map_ver_t *mv)
900 898 {
901 899 typedef struct {
902 900 const char *name; /* scope keyword string */
903 901 ld_map_scope_t type; /* Resulting type */
904 902 ofl_flag_t ofl_flags; /* 0, or ofl flags to add */
905 903 } scope_t;
906 904
907 905 /*
908 906 * Valid symbol scope keywords
909 907 *
910 908 * All symbols added by a mapfile are actually global entries, and
911 909 * are assigned the scope that is presently in effect.
912 910 *
913 911 * If a protected/symbolic scope is detected, remember this. If
914 912 * a protected/symbolic scope is the only scope defined in this
915 913 * (or any other mapfiles), then the mode -Bsymbolic is established.
916 914 */
917 915 static scope_t scope_list[] = {
918 916 { MSG_ORIG(MSG_MAPKW_DEFAULT), FLG_SCOPE_DFLT, FLG_OF_MAPGLOB },
919 917 { MSG_ORIG(MSG_MAPKW_ELIMINATE), FLG_SCOPE_ELIM, 0 },
920 918 { MSG_ORIG(MSG_MAPKW_EXPORTED), FLG_SCOPE_EXPT, 0 },
921 919 { MSG_ORIG(MSG_MAPKW_HIDDEN), FLG_SCOPE_HIDD, 0 },
922 920 { MSG_ORIG(MSG_MAPKW_GLOBAL), FLG_SCOPE_DFLT, FLG_OF_MAPGLOB },
923 921 { MSG_ORIG(MSG_MAPKW_LOCAL), FLG_SCOPE_HIDD, 0 },
924 922 { MSG_ORIG(MSG_MAPKW_PROTECTED),
925 923 FLG_SCOPE_PROT, FLG_OF_MAPSYMB },
926 924 { MSG_ORIG(MSG_MAPKW_SINGLETON),
927 925 FLG_SCOPE_SNGL, FLG_OF_MAPGLOB },
928 926 { MSG_ORIG(MSG_MAPKW_SYMBOLIC),
929 927 FLG_SCOPE_PROT, FLG_OF_MAPSYMB },
930 928
931 929 /* List must be null terminated */
932 930 { 0 }
933 931 };
934 932
935 933 /*
936 934 * Size of buffer needed to format the names in scope_list[]. Must
937 935 * be kept in sync with scope_list.
938 936 */
939 937 static size_t scope_list_bufsize =
940 938 KW_NAME_SIZE(MSG_MAPKW_DEFAULT) +
941 939 KW_NAME_SIZE(MSG_MAPKW_ELIMINATE) +
942 940 KW_NAME_SIZE(MSG_MAPKW_EXPORTED) +
943 941 KW_NAME_SIZE(MSG_MAPKW_HIDDEN) +
944 942 KW_NAME_SIZE(MSG_MAPKW_GLOBAL) +
945 943 KW_NAME_SIZE(MSG_MAPKW_LOCAL) +
946 944 KW_NAME_SIZE(MSG_MAPKW_PROTECTED) +
947 945 KW_NAME_SIZE(MSG_MAPKW_SINGLETON) +
948 946 KW_NAME_SIZE(MSG_MAPKW_SYMBOLIC);
949 947
950 948 scope_t *scope;
951 949
952 950 scope = ld_map_kwfind(scope_name, scope_list,
953 951 SGSOFFSETOF(scope_t, name), sizeof (scope_list[0]));
954 952 if (scope == NULL) {
955 953 char buf[VLA_SIZE(scope_list_bufsize)];
956 954
957 955 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMSCOPE),
958 956 ld_map_kwnames(scope_list, SGSOFFSETOF(scope_t, name),
959 957 sizeof (scope[0]), buf, scope_list_bufsize), scope_name);
960 958 mv->mv_errcnt++;
961 959 return;
962 960 }
963 961
964 962 mv->mv_scope = scope->type;
965 963 mf->mf_ofl->ofl_flags |= scope->ofl_flags;
966 964 }
967 965
968 966 /*
969 967 * Process the special auto-reduction directive ('*'). It can be specified
970 968 * in hidden/local, and eliminate scope. This directive indicates that all
971 969 * symbols processed that are not explicitly defined to be global are to be
972 970 * reduced to hidden/local scope in, or eliminated from, the output image.
973 971 *
974 972 * An auto-reduction directive also implies that a version definition must
975 973 * be created, as the user has effectively defined an interface.
976 974 */
977 975 void
978 976 ld_map_sym_autoreduce(Mapfile *mf, ld_map_ver_t *mv)
979 977 {
980 978 switch (mv->mv_scope) {
981 979 case FLG_SCOPE_HIDD:
982 980 mf->mf_ofl->ofl_flags |= (FLG_OF_VERDEF | FLG_OF_AUTOLCL);
983 981 break;
984 982 case FLG_SCOPE_ELIM:
985 983 mf->mf_ofl->ofl_flags |= (FLG_OF_VERDEF | FLG_OF_AUTOELM);
986 984 break;
987 985 default:
988 986 /*
989 987 * Auto reduction has been applied to a scope that doesn't
990 988 * support it. This should be a fatal error, but we limit
991 989 * it to a warning for version 1 mapfiles. For years, we
992 990 * quietly ignored this case, so there may be mapfiles in
993 991 * production use that we do not wish to break.
994 992 */
995 993 if (mf->mf_version == 1) {
996 994 mf_warn0(mf, MSG_INTL(MSG_MAP_BADAUTORED));
997 995 } else {
998 996 mf_fatal0(mf, MSG_INTL(MSG_MAP_BADAUTORED));
999 997 mv->mv_errcnt++;
1000 998 }
1001 999 }
1002 1000 }
1003 1001
1004 1002 /*
1005 1003 * Add a standard or auxiliary filter to the given symbol
1006 1004 *
1007 1005 * entry:
1008 1006 * mf - Mapfile descriptor
1009 1007 * mv - Information related to version being defined
1010 1008 * ms - Information related to symbol being defined
1011 1009 * dft_flag - One of FLG_SY_STDFLTR or FLG_SY_AUXFLTR,
1012 1010 * specifying the type of filter.
1013 1011 * filtee - String giving filtee to be added
1014 1012 *
1015 1013 * exit:
1016 1014 * On success, the filtee is added. On failure, mv->errcnt is
1017 1015 * incremented, and mv/ms are otherwise unaltered.
1018 1016 */
1019 1017 void
1020 1018 ld_map_sym_filtee(Mapfile *mf, ld_map_ver_t *mv, ld_map_sym_t *ms,
1021 1019 Word dft_flag, const char *filtee)
1022 1020 {
1023 1021 /*
1024 1022 * A given symbol can only be tied to a single filter, be it
1025 1023 * a standard filter, or auxiliary.
1026 1024 */
1027 1025 if (ms->ms_filtee) {
1028 1026 mf_fatal0(mf, MSG_INTL(MSG_MAP_MULTFILTEE));
1029 1027 mv->mv_errcnt++;
1030 1028 return;
1031 1029 }
1032 1030
1033 1031 /* Symbol filtering is only for sharable objects */
1034 1032 if (!(mf->mf_ofl->ofl_flags & FLG_OF_SHAROBJ)) {
1035 1033 mf_fatal0(mf, MSG_INTL(MSG_MAP_FLTR_ONLYAVL));
1036 1034 mv->mv_errcnt++;
1037 1035 return;
1038 1036 }
1039 1037
1040 1038 ms->ms_filtee = filtee;
1041 1039 ms->ms_dft_flag = dft_flag;
1042 1040 ms->ms_sdflags |= dft_flag;
1043 1041 mf->mf_ofl->ofl_flags |= FLG_OF_SYMINFO;
1044 1042 }
1045 1043
1046 1044 /*
1047 1045 * Enter a mapfile defined symbol into the given version
1048 1046 *
1049 1047 * entry:
1050 1048 * mf - Mapfile descriptor
1051 1049 * ms - Information related to symbol being added to version
1052 1050 *
1053 1051 * exit:
1054 1052 * On success, returns TRUE. On failure that requires an immediate
1055 1053 * halt, returns FALSE.
1056 1054 *
1057 1055 * On failure that requires eventual halt, but for which it would
1058 1056 * be OK to continue parsing in hopes of flushing out additional
1059 1057 * problems, increments mv->mv_errcnt, and returns TRUE.
1060 1058 */
1061 1059 Boolean
1062 1060 ld_map_sym_enter(Mapfile *mf, ld_map_ver_t *mv, ld_map_sym_t *ms)
1063 1061 {
1064 1062 Ofl_desc *ofl = mf->mf_ofl;
1065 1063 Word hash;
1066 1064 avl_index_t where;
1067 1065 Sym *sym;
1068 1066 Sym_desc *sdp;
1069 1067 const char *conflict;
1070 1068
1071 1069 /*
1072 1070 * Add the new symbol. It should be noted that all
1073 1071 * symbols added by the mapfile start out with global
1074 1072 * scope, thus they will fall through the normal symbol
1075 1073 * resolution process. Symbols defined as locals will
1076 1074 * be reduced in scope after all input file processing.
1077 1075 */
1078 1076 /* LINTED */
1079 1077 hash = (Word)elf_hash(ms->ms_name);
1080 1078 DBG_CALL(Dbg_map_version(ofl->ofl_lml, mv->mv_name, ms->ms_name,
1081 1079 mv->mv_scope));
1082 1080
1083 1081 /*
1084 1082 * Make sure that any parent or external declarations fall back to
1085 1083 * references.
1086 1084 */
1087 1085 if (ms->ms_sdflags & (FLG_SY_PARENT | FLG_SY_EXTERN)) {
1088 1086 /*
1089 1087 * Turn it into a reference by setting the section index
1090 1088 * to UNDEF.
1091 1089 */
1092 1090 ms->ms_shndx = SHN_UNDEF;
1093 1091
1094 1092 /*
1095 1093 * It is wrong to specify size or value for an external symbol.
1096 1094 */
1097 1095 if (ms->ms_value_set || (ms->ms_size != 0)) {
1098 1096 mf_fatal0(mf, MSG_INTL(MSG_MAP_NOEXVLSZ));
1099 1097 mv->mv_errcnt++;
1100 1098 return (TRUE);
1101 1099 }
1102 1100 }
1103 1101
1104 1102 if ((sdp = ld_sym_find(ms->ms_name, hash, &where, ofl)) == NULL) {
1105 1103 if ((sym = libld_calloc(sizeof (Sym), 1)) == NULL)
1106 1104 return (FALSE);
1107 1105
1108 1106 sym->st_shndx = (Half)ms->ms_shndx;
1109 1107 sym->st_value = ms->ms_value;
1110 1108 sym->st_size = ms->ms_size;
1111 1109 sym->st_info = ELF_ST_INFO(STB_GLOBAL, ms->ms_type);
1112 1110
1113 1111 if ((sdp = ld_sym_enter(ms->ms_name, sym, hash,
1114 1112 ld_map_ifl(mf), ofl, 0, ms->ms_shndx, ms->ms_sdflags,
1115 1113 &where)) == (Sym_desc *)S_ERROR)
1116 1114 return (FALSE);
1117 1115
1118 1116 sdp->sd_flags &= ~FLG_SY_CLEAN;
1119 1117
1120 1118 /*
1121 1119 * Identify any references. FLG_SY_MAPREF is
1122 1120 * turned off once a relocatable object with
1123 1121 * the same symbol is found, thus the existence
1124 1122 * of FLG_SY_MAPREF at symbol validation is
1125 1123 * used to flag undefined/misspelled entries.
1126 1124 */
1127 1125 if (sym->st_shndx == SHN_UNDEF)
1128 1126 sdp->sd_flags |= (FLG_SY_MAPREF | FLG_SY_GLOBREF);
1129 1127
1130 1128 } else {
1131 1129 conflict = NULL;
1132 1130 sym = sdp->sd_sym;
1133 1131
1134 1132 /*
1135 1133 * If this symbol already exists, make sure this
1136 1134 * definition doesn't conflict with the former.
1137 1135 * Provided it doesn't, multiple definitions
1138 1136 * from different mapfiles can augment each
1139 1137 * other.
1140 1138 */
1141 1139 if (sym->st_value) {
1142 1140 if (ms->ms_value && (sym->st_value != ms->ms_value))
1143 1141 conflict = MSG_INTL(MSG_MAP_DIFF_SYMVAL);
1144 1142 } else {
1145 1143 sym->st_value = ms->ms_value;
1146 1144 }
1147 1145 if (sym->st_size) {
1148 1146 if (ms->ms_size && (sym->st_size != ms->ms_size))
1149 1147 conflict = MSG_INTL(MSG_MAP_DIFF_SYMSZ);
1150 1148 } else {
1151 1149 sym->st_size = ms->ms_size;
1152 1150 }
1153 1151 if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) {
1154 1152 if ((ms->ms_type != STT_NOTYPE) &&
1155 1153 (ELF_ST_TYPE(sym->st_info) != ms->ms_type))
1156 1154 conflict = MSG_INTL(MSG_MAP_DIFF_SYMTYP);
1157 1155 } else {
1158 1156 sym->st_info = ELF_ST_INFO(STB_GLOBAL, ms->ms_type);
1159 1157 }
1160 1158 if (sym->st_shndx != SHN_UNDEF) {
1161 1159 if ((ms->ms_shndx != SHN_UNDEF) &&
1162 1160 (sym->st_shndx != ms->ms_shndx))
1163 1161 conflict = MSG_INTL(MSG_MAP_DIFF_SYMNDX);
1164 1162 } else {
1165 1163 sym->st_shndx = sdp->sd_shndx = ms->ms_shndx;
1166 1164 }
1167 1165
1168 1166 if ((sdp->sd_flags & MSK_SY_GLOBAL) &&
1169 1167 (sdp->sd_aux->sa_overndx != VER_NDX_GLOBAL) &&
1170 1168 (mv->mv_vdp->vd_ndx != VER_NDX_GLOBAL) &&
1171 1169 (sdp->sd_aux->sa_overndx != mv->mv_vdp->vd_ndx)) {
1172 1170 conflict = MSG_INTL(MSG_MAP_DIFF_SYMVER);
1173 1171 }
1174 1172
1175 1173 if (conflict) {
1176 1174 mf_fatal(mf, MSG_INTL(MSG_MAP_SYMDEF1),
1177 1175 demangle(ms->ms_name),
1178 1176 sdp->sd_file->ifl_name, conflict);
1179 1177 mv->mv_errcnt++;
1180 1178 return (TRUE);
1181 1179 }
1182 1180
1183 1181 /*
1184 1182 * If this mapfile entry supplies a definition,
1185 1183 * indicate that the symbol is now used.
1186 1184 */
1187 1185 if (ms->ms_shndx != SHN_UNDEF)
1188 1186 sdp->sd_flags |= FLG_SY_MAPUSED;
1189 1187 }
1190 1188
1191 1189 /*
1192 1190 * A symbol declaration that defines a size but no
1193 1191 * value is processed as a request to create an
1194 1192 * associated backing section. The intent behind this
1195 1193 * functionality is to provide OBJT definitions within
1196 1194 * filters that are not ABS. ABS symbols don't allow
1197 1195 * copy-relocations to be established to filter OBJT
1198 1196 * definitions.
1199 1197 */
1200 1198 if ((ms->ms_shndx == SHN_ABS) && ms->ms_size && !ms->ms_value_set) {
1201 1199 /* Create backing section if not there */
1202 1200 if (sdp->sd_isc == NULL) {
1203 1201 Is_desc *isp;
1204 1202
1205 1203 if (ms->ms_type == STT_OBJECT) {
1206 1204 if ((isp = ld_make_data(ofl, ms->ms_size)) ==
1207 1205 (Is_desc *)S_ERROR)
1208 1206 return (FALSE);
1209 1207 } else {
1210 1208 if ((isp = ld_make_text(ofl, ms->ms_size)) ==
1211 1209 (Is_desc *)S_ERROR)
1212 1210 return (FALSE);
1213 1211 }
1214 1212
1215 1213 sdp->sd_isc = isp;
1216 1214 isp->is_file = ld_map_ifl(mf);
1217 1215 }
1218 1216
1219 1217 /*
1220 1218 * Now that backing storage has been created,
1221 1219 * associate the symbol descriptor. Remove the
1222 1220 * symbols special section tag so that it will
1223 1221 * be assigned the correct section index as part
1224 1222 * of update symbol processing.
1225 1223 */
1226 1224 sdp->sd_flags &= ~FLG_SY_SPECSEC;
1227 1225 ms->ms_sdflags &= ~FLG_SY_SPECSEC;
1228 1226 }
1229 1227
1230 1228 /*
1231 1229 * Indicate the new symbols scope. Although the
1232 1230 * symbols st_other field will eventually be updated as
1233 1231 * part of writing out the final symbol, update the
1234 1232 * st_other field here to trigger better diagnostics
1235 1233 * during symbol validation (for example, undefined
1236 1234 * references that are defined symbolic in a mapfile).
1237 1235 */
1238 1236 if (mv->mv_scope == FLG_SCOPE_HIDD) {
1239 1237 /*
1240 1238 * This symbol needs to be reduced to local.
1241 1239 */
1242 1240 if (ofl->ofl_flags & FLG_OF_REDLSYM) {
1243 1241 sdp->sd_flags |= (FLG_SY_HIDDEN | FLG_SY_ELIM);
1244 1242 sdp->sd_sym->st_other = STV_ELIMINATE;
1245 1243 } else {
1246 1244 sdp->sd_flags |= FLG_SY_HIDDEN;
1247 1245 sdp->sd_sym->st_other = STV_HIDDEN;
1248 1246 }
1249 1247 } else if (mv->mv_scope == FLG_SCOPE_ELIM) {
1250 1248 /*
1251 1249 * This symbol needs to be eliminated. Note,
1252 1250 * the symbol is also tagged as local to trigger
1253 1251 * any necessary relocation processing prior
1254 1252 * to the symbol being eliminated.
1255 1253 */
1256 1254 sdp->sd_flags |= (FLG_SY_HIDDEN | FLG_SY_ELIM);
1257 1255 sdp->sd_sym->st_other = STV_ELIMINATE;
1258 1256
1259 1257 } else {
1260 1258 /*
1261 1259 * This symbol is explicitly defined to remain
1262 1260 * global.
1263 1261 */
1264 1262 sdp->sd_flags |= ms->ms_sdflags;
1265 1263
1266 1264 /*
1267 1265 * Qualify any global scope.
1268 1266 */
1269 1267 if (mv->mv_scope == FLG_SCOPE_SNGL) {
1270 1268 sdp->sd_flags |= (FLG_SY_SINGLE | FLG_SY_NDIR);
1271 1269 sdp->sd_sym->st_other = STV_SINGLETON;
1272 1270 } else if (mv->mv_scope == FLG_SCOPE_PROT) {
1273 1271 sdp->sd_flags |= FLG_SY_PROTECT;
1274 1272 sdp->sd_sym->st_other = STV_PROTECTED;
1275 1273 } else if (mv->mv_scope == FLG_SCOPE_EXPT) {
1276 1274 sdp->sd_flags |= FLG_SY_EXPORT;
1277 1275 sdp->sd_sym->st_other = STV_EXPORTED;
1278 1276 } else
1279 1277 sdp->sd_flags |= FLG_SY_DEFAULT;
1280 1278
1281 1279 /*
1282 1280 * Record the present version index for later
1283 1281 * potential versioning.
1284 1282 */
1285 1283 if ((sdp->sd_aux->sa_overndx == 0) ||
1286 1284 (sdp->sd_aux->sa_overndx == VER_NDX_GLOBAL))
1287 1285 sdp->sd_aux->sa_overndx = mv->mv_vdp->vd_ndx;
1288 1286 mv->mv_vdp->vd_flags |= FLG_VER_REFER;
1289 1287 }
1290 1288
1291 1289 conflict = NULL;
1292 1290
1293 1291 /*
1294 1292 * Carry out some validity checks to ensure incompatible
1295 1293 * symbol characteristics have not been defined.
1296 1294 * These checks are carried out after symbols are added
1297 1295 * or resolved, to catch single instance, and
1298 1296 * multi-instance definition inconsistencies.
1299 1297 */
1300 1298 if ((sdp->sd_flags & (FLG_SY_HIDDEN | FLG_SY_ELIM)) &&
1301 1299 ((mv->mv_scope != FLG_SCOPE_HIDD) &&
1302 1300 (mv->mv_scope != FLG_SCOPE_ELIM))) {
1303 1301 conflict = MSG_INTL(MSG_MAP_DIFF_SYMLCL);
1304 1302
1305 1303 } else if ((sdp->sd_flags &
1306 1304 (FLG_SY_SINGLE | FLG_SY_EXPORT)) &&
1307 1305 ((mv->mv_scope != FLG_SCOPE_DFLT) &&
1308 1306 (mv->mv_scope != FLG_SCOPE_EXPT) &&
1309 1307 (mv->mv_scope != FLG_SCOPE_SNGL))) {
1310 1308 conflict = MSG_INTL(MSG_MAP_DIFF_SYMGLOB);
1311 1309
1312 1310 } else if ((sdp->sd_flags & FLG_SY_PROTECT) &&
1313 1311 ((mv->mv_scope != FLG_SCOPE_DFLT) &&
1314 1312 (mv->mv_scope != FLG_SCOPE_PROT))) {
1315 1313 conflict = MSG_INTL(MSG_MAP_DIFF_SYMPROT);
1316 1314
1317 1315 } else if ((sdp->sd_flags & FLG_SY_NDIR) &&
1318 1316 (mv->mv_scope == FLG_SCOPE_PROT)) {
1319 1317 conflict = MSG_INTL(MSG_MAP_DIFF_PROTNDIR);
1320 1318
1321 1319 } else if ((sdp->sd_flags & FLG_SY_DIR) &&
1322 1320 (mv->mv_scope == FLG_SCOPE_SNGL)) {
1323 1321 conflict = MSG_INTL(MSG_MAP_DIFF_SNGLDIR);
1324 1322 }
1325 1323
1326 1324 if (conflict) {
1327 1325 /*
1328 1326 * Select the conflict message from either a
1329 1327 * single instance or multi-instance definition.
1330 1328 */
1331 1329 if (sdp->sd_file->ifl_name == mf->mf_name) {
1332 1330 mf_fatal(mf, MSG_INTL(MSG_MAP_SYMDEF2),
1333 1331 demangle(ms->ms_name), conflict);
1334 1332 } else {
1335 1333 mf_fatal(mf, MSG_INTL(MSG_MAP_SYMDEF1),
1336 1334 demangle(ms->ms_name),
1337 1335 sdp->sd_file->ifl_name, conflict);
1338 1336 }
1339 1337 mv->mv_errcnt++;
1340 1338 return (TRUE);
1341 1339 }
1342 1340
1343 1341 /*
1344 1342 * Indicate that this symbol has been explicitly
1345 1343 * contributed from a mapfile.
1346 1344 */
1347 1345 sdp->sd_flags |= (FLG_SY_MAPFILE | FLG_SY_EXPDEF);
1348 1346
1349 1347 /*
1350 1348 * If we've encountered a symbol definition simulate
1351 1349 * that an input file has been processed - this allows
1352 1350 * things like filters to be created purely from a
1353 1351 * mapfile.
1354 1352 */
1355 1353 if (ms->ms_type != STT_NOTYPE)
1356 1354 ofl->ofl_objscnt++;
1357 1355 DBG_CALL(Dbg_map_symbol(ofl, sdp));
1358 1356
1359 1357 /*
1360 1358 * If this symbol has an associated filtee, record the
1361 1359 * filtee string and associate the string index with the
1362 1360 * symbol. This is used later to associate the syminfo
1363 1361 * information with the necessary .dynamic entry.
1364 1362 */
1365 1363 if (ms->ms_filtee) {
1366 1364 Dfltr_desc * dftp;
1367 1365 Sfltr_desc sft;
1368 1366 Aliste idx, _idx, nitems;
1369 1367
1370 1368 /*
1371 1369 * Make sure we don't duplicate any filtee
1372 1370 * strings, and create a new descriptor if
1373 1371 * necessary.
1374 1372 */
1375 1373 idx = nitems = alist_nitems(ofl->ofl_dtsfltrs);
1376 1374 for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, _idx, dftp)) {
1377 1375 if ((ms->ms_dft_flag != dftp->dft_flag) ||
1378 1376 (strcmp(dftp->dft_str, ms->ms_filtee)))
1379 1377 continue;
1380 1378 idx = _idx;
1381 1379 break;
1382 1380 }
1383 1381 if (idx == nitems) {
1384 1382 Dfltr_desc dft;
1385 1383
1386 1384 dft.dft_str = ms->ms_filtee;
1387 1385 dft.dft_flag = ms->ms_dft_flag;
1388 1386 dft.dft_ndx = 0;
1389 1387
1390 1388 /*
1391 1389 * The following append puts the new
1392 1390 * item at the offset contained in
1393 1391 * idx, because we know idx contains
1394 1392 * the index of the next available slot.
1395 1393 */
1396 1394 if (alist_append(&ofl->ofl_dtsfltrs, &dft,
1397 1395 sizeof (Dfltr_desc), AL_CNT_OFL_DTSFLTRS) == NULL)
1398 1396 return (FALSE);
1399 1397 }
1400 1398
1401 1399 /*
1402 1400 * Create a new filter descriptor for this
1403 1401 * symbol.
1404 1402 */
1405 1403 sft.sft_sdp = sdp;
1406 1404 sft.sft_idx = idx;
1407 1405
1408 1406 if (alist_append(&ofl->ofl_symfltrs, &sft, sizeof (Sfltr_desc),
1409 1407 AL_CNT_OFL_SYMFLTRS) == NULL)
1410 1408 return (FALSE);
1411 1409 }
1412 1410
1413 1411 return (TRUE);
1414 1412 }
1415 1413
1416 1414 /*
1417 1415 * In both the version 1 and version 2 syntaxes, a version definition
1418 1416 * can have 0 or more inherited versions following the closing '}',
1419 1417 * terminated by a ';'.
1420 1418 *
1421 1419 * Add the inherited names, and return when the terminator is seen.
1422 1420 */
1423 1421 Boolean
1424 1422 ld_map_sym_ver_fini(Mapfile *mf, ld_map_ver_t *mv)
1425 1423 {
1426 1424 Token tok;
1427 1425 ld_map_tkval_t tkv; /* Value of token */
1428 1426 Boolean done = FALSE;
1429 1427 Conv_inv_buf_t inv_buf;
1430 1428 const char *name;
1431 1429 Ver_desc *vdp;
1432 1430 Word hash;
1433 1431
1434 1432 /*
1435 1433 * Read version names until we encounter the ';' terminator.
1436 1434 */
1437 1435 while (!done) {
1438 1436 switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
1439 1437 case TK_ERROR:
1440 1438 return (FALSE);
1441 1439
1442 1440 case TK_STRING:
1443 1441 name = tkv.tkv_str;
1444 1442
1445 1443 /* The unnamed global scope can't inherit */
1446 1444 if (mv->mv_vdp->vd_ndx == VER_NDX_GLOBAL) {
1447 1445 mf_fatal(mf, MSG_INTL(MSG_MAP_UNEXINHERIT),
1448 1446 name);
1449 1447 return (FALSE);
1450 1448 }
1451 1449
1452 1450 /*
1453 1451 * Generate a new version descriptor if it doesn't
1454 1452 * already exist.
1455 1453 */
1456 1454 /* LINTED */
1457 1455 hash = (Word)elf_hash(name);
1458 1456 vdp = ld_vers_find(name, hash, mf->mf_ofl->ofl_verdesc);
1459 1457 if ((vdp == NULL) && ((vdp = ld_vers_desc(name, hash,
1460 1458 &mf->mf_ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR))
1461 1459 return (FALSE);
1462 1460
1463 1461 /*
1464 1462 * Add the new version descriptor to the parent version
1465 1463 * descriptors reference list. Indicate the version
1466 1464 * descriptors first reference (used for error diags
1467 1465 * if undefined version dependencies remain).
1468 1466 */
1469 1467 if (ld_vers_find(name, hash, mv->mv_vdp->vd_deps) ==
1470 1468 NULL)
1471 1469 if (aplist_append(&mv->mv_vdp->vd_deps, vdp,
1472 1470 AL_CNT_VERDESCS) == NULL)
1473 1471 return (FALSE);
1474 1472
1475 1473 if (vdp->vd_ref == NULL)
1476 1474 vdp->vd_ref = mv->mv_vdp;
1477 1475 break;
1478 1476
1479 1477 case TK_SEMICOLON:
1480 1478 done = TRUE;
1481 1479 break;
1482 1480
1483 1481 default:
1484 1482 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMEND),
1485 1483 ld_map_tokenstr(tok, &tkv, &inv_buf));
1486 1484 return (FALSE);
1487 1485 }
1488 1486 }
1489 1487
1490 1488 return (TRUE);
1491 1489 }
↓ open down ↓ |
1279 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX