summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorRod Evans <Rod.Evans@Sun.COM>2009-05-08 10:36:22 -0700
committerRod Evans <Rod.Evans@Sun.COM>2009-05-08 10:36:22 -0700
commit2017c9656f884256b400be40fa25d96d630bf02a (patch)
tree3595b8a5a17d9c3e47ec41e5214458d7a2912efb /usr/src
parentb57459abfba36eb3068cfe44c6921168b4c4f774 (diff)
downloadillumos-gate-2017c9656f884256b400be40fa25d96d630bf02a.tar.gz
6831308 ld.so.1: symbol rescanning does a little too much work
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/sgs/include/alist.h2
-rw-r--r--usr/src/cmd/sgs/include/conv.h19
-rw-r--r--usr/src/cmd/sgs/include/debug.h39
-rw-r--r--usr/src/cmd/sgs/include/rtld.h175
-rw-r--r--usr/src/cmd/sgs/libconv/Makefile.com6
-rw-r--r--usr/src/cmd/sgs/libconv/common/group.c4
-rw-r--r--usr/src/cmd/sgs/libconv/common/group.msg7
-rw-r--r--usr/src/cmd/sgs/libconv/common/lintsup.c2
-rw-r--r--usr/src/cmd/sgs/libconv/common/llib-lconv2
-rw-r--r--usr/src/cmd/sgs/libconv/common/time.c73
-rw-r--r--usr/src/cmd/sgs/libconv/common/time.msg28
-rw-r--r--usr/src/cmd/sgs/libld/common/args.c95
-rw-r--r--usr/src/cmd/sgs/libld/common/debug.c17
-rw-r--r--usr/src/cmd/sgs/libld/common/ldmain.c13
-rw-r--r--usr/src/cmd/sgs/libld/common/outfile.c2
-rw-r--r--usr/src/cmd/sgs/libld/common/relocate.c4
-rw-r--r--usr/src/cmd/sgs/libld/common/syms.c2
-rw-r--r--usr/src/cmd/sgs/liblddbg/Makefile.com8
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/args.c6
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/basic.c111
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/debug.c17
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/files.c5
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/liblddbg.msg60
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/llib-llddbg14
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/mapfile-vers14
-rw-r--r--usr/src/cmd/sgs/packages/Makefile.targ7
-rw-r--r--usr/src/cmd/sgs/packages/common/SUNWonld-README2
-rw-r--r--usr/src/cmd/sgs/rtld/common/_elf.h2
-rw-r--r--usr/src/cmd/sgs/rtld/common/_rtld.h8
-rw-r--r--usr/src/cmd/sgs/rtld/common/analyze.c222
-rw-r--r--usr/src/cmd/sgs/rtld/common/cap.c5
-rw-r--r--usr/src/cmd/sgs/rtld/common/debug.c53
-rw-r--r--usr/src/cmd/sgs/rtld/common/dlfcns.c163
-rw-r--r--usr/src/cmd/sgs/rtld/common/elf.c276
-rw-r--r--usr/src/cmd/sgs/rtld/common/remove.c90
-rw-r--r--usr/src/cmd/sgs/rtld/common/rtld.msg1
-rw-r--r--usr/src/cmd/sgs/rtld/common/setup.c19
-rw-r--r--usr/src/cmd/sgs/rtld/common/util.c15
-rw-r--r--usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c10
-rw-r--r--usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg10
40 files changed, 1170 insertions, 438 deletions
diff --git a/usr/src/cmd/sgs/include/alist.h b/usr/src/cmd/sgs/include/alist.h
index d020feb15a..c5071a8cd2 100644
--- a/usr/src/cmd/sgs/include/alist.h
+++ b/usr/src/cmd/sgs/include/alist.h
@@ -229,7 +229,7 @@ typedef struct {
* Possible values returned by aplist_test()
*/
typedef enum {
- ALE_ALLOCFAIL = 0, /* Memory allocation error */
+ ALE_ALLOCFAIL = 0, /* memory allocation error */
ALE_EXISTS = 1, /* alist entry already exists */
ALE_NOTFND = 2, /* item not found and insert not required */
ALE_CREATE = 3 /* alist entry created */
diff --git a/usr/src/cmd/sgs/include/conv.h b/usr/src/cmd/sgs/include/conv.h
index 28df496cd8..93c2d2ce39 100644
--- a/usr/src/cmd/sgs/include/conv.h
+++ b/usr/src/cmd/sgs/include/conv.h
@@ -193,7 +193,7 @@ typedef union {
} Conv_grphdl_flags_buf_t;
/* conv_grpdesc_flags() */
-#define CONV_GRPDESC_FLAGS_BUFSIZE 102
+#define CONV_GRPDESC_FLAGS_BUFSIZE 91
typedef union {
Conv_inv_buf_t inv_buf;
char buf[CONV_GRPDESC_FLAGS_BUFSIZE];
@@ -251,8 +251,8 @@ typedef union {
/* conv_phdr_flags() */
#define CONV_PHDR_FLAGS_BUFSIZE 57
typedef union {
- Conv_inv_buf_t inv_buf;
- char buf[CONV_PHDR_FLAGS_BUFSIZE];
+ Conv_inv_buf_t inv_buf;
+ char buf[CONV_PHDR_FLAGS_BUFSIZE];
} Conv_phdr_flags_buf_t;
/* conv_sec_flags() */
@@ -354,7 +354,16 @@ typedef union {
char buf[CONV_VER_FLAGS_BUFSIZE];
} Conv_ver_flags_buf_t;
-
+/*
+ * conv_time()
+ *
+ * This size is based on the maximum "hour.min.sec.fraction: " time that
+ * would be expected of ld().
+ */
+#define CONV_TIME_BUFSIZE 18
+typedef union {
+ char buf[CONV_TIME_BUFSIZE];
+} Conv_time_buf_t;
/*
* Many conversion routines accept a fmt_flags argument of this type
@@ -852,6 +861,8 @@ extern const char *conv_syminfo_boundto(Half, Conv_fmt_flags_t,
Conv_inv_buf_t *);
extern const char *conv_syminfo_flags(Half, Conv_fmt_flags_t,
Conv_syminfo_flags_buf_t *);
+extern const char *conv_time(struct timeval *, struct timeval *,
+ Conv_time_buf_t *);
extern Uts_desc *conv_uts(void);
extern const char *conv_ver_flags(Half, Conv_fmt_flags_t,
Conv_ver_flags_buf_t *);
diff --git a/usr/src/cmd/sgs/include/debug.h b/usr/src/cmd/sgs/include/debug.h
index d8db81bddb..4f0c68e851 100644
--- a/usr/src/cmd/sgs/include/debug.h
+++ b/usr/src/cmd/sgs/include/debug.h
@@ -43,6 +43,7 @@
* start with the `Elf_' prefix. These latter routines are the only
* routines used by the elfdump(1) utility.
*/
+#include <sys/times.h>
#include <sgs.h>
#include <libld.h>
#include <rtld.h>
@@ -160,6 +161,10 @@ typedef struct {
uint_t d_class; /* debugging classes */
uint_t d_extra; /* extra public information */
APlist *d_list; /* accepted link-map list names */
+ struct timeval d_totaltime; /* total time since entry - */
+ /* gettimeofday(3c) */
+ struct timeval d_deltatime; /* delta time since last diagnostic - */
+ /* gettimeofday(3c) */
} Dbg_desc;
extern Dbg_desc *dbg_desc;
@@ -180,6 +185,9 @@ extern Dbg_desc *dbg_desc;
#define DBG_E_STDNL 0x00000008 /* standard newline indicator */
#define DBG_E_HELP 0x00000010 /* help requested */
#define DBG_E_HELP_EXIT 0x00000020 /* hint: user should exit after help */
+#define DBG_E_TTIME 0x00000040 /* prepend total time */
+#define DBG_E_DTIME 0x00000080 /* prepend delta time */
+#define DBG_E_RESET 0x00000100 /* reset times */
/* ld only */
#define DBG_E_SNAME 0x00001000 /* prepend simple name */
@@ -197,12 +205,25 @@ extern Dbg_desc *dbg_desc;
#define DBG_NOTDETAIL() !(dbg_desc->d_extra & DBG_E_DETAIL)
#define DBG_NOTLONG() !(dbg_desc->d_extra & DBG_E_LONG)
+#define DBG_ISDEMANGLE() \
+ (dbg_desc->d_extra & DBG_E_DEMANGLE)
+
+#define DBG_TOTALTIME (dbg_desc->d_totaltime)
+#define DBG_DELTATIME (dbg_desc->d_deltatime)
+
+#define DBG_ISTTIME() (dbg_desc->d_extra & DBG_E_TTIME)
+#define DBG_ISDTIME() (dbg_desc->d_extra & DBG_E_DTIME)
+#define DBG_ISTIME() (dbg_desc->d_extra & (DBG_E_TTIME | DBG_E_DTIME))
+#define DBG_NOTTIME() !(dbg_desc->d_extra & (DBG_E_TTIME | DBG_E_DTIME))
+
+#define DBG_ISRESET() (dbg_desc->d_extra & DBG_E_RESET)
+#define DBG_ONRESET() (dbg_desc->d_extra |= DBG_E_RESET)
+#define DBG_OFFRESET() (dbg_desc->d_extra &= ~DBG_E_RESET)
+
#define DBG_ISSNAME() (dbg_desc->d_extra & DBG_E_SNAME)
#define DBG_ISFNAME() (dbg_desc->d_extra & DBG_E_FNAME)
#define DBG_ISCLASS() (dbg_desc->d_extra & DBG_E_CLASS)
#define DBG_ISLMID() (dbg_desc->d_extra & DBG_E_LMID)
-#define DBG_ISDEMANGLE() \
- (dbg_desc->d_extra & DBG_E_DEMANGLE)
/*
* Print routine, this must be supplied by the application. The initial
@@ -648,8 +669,8 @@ extern void Dbg_help(void);
/*
* External Dbg_*() interface routines.
*/
-extern void Dbg_args_files(Lm_list *, int, char *);
-extern void Dbg_args_opts(Lm_list *, int, int, char *);
+extern void Dbg_args_file(Lm_list *, int, char *);
+extern void Dbg_args_option(Lm_list *, int, int, char *);
extern void Dbg_args_str2chr(Lm_list *, int, const char *, int);
extern void Dbg_args_Wldel(Lm_list *, int, const char *);
extern void Dbg_audit_ignore(Rt_map *);
@@ -662,6 +683,14 @@ extern void Dbg_audit_skip(Lm_list *, const char *, const char *);
extern void Dbg_audit_terminate(Lm_list *, const char *);
extern void Dbg_audit_version(Lm_list *, const char *, ulong_t);
+extern void Dbg_basic_collect(Lm_list *);
+extern void Dbg_basic_create(Lm_list *);
+extern void Dbg_basic_finish(Lm_list *);
+extern void Dbg_basic_files(Lm_list *);
+extern void Dbg_basic_options(Lm_list *);
+extern void Dbg_basic_relocate(Lm_list *);
+extern void Dbg_basic_validate(Lm_list *);
+
extern void Dbg_bind_global(Rt_map *, Addr, Off, Xword, Pltbindtype,
Rt_map *, Addr, Off, const char *, uint_t);
extern void Dbg_bind_plt_summary(Lm_list *, Half, Word, Word, Word, Word,
@@ -885,9 +914,9 @@ extern void Dbg_util_intoolate(Rt_map *);
extern void Dbg_util_lcinterface(Rt_map *, int, char *);
extern void Dbg_util_nl(Lm_list *, int);
extern void Dbg_util_no_init(Rt_map *);
-extern void Dbg_util_str(Lm_list *, const char *);
extern void Dbg_util_scc_entry(Rt_map *, uint_t);
extern void Dbg_util_scc_title(Lm_list *, int);
+extern void Dbg_util_str(Lm_list *, const char *);
extern void Dbg_unused_file(Lm_list *, const char *, int, uint_t);
extern void Dbg_unused_lcinterface(Rt_map *, Rt_map *, int);
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 */
diff --git a/usr/src/cmd/sgs/libconv/Makefile.com b/usr/src/cmd/sgs/libconv/Makefile.com
index 35875f0358..68a360da5f 100644
--- a/usr/src/cmd/sgs/libconv/Makefile.com
+++ b/usr/src/cmd/sgs/libconv/Makefile.com
@@ -47,7 +47,8 @@ COMOBJS= arch.o c_literal.o \
relocate_sparc.o sections.o \
segments.o strproc.o \
symbols.o syminfo.o \
- tokens.o version.o
+ tokens.o time.o \
+ version.o
ELFCAP_OBJS= elfcap.o
@@ -65,7 +66,8 @@ BLTOBJS= arch_msg.o c_literal_msg.o \
relocate_i386_msg.o relocate_sparc_msg.o \
sections_msg.o segments_msg.o \
symbols_msg.o symbols_sparc_msg.o \
- syminfo_msg.o version_msg.o
+ syminfo_msg.o time_msg.o \
+ version_msg.o
OBJECTS = $(COMOBJS) $(COMOBJS32) $(COMOBJS64) $(ELFCAP_OBJS) \
diff --git a/usr/src/cmd/sgs/libconv/common/group.c b/usr/src/cmd/sgs/libconv/common/group.c
index c0e09d99db..3fb596b059 100644
--- a/usr/src/cmd/sgs/libconv/common/group.c
+++ b/usr/src/cmd/sgs/libconv/common/group.c
@@ -60,6 +60,8 @@ const char *
conv_grphdl_flags(uint_t flags, Conv_grphdl_flags_buf_t *grphdl_flags_buf)
{
static const Val_desc vda[] = {
+ { GPH_PUBLIC, MSG_GPH_PUBLIC },
+ { GPH_PRIVATE, MSG_GPH_PRIVATE },
{ GPH_ZERO, MSG_GPH_ZERO },
{ GPH_LDSO, MSG_GPH_LDSO },
{ GPH_FIRST, MSG_GPH_FIRST },
@@ -118,8 +120,8 @@ conv_grpdesc_flags(uint_t flags, Conv_grpdesc_flags_buf_t *grpdesc_flags_buf)
{ GPD_ADDEPS, MSG_GPD_ADDEPS },
{ GPD_PARENT, MSG_GPD_PARENT },
{ GPD_FILTER, MSG_GPD_FILTER },
- { GPD_PROMOTE, MSG_GPD_PROMOTE },
{ GPD_REMOVE, MSG_GPD_REMOVE },
+ { GPD_MODECHANGE, MSG_GPD_MODECHANGE },
{ 0, 0 }
};
static CONV_EXPN_FIELD_ARG conv_arg = {
diff --git a/usr/src/cmd/sgs/libconv/common/group.msg b/usr/src/cmd/sgs/libconv/common/group.msg
index e98cf79c03..c49c6e7283 100644
--- a/usr/src/cmd/sgs/libconv/common/group.msg
+++ b/usr/src/cmd/sgs/libconv/common/group.msg
@@ -20,11 +20,12 @@
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
+@ MSG_GPH_PUBLIC "GPH_PUBLIC"
+@ MSG_GPH_PRIVATE "GPH_PRIVATE"
@ MSG_GPH_ZERO "GPH_ZERO"
@ MSG_GPH_LDSO "GPH_LDSO"
@ MSG_GPH_FIRST "GPH_FIRST"
@@ -37,7 +38,7 @@
@ MSG_GPD_ADDEPS "GPD_ADDEPS"
@ MSG_GPD_PARENT "GPD_PARENT"
@ MSG_GPD_FILTER "GPD_FILTER"
-@ MSG_GPD_PROMOTE "GPD_PROMOTE"
@ MSG_GPD_REMOVE "GPD_REMOVE"
+@ MSG_GPD_MODECHANGE "GPD_MODECHANGE"
@ MSG_GBL_NULL ""
diff --git a/usr/src/cmd/sgs/libconv/common/lintsup.c b/usr/src/cmd/sgs/libconv/common/lintsup.c
index b05e76e13c..306f562f63 100644
--- a/usr/src/cmd/sgs/libconv/common/lintsup.c
+++ b/usr/src/cmd/sgs/libconv/common/lintsup.c
@@ -78,6 +78,7 @@
#include "symbols_msg.h"
#include "symbols_sparc_msg.h"
#include "syminfo_msg.h"
+#include "time_msg.h"
#include "version_msg.h"
void
@@ -110,6 +111,7 @@ foo()
USE(_sgs_msg_libconv_symbols);
USE(_sgs_msg_libconv_symbols_sparc);
USE(_sgs_msg_libconv_syminfo);
+ USE(_sgs_msg_libconv_time);
USE(_sgs_msg_libconv_version);
#undef USE
diff --git a/usr/src/cmd/sgs/libconv/common/llib-lconv b/usr/src/cmd/sgs/libconv/common/llib-lconv
index 2f2c28bce7..58b2f65b39 100644
--- a/usr/src/cmd/sgs/libconv/common/llib-lconv
+++ b/usr/src/cmd/sgs/libconv/common/llib-lconv
@@ -170,6 +170,8 @@ const char *conv_sym_other_vis(uchar_t, Conv_fmt_flags_t,
const char *conv_syminfo_boundto(Half, Conv_fmt_flags_t, Conv_inv_buf_t *);
const char *conv_syminfo_flags(Half, Conv_fmt_flags_t,
Conv_syminfo_flags_buf_t *);
+const char *conv_time(struct timeval *, struct timeval *,
+ Conv_time_buf_t *);
Uts_desc *conv_uts(void);
const char *conv_ver_flags(Half, Conv_fmt_flags_t, Conv_ver_flags_buf_t *);
const char *conv_ver_index(Versym, int, Conv_inv_buf_t *);
diff --git a/usr/src/cmd/sgs/libconv/common/time.c b/usr/src/cmd/sgs/libconv/common/time.c
new file mode 100644
index 0000000000..042f69c008
--- /dev/null
+++ b/usr/src/cmd/sgs/libconv/common/time.c
@@ -0,0 +1,73 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/time.h>
+#include <string.h>
+#include <stdio.h>
+#include "_conv.h"
+#include "time_msg.h"
+
+/*
+ * Translate a struct timeval into a string appropriate for ld(1) and ld.so.1(1)
+ * diagnostics.
+ */
+const char *
+conv_time(struct timeval *oldtime, struct timeval *newtime,
+ Conv_time_buf_t *time_buf)
+{
+ int hour, min;
+ time_t sec;
+ suseconds_t usec;
+
+ sec = newtime->tv_sec - oldtime->tv_sec;
+ if (newtime->tv_usec >= oldtime->tv_usec)
+ usec = newtime->tv_usec - oldtime->tv_usec;
+ else {
+ usec = (newtime->tv_usec + MICROSEC) - oldtime->tv_usec;
+ sec -= 1;
+ }
+
+ /*
+ * The default display is "sec.fraction", but ld(1) has been know to
+ * ascend into minutes, and in worst case scenarios, hours.
+ */
+ if ((min = sec / 60) != 0)
+ sec = sec % 60;
+ if ((hour = min / 60) != 0)
+ min = min % 60;
+
+ if (hour)
+ (void) snprintf(time_buf->buf, sizeof (time_buf->buf),
+ MSG_ORIG(MSG_TIME_HMSF), hour, min, sec, usec);
+ else if (min)
+ (void) snprintf(time_buf->buf, sizeof (time_buf->buf),
+ MSG_ORIG(MSG_TIME_MSF), min, sec, usec);
+ else
+ (void) snprintf(time_buf->buf, sizeof (time_buf->buf),
+ MSG_ORIG(MSG_TIME_SF), sec, usec);
+
+ return ((const char *)time_buf);
+}
diff --git a/usr/src/cmd/sgs/libconv/common/time.msg b/usr/src/cmd/sgs/libconv/common/time.msg
new file mode 100644
index 0000000000..659f04d7c0
--- /dev/null
+++ b/usr/src/cmd/sgs/libconv/common/time.msg
@@ -0,0 +1,28 @@
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+# or http://www.opensolaris.org/os/licensing.
+# 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
+#
+# Message file for cmd/sgs/libconv/common/time.c
+
+@ MSG_TIME_HMSF "%d.%d.%.2ld.%.6ld: "
+@ MSG_TIME_MSF "%d.%.2ld.%.6ld: "
+@ MSG_TIME_SF "%.2ld.%.6ld: "
diff --git a/usr/src/cmd/sgs/libld/common/args.c b/usr/src/cmd/sgs/libld/common/args.c
index 3823c51bb1..0d18215a68 100644
--- a/usr/src/cmd/sgs/libld/common/args.c
+++ b/usr/src/cmd/sgs/libld/common/args.c
@@ -833,6 +833,7 @@ createargv(Ofl_desc *ofl, int *error)
return (ret);
}
+static int optitle = 0;
/*
* Parsing options pass1 for process_flags().
*/
@@ -855,7 +856,7 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
switch (c) {
case '6':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
/*
* -64 is processed by ld to determine the output class.
@@ -871,12 +872,12 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
continue;
case 'a':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, NULL));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
aflag = TRUE;
break;
case 'b':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, NULL));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
bflag = TRUE;
/*
@@ -893,7 +894,7 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'c':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if (ofl->ofl_config)
eprintf(ofl->ofl_lml, ERR_WARNING,
MSG_INTL(MSG_ARG_MTONCE),
@@ -903,12 +904,12 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'C':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, NULL));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
demangle_flag = 1;
break;
case 'd':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if ((optarg[0] == 'n') && (optarg[1] == '\0')) {
if (dflag != SET_UNKNOWN)
eprintf(ofl->ofl_lml, ERR_WARNING,
@@ -932,7 +933,7 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'e':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if (ofl->ofl_entry)
eprintf(ofl->ofl_lml, ERR_WARNING,
MSG_INTL(MSG_MARG_MTONCE),
@@ -942,7 +943,7 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'f':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if (ofl->ofl_filtees &&
(!(ofl->ofl_flags & FLG_OF_AUX))) {
eprintf(ofl->ofl_lml, ERR_FATAL,
@@ -960,7 +961,7 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'F':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if (ofl->ofl_filtees &&
(ofl->ofl_flags & FLG_OF_AUX)) {
eprintf(ofl->ofl_lml, ERR_FATAL,
@@ -977,7 +978,7 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'h':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if (ofl->ofl_soname)
eprintf(ofl->ofl_lml, ERR_WARNING,
MSG_INTL(MSG_MARG_MTONCE),
@@ -987,12 +988,12 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'i':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, NULL));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
ofl->ofl_flags |= FLG_OF_IGNENV;
break;
case 'I':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if (ofl->ofl_interp)
eprintf(ofl->ofl_lml, ERR_WARNING,
MSG_INTL(MSG_ARG_MTONCE),
@@ -1002,7 +1003,7 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'l':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
/*
* For now, count any library as a shared object. This
* is used to size the internal symbol cache. This
@@ -1013,12 +1014,12 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'm':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, NULL));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
ofl->ofl_flags |= FLG_OF_GENMAP;
break;
case 'o':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if (ofl->ofl_name)
eprintf(ofl->ofl_lml, ERR_WARNING,
MSG_INTL(MSG_MARG_MTONCE),
@@ -1028,7 +1029,7 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'p':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
/*
* Multiple instances of this option may occur. Each
@@ -1044,7 +1045,7 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'P':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
/*
* Multiple instances of this option may occur. Each
@@ -1060,12 +1061,12 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'r':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, NULL));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
rflag = TRUE;
break;
case 'R':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
/*
* Multiple instances of this option may occur. Each
@@ -1081,21 +1082,21 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 's':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, NULL));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
sflag = TRUE;
break;
case 't':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, NULL));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
ofl->ofl_flags |= FLG_OF_NOWARN;
break;
case 'u':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
break;
case 'z':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
/*
* For specific help, print our usage message and exit
@@ -1343,12 +1344,18 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
/*
* A diagnostic can only be provided after dbg_setup().
+ * As this is the first diagnostic that can be produced
+ * by ld(1), issue a title for timing and basic output.
*/
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ if ((optitle == 0) && DBG_ENABLED) {
+ optitle++;
+ DBG_CALL(Dbg_basic_options(ofl->ofl_lml));
+ }
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
break;
case 'B':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if (strcmp(optarg, MSG_ORIG(MSG_ARG_DIRECT)) == 0) {
if (Bdflag == SET_FALSE) {
eprintf(ofl->ofl_lml, ERR_FATAL,
@@ -1393,27 +1400,27 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'G':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, NULL));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
Gflag = TRUE;
break;
case 'L':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
break;
case 'M':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if (aplist_append(&(ofl->ofl_maps), optarg,
AL_CNT_OFL_MAPFILES) == NULL)
return (S_ERROR);
break;
case 'N':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
break;
case 'Q':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if ((optarg[0] == 'n') && (optarg[1] == '\0')) {
if (Qflag != SET_UNKNOWN)
eprintf(ofl->ofl_lml, ERR_WARNING,
@@ -1437,14 +1444,14 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'S':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if (aplist_append(&lib_support, optarg,
AL_CNT_SUPPORT) == NULL)
return (S_ERROR);
break;
case 'V':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, NULL));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
if (!Vflag)
(void) fprintf(stderr, MSG_ORIG(MSG_STR_STRNL),
ofl->ofl_sgsid);
@@ -1452,7 +1459,7 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case 'Y':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, optarg));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
if (strncmp(optarg, MSG_ORIG(MSG_ARG_LCOM), 2) == 0) {
if (Llibdir)
eprintf(ofl->ofl_lml, ERR_WARNING,
@@ -1485,7 +1492,7 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
break;
case '?':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c, NULL));
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
(*error)++;
break;
@@ -1515,13 +1522,13 @@ parseopt_pass2(Ofl_desc *ofl, int argc, char **argv)
switch (c) {
case 'l':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c,
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
optarg));
if (ld_find_library(optarg, ofl) == S_ERROR)
return (S_ERROR);
break;
case 'B':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c,
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
optarg));
if (strcmp(optarg,
MSG_ORIG(MSG_STR_LD_DYNAMIC)) == 0) {
@@ -1539,13 +1546,13 @@ parseopt_pass2(Ofl_desc *ofl, int argc, char **argv)
ofl->ofl_flags &= ~FLG_OF_DYNLIBS;
break;
case 'L':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c,
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
optarg));
if (ld_add_libdir(ofl, optarg) == S_ERROR)
return (S_ERROR);
break;
case 'N':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c,
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
optarg));
/*
* Record DT_NEEDED string
@@ -1569,19 +1576,19 @@ parseopt_pass2(Ofl_desc *ofl, int argc, char **argv)
break;
case 'D':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c,
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
optarg));
(void) dbg_setup(ofl, optarg, 3);
break;
case 'u':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c,
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
optarg));
if (ld_sym_add_u(optarg, ofl,
MSG_STR_COMMAND) == (Sym_desc *)S_ERROR)
return (S_ERROR);
break;
case 'z':
- DBG_CALL(Dbg_args_opts(ofl->ofl_lml, ndx, c,
+ DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
optarg));
if ((strncmp(optarg, MSG_ORIG(MSG_ARG_LD32),
MSG_ARG_LD32_SIZE) == 0) ||
@@ -1808,7 +1815,7 @@ process_files_com(Ofl_desc *ofl, int argc, char **argv)
continue;
}
- DBG_CALL(Dbg_args_files(ofl->ofl_lml, optind, path));
+ DBG_CALL(Dbg_args_file(ofl->ofl_lml, optind, path));
ifl = ld_process_open(path, path, &fd, ofl,
(FLG_IF_CMDLINE | FLG_IF_NEEDED), &rej);
@@ -1839,9 +1846,11 @@ process_files_com(Ofl_desc *ofl, int argc, char **argv)
uintptr_t
ld_process_files(Ofl_desc *ofl, int argc, char **argv)
{
+ DBG_CALL(Dbg_basic_files(ofl->ofl_lml));
+
/*
* Process command line files (taking into account any applicable
- * preceeding flags). Return if any fatal errors have occurred.
+ * preceding flags). Return if any fatal errors have occurred.
*/
opterr = 0;
optind = 1;
diff --git a/usr/src/cmd/sgs/libld/common/debug.c b/usr/src/cmd/sgs/libld/common/debug.c
index 4ffa5ef19f..127a921987 100644
--- a/usr/src/cmd/sgs/libld/common/debug.c
+++ b/usr/src/cmd/sgs/libld/common/debug.c
@@ -30,6 +30,7 @@
#include <strings.h>
#include <dlfcn.h>
#include <debug.h>
+#include <conv.h>
#include "msg.h"
/*
@@ -205,6 +206,22 @@ dbg_print(Lm_list *lml, const char *format, ...)
} else
(void) fputs(MSG_INTL(MSG_DBG_DFLT_FMT), dbg_ofile.fptr);
+ if (DBG_ISTIME()) {
+ Conv_time_buf_t buf;
+ struct timeval new;
+
+ if (gettimeofday(&new, NULL) == 0) {
+ if (DBG_ISTTIME())
+ (void) fputs(conv_time(&DBG_TOTALTIME, &new,
+ &buf), stderr);
+ if (DBG_ISDTIME())
+ (void) fputs(conv_time(&DBG_DELTATIME, &new,
+ &buf), stderr);
+
+ DBG_DELTATIME = new;
+ }
+ }
+
va_start(args, format);
(void) vfprintf(dbg_ofile.fptr, format, args);
(void) fprintf(dbg_ofile.fptr, MSG_ORIG(MSG_STR_NL));
diff --git a/usr/src/cmd/sgs/libld/common/ldmain.c b/usr/src/cmd/sgs/libld/common/ldmain.c
index 19ef992801..4c850ec780 100644
--- a/usr/src/cmd/sgs/libld/common/ldmain.c
+++ b/usr/src/cmd/sgs/libld/common/ldmain.c
@@ -35,6 +35,7 @@
* ld -- link/editor main program
*/
#include <sys/types.h>
+#include <sys/time.h>
#include <sys/mman.h>
#include <string.h>
#include <stdio.h>
@@ -114,6 +115,13 @@ ld_main(int argc, char **argv, Half mach)
Ofl_desc *ofl;
/*
+ * Establish a base time. Total time diagnostics are relative to
+ * entering the link-editor here.
+ */
+ (void) gettimeofday(&DBG_TOTALTIME, NULL);
+ DBG_DELTATIME = DBG_TOTALTIME;
+
+ /*
* Initialize signal handlers, and output file variables. Establish a
* default output ELF header to satisfy diagnostic requirements.
*/
@@ -186,10 +194,10 @@ ld_main(int argc, char **argv, Half mach)
do {
if (ld_sup_loadso(ofl, lib) == S_ERROR)
return (ld_exit(ofl));
+ DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
} while ((lib = strtok_r(NULL, sep, &lasts)) != NULL);
}
- DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
}
if (lib_support) {
Aliste idx;
@@ -200,9 +208,9 @@ ld_main(int argc, char **argv, Half mach)
DBG_SUP_CMDLINE));
if (ld_sup_loadso(ofl, lib) == S_ERROR)
return (ld_exit(ofl));
+ DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
}
}
- DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
DBG_CALL(Dbg_ent_print(ofl->ofl_lml,
ofl->ofl_dehdr->e_ident[EI_OSABI], ofl->ofl_dehdr->e_machine,
@@ -383,6 +391,7 @@ ld_main(int argc, char **argv, Half mach)
ld_sup_atexit(ofl, 0);
DBG_CALL(Dbg_statistics_ld(ofl));
+ DBG_CALL(Dbg_basic_finish(ofl->ofl_lml));
/*
* Wrap up debug output file if one is open
diff --git a/usr/src/cmd/sgs/libld/common/outfile.c b/usr/src/cmd/sgs/libld/common/outfile.c
index 8c51c8e1ef..ba81305a91 100644
--- a/usr/src/cmd/sgs/libld/common/outfile.c
+++ b/usr/src/cmd/sgs/libld/common/outfile.c
@@ -377,6 +377,8 @@ ld_create_outfile(Ofl_desc *ofl)
Boolean fixalign = FALSE;
int fd, nseg = 0, shidx, dataidx, ptloadidx = 0;
+ DBG_CALL(Dbg_basic_create(ofl->ofl_lml));
+
/*
* If DF_1_NOHDR was set in map_parse() or FLG_OF1_VADDR was set,
* we need to do alignment adjustment.
diff --git a/usr/src/cmd/sgs/libld/common/relocate.c b/usr/src/cmd/sgs/libld/common/relocate.c
index 2f31d506b1..307f7ef426 100644
--- a/usr/src/cmd/sgs/libld/common/relocate.c
+++ b/usr/src/cmd/sgs/libld/common/relocate.c
@@ -2138,6 +2138,8 @@ ld_reloc_init(Ofl_desc *ofl)
Is_desc *isp;
Sym_desc *sdp;
+ DBG_CALL(Dbg_basic_collect(ofl->ofl_lml));
+
/*
* At this point we have finished processing all input symbols. Make
* sure we add any absolute (internal) symbols before continuing with
@@ -2381,6 +2383,8 @@ ld_reloc_process(Ofl_desc *ofl)
ofl_flag_t flags = ofl->ofl_flags;
Shdr *shdr;
+ DBG_CALL(Dbg_basic_relocate(ofl->ofl_lml));
+
/*
* Determine the index of the symbol table that will be referenced by
* the relocation entries.
diff --git a/usr/src/cmd/sgs/libld/common/syms.c b/usr/src/cmd/sgs/libld/common/syms.c
index 6638dac5e6..38b960bc7d 100644
--- a/usr/src/cmd/sgs/libld/common/syms.c
+++ b/usr/src/cmd/sgs/libld/common/syms.c
@@ -1091,6 +1091,8 @@ ld_sym_validate(Ofl_desc *ofl)
int allow_ldynsym;
uchar_t type;
+ DBG_CALL(Dbg_basic_validate(ofl->ofl_lml));
+
/*
* If a symbol is undefined and this link-edit calls for no undefined
* symbols to remain (this is the default case when generating an
diff --git a/usr/src/cmd/sgs/liblddbg/Makefile.com b/usr/src/cmd/sgs/liblddbg/Makefile.com
index b7e2980d05..339d8b9537 100644
--- a/usr/src/cmd/sgs/liblddbg/Makefile.com
+++ b/usr/src/cmd/sgs/liblddbg/Makefile.com
@@ -19,17 +19,15 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
LIBRARY = liblddbg.a
VERS = .4
-COMOBJS = args.o audit.o debug.o syminfo.o \
- tls.o
+COMOBJS = args.o audit.o basic.o debug.o \
+ syminfo.o tls.o
COMOBJS32 = bindings32.o cap32.o dynamic32.o elf32.o \
entry32.o files32.o got32.o libs32.o \
diff --git a/usr/src/cmd/sgs/liblddbg/common/args.c b/usr/src/cmd/sgs/liblddbg/common/args.c
index e210f32e7b..4b56f4887f 100644
--- a/usr/src/cmd/sgs/liblddbg/common/args.c
+++ b/usr/src/cmd/sgs/liblddbg/common/args.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,7 +29,7 @@
#include "msg.h"
void
-Dbg_args_opts(Lm_list *lml, int ndx, int c, char *optarg)
+Dbg_args_option(Lm_list *lml, int ndx, int c, char *optarg)
{
if (DBG_NOTCLASS(DBG_C_ARGS))
return;
@@ -59,7 +59,7 @@ Dbg_args_Wldel(Lm_list *lml, int ndx, const char *opt)
}
void
-Dbg_args_files(Lm_list *lml, int ndx, char *file)
+Dbg_args_file(Lm_list *lml, int ndx, char *file)
{
if (DBG_NOTCLASS(DBG_C_ARGS))
return;
diff --git a/usr/src/cmd/sgs/liblddbg/common/basic.c b/usr/src/cmd/sgs/liblddbg/common/basic.c
new file mode 100644
index 0000000000..fd66f8af99
--- /dev/null
+++ b/usr/src/cmd/sgs/liblddbg/common/basic.c
@@ -0,0 +1,111 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <debug.h>
+#include "_debug.h"
+#include "msg.h"
+
+/*
+ * This file contains a number of simple title interfaces, that give a basic
+ * trace of a link-edit. These interfaces cross several functional boundaries,
+ * but are consolidated here to ensure consistent use of the DBG_C_BASIC and
+ * DBG_NOTTIME macros.
+ */
+void
+Dbg_basic_collect(Lm_list *lml)
+{
+ if (DBG_NOTCLASS(DBG_C_BASIC) && DBG_NOTTIME())
+ return;
+
+ Dbg_util_nl(lml, DBG_NL_STD);
+ dbg_print(lml, MSG_INTL(MSG_BASIC_COLLECT));
+ Dbg_util_nl(lml, DBG_NL_STD);
+}
+
+void
+Dbg_basic_create(Lm_list *lml)
+{
+ if (DBG_NOTCLASS(DBG_C_BASIC) && DBG_NOTTIME())
+ return;
+
+ Dbg_util_nl(lml, DBG_NL_STD);
+ dbg_print(lml, MSG_INTL(MSG_BASIC_CREATE));
+ Dbg_util_nl(lml, DBG_NL_STD);
+}
+
+void
+Dbg_basic_files(Lm_list *lml)
+{
+ if (DBG_NOTCLASS(DBG_C_BASIC) && DBG_NOTTIME())
+ return;
+
+ Dbg_util_nl(lml, DBG_NL_STD);
+ dbg_print(lml, MSG_INTL(MSG_BASIC_FILES));
+ Dbg_util_nl(lml, DBG_NL_STD);
+}
+void
+Dbg_basic_finish(Lm_list *lml)
+{
+ if (DBG_NOTCLASS(DBG_C_BASIC) && DBG_NOTTIME())
+ return;
+
+ Dbg_util_nl(lml, DBG_NL_STD);
+ dbg_print(lml, MSG_INTL(MSG_BASIC_FINISHED));
+ Dbg_util_nl(lml, DBG_NL_STD);
+}
+
+void
+Dbg_basic_options(Lm_list *lml)
+{
+ if (DBG_NOTCLASS(DBG_C_BASIC) && DBG_NOTTIME())
+ return;
+
+ Dbg_util_nl(lml, DBG_NL_STD);
+ dbg_print(lml, MSG_INTL(MSG_BASIC_OPTIONS));
+ Dbg_util_nl(lml, DBG_NL_STD);
+}
+
+void
+Dbg_basic_relocate(Lm_list *lml)
+{
+ if (DBG_NOTCLASS(DBG_C_BASIC) && DBG_NOTTIME())
+ return;
+
+ Dbg_util_nl(lml, DBG_NL_STD);
+ dbg_print(lml, MSG_INTL(MSG_BASIC_RELOCATE));
+ Dbg_util_nl(lml, DBG_NL_STD);
+}
+
+void
+Dbg_basic_validate(Lm_list *lml)
+{
+ if (DBG_NOTCLASS(DBG_C_BASIC) && DBG_NOTTIME())
+ return;
+
+ Dbg_util_nl(lml, DBG_NL_STD);
+ dbg_print(lml, MSG_INTL(MSG_BASIC_VALIDATE));
+ Dbg_util_nl(lml, DBG_NL_STD);
+}
diff --git a/usr/src/cmd/sgs/liblddbg/common/debug.c b/usr/src/cmd/sgs/liblddbg/common/debug.c
index 110d64938a..7026a6ac80 100644
--- a/usr/src/cmd/sgs/liblddbg/common/debug.c
+++ b/usr/src/cmd/sgs/liblddbg/common/debug.c
@@ -39,7 +39,7 @@
* definition to which most users bind, ld.so.1 must provide its own definition,
* and thus interposition is expected. This item should be defined NODIRECT.
*/
-static Dbg_desc _dbg_desc = { 0, 0, 0 };
+static Dbg_desc _dbg_desc = { 0, 0, NULL, { 0, 0 }, { 0, 0 } };
Dbg_desc *dbg_desc = &_dbg_desc;
int _Dbg_cnt = 0;
@@ -54,6 +54,8 @@ static DBG_options _Dbg_options[] = { /* Options accepted by both linkers */
{MSG_ORIG(MSG_TOK_DETAIL), 0, DBG_E_DETAIL},
{MSG_ORIG(MSG_TOK_LONG), 0, DBG_E_LONG},
{MSG_ORIG(MSG_TOK_HELP), 0, DBG_E_HELP},
+ {MSG_ORIG(MSG_TOK_TTIME), 0, DBG_E_TTIME},
+ {MSG_ORIG(MSG_TOK_DTIME), 0, DBG_E_DTIME},
{MSG_ORIG(MSG_TOK_ALL), DBG_C_ALL, 0},
{MSG_ORIG(MSG_TOK_BASIC), DBG_C_BASIC, 0},
@@ -193,9 +195,18 @@ Dbg_help(void)
dbg_print(0, MSG_INTL(MSG_USE_R4_B));
dbg_print(0, MSG_INTL(MSG_USE_R4_B2));
dbg_print(0, MSG_INTL(MSG_USE_R4_C));
+ dbg_print(0, MSG_INTL(MSG_USE_R4_C2));
+ dbg_print(0, MSG_INTL(MSG_USE_R4_C3));
dbg_print(0, MSG_INTL(MSG_USE_R4_D));
- dbg_print(0, MSG_INTL(MSG_USE_R4_D2));
- dbg_print(0, MSG_INTL(MSG_USE_R4_D3));
+ dbg_print(0, MSG_INTL(MSG_USE_R4_E));
+ dbg_print(0, MSG_INTL(MSG_USE_R4_E2));
+ dbg_print(0, MSG_INTL(MSG_USE_R4_E3));
+ dbg_print(0, MSG_INTL(MSG_USE_R4_F));
+ dbg_print(0, MSG_INTL(MSG_USE_R4_F2));
+ dbg_print(0, MSG_INTL(MSG_USE_R4_F3));
+ dbg_print(0, MSG_INTL(MSG_USE_R4_F4));
+ dbg_print(0, MSG_INTL(MSG_USE_R4_F5));
+ dbg_print(0, MSG_INTL(MSG_USE_R4_F6));
Dbg_util_nl(0, DBG_NL_FRC);
dbg_print(0, MSG_INTL(MSG_USE_HDR_RTLD));
diff --git a/usr/src/cmd/sgs/liblddbg/common/files.c b/usr/src/cmd/sgs/liblddbg/common/files.c
index b4fbd54845..e529e2f0f6 100644
--- a/usr/src/cmd/sgs/liblddbg/common/files.c
+++ b/usr/src/cmd/sgs/liblddbg/common/files.c
@@ -245,6 +245,7 @@ Dbg_file_hdl_action(Grp_hdl *ghp, Rt_map *lmp, int type, uint_t flags)
if (hdl_title) {
Dbg_util_nl(lml, DBG_NL_STD);
if (hdl_str) {
+ Conv_grphdl_flags_buf_t grphdl_flags_buf;
const char *name;
/*
@@ -256,7 +257,9 @@ Dbg_file_hdl_action(Grp_hdl *ghp, Rt_map *lmp, int type, uint_t flags)
else
name = MSG_INTL(MSG_STR_UNKNOWN);
- dbg_print(lml, MSG_INTL(hdl_str), name, EC_NATPTR(ghp));
+ dbg_print(lml, MSG_INTL(hdl_str), name,
+ conv_grphdl_flags(ghp->gh_flags, &grphdl_flags_buf),
+ EC_NATPTR(ghp));
}
hdl_title = 0;
}
diff --git a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg
index 558e1a3c28..a2e64315ac 100644
--- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg
+++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg
@@ -216,10 +216,19 @@
# demangle show C++ symbol names in their demangled form
# detail provide more information in conjunction with
# other options
+# dtime prepend a time delta to diagnostics. The value
+# appears as seconds.fraction, and represents
+# the elapsed time since that last diagnostic.
# long display long object names without truncation
# output=file debug output is sent to the named file
# instead of stderr. If file is empty (\"\"),
# following output will be sent to stderr.
+# ttime prepend a time stamp to diagnostics. The value
+# appears as seconds.fraction, and represents
+# the time since entering ld or ld.so.1.
+# Note, all diagnostics induce a probe affect,
+# which should be taken into account when
+# interpreting dtime and ttime information.
#
# TRANSLATION_NOTE - The next series of messages makes the above output in C
@@ -234,24 +243,46 @@
conjunction with"
@ MSG_USE_R4_B2 " other options"
+# TRANSLATION_NOTE -- do not translate the first token "dtime".
+@ MSG_USE_R4_C " dtime prepend a time delta to diagnostics. \
+ The value"
+@ MSG_USE_R4_C2 " appears as seconds.fraction, and \
+ represents"
+@ MSG_USE_R4_C3 " the elapsed time since that last \
+ diagnostic."
+
# TRANSLATION_NOTE -- do not translate the first token "long".
-@ MSG_USE_R4_C " long display long object names without \
+@ MSG_USE_R4_D " long display long object names without \
truncation"
# TRANSLATION_NOTE -- do not translate the first token "output".
-@ MSG_USE_R4_D " output=file debug output is sent to the \
+@ MSG_USE_R4_E " output=file debug output is sent to the \
named file"
-@ MSG_USE_R4_D2 " instead of stderr. If file is \
+@ MSG_USE_R4_E2 " instead of stderr. If file is \
empty (\"\"),"
-@ MSG_USE_R4_D3 " following output will be \
+@ MSG_USE_R4_E3 " following output will be \
sent to stderr."
+# TRANSLATION_NOTE -- do not translate the first token "ttime".
+@ MSG_USE_R4_F " ttime prepend a time stamp to diagnostics. \
+ The value"
+@ MSG_USE_R4_F2 " appears as seconds.fraction, and \
+ represents"
+@ MSG_USE_R4_F3 " the time since entering ld or \
+ ld.so.1."
+@ MSG_USE_R4_F4 " Note all diagnostics induce a \
+ probe affect,"
+@ MSG_USE_R4_F5 " which should be taken into \
+ account when"
+@ MSG_USE_R4_F6 " interpreting dtime and ttime \
+ information."
+
# TRANSLATION_NOTE - End of reference 4
# TRANSLATION_NOTE - Use the following output in the C locale as reference 5.
#
-# lmid[=name] Prepend link-map list id to diagnostics, and
+# lmid[=name] prepend link-map list id to diagnostics, and
# optionally filter the lists: By default,
# diagnostics are produced for all link-map
# lists except that of the runtime linker
@@ -273,7 +304,7 @@
# TRANSLATION_NOTE -- do not translate the first token "lmid".
-@ MSG_USE_R5_A " lmid[=name] Prepend link-map list id to \
+@ MSG_USE_R5_A " lmid[=name] prepend link-map list id to \
diagnostics, and"
@ MSG_USE_R5_A2 " optionally filter the lists: By \
default,"
@@ -490,6 +521,16 @@
# TRANSLATION_NOTE - End of reference 9
+# Basic processing (ld).
+
+@ MSG_BASIC_COLLECT "collect relocations"
+@ MSG_BASIC_CREATE "create output image"
+@ MSG_BASIC_FILES "process files"
+@ MSG_BASIC_FINISHED "processing finished"
+@ MSG_BASIC_OPTIONS "process options"
+@ MSG_BASIC_RELOCATE "relocate output image"
+@ MSG_BASIC_VALIDATE "validating symbols"
+
# Argument messages
@ MSG_ARG_OPTION "arg[%d]\toption=-%c"
@@ -638,8 +679,8 @@
@ MSG_FIL_DEP_ORPHAN " file=%s; object remains on orphan handle %s"
@ MSG_FIL_DEP_REINST " file=%s; object reinstated %s"
-@ MSG_FIL_HDL_CREATE "handle=%s; creating: 0x%llx"
-@ MSG_FIL_HDL_ADD "handle=%s; adding dependent objects:"
+@ MSG_FIL_HDL_CREATE "handle=%s; creating %s 0x%llx:"
+@ MSG_FIL_HDL_ADD "handle=%s; adding dependent objects %s:"
@ MSG_FIL_HDL_DELETE "handle=%s; inspecting for deletion:"
@ MSG_FIL_HDL_ORPHAN "handle=%s; deletion cannot be completed: moving to \
orphan list:"
@@ -1352,6 +1393,9 @@
@ MSG_TOK_FULLNAME "fullname"
@ MSG_TOK_CLASS "class"
@ MSG_TOK_LMID "lmid"
+@ MSG_TOK_TTIME "ttime"
+@ MSG_TOK_DTIME "dtime"
+
@ MSG_TOK_OUTFILE "output"
@ MSG_TOK_LMID_ALL "ALL"
diff --git a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg
index 98d4ccaef6..56648cadc6 100644
--- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg
+++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg
@@ -15,7 +15,7 @@
* 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
*/
/* LINTLIBRARY */
@@ -34,8 +34,8 @@ int Dbg_setup(dbg_setup_caller_t, const char *, Dbg_desc *, const char **);
const char *
Dbg_demangle_name(const char *);
-void Dbg_args_files(Lm_list *, int, char *);
-void Dbg_args_opts(Lm_list *, int, int, char *);
+void Dbg_args_file(Lm_list *, int, char *);
+void Dbg_args_option(Lm_list *, int, int, char *);
void Dbg_args_str2chr(Lm_list *, int, const char *, int);
void Dbg_args_Wldel(Lm_list *, int, const char *);
void Dbg_audit_ignore(Rt_map *);
@@ -48,6 +48,14 @@ void Dbg_audit_skip(Lm_list *, const char *, const char *);
void Dbg_audit_terminate(Lm_list *, const char *);
void Dbg_audit_version(Lm_list *, const char *, ulong_t);
+void Dbg_basic_collect(Lm_list *);
+void Dbg_basic_create(Lm_list *);
+void Dbg_basic_files(Lm_list *);
+void Dbg_basic_finish(Lm_list *);
+void Dbg_basic_options(Lm_list *);
+void Dbg_basic_relocate(Lm_list *);
+void Dbg_basic_validate(Lm_list *);
+
void Dbg_tls_modactivity(Lm_list *, void *, uint_t);
void Dbg_tls_static_block(Lm_list *, void *, ulong_t, ulong_t);
void Dbg_tls_static_resv(Rt_map *, ulong_t, ulong_t);
diff --git a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers
index dc6b90c4f2..2dba0119b0 100644
--- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers
+++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers
@@ -41,13 +41,13 @@
# MAPFILE HEADER END
#
-SUNWprivate_4.71 {
+SUNWprivate_4.72 {
global:
dbg_desc = NODIRECT; # interposed - ld.so.1(1)
dbg_print = NODIRECT; # interposed - ld(1) and ld.so.1(1)
- Dbg_args_files;
- Dbg_args_opts;
+ Dbg_args_file;
+ Dbg_args_option;
Dbg_args_str2chr;
Dbg_args_Wldel;
Dbg_audit_ignore;
@@ -59,6 +59,14 @@ SUNWprivate_4.71 {
Dbg_audit_terminate;
Dbg_audit_version;
+ Dbg_basic_collect;
+ Dbg_basic_create;
+ Dbg_basic_files;
+ Dbg_basic_finish;
+ Dbg_basic_options;
+ Dbg_basic_relocate;
+ Dbg_basic_validate;
+
Dbg_help;
Dbg_setup;
diff --git a/usr/src/cmd/sgs/packages/Makefile.targ b/usr/src/cmd/sgs/packages/Makefile.targ
index d32d41e1c7..27f0ce4ea1 100644
--- a/usr/src/cmd/sgs/packages/Makefile.targ
+++ b/usr/src/cmd/sgs/packages/Makefile.targ
@@ -18,10 +18,7 @@
#
# CDDL HEADER END
#
-#
-# ident "%Z%%M% %I% %E% SMI"
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
pkginfo: ../common/pkginfo.tmpl awk_pkginfo
@@ -29,7 +26,7 @@ pkginfo: ../common/pkginfo.tmpl awk_pkginfo
pkg: FRC
@ $(RM) -r $(PACKAGE)
- pkgmk -l 20000 -f prototype_$(MACH) -d $(PKGARCHIVE) -r $(ROOT) \
+ pkgmk -f prototype_$(MACH) -d $(PKGARCHIVE) -r $(ROOT) \
-o $(PACKAGE) 2>&1 | egrep -v "$(SRC)|parametric paths may"
pkgtrans -o -s $(PKGARCHIVE) $(PACKAGE).tmp $(PACKAGE)
$(RM) -r $(PKGARCHIVE)/$(PACKAGE)
diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README
index b46a2806c5..6e023b14cf 100644
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README
@@ -1254,6 +1254,7 @@ Bugid Risk Synopsis
6805502 The addition of "inline" keywords to sgs code broke the lint
verification in S10
6807864 ld.so.1 is susceptible to a fatal dlsym()/setlocale() race
+6826410 ld needs to sort sections using 32-bit sort keys
--------------------------------------------------------------------------------
All the above changes are incorporated in the following patches:
Solaris/SunOS 5.10_sparc patch TXXXXXX-XX
@@ -1478,3 +1479,4 @@ Bugid Risk Synopsis
6806791 filter builds could be optimized (link-editor components only)
6823371 calloc() uses suboptimal memset() causing 15% regression in SpecCPU2006
gcc code (link-editor components only)
+6831308 ld.so.1: symbol rescanning does a little too much work
diff --git a/usr/src/cmd/sgs/rtld/common/_elf.h b/usr/src/cmd/sgs/rtld/common/_elf.h
index 6babcb8c78..0e010fab08 100644
--- a/usr/src/cmd/sgs/rtld/common/_elf.h
+++ b/usr/src/cmd/sgs/rtld/common/_elf.h
@@ -53,7 +53,7 @@ extern int elf_copy_reloc(char *, Sym *, Rt_map *, void *, Sym *,
extern Sym *elf_find_sym(Slookup *, Rt_map **, uint_t *, int *);
extern Sym *elf_lazy_find_sym(Slookup *, Rt_map **, uint_t *, int *);
extern Rt_map *elf_lazy_load(Rt_map *, Slookup *, uint_t, const char *,
- int *);
+ uint_t, Grp_hdl **, int *);
extern Sym *elf_lookup_filtee(Slookup *, Rt_map **, uint_t *, uint_t,
int *);
extern int elf_mach_flags_check(Rej_desc *, Ehdr *);
diff --git a/usr/src/cmd/sgs/rtld/common/_rtld.h b/usr/src/cmd/sgs/rtld/common/_rtld.h
index aa3355ffa0..2dad943572 100644
--- a/usr/src/cmd/sgs/rtld/common/_rtld.h
+++ b/usr/src/cmd/sgs/rtld/common/_rtld.h
@@ -138,7 +138,7 @@ struct fct {
#define AL_CNT_ALIAS 2 /* ALIAS() */
#define AL_CNT_DEPENDS 20 /* DEPENDS() */
#define AL_CNT_CALLERS 20 /* CALLERS() */
-#define AL_CNT_GROUPS 4 /* GROUPS() */
+#define AL_CNT_GROUPS 20 /* GROUPS() */
#define AL_CNT_COPYREL 10 /* COPY() */
#define AL_CNT_LAZYFIND 10 /* elf_lazy_find_sym() */
#define AL_CNT_GRPCLCT 10 /* gdp_collect() */
@@ -567,7 +567,7 @@ extern APlist *free_alp; /* defragmentation list */
extern uint_t audit_argcnt; /* no. of stack args to copy */
extern Audit_desc *auditors; /* global auditors */
-extern char **_environ;
+extern char **_environ; /* environ reference for libc */
extern const char *dbg_file; /* debugging directed to a file */
@@ -629,7 +629,7 @@ extern uint_t expand(char **, size_t *, char **, uint_t, uint_t,
Rt_map *);
extern int expand_paths(Rt_map *, const char *, Alist **, Aliste,
uint_t, uint_t);
-extern void free_hdl(Grp_hdl *, Rt_map *, uint_t);
+extern void free_hdl(Grp_hdl *);
extern void file_notfound(Lm_list *, const char *, Rt_map *,
uint_t, Rej_desc *);
extern int find_path(Lm_list *, Rt_map *, uint_t, Fdesc *,
@@ -642,7 +642,7 @@ extern void fpavl_remove(Rt_map *);
extern size_t fullpath(Rt_map *, Fdesc *);
extern Lmid_t get_linkmap_id(Lm_list *);
extern Pdesc *get_next_dir(Spath_desc *, Rt_map *, uint_t);
-extern int hdl_add(Grp_hdl *, Rt_map *, uint_t);
+extern Grp_desc *hdl_add(Grp_hdl *, Rt_map *, uint_t, int *);
extern Grp_hdl *hdl_create(Lm_list *, Rt_map *, Rt_map *, uint_t,
uint_t, uint_t);
extern int hdl_initialize(Grp_hdl *, Rt_map *, int, int);
diff --git a/usr/src/cmd/sgs/rtld/common/analyze.c b/usr/src/cmd/sgs/rtld/common/analyze.c
index 09400a8940..4afa82c9c3 100644
--- a/usr/src/cmd/sgs/rtld/common/analyze.c
+++ b/usr/src/cmd/sgs/rtld/common/analyze.c
@@ -447,7 +447,7 @@ _relocate_lmc(Lm_list *lml, Aliste lmco, Rt_map *nlmp, int *relocated,
DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
free(COPY_S(nlmp));
- COPY_S(nlmp) = 0;
+ COPY_S(nlmp) = NULL;
}
return (1);
}
@@ -689,17 +689,24 @@ _is_so_matched(const char *name, const char *str, int path)
* Determine whether a search name matches one of the names associated with a
* link-map. A link-map contains several names:
*
- * . a NAME() - typically the full pathname of an object that has been
- * loaded. For example, when looking for the dependency "libc.so.1", a
- * search path is applied, with the eventual NAME() being "/lib/libc.so.1".
- * The name of a dynamic executable can be a simple filename, such as
- * "main", as this can be the name passed to exec() to start the process.
+ * - a NAME() - this is the basename of the dynamic executable that started
+ * the process, and the path name of any dependencies used by the process.
+ * Most executables are received as full path names, as exec() prepends a
+ * search $PATH to locate the executable. However, simple file names can
+ * be received from exec() if the file is executed from the present working
+ * directory. Regardless, ld.so.1 maintains NAME() as the basename, as
+ * this has always been the name used in diagnostics and error messages.
+ * Most dependencies are full path names, as the typical search for a
+ * dependency, say "libx.so.1", results in search paths being prepended to
+ * the name, which eventually open "/lib/libx.so.1". However, relative
+ * path names can be supplied as dependencies, e.g. dlopen("../libx.so.1").
*
- * . a PATHNAME() - this is maintained if the resolved NAME() is different
- * than NAME(), ie. a component of the original name is a symbolic link.
- * This is also the resolved full pathname for a simple dynamic executable.
+ * - a PATHNAME() - this is the fully resolved path name of the object. This
+ * name will differ from NAME() for all dynamic executables, and may differ
+ * from the NAME() of dependencies, if the dependency is not a full path
+ * name, or the dependency resolves to a symbolic link.
*
- * . an ALIAS() name - these are alternative names by which the object has
+ * - an ALIAS() name - these are alternative names by which the object has
* been found, ie. when dependencies are loaded through a variety of
* different symbolic links.
*
@@ -739,12 +746,12 @@ is_so_matched(Rt_map *lmp, const char *name, int path)
* environment. Once a full path name has been established, the following
* checks are made:
*
- * . does the path exist in the link-map lists FullPathNode AVL tree? if
+ * - does the path exist in the link-map lists FullPathNode AVL tree? if
* so, the file is already loaded, and its associated link-map pointer
* is returned.
- * . does the path exist in the not-found AVL tree? if so, this path has
+ * - does the path exist in the not-found AVL tree? if so, this path has
* already been determined to not exist, and a failure is returned.
- * . a device/inode check, to ensure the same file isn't mapped multiple
+ * - a device/inode check, to ensure the same file isn't mapped multiple
* times through different paths. See file_open().
*
* However, there are cases where a test for an existing file name needs to be
@@ -2147,12 +2154,13 @@ static int
load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
uint_t flags, Grp_hdl **hdl, Rt_map *nlmp)
{
- Aliste idx;
+ Aliste idx1;
Grp_hdl *ghp;
int promote;
+ uint_t rdflags;
/*
- * If this dependency is associated with a required version insure that
+ * If this dependency is associated with a required version ensure that
* the version is present in the loaded file.
*/
if (((rtld_flags & RT_FL_NOVERSION) == 0) && THIS_IS_ELF(clmp) &&
@@ -2163,25 +2171,27 @@ load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
* If this object has indicated that it should be isolated as a group
* (DT_FLAGS_1 contains DF_1_GROUP - object was built with -B group),
* or if the callers direct bindings indicate it should be isolated as
- * a group (DYNINFO flags contains FLG_DI_GROUP - dependency followed
+ * a group (DYNINFO flags contains FLG_DI_GROUP - dependency following
* -zgroupperm), establish the appropriate mode.
*
* The intent of an object defining itself as a group is to isolate the
* relocation of the group within its own members, however, unless
* opened through dlopen(), in which case we assume dlsym() will be used
- * to located symbols in the new object, we still need to associate it
- * with the caller for it to be bound with. This is equivalent to a
- * dlopen(RTLD_GROUP) and dlsym() using the returned handle.
+ * to locate symbols in the new object, we still need to associate the
+ * new object with the caller so that the caller can bind to this new
+ * object. This is equivalent to a dlopen(RTLD_GROUP) and dlsym()
+ * using the returned handle.
*/
if ((FLAGS(nlmp) | flags) & FLG_RT_SETGROUP) {
nmode &= ~RTLD_WORLD;
nmode |= RTLD_GROUP;
/*
- * If the object wasn't explicitly dlopen()'ed associate it with
+ * If the object wasn't explicitly dlopen()'ed, in which case a
+ * handle would have been requested, associate the object with
* the parent.
*/
- if ((flags & FLG_RT_HANDLE) == 0)
+ if ((flags & FLG_RT_PUBHDL) == 0)
nmode |= RTLD_PARENT;
}
@@ -2192,6 +2202,17 @@ load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
FLAGS(nlmp) |= flags;
/*
+ * Establish the flags for any referenced dependency descriptors
+ * (Grp_desc).
+ *
+ * - The referenced object is available for dlsym().
+ * - The referenced object is available to relocate against.
+ * - The referenced object should have it's dependencies
+ * added to this handle
+ */
+ rdflags = (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS);
+
+ /*
* If this is a global object, ensure the associated link-map list can
* be rescanned for global, lazy dependencies.
*/
@@ -2201,59 +2222,83 @@ load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
/*
* If we've been asked to establish a handle create one for this object.
* Or, if this object has already been analyzed, but this reference
- * requires that the mode of the object be promoted, also create a
+ * requires that the mode of the object be promoted, create a private
* handle to propagate the new modes to all this objects dependencies.
*/
- if (((FLAGS(nlmp) | flags) & FLG_RT_HANDLE) || (promote &&
- (FLAGS(nlmp) & FLG_RT_ANALYZED))) {
- uint_t oflags, hflags = 0, cdflags;
+ if ((FLAGS(nlmp) & (FLG_RT_PUBHDL | FLG_RT_PRIHDL)) ||
+ (promote && (FLAGS(nlmp) & FLG_RT_ANALYZED))) {
+ uint_t oflags, hflags, cdflags = 0;
/*
* Establish any flags for the handle (Grp_hdl).
*
- * . Use of the RTLD_FIRST flag indicates that only the first
+ * - Public handles establish dependencies between objects
+ * that must be taken into account when dlclose()'ing
+ * objects. Private handles provide for collecting
+ * dependencies, but do not affect dlclose(). Note that
+ * a handle may already exist, but the public/private
+ * state is set to trigger the required propagation of the
+ * handle's flags and any dependency gathering.
+ * - Use of the RTLD_FIRST flag indicates that only the first
* dependency on the handle (the new object) can be used
* to satisfy dlsym() requests.
*/
+ if (FLAGS(nlmp) & FLG_RT_PUBHDL)
+ hflags = GPH_PUBLIC;
+ else
+ hflags = GPH_PRIVATE;
+
if (nmode & RTLD_FIRST)
- hflags = GPH_FIRST;
+ hflags |= GPH_FIRST;
/*
* Establish the flags for this callers dependency descriptor
* (Grp_desc).
*
- * . The creation of a handle associates a descriptor for the
- * new object and descriptor for the parent (caller).
+ * - The creation of a public handle creates a descriptor
+ * for the referenced object and the caller (parent).
* Typically, the handle is created for dlopen() or for
- * filtering. A handle may also be created to promote
- * the callers modes (RTLD_NOW) to the new object. In this
- * latter case, the handle/descriptor are torn down once
- * the mode propagation has occurred.
- *
- * . Use of the RTLD_PARENT flag indicates that the parent
+ * filtering. A private handle does not need to maintain
+ * a descriptor to the parent.
+ * - Use of the RTLD_PARENT flag indicates that the parent
* can be relocated against.
*/
- if (((FLAGS(nlmp) | flags) & FLG_RT_HANDLE) == 0)
- cdflags = GPD_PROMOTE;
- else
- cdflags = GPD_PARENT;
- if (nmode & RTLD_PARENT)
- cdflags |= GPD_RELOC;
+ if (FLAGS(nlmp) & FLG_RT_PUBHDL) {
+ cdflags |= GPD_PARENT;
+ if (nmode & RTLD_PARENT)
+ cdflags |= GPD_RELOC;
+ }
/*
- * Now that a handle is being created, remove this state from
- * the object so that it doesn't mistakenly get inherited by
- * a dependency.
+ * Now that the handle flags have been established, remove any
+ * handle definition from the referenced object so that the
+ * definitions don't mistakenly get inherited by a dependency.
*/
oflags = FLAGS(nlmp);
- FLAGS(nlmp) &= ~FLG_RT_HANDLE;
+ FLAGS(nlmp) &= ~(FLG_RT_PUBHDL | FLG_RT_PRIHDL);
DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ADD));
- if ((ghp = hdl_create(lml, nlmp, clmp, hflags,
- (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS), cdflags)) == 0)
+ if ((ghp = hdl_create(lml, nlmp, clmp, hflags, rdflags,
+ cdflags)) == NULL)
return (0);
/*
+ * If the new link-map has been promoted, record this mode
+ * change for possible rescan use.
+ */
+ if (promote) {
+ Aliste idx2;
+ Grp_desc *gdp;
+
+ for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
+ if (gdp->gd_depend == nlmp) {
+ gdp->gd_flags |= GPD_MODECHANGE;
+ break;
+ }
+ }
+ }
+
+ /*
* Add any dependencies that are already loaded, to the handle.
*/
if (hdl_initialize(ghp, nlmp, nmode, promote) == 0)
@@ -2263,25 +2308,17 @@ load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
*hdl = ghp;
/*
- * If we were asked to create a handle, we're done.
- */
- if ((oflags | flags) & FLG_RT_HANDLE)
- return (1);
-
- /*
- * If the handle was created to promote modes from the parent
- * (caller) to the new object, then this relationship needs to
- * be removed to ensure the handle doesn't prevent the new
- * objects from being deleted if required. If the parent is
- * the only dependency on the handle, then the handle can be
- * completely removed. However, the handle may have already
- * existed, in which case only the parent descriptor can be
- * deleted from the handle, or at least the GPD_PROMOTE flag
- * removed from the descriptor.
+ * If we were asked to create a public handle, we're done.
*
- * Fall through to carry out any group processing.
- */
- free_hdl(ghp, clmp, GPD_PROMOTE);
+ * If this is a private handle request, then the handle is left
+ * intact with a GPH_PRIVATE identifier. This handle is a
+ * convenience for processing the dependencies of this object,
+ * but does not affect how this object might be dlclose()'d.
+ * For a private handle, fall through to carry out any group
+ * processing.
+ */
+ if (oflags & FLG_RT_PUBHDL)
+ return (1);
}
/*
@@ -2296,35 +2333,42 @@ load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
* Traverse the list of groups our caller is a member of and add this
* new link-map to those groups.
*/
- DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ADD));
- for (APLIST_TRAVERSE(GROUPS(clmp), idx, ghp)) {
- Aliste idx1;
+ for (APLIST_TRAVERSE(GROUPS(clmp), idx1, ghp)) {
+ Aliste idx2;
Grp_desc *gdp;
- int exist;
+ int ale;
Rt_map *dlmp1;
APlist *lmalp = NULL;
+ DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ADD));
+
/*
* If the caller doesn't indicate that its dependencies should
* be added to a handle, ignore it. This case identifies a
* parent of a dlopen(RTLD_PARENT) request.
*/
- for (ALIST_TRAVERSE(ghp->gh_depends, idx1, gdp)) {
+ for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
if (gdp->gd_depend == clmp)
break;
}
if ((gdp->gd_flags & GPD_ADDEPS) == 0)
continue;
- if ((exist = hdl_add(ghp, nlmp,
- (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS))) == 0)
+ if ((gdp = hdl_add(ghp, nlmp, rdflags, &ale)) == NULL)
return (0);
/*
+ * If the new link-map has been promoted, record this mode
+ * change for possible rescan use.
+ */
+ if (promote)
+ gdp->gd_flags |= GPD_MODECHANGE;
+
+ /*
* If this member already exists then its dependencies will
* have already been processed.
*/
- if (exist == ALE_EXISTS)
+ if (ale == ALE_EXISTS)
continue;
/*
@@ -2344,8 +2388,8 @@ load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
if (aplist_append(&lmalp, nlmp, AL_CNT_DEPCLCT) == NULL)
return (0);
- for (APLIST_TRAVERSE(lmalp, idx1, dlmp1)) {
- Aliste idx2;
+ for (APLIST_TRAVERSE(lmalp, idx2, dlmp1)) {
+ Aliste idx3;
Bnd_desc *bdp;
/*
@@ -2353,7 +2397,7 @@ load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
* dynamic dependency list so they can be further
* processed.
*/
- for (APLIST_TRAVERSE(DEPENDS(dlmp1), idx2, bdp)) {
+ for (APLIST_TRAVERSE(DEPENDS(dlmp1), idx3, bdp)) {
Rt_map *dlmp2 = bdp->b_depend;
if ((bdp->b_flags & BND_NEEDED) == 0)
@@ -2369,14 +2413,15 @@ load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
if (nlmp == dlmp1)
continue;
- if ((exist = hdl_add(ghp, dlmp1,
- (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS))) == 0) {
+ if ((gdp =
+ hdl_add(ghp, dlmp1, rdflags, &ale)) == NULL) {
free(lmalp);
return (0);
}
- if (exist == ALE_CREATE)
- (void) update_mode(dlmp1, MODE(dlmp1), nmode);
+ if ((ale == ALE_CREATE) &&
+ (update_mode(dlmp1, MODE(dlmp1), nmode)))
+ gdp->gd_flags |= GPD_MODECHANGE;
}
free(lmalp);
}
@@ -2860,7 +2905,7 @@ core_lookup_sym(Rt_map *ilmp, Slookup *slp, Rt_map **dlmp, uint_t *binfo,
}
static Sym *
-_lazy_find_sym(Rt_map *ilmp, Slookup *slp, Rt_map **dlmp, uint_t *binfo,
+rescan_lazy_find_sym(Rt_map *ilmp, Slookup *slp, Rt_map **dlmp, uint_t *binfo,
int *in_nfavl)
{
Rt_map *lmp;
@@ -2941,7 +2986,7 @@ _lookup_sym(Slookup *slp, Rt_map **dlmp, uint_t *binfo, int *in_nfavl)
lmp = 0;
if (bound < SYMINFO_BT_LOWRESERVE)
lmp = elf_lazy_load(clmp, slp, bound,
- name, in_nfavl);
+ name, 0, NULL, in_nfavl);
/*
* If direct bindings have been disabled, and this isn't
@@ -3071,15 +3116,16 @@ _lookup_sym(Slookup *slp, Rt_map **dlmp, uint_t *binfo, int *in_nfavl)
* initial link-map.
*/
if (sl.sl_flags & LKUP_NEXT)
- sym = _lazy_find_sym(clmp, &sl, dlmp, binfo, in_nfavl);
+ sym = rescan_lazy_find_sym(clmp, &sl, dlmp, binfo,
+ in_nfavl);
else {
Aliste idx;
Lm_cntl *lmc;
for (ALIST_TRAVERSE(lml->lm_lists, idx, lmc)) {
sl.sl_flags |= LKUP_NOFALLBACK;
- if ((sym = _lazy_find_sym(lmc->lc_head, &sl,
- dlmp, binfo, in_nfavl)) != 0)
+ if ((sym = rescan_lazy_find_sym(lmc->lc_head,
+ &sl, dlmp, binfo, in_nfavl)) != NULL)
break;
}
}
@@ -3101,7 +3147,7 @@ Sym *
lookup_sym(Slookup *slp, Rt_map **dlmp, uint_t *binfo, int *in_nfavl)
{
Rt_map *clmp = slp->sl_cmap;
- Sym *rsym = slp->sl_rsym, *sym = 0;
+ Sym *rsym = slp->sl_rsym, *sym = NULL;
uchar_t rtype = slp->sl_rtype;
int mode;
@@ -3161,9 +3207,9 @@ lookup_sym(Slookup *slp, Rt_map **dlmp, uint_t *binfo, int *in_nfavl)
/*
* Try the symbol search again. This retry can be necessary if:
*
- * . a binding has been rejected because of binding to a
+ * - a binding has been rejected because of binding to a
* singleton without going through a singleton search.
- * . a group binding has resulted in binding to a symbol
+ * - a group binding has resulted in binding to a symbol
* that indicates no-direct binding.
*
* Reset the lookup data, and try again.
diff --git a/usr/src/cmd/sgs/rtld/common/cap.c b/usr/src/cmd/sgs/rtld/common/cap.c
index 3b6ec98391..1ad4525cbc 100644
--- a/usr/src/cmd/sgs/rtld/common/cap.c
+++ b/usr/src/cmd/sgs/rtld/common/cap.c
@@ -262,7 +262,7 @@ hwcap_filtees(Alist **alpp, Aliste oidx, const char *dir, Aliste nlmco,
DBG_CALL(Dbg_file_filtee(lml, NAME(flmp), fdp->fd_nname, 0));
nlmp = load_path(lml, nlmco, flmp, mode,
- (flags | FLG_RT_HANDLE), &ghp, fdp, &rej, in_nfavl);
+ (flags | FLG_RT_PUBHDL), &ghp, fdp, &rej, in_nfavl);
if (nlmp == NULL)
continue;
@@ -316,7 +316,8 @@ hwcap_filtees(Alist **alpp, Aliste oidx, const char *dir, Aliste nlmco,
* filter and filtee if necessary.
*/
DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ADD));
- if (nlmp && ghp && (hdl_add(ghp, flmp, GPD_FILTER) == 0))
+ if (nlmp && ghp &&
+ (hdl_add(ghp, flmp, GPD_FILTER, NULL) == NULL))
nlmp = NULL;
/*
diff --git a/usr/src/cmd/sgs/rtld/common/debug.c b/usr/src/cmd/sgs/rtld/common/debug.c
index 1fde0068c0..377a2da34a 100644
--- a/usr/src/cmd/sgs/rtld/common/debug.c
+++ b/usr/src/cmd/sgs/rtld/common/debug.c
@@ -35,6 +35,7 @@
#include <string.h>
#include <thread.h>
#include <debug.h>
+#include <conv.h>
#include "_rtld.h"
#include "_elf.h"
#include "msg.h"
@@ -272,8 +273,6 @@ dbg_print(Lm_list *lml, const char *format, ...)
}
}
- prf.pr_buf = prf.pr_cur = buffer;
- prf.pr_len = ERRSIZE;
prf.pr_fd = dbg_fd;
/*
@@ -281,6 +280,37 @@ dbg_print(Lm_list *lml, const char *format, ...)
*/
_pid = getpid();
+ /*
+ * Each time ld.so.1 is entered, the diagnostic times are reset. It is
+ * useful to convey this reset as part of our diagnostics, but only if
+ * other diagnostics will follow. If a reset has preceded this
+ * diagnostic, print a division line.
+ */
+ if (DBG_ISRESET()) {
+ DBG_OFFRESET();
+
+ prf.pr_buf = prf.pr_cur = buffer;
+ prf.pr_len = ERRSIZE;
+
+ if (lml)
+ (void) bufprint(&prf, MSG_ORIG(MSG_DBG_PID), _pid);
+ else
+ (void) bufprint(&prf, MSG_ORIG(MSG_DBG_UNDEF));
+ prf.pr_cur--;
+
+ (void) bufprint(&prf, MSG_ORIG(MSG_DBG_RESET));
+ (void) dowrite(&prf);
+ }
+
+ /*
+ * Reestablish the buffer for standard printing.
+ */
+ prf.pr_buf = prf.pr_cur = buffer;
+ prf.pr_len = ERRSIZE;
+
+ /*
+ * Establish any diagnostic prefix strings.
+ */
if (lml)
(void) bufprint(&prf, MSG_ORIG(MSG_DBG_PID), _pid);
else
@@ -291,6 +321,25 @@ dbg_print(Lm_list *lml, const char *format, ...)
(void) bufprint(&prf, MSG_ORIG(MSG_DBG_LMID), lml->lm_lmidstr);
prf.pr_cur--;
}
+ if (DBG_ISTIME()) {
+ struct timeval new;
+
+ if (gettimeofday(&new, NULL) == 0) {
+ Conv_time_buf_t buf;
+
+ if (DBG_ISTTIME()) {
+ (void) bufprint(&prf,
+ conv_time(&DBG_TOTALTIME, &new, &buf));
+ prf.pr_cur--;
+ }
+ if (DBG_ISDTIME()) {
+ (void) bufprint(&prf,
+ conv_time(&DBG_DELTATIME, &new, &buf));
+ prf.pr_cur--;
+ }
+ DBG_DELTATIME = new;
+ }
+ }
if (rtld_flags & RT_FL_THREADS) {
(void) bufprint(&prf, MSG_ORIG(MSG_DBG_THREAD), rt_thr_self());
prf.pr_cur--;
diff --git a/usr/src/cmd/sgs/rtld/common/dlfcns.c b/usr/src/cmd/sgs/rtld/common/dlfcns.c
index 02ebfb8715..373a859983 100644
--- a/usr/src/cmd/sgs/rtld/common/dlfcns.c
+++ b/usr/src/cmd/sgs/rtld/common/dlfcns.c
@@ -119,15 +119,16 @@ dlerror()
/*
* Add a dependency as a group descriptor to a group handle. Returns 0 on
- * failure, ALE_EXISTS if the dependency already exists, or ALE_CREATE if it
- * is newly created.
+ * failure. On success, returns the group descriptor, and if alep is non-NULL
+ * the *alep is set to ALE_EXISTS if the dependency already exists, or to
+ * ALE_CREATE if the dependency is newly created.
*/
-int
-hdl_add(Grp_hdl *ghp, Rt_map *lmp, uint_t flags)
+Grp_desc *
+hdl_add(Grp_hdl *ghp, Rt_map *lmp, uint_t dflags, int *alep)
{
Grp_desc *gdp;
Aliste idx;
- int found = ALE_CREATE;
+ int ale = ALE_CREATE;
uint_t oflags;
/*
@@ -135,12 +136,12 @@ hdl_add(Grp_hdl *ghp, Rt_map *lmp, uint_t flags)
*/
for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) {
if (gdp->gd_depend == lmp) {
- found = ALE_EXISTS;
+ ale = ALE_EXISTS;
break;
}
}
- if (found == ALE_CREATE) {
+ if (ale == ALE_CREATE) {
Grp_desc gd;
/*
@@ -153,49 +154,63 @@ hdl_add(Grp_hdl *ghp, Rt_map *lmp, uint_t flags)
* Indicate this object is a part of this handles group.
*/
if (aplist_append(&GROUPS(lmp), ghp, AL_CNT_GROUPS) == NULL)
- return (0);
+ return (NULL);
/*
* Append the new dependency to this handle.
*/
if ((gdp = alist_append(&ghp->gh_depends, &gd,
sizeof (Grp_desc), AL_CNT_DEPENDS)) == NULL)
- return (0);
+ return (NULL);
}
oflags = gdp->gd_flags;
- gdp->gd_flags |= flags;
+ gdp->gd_flags |= dflags;
if (DBG_ENABLED) {
- if (found == ALE_CREATE)
+ if (ale == ALE_CREATE)
DBG_CALL(Dbg_file_hdl_action(ghp, lmp, DBG_DEP_ADD,
gdp->gd_flags));
else if (gdp->gd_flags != oflags)
DBG_CALL(Dbg_file_hdl_action(ghp, lmp, DBG_DEP_UPDATE,
gdp->gd_flags));
}
- return (found);
+
+ if (alep)
+ *alep = ale;
+ return (gdp);
}
/*
* Create a handle.
+ *
+ * rlmp - represents the reference link-map for which the handle is being
+ * created.
+ * clmp - represents the caller who is requesting the handle.
+ * hflags - provide group handle flags (GPH_*) that affect the use of the
+ * handle, such as dlopen(0), or use or use of RTLD_FIRST.
+ * rdflags - provide group dependency flags for the reference link-map rlmp,
+ * such as whether the dependency can be used for dlsym(), can be
+ * relocated against, or whether this objects dependencies should
+ * be processed.
+ * cdflags - provide group dependency flags for the caller.
*/
Grp_hdl *
-hdl_create(Lm_list *lml, Rt_map *nlmp, Rt_map *clmp, uint_t hflags,
- uint_t ndflags, uint_t cdflags)
+hdl_create(Lm_list *lml, Rt_map *rlmp, Rt_map *clmp, uint_t hflags,
+ uint_t rdflags, uint_t cdflags)
{
- Grp_hdl *ghp = NULL, *_ghp;
+ Grp_hdl *ghp = NULL, *aghp;
APlist **alpp;
Aliste idx;
/*
* For dlopen(0) the handle is maintained as part of the link-map list,
- * otherwise it is associated with the referenced link-map.
+ * otherwise the handle is associated with the reference link-map.
*/
if (hflags & GPH_ZERO)
alpp = &(lml->lm_handle);
else
- alpp = &(HANDLES(nlmp));
+ alpp = &(HANDLES(rlmp));
/*
* Objects can contain multiple handles depending on the handle flags
@@ -206,9 +221,9 @@ hdl_create(Lm_list *lml, Rt_map *nlmp, Rt_map *clmp, uint_t hflags,
* sense for RTLD_FIRST. Determine if an appropriate handle already
* exists.
*/
- for (APLIST_TRAVERSE(*alpp, idx, _ghp)) {
- if ((_ghp->gh_flags & GPH_FIRST) == (hflags & GPH_FIRST)) {
- ghp = _ghp;
+ for (APLIST_TRAVERSE(*alpp, idx, aghp)) {
+ if ((aghp->gh_flags & GPH_FIRST) == (hflags & GPH_FIRST)) {
+ ghp = aghp;
break;
}
}
@@ -216,12 +231,12 @@ hdl_create(Lm_list *lml, Rt_map *nlmp, Rt_map *clmp, uint_t hflags,
if (ghp == NULL) {
uint_t ndx;
- DBG_CALL(Dbg_file_hdl_title(DBG_HDL_CREATE));
-
/*
- * If this is the first dlopen() request for this handle
- * allocate and initialize a new handle.
+ * If this is the first request for this handle, allocate and
+ * initialize a new handle.
*/
+ DBG_CALL(Dbg_file_hdl_title(DBG_HDL_CREATE));
+
if ((ghp = malloc(sizeof (Grp_hdl))) == NULL)
return (NULL);
@@ -262,18 +277,27 @@ hdl_create(Lm_list *lml, Rt_map *nlmp, Rt_map *clmp, uint_t hflags,
ghp->gh_ownlmp = lml->lm_head;
ghp->gh_ownlml = lml;
} else {
- ghp->gh_ownlmp = nlmp;
- ghp->gh_ownlml = LIST(nlmp);
+ ghp->gh_ownlmp = rlmp;
+ ghp->gh_ownlml = LIST(rlmp);
- if (hdl_add(ghp, nlmp, ndflags) == 0)
+ if (hdl_add(ghp, rlmp, rdflags, NULL) == NULL)
return (NULL);
/*
- * Indicate that a local group now exists. This state
- * allows singleton searches to be optimized.
+ * If this new handle is a private handle, there's no
+ * need to track the caller, so we're done.
+ */
+ if (hflags & GPH_PRIVATE)
+ return (ghp);
+
+ /*
+ * If this new handle is public, and isn't a special
+ * handle representing ld.so.1, indicate that a local
+ * group now exists. This state allows singleton
+ * searches to be optimized.
*/
if ((hflags & GPH_LDSO) == 0)
- LIST(nlmp)->lm_flags |= LML_FLG_GROUPSEXIST;
+ LIST(rlmp)->lm_flags |= LML_FLG_GROUPSEXIST;
}
} else {
/*
@@ -310,14 +334,37 @@ hdl_create(Lm_list *lml, Rt_map *nlmp, Rt_map *clmp, uint_t hflags,
gdp->gd_depend, DBG_DEP_REINST, 0));
}
}
+
+ /*
+ * If we've been asked to create a private handle, there's no
+ * need to track the caller.
+ */
+ if (hflags & GPH_PRIVATE) {
+ /*
+ * Negate the reference count increment.
+ */
+ ghp->gh_refcnt--;
+ return (ghp);
+ } else {
+ /*
+ * If a private handle already exists, promote this
+ * handle to public by initializing both the reference
+ * count and the handle flags.
+ */
+ if (ghp->gh_flags & GPH_PRIVATE) {
+ ghp->gh_refcnt = 1;
+ ghp->gh_flags &= ~GPH_PRIVATE;
+ ghp->gh_flags |= hflags;
+ }
+ }
}
/*
- * Keep track of the parent (caller). As this object could be opened
+ * Keep track of the parent (caller). As this object can be referenced
* by different parents, this processing is carried out every time a
* handle is requested.
*/
- if (clmp && (hdl_add(ghp, clmp, cdflags) == 0))
+ if (clmp && (hdl_add(ghp, clmp, cdflags, NULL) == NULL))
return (NULL);
return (ghp);
@@ -353,7 +400,7 @@ hdl_initialize(Grp_hdl *ghp, Rt_map *nlmp, int mode, int promote)
DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ADD));
for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) {
- Rt_map * lmp = gdp->gd_depend;
+ Rt_map *lmp = gdp->gd_depend;
Aliste idx1;
Bnd_desc *bdp;
@@ -366,16 +413,19 @@ hdl_initialize(Grp_hdl *ghp, Rt_map *nlmp, int mode, int promote)
continue;
for (APLIST_TRAVERSE(DEPENDS(lmp), idx1, bdp)) {
+ Grp_desc *gdp;
Rt_map *dlmp = bdp->b_depend;
if ((bdp->b_flags & BND_NEEDED) == 0)
continue;
- if (hdl_add(ghp, dlmp,
- (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS)) == 0)
+ if ((gdp = hdl_add(ghp, dlmp,
+ (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS),
+ NULL)) == NULL)
return (0);
- (void) update_mode(dlmp, MODE(dlmp), mode);
+ if (update_mode(dlmp, MODE(dlmp), mode))
+ gdp->gd_flags |= GPD_MODECHANGE;
}
}
ghp->gh_flags |= GPH_INITIAL;
@@ -595,37 +645,48 @@ dlmopen_core(Lm_list *lml, Lm_list *olml, const char *path, int mode,
*/
if (path == NULL) {
Grp_hdl *ghp;
- uint_t hflags = GPH_ZERO, cdflags = GPD_PARENT;
+ uint_t hflags, rdflags, cdflags;
int promote = 0;
/*
* Establish any flags for the handle (Grp_hdl).
*
- * . This is a dummy handle (0) that provides for a dynamic
- * search of all global objects within the process.
- *
- * . Use of the RTLD_FIRST flag indicates that only the first
- * dependency on the handle (the new object) can be used
- * to satisfy dlsym() requests.
+ * - This is a dummy, public, handle (0) that provides for a
+ * dynamic search of all global objects within the process.
+ * - Use of the RTLD_FIRST mode indicates that only the first
+ * dependency on the handle (the referenced object) can be
+ * used to satisfy dlsym() requests.
*/
+ hflags = (GPH_PUBLIC | GPH_ZERO);
if (mode & RTLD_FIRST)
hflags |= GPH_FIRST;
/*
- * Establish the flags for this callers dependency descriptor
+ * Establish the flags for the referenced dependency descriptor
* (Grp_desc).
*
- * . The explicit creation of a handle creates a descriptor
- * for the new object and the parent (caller),
+ * - The referenced object is available for dlsym().
+ * - The referenced object is available to relocate against.
+ * - The referenced object should have it's dependencies
+ * added to this handle.
+ */
+ rdflags = (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS);
+
+ /*
+ * Establish the flags for this callers dependency descriptor
+ * (Grp_desc).
*
- * . Use of the RTLD_PARENT flag indicates that the parent
+ * - The explicit creation of a handle creates a descriptor
+ * for the referenced object and the parent (caller).
+ * - Use of the RTLD_PARENT flag indicates that the parent
* can be relocated against.
*/
+ cdflags = GPD_PARENT;
if (mode & RTLD_PARENT)
cdflags |= GPD_RELOC;
- if ((ghp = hdl_create(lml, 0, clmp, hflags,
- (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS), cdflags)) == NULL)
+ if ((ghp = hdl_create(lml, 0, clmp, hflags, rdflags,
+ cdflags)) == NULL)
return (NULL);
/*
@@ -682,7 +743,7 @@ dlmopen_core(Lm_list *lml, Lm_list *olml, const char *path, int mode,
}
olmco = nlmco;
- nlmp = load_one(lml, nlmco, palp, clmp, mode, (flags | FLG_RT_HANDLE),
+ nlmp = load_one(lml, nlmco, palp, clmp, mode, (flags | FLG_RT_PUBHDL),
&ghp, in_nfavl);
/*
@@ -1209,7 +1270,7 @@ dlsym_core(void *handle, const char *name, Rt_map *clmp, Rt_map **dlmp,
if ((sip->si_flags & SYMINFO_FLG_DIRECT) &&
(sip->si_boundto < SYMINFO_BT_LOWRESERVE))
(void) elf_lazy_load(clmp, &sl,
- sip->si_boundto, name, in_nfavl);
+ sip->si_boundto, name, 0, NULL, in_nfavl);
/*
* Clear the symbol index, so as not to confuse
diff --git a/usr/src/cmd/sgs/rtld/common/elf.c b/usr/src/cmd/sgs/rtld/common/elf.c
index 8ccd79ece4..b1e7204057 100644
--- a/usr/src/cmd/sgs/rtld/common/elf.c
+++ b/usr/src/cmd/sgs/rtld/common/elf.c
@@ -303,11 +303,11 @@ elf_verify(caddr_t addr, size_t size, Fdesc *fdp, const char *name,
* to perform plt relocation on ld.so.1's link-map. The first time lazy loading
* is called we get here to perform these initializations:
*
- * o elf_needed() is called to set up the DYNINFO() indexes for each lazy
+ * - elf_needed() is called to set up the DYNINFO() indexes for each lazy
* dependency. Typically, for all other objects, this is called during
* analyze_so(), but as ld.so.1 is set-contained we skip this processing.
*
- * o For intel, ld.so.1's JMPSLOT relocations need relative updates. These
+ * - For intel, ld.so.1's JMPSLOT relocations need relative updates. These
* are by default skipped thus delaying all relative relocation processing
* on every invocation of ld.so.1.
*/
@@ -332,10 +332,10 @@ elf_rtld_load()
* This is a kludge to give ld.so.1 a performance benefit on i386.
* It's based around two factors.
*
- * o JMPSLOT relocations (PLT's) actually need a relative relocation
+ * - JMPSLOT relocations (PLT's) actually need a relative relocation
* applied to the GOT entry so that they can find PLT0.
*
- * o ld.so.1 does not exercise *any* PLT's before it has made a call
+ * - ld.so.1 does not exercise *any* PLT's before it has made a call
* to elf_lazy_load(). This is because all dynamic dependencies
* are recorded as lazy dependencies.
*/
@@ -353,12 +353,11 @@ elf_rtld_load()
*/
Rt_map *
elf_lazy_load(Rt_map *clmp, Slookup *slp, uint_t ndx, const char *sym,
- int *in_nfavl)
+ uint_t flags, Grp_hdl **hdl, int *in_nfavl)
{
Alist *palp = NULL;
Rt_map *nlmp;
Dyninfo *dip = &DYNINFO(clmp)[ndx], *pdip;
- uint_t flags = 0;
const char *name;
Lm_list *lml = LIST(clmp);
Aliste lmco;
@@ -392,7 +391,7 @@ elf_lazy_load(Rt_map *clmp, Slookup *slp, uint_t ndx, const char *sym,
* is created.
*/
if (dip->di_flags & FLG_DI_GROUP)
- flags |= (FLG_RT_SETGROUP | FLG_RT_HANDLE);
+ flags |= (FLG_RT_SETGROUP | FLG_RT_PUBHDL);
/*
* Lazy dependencies are identified as DT_NEEDED entries with a
@@ -425,7 +424,7 @@ elf_lazy_load(Rt_map *clmp, Slookup *slp, uint_t ndx, const char *sym,
* Load the associated object.
*/
dip->di_info = nlmp =
- load_one(lml, lmco, palp, clmp, MODE(clmp), flags, 0, in_nfavl);
+ load_one(lml, lmco, palp, clmp, MODE(clmp), flags, hdl, in_nfavl);
/*
* Remove any expanded pathname infrastructure. Reduce the pending lazy
@@ -662,7 +661,7 @@ elf_needed(Lm_list *lml, Aliste lmco, Rt_map *clmp, int *in_nfavl)
if (pdyn->d_un.d_val & DF_P1_GROUPPERM) {
dip->di_flags |= FLG_DI_GROUP;
flags =
- (FLG_RT_SETGROUP | FLG_RT_HANDLE);
+ (FLG_RT_SETGROUP | FLG_RT_PUBHDL);
}
}
@@ -956,7 +955,7 @@ _elf_lookup_filtee(Slookup *slp, Rt_map **dlmp, uint_t *binfo, uint_t ndx,
DBG_CALL(Dbg_cap_hw_filter(lml, dir, ilmp));
if (hwcap_filtees((Alist **)&dip->di_info, idx, dir,
lmco, ilmp, filtees, mode,
- (FLG_RT_HANDLE | FLG_RT_HWCAP), in_nfavl) == 0) {
+ (FLG_RT_PUBHDL | FLG_RT_HWCAP), in_nfavl) == 0) {
if ((lml->lm_flags & LML_FLG_TRC_ENABLE) &&
(dip->di_flags & FLG_DI_AUXFLTR) &&
(rtld_flags & RT_FL_WARNFLTR)) {
@@ -1014,20 +1013,49 @@ _elf_lookup_filtee(Slookup *slp, Rt_map **dlmp, uint_t *binfo, uint_t ndx,
#else
if (strcmp(filtee, MSG_ORIG(MSG_PTH_RTLD)) == 0) {
#endif
+ uint_t hflags, rdflags, cdflags;
+
+ /*
+ * Establish any flags for the handle (Grp_hdl).
+ *
+ * - This is a special, public, ld.so.1
+ * handle.
+ * - Only the first object on this handle
+ * can supply symbols.
+ * - This handle provides a filtee.
+ *
+ * Essentially, this handle allows a caller to
+ * reference the dl*() family of interfaces from
+ * ld.so.1.
+ */
+ hflags = (GPH_PUBLIC | GPH_LDSO |
+ GPH_FIRST | GPH_FILTEE);
+
+ /*
+ * Establish the flags for the referenced
+ * dependency descriptor (Grp_desc).
+ *
+ * - ld.so.1 is available for dlsym().
+ * - ld.so.1 is available to relocate
+ * against.
+ * - There's no need to add an dependencies
+ * to this handle.
+ */
+ rdflags = (GPD_DLSYM | GPD_RELOC);
+
/*
- * Create an association between ld.so.1 and the
- * filter. As an optimization, a handle for
- * ld.so.1 itself (required for the dlopen()
- * family filtering mechanism) shouldn't search
- * any dependencies of ld.so.1. Omitting
- * GPD_ADDEPS prevents the addition of any
- * ld.so.1 dependencies to this handle.
+ * Establish the flags for this callers
+ * dependency descriptor (Grp_desc).
+ *
+ * - The explicit creation of a handle
+ * creates a descriptor for the referenced
+ * object and the parent (caller).
*/
+ cdflags = GPD_PARENT;
+
nlmp = lml_rtld.lm_head;
if ((ghp = hdl_create(&lml_rtld, nlmp, ilmp,
- (GPH_LDSO | GPH_FIRST | GPH_FILTEE),
- (GPD_DLSYM | GPD_RELOC), GPD_PARENT)) ==
- NULL)
+ hflags, rdflags, cdflags)) == NULL)
nlmp = NULL;
/*
@@ -1072,10 +1100,10 @@ _elf_lookup_filtee(Slookup *slp, Rt_map **dlmp, uint_t *binfo, uint_t ndx,
* Locate and load the filtee.
*/
if ((nlmp = load_path(lml, lmco, ilmp, mode,
- FLG_RT_HANDLE, &ghp, &fd, &rej,
+ FLG_RT_PUBHDL, &ghp, &fd, &rej,
in_nfavl)) == NULL)
file_notfound(LIST(ilmp), filtee, ilmp,
- FLG_RT_HANDLE, &rej);
+ FLG_RT_PUBHDL, &rej);
filtee = pdp->pd_pname;
@@ -1126,8 +1154,8 @@ _elf_lookup_filtee(Slookup *slp, Rt_map **dlmp, uint_t *binfo, uint_t ndx,
* necessary.
*/
DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ADD));
- if (nlmp && ghp &&
- (hdl_add(ghp, ilmp, GPD_FILTER) == 0))
+ if (nlmp && ghp && (hdl_add(ghp, ilmp,
+ GPD_FILTER, NULL) == NULL))
nlmp = NULL;
/*
@@ -1258,17 +1286,17 @@ _elf_lookup_filtee(Slookup *slp, Rt_map **dlmp, uint_t *binfo, uint_t ndx,
* produced. ldd(1) employs printf(), and here, the selection of whether to
* print a diagnostic in regards to auxiliary filters is a little more complex.
*
- * . The determination of whether to produce an ldd message, or a fatal
+ * - The determination of whether to produce an ldd message, or a fatal
* error message is driven by LML_FLG_TRC_ENABLE.
- * . More detailed ldd messages may also be driven off of LML_FLG_TRC_WARN,
+ * - More detailed ldd messages may also be driven off of LML_FLG_TRC_WARN,
* (ldd -d/-r), LML_FLG_TRC_VERBOSE (ldd -v), LML_FLG_TRC_SEARCH (ldd -s),
* and LML_FLG_TRC_UNREF/LML_FLG_TRC_UNUSED (ldd -U/-u).
*
- * . If the calling object is lddstub, then several classes of message are
+ * - If the calling object is lddstub, then several classes of message are
* suppressed. The user isn't trying to diagnose lddstub, this is simply
* a stub executable employed to preload a user specified library against.
*
- * . If RT_FL_SILENCERR is in effect then any generic ldd() messages should
+ * - If RT_FL_SILENCERR is in effect then any generic ldd() messages should
* be suppressed. All detailed ldd messages should still be produced.
*/
Sym *
@@ -1924,7 +1952,7 @@ elf_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize,
FLAGS1(lmp) |= FL1_RT_DISPREL;
if (dyn->d_un.d_val & DF_1_GROUP)
FLAGS(lmp) |=
- (FLG_RT_SETGROUP | FLG_RT_HANDLE);
+ (FLG_RT_SETGROUP | FLG_RT_PUBHDL);
if ((dyn->d_un.d_val & DF_1_NOW) &&
((rtld_flags2 & RT_FL2_BINDLAZY) == 0)) {
MODE(lmp) |= RTLD_NOW;
@@ -2475,42 +2503,49 @@ elf_dladdr(ulong_t addr, Rt_map *lmp, Dl_info *dlip, void **info, int flags)
}
}
-static void
-elf_lazy_cleanup(APlist *alp)
-{
- Rt_map *lmp;
- Aliste idx;
-
- /*
- * Cleanup any link-maps added to this dynamic list and free it.
- */
- for (APLIST_TRAVERSE(alp, idx, lmp))
- FLAGS(lmp) &= ~FLG_RT_TMPLIST;
- free(alp);
-}
-
/*
* This routine is called as a last fall-back to search for a symbol from a
- * standard relocation. To maintain lazy loadings goal of reducing the number
- * of objects mapped, any symbol search is first carried out using the objects
- * that already exist in the process (either on a link-map list or handle).
- * If a symbol can't be found, and lazy dependencies are still pending, this
- * routine loads the dependencies in an attempt to locate the symbol.
- *
- * Only new objects are inspected as we will have already inspected presently
- * loaded objects before calling this routine. However, a new object may not
- * be new - although the di_lmp might be zero, the object may have been mapped
- * as someone elses dependency. Thus there's a possibility of some symbol
- * search duplication.
+ * standard relocation or dlsym(). To maintain lazy loadings goal of reducing
+ * the number of objects mapped, any symbol search is first carried out using
+ * the objects that already exist in the process (either on a link-map list or
+ * handle). If a symbol can't be found, and lazy dependencies are still
+ * pending, this routine loads the dependencies in an attempt to locate the
+ * symbol.
*/
Sym *
elf_lazy_find_sym(Slookup *slp, Rt_map **_lmp, uint_t *binfo, int *in_nfavl)
{
Sym *sym = NULL;
- APlist *alist = NULL;
- Aliste idx;
- Rt_map *lmp1, *lmp = slp->sl_imap;
+ static APlist *alist = NULL;
+ Aliste idx1;
+ Rt_map *lmp1, *lmp = slp->sl_imap, *clmp = slp->sl_cmap;
const char *name = slp->sl_name;
+ Slookup sl1 = *slp;
+ Lm_list *lml;
+ Lm_cntl *lmc;
+
+ /*
+ * It's quite possible we've been here before to process objects,
+ * therefore reinitialize our dynamic list.
+ */
+ if (alist)
+ aplist_reset(alist);
+
+ /*
+ * Discard any relocation index from further symbol searches. This
+ * index has already been used to trigger any necessary lazy-loads,
+ * and it might be because one of these lazy loads has failed that
+ * we're performing this fallback. By removing the relocation index
+ * we don't try and perform the same failed lazy loading activity again.
+ */
+ sl1.sl_rsymndx = 0;
+
+ /*
+ * Determine the callers link-map list so that we can monitor whether
+ * new objects have been added.
+ */
+ lml = LIST(clmp);
+ lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, CNTL(clmp));
/*
* Generate a local list of new objects to process. This list can grow
@@ -2518,24 +2553,12 @@ elf_lazy_find_sym(Slookup *slp, Rt_map **_lmp, uint_t *binfo, int *in_nfavl)
*/
if (aplist_append(&alist, lmp, AL_CNT_LAZYFIND) == NULL)
return (NULL);
- FLAGS(lmp) |= FLG_RT_TMPLIST;
- for (APLIST_TRAVERSE(alist, idx, lmp1)) {
+ for (APLIST_TRAVERSE(alist, idx1, lmp1)) {
uint_t cnt = 0;
- Slookup sl = *slp;
Dyninfo *dip, *pdip;
/*
- * Discard any relocation index from further symbol searches.
- * This index will have already been used to trigger any
- * necessary lazy-loads, and it might be because one of these
- * lazy loads have failed that we're here performing this
- * fallback. By removing the relocation index we don't try
- * and perform the same failed lazy loading activity again.
- */
- sl.sl_rsymndx = 0;
-
- /*
* Loop through the lazy DT_NEEDED entries examining each object
* for the required symbol. If the symbol is not found, the
* object is in turn added to the local alist, so that the
@@ -2544,7 +2567,11 @@ elf_lazy_find_sym(Slookup *slp, Rt_map **_lmp, uint_t *binfo, int *in_nfavl)
lmp = lmp1;
for (dip = DYNINFO(lmp), pdip = NULL; cnt < DYNINFOCNT(lmp);
cnt++, pdip = dip++) {
- Rt_map *nlmp;
+ Grp_hdl *ghp;
+ Grp_desc *gdp;
+ Rt_map *nlmp, *llmp;
+ Slookup sl2;
+ Aliste idx2;
if (((dip->di_flags & FLG_DI_LAZY) == 0) ||
dip->di_info)
@@ -2566,57 +2593,102 @@ elf_lazy_find_sym(Slookup *slp, Rt_map **_lmp, uint_t *binfo, int *in_nfavl)
}
/*
+ * Determine the last link-map presently on the callers
+ * link-map control list.
+ */
+ llmp = lmc->lc_tail;
+
+ /*
* Try loading this lazy dependency. If the object
* can't be loaded, consider this non-fatal and continue
* the search. Lazy loaded dependencies need not exist
* and their loading should only turn out to be fatal
* if they are required to satisfy a relocation.
*
- * If the file is already loaded and relocated we must
- * still inspect it for symbols, even though it might
- * have already been searched. This lazy load operation
- * might have promoted the permissions of the object,
- * and thus made the object applicable for this symbol
- * search, whereas before the object might have been
- * skipped.
+ * A successful lazy load can mean one of two things:
+ *
+ * - new objects have been loaded, in which case the
+ * objects will have been analyzed, relocated, and
+ * finally moved to the callers control list.
+ * - the objects are already loaded, and this lazy
+ * load has simply associated the referenced object
+ * with it's lazy dependencies.
+ *
+ * If new objects are loaded, look in these objects
+ * first. Note, a new object can be the object being
+ * referenced by this lazy load, however we can also
+ * descend into multiple lazy loads as we relocate this
+ * reference.
+ *
+ * If the symbol hasn't been found, use the referenced
+ * objects handle, as it might have dependencies on
+ * objects that are already loaded. We only need to
+ * look in any existing objects if the mode of those
+ * objects has changed. Existing objects would have
+ * already been searched, however, a lazy load might
+ * still cause the promotion of modes, and in this case
+ * the handle associated with the object is used to
+ * carry out the symbol search.
*/
- if ((nlmp = elf_lazy_load(lmp, &sl, cnt,
- name, in_nfavl)) == NULL)
+ if ((nlmp = elf_lazy_load(lmp, &sl1, cnt, name,
+ FLG_RT_PRIHDL, &ghp, in_nfavl)) == NULL)
continue;
+ if (NEXT_RT_MAP(llmp)) {
+ /*
+ * Look in any new objects.
+ */
+ sl1.sl_imap = NEXT_RT_MAP(llmp);
+ sl1.sl_flags &= ~LKUP_STDRELOC;
+
+ sym = lookup_sym(&sl1, _lmp, binfo, in_nfavl);
+ }
+
/*
- * If this object isn't yet a part of the dynamic list
- * then inspect it for the symbol. If the symbol isn't
- * found add the object to the dynamic list so that we
- * can inspect its dependencies.
+ * Use the objects handle to determine any promoted
+ * objects. Clear any modes regardless. Note, there's
+ * a possibility of overlap with the above search,
+ * should a lazy load bring in new objects and
+ * reference existing objects.
*/
- if (FLAGS(nlmp) & FLG_RT_TMPLIST)
- continue;
+ sl2 = sl1;
+ for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
+ if ((gdp->gd_flags & GPD_MODECHANGE) == 0)
+ continue;
- sl.sl_imap = nlmp;
- if (sym = lookup_sym(&sl, _lmp, binfo, in_nfavl))
- break;
+ if ((sym == NULL) &&
+ (gdp->gd_depend != NEXT_RT_MAP(llmp)) &&
+ (gdp->gd_flags & GPD_DLSYM)) {
+
+ sl2.sl_imap = gdp->gd_depend;
+ sl2.sl_flags |= LKUP_FIRST;
+
+ sym = lookup_sym(&sl2, _lmp, binfo,
+ in_nfavl);
+ }
+ gdp->gd_flags &= ~GPD_MODECHANGE;
+ }
+
+ /*
+ * If the symbol has been found, cleanup and return.
+ */
+ if (sym)
+ return (sym);
/*
* Some dlsym() operations are already traversing a
* link-map (dlopen(0)), and thus there's no need to
- * build our own dynamic dependency list.
+ * save them on the dynamic dependency list.
*/
- if ((sl.sl_flags & LKUP_NODESCENT) == 0) {
- if (aplist_append(&alist, nlmp,
- AL_CNT_LAZYFIND) == NULL) {
- elf_lazy_cleanup(alist);
- return (NULL);
- }
- FLAGS(nlmp) |= FLG_RT_TMPLIST;
- }
+ if (slp->sl_flags & LKUP_NODESCENT)
+ continue;
+
+ if (aplist_test(&alist, nlmp, AL_CNT_LAZYFIND) == NULL)
+ return (NULL);
}
- if (sym)
- break;
}
- elf_lazy_cleanup(alist);
- return (sym);
+ return (NULL);
}
/*
diff --git a/usr/src/cmd/sgs/rtld/common/remove.c b/usr/src/cmd/sgs/rtld/common/remove.c
index 7e978f1eb5..080ec53af8 100644
--- a/usr/src/cmd/sgs/rtld/common/remove.c
+++ b/usr/src/cmd/sgs/rtld/common/remove.c
@@ -27,9 +27,9 @@
/*
* Remove objects. Objects need removal from a process as part of:
*
- * o a dlclose() request
+ * - a dlclose() request
*
- * o tearing down a dlopen(), lazy-load, or filter hierarchy that failed to
+ * - tearing down a dlopen(), lazy-load, or filter hierarchy that failed to
* completely load
*
* Any other failure condition will result in process exit (in which case all
@@ -542,6 +542,13 @@ is_deletable(APlist **lmalp, APlist **ghalp, Rt_map *lmp)
* handles we can ferret out these outsiders.
*/
for (APLIST_TRAVERSE(HANDLES(lmp), idx, ghp)) {
+ /*
+ * If this is a private handle, then the handle isn't referenced
+ * from outside of the group of objects being deleted, and can
+ * be ignored when evaluating objects for deletion.
+ */
+ if (ghp->gh_flags & GPH_PRIVATE)
+ continue;
if (aplist_test(ghalp, ghp, 0) != ALE_EXISTS)
return (0);
}
@@ -551,8 +558,7 @@ is_deletable(APlist **lmalp, APlist **ghalp, Rt_map *lmp)
* objects selected for deletion, it can't be deleted.
*/
for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp)) {
- if (aplist_test(lmalp, bdp->b_caller, 0) !=
- ALE_EXISTS)
+ if (aplist_test(lmalp, bdp->b_caller, 0) != ALE_EXISTS)
return (0);
}
@@ -612,12 +618,12 @@ gdp_collect(APlist **ghalpp, APlist **lmalpp, Grp_hdl *ghp1)
*
* An object is a candidate for deletion if:
*
- * . the object hasn't yet been relocated, in which case
+ * - the object hasn't yet been relocated, in which case
* we're here to clean up a failed load, or
- * . the object doesn't reside on the base link-map control
+ * - the object doesn't reside on the base link-map control
* list, in which case a group of objects, typically
* lazily loaded, or filtees, need cleaning up, or
- * . the object isn't tagged as non-deletable.
+ * - the object isn't tagged as non-deletable.
*/
if ((((FLAGS(lmp) & FLG_RT_RELOCED) == 0) ||
(CNTL(lmp) != ALIST_OFF_DATA) ||
@@ -756,20 +762,14 @@ remove_collect(APlist *ghalp, APlist *lmalp)
}
/*
- * Remove a handle, leaving the associated objects intact. Besides the classic
- * dlopen() usage, handles are used as a means of associating a group of objects
- * and promoting modes. Once object promotion is completed, the handle should
- * be discarded while leaving the associated objects intact. Leaving the handle
- * would prevent the object from being deleted (as it looks like it's in use
- * by another user).
+ * Remove a handle, leaving the associated objects intact.
*/
void
-free_hdl(Grp_hdl *ghp, Rt_map *clmp, uint_t cdflags)
+free_hdl(Grp_hdl *ghp)
{
- Grp_desc *gdp;
- Aliste idx;
-
if (--(ghp->gh_refcnt) == 0) {
+ Grp_desc *gdp;
+ Aliste idx;
uintptr_t ndx;
for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) {
@@ -786,29 +786,6 @@ free_hdl(Grp_hdl *ghp, Rt_map *clmp, uint_t cdflags)
(void) aplist_delete_value(hdl_alp[ndx], ghp);
(void) free(ghp);
-
- } else if (clmp) {
- /*
- * It's possible that an RTLD_NOW promotion (via GPD_PROMOTE)
- * has associated a caller with a handle that is already in use.
- * In this case, find the caller and either remove the caller
- * from the handle, or if the caller is used for any other
- * reason, clear the promotion flag.
- */
- for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) {
- Rt_map *lmp = gdp->gd_depend;
-
- if (lmp != clmp)
- continue;
-
- if (gdp->gd_flags == cdflags) {
- alist_delete(ghp->gh_depends, &idx);
- (void) aplist_delete_value(GROUPS(lmp), ghp);
- } else {
- gdp->gd_flags &= ~cdflags;
- }
- return;
- }
}
}
@@ -865,12 +842,18 @@ remove_lmc(Lm_list *lml, Rt_map *clmp, Aliste lmco, const char *name)
if (HANDLES(lmp)) {
ghp = (Grp_hdl *)HANDLES(lmp)->apl_data[0];
+ /*
+ * If this is a private handle, remove this state, so as to
+ * prevent any attempt to remove the handle more than once.
+ */
+ ghp->gh_flags &= ~GPH_PRIVATE;
+
} else if (lmc->lc_flags & LMC_FLG_RELOCATING) {
/*
* Establish a handle, and should anything fail, fall through
* to remove the link-map control list.
*/
- if (((ghp = hdl_create(lml, lmc->lc_head, 0, 0,
+ if (((ghp = hdl_create(lml, lmc->lc_head, NULL, GPH_PUBLIC,
GPD_ADDEPS, 0)) == NULL) ||
(hdl_initialize(ghp, lmc->lc_head, 0, 0) == 0))
lmc->lc_flags &= ~LMC_FLG_RELOCATING;
@@ -887,7 +870,7 @@ remove_lmc(Lm_list *lml, Rt_map *clmp, Aliste lmco, const char *name)
if (ghp) {
ghp->gh_refcnt = 1;
- free_hdl(ghp, 0, 0);
+ free_hdl(ghp);
}
return;
}
@@ -981,18 +964,18 @@ remove_lmc(Lm_list *lml, Rt_map *clmp, Aliste lmco, const char *name)
* cised to make sure any filtees found aren't being used by filters outside of
* the groups we've collect. The series of events is basically:
*
- * o Determine the groups (handles) that might be deletable.
+ * - Determine the groups (handles) that might be deletable.
*
- * o Determine the objects of these handles that can be deleted.
+ * - Determine the objects of these handles that can be deleted.
*
- * o Fire the fini's of those objects selected for deletion.
+ * - Fire the fini's of those objects selected for deletion.
*
- * o Remove all inter-dependency linked lists while the objects link-maps
+ * - Remove all inter-dependency linked lists while the objects link-maps
* are still available.
*
- * o Remove all deletable objects link-maps and unmap the objects themselves.
+ * - Remove all deletable objects link-maps and unmap the objects themselves.
*
- * o Remove the handle descriptors for each deleted object, and hopefully
+ * - Remove the handle descriptors for each deleted object, and hopefully
* the whole handle.
*
* An handle that can't be deleted is added to an orphans list. This list is
@@ -1257,6 +1240,8 @@ remove_hdl(Grp_hdl *ghp, Rt_map *clmp, int *removed)
DBG_CALL(Dbg_file_hdl_title(DBG_HDL_DELETE));
for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
+ Grp_hdl *ghp3;
+ Aliste idx3;
int flag;
lmp = gdp->gd_depend;
@@ -1287,6 +1272,15 @@ remove_hdl(Grp_hdl *ghp, Rt_map *clmp, int *removed)
flag = DBG_DEP_REMAIN;
DBG_CALL(Dbg_file_hdl_action(ghp, lmp, flag, 0));
+
+ /*
+ * If this object contains any private handles, remove
+ * them now.
+ */
+ for (APLIST_TRAVERSE(HANDLES(lmp), idx3, ghp3)) {
+ if (ghp3->gh_flags & GPH_PRIVATE)
+ free_hdl(ghp3);
+ }
}
}
diff --git a/usr/src/cmd/sgs/rtld/common/rtld.msg b/usr/src/cmd/sgs/rtld/common/rtld.msg
index eba3d4d274..919009d3a3 100644
--- a/usr/src/cmd/sgs/rtld/common/rtld.msg
+++ b/usr/src/cmd/sgs/rtld/common/rtld.msg
@@ -378,6 +378,7 @@
@ MSG_EMG_ENOMEM "internal: Not enough space"
@ MSG_DBG_PID "%5.5d: "
+@ MSG_DBG_RESET "---------\n"
@ MSG_DBG_UNDEF "debug: "
@ MSG_DBG_LMID "%s: "
@ MSG_DBG_THREAD "%d: "
diff --git a/usr/src/cmd/sgs/rtld/common/setup.c b/usr/src/cmd/sgs/rtld/common/setup.c
index 2ac3070ca5..cecdf4f2c0 100644
--- a/usr/src/cmd/sgs/rtld/common/setup.c
+++ b/usr/src/cmd/sgs/rtld/common/setup.c
@@ -197,14 +197,23 @@ setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz,
/*
* Now that ld.so has relocated itself, initialize our own 'environ' so
- * as to establish an address suitable for libc's hardware mul/div
- * magic (libc/sparc/crt/hwmuldiv.o).
+ * as to establish an address suitable for any libc requirements.
*/
_environ = (char **)((ulong_t)auxv - sizeof (char *));
_init();
_environ = envp;
/*
+ * Establish a base time. Total time diagnostics start from entering
+ * ld.so.1 here, however the base time is reset each time the ld.so.1
+ * is re-entered. Note also, there will be a large time associated
+ * with the first diagnostic from ld.so.1, as bootstrapping ld.so.1
+ * and establishing the liblddbg infrastructure takes some time.
+ */
+ (void) gettimeofday(&DBG_TOTALTIME, NULL);
+ DBG_DELTATIME = DBG_TOTALTIME;
+
+ /*
* Determine how ld.so.1 has been executed.
*/
if ((fd == -1) && (phdr == NULL)) {
@@ -855,7 +864,9 @@ setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz,
* that expects the old getpid() initialization handshake.
*/
if ((rpl_debug || prm_debug) && ((rtld_flags & RT_FL_DEBUGGER) == 0)) {
- Dbg_desc _dbg_desc = {0, 0, NULL};
+ Dbg_desc _dbg_desc = {0};
+ struct timeval total = DBG_TOTALTIME;
+ struct timeval delta = DBG_DELTATIME;
if (rpl_debug) {
if (dbg_setup(rpl_debug, &_dbg_desc) == 0)
@@ -867,6 +878,8 @@ setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz,
(void) dbg_setup(prm_debug, &_dbg_desc);
*dbg_desc = _dbg_desc;
+ DBG_TOTALTIME = total;
+ DBG_DELTATIME = delta;
}
/*
diff --git a/usr/src/cmd/sgs/rtld/common/util.c b/usr/src/cmd/sgs/rtld/common/util.c
index f460541cc9..323d57a15e 100644
--- a/usr/src/cmd/sgs/rtld/common/util.c
+++ b/usr/src/cmd/sgs/rtld/common/util.c
@@ -34,6 +34,7 @@
* (with different names) to avoid name space collisions.
*/
#include <stdio.h>
+#include <sys/time.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/lwp.h>
@@ -3040,8 +3041,20 @@ enter(int flags)
if (rt_bind_guard(THR_FLG_RTLD | thr_flg_nolock | flags)) {
if (!thr_flg_nolock)
(void) rt_mutex_lock(&rtldlock);
- if (rtld_flags & RT_FL_OPERATION)
+ if (rtld_flags & RT_FL_OPERATION) {
ld_entry_cnt++;
+
+ /*
+ * Reset the diagnostic time information for each new
+ * "operation". Thus timing diagnostics are relative
+ * to entering ld.so.1.
+ */
+ if (DBG_ISTIME() &&
+ (gettimeofday(&DBG_TOTALTIME, NULL) == 0)) {
+ DBG_DELTATIME = DBG_TOTALTIME;
+ DBG_ONRESET();
+ }
+ }
return (1);
}
return (0);
diff --git a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c
index b3108bdd63..e31f306261 100644
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c
+++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c
@@ -71,11 +71,11 @@ static const mdb_bitmask_t rtflags_bits[] = {
{ MSG_ORIG(MSG_FLG_OBJINTPO), FLG_RT_OBJINTPO, FLG_RT_OBJINTPO},
{ MSG_ORIG(MSG_FLG_SYMINTPO), FLG_RT_SYMINTPO, FLG_RT_SYMINTPO},
{ MSG_ORIG(MSG_FLG_MOVE), FLG_RT_MOVE, FLG_RT_MOVE},
- { MSG_ORIG(MSG_FLG_TMPLIST), FLG_RT_TMPLIST, FLG_RT_TMPLIST},
+ { MSG_ORIG(MSG_FLG_RELOCING), FLG_RT_RELOCING, FLG_RT_RELOCING},
{ MSG_ORIG(MSG_FLG_REGSYMS), FLG_RT_REGSYMS, FLG_RT_REGSYMS},
{ MSG_ORIG(MSG_FLG_INITCLCT), FLG_RT_INITCLCT, FLG_RT_INITCLCT},
- { MSG_ORIG(MSG_FLG_HANDLE), FLG_RT_HANDLE, FLG_RT_HANDLE},
- { MSG_ORIG(MSG_FLG_RELOCING), FLG_RT_RELOCING, FLG_RT_RELOCING},
+ { MSG_ORIG(MSG_FLG_PUBHDL), FLG_RT_PUBHDL, FLG_RT_PUBHDL},
+ { MSG_ORIG(MSG_FLG_PRIHDL), FLG_RT_PRIHDL, FLG_RT_PRIHDL},
{ NULL, 0, 0}
};
@@ -145,6 +145,8 @@ static const mdb_bitmask_t bndflags_bits[] = {
};
static const mdb_bitmask_t grhflags_bits[] = {
+ { MSG_ORIG(MSG_GPH_PUBLIC), GPH_PUBLIC, GPH_PUBLIC },
+ { MSG_ORIG(MSG_GPH_PRIVATE), GPH_PRIVATE, GPH_PRIVATE },
{ MSG_ORIG(MSG_GPH_ZERO), GPH_ZERO, GPH_ZERO },
{ MSG_ORIG(MSG_GPH_LDSO), GPH_LDSO, GPH_LDSO },
{ MSG_ORIG(MSG_GPH_FIRST), GPH_FIRST, GPH_FIRST },
@@ -160,8 +162,8 @@ static const mdb_bitmask_t grdflags_bits[] = {
{ MSG_ORIG(MSG_GPD_ADDEPS), GPD_ADDEPS, GPD_ADDEPS },
{ MSG_ORIG(MSG_GPD_PARENT), GPD_PARENT, GPD_PARENT },
{ MSG_ORIG(MSG_GPD_FILTER), GPD_FILTER, GPD_FILTER },
- { MSG_ORIG(MSG_GPD_PROMOTE), GPD_PROMOTE, GPD_PROMOTE },
{ MSG_ORIG(MSG_GPD_REMOVE), GPD_REMOVE, GPD_REMOVE },
+ { MSG_ORIG(MSG_GPD_MODECHANGE), GPD_MODECHANGE, GPD_MODECHANGE },
{ NULL, 0, 0}
};
diff --git a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg
index 597316816c..d72f5c1878 100644
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg
+++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg
@@ -86,11 +86,11 @@
@ MSG_FLG_OBJINTPO "OBJECT-INTERPOSE"
@ MSG_FLG_SYMINTPO "SYMBOL-INTERPOSE"
@ MSG_FLG_MOVE "MOVE"
-@ MSG_FLG_TMPLIST "TEMPORARY-LIST"
+@ MSG_FLG_RELOCING "RELOCATING"
@ MSG_FLG_REGSYMS "REGISTER-SYMS"
@ MSG_FLG_INITCLCT "INIT-COLLECTED"
-@ MSG_FLG_HANDLE "HANDLE"
-@ MSG_FLG_RELOCING "RELOCATING"
+@ MSG_FLG_PUBHDL "PUBLIC-HANDLE"
+@ MSG_FLG_PRIHDL "PRIVATE-HANDLE"
@ MSG_FL1_COPYTOOK "COPYTOOK"
@ MSG_FL1_CONFSET "CONFSET"
@@ -126,6 +126,8 @@
@ MSG_BFL_REFER "REFERENCED"
@ MSG_BFL_FILTER "FILTER"
+@ MSG_GPH_PUBLIC "PUBLIC-HANDLE"
+@ MSG_GPH_PRIVATE "PRIVATE-HANDLE"
@ MSG_GPH_ZERO "ZERO"
@ MSG_GPH_LDSO "LD.SO.1"
@ MSG_GPH_FIRST "FIRST-ONLY"
@@ -139,7 +141,7 @@
@ MSG_GPD_PARENT "PARENT"
@ MSG_GPD_FILTER "FILTER"
@ MSG_GPD_REMOVE "REMOVAL-CANDIDATE"
-@ MSG_GPD_PROMOTE "RTLD_NOW-PROMOTER"
+@ MSG_GPD_MODECHANGE "MODES-HAVE-CHANGED"
@ MSG_LFL_BASELM "BASELM"
@ MSG_LFL_RTLDLM "RTLDLM"