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