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]
23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Copyright (c) 1988 AT&T
36 #include <sys/debug.h>
48 #include "_inline_gen.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.
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
);
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
++) {
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
)))
85 (void) elf_lookup_filtee(&sl
, &sr
, &binfo
, cnt
,
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().
105 analyze_lmc(Lm_list
*lml
, Aliste nlmco
, Rt_map
*nlmp
, Rt_map
*clmp
,
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.
120 nlmc
= (Lm_cntl
*)alist_item_by_offset(lml
->lm_lists
, nlmco
);
121 if (nlmc
->lc_flags
& LMC_FLG_ANALYZING
)
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
))
133 nlmc
->lc_flags
|= LMC_FLG_ANALYZING
;
135 for (lmp
= nlmp
; lmp
; lmp
= NEXT_RT_MAP(lmp
)) {
137 (FLG_RT_ANALZING
| FLG_RT_ANALYZED
| FLG_RT_DELETE
))
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
) {
152 if ((olmp
= elf_obj_fini(lml
, lmp
, clmp
,
153 in_nfavl
)) == NULL
) {
154 if (lml
->lm_flags
& LML_FLG_TRC_ENABLE
)
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
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
)
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
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
;
219 nlmc
= (Lm_cntl
*)alist_item_by_offset(lml
->lm_lists
, nlmco
);
220 nlmc
->lc_flags
&= ~LMC_FLG_ANALYZING
;
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.
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)
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
)
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
))
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)
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
))
284 * Relocate an individual object.
287 relocate_so(Lm_list
*lml
, Rt_map
*lmp
, int *relocated
, int now
, int *in_nfavl
)
289 APlist
*textrel
= NULL
;
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
)) {
302 if ((LM_RELOC(lmp
)(lmp
, now
, in_nfavl
, &textrel
) == 0) &&
303 ((lml
->lm_flags
& LML_FLG_TRC_ENABLE
) == 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))
319 * If a text segment was write enabled to perform any relocations or
320 * move records, then re-protect the segment by disabling writes.
323 mmapobj_result_t
*mpp
;
326 for (APLIST_TRAVERSE(textrel
, idx
, mpp
))
327 (void) set_prot(lmp
, mpp
, 0);
335 * Relocate the objects on a link-map control list.
338 _relocate_lmc(Lm_list
*lml
, Aliste lmco
, Rt_map
*nlmp
, int *relocated
,
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.
350 (FLG_RT_RELOCING
| FLG_RT_RELOCED
| FLG_RT_DELETE
))
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)
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
379 * Note, even under ldd(1) this init identification is necessary
380 * for -i (tsort) gathering.
382 if (lmco
== ALIST_OFF_DATA
) {
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
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
))) {
411 if (elf_copy_gen(nlmp
) == 0)
414 if (COPY_S(nlmp
) == NULL
)
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
)))
424 DBG_CALL(Dbg_util_nl(lml
, DBG_NL_STD
));
426 for (APLIST_TRAVERSE(COPY_S(nlmp
), idx1
, lmp
)) {
430 for (ALIST_TRAVERSE(COPY_R(lmp
), idx2
, rcp
)) {
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
,
439 DBG_CALL(Dbg_reloc_copy(rcp
->r_dlmp
, nlmp
,
444 (void) memcpy(rcp
->r_radd
, rcp
->r_dadd
,
447 if ((tracing
== 0) || ((FLAGS1(rcp
->r_dlmp
) &
448 FL1_RT_DISPREL
) == 0))
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
));
465 relocate_lmc(Lm_list
*lml
, Aliste nlmco
, Rt_map
*clmp
, Rt_map
*nlmp
,
468 int lret
= 1, pret
= 1;
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.
482 nlmc
= (Lm_cntl
*)alist_item_by_offset(lml
->lm_lists
, nlmco
);
484 if (nlmc
->lc_flags
& LMC_FLG_RELOCATING
)
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
)) {
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.
541 nlmc
= (Lm_cntl
*)alist_item_by_offset(lml
->lm_lists
, nlmco
);
542 if (nlmco
== ALIST_OFF_DATA
) {
546 plmco
= nlmco
- lml
->lm_lists
->al_size
;
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
) {
576 * Remove the relocation promotion list, as performing more
577 * relocations may result in discovering more objects that need
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
589 if ((lret
== 0) || (pret
== 0)) {
590 MODE(lmp
) &= ~RTLD_NOW
;
591 MODE(lmp
) |= RTLD_LAZY
;
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)
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.
618 nlmc
= (Lm_cntl
*)alist_item_by_offset(lml
->lm_lists
, nlmco
);
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
);
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()).
634 nlmc
= (Lm_cntl
*)alist_item_by_offset(lml
->lm_lists
, nlmco
);
635 nlmc
->lc_flags
&= ~LMC_FLG_RELOCATING
;
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.
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
;
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.
685 _is_so_matched(const char *name
, const char *str
, int path
)
689 if ((path
== 0) && ((_str
= strrchr(str
, '/')) != NULL
))
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
)
736 if (_is_so_matched(name
, NAME(lmp
), path
) == 0)
739 if (PATHNAME(lmp
) != NAME(lmp
)) {
740 if (_is_so_matched(name
, PATHNAME(lmp
), path
) == 0)
744 for (APLIST_TRAVERSE(ALIAS(lmp
), idx
, cp
)) {
745 if (_is_so_matched(name
, cp
, path
) == 0)
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
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
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
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.
784 is_so_loaded(Lm_list
*lml
, const char *name
, int *in_nfavl
)
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))
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.
816 * Determine whether the name is a simple file name, or a path name.
818 if (strchr(name
, '/'))
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
))
829 if (is_so_matched(lmp
, name
, path
))
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.
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
)
860 * Without any rejection info, this is a supplied not-found condition.
862 if (rej
&& (rej
->rej_type
== 0)) {
863 (void) printf(nfound
, name
);
868 * If rejection information exists then establish what object was
869 * found and the reason for its rejection.
872 Conv_reject_desc_buf_t rej_buf
;
875 (void) snprintf(_reject
, PATH_MAX
,
876 MSG_INTL(ldd_reject
[rej
->rej_type
]),
877 conv_reject_desc(rej
, &rej_buf
, M_MACH
));
879 path
= rej
->rej_name
;
880 reject
= (char *)_reject
;
883 * Was an alternative pathname defined (from a configuration
886 if (rej
->rej_flags
& FLG_REJ_ALTER
)
887 str
= MSG_INTL(MSG_LDD_FIL_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.
898 (void) printf(MSG_ORIG(MSG_LDD_FIL_PATH
), path
, str
, reject
);
900 (void) printf(MSG_ORIG(MSG_LDD_FIL_EQUIV
), name
, path
, str
,
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
);
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
;
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
;
938 pmode
|= ((~omode
& nmode
) &
939 (RTLD_GLOBAL
| RTLD_WORLD
| RTLD_NODELETE
));
941 DBG_CALL(Dbg_file_mode_promote(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
))) {
957 lmc
= (Lm_cntl
*)alist_item_by_offset(LIST(lmp
)->lm_lists
,
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
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
;
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
)
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)
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
))
1022 * Determine whether a file is already loaded by comparing device and inode
1026 is_devinode_loaded(rtld_stat_t
*status
, Lm_list
*lml
, const char *name
,
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
) {
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
))
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
)) {
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
))
1066 if ((STDEV(nlmp
) != status
->st_dev
) ||
1067 (STINO(nlmp
) != status
->st_ino
))
1070 if (lml
->lm_flags
& LML_FLG_TRC_VERBOSE
) {
1073 (void) printf(MSG_ORIG(MSG_LDD_FIL_PATH
),
1074 name
, MSG_ORIG(MSG_STR_EMPTY
),
1075 MSG_ORIG(MSG_STR_EMPTY
));
1077 (void) printf(MSG_ORIG(MSG_LDD_FIL_EQUIV
),
1079 MSG_ORIG(MSG_STR_EMPTY
),
1080 MSG_ORIG(MSG_STR_EMPTY
));
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.
1096 file_notfound(Lm_list
*lml
, const char *name
, Rt_map
*clmp
, uint_t flags
,
1101 if ((rtld_flags
& RT_FL_SECURE
) &&
1102 (flags
& (FLG_RT_PRELOAD
| FLG_RT_AUDIT
)))
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))
1115 trace_so(clmp
, rej
, name
, 0, 0,
1116 MSG_INTL(MSG_LDD_SEC_NFOUND
));
1118 trace_so(clmp
, rej
, name
, 0, 0,
1119 MSG_INTL(MSG_LDD_FIL_NFOUND
));
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
));
1133 eprintf(lml
, ERR_FATAL
, MSG_INTL(MSG_SEC_OPEN
), name
);
1135 eprintf(lml
, ERR_FATAL
, MSG_INTL(MSG_SYS_OPEN
), name
,
1140 file_open(int err
, Lm_list
*lml
, Rt_map
*clmp
, uint_t flags
, Fdesc
*fdp
,
1141 Rej_desc
*rej
, int *in_nfavl
)
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
)
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
) {
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.
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
))
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
));
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)) {
1228 fdp
->fd_flags
|= FLG_FD_RESOLVED
;
1230 if (strcmp(nname
, path
)) {
1232 fpavl_recorded(lml
, path
, 0, 0)) != NULL
) {
1235 if (append_alias(nlmp
, nname
,
1240 DBG_CALL(Dbg_file_skip(LIST(clmp
),
1241 NAME(nlmp
), nname
));
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()
1253 if ((fdp
->fd_pname
= stravl_insert(path
, 0,
1254 (size
+ 1), 0)) == NULL
)
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
));
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.
1277 if (append_alias(nlmp
, nname
, &added
) == 0)
1280 if ((nname
[0] == '/') &&
1281 (fpavl_insert(lml
, nlmp
,
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.
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
);
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
,
1313 if (fdp
->fd_ftp
!= NULL
) {
1314 fdp
->fd_dev
= status
.st_dev
;
1315 fdp
->fd_ino
= status
.st_ino
;
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
));
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
,
1355 const char *oname
= fdp
->fd_oname
;
1359 * If directory configuration exists determine if this path is known.
1361 if (rtld_flags
& RT_FL_DIRCFG
) {
1365 if ((obj
= elf_config_ent(oname
, (Word
)elf_hash(oname
),
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
) {
1375 } else if ((obj
->co_flags
&
1376 (RTC_OBJ_NOEXIST
| RTC_OBJ_ALTER
)) ==
1379 } else if ((obj
->co_flags
& RTC_OBJ_ALTER
) &&
1380 (rtld_flags
& RT_FL_OBJALT
) && (lml
== &lml_main
)) {
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
1392 DBG_CALL(Dbg_libs_found(lml
, aname
,
1394 ret
= file_open(0, lml
, clmp
, flags
, fdp
,
1396 if (ret
|| ((obj
->co_flags
&
1397 RTC_OBJ_OPTINAL
) == 0))
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 "/").
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
) {
1433 if ((aname
= audit_objsearch(clmp
, nname
,
1434 (pdp
->pd_flags
& LA_SER_MASK
))) == NULL
) {
1435 DBG_CALL(Dbg_audit_terminate(lml
, nname
));
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
));
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 };
1453 const char *oname
= fdp
->fd_oname
;
1454 size_t olen
= strlen(oname
);
1456 if (pdp
->pd_pname
== NULL
)
1459 dobj
= (Rtc_obj
*)pdp
->pd_info
;
1460 if ((dobj
->co_flags
&
1461 (RTC_OBJ_NOEXIST
| RTC_OBJ_ALTER
)) == RTC_OBJ_NOEXIST
)
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))) {
1473 const char *aname
= NULL
;
1476 * If this object descriptor has not yet been searched for in
1477 * the configuration file go find it.
1480 dobj
= elf_config_ent(pdp
->pd_pname
,
1481 (Word
)elf_hash(pdp
->pd_pname
), 0, 0);
1484 pdp
->pd_info
= (void *)dobj
;
1486 if ((dobj
->co_flags
& (RTC_OBJ_NOEXIST
|
1487 RTC_OBJ_ALTER
)) == RTC_OBJ_NOEXIST
)
1492 * If we found a directory search for the file.
1494 if (dobj
->co_id
!= 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.
1507 if (dobj
->co_flags
& RTC_OBJ_ALLENTS
)
1510 if ((fobj
->co_flags
& (RTC_OBJ_NOEXIST
|
1511 RTC_OBJ_ALTER
)) == RTC_OBJ_NOEXIST
)
1514 if ((fobj
->co_flags
& RTC_OBJ_ALTER
) &&
1515 (rtld_flags
& RT_FL_OBJALT
) &&
1516 (lml
== &lml_main
)) {
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))
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
));
1548 if ((fdp
->fd_nname
= (LM_GET_SO(clmp
)(pdp
->pd_pname
, oname
,
1549 pdp
->pd_plen
, olen
))) == NULL
)
1552 return (_find_file(lml
, clmp
, flags
, fdp
, rej
, pdp
, 0, in_nfavl
));
1555 static Fct
*Vector
[] = {
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.
1571 map_fail(Fdesc
*fdp
, size_t fsize
, const char *name
, int fd
, Rej_desc
*rej
)
1578 * Use the original file size to determine what to map, and catch the
1579 * obvious error of a zero sized file.
1582 rej
->rej_type
= SGS_REJ_UNKFILE
;
1584 } else if (fsize
< syspagsz
)
1589 if ((addr
= mmap(NULL
, size
, PROT_READ
, MAP_PRIVATE
, fd
, 0)) == MAP_FAILED
)
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
)
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
);
1620 unmap_obj(mmapobj_result_t
*mpp
, uint_t mapnum
)
1624 for (num
= 0; num
< mapnum
; num
++) {
1626 (void) munmap((void *)(uintptr_t)mpp
[num
].mr_addr
,
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
;
1646 * Allocate an initial mapping array. The initial size should be large
1647 * enough to handle the normal ELF objects we come across.
1650 smpp
= malloc(sizeof (mmapobj_result_t
) * MMAPFD_NUM
);
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
;
1663 mflags
= MMOBJ_INTERPRET
;
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.
1676 if (mmapobj(fd
, mflags
, smpp
, &mapnum
, padding
) == -1) {
1677 if (errno
!= E2BIG
) {
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
,
1690 rej
->rej_type
= SGS_REJ_STR
;
1691 rej
->rej_str
= strerror(err
);
1696 * The mapping requirement exceeds the present mapping
1697 * structure, however the number of mapping required is
1698 * available in the mapping number.
1701 if ((smpp
= malloc(sizeof (mmapobj_result_t
) * mapnum
)) == NULL
)
1706 * With the appropriate mapping structure, try the mapping
1709 if (mmapobj(fd
, mflags
, smpp
, &mapnum
, padding
) == -1) {
1710 rej
->rej_type
= SGS_REJ_STR
;
1711 rej
->rej_str
= strerror(errno
);
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
1724 DBG_CALL(Dbg_file_mmapobj(lml
, name
, smpp
, mapnum
));
1727 for (mnum
= 0, mpp
= smpp
; mnum
< mapnum
; mnum
++, mpp
++) {
1728 uint_t flags
= (mpp
->mr_flags
& MR_TYPE_MASK
);
1731 if (flags
== MR_HDR_ELF
) {
1732 fptr
= elf_verify((mpp
->mr_addr
+ mpp
->mr_offset
),
1733 mpp
->mr_fsize
, fdp
, name
, rej
);
1736 if (flags
== MR_HDR_AOUT
) {
1737 fptr
= aout_verify((mpp
->mr_addr
+ mpp
->mr_offset
),
1738 mpp
->mr_fsize
, fdp
, name
, rej
);
1742 fdp
->fd_mapn
= mapnum
;
1743 fdp
->fd_mapp
= smpp
;
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
);
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.
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
;
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
1792 * Keep track of the first and last mappings that do not include
1795 if (flags
!= MR_PADDING
) {
1800 if (flags
== MR_HDR_ELF
) {
1802 ehdr
= (Ehdr
*)(mpp
->mr_addr
+ mpp
->mr_offset
);
1804 } else if (flags
== MR_HDR_AOUT
)
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
,
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
)
1841 * Save generic mapping information.
1844 MMAPCNT(nlmp
) = omapnum
;
1845 PADSTART(nlmp
) = (ulong_t
)fpmpp
->mr_addr
;
1846 PADIMLEN(nlmp
) = lpmpp
->mr_addr
+ lpmpp
->mr_msize
-
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
))
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
);
1875 if (((NAME(nlmp
)[0] != '/') || (NAME(nlmp
) != PATHNAME(nlmp
))) &&
1876 (fpavl_insert(lml
, nlmp
, PATHNAME(nlmp
), 0) == 0)) {
1877 remove_so(lml
, nlmp
, clmp
);
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
;
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
1913 if (fdp
->fd_flags
& FLG_FD_SLASH
) {
1916 odir
= fdp
->fd_oname
;
1917 ofil
= strrchr(fdp
->fd_oname
, '/');
1918 olen
= ofil
- odir
+ 1;
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
);
1927 ORIGNAME(nlmp
) = ndir
;
1928 DIRSZ(nlmp
) = --olen
;
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.
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
;
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) {
1959 for (str
= oname
; *str
; str
++) {
1961 fdp
->fd_flags
|= FLG_FD_SLASH
;
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.
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.
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
);
2010 * If this object is already loaded, we're done.
2013 return (fdp
->fd_lmp
);
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 };
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 };
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
2040 if (pdp
->pd_flags
& PD_FLG_DUPLICAT
)
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
);
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.
2070 return (fdp
->fd_lmp
);
2072 fdp
->fd_odir
= pdp
->pd_pname
;
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).
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.
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.
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
) {
2142 * The auditor can indicate that this object should be ignored.
2145 audit_objsearch(clmp
, name
, LA_SER_ORIG
)) == NULL
) {
2146 DBG_CALL(Dbg_audit_terminate(lml
, name
));
2150 if (name
!= aname
) {
2151 fdp
->fd_flags
&= ~FLG_FD_SLASH
;
2155 fdp
->fd_oname
= 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.
2166 load_finish(Lm_list
*lml
, const char *name
, Rt_map
*clmp
, int nmode
,
2167 uint_t flags
, Grp_hdl
**hdl
, Rt_map
*nlmp
)
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))
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
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
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
;
2254 hflags
= GPH_PRIVATE
;
2256 if (nmode
& RTLD_FIRST
)
2257 hflags
|= GPH_FIRST
;
2260 * Establish the flags for this callers dependency descriptor
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
,
2291 * Add any dependencies that are already loaded, to the handle.
2293 if (hdl_initialize(ghp
, nlmp
, nmode
, promote
) == 0)
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
2309 if (oflags
& FLG_RT_PUBHDL
)
2314 * If the caller isn't part of a group we're done.
2316 if (GROUPS(clmp
) == NULL
)
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
)) {
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
)
2343 if ((gdp
->gd_flags
& GPD_ADDEPS
) == 0)
2346 if ((gdp
= hdl_add(ghp
, nlmp
, rdflags
, &ale
)) == NULL
)
2350 * If this member already exists then its dependencies will
2351 * have already been processed.
2353 if (ale
== ALE_EXISTS
)
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
))
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
)
2373 for (APLIST_TRAVERSE(lmalp
, idx2
, dlmp1
)) {
2378 * Add any dependencies of this dependency to the
2379 * dynamic dependency list so they can be further
2382 for (APLIST_TRAVERSE(DEPENDS(dlmp1
), idx3
, bdp
)) {
2383 Rt_map
*dlmp2
= bdp
->b_depend
;
2385 if ((bdp
->b_flags
& BND_NEEDED
) == 0)
2388 if (aplist_test(&lmalp
, dlmp2
,
2389 AL_CNT_DEPCLCT
) == 0) {
2399 hdl_add(ghp
, dlmp1
, rdflags
, &ale
)) == NULL
) {
2404 if (ale
== ALE_CREATE
)
2405 (void) update_mode(dlmp1
, MODE(dlmp1
), nmode
);
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.
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
;
2423 if ((nmode
& RTLD_NOLOAD
) == 0) {
2427 * Keep track of the number of not-found loads.
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
,
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.
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
);
2470 * If it's a NOLOAD request - check to see if the object
2471 * has already been loaded.
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
,
2481 (void) printf(MSG_ORIG(MSG_LDD_FIL_PATH
),
2482 name
, MSG_ORIG(MSG_STR_EMPTY
),
2483 MSG_ORIG(MSG_STR_EMPTY
));
2485 (void) printf(MSG_ORIG(MSG_LDD_FIL_EQUIV
),
2487 MSG_ORIG(MSG_STR_EMPTY
),
2488 MSG_ORIG(MSG_STR_EMPTY
));
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
);
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
2514 if ((FLAGS(nlmp
) & FLG_RT_ANALYZED
) == 0)
2515 remove_so(lml
, nlmp
, clmp
);
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
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
);
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).
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 };
2554 for (ALIST_TRAVERSE(palp
, idx
, pdp
)) {
2558 * A $CAPABILITY/$HWCAP requirement can expand into a number of
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
);
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
)
2576 * Locate and load the file.
2578 lmp
= load_path(lml
, lmco
, clmp
, mode
, flags
, hdl
, &fd
,
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
);
2600 * Determine whether a symbol is defined as an interposer.
2603 is_sym_interposer(Rt_map
*lmp
, Sym
*sym
)
2605 Syminfo
*sip
= SYMINFO(lmp
);
2610 ndx
= (((ulong_t
)sym
- (ulong_t
)SYMTAB(lmp
)) / SYMENT(lmp
));
2612 sip
= (Syminfo
*)((char *)sip
+ (ndx
* SYMINENT(lmp
)));
2613 if (sip
->si_flags
& SYMINFO_FLG_INTERPOSE
)
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.
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
;
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
)) {
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
;
2647 (DBG_BINFO_INTERPOSE
| DBG_BINFO_COPYREF
);
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
2661 clmp
= slp
->sl_cmap
;
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)) {
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
);
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)) {
2715 (DBG_BINFO_INTERPOSE
| DBG_BINFO_COPYREF
);
2721 if ((lml
->lm_flags
& LML_FLG_INTRPOSE
) == 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.
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
)
2740 if ((FLAGS(lmp
) & MSK_RT_INTPOSE
) == 0)
2744 * If we had already bound to this object, there's no point in
2745 * searching it again, we're done.
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
)) {
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
);
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))
2780 * Indicate this binding has occurred to an
2781 * interposer, and return the symbol.
2784 *binfo
|= DBG_BINFO_INTERPOSE
;
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.
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
;
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
);
2830 * If we need to directly bind to our parent, start looking in each
2834 sl
.sl_flags
|= LKUP_DIRECT
;
2837 if (sip
->si_boundto
== SYMINFO_BT_PARENT
) {
2843 * Determine the parent of this explicit dependency from its
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
))
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
2859 for (APLIST_TRAVERSE(HANDLES(clmp
), idx1
, ghp
)) {
2863 for (ALIST_TRAVERSE(ghp
->gh_depends
, idx2
, gdp
)) {
2864 if ((gdp
->gd_flags
& GPD_PARENT
) == 0)
2866 sl
.sl_imap
= lmp
= gdp
->gd_depend
;
2867 if (ret
= SYMINTP(lmp
)(&sl
, srp
, binfo
,
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
;
2883 ret
= SYMINTP(lmp
)(&sl
, srp
, binfo
, in_nfavl
);
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
))
2906 core_lookup_sym(Rt_map
*ilmp
, Slookup
*slp
, Sresult
*srp
, uint_t
*binfo
,
2907 Aliste off
, int *in_nfavl
)
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
);
2920 for (; lmp
; lmp
= NEXT_RT_MAP(lmp
)) {
2921 if (callable(slp
->sl_cmap
, lmp
, 0, slp
->sl_flags
)) {
2924 if ((SYMINTP(lmp
)(slp
, srp
, binfo
, in_nfavl
)) ||
2925 (*binfo
& BINFO_MSK_TRYAGAIN
))
2933 rescan_lazy_find_sym(Rt_map
*ilmp
, Slookup
*slp
, Sresult
*srp
, uint_t
*binfo
,
2938 for (lmp
= ilmp
; lmp
; lmp
= NEXT_RT_MAP(lmp
)) {
2941 if (callable(slp
->sl_cmap
, lmp
, 0, slp
->sl_flags
)) {
2944 if (elf_lazy_find_sym(slp
, srp
, binfo
, in_nfavl
))
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
;
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
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
)) {
2982 * Find the corresponding Syminfo entry for the original
2983 * referencing symbol.
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
) {
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
3047 if (((*binfo
& BINFO_MSK_REJECTED
) == 0) ||
3048 (*binfo
& BINFO_MSK_TRYAGAIN
))
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.
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)) {
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
3080 if (((sip
= SYMINFO(dlmp
)) == 0) ||
3082 ((sip
= (Syminfo
*)((char *)sip
+
3083 (dsymndx
* SYMINENT(dlmp
)))) == 0) ||
3084 ((sip
->si_flags
& SYMINFO_FLG_NOEXTDIRECT
) == 0))
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
) {
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
))
3110 ret
= core_lookup_sym(ilmp
, &sl
, srp
, binfo
, ALIST_OFF_DATA
,
3114 * If a symbol binding should be retried, return so that the search can
3117 if (*binfo
& BINFO_MSK_TRYAGAIN
)
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
;
3133 if ((sl
.sl_flags
& LKUP_WEAK
) || (lml
->lm_lazy
== 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
3143 if (sl
.sl_flags
& LKUP_NEXT
)
3144 ret
= rescan_lazy_find_sym(clmp
, &sl
, srp
, binfo
,
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
))
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
;
3179 if (slp
->sl_hash
== 0)
3180 slp
->sl_hash
= elf_hash(slp
->sl_name
);
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
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
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
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
)) ==
3238 slp
->sl_flags
|= LKUP_WEAK
;
3242 * Save the callers MODE().
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
)) {
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
);
3268 if (*binfo
& BINFO_REJSINGLE
)
3269 sl
.sl_flags
|= LKUP_SINGLETON
;
3270 if (*binfo
& BINFO_REJGROUP
) {
3271 sl
.sl_flags
|= LKUP_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
3284 if (((mode
& (RTLD_GROUP
| RTLD_WORLD
)) == RTLD_GROUP
) &&
3285 (lookup_sym_interpose(slp
, srp
, binfo
, in_nfavl
)))
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
)
3300 int found
= ALE_CREATE
;
3303 * Determine whether a binding descriptor already exists between the
3306 for (APLIST_TRAVERSE(DEPENDS(clmp
), idx
, bdp
)) {
3307 if (bdp
->b_depend
== dlmp
) {
3313 if (found
== ALE_CREATE
) {
3315 * Create a new binding descriptor.
3317 if ((bdp
= malloc(sizeof (Bnd_desc
))) == NULL
)
3320 bdp
->b_caller
= clmp
;
3321 bdp
->b_depend
= dlmp
;
3325 * Append the binding descriptor to the caller and the
3328 if (aplist_append(&DEPENDS(clmp
), bdp
, AL_CNT_DEPENDS
) == NULL
)
3331 if (aplist_append(&CALLERS(dlmp
), bdp
, AL_CNT_CALLERS
) == NULL
)
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
));
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.
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
);
3375 for (APLIST_TRAVERSE(bound
, idx
, _lmp
)) {
3376 if (bind_one(lmp
, _lmp
, BND_REFER
) || used
)
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
)
3403 * If this is an allocated image (ie. a relocatable object) we can't
3404 * mprotect() anything.
3406 if (FLAGS(lmp
) & FLG_RT_IMGALLOC
)
3409 DBG_CALL(Dbg_file_prot(lmp
, perm
));
3412 prot
= mpp
->mr_prot
| PROT_WRITE
;
3414 prot
= mpp
->mr_prot
& ~PROT_WRITE
;
3416 if (mprotect((void *)(uintptr_t)mpp
->mr_addr
,
3417 mpp
->mr_msize
, prot
) == -1) {
3419 eprintf(LIST(lmp
), ERR_FATAL
, MSG_INTL(MSG_SYS_MPROT
),
3420 NAME(lmp
), strerror(err
));
3423 mpp
->mr_prot
= prot
;