summaryrefslogtreecommitdiff
path: root/usr/src/cmd/sgs/include/rtld.h
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/sgs/include/rtld.h')
-rw-r--r--usr/src/cmd/sgs/include/rtld.h175
1 files changed, 139 insertions, 36 deletions
diff --git a/usr/src/cmd/sgs/include/rtld.h b/usr/src/cmd/sgs/include/rtld.h
index b350a63f3c..99fd1ea355 100644
--- a/usr/src/cmd/sgs/include/rtld.h
+++ b/usr/src/cmd/sgs/include/rtld.h
@@ -63,6 +63,28 @@ typedef struct slookup Slookup;
/*
* 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 {
Rt_map *b_caller; /* caller (originator) of a binding */
@@ -75,8 +97,8 @@ typedef struct {
#define BND_NEEDED 0x0001 /* caller NEEDED the dependency */
#define BND_REFER 0x0002 /* caller relocation references the */
/* dependency */
-#define BND_FILTER 0x0004 /* pseudo binding to identify filter */
-
+#define BND_FILTER 0x0004 /* binding identifies filter, used */
+ /* for diagnostics only */
/*
* Private structure for communication between rtld_db and rtld.
*
@@ -182,7 +204,7 @@ typedef struct {
* | | | lc_head | -- ------ | ------
* | | | lc_tail | ------------------
* | | |---------|
- * | lc_head |
+ * ---------- | lc_head |
* | lc_tail |
* |---------|
*
@@ -393,31 +415,56 @@ struct lm_list32 {
*
* 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. This
- * data structure is tracked from the link-map HANDLE(), and is the structure
- * returned from dlopen(), and similar object loading capabilities such as
- * filter/filtee processing.
+ * 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.
*
- * A handle keeps track of all the dependencies of the associated object.
- * These dependencies may be added as objects are lazily loaded. The core
- * dependencies on the handle are the ldd(1) list of the associated object.
- * The object assigned the handle, and the parent (or caller) who requested the
- * handle are also maintained as dependencies on the 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 parents (callers). A reference
+ * 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 that 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.
+ * 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,
@@ -427,9 +474,53 @@ struct lm_list32 {
* 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. A temporary handle is created for this
- * purpose, and is discarded immediately after the promotion operation has been
- * completed.
+ * 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 {
Alist *gh_depends; /* handle dependency list */
@@ -439,15 +530,27 @@ typedef struct {
uint_t gh_flags; /* handle flags (GPH_ values) */
} Grp_hdl;
-#define GPH_ZERO 0x0001 /* special handle for dlopen(0) */
-#define GPH_LDSO 0x0002 /* special handle for ld.so.1 */
-#define GPH_FIRST 0x0004 /* dlsym() can only use originating */
+/*
+ * Define the two categories of handle.
+ */
+#define GPH_PUBLIC 0x0001 /* handle returned to caller(s) */
+#define GPH_PRIVATE 0x0002 /* handle used internally */
+
+/*
+ * Define any flags that affects how the handle is used.
+ */
+#define GPH_ZERO 0x0010 /* special handle for dlopen(0) */
+#define GPH_LDSO 0x0020 /* special handle for ld.so.1 */
+#define GPH_FIRST 0x0040 /* dlsym() can only use originating */
/* dependency */
-#define GPH_FILTEE 0x0008 /* handle used to specify a filtee */
-#define GPH_INITIAL 0x0010 /* handle is initialized */
-#define GPH_NOPENDLAZY 0x0020 /* no pending lazy dependencies */
+#define GPH_FILTEE 0x0080 /* handle identifies a filtee, used */
+ /* for diagnostics only */
+/*
+ * Define any state that is associated with the handle.
+ */
+#define GPH_INITIAL 0x0100 /* handle is initialized */
+#define GPH_NOPENDLAZY 0x0200 /* no pending lazy dependencies */
/* remain for this handle */
-
/*
* Define a Group Descriptor.
*
@@ -467,10 +570,10 @@ typedef struct {
/* should be added to handle */
#define GPD_PARENT 0x0008 /* dependency is a parent */
#define GPD_FILTER 0x0010 /* dependency is our filter */
-#define GPD_PROMOTE 0x0020 /* dependency is our RTLD_NOW */
- /* promoter */
-#define GPD_REMOVE 0x1000 /* descriptor is a candidate for */
+#define GPD_REMOVE 0x0100 /* descriptor is a candidate for */
/* removal from the group */
+#define GPD_MODECHANGE 0x0200 /* dependency mode has changed, e.g. */
+ /* promoted to RTLD_GOBAL */
/*
* Define threading structures. For compatibility with libthread (T1_VERSION 1
@@ -728,11 +831,11 @@ typedef struct rt_map32 {
#define MSK_RT_INTPOSE 0x01800000 /* mask for all interposer */
/* possibilities */
#define FLG_RT_MOVE 0x02000000 /* object needs move operation */
-#define FLG_RT_TMPLIST 0x04000000 /* object is part of a temporary list */
+#define FLG_RT_RELOCING 0x04000000 /* object is being relocated */
#define FLG_RT_REGSYMS 0x08000000 /* object has DT_REGISTER entries */
#define FLG_RT_INITCLCT 0x10000000 /* init has been collected (tsort) */
-#define FLG_RT_HANDLE 0x20000000 /* generate a handle for this object */
-#define FLG_RT_RELOCING 0x40000000 /* object is being relocated */
+#define FLG_RT_PUBHDL 0x20000000 /* generate a handle for this object */
+#define FLG_RT_PRIHDL 0x40000000 /* either public or private */
#define FL1_RT_COPYTOOK 0x00000001 /* copy relocation taken */