rtld.h revision b23a7923c0fe493ed4beebaf775ad634ea217080
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#ifndef _RTLD_H
#define _RTLD_H
/*
* Global include file for the runtime linker.
*/
#include <time.h>
#include <sgs.h>
#include <thread.h>
#include <synch.h>
#include <link.h>
#include <alist.h>
#include <libc_int.h>
#include <elfcap.h>
#ifdef _SYSCALL32
#include <inttypes.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* We use rtld_ino_t instead of ino_t so that we can get
* access to large inode values from 32-bit code.
*/
#ifdef _LP64
typedef ino_t rtld_ino_t;
#else
typedef ino64_t rtld_ino_t;
#endif
/*
* A binding descriptor. Establishes the binding relationship between two
* objects, the caller (originator) and the dependency (destination).
*
* Every relationship between two objects is tracked by a binding descriptor.
* This descriptor is referenced from a link-map's DEPENDS and CALLERS lists.
* Note, Aplist's are diagramed to fully expose the allocations required to
* establish the data structure relationships.
*
* Bnd_desc
* ----------
* ------------| b_caller |
* | | b_depend | ----------
* | | | |
* Rt_map | ---------- | Rt_map
* ---------- | ^ ^ | ----------
* | | <-- | | --> | |
* | | -------- | | | |
* | DEPENDS | ----> | | | | -------- | |
* | | | | | | | | <---- | CALLERS |
* | | | | --- | | | | |
* | | | | --- | | | |
* | | -------- | | | |
* ---------- Aplist -------- ----------
* Aplist
*/
typedef struct {
/* binding */
/* dependency */
} Bnd_desc;
/* dependency */
/* for diagnostics only */
/*
* Private structure for communication between rtld_db and rtld.
*
* We must bump the version number when ever an update in one of the
* structures/fields that rtld_db reads is updated. This hopefully permits
* rtld_db implementations of the future to recognize core files produced on
* older systems and deal with these core files accordingly.
*
* As of version 'R_RTLDDB_VERSION <= 2' the following fields were valid for
* core file examination (basically the public Link_map):
*
* ADDR()
* NAME()
* DYN()
* NEXT()
* PREV()
*
* Valid fields for R_RTLDDB_VERSION3
*
* PATHNAME()
* PADSTART()
* PADIMLEN()
* MSIZE()
* FLAGS()
* FLAGS1()
*
* Valid fields for R_RTLDDB_VERSION4
*
* TLSMODID()
*
* Valid fields for R_RTLDDB_VERSION5
*
* Added rtld_flags & FLG_RT_RELOCED to stable flags range
*
* Valid fields for R_RTLDDB_VERSION6
*
* rtd_dynlmlst converted from a List to APlist
*/
/* file examination */
/* core files */
#define R_RTLDDB_VERSION3 3
#define R_RTLDDB_VERSION4 4
#define R_RTLDDB_VERSION5 5
#define R_RTLDDB_VERSION6 6
typedef struct rtld_db_priv {
} Rtld_db_priv;
#ifdef _SYSCALL32
typedef struct rtld_db_priv32 {
#endif /* _SYSCALL32 */
/*
* External function definitions. ld.so.1 must convey information to libc in
* regards to threading. libc also provides routines for atexit() and message
* localization. libc provides the necessary interfaces via its RTLDINFO
*
* These external functions are maintained for each link-map list, and used
* where appropriate. The functions are associated with the object that
* provided them, so that should the object be deleted (say, from an alternative
* link-map), the functions can be removed.
*/
typedef struct {
union {
int (*lc_func)(); /* external function pointer */
char *lc_ptr; /* external character pointer */
} lc_un;
} Lc_desc;
/*
* Link map list definition. Link-maps are used to describe each loaded object.
* Lists of these link-maps describe the various namespaces within a process.
* The process executable and its dependencies are maintained on the lml_main
* list. The runtime linker, and its dependencies are maintained on the
* lml_rtld list. Additional lists can be created (see dlmopen()) for such
* things as auditors and their dependencies.
*
* Each link-map list maintains an Alist of one, or more, linked lists of
* initialized to the first linked-list of link-maps:
*
* Lm_list
* ----------
* | lm_tail | ------------------------------------
* | lm_head | -------------------- |
* | | | Rt_map | Rt_map
* | | | ------ | ------
* | | Alist --> | | |--> | |
* | | --------- | | | -- | |
* | lm_lists | ----> | | | | | --> | |
* | | |---------| | | | | | |
* | | | lc_head | -- ------ | ------
* | | | lc_tail | ------------------
* | | |---------|
* ---------- | lc_head |
* | lc_tail |
* |---------|
*
* Multiple link-map lists exist to support the addition of lazy loaded
* families, filtee families, and dlopen() families. The intent of these
* lists is to insure that a family of objects that are to be loaded are
* fully relocatable, and hence usable, before they become part of the main
* (al_data[0]) link-map control list. This main link-map control list is
* the only list in existence when control is transferred to user code.
*
* During process initialization, the dynamic executable and its non-lazy
* dependencies are maintained on al_data[0]. If a new object is loaded, then
* this object is added to the next available control list [1], typically
* al_data[1]. Any dependencies of this object that have not already been
* loaded are added to the same control list. Once all of the objects on the
* new control list have been successfully relocated, the objects are moved from
* the new control list to the highest control list to which objects of the new
* control list bound to, typically al_data[1] to al_data[0].
*
* Each loading scenario can be broken down as follows:
*
* setup() - only the initial link-map control list is used:
* i. create al_data[0]
* ii. add new link-map for main on al_data[0]
* iii. analyze al_data[0] to add all non-lazy dependencies
* iv. relocate al_data[0] dependencies.
*
* dlopen() - the initiator can only be the initial link-map control list:
* i. create al_data[1] from caller al_data[0]
* ii. add new link-map for the dlopen'ed object on al_data[1]
* iii. analyze al_data[1] to add all non-lazy dependencies
* iv. relocate al_data[1] dependencies, and move to al_data[0].
*
* filtee and lazy loading processing - the initiator can be any link-map
* control list that is being relocated:
* i. create al_data[y] from caller al_data[x]
* ii. add new link-map for the new object on al_data[y]
* iii. analyze al_data[y] to add all non-lazy dependencies
* iv. relocate al_data[y] dependencies, and move to al_data[x].
*
* This Alist therefore maintains a stack of link-map control lists. The newest
* link-map control list can locate symbols within any of the former lists,
* however, control is not passed to a former list until the newest lists
* processing is complete. Thus, objects can't bind to new objects until they
* have been fully analyzed and relocated.
*
* [1] Note, additional link-map control list creation occurs after the head
* link-map object (typically the dynamic executable) has been relocated. This
* staging is required to satisfy the binding requirements of copy relocations.
* Copy relocations, effectively, transfer the bindings of the copied data
* (say _iob in libc.so.1) to the copy location (_iob in the application).
* Thus an object that might bind to the original copy data must be redirected
* to the copy reference. As the knowledge of a copy relocation having taken
* place is only known after relocating the application, link-map control list
* additions are suspended until after this relocation has completed.
*/
typedef struct {
} Lm_cntl;
/* interposers are added */
struct lm_list {
/*
* BEGIN: Exposed to rtld_db - don't move, don't delete
*/
/* is required for flags */
/*
* END: Exposed to rtld_db - don't move, don't delete
*/
char ***lm_environ; /* pointer to environment array */
/* lazy dependencies */
char *lm_lmidstr; /* and associated diagnostic string */
};
#ifdef _SYSCALL32
struct lm_list32 {
/*
* BEGIN: Exposed to rtld_db - don't move, don't delete
*/
/*
* END: Exposed to rtld_db - don't move, don't delete
*/
};
#endif /* _SYSCALL32 */
/*
* Possible Link_map list flags (Lm_list.lm_flags)
*/
/*
* BEGIN: Exposed to rtld_db - don't move, don't delete
*/
/*
* END: Exposed to rtld_db - don't move, don't delete
*/
/* initialization */
/* (ld.so.1 only) */
/* this link-map list */
/* internal for crle(1) */
/* tsort reevaluation */
/* dependencies */
/* are not allowed */
/* references are not */
/* allowed */
/*
* Possible Link_map transferable flags (Lm_list.lm_tflags), i.e., link-map
* list flags that can be propagated to any new link-map list created.
*/
/*
* NOTE: Each auditing module establishes a set of audit flags, AFLAGS(), that
* define the auditing interfaces the module offers. These auditing flags are
* the LML_TFLG_AUD_ flags defined above. Global auditors result in setting
* the lm_tflags too. Local auditors only use the AFLAGS(). All tests for
* auditing inspect the lm_tflags and AFLAGS() for a specific auditing
* interface, and thus use the same flag to test for both types of auditors.
*/
/*
* Define a Group Handle.
*
* The capability of ld.so.1 to associate a group of objects, look for symbols
* within that group, ensure that groups are isolated from one another (with
* regard to relocations), and to unload a group, centers around a handle.
*
* Dependencies can be added to an existing handle as the dependencies are
* lazily loaded. The core dependencies on the handle are the ldd(1) list of
* the referenced object.
*
* Handles can be created from:
*
* - a dlopen() request. This associates a caller to a reference object,
* and the referenced objects dependencies. This group of objects can
* then be inspected for symbols (dlsym()).
* - a filtering request. This associates a filter (caller) to a referenced
* object (filtee). The redirection of filter symbols to their filtee
* counterpart is essentially a dlsym() using the filtee's handle.
*
* The handle created for these events is referred to as a public handle. This
* handle tracks the referenced object, all of the dependencies of the
* referenced object, and the caller (parent).
*
* Presently, an object may have two handles, one requested with RTLD_FIRST
* and one without.
*
* A handle may be referenced by any number of callers (parents). A reference
* count tracks the number. A dlclose() operation drops the reference count,
* and when the count is zero, the handle is used to determine the family of
* objects to unload. As bindings may occur to objects on the handle from
* other handles, it may not be possible to remove a complete family of objects
* or the handle itself. Handles in this state are moved to an orphan list.
* A handle on the orphan list is taken off the orphan list if the associated
* object is reopened. Otherwise, the handle remains on the orphan list for
* the duration of the process. The orphan list is inspected any time objects
* are unloaded, to determine if the orphaned objects can also be unloaded.
*
* Handles can also be created for internal uses:
*
* - to promote objects to RTLD_NOW.
* - to establish families for symbol binding fallback, required when lazy
* loadable objects are still pending.
*
* The handle created for these events is referred to as a private handle. This
* handle does not need to track the caller (parent), and because of this, does
* not need to be considered during dlclose() operations, as the handle can not
* be referenced by callers outside of the referenced objects family.
*
* Note, a private handle is essentially a subset of a public handle. Should
* an internal operation require a private handle, and a public handle already
* exist, the public handle can be used. Should an external operation require
* a public handle, and a private handle exist, the private handle is promoted
* to a public handle. Any handle that gets created will remain in existence
* for the life time of the referenced object.
*
* Objects can be dlopened using RTLD_NOW. This attribute requires that all
* relocations of the object, and its dependencies are processed immediately,
* before return to the caller. Typically, an object is loaded without
* RTLD_NOW, and procedure linkage relocations are satisfied when their
* associated function is first called. If an object is already loaded, and an
* RTLD_NOW request is made, then the object, and its dependencies, most undergo
* additional relocation processing. This promotion from lazy binding to
* immediate binding is carried out using handles, as the handle defines the
* dependencies that must be processed.
*
* To ensure that objects within a lazy loadable environment can be relocated,
* no matter whether the objects have their dependencies described completely,
* a symbol lookup fallback is employed. Any pending lazy loadable objects are
* loaded, and a handle established to search the object and it's dependencies
* for the required symbol.
*
* A group handle (and its associated group descriptors), is referenced from
* a link-map's HANDLES and GROUPS lists. Note, Aplist's are diagramed to
* fully expose the allocations required to establish the data structure
* relationships.
*
* Grp_desc
* Alist
* -----------
* --> | |
* | |-----------|
* | | gd_depend | ---------
* | | | |
* | |-----------| |
* --------|--- | gd_depend | |
* | | | (parent) | |
* | | |-----------| |
* | | | gd_depend | |
* | | | | |
* | | | | |
* | | ----------- |
* | | |
* | | Grp_hdl |
* | | ----------- |
* | -- | gh_depends | |
* | --------- | gh_ownlmp | |
* | | | | |
* | | | | |
* | | | | |
* Rt_map | | ------------ | Rt_map
* ---------- | | ^ ^ | ----------
* | | <- | | | --> | |
* | | <--- -------- | | | |
* | HANDLES | ----> | | | | -------- | |
* | | | | | | | | <---- | GROUPS |
* | | | | --- | | | | |
* | | | | --- | | | |
* | | -------- | | | |
* ---------- Aplist -------- ----------
* Aplist
*/
typedef struct {
} Grp_hdl;
/*
* Define the two categories of handle.
*/
/*
* Define any flags that affects how the handle is used.
*/
/* dependency */
/* for diagnostics only */
/*
* Define any state that is associated with the handle.
*/
/*
* Define a Group Descriptor.
*
* Each dependency associated with a group handle is maintained by a group
* descriptor. The descriptor defines the associated dependency together with
* flags that indicate how the dependency can be used.
*/
typedef struct {
} Grp_desc;
/* relocation binding */
/* should be added to handle */
/* removal from the group */
/*
* Define threading structures. For compatibility with libthread (T1_VERSION 1
* and TI_VERSION 2) our locking structure is sufficient to hold a mutex or a
*/
typedef struct {
union {
} u;
} Rt_lock;
/*
* Define a dynamic section information descriptor. This parallels the entries
* in the .dynamic section and holds auxiliary information to implement lazy
* loading and filtee processing.
*/
typedef struct {
void *di_info;
const char *di_name;
} Dyninfo;
/* and DT_SYMAUXILIARY */
/* DF_P1_LAZYLOAD (DT_POSFLAG_1) */
/* DF_P1_GROUPPERM (DT_POSFLAG_1) */
/* DF_P1_DEFERRED (DT_POSFLAG_1) */
/* failed */
/*
* Data structure to track AVL tree of pathnames. This structure provides the
* basis of both the "not-found" node tree, and the "full-path" node tree. Both
* of these trees persist for the life of a process, although the "not-found"
* tree may be moved aside during a dlopen() or dlsym() fall back operation.
*/
typedef struct {
const char *pn_name; /* path name */
} PathNode;
/*
* Data structure to track AVL tree for full path names of objects that are
* loaded into memory.
*/
typedef struct {
} FullPathNode;
/*
* A given link-map can hold either a supplier or receiver copy
* relocation list, but not both. This union is used to overlap
* the space used for the two lists.
*/
typedef union {
} Rt_map_copy;
/*
* Link-map definition.
*/
struct rt_map {
/*
* BEGIN: Exposed to rtld_db - don't move, don't delete
*/
const char *rt_pathname; /* full pathname of loaded object */
/*
* END: Exposed to rtld_db - don't move, don't delete
*/
char *rt_runpath; /* LD_RUN_PATH and its equivalent */
void *rt_priv; /* private data, object type specific */
int rt_mode; /* usage mode, see RTLD mode flags */
int rt_sortval; /* temporary buffer to traverse graph */
const char *rt_origname; /* original pathname of loaded object */
/* because it is checked in */
/* common code */
/* pending */
/* address of _init */
void (*rt_init)(void);
/* address of _fini */
void (*rt_fini)(void);
/* link map symbol interpreter */
};
#ifdef _SYSCALL32
/*
* Structure to allow 64-bit rtld_db to read 32-bit processes out of procfs.
*/
typedef union {
typedef struct rt_map32 {
/*
* BEGIN: Exposed to rtld_db - don't move, don't delete
*/
/*
* END: Exposed to rtld_db - don't move, don't delete
*/
} Rt_map32;
#endif /* _SYSCALL32 */
/*
* Link map state flags.
*/
/*
* BEGIN: Exposed to rtld_db - don't move, don't delete
*/
/*
* Available for r_debug version >= R_RTLDDB_VERSION5
*/
/*
* END: Exposed to rtld_db - don't move, don't delete
*/
/* possibilities */
/* checked */
/* should be used */
/* symbolic sym resolution */
/*
* Flags for the tls_modactivity() routine
*/
/*
* Macros for getting to exposed, link_map data (R_RTLDDB_VERSION <= 2).
*/
/*
* An Rt_map starts with a Link_map, followed by other information.
* ld.so.1 allocates Rt_map structures, and then casts them to Link_map,
* and back, depending on context.
*
* On some platforms, Rt_map can have a higher alignment requirement
* than Link_map. On such platforms, the cast from Link_map to Rt_map will
* draw an E_BAD_PTR_CAST_ALIGN warning from lint. Since we allocate
* the memory as the higher alignment Rt_map, we know that this is a safe
* conversion. The LINKMAP_TO_RTMAP macro is used to handle the conversion
* in a manner that satisfies lint.
*/
#ifdef lint
#define LINKMAP_TO_RTMAP(X) (Rt_map *)(void *)(X)
#else
#define LINKMAP_TO_RTMAP(X) (Rt_map *)(X)
#endif
/*
* Convenience macros for the common case of using
* NEXT()/PREV() and casting the result to (Rt_map *)
*/
/*
* Macros for getting to exposed, link_map data (R_RTLDDB_VERSION3).
*/
#define PATHNAME(X) ((X)->rt_pathname)
#define PADSTART(X) ((X)->rt_padstart)
#define PADIMLEN(X) ((X)->rt_padimlen)
/*
* Macros for getting to exposed, link_map data (R_RTLDDB_VERSION4).
*/
#define TLSMODID(X) ((X)->rt_tlsmodid)
/*
* Macros for getting to unexposed, link-map data.
*/
#define RPATH(X) ((X)->rt_runpath)
#define RLIST(X) ((X)->rt_runlist)
#define DEPENDS(X) ((X)->rt_depends)
#define CALLERS(X) ((X)->rt_callers)
#define HANDLES(X) ((X)->rt_handles)
#define SYMINTP(X) ((X)->rt_symintp)
#define OBJFLTRNDX(X) ((X)->rt_objfltrndx)
#define SYMSFLTRCNT(X) ((X)->rt_symsfltrcnt)
#define SYMAFLTRCNT(X) ((X)->rt_symafltrcnt)
#define SORTVAL(X) ((X)->rt_sortval)
#define CYCGROUP(X) ((X)->rt_cycgroup)
#define ORIGNAME(X) ((X)->rt_origname)
#define AUDITORS(X) ((X)->rt_auditors)
#define AUDINFO(X) ((X)->rt_audinfo)
#define SYMINFO(X) ((X)->rt_syminfo)
#define INITARRAY(X) ((X)->rt_initarray)
#define FINIARRAY(X) ((X)->rt_finiarray)
#define PREINITARRAY(X) ((X)->rt_preinitarray)
#define MMAPCNT(X) ((X)->rt_mmapcnt)
#define INITARRAYSZ(X) ((X)->rt_initarraysz)
#define FINIARRAYSZ(X) ((X)->rt_finiarraysz)
#define PREINITARRAYSZ(X) ((X)->rt_preinitarraysz)
#define DYNINFO(X) ((X)->rt_dyninfo)
#define DYNINFOCNT(X) ((X)->rt_dyninfocnt)
#define RELACOUNT(X) ((X)->rt_relacount)
#define CAPCHAIN(X) ((X)->rt_capchain)
/*
* Flags for tsorting.
*/
/* only (called via dlclose()) */
/*
* Flags for lookup_sym (and hence find_sym) routines.
*/
/* resolutions to plt[] entries) */
/* symbol had a leading `.' */
/* only */
/* not bind to symbol at head */
/* relocation (elf_reloc()) */
/* is valid */
/* pending lazy dependencies */
/* head link-map element */
/*
* For the runtime linker to perform a symbol search, a number of data items
* related to the search are required. An Slookup data structure is used to
* convey this data to lookup_sym(), and in special cases, to other core
* routines that provide the implementation details for lookup_sym()
*
* The symbol name (sl_name), the caller (sl_cmap), and the link-map from which
* to start the search (sl_imap) are fundamental to the symbol search. The
* initial search link-map might get modified by the core routines that provide
* the implementation details for lookup_sym(). This modification accommodates
* requirements such as processing a handle, direct binding and interposition.
* The association between the caller and the potential destination also
* determines whether the destination is a candidate to search.
*
* The lookup identifier (sl_id) is used to identify a runtime linker operation.
* Within this operation, any lazy loads that fail are not re-examined. This
* technique keeps the overhead of processing a failed lazy load to a minimum.
*
* Symbol searches that originate from a relocation record are accompanied by
* the relocation index (sl_rsymndx), the symbol reference (sl_rsym) and
* possibly the relocation type (sl_rtype). This data provides for determining
* lazy loading, direct binding, and special symbol processing requirements
* such as copy relocations and singleton lookup.
*
* The symbols hash value is computed by lookup_sym, and propagated throughout
* the search engine. Note, occasionally the Slookup data is passed to a core
* routine that provides the implementation details for lookup_sym(), ie.
* elf_find_sym(), in which case the caller must initialize the hash value.
*
* The symbols binding information is established by lookup_sym() when the
* symbols relocation type is supplied. Weak bindings allow relocations to
* be set to zero should a symbol lookup fail.
*
* The flags allow the caller to control aspects of the search, including the
* interpretation of copy relocations, etc. Note, a number of flag settings
* are established in lookup_sym() from attributes of the symbol reference.
*/
struct slookup {
const char *sl_name; /* symbol name */
/* symbol */
};
flags) \
/*
* After a symbol lookup has been resolved, the runtime linker needs to retain
* information regarding the bound definition. An Sresult data structure is
* used to provide this information.
*
* The symbol name (sr_name) may differ from the original referenced symbol if
* a symbol capabilities family member has resolved the binding. The defining
* object (sr_dmap) indicates the object in which the definition has been found.
* The symbol table entry (sr_sym) defines the bound symbol definition.
*
* Note, a symbol lookup may start with one Sresult buffer, but underlying
* routines (for example, those that probe filters) might employ their own
* Sresult buffer. If a binding is allowed, the latter buffer may get inherited
* by the former. Along with this chain of requests, binding info (binfo) and
* not-found information (in_nfavl), may be passed between all the associated
* functions. Hence, the binfo and in_nfavl data is not maintained as part of
* a Sresult structure.
*/
struct sresult {
const char *sr_name; /* symbol definition name */
};
/*
* Define a system capabilities structure for maintaining the various
* capabilities of the system. This structure follows the Objcapset definition
* from libld.h, however the system can only have one platform or machine
* hardware name, thus this structure is a little simpler.
*/
typedef struct {
char *sc_plat; /* CA_SUNW_PLAT capability */
char *sc_mach; /* CA_SUNW_MACH capability */
} Syscapset;
/*
* Define a number of .plt lookup outcomes, for use in binding diagnostics.
*/
typedef enum {
PLT_T_NONE = 0,
PLT_T_NUM /* Must be last */
} Pltbindtype;
/*
* Prototypes.
*/
/* ld.so.1. */
Xword);
#ifdef __cplusplus
}
#endif
#endif /* _RTLD_H */