rtld.h revision 37ffaf8335982d89ab569e9a1020419e32003404
/*
* 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
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#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>
#ifdef _SYSCALL32
#include <inttypes.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* Linked list of directories or filenames (built from colon separated string).
*/
typedef struct pnode {
const char *p_name;
const char *p_oname;
void *p_info;
} Pnode;
/*
* A binding descriptor. Establishes the binding relationship between two
* objects, the caller (originator) and the dependency (destination).
*/
typedef struct {
/* binding */
/* dependency */
} Bnd_desc;
/* dependency */
/*
* 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 'RTLD_DB_VERSION <= 2' the following fields were valid for core
* file examination (basically the public Link_map):
*
* ADDR()
* NAME()
* DYN()
* NEXT()
* PREV()
*
* Valid fields for RTLD_DB_VERSION3
*
* PATHNAME()
* PADSTART()
* PADIMLEN()
* MSIZE()
* FLAGS()
* FLAGS1()
*
* Valid fields for RTLD_DB_VERSION4
*
* TLSMODID()
*
* Valid fields for RTLD_DB_VERSION5
*
* Added rtld_flags & FLG_RT_RELOCED to stable flags range
*
*/
/* file examination */
/* core files */
#define R_RTLDDB_VERSION3 3
#define R_RTLDDB_VERSION4 4
#define R_RTLDDB_VERSION5 5
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 */
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 remain */
/* 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: Audit flags have duplicated FLAGS1() values. If more audit flags are
* added, update the FLAGS1() reservation FL1_AUD_RS_STR to FL1_AUD_RS_END
* defined later.
*/
/*
* 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. This
* data structure is tracked from the link-map HANDLE(), and is the structure
* returned from dlopen(), and similar object loading capabilities such as
*
* 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.
*
* 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
* 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.
*
* 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. A temporary handle is created for this
* purpose, and is discarded immediately after the promotion operation has been
* completed.
*/
typedef struct {
} Grp_hdl;
/* dependency */
/* remain for this 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 */
/* promoter */
/* 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;
} Dyninfo;
/* and DT_SYMAUXILIARY */
/* DF_P1_LAZYLOAD (DT_POSFLAG_1) */
/* DF_P1_GROUPPERM (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;
/*
* Define a mapping structure, which is maintained to describe each mapping
* of an object, ie. the text segment, data segment, bss segment, etc.
*/
typedef struct {
int m_perm; /* mapping permissions */
} Mmap;
/*
* 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
*/
char *rt_pathname; /* full pathname of loaded object */
/*
* END: Exposed to rtld_db - don't move, don't delete
*/
void (*rt_init)(); /* address of _init */
void (*rt_fini)(); /* address of _fini */
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 */
char *rt_origname; /* original pathname of loaded object */
/* because it is checked in */
/* common code */
};
#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 >= RTLD_DB_VERSION5
*/
/*
* END: Exposed to rtld_db - don't move, don't delete
*/
/* possibilities */
/* symbolic sym resolution */
/*
* The following range of bits are reserved to hold LML_TFLG_AUD_ values
* (although the definitions themselves aren't used anywhere).
*/
/*
* Flags for the tls_modactivity() routine
*/
/*
* Macros for getting to link_map data.
*/
/*
* Macros for getting to linker private data.
*/
#define PATHNAME(X) ((X)->rt_pathname)
#define PADSTART(X) ((X)->rt_padstart)
#define PADIMLEN(X) ((X)->rt_padimlen)
#define TLSMODID(X) ((X)->rt_tlsmodid)
#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 CONDVAR(X) ((X)->rt_condvar)
#define THREADID(X) ((X)->rt_threadid)
/*
* 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.
*/
typedef struct {
const char *sl_name; /* symbol name */
/* symbol */
} Slookup;
flags) \
/*
* 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 */