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