dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / sgs / rtld / common / analyze.c
blob3553eac517cceab97b95b71af060b70d7b76cdbc
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) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Copyright (c) 1988 AT&T
28 * All Rights Reserved
31 #include <string.h>
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <sys/stat.h>
35 #include <sys/mman.h>
36 #include <sys/debug.h>
37 #include <fcntl.h>
38 #include <limits.h>
39 #include <dlfcn.h>
40 #include <errno.h>
41 #include <link.h>
42 #include <debug.h>
43 #include <conv.h>
44 #include "_rtld.h"
45 #include "_audit.h"
46 #include "_elf.h"
47 #include "_a.out.h"
48 #include "_inline_gen.h"
49 #include "msg.h"
52 * If a load filter flag is in effect, and this object is a filter, trigger the
53 * loading of all its filtees. The load filter flag is in effect when creating
54 * configuration files, or when under the control of ldd(1), or the LD_LOADFLTR
55 * environment variable is set, or this object was built with the -zloadfltr
56 * flag. Otherwise, filtee loading is deferred until triggered by a relocation.
58 static void
59 load_filtees(Rt_map *lmp, int *in_nfavl)
61 if ((FLAGS1(lmp) & MSK_RT_FILTER) &&
62 ((FLAGS(lmp) & FLG_RT_LOADFLTR) ||
63 (LIST(lmp)->lm_tflags & LML_TFLG_LOADFLTR))) {
64 Dyninfo *dip = DYNINFO(lmp);
65 uint_t cnt, max = DYNINFOCNT(lmp);
66 Slookup sl;
69 * Initialize the symbol lookup data structure. Note, no symbol
70 * name is supplied. This NULL name causes filters to be loaded
71 * but no symbol to be searched for.
73 SLOOKUP_INIT(sl, 0, lmp, lmp, ld_entry_cnt, 0, 0, 0, 0, 0);
75 for (cnt = 0; cnt < max; cnt++, dip++) {
76 uint_t binfo;
77 Sresult sr;
79 SRESULT_INIT(sr, NULL);
81 if (((dip->di_flags & MSK_DI_FILTER) == 0) ||
82 ((dip->di_flags & FLG_DI_AUXFLTR) &&
83 (rtld_flags & RT_FL_NOAUXFLTR)))
84 continue;
85 (void) elf_lookup_filtee(&sl, &sr, &binfo, cnt,
86 in_nfavl);
92 * Analyze one or more link-maps of a link map control list. This routine is
93 * called at startup to continue the processing of the main executable. It is
94 * also called each time a new set of objects are loaded, ie. from filters,
95 * lazy-loaded objects, or dlopen().
97 * In each instance we traverse the link-map control list starting with the
98 * initial object. As dependencies are analyzed they are added to the link-map
99 * control list. Thus the list grows as we traverse it - this results in the
100 * breadth first ordering of all needed objects.
102 * Return the initial link-map from which analysis starts for relocate_lmc().
104 Rt_map *
105 analyze_lmc(Lm_list *lml, Aliste nlmco, Rt_map *nlmp, Rt_map *clmp,
106 int *in_nfavl)
108 Rt_map *lmp;
109 Lm_cntl *nlmc;
112 * If this link-map control list is being analyzed, return. The object
113 * that has just been added will be picked up by the existing analysis
114 * thread. Note, this is only really meaningful during process init-
115 * ialization, as objects are added to the main link-map control list.
116 * Following this initialization, each family of objects that are loaded
117 * are added to a new link-map control list.
119 /* LINTED */
120 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
121 if (nlmc->lc_flags & LMC_FLG_ANALYZING)
122 return (nlmp);
125 * If this object doesn't belong to the present link-map control list
126 * then it must already have been analyzed, or it is in the process of
127 * being analyzed prior to us recursing into this analysis. In either
128 * case, ignore the object as it's already being taken care of.
130 if (nlmco != CNTL(nlmp))
131 return (nlmp);
133 nlmc->lc_flags |= LMC_FLG_ANALYZING;
135 for (lmp = nlmp; lmp; lmp = NEXT_RT_MAP(lmp)) {
136 if (FLAGS(lmp) &
137 (FLG_RT_ANALZING | FLG_RT_ANALYZED | FLG_RT_DELETE))
138 continue;
141 * Indicate that analyzing is under way.
143 FLAGS(lmp) |= FLG_RT_ANALZING;
146 * If this link map represents a relocatable object, then we
147 * need to finish the link-editing of the object at this point.
149 if (FLAGS(lmp) & FLG_RT_OBJECT) {
150 Rt_map *olmp;
152 if ((olmp = elf_obj_fini(lml, lmp, clmp,
153 in_nfavl)) == NULL) {
154 if (lml->lm_flags & LML_FLG_TRC_ENABLE)
155 continue;
156 nlmp = NULL;
157 break;
161 * The original link-map that captured a relocatable
162 * object is a temporary link-map, that basically acts
163 * as a place holder in the link-map list. On
164 * completion of relocatable object processing, a new
165 * link-map is created, and switched with the place
166 * holder. Therefore, reassign both the present
167 * link-map pointer and the return link-map pointer.
168 * The former resets this routines link-map processing,
169 * while the latter provides for later functions, like
170 * relocate_lmc(), to start processing from this new
171 * link-map.
173 if (nlmp == lmp)
174 nlmp = olmp;
175 lmp = olmp;
178 DBG_CALL(Dbg_file_analyze(lmp));
181 * Establish any dependencies this object requires.
183 if (LM_NEEDED(lmp)(lml, nlmco, lmp, in_nfavl) == 0) {
184 if (lml->lm_flags & LML_FLG_TRC_ENABLE)
185 continue;
186 nlmp = NULL;
187 break;
190 FLAGS(lmp) &= ~FLG_RT_ANALZING;
191 FLAGS(lmp) |= FLG_RT_ANALYZED;
194 * If we're building a configuration file, determine if this
195 * object is a filter and if so load its filtees. This
196 * traversal is only necessary for crle(1), as typical use of
197 * an object will load filters as part of relocation processing.
199 if (MODE(nlmp) & RTLD_CONFGEN)
200 load_filtees(lmp, in_nfavl);
203 * If an interposer has been added, it will have been inserted
204 * in the link-map before the link we're presently analyzing.
205 * Break out of this analysis loop and return to the head of
206 * the link-map control list to analyze the interposer. Note
207 * that this rescan preserves the breadth first loading of
208 * dependencies.
210 /* LINTED */
211 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
212 if (nlmc->lc_flags & LMC_FLG_REANALYZE) {
213 nlmc->lc_flags &= ~LMC_FLG_REANALYZE;
214 lmp = nlmc->lc_head;
218 /* LINTED */
219 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
220 nlmc->lc_flags &= ~LMC_FLG_ANALYZING;
222 return (nlmp);
226 * Determine whether a symbol represents zero, .bss, bits. Most commonly this
227 * function is used to determine whether the data for a copy relocation refers
228 * to initialized data or .bss. If the data definition is within .bss, then the
229 * data is zero filled, and as the copy destination within the executable is
230 * .bss, we can skip copying zero's to zero's.
232 * However, if the defining object has MOVE data, it's .bss might contain
233 * non-zero data, in which case copy the definition regardless.
235 * For backward compatibility copy relocation processing, this routine can be
236 * used to determine precisely if a copy destination is a move record recipient.
238 static int
239 are_bits_zero(Rt_map *dlmp, Sym *dsym, int dest)
241 mmapobj_result_t *mpp;
242 caddr_t daddr = (caddr_t)dsym->st_value;
244 if ((FLAGS(dlmp) & FLG_RT_FIXED) == 0)
245 daddr += ADDR(dlmp);
248 * Determine the segment that contains the copy definition. Given that
249 * the copy relocation records have already been captured and verified,
250 * a segment must be found (but we add an escape clause never the less).
252 if ((mpp = find_segment(daddr, dlmp)) == NULL)
253 return (1);
256 * If the definition is not within .bss, indicate this is not zero data.
258 if (daddr < (mpp->mr_addr + mpp->mr_offset + mpp->mr_fsize))
259 return (0);
262 * If the definition is within .bss, make sure the definition isn't the
263 * recipient of a move record. Note, we don't precisely analyze whether
264 * the address is a move record recipient, as the infrastructure to
265 * prepare for, and carry out this analysis, is probably more costly
266 * than just copying the bytes regardless.
268 if ((FLAGS(dlmp) & FLG_RT_MOVE) == 0)
269 return (1);
272 * However, for backward compatibility copy relocation processing, we
273 * can afford to work a little harder. Here, determine precisely
274 * whether the destination in the executable is a move record recipient.
275 * See comments in lookup_sym_interpose(), below.
277 if (dest && is_move_data(daddr))
278 return (0);
280 return (1);
284 * Relocate an individual object.
286 static int
287 relocate_so(Lm_list *lml, Rt_map *lmp, int *relocated, int now, int *in_nfavl)
289 APlist *textrel = NULL;
290 int ret = 1;
293 * If we're running under ldd(1), and haven't been asked to trace any
294 * warnings, skip any actual relocation processing.
296 if (((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0) ||
297 (lml->lm_flags & LML_FLG_TRC_WARN)) {
299 if (relocated)
300 (*relocated)++;
302 if ((LM_RELOC(lmp)(lmp, now, in_nfavl, &textrel) == 0) &&
303 ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0))
304 ret = 0;
307 * Finally process any move data. Note, this is carried out
308 * with ldd(1) under relocation processing too, as it can flush
309 * out move errors, and enables lari(1) to provide a true
310 * representation of the runtime bindings.
312 if ((FLAGS(lmp) & FLG_RT_MOVE) &&
313 (move_data(lmp, &textrel) == 0) &&
314 ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0))
315 ret = 0;
319 * If a text segment was write enabled to perform any relocations or
320 * move records, then re-protect the segment by disabling writes.
322 if (textrel) {
323 mmapobj_result_t *mpp;
324 Aliste idx;
326 for (APLIST_TRAVERSE(textrel, idx, mpp))
327 (void) set_prot(lmp, mpp, 0);
328 free(textrel);
331 return (ret);
335 * Relocate the objects on a link-map control list.
337 static int
338 _relocate_lmc(Lm_list *lml, Aliste lmco, Rt_map *nlmp, int *relocated,
339 int *in_nfavl)
341 Rt_map *lmp;
343 for (lmp = nlmp; lmp; lmp = NEXT_RT_MAP(lmp)) {
345 * If this object has already been relocated, we're done. If
346 * this object is being deleted, skip it, there's probably a
347 * relocation error somewhere that's causing this deletion.
349 if (FLAGS(lmp) &
350 (FLG_RT_RELOCING | FLG_RT_RELOCED | FLG_RT_DELETE))
351 continue;
354 * Indicate that relocation processing is under way.
356 FLAGS(lmp) |= FLG_RT_RELOCING;
359 * Relocate the object.
361 if (relocate_so(lml, lmp, relocated, 0, in_nfavl) == 0)
362 return (0);
365 * Indicate that the objects relocation is complete.
367 FLAGS(lmp) &= ~FLG_RT_RELOCING;
368 FLAGS(lmp) |= FLG_RT_RELOCED;
371 * If this object is being relocated on the main link-map list
372 * indicate that this object's init is available for harvesting.
373 * Objects that are being collected on other link-map lists
374 * will have there init availability tagged when the objects
375 * are move to the main link-map list (ie, after we know they,
376 * and their dependencies, are fully relocated and ready for
377 * use).
379 * Note, even under ldd(1) this init identification is necessary
380 * for -i (tsort) gathering.
382 if (lmco == ALIST_OFF_DATA) {
383 lml->lm_init++;
384 lml->lm_flags |= LML_FLG_OBJADDED;
388 * Determine if this object is a filter, and if a load filter
389 * flag is in effect, trigger the loading of all its filtees.
391 load_filtees(lmp, in_nfavl);
395 * Perform special copy relocations. These are only meaningful for
396 * dynamic executables (fixed and head of their link-map list). If
397 * this ever has to change then the infrastructure of COPY() has to
398 * change. Presently, a given link map can only have a receiver or
399 * supplier of copy data, so a union is used to overlap the storage
400 * for the COPY_R() and COPY_S() lists. These lists would need to
401 * be separated.
403 if ((FLAGS(nlmp) & FLG_RT_FIXED) && (nlmp == LIST(nlmp)->lm_head) &&
404 (((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0) ||
405 (lml->lm_flags & LML_FLG_TRC_WARN))) {
406 Rt_map *lmp;
407 Aliste idx1;
408 Word tracing;
410 #if defined(__i386)
411 if (elf_copy_gen(nlmp) == 0)
412 return (0);
413 #endif
414 if (COPY_S(nlmp) == NULL)
415 return (1);
417 if ((LIST(nlmp)->lm_flags & LML_FLG_TRC_ENABLE) &&
418 (((rtld_flags & RT_FL_SILENCERR) == 0) ||
419 (LIST(nlmp)->lm_flags & LML_FLG_TRC_VERBOSE)))
420 tracing = 1;
421 else
422 tracing = 0;
424 DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
426 for (APLIST_TRAVERSE(COPY_S(nlmp), idx1, lmp)) {
427 Rel_copy *rcp;
428 Aliste idx2;
430 for (ALIST_TRAVERSE(COPY_R(lmp), idx2, rcp)) {
431 int zero;
434 * Only copy the data if the data is from
435 * a non-zero definition (ie. not .bss).
437 zero = are_bits_zero(rcp->r_dlmp,
438 rcp->r_dsym, 0);
439 DBG_CALL(Dbg_reloc_copy(rcp->r_dlmp, nlmp,
440 rcp->r_name, zero));
441 if (zero)
442 continue;
444 (void) memcpy(rcp->r_radd, rcp->r_dadd,
445 rcp->r_size);
447 if ((tracing == 0) || ((FLAGS1(rcp->r_dlmp) &
448 FL1_RT_DISPREL) == 0))
449 continue;
451 (void) printf(MSG_INTL(MSG_LDD_REL_CPYDISP),
452 demangle(rcp->r_name), NAME(rcp->r_dlmp));
456 DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
458 free(COPY_S(nlmp));
459 COPY_S(nlmp) = NULL;
461 return (1);
465 relocate_lmc(Lm_list *lml, Aliste nlmco, Rt_map *clmp, Rt_map *nlmp,
466 int *in_nfavl)
468 int lret = 1, pret = 1;
469 APlist *alp;
470 Aliste plmco;
471 Lm_cntl *plmc, *nlmc;
474 * If this link-map control list is being relocated, return. The object
475 * that has just been added will be picked up by the existing relocation
476 * thread. Note, this is only really meaningful during process init-
477 * ialization, as objects are added to the main link-map control list.
478 * Following this initialization, each family of objects that are loaded
479 * are added to a new link-map control list.
481 /* LINTED */
482 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
484 if (nlmc->lc_flags & LMC_FLG_RELOCATING)
485 return (1);
487 nlmc->lc_flags |= LMC_FLG_RELOCATING;
490 * Relocate one or more link-maps of a link map control list. If this
491 * object doesn't belong to the present link-map control list then it
492 * must already have been relocated, or it is in the process of being
493 * relocated prior to us recursing into this relocation. In either
494 * case, ignore the object as it's already being taken care of, however,
495 * fall through and capture any relocation promotions that might have
496 * been established from the reference mode of this object.
498 * If we're generating a configuration file using crle(1), two passes
499 * may be involved. Under the first pass, RTLD_CONFGEN is set. Under
500 * this pass, crle() loads objects into the process address space. No
501 * relocation is necessary at this point, we simply need to analyze the
502 * objects to ensure any directly bound dependencies, filtees, etc.
503 * get loaded. Although we skip the relocation, fall through to ensure
504 * any control lists are maintained appropriately.
506 * If objects are to be dldump(3c)'ed, crle(1) makes a second pass,
507 * using RTLD_NOW and RTLD_CONFGEN. The RTLD_NOW effectively carries
508 * out the relocations of all loaded objects.
510 if ((nlmco == CNTL(nlmp)) &&
511 ((MODE(nlmp) & (RTLD_NOW | RTLD_CONFGEN)) != RTLD_CONFGEN)) {
512 int relocated = 0;
515 * Determine whether the initial link-map control list has
516 * started relocation. From this point, should any interposing
517 * objects be added to this link-map control list, the objects
518 * are demoted to standard objects. Their interposition can't
519 * be guaranteed once relocations have been carried out.
521 if (nlmco == ALIST_OFF_DATA)
522 lml->lm_flags |= LML_FLG_STARTREL;
525 * Relocate the link-map control list. Should this relocation
526 * fail, clean up this link-map list. Relocations within this
527 * list may have required relocation promotions on other lists,
528 * so before acting upon these, and possibly adding more objects
529 * to the present link-map control list, try and clean up any
530 * failed objects now.
532 lret = _relocate_lmc(lml, nlmco, nlmp, &relocated, in_nfavl);
533 if ((lret == 0) && (nlmco != ALIST_OFF_DATA))
534 remove_lmc(lml, clmp, nlmco, NAME(nlmp));
538 * Determine the new, and previous link-map control lists.
540 /* LINTED */
541 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
542 if (nlmco == ALIST_OFF_DATA) {
543 plmco = nlmco;
544 plmc = nlmc;
545 } else {
546 plmco = nlmco - lml->lm_lists->al_size;
547 /* LINTED */
548 plmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, plmco);
552 * Having completed this control list of objects, they can now be bound
553 * to from other objects. Move this control list to the control list
554 * that precedes it. Although this control list may have only bound to
555 * controls lists much higher up the control list stack, it must only
556 * be moved up one control list so as to preserve the link-map order
557 * that may have already been traversed in search of symbols.
559 if (lret && (nlmco != ALIST_OFF_DATA) && nlmc->lc_head)
560 lm_move(lml, nlmco, plmco, nlmc, plmc);
563 * Determine whether existing objects that have already been relocated,
564 * need any additional relocations performed. This can occur when new
565 * objects are loaded with RTLD_NOW, and these new objects have
566 * dependencies on objects that are already loaded. Note, that we peel
567 * any relocation promotions off of one control list at a time. This
568 * prevents relocations from being bound to objects that might yet fail
569 * to relocate themselves.
571 while ((alp = plmc->lc_now) != NULL) {
572 Aliste idx;
573 Rt_map *lmp;
576 * Remove the relocation promotion list, as performing more
577 * relocations may result in discovering more objects that need
578 * promotion.
580 plmc->lc_now = NULL;
582 for (APLIST_TRAVERSE(alp, idx, lmp)) {
584 * If the original relocation of the link-map control
585 * list failed, or one of the relocation promotions of
586 * this loop has failed, demote any pending objects
587 * relocation mode.
589 if ((lret == 0) || (pret == 0)) {
590 MODE(lmp) &= ~RTLD_NOW;
591 MODE(lmp) |= RTLD_LAZY;
592 continue;
596 * If a relocation fails, save the error condition.
597 * It's possible that all new objects on the original
598 * link-map control list have been relocated
599 * successfully, but if the user request requires
600 * promoting objects that have already been loaded, we
601 * have to indicate that this operation couldn't be
602 * performed. The unrelocated objects are in use on
603 * another control list, and may continue to be used.
604 * If the .plt that resulted in the error is called,
605 * then the process will receive a fatal error at that
606 * time. But, the .plt may never be called.
608 if (relocate_so(lml, lmp, 0, 1, in_nfavl) == 0)
609 pret = 0;
613 * Having promoted any objects, determine whether additional
614 * dependencies were added, and if so move them to the previous
615 * link-map control list.
617 /* LINTED */
618 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
619 /* LINTED */
620 plmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, plmco);
621 if ((nlmco != ALIST_OFF_DATA) && nlmc->lc_head)
622 lm_move(lml, nlmco, plmco, nlmc, plmc);
623 free(alp);
627 * If relocations have been successful, indicate that relocations are
628 * no longer active for this control list. Otherwise, leave the
629 * relocation flag, as this flag is used to determine the style of
630 * cleanup (see remove_lmc()).
632 if (lret && pret) {
633 /* LINTED */
634 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
635 nlmc->lc_flags &= ~LMC_FLG_RELOCATING;
637 return (1);
640 return (0);
644 * Inherit the first rejection message for possible later diagnostics.
646 * Any attempt to process a file that is unsuccessful, should be accompanied
647 * with an error diagnostic. However, some operations like searching for a
648 * simple filename, involve trying numerous paths, and an error message for each
649 * lookup is not required. Although a multiple search can fail, it's possible
650 * that a file was found, but was rejected because it was the wrong type.
651 * To satisfy these possibilities, the first failure is recorded as a rejection
652 * message, and this message is used later for a more specific diagnostic.
654 * File searches are focused at load_one(), and from here a rejection descriptor
655 * is passed down to various child routines. If these child routines can
656 * process multiple files, then they will maintain their own rejection desc-
657 * riptor. This is filled in for any failures, and a diagnostic produced to
658 * reflect the failure. The child routines then employ rejection_inherit() to
659 * pass the first rejection message back to load_one().
661 * Note that the name, and rejection string must be duplicated, as the name
662 * buffer and error string buffer (see conv_ routines) may be reused for
663 * additional processing or rejection messages.
665 void
666 rejection_inherit(Rej_desc *rej1, Rej_desc *rej2)
668 if (rej2->rej_type && (rej1->rej_type == 0)) {
669 rej1->rej_type = rej2->rej_type;
670 rej1->rej_info = rej2->rej_info;
671 rej1->rej_flags = rej2->rej_flags;
672 if (rej2->rej_name)
673 rej1->rej_name = stravl_insert(rej2->rej_name, 0, 0, 0);
674 if ((rej2->rej_str) && ((rej1->rej_str =
675 stravl_insert(rej2->rej_str, 0, 0, 0)) == NULL))
676 rej1->rej_str = MSG_ORIG(MSG_EMG_ENOMEM);
681 * Helper routine for is_so_matched() that consolidates matching a path name,
682 * or file name component of a link-map name.
684 inline static int
685 _is_so_matched(const char *name, const char *str, int path)
687 const char *_str;
689 if ((path == 0) && ((_str = strrchr(str, '/')) != NULL))
690 _str++;
691 else
692 _str = str;
694 return (strcmp(name, _str));
698 * Determine whether a search name matches one of the names associated with a
699 * link-map. A link-map contains several names:
701 * - a NAME() - this is the basename of the dynamic executable that started
702 * the process, and the path name of any dependencies used by the process.
703 * Most executables are received as full path names, as exec() prepends a
704 * search $PATH to locate the executable. However, simple file names can
705 * be received from exec() if the file is executed from the present working
706 * directory. Regardless, ld.so.1 maintains NAME() as the basename, as
707 * this has always been the name used in diagnostics and error messages.
708 * Most dependencies are full path names, as the typical search for a
709 * dependency, say "libx.so.1", results in search paths being prepended to
710 * the name, which eventually open "/lib/libx.so.1". However, relative
711 * path names can be supplied as dependencies, e.g. dlopen("../libx.so.1").
713 * - a PATHNAME() - this is the fully resolved path name of the object. This
714 * name will differ from NAME() for all dynamic executables, and may differ
715 * from the NAME() of dependencies, if the dependency is not a full path
716 * name, or the dependency resolves to a symbolic link.
718 * - an ALIAS() name - these are alternative names by which the object has
719 * been found, ie. when dependencies are loaded through a variety of
720 * different symbolic links.
722 * The name pattern matching can differ depending on whether we are looking
723 * for a full path name (path != 0), or a simple file name (path == 0). Full
724 * path names typically match NAME() or PATHNAME() entries.
726 * For all full path name searches, the link-map names are taken as is. For
727 * simple file name searches, only the file name component of any link-map
728 * names are used for comparison.
730 inline static Rt_map *
731 is_so_matched(Rt_map *lmp, const char *name, int path)
733 Aliste idx;
734 const char *cp;
736 if (_is_so_matched(name, NAME(lmp), path) == 0)
737 return (lmp);
739 if (PATHNAME(lmp) != NAME(lmp)) {
740 if (_is_so_matched(name, PATHNAME(lmp), path) == 0)
741 return (lmp);
744 for (APLIST_TRAVERSE(ALIAS(lmp), idx, cp)) {
745 if (_is_so_matched(name, cp, path) == 0)
746 return (lmp);
749 return (NULL);
753 * Files are opened by ld.so.1 to satisfy dependencies, filtees and dlopen()
754 * requests. Each request investigates the file based upon the callers
755 * environment. Once a full path name has been established, the following
756 * checks are made:
758 * - does the path exist in the link-map lists FullPathNode AVL tree? if
759 * so, the file is already loaded, and its associated link-map pointer
760 * is returned.
761 * - does the path exist in the not-found AVL tree? if so, this path has
762 * already been determined to not exist, and a failure is returned.
763 * - a device/inode check, to ensure the same file isn't mapped multiple
764 * times through different paths. See file_open().
766 * However, there are cases where a test for an existing file name needs to be
767 * carried out, such as dlopen(NOLOAD) requests, dldump() requests, and as a
768 * final fallback to dependency loading. These requests are handled by
769 * is_so_loaded().
771 * A traversal through the callers link-map list is carried out, and from each
772 * link-map, a comparison is made against all of the various names by which the
773 * object has been referenced. is_so_matched() is used to compare the link-map
774 * names against the name being searched for. Whether the search name is a full
775 * path name or a simple file name, governs what comparisons are made.
777 * A full path name, which is a fully resolved path name that starts with a "/"
778 * character, or a relative path name that includes a "/" character, must match
779 * the link-map names exactly. A simple file name, which is any name *not*
780 * containing a "/" character, are matched against the file name component of
781 * any link-map names.
783 Rt_map *
784 is_so_loaded(Lm_list *lml, const char *name, int *in_nfavl)
786 Rt_map *lmp;
787 avl_index_t where;
788 Lm_cntl *lmc;
789 Aliste idx;
790 int path = 0;
793 * If the name is a full path name, first determine if the path name is
794 * registered on the FullPathNode AVL, or not-found AVL trees.
796 if (name[0] == '/') {
797 uint_t hash = sgs_str_hash(name);
799 if (((lmp = fpavl_recorded(lml, name, hash, &where)) != NULL) &&
800 ((FLAGS(lmp) & (FLG_RT_OBJECT | FLG_RT_DELETE)) == 0))
801 return (lmp);
803 if (pnavl_recorded(&nfavl, name, hash, NULL)) {
805 * For dlopen() and dlsym() fall backs, indicate that
806 * a registered not-found path has indicated that this
807 * object does not exist.
809 if (in_nfavl)
810 (*in_nfavl)++;
811 return (NULL);
816 * Determine whether the name is a simple file name, or a path name.
818 if (strchr(name, '/'))
819 path++;
822 * Loop through the callers link-map lists.
824 for (ALIST_TRAVERSE(lml->lm_lists, idx, lmc)) {
825 for (lmp = lmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp)) {
826 if (FLAGS(lmp) & (FLG_RT_OBJECT | FLG_RT_DELETE))
827 continue;
829 if (is_so_matched(lmp, name, path))
830 return (lmp);
833 return (NULL);
837 * Tracing is enabled by the LD_TRACE_LOADED_OPTIONS environment variable which
838 * is normally set from ldd(1). For each link map we load, print the load name
839 * and the full pathname of the associated object.
841 /* ARGSUSED4 */
842 static void
843 trace_so(Rt_map *clmp, Rej_desc *rej, const char *name, const char *path,
844 int alter, const char *nfound)
846 const char *str = MSG_ORIG(MSG_STR_EMPTY);
847 const char *reject = MSG_ORIG(MSG_STR_EMPTY);
848 char _reject[PATH_MAX];
851 * The first time through trace_so() will only have lddstub on the
852 * link-map list and the preloaded shared object is supplied as "path".
853 * As we don't want to print this shared object as a dependency, but
854 * instead inspect *its* dependencies, return.
856 if (FLAGS1(clmp) & FL1_RT_LDDSTUB)
857 return;
860 * Without any rejection info, this is a supplied not-found condition.
862 if (rej && (rej->rej_type == 0)) {
863 (void) printf(nfound, name);
864 return;
868 * If rejection information exists then establish what object was
869 * found and the reason for its rejection.
871 if (rej) {
872 Conv_reject_desc_buf_t rej_buf;
874 /* LINTED */
875 (void) snprintf(_reject, PATH_MAX,
876 MSG_INTL(ldd_reject[rej->rej_type]),
877 conv_reject_desc(rej, &rej_buf, M_MACH));
878 if (rej->rej_name)
879 path = rej->rej_name;
880 reject = (char *)_reject;
883 * Was an alternative pathname defined (from a configuration
884 * file).
886 if (rej->rej_flags & FLG_REJ_ALTER)
887 str = MSG_INTL(MSG_LDD_FIL_ALTER);
888 } else {
889 if (alter)
890 str = MSG_INTL(MSG_LDD_FIL_ALTER);
894 * If the load name isn't a full pathname print its associated pathname
895 * together with all the other information we've gathered.
897 if (*name == '/')
898 (void) printf(MSG_ORIG(MSG_LDD_FIL_PATH), path, str, reject);
899 else
900 (void) printf(MSG_ORIG(MSG_LDD_FIL_EQUIV), name, path, str,
901 reject);
905 * Establish a link-map mode, initializing it if it has just been loaded, or
906 * potentially updating it if it already exists.
909 update_mode(Rt_map *lmp, int omode, int nmode)
911 Lm_list *lml = LIST(lmp);
912 int pmode = 0;
915 * A newly loaded object hasn't had its mode set yet. Modes are used to
916 * load dependencies, so don't propagate any parent or no-load flags, as
917 * these would adversely affect this objects ability to load any of its
918 * dependencies that aren't already loaded. RTLD_FIRST is applicable to
919 * this objects handle creation only, and should not be propagated.
921 if ((FLAGS(lmp) & FLG_RT_MODESET) == 0) {
922 MODE(lmp) |= nmode & ~(RTLD_PARENT | RTLD_NOLOAD | RTLD_FIRST);
923 FLAGS(lmp) |= FLG_RT_MODESET;
924 return (1);
928 * Establish any new overriding modes. RTLD_LAZY and RTLD_NOW should be
929 * represented individually (this is historic, as these two flags were
930 * the only flags originally available to dlopen()). Other flags are
931 * accumulative, but have a hierarchy of preference.
933 if ((omode & RTLD_LAZY) && (nmode & RTLD_NOW)) {
934 MODE(lmp) &= ~RTLD_LAZY;
935 pmode |= RTLD_NOW;
938 pmode |= ((~omode & nmode) &
939 (RTLD_GLOBAL | RTLD_WORLD | RTLD_NODELETE));
940 if (pmode) {
941 DBG_CALL(Dbg_file_mode_promote(lmp, pmode));
942 MODE(lmp) |= pmode;
946 * If this load is an RTLD_NOW request and the object has already been
947 * loaded non-RTLD_NOW, append this object to the relocation-now list
948 * of the objects associated control list. Note, if the object hasn't
949 * yet been relocated, setting its MODE() to RTLD_NOW will establish
950 * full relocation processing when it eventually gets relocated.
952 if ((pmode & RTLD_NOW) &&
953 (FLAGS(lmp) & (FLG_RT_RELOCED | FLG_RT_RELOCING))) {
954 Lm_cntl *lmc;
956 /* LINTED */
957 lmc = (Lm_cntl *)alist_item_by_offset(LIST(lmp)->lm_lists,
958 CNTL(lmp));
959 (void) aplist_append(&lmc->lc_now, lmp, AL_CNT_LMNOW);
963 * If this objects .init has been collected but has not yet been called,
964 * it may be necessary to reevaluate the object using tsort(). For
965 * example, a new dlopen() hierarchy may bind to uninitialized objects
966 * that are already loaded, or a dlopen(RTLD_NOW) can establish new
967 * bindings between already loaded objects that require the tsort()
968 * information be recomputed. If however, no new objects have been
969 * added to the process, and this object hasn't been promoted, don't
970 * bother reevaluating the .init. The present tsort() information is
971 * probably as accurate as necessary, and by not establishing a parallel
972 * tsort() we can help reduce the amount of recursion possible between
973 * .inits.
975 if (((FLAGS(lmp) &
976 (FLG_RT_INITCLCT | FLG_RT_INITCALL)) == FLG_RT_INITCLCT) &&
977 ((lml->lm_flags & LML_FLG_OBJADDED) || ((pmode & RTLD_NOW) &&
978 (FLAGS(lmp) & (FLG_RT_RELOCED | FLG_RT_RELOCING))))) {
979 FLAGS(lmp) &= ~FLG_RT_INITCLCT;
980 LIST(lmp)->lm_init++;
981 LIST(lmp)->lm_flags |= LML_FLG_OBJREEVAL;
984 return (pmode);
988 * Determine whether an alias name already exists, and if not create one. This
989 * is typically used to retain dependency names, such as "libc.so.1", which
990 * would have been expanded to full path names when they were loaded. The
991 * full path names (NAME() and possibly PATHNAME()) are maintained on the
992 * FullPathNode AVL tree, and thus would have been matched by fpavl_loaded()
993 * during file_open().
996 append_alias(Rt_map *lmp, const char *str, int *added)
998 const char *cp;
999 Aliste idx;
1002 * Determine if this filename is already on the alias list.
1004 for (APLIST_TRAVERSE(ALIAS(lmp), idx, cp)) {
1005 if (strcmp(cp, str) == 0)
1006 return (1);
1010 * This is a new alias, append it to the alias list.
1012 if (((cp = stravl_insert(str, 0, 0, 0)) == NULL) ||
1013 (aplist_append(&ALIAS(lmp), cp, AL_CNT_ALIAS) == NULL))
1014 return (0);
1016 if (added)
1017 *added = 1;
1018 return (1);
1022 * Determine whether a file is already loaded by comparing device and inode
1023 * values.
1025 static Rt_map *
1026 is_devinode_loaded(rtld_stat_t *status, Lm_list *lml, const char *name,
1027 uint_t flags)
1029 Lm_cntl *lmc;
1030 Aliste idx;
1033 * If this is an auditor, it will have been opened on a new link-map.
1034 * To prevent multiple occurrences of the same auditor on multiple
1035 * link-maps, search the head of each link-map list and see if this
1036 * object is already loaded as an auditor.
1038 if (flags & FLG_RT_AUDIT) {
1039 Lm_list *lml;
1041 for (APLIST_TRAVERSE(dynlm_list, idx, lml)) {
1042 Rt_map *nlmp = lml->lm_head;
1044 if (nlmp && ((FLAGS(nlmp) &
1045 (FLG_RT_AUDIT | FLG_RT_DELETE)) == FLG_RT_AUDIT) &&
1046 (STDEV(nlmp) == status->st_dev) &&
1047 (STINO(nlmp) == status->st_ino))
1048 return (nlmp);
1050 return (NULL);
1054 * If the file has been found determine from the new files status
1055 * information if this file is actually linked to one we already have
1056 * mapped. This catches symlink names not caught by is_so_loaded().
1058 for (ALIST_TRAVERSE(lml->lm_lists, idx, lmc)) {
1059 Rt_map *nlmp;
1061 for (nlmp = lmc->lc_head; nlmp; nlmp = NEXT_RT_MAP(nlmp)) {
1062 if ((FLAGS(nlmp) & FLG_RT_DELETE) ||
1063 (FLAGS1(nlmp) & FL1_RT_LDDSTUB))
1064 continue;
1066 if ((STDEV(nlmp) != status->st_dev) ||
1067 (STINO(nlmp) != status->st_ino))
1068 continue;
1070 if (lml->lm_flags & LML_FLG_TRC_VERBOSE) {
1071 /* BEGIN CSTYLED */
1072 if (*name == '/')
1073 (void) printf(MSG_ORIG(MSG_LDD_FIL_PATH),
1074 name, MSG_ORIG(MSG_STR_EMPTY),
1075 MSG_ORIG(MSG_STR_EMPTY));
1076 else
1077 (void) printf(MSG_ORIG(MSG_LDD_FIL_EQUIV),
1078 name, NAME(nlmp),
1079 MSG_ORIG(MSG_STR_EMPTY),
1080 MSG_ORIG(MSG_STR_EMPTY));
1081 /* END CSTYLED */
1083 return (nlmp);
1086 return (NULL);
1090 * Generate any error messages indicating a file could not be found. When
1091 * preloading or auditing a secure application, it can be a little more helpful
1092 * to indicate that a search of secure directories has failed, so adjust the
1093 * messages accordingly.
1095 void
1096 file_notfound(Lm_list *lml, const char *name, Rt_map *clmp, uint_t flags,
1097 Rej_desc *rej)
1099 int secure = 0;
1101 if ((rtld_flags & RT_FL_SECURE) &&
1102 (flags & (FLG_RT_PRELOAD | FLG_RT_AUDIT)))
1103 secure++;
1105 if (lml->lm_flags & LML_FLG_TRC_ENABLE) {
1107 * Under ldd(1), auxiliary filtees that can't be loaded are
1108 * ignored, unless verbose errors are requested.
1110 if ((rtld_flags & RT_FL_SILENCERR) &&
1111 ((lml->lm_flags & LML_FLG_TRC_VERBOSE) == 0))
1112 return;
1114 if (secure)
1115 trace_so(clmp, rej, name, 0, 0,
1116 MSG_INTL(MSG_LDD_SEC_NFOUND));
1117 else
1118 trace_so(clmp, rej, name, 0, 0,
1119 MSG_INTL(MSG_LDD_FIL_NFOUND));
1120 return;
1123 if (rej->rej_type) {
1124 Conv_reject_desc_buf_t rej_buf;
1126 eprintf(lml, ERR_FATAL, MSG_INTL(err_reject[rej->rej_type]),
1127 rej->rej_name ? rej->rej_name : MSG_INTL(MSG_STR_UNKNOWN),
1128 conv_reject_desc(rej, &rej_buf, M_MACH));
1129 return;
1132 if (secure)
1133 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SEC_OPEN), name);
1134 else
1135 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), name,
1136 strerror(ENOENT));
1139 static int
1140 file_open(int err, Lm_list *lml, Rt_map *clmp, uint_t flags, Fdesc *fdp,
1141 Rej_desc *rej, int *in_nfavl)
1143 rtld_stat_t status;
1144 Rt_map *nlmp;
1145 avl_index_t nfavlwhere = 0;
1146 const char *oname = fdp->fd_oname, *nname = fdp->fd_nname;
1147 uint_t hash = sgs_str_hash(nname);
1150 if ((nname = stravl_insert(fdp->fd_nname, hash, 0, 0)) == NULL)
1151 return (0);
1152 fdp->fd_nname = nname;
1154 if ((err == 0) && (fdp->fd_flags & FLG_FD_ALTER))
1155 DBG_CALL(Dbg_file_config_obj(lml, oname, 0, nname));
1158 * If we're dealing with a full pathname, determine whether this
1159 * pathname is already known. Other pathnames fall through to the
1160 * dev/inode check, as even though the pathname may look the same as
1161 * one previously used, the process may have changed directory.
1163 if ((err == 0) && (nname[0] == '/')) {
1164 if ((nlmp = fpavl_recorded(lml, nname, hash,
1165 &(fdp->fd_avlwhere))) != NULL) {
1166 fdp->fd_lmp = nlmp;
1167 return (1);
1169 if (pnavl_recorded(&nfavl, nname, hash, &nfavlwhere)) {
1171 * For dlopen() and dlsym() fall backs, indicate that
1172 * a registered not-found path has indicated that this
1173 * object does not exist. If this path has been
1174 * constructed as part of expanding a CAPABILITY
1175 * directory, this is a silent failure, where no
1176 * rejection message is created.
1178 if (in_nfavl)
1179 (*in_nfavl)++;
1180 return (0);
1184 if ((err == 0) && ((rtld_stat(nname, &status)) != -1)) {
1185 char path[PATH_MAX];
1186 int fd, size, added;
1189 * If this path has been constructed as part of expanding a
1190 * CAPABILITY directory, ignore any subdirectories. As this
1191 * is a silent failure, no rejection message is created. For
1192 * any other reference that expands to a directory, fall
1193 * through to construct a meaningful rejection message.
1195 if ((flags & FLG_RT_CAP) &&
1196 ((status.st_mode & S_IFMT) == S_IFDIR))
1197 return (0);
1200 * If this is a directory (which can't be mmap()'ed) generate a
1201 * precise error message.
1203 if ((status.st_mode & S_IFMT) == S_IFDIR) {
1204 rej->rej_name = nname;
1205 if (fdp->fd_flags & FLG_FD_ALTER)
1206 rej->rej_flags = FLG_REJ_ALTER;
1207 rej->rej_type = SGS_REJ_STR;
1208 rej->rej_str = strerror(EISDIR);
1209 DBG_CALL(Dbg_file_rejected(lml, rej, M_MACH));
1210 return (0);
1214 * Resolve the filename and determine whether the resolved name
1215 * is already known. Typically, the previous fpavl_loaded()
1216 * will have caught this, as both NAME() and PATHNAME() for a
1217 * link-map are recorded in the FullPathNode AVL tree. However,
1218 * instances exist where a file can be replaced (loop-back
1219 * mounts, bfu, etc.), and reference is made to the original
1220 * file through a symbolic link. By checking the pathname here,
1221 * we don't fall through to the dev/inode check and conclude
1222 * that a new file should be loaded.
1224 if ((nname[0] == '/') &&
1225 ((size = resolvepath(nname, path, (PATH_MAX - 1))) > 0)) {
1226 path[size] = '\0';
1228 fdp->fd_flags |= FLG_FD_RESOLVED;
1230 if (strcmp(nname, path)) {
1231 if ((nlmp =
1232 fpavl_recorded(lml, path, 0, 0)) != NULL) {
1233 added = 0;
1235 if (append_alias(nlmp, nname,
1236 &added) == 0)
1237 return (0);
1238 /* BEGIN CSTYLED */
1239 if (added)
1240 DBG_CALL(Dbg_file_skip(LIST(clmp),
1241 NAME(nlmp), nname));
1242 /* END CSTYLED */
1243 fdp->fd_lmp = nlmp;
1244 return (1);
1248 * If this pathname hasn't been loaded, save
1249 * the resolved pathname so that it doesn't
1250 * have to be recomputed as part of fullpath()
1251 * processing.
1253 if ((fdp->fd_pname = stravl_insert(path, 0,
1254 (size + 1), 0)) == NULL)
1255 return (0);
1259 if (nlmp = is_devinode_loaded(&status, lml, nname, flags)) {
1260 if (flags & FLG_RT_AUDIT) {
1262 * If we've been requested to load an auditor,
1263 * and an auditor of the same name already
1264 * exists, then the original auditor is used.
1266 DBG_CALL(Dbg_audit_skip(LIST(clmp),
1267 NAME(nlmp), LIST(nlmp)->lm_lmidstr));
1268 } else {
1270 * Otherwise, if an alternatively named file
1271 * has been found for the same dev/inode, add
1272 * a new name alias. Insert any alias full path
1273 * name in the FullPathNode AVL tree.
1275 added = 0;
1277 if (append_alias(nlmp, nname, &added) == 0)
1278 return (0);
1279 if (added) {
1280 if ((nname[0] == '/') &&
1281 (fpavl_insert(lml, nlmp,
1282 nname, 0) == 0))
1283 return (0);
1284 DBG_CALL(Dbg_file_skip(LIST(clmp),
1285 NAME(nlmp), nname));
1290 * Record in the file descriptor the existing object
1291 * that satisfies this open request.
1293 fdp->fd_lmp = nlmp;
1294 return (1);
1297 if ((fd = open(nname, O_RDONLY, 0)) == -1) {
1299 * As the file must exist for the previous stat() to
1300 * have succeeded, record the error condition.
1302 rej->rej_type = SGS_REJ_STR;
1303 rej->rej_str = strerror(errno);
1304 } else {
1306 * Map the object. A successful return indicates that
1307 * the object is appropriate for ld.so.1 processing.
1309 fdp->fd_ftp = map_obj(lml, fdp, status.st_size, nname,
1310 fd, FALSE, rej);
1311 (void) close(fd);
1313 if (fdp->fd_ftp != NULL) {
1314 fdp->fd_dev = status.st_dev;
1315 fdp->fd_ino = status.st_ino;
1316 return (1);
1320 } else if (errno != ENOENT) {
1322 * If the open() failed for anything other than the file not
1323 * existing, record the error condition.
1325 rej->rej_type = SGS_REJ_STR;
1326 rej->rej_str = strerror(errno);
1330 * Regardless of error, duplicate and record any full path names that
1331 * can't be used on the "not-found" AVL tree.
1333 if (nname[0] == '/')
1334 nfavl_insert(nname, nfavlwhere);
1337 * Indicate any rejection.
1339 if (rej->rej_type) {
1340 rej->rej_name = nname;
1341 if (fdp->fd_flags & FLG_FD_ALTER)
1342 rej->rej_flags = FLG_REJ_ALTER;
1343 DBG_CALL(Dbg_file_rejected(lml, rej, M_MACH));
1345 return (0);
1349 * Find a full pathname (it contains a "/").
1352 find_path(Lm_list *lml, Rt_map *clmp, uint_t flags, Fdesc *fdp, Rej_desc *rej,
1353 int *in_nfavl)
1355 const char *oname = fdp->fd_oname;
1356 int err = 0;
1359 * If directory configuration exists determine if this path is known.
1361 if (rtld_flags & RT_FL_DIRCFG) {
1362 Rtc_obj *obj;
1363 const char *aname;
1365 if ((obj = elf_config_ent(oname, (Word)elf_hash(oname),
1366 0, &aname)) != 0) {
1368 * If the configuration file states that this path is a
1369 * directory, or the path is explicitly defined as
1370 * non-existent (ie. a unused platform specific
1371 * library), then go no further.
1373 if (obj->co_flags & RTC_OBJ_DIRENT) {
1374 err = EISDIR;
1375 } else if ((obj->co_flags &
1376 (RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) ==
1377 RTC_OBJ_NOEXIST) {
1378 err = ENOENT;
1379 } else if ((obj->co_flags & RTC_OBJ_ALTER) &&
1380 (rtld_flags & RT_FL_OBJALT) && (lml == &lml_main)) {
1381 int ret;
1383 fdp->fd_flags |= FLG_FD_ALTER;
1384 fdp->fd_nname = aname;
1387 * Attempt to open the alternative path. If
1388 * this fails, and the alternative is flagged
1389 * as optional, fall through to open the
1390 * original path.
1392 DBG_CALL(Dbg_libs_found(lml, aname,
1393 FLG_FD_ALTER));
1394 ret = file_open(0, lml, clmp, flags, fdp,
1395 rej, in_nfavl);
1396 if (ret || ((obj->co_flags &
1397 RTC_OBJ_OPTINAL) == 0))
1398 return (ret);
1400 fdp->fd_flags &= ~FLG_FD_ALTER;
1404 DBG_CALL(Dbg_libs_found(lml, oname, 0));
1405 fdp->fd_nname = oname;
1406 return (file_open(err, lml, clmp, flags, fdp, rej, in_nfavl));
1410 * Find a simple filename (it doesn't contain a "/").
1412 static int
1413 _find_file(Lm_list *lml, Rt_map *clmp, uint_t flags, Fdesc *fdp, Rej_desc *rej,
1414 Pdesc *pdp, int aflag, int *in_nfavl)
1416 const char *nname = fdp->fd_nname;
1418 DBG_CALL(Dbg_libs_found(lml, nname, aflag));
1419 if ((lml->lm_flags & LML_FLG_TRC_SEARCH) &&
1420 ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0)) {
1421 (void) printf(MSG_INTL(MSG_LDD_PTH_TRYING), nname, aflag ?
1422 MSG_INTL(MSG_LDD_FIL_ALTER) : MSG_ORIG(MSG_STR_EMPTY));
1426 * If we're being audited tell the audit library of the file we're about
1427 * to go search for. The audit library may offer an alternative
1428 * dependency, or indicate that this dependency should be ignored.
1430 if ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_OBJSEARCH) {
1431 char *aname;
1433 if ((aname = audit_objsearch(clmp, nname,
1434 (pdp->pd_flags & LA_SER_MASK))) == NULL) {
1435 DBG_CALL(Dbg_audit_terminate(lml, nname));
1436 return (0);
1439 if (aname != nname) {
1440 fdp->fd_flags &= ~FLG_FD_SLASH;
1441 fdp->fd_nname = aname;
1444 return (file_open(0, lml, clmp, flags, fdp, rej, in_nfavl));
1447 static int
1448 find_file(Lm_list *lml, Rt_map *clmp, uint_t flags, Fdesc *fdp, Rej_desc *rej,
1449 Pdesc *pdp, Word *strhash, int *in_nfavl)
1451 static Rtc_obj Obj = { 0 };
1452 Rtc_obj *dobj;
1453 const char *oname = fdp->fd_oname;
1454 size_t olen = strlen(oname);
1456 if (pdp->pd_pname == NULL)
1457 return (0);
1458 if (pdp->pd_info) {
1459 dobj = (Rtc_obj *)pdp->pd_info;
1460 if ((dobj->co_flags &
1461 (RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) == RTC_OBJ_NOEXIST)
1462 return (0);
1463 } else
1464 dobj = NULL;
1467 * If configuration information exists see if this directory/file
1468 * combination exists.
1470 if ((rtld_flags & RT_FL_DIRCFG) &&
1471 ((dobj == NULL) || (dobj->co_id != 0))) {
1472 Rtc_obj *fobj;
1473 const char *aname = NULL;
1476 * If this object descriptor has not yet been searched for in
1477 * the configuration file go find it.
1479 if (dobj == NULL) {
1480 dobj = elf_config_ent(pdp->pd_pname,
1481 (Word)elf_hash(pdp->pd_pname), 0, 0);
1482 if (dobj == NULL)
1483 dobj = &Obj;
1484 pdp->pd_info = (void *)dobj;
1486 if ((dobj->co_flags & (RTC_OBJ_NOEXIST |
1487 RTC_OBJ_ALTER)) == RTC_OBJ_NOEXIST)
1488 return (0);
1492 * If we found a directory search for the file.
1494 if (dobj->co_id != 0) {
1495 if (*strhash == 0)
1496 *strhash = (Word)elf_hash(oname);
1497 fobj = elf_config_ent(oname, *strhash,
1498 dobj->co_id, &aname);
1501 * If this object specifically does not exist, or the
1502 * object can't be found in a know-all-entries
1503 * directory, continue looking. If the object does
1504 * exist determine if an alternative object exists.
1506 if (fobj == NULL) {
1507 if (dobj->co_flags & RTC_OBJ_ALLENTS)
1508 return (0);
1509 } else {
1510 if ((fobj->co_flags & (RTC_OBJ_NOEXIST |
1511 RTC_OBJ_ALTER)) == RTC_OBJ_NOEXIST)
1512 return (0);
1514 if ((fobj->co_flags & RTC_OBJ_ALTER) &&
1515 (rtld_flags & RT_FL_OBJALT) &&
1516 (lml == &lml_main)) {
1517 int ret;
1519 fdp->fd_flags |= FLG_FD_ALTER;
1520 fdp->fd_nname = aname;
1523 * Attempt to open the alternative path.
1524 * If this fails, and the alternative is
1525 * flagged as optional, fall through to
1526 * open the original path.
1528 ret = _find_file(lml, clmp, flags, fdp,
1529 rej, pdp, 1, in_nfavl);
1530 if (ret || ((fobj->co_flags &
1531 RTC_OBJ_OPTINAL) == 0))
1532 return (ret);
1534 fdp->fd_flags &= ~FLG_FD_ALTER;
1541 * Protect ourselves from building an invalid pathname.
1543 if ((olen + pdp->pd_plen + 1) >= PATH_MAX) {
1544 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), oname,
1545 strerror(ENAMETOOLONG));
1546 return (0);
1548 if ((fdp->fd_nname = (LM_GET_SO(clmp)(pdp->pd_pname, oname,
1549 pdp->pd_plen, olen))) == NULL)
1550 return (0);
1552 return (_find_file(lml, clmp, flags, fdp, rej, pdp, 0, in_nfavl));
1555 static Fct *Vector[] = {
1556 &elf_fct,
1557 #ifdef A_OUT
1558 &aout_fct,
1559 #endif
1564 * Remap the first page of a file to provide a better diagnostic as to why
1565 * an mmapobj(2) operation on this file failed. Sadly, mmapobj(), and all
1566 * system calls for that matter, only pass back a generic failure in errno.
1567 * Hopefully one day this will be improved, but in the mean time we repeat
1568 * the kernels ELF verification to try and provide more detailed information.
1570 static int
1571 map_fail(Fdesc *fdp, size_t fsize, const char *name, int fd, Rej_desc *rej)
1573 caddr_t addr;
1574 int vnum;
1575 size_t size;
1578 * Use the original file size to determine what to map, and catch the
1579 * obvious error of a zero sized file.
1581 if (fsize == 0) {
1582 rej->rej_type = SGS_REJ_UNKFILE;
1583 return (1);
1584 } else if (fsize < syspagsz)
1585 size = fsize;
1586 else
1587 size = syspagsz;
1589 if ((addr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
1590 return (0);
1592 rej->rej_type = 0;
1595 * Validate the file against each supported file type. Should a
1596 * characteristic of the file be found invalid for this platform, a
1597 * rejection message will have been recorded.
1599 for (vnum = 0; Vector[vnum]; vnum++) {
1600 if (((Vector[vnum]->fct_verify_file)(addr, size,
1601 fdp, name, rej) == 0) && rej->rej_type)
1602 break;
1606 * If no rejection message has been recorded, then this is simply an
1607 * unknown file type.
1609 if (rej->rej_type == 0)
1610 rej->rej_type = SGS_REJ_UNKFILE;
1612 (void) munmap(addr, size);
1613 return (1);
1617 * Unmap a file.
1619 void
1620 unmap_obj(mmapobj_result_t *mpp, uint_t mapnum)
1622 uint_t num;
1624 for (num = 0; num < mapnum; num++) {
1625 /* LINTED */
1626 (void) munmap((void *)(uintptr_t)mpp[num].mr_addr,
1627 mpp[num].mr_msize);
1629 cnt_unmap++;
1633 * Map a file.
1635 Fct *
1636 map_obj(Lm_list *lml, Fdesc *fdp, size_t fsize, const char *name, int fd,
1637 Boolean is_primary, Rej_desc *rej)
1639 static mmapobj_result_t *smpp = NULL;
1640 static uint_t smapnum;
1641 mmapobj_result_t *mpp;
1642 uint_t mnum, mapnum, mflags;
1643 void *padding;
1646 * Allocate an initial mapping array. The initial size should be large
1647 * enough to handle the normal ELF objects we come across.
1649 if (smpp == NULL) {
1650 smpp = malloc(sizeof (mmapobj_result_t) * MMAPFD_NUM);
1651 if (smpp == NULL)
1652 return (NULL);
1653 smapnum = MMAPFD_NUM;
1657 * If object padding is required, set the necessary flags.
1659 if (r_debug.rtd_objpad) {
1660 mflags = MMOBJ_INTERPRET | MMOBJ_PADDING;
1661 padding = &r_debug.rtd_objpad;
1662 } else {
1663 mflags = MMOBJ_INTERPRET;
1664 padding = NULL;
1667 if (is_primary)
1668 mflags |= MMOBJ_PRIMARY;
1671 * Map the file. If the number of mappings required by this file
1672 * exceeds the present mapping structure, an error indicating the
1673 * return data is too big is returned. Bail on any other error.
1675 mapnum = smapnum;
1676 if (mmapobj(fd, mflags, smpp, &mapnum, padding) == -1) {
1677 if (errno != E2BIG) {
1678 int err = errno;
1681 * An unsupported error indicates that there's something
1682 * incompatible with this ELF file, and the process that
1683 * is already running. Map the first page of the file
1684 * and see if we can generate a better error message.
1686 if ((errno == ENOTSUP) && map_fail(fdp, fsize, name,
1687 fd, rej))
1688 return (NULL);
1690 rej->rej_type = SGS_REJ_STR;
1691 rej->rej_str = strerror(err);
1692 return (NULL);
1696 * The mapping requirement exceeds the present mapping
1697 * structure, however the number of mapping required is
1698 * available in the mapping number.
1700 free((void *)smpp);
1701 if ((smpp = malloc(sizeof (mmapobj_result_t) * mapnum)) == NULL)
1702 return (NULL);
1703 smapnum = mapnum;
1706 * With the appropriate mapping structure, try the mapping
1707 * request again.
1709 if (mmapobj(fd, mflags, smpp, &mapnum, padding) == -1) {
1710 rej->rej_type = SGS_REJ_STR;
1711 rej->rej_str = strerror(errno);
1712 return (NULL);
1715 ASSERT(mapnum != 0);
1718 * Traverse the mappings in search of a file type ld.so.1 can process.
1719 * If the file type is verified as one ld.so.1 can process, retain the
1720 * mapping information, and the number of mappings this object uses,
1721 * and clear the static mapping pointer for the next map_obj() use of
1722 * mmapobj().
1724 DBG_CALL(Dbg_file_mmapobj(lml, name, smpp, mapnum));
1725 cnt_map++;
1727 for (mnum = 0, mpp = smpp; mnum < mapnum; mnum++, mpp++) {
1728 uint_t flags = (mpp->mr_flags & MR_TYPE_MASK);
1729 Fct *fptr = NULL;
1731 if (flags == MR_HDR_ELF) {
1732 fptr = elf_verify((mpp->mr_addr + mpp->mr_offset),
1733 mpp->mr_fsize, fdp, name, rej);
1735 #ifdef A_OUT
1736 if (flags == MR_HDR_AOUT) {
1737 fptr = aout_verify((mpp->mr_addr + mpp->mr_offset),
1738 mpp->mr_fsize, fdp, name, rej);
1740 #endif
1741 if (fptr) {
1742 fdp->fd_mapn = mapnum;
1743 fdp->fd_mapp = smpp;
1745 smpp = NULL;
1747 return (fptr);
1752 * If the mapped file is inappropriate, indicate that the file type is
1753 * unknown, and free the mapping.
1755 if (rej->rej_type == 0)
1756 rej->rej_type = SGS_REJ_UNKFILE;
1757 unmap_obj(smpp, mapnum);
1759 return (NULL);
1763 * A unique file has been opened. Create a link-map to represent it, and
1764 * process the various names by which it can be referenced.
1766 Rt_map *
1767 load_file(Lm_list *lml, Aliste lmco, Rt_map *clmp, Fdesc *fdp, int *in_nfavl)
1769 mmapobj_result_t *fpmpp = NULL, *fmpp = NULL, *lpmpp, *lmpp;
1770 mmapobj_result_t *hmpp, *mpp, *ompp = fdp->fd_mapp;
1771 uint_t mnum, omapnum = fdp->fd_mapn;
1772 const char *nname = fdp->fd_nname;
1773 Rt_map *nlmp;
1774 Ehdr *ehdr = NULL;
1777 * Traverse the mappings for the input file to capture generic mapping
1778 * information, and create a link-map to represent the file.
1780 for (mnum = 0, mpp = ompp; mnum < omapnum; mnum++, mpp++) {
1781 uint_t flags = (mpp->mr_flags & MR_TYPE_MASK);
1784 * Keep track of the first and last mappings that may include
1785 * padding.
1787 if (fpmpp == NULL)
1788 fpmpp = mpp;
1789 lpmpp = mpp;
1792 * Keep track of the first and last mappings that do not include
1793 * padding.
1795 if (flags != MR_PADDING) {
1796 if (fmpp == NULL)
1797 fmpp = mpp;
1798 lmpp = mpp;
1800 if (flags == MR_HDR_ELF) {
1801 /* LINTED */
1802 ehdr = (Ehdr *)(mpp->mr_addr + mpp->mr_offset);
1803 hmpp = mpp;
1804 } else if (flags == MR_HDR_AOUT)
1805 hmpp = mpp;
1809 * The only ELF files we can handle are ET_EXEC, ET_DYN, and ET_REL.
1811 * ET_REL must be processed by ld(1) to create an in-memory ET_DYN.
1812 * The initial processing carried out by elf_obj_file() creates a
1813 * temporary link-map, that acts as a place holder, until the objects
1814 * processing is finished with elf_obj_fini().
1816 if (ehdr && (ehdr->e_type == ET_REL)) {
1817 if ((nlmp = elf_obj_file(lml, lmco, clmp, nname, hmpp, ompp,
1818 omapnum)) == NULL)
1819 return (nlmp);
1820 } else {
1821 Addr addr;
1822 size_t msize;
1825 * The size of the total reservation, and the padding range,
1826 * are a historic artifact required by debuggers. Although
1827 * these values express the range of the associated mappings,
1828 * there can be holes between segments (in which small objects
1829 * could be mapped). Anyone who needs to verify offsets
1830 * against segments should analyze all the object mappings,
1831 * rather than relying on these address ranges.
1833 addr = (Addr)(hmpp->mr_addr + hmpp->mr_offset);
1834 msize = lmpp->mr_addr + lmpp->mr_msize - fmpp->mr_addr;
1836 if ((nlmp = ((fdp->fd_ftp)->fct_new_lmp)(lml, lmco, fdp, addr,
1837 msize, NULL, clmp, in_nfavl)) == NULL)
1838 return (NULL);
1841 * Save generic mapping information.
1843 MMAPS(nlmp) = ompp;
1844 MMAPCNT(nlmp) = omapnum;
1845 PADSTART(nlmp) = (ulong_t)fpmpp->mr_addr;
1846 PADIMLEN(nlmp) = lpmpp->mr_addr + lpmpp->mr_msize -
1847 fpmpp->mr_addr;
1851 * Save the dev/inode information for later comparisons, and identify
1852 * this as a new object.
1854 STDEV(nlmp) = fdp->fd_dev;
1855 STINO(nlmp) = fdp->fd_ino;
1856 FLAGS(nlmp) |= FLG_RT_NEWLOAD;
1859 * If this is ELF relocatable object, we're done for now.
1861 if (ehdr && (ehdr->e_type == ET_REL))
1862 return (nlmp);
1865 * Insert the names of this link-map into the FullPathNode AVL tree.
1866 * Save both the NAME() and PATHNAME() if the names differ.
1868 (void) fullpath(nlmp, fdp);
1870 if ((NAME(nlmp)[0] == '/') && (fpavl_insert(lml, nlmp, NAME(nlmp),
1871 fdp->fd_avlwhere) == 0)) {
1872 remove_so(lml, nlmp, clmp);
1873 return (NULL);
1875 if (((NAME(nlmp)[0] != '/') || (NAME(nlmp) != PATHNAME(nlmp))) &&
1876 (fpavl_insert(lml, nlmp, PATHNAME(nlmp), 0) == 0)) {
1877 remove_so(lml, nlmp, clmp);
1878 return (NULL);
1882 * If this is a secure application, record any full path name directory
1883 * in which this dependency has been found. This directory can be
1884 * deemed safe (as we've already found a dependency here). This
1885 * recording provides a fall-back should another objects $ORIGIN
1886 * definition expands to this directory, an expansion that would
1887 * ordinarily be deemed insecure.
1889 if (rtld_flags & RT_FL_SECURE) {
1890 if (NAME(nlmp)[0] == '/')
1891 spavl_insert(NAME(nlmp));
1892 if ((NAME(nlmp) != PATHNAME(nlmp)) &&
1893 (PATHNAME(nlmp)[0] == '/'))
1894 spavl_insert(PATHNAME(nlmp));
1898 * If we're processing an alternative object reset the original name
1899 * for possible $ORIGIN processing.
1901 if (fdp->fd_flags & FLG_FD_ALTER) {
1902 const char *odir, *ndir;
1903 size_t olen;
1905 FLAGS(nlmp) |= FLG_RT_ALTER;
1908 * If we were given a pathname containing a slash then the
1909 * original name is still in oname. Otherwise the original
1910 * directory is in dir->p_name (which is all we need for
1911 * $ORIGIN).
1913 if (fdp->fd_flags & FLG_FD_SLASH) {
1914 char *ofil;
1916 odir = fdp->fd_oname;
1917 ofil = strrchr(fdp->fd_oname, '/');
1918 olen = ofil - odir + 1;
1919 } else {
1920 odir = fdp->fd_odir;
1921 olen = strlen(odir) + 1;
1923 if ((ndir = stravl_insert(odir, 0, olen, 1)) == NULL) {
1924 remove_so(lml, nlmp, clmp);
1925 return (NULL);
1927 ORIGNAME(nlmp) = ndir;
1928 DIRSZ(nlmp) = --olen;
1931 return (nlmp);
1935 * This function loads the named file and returns a pointer to its link map.
1936 * It is assumed that the caller has already checked that the file is not
1937 * already loaded before calling this function (refer is_so_loaded()).
1938 * Find and open the file, map it into memory, add it to the end of the list
1939 * of link maps and return a pointer to the new link map. Return 0 on error.
1941 static Rt_map *
1942 load_so(Lm_list *lml, Aliste lmco, Rt_map *clmp, uint_t flags,
1943 Fdesc *fdp, Rej_desc *rej, int *in_nfavl)
1945 const char *oname = fdp->fd_oname;
1946 Pdesc *pdp;
1949 * If this path name hasn't already been identified as containing a
1950 * slash, check the path name. Most paths have been constructed
1951 * through appending a file name to a search path, and/or have been
1952 * inspected by expand(), and thus have a slash. However, we can
1953 * receive path names via auditors or configuration files, and thus
1954 * an evaluation here catches these instances.
1956 if ((fdp->fd_flags & FLG_FD_SLASH) == 0) {
1957 const char *str;
1959 for (str = oname; *str; str++) {
1960 if (*str == '/') {
1961 fdp->fd_flags |= FLG_FD_SLASH;
1962 break;
1968 * If we are passed a 'null' link-map this means that this is the first
1969 * object to be loaded on this link-map list. In that case we set the
1970 * link-map to ld.so.1's link-map.
1972 * This link-map is referenced to determine what lookup rules to use
1973 * when searching for files. By using ld.so.1's we are defaulting to
1974 * ELF look-up rules.
1976 * Note: This case happens when loading the first object onto
1977 * the plt_tracing link-map.
1979 if (clmp == 0)
1980 clmp = lml_rtld.lm_head;
1983 * If this path resulted from a $CAPABILITY specification, then the
1984 * best capability object has already been establish, and is available
1985 * in the calling file descriptor. Perform some minor book-keeping so
1986 * that we can fall through into common code.
1988 if (flags & FLG_RT_CAP) {
1990 * If this object is already loaded, we're done.
1992 if (fdp->fd_lmp)
1993 return (fdp->fd_lmp);
1996 * Obtain the avl index for this object.
1998 (void) fpavl_recorded(lml, fdp->fd_nname, 0,
1999 &(fdp->fd_avlwhere));
2001 } else if (fdp->fd_flags & FLG_FD_SLASH) {
2002 Rej_desc _rej = { 0 };
2004 if (find_path(lml, clmp, flags, fdp, &_rej, in_nfavl) == 0) {
2005 rejection_inherit(rej, &_rej);
2006 return (NULL);
2010 * If this object is already loaded, we're done.
2012 if (fdp->fd_lmp)
2013 return (fdp->fd_lmp);
2015 } else {
2017 * No '/' - for each directory on list, make a pathname using
2018 * that directory and filename and try to open that file.
2020 Spath_desc sd = { search_rules, NULL, 0 };
2021 Word strhash = 0;
2022 int found = 0;
2025 * Traverse the search path lists, creating full pathnames and
2026 * attempt to load each path.
2028 for (pdp = get_next_dir(&sd, clmp, flags); pdp;
2029 pdp = get_next_dir(&sd, clmp, flags)) {
2030 Rej_desc _rej = { 0 };
2031 Fdesc fd = { 0 };
2034 * Under debugging, duplicate path name entries are
2035 * tagged but remain part of the search path list so
2036 * that they can be diagnosed under "unused" processing.
2037 * Skip these entries, as this path would have already
2038 * been attempted.
2040 if (pdp->pd_flags & PD_FLG_DUPLICAT)
2041 continue;
2043 fd = *fdp;
2046 * Try and locate this file. Make sure to clean up
2047 * any rejection information should the file have
2048 * been found, but not appropriate.
2050 if (find_file(lml, clmp, flags, &fd, &_rej, pdp,
2051 &strhash, in_nfavl) == 0) {
2052 rejection_inherit(rej, &_rej);
2053 continue;
2057 * Indicate that this search path has been used. If
2058 * this is an LD_LIBRARY_PATH setting, ignore any use
2059 * by ld.so.1 itself.
2061 if (((pdp->pd_flags & LA_SER_LIBPATH) == 0) ||
2062 ((lml->lm_flags & LML_FLG_RTLDLM) == 0))
2063 pdp->pd_flags |= PD_FLG_USED;
2066 * If this object is already loaded, we're done.
2068 *fdp = fd;
2069 if (fdp->fd_lmp)
2070 return (fdp->fd_lmp);
2072 fdp->fd_odir = pdp->pd_pname;
2073 found = 1;
2074 break;
2078 * If the file couldn't be loaded, do another comparison of
2079 * loaded files using just the basename. This catches folks
2080 * who may have loaded multiple full pathname files (possibly
2081 * from setxid applications) to satisfy dependency relationships
2082 * (i.e., a file might have a dependency on foo.so.1 which has
2083 * already been opened using its full pathname).
2085 if (found == 0)
2086 return (is_so_loaded(lml, oname, in_nfavl));
2090 * Trace that this successfully opened file is about to be processed.
2091 * Note, as part of processing a family of hardware capabilities filtees
2092 * a number of candidates may have been opened and mapped to determine
2093 * their capability requirements. At this point we've decided which
2094 * of the candidates to use.
2096 if (lml->lm_flags & LML_FLG_TRC_ENABLE) {
2097 trace_so(clmp, 0, fdp->fd_oname, fdp->fd_nname,
2098 (fdp->fd_flags & FLG_FD_ALTER), 0);
2102 * Finish mapping the file and return the link-map descriptor.
2104 return (load_file(lml, lmco, clmp, fdp, in_nfavl));
2108 * Trace an attempt to load an object, and seed the originating name.
2110 const char *
2111 load_trace(Lm_list *lml, Pdesc *pdp, Rt_map *clmp, Fdesc *fdp)
2113 const char *name = pdp->pd_pname;
2115 DBG_CALL(Dbg_libs_find(lml, name));
2118 * First generate any ldd(1) diagnostics.
2120 if ((lml->lm_flags & (LML_FLG_TRC_VERBOSE | LML_FLG_TRC_SEARCH)) &&
2121 ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0))
2122 (void) printf(MSG_INTL(MSG_LDD_FIL_FIND), name, NAME(clmp));
2125 * Propagate any knowledge of a slash within the path name.
2127 if (pdp->pd_flags & PD_FLG_PNSLASH)
2128 fdp->fd_flags |= FLG_FD_SLASH;
2131 * If we're being audited tell any audit libraries of the file we're
2132 * about to go search for.
2134 if (aud_activity ||
2135 ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_ACTIVITY))
2136 audit_activity(clmp, LA_ACT_ADD);
2138 if ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_OBJSEARCH) {
2139 char *aname;
2142 * The auditor can indicate that this object should be ignored.
2144 if ((aname =
2145 audit_objsearch(clmp, name, LA_SER_ORIG)) == NULL) {
2146 DBG_CALL(Dbg_audit_terminate(lml, name));
2147 return (NULL);
2150 if (name != aname) {
2151 fdp->fd_flags &= ~FLG_FD_SLASH;
2152 name = aname;
2155 fdp->fd_oname = name;
2156 return (name);
2160 * Having loaded an object and created a link-map to describe it, finish
2161 * processing this stage, including verifying any versioning requirements,
2162 * updating the objects mode, creating a handle if necessary, and adding this
2163 * object to existing handles if required.
2165 static int
2166 load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
2167 uint_t flags, Grp_hdl **hdl, Rt_map *nlmp)
2169 Aliste idx1;
2170 Grp_hdl *ghp;
2171 int promote;
2172 uint_t rdflags;
2175 * If this dependency is associated with a required version ensure that
2176 * the version is present in the loaded file.
2178 if (((rtld_flags & RT_FL_NOVERSION) == 0) && THIS_IS_ELF(clmp) &&
2179 VERNEED(clmp) && (elf_verify_vers(name, clmp, nlmp) == 0))
2180 return (0);
2183 * If this object has indicated that it should be isolated as a group
2184 * (DT_FLAGS_1 contains DF_1_GROUP - object was built with -B group),
2185 * or if the callers direct bindings indicate it should be isolated as
2186 * a group (DYNINFO flags contains FLG_DI_GROUP - dependency following
2187 * -zgroupperm), establish the appropriate mode.
2189 * The intent of an object defining itself as a group is to isolate the
2190 * relocation of the group within its own members, however, unless
2191 * opened through dlopen(), in which case we assume dlsym() will be used
2192 * to locate symbols in the new object, we still need to associate the
2193 * new object with the caller so that the caller can bind to this new
2194 * object. This is equivalent to a dlopen(RTLD_GROUP) and dlsym()
2195 * using the returned handle.
2197 if ((FLAGS(nlmp) | flags) & FLG_RT_SETGROUP) {
2198 nmode &= ~RTLD_WORLD;
2199 nmode |= RTLD_GROUP;
2202 * If the object wasn't explicitly dlopen()'ed, in which case a
2203 * handle would have been requested, associate the object with
2204 * the parent.
2206 if ((flags & FLG_RT_PUBHDL) == 0)
2207 nmode |= RTLD_PARENT;
2211 * Establish new mode and flags.
2213 promote = update_mode(nlmp, MODE(nlmp), nmode);
2214 FLAGS(nlmp) |= flags;
2217 * Establish the flags for any referenced dependency descriptors
2218 * (Grp_desc).
2220 * - The referenced object is available for dlsym().
2221 * - The referenced object is available to relocate against.
2222 * - The referenced object should have it's dependencies
2223 * added to this handle
2225 rdflags = (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS);
2228 * If we've been asked to establish a handle create one for this object.
2229 * Or, if this object has already been analyzed, but this reference
2230 * requires that the mode of the object be promoted, create a private
2231 * handle to propagate the new modes to all this objects dependencies.
2233 if ((FLAGS(nlmp) & (FLG_RT_PUBHDL | FLG_RT_PRIHDL)) ||
2234 (promote && (FLAGS(nlmp) & FLG_RT_ANALYZED))) {
2235 uint_t oflags, hflags, cdflags = 0;
2238 * Establish any flags for the handle (Grp_hdl).
2240 * - Public handles establish dependencies between objects
2241 * that must be taken into account when dlclose()'ing
2242 * objects. Private handles provide for collecting
2243 * dependencies, but do not affect dlclose(). Note that
2244 * a handle may already exist, but the public/private
2245 * state is set to trigger the required propagation of the
2246 * handle's flags and any dependency gathering.
2247 * - Use of the RTLD_FIRST flag indicates that only the first
2248 * dependency on the handle (the new object) can be used
2249 * to satisfy dlsym() requests.
2251 if (FLAGS(nlmp) & FLG_RT_PUBHDL)
2252 hflags = GPH_PUBLIC;
2253 else
2254 hflags = GPH_PRIVATE;
2256 if (nmode & RTLD_FIRST)
2257 hflags |= GPH_FIRST;
2260 * Establish the flags for this callers dependency descriptor
2261 * (Grp_desc).
2263 * - The creation of a public handle creates a descriptor
2264 * for the referenced object and the caller (parent).
2265 * Typically, the handle is created for dlopen() or for
2266 * filtering. A private handle does not need to maintain
2267 * a descriptor to the parent.
2268 * - Use of the RTLD_PARENT flag indicates that the parent
2269 * can be relocated against.
2271 if (FLAGS(nlmp) & FLG_RT_PUBHDL) {
2272 cdflags |= GPD_PARENT;
2273 if (nmode & RTLD_PARENT)
2274 cdflags |= GPD_RELOC;
2278 * Now that the handle flags have been established, remove any
2279 * handle definition from the referenced object so that the
2280 * definitions don't mistakenly get inherited by a dependency.
2282 oflags = FLAGS(nlmp);
2283 FLAGS(nlmp) &= ~(FLG_RT_PUBHDL | FLG_RT_PRIHDL);
2285 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ADD));
2286 if ((ghp = hdl_create(lml, nlmp, clmp, hflags, rdflags,
2287 cdflags)) == NULL)
2288 return (0);
2291 * Add any dependencies that are already loaded, to the handle.
2293 if (hdl_initialize(ghp, nlmp, nmode, promote) == 0)
2294 return (0);
2296 if (hdl)
2297 *hdl = ghp;
2300 * If we were asked to create a public handle, we're done.
2302 * If this is a private handle request, then the handle is left
2303 * intact with a GPH_PRIVATE identifier. This handle is a
2304 * convenience for processing the dependencies of this object,
2305 * but does not affect how this object might be dlclose()'d.
2306 * For a private handle, fall through to carry out any group
2307 * processing.
2309 if (oflags & FLG_RT_PUBHDL)
2310 return (1);
2314 * If the caller isn't part of a group we're done.
2316 if (GROUPS(clmp) == NULL)
2317 return (1);
2320 * Determine if our caller is already associated with a handle, if so
2321 * we need to add this object to any handles that already exist.
2322 * Traverse the list of groups our caller is a member of and add this
2323 * new link-map to those groups.
2325 for (APLIST_TRAVERSE(GROUPS(clmp), idx1, ghp)) {
2326 Aliste idx2;
2327 Grp_desc *gdp;
2328 int ale;
2329 Rt_map *dlmp1;
2330 APlist *lmalp = NULL;
2332 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ADD));
2335 * If the caller doesn't indicate that its dependencies should
2336 * be added to a handle, ignore it. This case identifies a
2337 * parent of a dlopen(RTLD_PARENT) request.
2339 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
2340 if (gdp->gd_depend == clmp)
2341 break;
2343 if ((gdp->gd_flags & GPD_ADDEPS) == 0)
2344 continue;
2346 if ((gdp = hdl_add(ghp, nlmp, rdflags, &ale)) == NULL)
2347 return (0);
2350 * If this member already exists then its dependencies will
2351 * have already been processed.
2353 if (ale == ALE_EXISTS)
2354 continue;
2357 * If the object we've added has just been opened, it will not
2358 * yet have been processed for its dependencies, these will be
2359 * added on later calls to load_one(). If it doesn't have any
2360 * dependencies we're also done.
2362 if (((FLAGS(nlmp) & FLG_RT_ANALYZED) == 0) ||
2363 (DEPENDS(nlmp) == NULL))
2364 continue;
2367 * Otherwise, this object exists and has dependencies, so add
2368 * all of its dependencies to the handle were operating on.
2370 if (aplist_append(&lmalp, nlmp, AL_CNT_DEPCLCT) == NULL)
2371 return (0);
2373 for (APLIST_TRAVERSE(lmalp, idx2, dlmp1)) {
2374 Aliste idx3;
2375 Bnd_desc *bdp;
2378 * Add any dependencies of this dependency to the
2379 * dynamic dependency list so they can be further
2380 * processed.
2382 for (APLIST_TRAVERSE(DEPENDS(dlmp1), idx3, bdp)) {
2383 Rt_map *dlmp2 = bdp->b_depend;
2385 if ((bdp->b_flags & BND_NEEDED) == 0)
2386 continue;
2388 if (aplist_test(&lmalp, dlmp2,
2389 AL_CNT_DEPCLCT) == 0) {
2390 free(lmalp);
2391 return (0);
2395 if (nlmp == dlmp1)
2396 continue;
2398 if ((gdp =
2399 hdl_add(ghp, dlmp1, rdflags, &ale)) == NULL) {
2400 free(lmalp);
2401 return (0);
2404 if (ale == ALE_CREATE)
2405 (void) update_mode(dlmp1, MODE(dlmp1), nmode);
2407 free(lmalp);
2409 return (1);
2413 * The central routine for loading shared objects. Insures ldd() diagnostics,
2414 * handle creation, and any other related additions are all done in one place.
2416 Rt_map *
2417 load_path(Lm_list *lml, Aliste lmco, Rt_map *clmp, int nmode, uint_t flags,
2418 Grp_hdl **hdl, Fdesc *fdp, Rej_desc *rej, int *in_nfavl)
2420 const char *name = fdp->fd_oname;
2421 Rt_map *nlmp;
2423 if ((nmode & RTLD_NOLOAD) == 0) {
2424 int oin_nfavl;
2427 * Keep track of the number of not-found loads.
2429 if (in_nfavl)
2430 oin_nfavl = *in_nfavl;
2433 * If this isn't a noload request attempt to load the file.
2435 if ((nlmp = load_so(lml, lmco, clmp, flags, fdp, rej,
2436 in_nfavl)) == NULL)
2437 return (NULL);
2440 * If this file has been found, reset the not-found load count.
2441 * Although a search for this file might have inspected a number
2442 * of non-existent path names, the file has been found so there
2443 * is no need to accumulate a non-found count, as this may
2444 * trigger unnecessary fall back (retry) processing.
2446 if (in_nfavl)
2447 *in_nfavl = oin_nfavl;
2450 * If we've loaded a library which identifies itself as not
2451 * being dlopen()'able catch it here. Let non-dlopen()'able
2452 * objects through under RTLD_CONFGEN as they're only being
2453 * mapped to be dldump()'ed.
2455 if ((rtld_flags & RT_FL_APPLIC) && ((FLAGS(nlmp) &
2456 (FLG_RT_NOOPEN | FLG_RT_RELOCED)) == FLG_RT_NOOPEN) &&
2457 ((nmode & RTLD_CONFGEN) == 0)) {
2458 Rej_desc _rej = { 0 };
2460 _rej.rej_name = name;
2461 _rej.rej_type = SGS_REJ_STR;
2462 _rej.rej_str = MSG_INTL(MSG_GEN_NOOPEN);
2463 DBG_CALL(Dbg_file_rejected(lml, &_rej, M_MACH));
2464 rejection_inherit(rej, &_rej);
2465 remove_so(lml, nlmp, clmp);
2466 return (NULL);
2468 } else {
2470 * If it's a NOLOAD request - check to see if the object
2471 * has already been loaded.
2473 /* LINTED */
2474 if (nlmp = is_so_loaded(lml, name, in_nfavl)) {
2475 if ((lml->lm_flags & LML_FLG_TRC_VERBOSE) &&
2476 ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0)) {
2477 (void) printf(MSG_INTL(MSG_LDD_FIL_FIND), name,
2478 NAME(clmp));
2479 /* BEGIN CSTYLED */
2480 if (*name == '/')
2481 (void) printf(MSG_ORIG(MSG_LDD_FIL_PATH),
2482 name, MSG_ORIG(MSG_STR_EMPTY),
2483 MSG_ORIG(MSG_STR_EMPTY));
2484 else
2485 (void) printf(MSG_ORIG(MSG_LDD_FIL_EQUIV),
2486 name, NAME(nlmp),
2487 MSG_ORIG(MSG_STR_EMPTY),
2488 MSG_ORIG(MSG_STR_EMPTY));
2489 /* END CSTYLED */
2491 } else {
2492 Rej_desc _rej = { 0 };
2494 _rej.rej_name = name;
2495 _rej.rej_type = SGS_REJ_STR;
2496 _rej.rej_str = strerror(ENOENT);
2497 DBG_CALL(Dbg_file_rejected(lml, &_rej, M_MACH));
2498 rejection_inherit(rej, &_rej);
2499 return (NULL);
2504 * Finish processing this loaded object.
2506 if (load_finish(lml, name, clmp, nmode, flags, hdl, nlmp) == 0) {
2507 FLAGS(nlmp) &= ~FLG_RT_NEWLOAD;
2510 * If this object has already been analyzed, then it is in use,
2511 * so even though this operation has failed, it should not be
2512 * torn down.
2514 if ((FLAGS(nlmp) & FLG_RT_ANALYZED) == 0)
2515 remove_so(lml, nlmp, clmp);
2516 return (NULL);
2520 * If this object is new, and we're being audited, tell the audit
2521 * libraries of the file we've just opened. Note, if the new link-map
2522 * requires local auditing of its dependencies we also register its
2523 * opening.
2525 if (FLAGS(nlmp) & FLG_RT_NEWLOAD) {
2526 FLAGS(nlmp) &= ~FLG_RT_NEWLOAD;
2528 if ((lml->lm_tflags | AFLAGS(clmp) | AFLAGS(nlmp)) &
2529 LML_TFLG_AUD_MASK) {
2530 if (audit_objopen(clmp, nlmp) == 0) {
2531 remove_so(lml, nlmp, clmp);
2532 return (NULL);
2536 return (nlmp);
2540 * Load one object from a possible list of objects. Typically, for requests
2541 * such as NEEDED's, only one object is specified. However, this object could
2542 * be specified using $ISALIST or $CAPABILITY, in which case only the first
2543 * object that can be loaded is used (ie. the best).
2545 Rt_map *
2546 load_one(Lm_list *lml, Aliste lmco, Alist *palp, Rt_map *clmp, int mode,
2547 uint_t flags, Grp_hdl **hdl, int *in_nfavl)
2549 Rej_desc rej = { 0 };
2550 Aliste idx;
2551 Pdesc *pdp;
2552 const char *name;
2554 for (ALIST_TRAVERSE(palp, idx, pdp)) {
2555 Rt_map *lmp = NULL;
2558 * A $CAPABILITY/$HWCAP requirement can expand into a number of
2559 * candidates.
2561 if (pdp->pd_flags & PD_TKN_CAP) {
2562 lmp = load_cap(lml, lmco, pdp->pd_pname, clmp,
2563 mode, (flags | FLG_RT_CAP), hdl, &rej, in_nfavl);
2564 } else {
2565 Fdesc fd = { 0 };
2568 * Trace the inspection of this file, determine any
2569 * auditor substitution, and seed the file descriptor
2570 * with the originating name.
2572 if (load_trace(lml, pdp, clmp, &fd) == NULL)
2573 continue;
2576 * Locate and load the file.
2578 lmp = load_path(lml, lmco, clmp, mode, flags, hdl, &fd,
2579 &rej, in_nfavl);
2581 if (lmp)
2582 return (lmp);
2586 * If no objects can be found, use the first path name from the Alist
2587 * to provide a diagnostic. If this pathname originated from an
2588 * expanded token, use the original name for any diagnostic output.
2590 pdp = alist_item(palp, 0);
2592 if ((name = pdp->pd_oname) == 0)
2593 name = pdp->pd_pname;
2595 file_notfound(lml, name, clmp, flags, &rej);
2596 return (NULL);
2600 * Determine whether a symbol is defined as an interposer.
2603 is_sym_interposer(Rt_map *lmp, Sym *sym)
2605 Syminfo *sip = SYMINFO(lmp);
2607 if (sip) {
2608 ulong_t ndx;
2610 ndx = (((ulong_t)sym - (ulong_t)SYMTAB(lmp)) / SYMENT(lmp));
2611 /* LINTED */
2612 sip = (Syminfo *)((char *)sip + (ndx * SYMINENT(lmp)));
2613 if (sip->si_flags & SYMINFO_FLG_INTERPOSE)
2614 return (1);
2616 return (0);
2620 * While processing direct or group bindings, determine whether the object to
2621 * which we've bound can be interposed upon. In this context, copy relocations
2622 * are a form of interposition.
2624 static int
2625 lookup_sym_interpose(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl)
2627 Rt_map *lmp, *clmp, *dlmp = srp->sr_dmap;
2628 Sym *osym = srp->sr_sym;
2629 Slookup sl;
2630 Lm_list *lml;
2633 * If we've bound to a copy relocation definition then we need to assign
2634 * this binding to the original copy reference. Fabricate an inter-
2635 * position diagnostic, as this is a legitimate form of interposition.
2637 if (osym && (FLAGS1(dlmp) & FL1_RT_COPYTOOK)) {
2638 Rel_copy *rcp;
2639 Aliste idx;
2641 for (ALIST_TRAVERSE(COPY_R(dlmp), idx, rcp)) {
2642 if ((osym == rcp->r_dsym) || (osym->st_value &&
2643 (osym->st_value == rcp->r_dsym->st_value))) {
2644 srp->sr_dmap = rcp->r_rlmp;
2645 srp->sr_sym = rcp->r_rsym;
2646 *binfo |=
2647 (DBG_BINFO_INTERPOSE | DBG_BINFO_COPYREF);
2648 return (1);
2654 * If a symbol binding has been established, inspect the link-map list
2655 * of the destination object, otherwise use the link-map list of the
2656 * original caller.
2658 if (osym)
2659 clmp = dlmp;
2660 else
2661 clmp = slp->sl_cmap;
2663 lml = LIST(clmp);
2664 lmp = lml->lm_head;
2667 * Prior to Solaris 8, external references from an executable that were
2668 * bound to an uninitialized variable (.bss) within a shared object did
2669 * not establish a copy relocation. This was thought to be an
2670 * optimization, to prevent copying zero's to zero's. Typically,
2671 * interposition took its course, with the shared object binding to the
2672 * executables data definition.
2674 * This scenario can be broken when this old executable runs against a
2675 * new shared object that is directly bound. With no copy-relocation
2676 * record, ld.so.1 has no data to trigger the normal vectoring of the
2677 * binding to the executable.
2679 * Starting with Solaris 8, a DT_FLAGS entry is written to all objects,
2680 * regardless of there being any DF_ flags entries. Therefore, an
2681 * object without this dynamic tag is susceptible to the copy relocation
2682 * issue. If the executable has no DT_FLAGS tag, and contains the same
2683 * .bss symbol definition as has been directly bound to, redirect the
2684 * binding to the executables data definition.
2686 if (osym && ((FLAGS1(lmp) & FL1_RT_DTFLAGS) == 0) &&
2687 (FCT(lmp) == &elf_fct) &&
2688 (ELF_ST_TYPE(osym->st_info) != STT_FUNC) &&
2689 are_bits_zero(dlmp, osym, 0)) {
2690 Sresult sr;
2693 * Initialize a local symbol result descriptor, using the
2694 * original symbol name. Initialize a local symbol lookup
2695 * descriptor, using the original lookup information, and a
2696 * new initial link-map.
2698 SRESULT_INIT(sr, slp->sl_name);
2699 sl = *slp;
2700 sl.sl_imap = lmp;
2703 * Determine whether the same symbol name exists within the
2704 * executable, that the size and type of symbol are the same,
2705 * and that the symbol is also associated with .bss.
2707 if (SYMINTP(lmp)(&sl, &sr, binfo, in_nfavl)) {
2708 Sym *isym = sr.sr_sym;
2710 if ((isym->st_size == osym->st_size) &&
2711 (isym->st_info == osym->st_info) &&
2712 are_bits_zero(lmp, isym, 1)) {
2713 *srp = sr;
2714 *binfo |=
2715 (DBG_BINFO_INTERPOSE | DBG_BINFO_COPYREF);
2716 return (1);
2721 if ((lml->lm_flags & LML_FLG_INTRPOSE) == 0)
2722 return (0);
2725 * Traverse the list of known interposers to determine whether any
2726 * offer the same symbol. Note, the head of the link-map could be
2727 * identified as an interposer. Otherwise, skip the head of the
2728 * link-map, so that we don't bind to any .plt references, or
2729 * copy-relocation destinations unintentionally.
2731 lmp = lml->lm_head;
2732 sl = *slp;
2734 if (((FLAGS(lmp) & MSK_RT_INTPOSE) == 0) || (sl.sl_flags & LKUP_COPY))
2735 lmp = NEXT_RT_MAP(lmp);
2737 for (; lmp; lmp = NEXT_RT_MAP(lmp)) {
2738 if (FLAGS(lmp) & FLG_RT_DELETE)
2739 continue;
2740 if ((FLAGS(lmp) & MSK_RT_INTPOSE) == 0)
2741 break;
2744 * If we had already bound to this object, there's no point in
2745 * searching it again, we're done.
2747 if (lmp == dlmp)
2748 break;
2751 * If this interposer can be inspected by the caller, look for
2752 * the symbol within the interposer.
2754 if (callable(clmp, lmp, 0, sl.sl_flags)) {
2755 Sresult sr;
2758 * Initialize a local symbol result descriptor, using
2759 * the original symbol name. Initialize a local symbol
2760 * lookup descriptor, using the original lookup
2761 * information, and a new initial link-map.
2763 SRESULT_INIT(sr, slp->sl_name);
2764 sl.sl_imap = lmp;
2766 if (SYMINTP(lmp)(&sl, &sr, binfo, in_nfavl)) {
2767 Sym *isym = sr.sr_sym;
2768 Rt_map *ilmp = sr.sr_dmap;
2771 * If this object provides individual symbol
2772 * interposers, make sure that the symbol we
2773 * have found is tagged as an interposer.
2775 if ((FLAGS(ilmp) & FLG_RT_SYMINTPO) &&
2776 (is_sym_interposer(ilmp, isym) == 0))
2777 continue;
2780 * Indicate this binding has occurred to an
2781 * interposer, and return the symbol.
2783 *srp = sr;
2784 *binfo |= DBG_BINFO_INTERPOSE;
2785 return (1);
2789 return (0);
2793 * If an object specifies direct bindings (it contains a syminfo structure
2794 * describing where each binding was established during link-editing, and the
2795 * object was built -Bdirect), then look for the symbol in the specific object.
2797 static int
2798 lookup_sym_direct(Slookup *slp, Sresult *srp, uint_t *binfo, Syminfo *sip,
2799 Rt_map *lmp, int *in_nfavl)
2801 Rt_map *dlmp, *clmp = slp->sl_cmap;
2802 int ret;
2803 Slookup sl;
2806 * If a direct binding resolves to the definition of a copy relocated
2807 * variable, it must be redirected to the copy (in the executable) that
2808 * will eventually be made. Typically, this redirection occurs in
2809 * lookup_sym_interpose(). But, there's an edge condition. If a
2810 * directly bound executable contains pic code, there may be a
2811 * reference to a definition that will eventually have a copy made.
2812 * However, this copy relocation may not yet have occurred, because
2813 * the relocation making this reference comes before the relocation
2814 * that will create the copy.
2815 * Under direct bindings, the syminfo indicates that a copy will be
2816 * taken (SYMINFO_FLG_COPY). This can only be set in an executable.
2817 * Thus, the caller must be the executable, so bind to the destination
2818 * of the copy within the executable.
2820 if (((slp->sl_flags & LKUP_COPY) == 0) &&
2821 (sip->si_flags & SYMINFO_FLG_COPY)) {
2822 slp->sl_imap = LIST(clmp)->lm_head;
2824 if (ret = SYMINTP(clmp)(slp, srp, binfo, in_nfavl))
2825 *binfo |= (DBG_BINFO_DIRECT | DBG_BINFO_COPYREF);
2826 return (ret);
2830 * If we need to directly bind to our parent, start looking in each
2831 * callers link map.
2833 sl = *slp;
2834 sl.sl_flags |= LKUP_DIRECT;
2835 ret = 0;
2837 if (sip->si_boundto == SYMINFO_BT_PARENT) {
2838 Aliste idx1;
2839 Bnd_desc *bdp;
2840 Grp_hdl *ghp;
2843 * Determine the parent of this explicit dependency from its
2844 * CALLERS()'s list.
2846 for (APLIST_TRAVERSE(CALLERS(clmp), idx1, bdp)) {
2847 sl.sl_imap = lmp = bdp->b_caller;
2848 if (ret = SYMINTP(lmp)(&sl, srp, binfo, in_nfavl))
2849 goto found;
2853 * A caller can also be defined as the parent of a dlopen()
2854 * call. Determine whether this object has any handles. The
2855 * dependencies maintained with the handle represent the
2856 * explicit dependencies of the dlopen()'ed object, and the
2857 * calling parent.
2859 for (APLIST_TRAVERSE(HANDLES(clmp), idx1, ghp)) {
2860 Grp_desc *gdp;
2861 Aliste idx2;
2863 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
2864 if ((gdp->gd_flags & GPD_PARENT) == 0)
2865 continue;
2866 sl.sl_imap = lmp = gdp->gd_depend;
2867 if (ret = SYMINTP(lmp)(&sl, srp, binfo,
2868 in_nfavl))
2869 goto found;
2872 } else {
2874 * If we need to direct bind to anything else look in the
2875 * link map associated with this symbol reference.
2877 if (sip->si_boundto == SYMINFO_BT_SELF)
2878 sl.sl_imap = lmp = clmp;
2879 else
2880 sl.sl_imap = lmp;
2882 if (lmp)
2883 ret = SYMINTP(lmp)(&sl, srp, binfo, in_nfavl);
2885 found:
2886 if (ret)
2887 *binfo |= DBG_BINFO_DIRECT;
2890 * If a reference to a directly bound symbol can't be satisfied, then
2891 * determine whether an interposer can provide the missing symbol. If
2892 * a reference to a directly bound symbol is satisfied, then determine
2893 * whether that object can be interposed upon for this symbol.
2895 dlmp = srp->sr_dmap;
2896 if ((ret == 0) || (dlmp && (LIST(dlmp)->lm_head != dlmp) &&
2897 (LIST(dlmp) == LIST(clmp)))) {
2898 if (lookup_sym_interpose(slp, srp, binfo, in_nfavl))
2899 return (1);
2902 return (ret);
2905 static int
2906 core_lookup_sym(Rt_map *ilmp, Slookup *slp, Sresult *srp, uint_t *binfo,
2907 Aliste off, int *in_nfavl)
2909 Rt_map *lmp;
2912 * Copy relocations should start their search after the head of the
2913 * main link-map control list.
2915 if ((off == ALIST_OFF_DATA) && (slp->sl_flags & LKUP_COPY) && ilmp)
2916 lmp = NEXT_RT_MAP(ilmp);
2917 else
2918 lmp = ilmp;
2920 for (; lmp; lmp = NEXT_RT_MAP(lmp)) {
2921 if (callable(slp->sl_cmap, lmp, 0, slp->sl_flags)) {
2923 slp->sl_imap = lmp;
2924 if ((SYMINTP(lmp)(slp, srp, binfo, in_nfavl)) ||
2925 (*binfo & BINFO_MSK_TRYAGAIN))
2926 return (1);
2929 return (0);
2932 static int
2933 rescan_lazy_find_sym(Rt_map *ilmp, Slookup *slp, Sresult *srp, uint_t *binfo,
2934 int *in_nfavl)
2936 Rt_map *lmp;
2938 for (lmp = ilmp; lmp; lmp = NEXT_RT_MAP(lmp)) {
2939 if (LAZY(lmp) == 0)
2940 continue;
2941 if (callable(slp->sl_cmap, lmp, 0, slp->sl_flags)) {
2943 slp->sl_imap = lmp;
2944 if (elf_lazy_find_sym(slp, srp, binfo, in_nfavl))
2945 return (1);
2948 return (0);
2951 static int
2952 _lookup_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl)
2954 const char *name = slp->sl_name;
2955 Rt_map *clmp = slp->sl_cmap;
2956 Lm_list *lml = LIST(clmp);
2957 Rt_map *ilmp = slp->sl_imap, *lmp;
2958 ulong_t rsymndx;
2959 int ret;
2960 Syminfo *sip;
2961 Slookup sl;
2964 * Search the initial link map for the required symbol (this category is
2965 * selected by dlsym(), where individual link maps are searched for a
2966 * required symbol. Therefore, we know we have permission to look at
2967 * the link map).
2969 if (slp->sl_flags & LKUP_FIRST)
2970 return (SYMINTP(ilmp)(slp, srp, binfo, in_nfavl));
2973 * Determine whether this lookup can be satisfied by an objects direct,
2974 * or lazy binding information. This is triggered by a relocation from
2975 * the object (hence rsymndx is set).
2977 if (((rsymndx = slp->sl_rsymndx) != 0) &&
2978 ((sip = SYMINFO(clmp)) != NULL)) {
2979 uint_t bound;
2982 * Find the corresponding Syminfo entry for the original
2983 * referencing symbol.
2985 /* LINTED */
2986 sip = (Syminfo *)((char *)sip + (rsymndx * SYMINENT(clmp)));
2987 bound = sip->si_boundto;
2990 * Identify any EXTERN or PARENT references for ldd(1).
2992 if ((lml->lm_flags & LML_FLG_TRC_WARN) &&
2993 (bound > SYMINFO_BT_LOWRESERVE)) {
2994 if (bound == SYMINFO_BT_PARENT)
2995 *binfo |= DBG_BINFO_REF_PARENT;
2996 if (bound == SYMINFO_BT_EXTERN)
2997 *binfo |= DBG_BINFO_REF_EXTERN;
3001 * If the symbol information indicates a direct binding,
3002 * determine the link map that is required to satisfy the
3003 * binding. Note, if the dependency can not be found, but a
3004 * direct binding isn't required, we will still fall through
3005 * to perform any default symbol search.
3007 if (sip->si_flags & SYMINFO_FLG_DIRECT) {
3009 lmp = 0;
3010 if (bound < SYMINFO_BT_LOWRESERVE)
3011 lmp = elf_lazy_load(clmp, slp, bound,
3012 name, 0, NULL, in_nfavl);
3015 * If direct bindings have been disabled, and this isn't
3016 * a translator, skip any direct binding now that we've
3017 * ensured the resolving object has been loaded.
3019 * If we need to direct bind to anything, we look in
3020 * ourselves, our parent, or in the link map we've just
3021 * loaded. Otherwise, even though we may have lazily
3022 * loaded an object we still continue to search for
3023 * symbols from the head of the link map list.
3025 if (((FLAGS(clmp) & FLG_RT_TRANS) ||
3026 (((lml->lm_tflags & LML_TFLG_NODIRECT) == 0) &&
3027 ((slp->sl_flags & LKUP_SINGLETON) == 0))) &&
3028 ((FLAGS1(clmp) & FL1_RT_DIRECT) ||
3029 (sip->si_flags & SYMINFO_FLG_DIRECTBIND))) {
3030 ret = lookup_sym_direct(slp, srp, binfo,
3031 sip, lmp, in_nfavl);
3034 * Determine whether this direct binding has
3035 * been rejected. If we've bound to a singleton
3036 * without following a singleton search, then
3037 * return. The caller detects this condition
3038 * and will trigger a new singleton search.
3040 * For any other rejection (such as binding to
3041 * a symbol labeled as nodirect - presumably
3042 * because the symbol definition has been
3043 * changed since the referring object was last
3044 * built), fall through to a standard symbol
3045 * search.
3047 if (((*binfo & BINFO_MSK_REJECTED) == 0) ||
3048 (*binfo & BINFO_MSK_TRYAGAIN))
3049 return (ret);
3051 *binfo &= ~BINFO_MSK_REJECTED;
3057 * Duplicate the lookup information, as we'll need to modify this
3058 * information for some of the following searches.
3060 sl = *slp;
3063 * If the referencing object has the DF_SYMBOLIC flag set, look in the
3064 * referencing object for the symbol first. Failing that, fall back to
3065 * our generic search.
3067 if ((FLAGS1(clmp) & FL1_RT_SYMBOLIC) &&
3068 ((sl.sl_flags & LKUP_SINGLETON) == 0)) {
3070 sl.sl_imap = clmp;
3071 if (SYMINTP(clmp)(&sl, srp, binfo, in_nfavl)) {
3072 Rt_map *dlmp = srp->sr_dmap;
3073 ulong_t dsymndx = (((ulong_t)srp->sr_sym -
3074 (ulong_t)SYMTAB(dlmp)) / SYMENT(dlmp));
3077 * Make sure this symbol hasn't explicitly been defined
3078 * as nodirect.
3080 if (((sip = SYMINFO(dlmp)) == 0) ||
3081 /* LINTED */
3082 ((sip = (Syminfo *)((char *)sip +
3083 (dsymndx * SYMINENT(dlmp)))) == 0) ||
3084 ((sip->si_flags & SYMINFO_FLG_NOEXTDIRECT) == 0))
3085 return (1);
3089 sl.sl_flags |= LKUP_STANDARD;
3092 * If this lookup originates from a standard relocation, then traverse
3093 * all link-map control lists, inspecting any object that is available
3094 * to this caller. Otherwise, traverse the link-map control list
3095 * associated with the caller.
3097 if (sl.sl_flags & LKUP_STDRELOC) {
3098 Aliste off;
3099 Lm_cntl *lmc;
3101 ret = 0;
3103 for (ALIST_TRAVERSE_BY_OFFSET(lml->lm_lists, off, lmc)) {
3104 if (((ret = core_lookup_sym(lmc->lc_head, &sl, srp,
3105 binfo, off, in_nfavl)) != 0) ||
3106 (*binfo & BINFO_MSK_TRYAGAIN))
3107 break;
3109 } else
3110 ret = core_lookup_sym(ilmp, &sl, srp, binfo, ALIST_OFF_DATA,
3111 in_nfavl);
3114 * If a symbol binding should be retried, return so that the search can
3115 * be repeated.
3117 if (*binfo & BINFO_MSK_TRYAGAIN)
3118 return (0);
3121 * To allow transitioning into a world of lazy loading dependencies see
3122 * if this link map contains objects that have lazy dependencies still
3123 * outstanding. If so, and we haven't been able to locate a non-weak
3124 * symbol reference, start bringing in any lazy dependencies to see if
3125 * the reference can be satisfied. Use of dlsym(RTLD_PROBE) sets the
3126 * LKUP_NOFALLBACK flag, and this flag disables this fall back.
3128 if ((ret == 0) && ((sl.sl_flags & LKUP_NOFALLBACK) == 0)) {
3129 if ((lmp = ilmp) == 0)
3130 lmp = LIST(clmp)->lm_head;
3132 lml = LIST(lmp);
3133 if ((sl.sl_flags & LKUP_WEAK) || (lml->lm_lazy == 0))
3134 return (0);
3136 DBG_CALL(Dbg_syms_lazy_rescan(lml, name));
3139 * If this request originated from a dlsym(RTLD_NEXT) then start
3140 * looking for dependencies from the caller, otherwise use the
3141 * initial link-map.
3143 if (sl.sl_flags & LKUP_NEXT)
3144 ret = rescan_lazy_find_sym(clmp, &sl, srp, binfo,
3145 in_nfavl);
3146 else {
3147 Aliste idx;
3148 Lm_cntl *lmc;
3150 for (ALIST_TRAVERSE(lml->lm_lists, idx, lmc)) {
3151 sl.sl_flags |= LKUP_NOFALLBACK;
3152 if (ret = rescan_lazy_find_sym(lmc->lc_head,
3153 &sl, srp, binfo, in_nfavl))
3154 break;
3158 return (ret);
3162 * Symbol lookup routine. Takes an ELF symbol name, and a list of link maps to
3163 * search. If successful, return a pointer to the symbol table entry, a
3164 * pointer to the link map of the enclosing object, and information relating
3165 * to the type of binding. Else return a null pointer.
3167 * To improve ELF performance, we first compute the ELF hash value and pass
3168 * it to each _lookup_sym() routine. The ELF function will use this value to
3169 * locate the symbol, the a.out function will simply ignore it.
3172 lookup_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl)
3174 Rt_map *clmp = slp->sl_cmap;
3175 Sym *rsym = slp->sl_rsym;
3176 uchar_t rtype = slp->sl_rtype, vis;
3177 int ret, mode;
3179 if (slp->sl_hash == 0)
3180 slp->sl_hash = elf_hash(slp->sl_name);
3181 *binfo = 0;
3183 if (rsym) {
3184 vis = ELF_ST_VISIBILITY(rsym->st_other);
3187 * Symbols that are defined as protected, or hidden, within an
3188 * object usually have any relocation references from within
3189 * the same object bound at link-edit time. Therefore, ld.so.1
3190 * is not involved. However, if a reference is to a
3191 * capabilities symbol, this reference must be resolved at
3192 * runtime. In this case look directly within the calling
3193 * object, and only within the calling object, for these
3194 * symbols. Note, an object may still use dlsym() to search
3195 * externally for a symbol which is defined as protected within
3196 * the same object.
3198 if ((rsym->st_shndx != SHN_UNDEF) &&
3199 ((slp->sl_flags & LKUP_DLSYM) == 0) &&
3200 ((vis == STV_PROTECTED) || (vis == STV_HIDDEN))) {
3201 slp->sl_imap = clmp;
3202 return (SYMINTP(clmp)(slp, srp, binfo, in_nfavl));
3206 * Establish any state that might be associated with a symbol
3207 * reference.
3209 if ((slp->sl_flags & LKUP_STDRELOC) &&
3210 (ELF_ST_BIND(rsym->st_info) == STB_WEAK))
3211 slp->sl_flags |= LKUP_WEAK;
3213 if (vis == STV_SINGLETON)
3214 slp->sl_flags |= LKUP_SINGLETON;
3218 * Establish any lookup state required for this type of relocation.
3220 if ((slp->sl_flags & LKUP_STDRELOC) && rtype) {
3221 if (rtype == M_R_COPY)
3222 slp->sl_flags |= LKUP_COPY;
3224 if (rtype != M_R_JMP_SLOT)
3225 slp->sl_flags |= LKUP_SPEC;
3229 * Under ldd -w, any unresolved weak references are diagnosed. Set the
3230 * symbol binding as global to trigger a relocation error if the symbol
3231 * can not be found.
3233 if (rsym) {
3234 if (LIST(slp->sl_cmap)->lm_flags & LML_FLG_TRC_NOUNRESWEAK)
3235 slp->sl_bind = STB_GLOBAL;
3236 else if ((slp->sl_bind = ELF_ST_BIND(rsym->st_info)) ==
3237 STB_WEAK)
3238 slp->sl_flags |= LKUP_WEAK;
3242 * Save the callers MODE().
3244 mode = MODE(clmp);
3247 * Carry out an initial symbol search. This search takes into account
3248 * all the modes of the requested search.
3250 if (((ret = _lookup_sym(slp, srp, binfo, in_nfavl)) == 0) &&
3251 (*binfo & BINFO_MSK_TRYAGAIN)) {
3252 Slookup sl = *slp;
3255 * Try the symbol search again. This retry can be necessary if:
3257 * - a binding has been rejected because of binding to a
3258 * singleton without going through a singleton search.
3259 * - a group binding has resulted in binding to a symbol
3260 * that indicates no-direct binding.
3262 * Reset the lookup data, and try again.
3264 sl.sl_imap = LIST(sl.sl_cmap)->lm_head;
3265 sl.sl_flags &= ~(LKUP_FIRST | LKUP_SELF | LKUP_NEXT);
3266 sl.sl_rsymndx = 0;
3268 if (*binfo & BINFO_REJSINGLE)
3269 sl.sl_flags |= LKUP_SINGLETON;
3270 if (*binfo & BINFO_REJGROUP) {
3271 sl.sl_flags |= LKUP_WORLD;
3272 mode |= RTLD_WORLD;
3274 *binfo &= ~BINFO_MSK_REJECTED;
3276 ret = _lookup_sym(&sl, srp, binfo, in_nfavl);
3280 * If the caller is restricted to a symbol search within its group,
3281 * determine if it is necessary to follow a binding from outside of
3282 * the group.
3284 if (((mode & (RTLD_GROUP | RTLD_WORLD)) == RTLD_GROUP) &&
3285 (lookup_sym_interpose(slp, srp, binfo, in_nfavl)))
3286 return (1);
3288 return (ret);
3292 * Associate a binding descriptor with a caller and its dependency, or update
3293 * an existing descriptor.
3296 bind_one(Rt_map *clmp, Rt_map *dlmp, uint_t flags)
3298 Bnd_desc *bdp;
3299 Aliste idx;
3300 int found = ALE_CREATE;
3303 * Determine whether a binding descriptor already exists between the
3304 * two objects.
3306 for (APLIST_TRAVERSE(DEPENDS(clmp), idx, bdp)) {
3307 if (bdp->b_depend == dlmp) {
3308 found = ALE_EXISTS;
3309 break;
3313 if (found == ALE_CREATE) {
3315 * Create a new binding descriptor.
3317 if ((bdp = malloc(sizeof (Bnd_desc))) == NULL)
3318 return (0);
3320 bdp->b_caller = clmp;
3321 bdp->b_depend = dlmp;
3322 bdp->b_flags = 0;
3325 * Append the binding descriptor to the caller and the
3326 * dependency.
3328 if (aplist_append(&DEPENDS(clmp), bdp, AL_CNT_DEPENDS) == NULL)
3329 return (0);
3331 if (aplist_append(&CALLERS(dlmp), bdp, AL_CNT_CALLERS) == NULL)
3332 return (0);
3335 if ((found == ALE_CREATE) || ((bdp->b_flags & flags) != flags)) {
3336 bdp->b_flags |= flags;
3338 if (flags & BND_REFER)
3339 FLAGS1(dlmp) |= FL1_RT_USED;
3341 DBG_CALL(Dbg_file_bind_entry(LIST(clmp), bdp));
3343 return (found);
3347 * Cleanup after relocation processing.
3350 relocate_finish(Rt_map *lmp, APlist *bound, int ret)
3352 DBG_CALL(Dbg_reloc_run(lmp, 0, ret, DBG_REL_FINISH));
3355 * Establish bindings to all objects that have been bound to.
3357 if (bound) {
3358 Rt_map *_lmp;
3359 Word used;
3362 * Only create bindings if the callers relocation was
3363 * successful (ret != 0), otherwise the object will eventually
3364 * be torn down. Create these bindings if running under ldd(1)
3365 * with the -U/-u options regardless of relocation errors, as
3366 * the unused processing needs to traverse these bindings to
3367 * diagnose unused objects.
3369 used = LIST(lmp)->lm_flags &
3370 (LML_FLG_TRC_UNREF | LML_FLG_TRC_UNUSED);
3372 if (ret || used) {
3373 Aliste idx;
3375 for (APLIST_TRAVERSE(bound, idx, _lmp)) {
3376 if (bind_one(lmp, _lmp, BND_REFER) || used)
3377 continue;
3379 ret = 0;
3380 break;
3383 free(bound);
3386 return (ret);
3390 * Function to correct protection settings. Segments are all mapped initially
3391 * with permissions as given in the segment header. We need to turn on write
3392 * permissions on a text segment if there are any relocations against that
3393 * segment, and then turn write permission back off again before returning
3394 * control to the caller. This function turns the permission on or off
3395 * depending on the value of the permission argument.
3398 set_prot(Rt_map *lmp, mmapobj_result_t *mpp, int perm)
3400 int prot;
3403 * If this is an allocated image (ie. a relocatable object) we can't
3404 * mprotect() anything.
3406 if (FLAGS(lmp) & FLG_RT_IMGALLOC)
3407 return (1);
3409 DBG_CALL(Dbg_file_prot(lmp, perm));
3411 if (perm)
3412 prot = mpp->mr_prot | PROT_WRITE;
3413 else
3414 prot = mpp->mr_prot & ~PROT_WRITE;
3416 if (mprotect((void *)(uintptr_t)mpp->mr_addr,
3417 mpp->mr_msize, prot) == -1) {
3418 int err = errno;
3419 eprintf(LIST(lmp), ERR_FATAL, MSG_INTL(MSG_SYS_MPROT),
3420 NAME(lmp), strerror(err));
3421 return (0);
3423 mpp->mr_prot = prot;
3424 return (1);