--- a/usr/src/cmd/sgs/elfdump/Makefile.com Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/elfdump/Makefile.com Tue Apr 18 08:51:16 2006 -0700
@@ -46,7 +46,7 @@
MAPFILE= ../common/mapfile-vers
CPPFLAGS= -I. -I../common -I../../include -I../../include/$(MACH) \
- -I$(SRCBASE)/uts/$(ARCH)/sys \
+ -I$(SRCBASE)/lib/libc/inc -I$(SRCBASE)/uts/$(ARCH)/sys \
$(CPPFLAGS.master)
LLDFLAGS = $(VAR_ELFDUMP_LLDFLAGS)
LLDFLAGS64 = $(VAR_LD_LLDFLAGS64)
--- a/usr/src/cmd/sgs/include/debug.h Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/include/debug.h Tue Apr 18 08:51:16 2006 -0700
@@ -353,6 +353,7 @@
#define Dbg_util_edge_in Dbg64_util_edge_in
#define Dbg_util_edge_out Dbg64_util_edge_out
#define Dbg_util_intoolate Dbg64_util_intoolate
+#define Dbg_util_lcinterface Dbg64_util_lcinterface
#define Dbg_util_nl Dbg64_util_nl
#define Dbg_util_no_init Dbg64_util_no_init
#define Dbg_util_scc_entry Dbg64_util_scc_entry
@@ -361,7 +362,7 @@
#define Dbg_util_wait Dbg64_util_wait
#define Dbg_unused_file Dbg64_unused_file
-#define Dbg_unused_rtldinfo Dbg64_unused_rtldinfo
+#define Dbg_unused_lcinterface Dbg64_unused_lcinterface
#define Dbg_unused_sec Dbg64_unused_sec
#define Dbg_unused_unref Dbg64_unused_unref
@@ -544,6 +545,7 @@
#define Dbg_util_edge_in Dbg32_util_edge_in
#define Dbg_util_edge_out Dbg32_util_edge_out
#define Dbg_util_intoolate Dbg32_util_intoolate
+#define Dbg_util_lcinterface Dbg32_util_lcinterface
#define Dbg_util_nl Dbg32_util_nl
#define Dbg_util_no_init Dbg32_util_no_init
#define Dbg_util_scc_entry Dbg32_util_scc_entry
@@ -552,7 +554,7 @@
#define Dbg_util_wait Dbg32_util_wait
#define Dbg_unused_file Dbg32_unused_file
-#define Dbg_unused_rtldinfo Dbg32_unused_rtldinfo
+#define Dbg_unused_lcinterface Dbg32_unused_lcinterface
#define Dbg_unused_sec Dbg32_unused_sec
#define Dbg_unused_unref Dbg32_unused_unref
@@ -777,6 +779,7 @@
int, int);
extern void Dbg_util_edge_out(Rt_map *, Rt_map *);
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 *);
@@ -785,7 +788,7 @@
extern void Dbg_util_wait(Rt_map *, Rt_map *, int);
extern void Dbg_unused_file(Lm_list *, const char *, int, uint_t);
-extern void Dbg_unused_rtldinfo(Rt_map *);
+extern void Dbg_unused_lcinterface(Rt_map *, Rt_map *, int);
extern void Dbg_unused_sec(Lm_list *, Is_desc *);
extern void Dbg_unused_unref(Rt_map *, const char *);
--- a/usr/src/cmd/sgs/include/rtld.h Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/include/rtld.h Tue Apr 18 08:51:16 2006 -0700
@@ -30,7 +30,7 @@
#pragma ident "%Z%%M% %I% %E% SMI"
/*
- * Global include file for the runtime linker support library.
+ * Global include file for the runtime linker.
*/
#include <time.h>
#include <sgs.h>
@@ -39,6 +39,7 @@
#include <machdep.h>
#include <sys/avl.h>
#include <alist.h>
+#include <libc_int.h>
#ifdef _SYSCALL32
#include <inttypes.h>
@@ -83,14 +84,13 @@
/*
* Private structure for communication between rtld_db and rtld.
*
- * We must bump the version number whenever a update in one of
- * the structures/fields that rtld_db reads is updated. This hopefully
- * permits rtld_db implementations of the future recognize corefiles
- * produced on older system and deal accordingly.
+ * We must bump the version number when ever an update in one of the
+ * structures/fields that rtld_db reads is updated. This hopefully permits
+ * rtld_db implementations of the future to recognize core files produced on
+ * older systems and deal with these core files accordingly.
*
- * As of version 'RTLD_DB_VERSION <= 2' the following fields
- * were valid for core file examination (basically the public
- * Link_map):
+ * As of version 'RTLD_DB_VERSION <= 2' the following fields were valid for core
+ * file examination (basically the public Link_map):
*
* ADDR()
* NAME()
@@ -98,7 +98,7 @@
* NEXT()
* PREV()
*
- * Valid fields for RTLD_DB_VERSION3
+ * Valid fields for RTLD_DB_VERSION3
*
* PATHNAME()
* PADSTART()
@@ -107,18 +107,18 @@
* FLAGS()
* FLAGS1()
*
- * Valid fields for RTLD_DB_VERSION4
+ * Valid fields for RTLD_DB_VERSION4
*
* TLSMODID()
*
- * Valid fields for RTLD_DB_VERSION5
+ * Valid fields for RTLD_DB_VERSION5
*
* Added rtld_flags & FLG_RT_RELOCED to stable flags range
*
*/
#define R_RTLDDB_VERSION1 1 /* base version level - used for core */
/* file examination */
-#define R_RTLDDB_VERSION2 2 /* minor revision - not relavant for */
+#define R_RTLDDB_VERSION2 2 /* minor revision - not relevant for */
/* core files */
#define R_RTLDDB_VERSION3 3
#define R_RTLDDB_VERSION4 4
@@ -141,6 +141,25 @@
} Rtld_db_priv32;
#endif /* _SYSCALL32 */
+/*
+ * External function definitions. ld.so.1 must convey information to libc in
+ * regards to threading. libc also provides routines for atexit() and message
+ * localization. libc provides the necessary interfaces via its RTLDINFO
+ * structure and/or later _ld_libc() calls.
+ *
+ * These external functions are maintained for each link-map list, and used
+ * where appropriate. The functions are associated with the object that
+ * provided them, so that should the object be deleted (say, from an alternative
+ * link-map), the functions can be removed.
+ */
+typedef struct {
+ Rt_map *lc_lmp; /* function provider */
+ union {
+ int (*lc_func)(); /* external function pointer */
+ uintptr_t lc_val; /* external value */
+ char *lc_ptr; /* external character pointer */
+ } lc_un;
+} Lc_desc;
/*
* Link map list definition. Link-maps are used to describe each loaded object.
@@ -248,10 +267,7 @@
/*
* END: Exposed to rtld_db - don't move, don't delete
*/
- int (*lm_peh)(); /* atexit() preexec_exit_handlers */
- Rt_map *lm_peh_lmp; /* and object that contributed them */
- Rt_map *lm_info_lmp; /* the first object with rtld_info */
- Alist *lm_rtldinfo; /* list of RTLDINFO tables */
+ Alist *lm_rti; /* list of RTLDINFO tables */
Audit_list *lm_alp; /* audit list descripter */
avl_tree_t *lm_fpavl; /* avl tree of objects loaded */
Alist *lm_lists; /* active and pending link-map lists */
@@ -260,8 +276,10 @@
uint_t lm_obj; /* total number of objs on link-map */
uint_t lm_init; /* new obj since last init processing */
uint_t lm_lazy; /* obj with pending lazy dependencies */
+ uint_t lm_tls; /* new obj that require TLS */
uint_t lm_lmid; /* unique link-map list identifier, */
char *lm_lmidstr; /* and associated diagnostic string */
+ Lc_desc lm_lcs[CI_MAX]; /* external libc functions */
};
#ifdef _SYSCALL32
@@ -276,10 +294,7 @@
/*
* END: Exposed to rtld_db - don't move, don't delete
*/
- Elf32_Addr lm_peh;
- Elf32_Addr lm_peh_lmp;
- Elf32_Addr lm_info_lmp;
- Elf32_Addr lm_alp;
+ Elf32_Addr lm_rti;
Elf32_Addr lm_fpavl;
Elf32_Addr lm_lists;
Elf32_Addr lm_environ;
@@ -287,8 +302,10 @@
uint_t lm_obj;
uint_t lm_init;
uint_t lm_lazy;
+ uint_t lm_tls;
uint_t lm_lmid;
Elf32_Addr lm_lmidstr;
+ Elf32_Addr lm_lcs[CI_MAX];
};
#endif /* _SYSCALL32 */
@@ -662,6 +679,8 @@
#define FL1_RT_SYMAFLTR 0x00008000 /* or auxiliary filter */
#define MSK_RT_FILTER 0x0000f000 /* mask for all filter possibilites */
+#define FL1_RT_TLSADD 0x00010000 /* objects TLS has been registered */
+
/*
* The following range of bits are reserved to hold LML_TFLG_AUD_ values
* (although the definitions themselves aren't used anywhere).
--- a/usr/src/cmd/sgs/ld/common/lintsup.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/ld/common/lintsup.c Tue Apr 18 08:51:16 2006 -0700
@@ -33,11 +33,11 @@
*/
#include <stdlib.h>
-#include <debug.h>
+#include <stdio.h>
#include "msg.h"
void
exit(int status)
{
- dbg_print(0, _ld_msg((Msg)&__ld_msg[0]), status);
+ (void) printf("%s: %d\n", _ld_msg((Msg)&__ld_msg[0]), status);
}
--- a/usr/src/cmd/sgs/libconv/Makefile.com Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/libconv/Makefile.com Tue Apr 18 08:51:16 2006 -0700
@@ -82,7 +82,7 @@
PICS= $(OBJECTS:%=pics/%)
-CPPFLAGS += -I$(ELFCAP) $(VAR_LIBCONV_CPPFLAGS)
+CPPFLAGS += -I$(SRCBASE)/lib/libc/inc -I$(ELFCAP) $(VAR_LIBCONV_CPPFLAGS)
ARFLAGS= cr
AS_CPPFLAGS= -P -D_ASM $(CPPFLAGS)
--- a/usr/src/cmd/sgs/libconv/common/dynamic.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/libconv/common/dynamic.c Tue Apr 18 08:51:16 2006 -0700
@@ -327,6 +327,12 @@
return ((const char *)string);
}
+/*
+ * Note, conv_bnd_obj() is called with either:
+ * LML_FLG_OBJADDED (possibly with LML_FLG_OBJREEVAL added), or
+ * LML_FLG_OBJDELETED, or
+ * LML_FLG_ATEXIT.
+ */
#define BINDOSZ MSG_GBL_OSQBRKT_SIZE + \
MSG_BND_ADDED_SIZE + \
MSG_BND_REEVAL_SIZE + \
@@ -344,8 +350,9 @@
{ 0, 0 }
};
- if (flags == 0)
- return (MSG_ORIG(MSG_STR_EMPTY));
+ if ((flags & (LML_FLG_OBJADDED | LML_FLG_OBJREEVAL |
+ LML_FLG_OBJDELETED | LML_FLG_ATEXIT)) == 0)
+ return (MSG_ORIG(MSG_BND_REVISIT));
/*
* Note, we're not worried about unknown flags for this family, only
--- a/usr/src/cmd/sgs/libconv/common/dynamic.msg Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/libconv/common/dynamic.msg Tue Apr 18 08:51:16 2006 -0700
@@ -135,6 +135,8 @@
@ MSG_BND_REEVAL " OBJECTS-REEVALUATED "
@ MSG_BND_DELETED " OBJECTS-DELETED "
@ MSG_BND_ATEXIT " ATEXIT-PROCESSING "
+@ MSG_BND_REVISIT "(revisiting)"
+
@ MSG_STR_EMPTY ""
@ MSG_GBL_ZERO "0"
--- a/usr/src/cmd/sgs/libcrle/Makefile.com Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/libcrle/Makefile.com Tue Apr 18 08:51:16 2006 -0700
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -21,7 +20,7 @@
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -55,6 +54,7 @@
LINTFLAGS += -u
LINTFLAGS64 += -u
+CPPFLAGS += -I$(SRCBASE)/lib/libc/inc
DYNFLAGS += $(VERSREF) $(CONVLIBDIR) -lconv \
$(MAPOPTS) $(USE_PROTO)
--- a/usr/src/cmd/sgs/libdl/common/llib-ldl Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/libdl/common/llib-ldl Tue Apr 18 08:51:16 2006 -0700
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -23,7 +22,7 @@
/* PROTOLIB1 */
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -41,5 +40,4 @@
int dladdr1(void *, Dl_info *, void **, int);
int dldump(const char *, const char *, int);
int dlinfo(void *, int, void *);
-void _ld_concurrency(void *);
void _ld_libc(void *);
--- a/usr/src/cmd/sgs/libdl/common/mapfile-vers Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/libdl/common/mapfile-vers Tue Apr 18 08:51:16 2006 -0700
@@ -1,13 +1,9 @@
-#
-# Copyright 2005 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, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -22,6 +18,11 @@
#
# CDDL HEADER END
#
+
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
# ident "%Z%%M% %I% %E% SMI"
SUNW_1.4 {
@@ -50,7 +51,6 @@
SUNWprivate_1.1 {
global:
- _ld_concurrency = FUNCTION;
_ld_libc = FUNCTION;
_dlinfo = FUNCTION;
_dldump = FUNCTION;
--- a/usr/src/cmd/sgs/libelf/common/lintsup.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/libelf/common/lintsup.c Tue Apr 18 08:51:16 2006 -0700
@@ -32,3 +32,4 @@
#include <malloc.h>
#include <link.h>
#include <sgs.h>
+#include <_libelf.h>
--- a/usr/src/cmd/sgs/libelf/common/llib-lelf Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/libelf/common/llib-lelf Tue Apr 18 08:51:16 2006 -0700
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -23,7 +22,7 @@
/* PROTOLIB1 */
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -106,6 +105,7 @@
GElf_Cap * gelf_getcap(Elf_Data *, int, GElf_Cap *);
int gelf_update_cap(Elf_Data *, int, GElf_Cap *);
+GElf_Xword _gelf_getdyndtflags_1(Elf *);
/*
* Class-Independent Elf Symbols
--- a/usr/src/cmd/sgs/libld/Makefile.com Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/libld/Makefile.com Tue Apr 18 08:51:16 2006 -0700
@@ -75,8 +75,9 @@
DLLIB = $(VAR_DL_LIB)
package := DLLIB = $(VAR_PKG_DL_LIB)
-CPPFLAGS += -DUSE_LIBLD_MALLOC -I$(SRCBASE)/uts/common/krtld \
- -I$(ELFCAP) $(VAR_LIBLD_CPPFLAGS)
+CPPFLAGS += -DUSE_LIBLD_MALLOC -I$(SRCBASE)/lib/libc/inc \
+ -I$(SRCBASE)/uts/common/krtld -I$(ELFCAP) \
+ $(VAR_LIBLD_CPPFLAGS)
LDLIBS += $(CONVLIBDIR) $(CONV_LIB) $(LDDBGLIBDIR) $(LDDBG_LIB) \
$(ELFLIBDIR) -lelf $(DLLIB) -lc
--- a/usr/src/cmd/sgs/libld/common/files.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/libld/common/files.c Tue Apr 18 08:51:16 2006 -0700
@@ -353,7 +353,7 @@
{
Cap *cdata;
- Dbg_cap_sec_title(ofl);
+ DBG_CALL(Dbg_cap_sec_title(ofl));
for (cdata = (Cap *)cisp->is_indata->d_buf;
cdata->c_tag != CA_SUNW_NULL; cdata++) {
--- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg Tue Apr 18 08:51:16 2006 -0700
@@ -545,7 +545,7 @@
@ MSG_USD_UNREF "file=%s unreferenced: unused dependency of %s"
@ MSG_USD_FILECYCLIC "file=%s unused: cyclic group [%d] member: \
unreferenced outside of group"
-@ MSG_USD_RTLDINFO "file=%s unused RTLDINFO: using RTLDINFO \
+@ MSG_USD_LCINTERFACE "file=%s unused interface [%s]: using interface \
from previously loaded object: file=%s"
# Segment messages
@@ -688,6 +688,8 @@
@ MSG_UTL_SCC_SUBI "reverse load-order"
@ MSG_UTL_SCC_SUBF "load-order"
+@ MSG_UTL_LCINTERFACE "file=%s; provides interface [%s]: 0x%llx"
+
# Generic strings
@ MSG_STR_IGNORE "ignored"
@@ -1204,3 +1206,17 @@
# Syminfo formats
@ MSG_SYMINFO_UNKFLAG " 0x%x"
+
+# Lc_interface interface tags.
+
+@ MSG_CI_NULL "NULL"
+@ MSG_CI_VERSION "VERSION"
+@ MSG_CI_ATEXIT "ATEXIT"
+@ MSG_CI_LCMESSAGES "LCMESSAGES"
+@ MSG_CI_BIND_GUARD "BIND_GUARD"
+@ MSG_CI_BIND_CLEAR "BIND_CLEAR"
+@ MSG_CI_THR_SELF "THR_SELF"
+@ MSG_CI_TLS_MODADD "TLS_MODADD"
+@ MSG_CI_TLS_MODREM "TLS_MODREM"
+@ MSG_CI_TLS_STATMOD "TLS_STATMOD"
+@ MSG_CI_THRINIT "THRINIT"
--- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg Tue Apr 18 08:51:16 2006 -0700
@@ -388,6 +388,8 @@
void Dbg64_util_edge_out(Rt_map *, Rt_map *);
void Dbg32_util_intoolate(Rt_map *);
void Dbg64_util_intoolate(Rt_map *);
+void Dbg32_util_lcinterface(Rt_map *, int, char *);
+void Dbg64_util_lcinterface(Rt_map *, int, char *);
void Dbg32_util_nl(Lm_list *, int);
void Dbg64_util_nl(Lm_list *, int);
void Dbg32_util_no_init(Rt_map *);
@@ -403,8 +405,8 @@
void Dbg32_unused_file(Lm_list *, const char *, int, uint_t);
void Dbg64_unused_file(Lm_list *, const char *, int, uint_t);
-void Dbg32_unused_rtldinfo(Rt_map *);
-void Dbg64_unused_rtldinfo(Rt_map *);
+void Dbg32_unused_lcinterface(Rt_map *, Rt_map *, int);
+void Dbg64_unused_lcinterface(Rt_map *, Rt_map *, int);
void Dbg32_unused_sec(Lm_list *, Is_desc *);
void Dbg64_unused_sec(Lm_list *, Is_desc *);
void Dbg32_unused_unref(Rt_map *, const char *);
--- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers Tue Apr 18 08:51:16 2006 -0700
@@ -38,7 +38,7 @@
# Policy for Shared Library Version Names and Interface Definitions
-SUNWprivate_4.50 {
+SUNWprivate_4.51 {
global:
dbg_desc = NODIRECT; # interposed - ld.so.1(1)
dbg_print = NODIRECT; # interposed - ld(1) and ld.so.1(1)
@@ -371,6 +371,8 @@
Dbg64_util_edge_in;
Dbg32_util_edge_out;
Dbg64_util_edge_out;
+ Dbg32_util_lcinterface;
+ Dbg64_util_lcinterface;
Dbg32_util_intoolate;
Dbg64_util_intoolate;
Dbg32_util_nl;
@@ -388,8 +390,8 @@
Dbg32_unused_file;
Dbg64_unused_file;
- Dbg32_unused_rtldinfo;
- Dbg64_unused_rtldinfo;
+ Dbg32_unused_lcinterface;
+ Dbg64_unused_lcinterface;
Dbg32_unused_sec;
Dbg64_unused_sec;
Dbg32_unused_unref;
--- a/usr/src/cmd/sgs/liblddbg/common/unused.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/unused.c Tue Apr 18 08:51:16 2006 -0700
@@ -30,18 +30,6 @@
#include "libld.h"
void
-Dbg_unused_rtldinfo(Rt_map *lmp)
-{
- Lm_list *lml = LIST(lmp);
-
- if (DBG_NOTCLASS(DBG_C_UNUSED))
- return;
-
- dbg_print(lml, MSG_INTL(MSG_USD_RTLDINFO), NAME(lmp),
- NAME(lml->lm_info_lmp));
-}
-
-void
Dbg_unused_unref(Rt_map *lmp, const char *depend)
{
if (DBG_NOTCLASS(DBG_C_UNUSED))
--- a/usr/src/cmd/sgs/liblddbg/common/util.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/util.c Tue Apr 18 08:51:16 2006 -0700
@@ -313,6 +313,56 @@
dbg_print(lml, MSG_INTL(MSG_UTL_COLLECT), ndx, NAME(lmp), str);
}
+static const Msg tags[] = {
+ MSG_CI_NULL, /* MSG_ORIG(MSG_CI_NULL) */
+ MSG_CI_VERSION, /* MSG_ORIG(MSG_CI_VERSION) */
+ MSG_CI_ATEXIT, /* MSG_ORIG(MSG_CI_ATEXIT) */
+ MSG_CI_LCMESSAGES, /* MSG_ORIG(MSG_CI_LCMESSAGES) */
+ MSG_CI_BIND_GUARD, /* MSG_ORIG(MSG_CI_BIND_GUARD) */
+ MSG_CI_BIND_CLEAR, /* MSG_ORIG(MSG_CI_BIND_CLEAR) */
+ MSG_CI_THR_SELF, /* MSG_ORIG(MSG_CI_THR_SELF) */
+ MSG_CI_TLS_MODADD, /* MSG_ORIG(MSG_CI_TLS_MODADD) */
+ MSG_CI_TLS_MODREM, /* MSG_ORIG(MSG_CI_TLS_MODREM) */
+ MSG_CI_TLS_STATMOD, /* MSG_ORIG(MSG_CI_TLS_STATMOD) */
+ MSG_CI_THRINIT /* MSG_ORIG(MSG_CI_THRINIT) */
+};
+
+void
+Dbg_util_lcinterface(Rt_map *lmp, int tag, char *val)
+{
+ const char *str;
+ static char string[CONV_INV_STRSIZE];
+
+ if (DBG_NOTDETAIL())
+ return;
+
+ if (tag < CI_MAX)
+ str = MSG_ORIG(tags[tag]);
+ else
+ str = conv_invalid_val(string, CONV_INV_STRSIZE, tag, 0);
+
+ dbg_print(LIST(lmp), MSG_INTL(MSG_UTL_LCINTERFACE), NAME(lmp), str,
+ EC_NATPTR(val));
+}
+
+void
+Dbg_unused_lcinterface(Rt_map *nlmp, Rt_map *olmp, int tag)
+{
+ const char *str;
+ static char string[CONV_INV_STRSIZE];
+
+ if (DBG_NOTCLASS(DBG_C_UNUSED))
+ return;
+
+ if (tag < CI_MAX)
+ str = MSG_ORIG(tags[tag]);
+ else
+ str = conv_invalid_val(string, CONV_INV_STRSIZE, tag, 0);
+
+ dbg_print(LIST(nlmp), MSG_INTL(MSG_USD_LCINTERFACE), NAME(nlmp), str,
+ NAME(olmp));
+}
+
/*
* Generic new line generator. To prevent multiple newlines from being
* generated, a flag is maintained in the global debug descriptor. This flag
--- a/usr/src/cmd/sgs/librtld_db/Makefile.com Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/librtld_db/Makefile.com Tue Apr 18 08:51:16 2006 -0700
@@ -39,6 +39,7 @@
MAPFILE= ../common/mapfile-vers
+CPPFLAGS += -I$(SRCBASE)/lib/libc/inc
DYNFLAGS += -M$(MAPFILE) $(VERSREF)
LDLIBS += $(CONVLIBDIR) $(CONV_LIB) -lc
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README Tue Apr 18 08:51:16 2006 -0700
@@ -1098,3 +1098,4 @@
6327926 ld does not set etext symbol correctly for AMD64 medium model (D)
6390410 64-bit LD_PROFILE can fail: relocation error when binding profile plt
6382945 AMD64-GCC: dbx: internal error: dwarf reference attribute out of bounds
+6262333 init section of .so dlopened from audit interface not being called
--- a/usr/src/cmd/sgs/pvs/Makefile.com Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/pvs/Makefile.com Tue Apr 18 08:51:16 2006 -0700
@@ -38,6 +38,7 @@
MAPFILE= ../common/mapfile-vers
+CPPFLAGS += -I$(SRCBASE)/lib/libc/inc
LLDFLAGS = '-R$$ORIGIN/../lib'
LLDFLAGS64 = '-R$$ORIGIN/../../lib/$(MACH64)'
LDFLAGS += $(VERSREF) $(USE_PROTO) -M$(MAPFILE) $(LLDFLAGS)
--- a/usr/src/cmd/sgs/rtld/amd64/Makefile Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/amd64/Makefile Tue Apr 18 08:51:16 2006 -0700
@@ -32,8 +32,8 @@
# secondary lists (less frequently used code, ie. a.out support).
P_COMOBJS= debugdata.o \
- analyze.o elf.o globals.o malloc.o \
- mutex.o paths.o setup.o util.o \
+ analyze.o elf.o external.o globals.o \
+ malloc.o paths.o setup.o util.o \
dlfcns.o config_elf.o locale.o tsort.o \
getcwd.o remove.o move.o tls.o \
cap.o
--- a/usr/src/cmd/sgs/rtld/common/_rtld.h Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/common/_rtld.h Tue Apr 18 08:51:16 2006 -0700
@@ -309,6 +309,7 @@
#define RT_FL2_FTL2WARN 0x00000080 /* convert fatal to warning messages */
#define RT_FL2_BINDNOW 0x00000100 /* LD_BIND_NOW in effect */
#define RT_FL2_BINDLAZY 0x00000200 /* disable RTLD_NOW (and LD_BIND_NOW) */
+#define RT_FL2_PLMSETUP 0x00000400 /* primary link-map set up complete */
/*
* Information flags for env_info.
@@ -320,7 +321,15 @@
/* from configuration file */
/*
- * Binding flags for the bindguard routines
+ * RTLDINFO descriptor.
+ */
+typedef struct {
+ Rt_map *rti_lmp; /* RTLDINFO provider */
+ Lc_interface *rti_info; /* RTLDINFO data */
+} Rti_desc;
+
+/*
+ * Binding flags for the bindguard routines.
*/
#define THR_FLG_RTLD 0x00000001 /* rtldlock bind_guard() flag */
#define THR_FLG_MASK THR_FLG_RTLD /* mask for all THR_FLG flags */
@@ -398,6 +407,8 @@
/*
* Data declarations.
*/
+extern Lc_desc glcs[]; /* global external interfaces */
+
extern Rt_lock rtldlock; /* rtld lock */
extern List dynlm_list; /* dynamic list of link-maps */
@@ -479,8 +490,6 @@
extern const char *err_strs[]; /* diagnostic error string headers */
extern const char *nosym_str; /* MSG_GEN_NOSYM message cache */
-extern void (*thrinit)(); /* thread initialization */
-
extern ulong_t hwcap; /* hardware capabilities */
extern ulong_t sfcap; /* software capabilities */
@@ -601,8 +610,10 @@
extern int rt_cond_wait(Rt_cond *, Rt_lock *);
extern int rt_bind_guard(int);
extern int rt_bind_clear(int);
+extern int rt_get_extern(Lm_list *, Rt_map *);
extern int rt_mutex_lock(Rt_lock *);
extern int rt_mutex_unlock(Rt_lock *);
+extern void rt_thr_init(Lm_list *);
extern thread_t rt_thr_self(void);
extern void rtld_db_dlactivity(Lm_list *);
extern void rtld_db_preinit(Lm_list *);
@@ -617,9 +628,8 @@
char **, int, uid_t, uid_t, gid_t, gid_t, void *,
int, uint_t);
extern void tls_assign_soffset(Rt_map *);
-extern void tls_setroutines(Lm_list *, void *, void *, void *);
-extern void tls_modactivity(Rt_map *, uint_t);
-extern int tls_report_modules();
+extern void tls_modaddrem(Rt_map *, uint_t);
+extern int tls_statmod(Lm_list *, Rt_map *);
extern Rt_map **tsort(Rt_map *, int, int);
extern void unused(Lm_list *);
extern int update_mode(Rt_map *, int, int);
--- a/usr/src/cmd/sgs/rtld/common/analyze.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/common/analyze.c Tue Apr 18 08:51:16 2006 -0700
@@ -290,36 +290,11 @@
lml->lm_flags |= LML_FLG_OBJADDED;
/*
- * None of the following processing is necessary under ldd().
+ * Process any move data (not necessary under ldd()).
*/
- if ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0) {
- /*
- * Process any move data.
- */
- if (FLAGS(lmp) & FLG_RT_MOVE)
- move_data(lmp);
-
- /*
- * Process any DT_SUNW_RTLDINFO information now the
- * object is relocated, and remove the RTLDINFO
- * infrastructure as it won't be needed anymore.
- *
- * We wait until lmp == lm_info_lmp, as it's at this
- * stage we know the object contributing RTLDINFO has
- * been properly relocated.
- */
- if ((FCT(lmp) == &elf_fct) && (lml->lm_rtldinfo) &&
- (lmp == lml->lm_info_lmp)) {
- Aliste off;
- Lc_interface ** funcs;
-
- for (ALIST_TRAVERSE(lml->lm_rtldinfo,
- off, funcs))
- get_lcinterface(lmp, *funcs);
- free(lml->lm_rtldinfo);
- lml->lm_rtldinfo = 0;
- }
- }
+ if ((FLAGS(lmp) & FLG_RT_MOVE) &&
+ ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0))
+ move_data(lmp);
/*
* Determine if this object is a filter, and if a load filter
@@ -1196,7 +1171,7 @@
&added) == 0)
return (0);
if (added)
- DBG_CALL(Dbg_file_skip(LIST(nlmp),
+ DBG_CALL(Dbg_file_skip(LIST(clmp),
NAME(nlmp), nname));
fdesc->fd_nname = nname;
fdesc->fd_lmp = nlmp;
@@ -1231,7 +1206,7 @@
if ((nname[0] == '/') && (fpavl_insert(lml,
nlmp, nname, 0) == 0))
return (0);
- DBG_CALL(Dbg_file_skip(LIST(nlmp), NAME(nlmp),
+ DBG_CALL(Dbg_file_skip(LIST(clmp), NAME(nlmp),
nname));
}
fdesc->fd_nname = nname;
@@ -1599,12 +1574,6 @@
*/
FLAGS(nlmp) |= FLG_RT_NEWLOAD;
- /*
- * Report module loads to TLS module activity.
- */
- if (nlmp)
- tls_modactivity(nlmp, TM_FLG_MODADD);
-
return (nlmp);
}
--- a/usr/src/cmd/sgs/rtld/common/dlfcns.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/common/dlfcns.c Tue Apr 18 08:51:16 2006 -0700
@@ -605,45 +605,6 @@
(path ? path : MSG_ORIG(MSG_STR_ZERO)), mode));
/*
- * Check for magic link-map list values:
- *
- * LM_ID_BASE: Operate on the PRIMARY (executables) link map
- * LM_ID_LDSO: Operation on ld.so.1's link map
- * LM_ID_NEWLM: Create a new link-map.
- */
- if (lml == (Lm_list *)LM_ID_NEWLM) {
- if ((lml = calloc(sizeof (Lm_list), 1)) == 0)
- return (0);
-
- /*
- * Establish the new link-map flags from the callers and those
- * explicitly provided.
- */
- lml->lm_tflags = LIST(clmp)->lm_tflags;
- if (flags & FLG_RT_AUDIT) {
- /*
- * Unset any auditing flags - an auditor shouldn't be
- * audited. Insure all audit dependencies are loaded.
- */
- lml->lm_tflags &= ~LML_TFLG_AUD_MASK;
- lml->lm_tflags |=
- (LML_TFLG_NOLAZYLD | LML_TFLG_LOADFLTR);
- lml->lm_flags |= LML_FLG_NOAUDIT;
- }
-
- if ((list_append(&dynlm_list, lml) == 0) ||
- (newlmid(lml) == 0)) {
- free(lml);
- return (0);
- }
- } else if ((uintptr_t)lml < LM_ID_NUM) {
- if ((uintptr_t)lml == LM_ID_BASE)
- lml = &lml_main;
- else if ((uintptr_t)lml == LM_ID_LDSO)
- lml = &lml_rtld;
- }
-
- /*
* If the path specified is null then we're operating on global
* objects. Associate a dummy handle with the link-map list.
*/
@@ -782,9 +743,51 @@
{
Rt_map *dlmp = 0;
Grp_hdl *ghp;
+ int objcnt;
/*
- * Determine the link-map that has just been loaded.
+ * Check for magic link-map list values:
+ *
+ * LM_ID_BASE: Operate on the PRIMARY (executables) link map
+ * LM_ID_LDSO: Operation on ld.so.1's link map
+ * LM_ID_NEWLM: Create a new link-map.
+ */
+ if (lml == (Lm_list *)LM_ID_NEWLM) {
+ if ((lml = calloc(sizeof (Lm_list), 1)) == 0)
+ return (0);
+
+ /*
+ * Establish the new link-map flags from the callers and those
+ * explicitly provided.
+ */
+ lml->lm_tflags = LIST(clmp)->lm_tflags;
+ if (flags & FLG_RT_AUDIT) {
+ /*
+ * Unset any auditing flags - an auditor shouldn't be
+ * audited. Insure all audit dependencies are loaded.
+ */
+ lml->lm_tflags &= ~LML_TFLG_AUD_MASK;
+ lml->lm_tflags |=
+ (LML_TFLG_NOLAZYLD | LML_TFLG_LOADFLTR);
+ lml->lm_flags |= LML_FLG_NOAUDIT;
+ }
+
+ if ((list_append(&dynlm_list, lml) == 0) ||
+ (newlmid(lml) == 0)) {
+ free(lml);
+ return (0);
+ }
+ } else if ((uintptr_t)lml < LM_ID_NUM) {
+ if ((uintptr_t)lml == LM_ID_BASE)
+ lml = &lml_main;
+ else if ((uintptr_t)lml == LM_ID_LDSO)
+ lml = &lml_rtld;
+ }
+
+ objcnt = lml->lm_obj;
+
+ /*
+ * Open the required object on the associated link-map list.
*/
if ((ghp = dlmopen_core(lml, path, mode, clmp, flags,
(orig | PN_SER_DLOPEN))) != 0) {
@@ -802,7 +805,7 @@
* trigger used() processing on return from a dlopen().
*/
if (loaded && dlmp)
- *loaded = LIST(dlmp)->lm_init;
+ *loaded = lml->lm_obj - objcnt;
load_completion(dlmp, clmp);
return (ghp);
@@ -1236,7 +1239,6 @@
}
load_completion(llmp, clmp);
-
return (error);
}
--- a/usr/src/cmd/sgs/rtld/common/elf.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/common/elf.c Tue Apr 18 08:51:16 2006 -0700
@@ -2075,9 +2075,9 @@
* dynamic structure.
*/
if (ld) {
- uint_t dyncnt = 0;
- Xword pltpadsz = 0;
- void *rtldinfo;
+ uint_t dyncnt = 0;
+ Xword pltpadsz = 0;
+ Rti_desc *rti;
/* CSTYLED */
for ( ; ld->d_tag != DT_NULL; ++ld, dyncnt++) {
@@ -2322,29 +2322,22 @@
pltpadsz = ld->d_un.d_val;
break;
case DT_SUNW_RTLDINF:
- if ((lml->lm_info_lmp != 0) &&
- (lml->lm_info_lmp != lmp)) {
- DBG_CALL(Dbg_unused_rtldinfo(lmp));
- break;
- }
- lml->lm_info_lmp = lmp;
- rtldinfo = (void *)(ld->d_un.d_ptr + base);
-
/*
- * We maintain a list of DT_SUNW_RTLDINFO
- * structures for a given object. This permits
- * the RTLDINFO structures to be grouped
- * functionly inside of a shared object.
- *
- * For example, we could have one for
- * thread_init, and another for atexit
- * reservations.
+ * Maintain a list of RTLDINFO structures.
+ * Typically, libc is the only supplier, and
+ * only one structure is provided. However,
+ * multiple suppliers and multiple structures
+ * are supported. For example, one structure
+ * may provide thread_init, and another
+ * structure may provide atexit reservations.
*/
- if (alist_append(&lml->lm_rtldinfo, &rtldinfo,
- sizeof (void *), AL_CNT_RTLDINFO) == 0) {
+ if ((rti = alist_append(&lml->lm_rti, 0,
+ sizeof (Rti_desc), AL_CNT_RTLDINFO)) == 0) {
remove_so(0, lmp);
return (0);
}
+ rti->rti_lmp = lmp;
+ rti->rti_info = (void *)(ld->d_un.d_ptr + base);
break;
case DT_DEPRECATED_SPARC_REGISTER:
case M_DT_REGISTER:
@@ -2604,14 +2597,15 @@
if (pptr->p_align > align)
align = pptr->p_align;
- } else if (pptr->p_type == PT_DYNAMIC)
+ } else if (pptr->p_type == PT_DYNAMIC) {
mld = (Dyn *)(pptr->p_vaddr);
- else if (pptr->p_type == PT_TLS)
+ } else if ((pptr->p_type == PT_TLS) && pptr->p_memsz) {
tlph = pptr;
- else if (pptr->p_type == PT_SUNWCAP)
+ } else if (pptr->p_type == PT_SUNWCAP) {
cap = (Cap *)(pptr->p_vaddr);
- else if (pptr->p_type == PT_SUNW_UNWIND)
+ } else if (pptr->p_type == PT_SUNW_UNWIND) {
unwindph = pptr;
+ }
}
#if defined(MAP_ALIGN)
@@ -2770,6 +2764,7 @@
if (tlph) {
PTTLS(lmp) = phdr + (tlph - phdr0);
tls_assign_soffset(lmp);
+ lml->lm_tls++;
}
if (unwindph)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/rtld/common/external.c Tue Apr 18 08:51:16 2006 -0700
@@ -0,0 +1,527 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Implementation of all external interfaces between ld.so.1 and libc.
+ *
+ * This file started as a set of routines that provided synchronization and
+ * locking operations using calls to libthread. libthread has merged with libc,
+ * and things have gotten a little simpler. This file continues to establish
+ * and redirect various events within ld.so.1 to interfaces within libc.
+ *
+ * Until libc is loaded and relocated, any external interfaces are captured
+ * locally. Each link-map list maintains its own set of external vectors, as
+ * each link-map list typically provides its own libc. Although this per-link-
+ * map list vectoring provides a degree of flexibility, there is a protocol
+ * expected when calling various libc interfaces.
+ *
+ * i. Any new alternative link-map list should call CI_THRINIT, and then call
+ * CI_TLS_MODADD to register any TLS for each object of that link-map list
+ * (this item is labeled i. as auditors can be the first objects loaded,
+ * and they exist on their own lik-map list).
+ *
+ * ii. For the primary link-map list, CI_TLS_STATMOD must be called first to
+ * register any static TLS. This routine is called regardless of there
+ * being any TLS, as this routine also establishes the link-map list as the
+ * primary list and fixes the association of uberdata). CI_THRINIT should
+ * then be called.
+ *
+ * iii. Any objects added to an existing link-map list (primary or alternative)
+ * should call CI_TLS_MODADD to register any additional TLS.
+ *
+ * These events are established by:
+ *
+ * i. Typically, libc is loaded as part of the primary dependencies of any
+ * link-map list (since the Unified Process Model (UPM), libc can't be
+ * lazily loaded). To minimize the possibility of loading and registering
+ * objects, and then tearing them down (because of a relocation error),
+ * external vectors are established as part of load_completion(). This
+ * routine is called on completion of any operation that can cause objects
+ * to be loaded. This point of control insures the objects have been fully
+ * analyzed and relocated, and moved to their controlling link-map list.
+ * The external vectors are established prior to any .inits being fired.
+ *
+ * ii. Calls to CI_THRINIT, and CI_TLS_MODADD also occur as part of
+ * load_completion(). CI_THRINIT is only called once for each link-map
+ * control list.
+ *
+ * iii. Calls to CI_TLS_STATMOD, and CI_THRINIT occur for the primary link-map
+ * list in the final stages of setup().
+ *
+ * The interfaces provide by libc can be divided into two families. The first
+ * family consists of those interfaces that should be called from the link-map
+ * list. It's possible that these interfaces convey state concerning the
+ * link-map list they are part of:
+ *
+ * CI_ATEXIT
+ * CI TLS_MODADD
+ * CI_TLS_MODREM
+ * CI_TLS_STATMOD
+ * CI_THRINIT
+ *
+ * The second family are global in nature, that is, the link-map list from
+ * which they are called provides no state information. In fact, for
+ * CI_BIND_GUARD, the calling link-map isn't even known. The link-map can only
+ * be deduced after ld.so.1's global lock has been obtained. Therefore, the
+ * following interfaces are also maintained as global:
+ *
+ * CI_LCMESSAGES
+ * CI_BIND_GUARD
+ * CI_BIND_CLEAR
+ * CI_THR_SELF
+ *
+ * Note, it is possible that these global interfaces are obtained from an
+ * alternative link-map list that gets torn down because of a processing
+ * failure (unlikely, because the link-map list components must be analyzed
+ * and relocated prior to load_completion(), but perhaps the tear down is still
+ * a possibility). Thus the global interfaces may have to be replaced. Once
+ * the interfaces have been obtained from the primary link-map, they can
+ * remain fixed, as the primary link-map isn't going to go anywhere.
+ *
+ * The last wrinkle in the puzzle is what happens if an alternative link-map
+ * is loaded with no libc dependency? In this case, the alternative objects
+ * can not call CI_THRINIT, can not be allowed to use TLS, and will not receive
+ * any atexit processing.
+ *
+ * The history of these external interfaces is defined by their version:
+ *
+ * TI_VERSION == 1
+ * Under this model libthread provided rw_rwlock/rw_unlock, through which
+ * all rt_mutex_lock/rt_mutex_unlock calls were vectored.
+ * Under libc/libthread these interfaces provided _sigon/_sigoff (unlike
+ * lwp/libthread that provided signal blocking via bind_guard/bind_clear).
+ *
+ * TI_VERSION == 2
+ * Under this model only libthreads bind_guard/bind_clear and thr_self
+ * interfaces were used. Both libthreads blocked signals under the
+ * bind_guard/bind_clear interfaces. Lower level locking is derived
+ * from internally bound _lwp_ interfaces. This removes recursive
+ * problems encountered when obtaining locking interfaces from libthread.
+ * The use of mutexes over reader/writer locks also enables the use of
+ * condition variables for controlling thread concurrency (allows access
+ * to objects only after their .init has completed).
+ *
+ * NOTE, the TI_VERSION indicated the ti_interface version number, where the
+ * ti_interface was a large vector of functions passed to both libc (to override
+ * the thread stub interfaces) and ld.so.1. ld.so.1 used only a small subset of
+ * these interfaces.
+ *
+ * CI_VERSION == 1
+ * Introduced with CI_VERSION & CI_ATEXIT
+ *
+ * CI_VERSION == 2 (Solaris 8 update 2).
+ * Added support for CI_LCMESSAGES
+ *
+ * CI_VERSION == 3 (Solaris 9).
+ * Added the following versions to the CI table:
+ *
+ * CI_BIND_GUARD, CI_BIND_CLEAR, CI_THR_SELF
+ * CI_TLS_MODADD, CI_TLS_MOD_REMOVE, CI_TLS_STATMOD
+ *
+ * This version introduced the DT_SUNW_RTLDINFO structure as a mechanism
+ * to handshake with ld.so.1.
+ *
+ * CI_VERSION == 4 (Solaris 10).
+ * Added the CI_THRINIT handshake as part of the libc/libthread unified
+ * process model. libc now initializes the current thread pointer from
+ * this interface (and no longer relies on the INITFIRST flag - which
+ * others have started to camp out on).
+ *
+ * Release summary:
+ *
+ * Solaris 8 CI_ATEXIT via _ld_libc()
+ * TI_* via _ld_concurrency()
+ *
+ * Solaris 9 CI_ATEXIT and CI_LCMESSAGES via _ld_libc()
+ * CI_* via RTLDINFO and _ld_libc() - new libthread
+ * TI_* via _ld_concurrency() - old libthread
+ *
+ * Solaris 10 CI_ATEXIT and CI_LCMESSAGES via _ld_libc()
+ * CI_* via RTLDINFO and _ld_libc() - new libthread
+ */
+#include "_synonyms.h"
+
+#include <sys/debug.h>
+#include <synch.h>
+#include <signal.h>
+#include <thread.h>
+#include <synch.h>
+#include <strings.h>
+#include <stdio.h>
+#include <debug.h>
+#include <libc_int.h>
+#include "_elf.h"
+#include "_rtld.h"
+
+/*
+ * This interface provides the unified process model communication between
+ * ld.so.1 and libc. This interface is supplied through RTLDINFO.
+ */
+void
+get_lcinterface(Rt_map *lmp, Lc_interface *funcs)
+{
+ int tag, threaded = 0;
+ Lm_list *lml;
+ Lc_desc *lcp;
+
+ if ((lmp == 0) || (funcs == 0))
+ return;
+
+ lml = LIST(lmp);
+ lcp = &lml->lm_lcs[0];
+
+ DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
+
+ for (tag = funcs->ci_tag; tag; tag = (++funcs)->ci_tag) {
+ char *gptr;
+ char *lptr = funcs->ci_un.ci_ptr;
+
+ DBG_CALL(Dbg_util_lcinterface(lmp, tag, lptr));
+
+ if (tag >= CI_MAX)
+ continue;
+
+ /*
+ * Maintain all interfaces on a per-link-map basis. Note, for
+ * most interfaces, only the first interface is used for any
+ * link-map list. This prevents accidents with developers who
+ * manage to load two different versions of libc.
+ */
+ if ((lcp[tag].lc_lmp) &&
+ (tag != CI_LCMESSAGES) && (tag != CI_VERSION)) {
+ DBG_CALL(Dbg_unused_lcinterface(lmp,
+ lcp[tag].lc_lmp, tag));
+ continue;
+ }
+
+ lcp[tag].lc_un.lc_ptr = lptr;
+ lcp[tag].lc_lmp = lmp;
+
+ gptr = glcs[tag].lc_un.lc_ptr;
+
+ /*
+ * Process any interfaces that must be maintained on a global
+ * basis.
+ */
+ switch (tag) {
+ case CI_ATEXIT:
+ break;
+
+ case CI_LCMESSAGES:
+ /*
+ * At startup, ld.so.1 can establish a locale from one
+ * of the locale family of environment variables (see
+ * ld_str_env() and readenv_user()). During process
+ * execution the locale can also be changed by the user.
+ * This interface is called from libc should the locale
+ * be modified. Presently, only one global locale is
+ * maintained for all link-map lists, and only objects
+ * on the primrary link-map may change this locale.
+ */
+ if ((lml->lm_flags & LML_FLG_BASELM) &&
+ ((gptr == 0) || (strcmp(gptr, lptr) != 0))) {
+ /*
+ * If we've obtained a message locale (typically
+ * supplied via libc's setlocale()), then
+ * register the locale for use in dgettext() so
+ * as to reestablish the locale for ld.so.1's
+ * messages.
+ */
+ if (gptr) {
+ free((void *)gptr);
+ rtld_flags |= RT_FL_NEWLOCALE;
+ }
+ glcs[tag].lc_un.lc_ptr = strdup(lptr);
+
+ /*
+ * Clear any cached messages.
+ */
+ err_strs[ERR_NONE] = 0;
+ err_strs[ERR_WARNING] = 0;
+ err_strs[ERR_FATAL] = 0;
+ err_strs[ERR_ELF] = 0;
+
+ nosym_str = 0;
+ }
+ break;
+
+ case CI_BIND_GUARD:
+ case CI_BIND_CLEAR:
+ case CI_THR_SELF:
+ /*
+ * If the global vector is unset, or this is the primary
+ * link-map, set the global vector.
+ */
+ if ((gptr == 0) || (lml->lm_flags & LML_FLG_BASELM))
+ glcs[tag].lc_un.lc_ptr = lptr;
+
+ /* FALLTHROUGH */
+
+ case CI_TLS_MODADD:
+ case CI_TLS_MODREM:
+ case CI_TLS_STATMOD:
+ case CI_THRINIT:
+ threaded++;
+ break;
+
+ case CI_VERSION:
+ if ((rtld_flags2 & RT_FL2_RTLDSEEN) == 0) {
+ rtld_flags2 |= RT_FL2_RTLDSEEN;
+
+ if (funcs->ci_un.ci_val >= CI_V_FOUR) {
+ Listnode *lnp;
+ Lm_list *lml2;
+
+ rtld_flags2 |= RT_FL2_UNIFPROC;
+
+ /*
+ * We might have seen auditor which is
+ * not dependent on libc. Such an
+ * auditor's link map list has
+ * LML_FLG_HOLDLOCK set. This lock
+ * needs to be dropped. Refer to
+ * audit_setup() in audit.c.
+ */
+ if ((rtld_flags2 & RT_FL2_HASAUDIT) ==
+ 0)
+ break;
+
+ /*
+ * Yes, we did. Take care of them.
+ */
+ for (LIST_TRAVERSE(&dynlm_list, lnp,
+ lml2)) {
+ Rt_map *map =
+ (Rt_map *)lml2->lm_head;
+
+ if (FLAGS(map) & FLG_RT_AUDIT) {
+ lml2->lm_flags &=
+ ~LML_FLG_HOLDLOCK;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (threaded == 0)
+ return;
+
+ /*
+ * If a version of libc gives us only a subset of the TLS interfaces -
+ * it's confused and we discard the whole lot.
+ */
+ if ((lcp[CI_TLS_MODADD].lc_un.lc_func &&
+ lcp[CI_TLS_MODREM].lc_un.lc_func &&
+ lcp[CI_TLS_STATMOD].lc_un.lc_func) == 0) {
+ lcp[CI_TLS_MODADD].lc_un.lc_func = 0;
+ lcp[CI_TLS_MODREM].lc_un.lc_func = 0;
+ lcp[CI_TLS_STATMOD].lc_un.lc_func = 0;
+ }
+
+ /*
+ * Indicate that we're now thread capable, and enable concurrency if
+ * requested.
+ */
+ if ((rtld_flags & RT_FL_NOCONCUR) == 0)
+ rtld_flags |= RT_FL_CONCUR;
+ if ((lml->lm_flags & LML_FLG_RTLDLM) == 0)
+ rtld_flags |= RT_FL_THREADS;
+}
+
+/*
+ * At this point we know we have a set of objects that have been fully analyzed
+ * and relocated. Prior to the next major step of running .init sections (ie.
+ * running user code), retrieve any RTLDINFO interfaces.
+ */
+int
+rt_get_extern(Lm_list *lml, Rt_map *lmp)
+{
+ if (lml->lm_rti) {
+ Aliste off;
+ Rti_desc *rti;
+
+ for (ALIST_TRAVERSE(lml->lm_rti, off, rti))
+ get_lcinterface(rti->rti_lmp, rti->rti_info);
+
+ free(lml->lm_rti);
+ lml->lm_rti = 0;
+ }
+
+ /*
+ * Perform some sanity checks. If we have TLS requirements we better
+ * have the associated external interfaces.
+ */
+ if (lml->lm_tls && (lml->lm_lcs[CI_TLS_STATMOD].lc_un.lc_func == 0)) {
+ eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ERR_TLS_NOTLS),
+ NAME(lmp));
+ return (0);
+ }
+ return (1);
+}
+
+static int bindmask = 0;
+
+int
+rt_bind_guard(int bindflag)
+{
+ int (*fptr)(int);
+
+ if ((fptr = glcs[CI_BIND_GUARD].lc_un.lc_func) != NULL) {
+ return ((*fptr)(bindflag));
+ } else {
+ if ((bindflag & bindmask) == 0) {
+ bindmask |= bindflag;
+ return (1);
+ }
+ return (0);
+ }
+}
+
+int
+rt_bind_clear(int bindflag)
+{
+ int (*fptr)(int);
+
+ if ((fptr = glcs[CI_BIND_CLEAR].lc_un.lc_func) != NULL) {
+ return ((*fptr)(bindflag));
+ } else {
+ if (bindflag == 0)
+ return (bindmask);
+ else {
+ bindmask &= ~bindflag;
+ return (0);
+ }
+ }
+}
+
+/*
+ * Make sure threads have been initialized. This interface is called once for
+ * each link-map list.
+ */
+void
+rt_thr_init(Lm_list *lml)
+{
+ void (*fptr)(void);
+
+ if ((fptr = (void (*)())lml->lm_lcs[CI_THRINIT].lc_un.lc_func) != 0) {
+ lml->lm_lcs[CI_THRINIT].lc_un.lc_func = 0;
+ leave((Lm_list *)0);
+ (*fptr)();
+ (void) enter();
+ }
+}
+
+thread_t
+rt_thr_self()
+{
+ thread_t (*fptr)(void);
+
+ if ((fptr = (thread_t (*)())glcs[CI_THR_SELF].lc_un.lc_func) != NULL)
+ return ((*fptr)());
+
+ return (1);
+}
+
+int
+rt_mutex_lock(Rt_lock * mp)
+{
+ return (_lwp_mutex_lock((lwp_mutex_t *)mp));
+}
+
+int
+rt_mutex_unlock(Rt_lock * mp)
+{
+ return (_lwp_mutex_unlock((lwp_mutex_t *)mp));
+}
+
+Rt_cond *
+rt_cond_create()
+{
+ return (calloc(1, sizeof (Rt_cond)));
+}
+
+int
+rt_cond_wait(Rt_cond * cvp, Rt_lock * mp)
+{
+ return (_lwp_cond_wait(cvp, (lwp_mutex_t *)mp));
+}
+
+int
+rt_cond_broadcast(Rt_cond * cvp)
+{
+ return (_lwp_cond_broadcast(cvp));
+}
+
+#ifdef EXPAND_RELATIVE
+
+/*
+ * Mutex interfaces to resolve references from any objects extracted from
+ * libc_pic.a. Note, as ld.so.1 is essentially single threaded these can be
+ * noops.
+ */
+#pragma weak lmutex_lock = __mutex_lock
+#pragma weak _private_mutex_lock = __mutex_lock
+#pragma weak mutex_lock = __mutex_lock
+#pragma weak _mutex_lock = __mutex_lock
+/* ARGSUSED */
+int
+__mutex_lock(mutex_t *mp)
+{
+ return (0);
+}
+
+#pragma weak lmutex_unlock = __mutex_unlock
+#pragma weak _private_mutex_unlock = __mutex_unlock
+#pragma weak mutex_unlock = __mutex_unlock
+#pragma weak _mutex_unlock = __mutex_unlock
+/* ARGSUSED */
+int
+__mutex_unlock(mutex_t *mp)
+{
+ return (0);
+}
+
+/*
+ * This is needed to satisfy sysconf() (case _SC_THREAD_STACK_MIN)
+ */
+#pragma weak thr_min_stack = _thr_min_stack
+size_t
+_thr_min_stack()
+{
+#ifdef _LP64
+ return (8 * 1024);
+#else
+ return (4 * 1024);
+#endif
+}
+
+#endif /* EXPAND_RELATIVE */
--- a/usr/src/cmd/sgs/rtld/common/globals.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/common/globals.c Tue Apr 18 08:51:16 2006 -0700
@@ -59,8 +59,6 @@
Reglist * reglist = 0; /* list of register symbols */
-void (*thrinit)() = 0; /* thread initialization */
-
ulong_t hwcap = 0; /* hardware capabilities */
ulong_t sfcap = 0; /* software capabilities */
@@ -99,6 +97,8 @@
/*
* Various other global data.
*/
+Lc_desc glcs[CI_MAX]; /* global external interfaces */
+
const char *procname = (const char *)0;
const char *rtldname = MSG_ORIG(MSG_FIL_RTLD);
@@ -117,8 +117,6 @@
/* is all) */
Audit_desc *auditors = 0; /* global auditors (LD_AUDIT) */
-const char *locale = 0; /* locale environment definition */
-
const char *rpl_audit = 0; /* replaceable LD_AUDIT string */
const char *rpl_debug = 0; /* replaceable LD_DEBUG string */
const char *rpl_ldflags = 0; /* replaceable LD_FLAGS string */
--- a/usr/src/cmd/sgs/rtld/common/locale.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/common/locale.c Tue Apr 18 08:51:16 2006 -0700
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -153,7 +153,7 @@
dom->dom_msghdr = (Msghdr *)-1;
(void) snprintf(path, PATH_MAX, MSG_ORIG(MSG_FMT_MSGFILE),
- locale, domain);
+ glcs[CI_LCMESSAGES].lc_un.lc_ptr, domain);
if ((fd = open(path, O_RDONLY, 0)) == -1)
return;
@@ -222,7 +222,7 @@
Domain *_domain;
int cnt;
- if (locale == 0)
+ if (glcs[CI_LCMESSAGES].lc_un.lc_val == 0)
return (msgid);
/*
--- a/usr/src/cmd/sgs/rtld/common/mapfile-vers Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/common/mapfile-vers Tue Apr 18 08:51:16 2006 -0700
@@ -60,7 +60,6 @@
_dlsym;
dlsym;
- _ld_concurrency; # Provides libthread initialization
_ld_libc; # provides libc initialization
_elf_rtbndr; # dbx expects to find these
--- a/usr/src/cmd/sgs/rtld/common/mutex.c Tue Apr 18 07:10:32 2006 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,524 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (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 2001-2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Implementation of all threads interfaces between ld.so.1 and libthread.
- *
- * In a non-threaded environment all thread interfaces are vectored to noops.
- * When called via _ld_concurrency() from libthread these vectors are reassigned
- * to real threads interfaces. Two models are supported:
- *
- * TI_VERSION == 1
- * Under this model libthread provides rw_rwlock/rw_unlock, through which
- * we vector all rt_mutex_lock/rt_mutex_unlock calls.
- * Under lib/libthread these interfaces provided _sigon/_sigoff (unlike
- * lwp/libthread that provided signal blocking via bind_guard/bind_clear.
- *
- * TI_VERSION == 2
- * Under this model only libthreads bind_guard/bind_clear and thr_self
- * interfaces are used. Both libthreads block signals under the
- * bind_guard/bind_clear interfaces. Lower level locking is derived
- * from internally bound _lwp_ interfaces. This removes recursive
- * problems encountered when obtaining locking interfaces from libthread.
- * The use of mutexes over reader/writer locks also enables the use of
- * condition variables for controlling thread concurrency (allows access to
- * objects only after their .init has completed).
- *
- * CI_VERSION == 1
- * introduced with CI_VERSION & CI_ATEXIT
- *
- * CI_VERSION == 2
- * add support for CI_LCMESSAGES
- *
- * CI_VERSION == 3
- * Add the following versions to the CI table:
- *
- * CI_BIND_GUARD, CI_BIND_CLEAR, CI_THR_SELF
- * CI_TLS_MODADD, CI_TLS_MOD_REMOVE, CI_TLS_STATMOD
- *
- * It was also at this level that the DT_SUNW_RTLDINFO structure
- * was introduced as a mechanism to handshake with ld.so.1
- *
- * CI_VERSION == 4
- * Added the CI_THRINIT handshake as part of the libc/libthread
- * merge project. libc now initializes the current thread pointer
- * (%g7 for sparc) as part of this and no longer relies on the
- * INITFIRST flag (which others have started to camp out on).
- */
-#include "_synonyms.h"
-
-#include <synch.h>
-#include <signal.h>
-#include <thread.h>
-#include <synch.h>
-#include <strings.h>
-#include <stdio.h>
-#include "thr_int.h"
-#include "_elf.h"
-#include "_rtld.h"
-
-/*
- * Define our own local mutex functions.
- */
-static int bindmask = THR_FLG_RTLD;
-
-static int
-_rt_bind_guard(int bit)
-{
- if ((bit & bindmask) == 0) {
- bindmask |= bit;
- return (1);
- }
- return (0);
-}
-
-static int
-_rt_bind_clear(int bit)
-{
- if (bit == 0)
- return (bindmask);
- else {
- bindmask &= ~bit;
- return (0);
- }
-}
-
-static int
-_rt_thr_self()
-{
- return (1);
-}
-
-static int
-_rt_null()
-{
- return (0);
-}
-
-#if (defined(DEBUG) || defined(SGS_PRE_UNIFIED_PROCESS))
-/*
- * These three routines are used to protect the locks that ld.so.1 has.
- * They are passed to pthread_atfork() and used during a fork1() to make
- * sure we do not do a fork while a lock is being held.
- */
-static void
-prepare_atfork(void)
-{
- (void) rt_bind_guard(THR_FLG_MASK);
- (void) rt_mutex_lock(&rtldlock);
-}
-
-static void
-child_atfork(void)
-{
- (void) rt_mutex_unlock(&rtldlock);
- (void) rt_bind_clear(THR_FLG_MASK);
-}
-
-static void
-parent_atfork(void)
-{
- (void) rt_mutex_unlock(&rtldlock);
- (void) rt_bind_clear(THR_FLG_MASK);
-}
-#endif
-
-/*
- * Define the maximum number of thread interfaces ld.so.1 is interested in,
- * this is a subset of the total number of interfaces communicated between
- * libthread and libc.
- */
-#define STI_MAX 11
-
-/*
- * Define our own thread jump table.
- */
-#define RT_BIND_GUARD 0
-#define RT_BIND_CLEAR 1
-#define RT_THR_SELF 2
-#define RT_MUTEX_LOCK 3
-#define RT_MUTEX_UNLOCK 4
-#define RT_COND_WAIT 5
-#define RT_COND_BROAD 6
-
-#define SRT_MAX 7
-
-static int (* thr_jmp_table[SRT_MAX])() = {
- _rt_bind_guard, /* RT_BIND_GUARD */
- _rt_bind_clear, /* RT_BIND_CLEAR */
- _rt_thr_self, /* RT_THR_SELF */
- _rt_null, /* RT_MUTEX_LOCK */
- _rt_null, /* RT_MUTEX_UNLOCK */
- _rt_null, /* RT_COND_WAIT */
- _rt_null /* RT_COND_BROAD */
-};
-
-#if (defined(DEBUG) || defined(SGS_PRE_UNIFIED_PROCESS))
-static int (* thr_def_table[SRT_MAX])() = {
- _rt_bind_guard, /* RT_BIND_GUARD */
- _rt_bind_clear, /* RT_BIND_CLEAR */
- _rt_thr_self, /* RT_THR_SELF */
- _rt_null, /* RT_MUTEX_LOCK */
- _rt_null, /* RT_MUTEX_UNLOCK */
- _rt_null, /* RT_COND_WAIT */
- _rt_null /* RT_COND_BROAD */
-};
-#endif
-
-/*
- * The interface with the threads library which is supplied through libdl.so.1.
- * A non-null argument allows a function pointer array to be passed to us which
- * is used to re-initialize the linker concurrency table. A null argument
- * causes the table to be reset to the defaults.
- */
-void
-/* ARGSUSED */
-_ld_concurrency(void * ptr)
-{
-#if (defined(DEBUG) || defined(SGS_PRE_UNIFIED_PROCESS))
- int tag;
- Thr_interface * funcs = ptr;
-
- if (funcs) {
- int (* table[STI_MAX])();
-
- /*
- * Collect all the threads interfaces we're interested in.
- */
- table[TI_LATFORK] = NULL;
- for (tag = funcs->ti_tag; tag; tag = (++funcs)->ti_tag) {
- if (tag < STI_MAX)
- table[tag] = funcs->ti_un.ti_func;
- }
-
- /*
- * At this point we've re-entered ld.so.1 from libthreads .init.
- * All locks are down. Exercise any common thread interfaces
- * before we remap ld.so.1 to use them, this allows us to be
- * re-entered to resolve .plt's without exercising locks.
- */
- (void) (*table[TI_BIND_GUARD])(THR_FLG_RTLD);
- (void) (*table[TI_BIND_CLEAR])(THR_FLG_RTLD);
- (void) (*table[TI_THRSELF])();
-
- /*
- * Prepare atfork, if necessary.
- */
- if (table[TI_LATFORK])
- (void) (*table[TI_LATFORK])(prepare_atfork,
- parent_atfork, child_atfork);
-
- /*
- * Establish what interfaces are available for this version of
- * libthread and make them live.
- */
- if (table[TI_VERSION] == (int (*)())1) {
- /*
- * Restrict ourselves to the readers/writers locks.
- */
- (void) (*table[TI_LRW_WRLOCK])(&rtldlock);
- (void) (*table[TI_LRW_UNLOCK])(&rtldlock);
-
- thr_jmp_table[RT_MUTEX_LOCK] = table[TI_LRW_WRLOCK];
- thr_jmp_table[RT_MUTEX_UNLOCK] = table[TI_LRW_UNLOCK];
- } else {
- /*
- * Go directly to our internal interfaces.
- */
- thr_jmp_table[RT_MUTEX_LOCK] = _lwp_mutex_lock;
- thr_jmp_table[RT_MUTEX_UNLOCK] = _lwp_mutex_unlock;
- thr_jmp_table[RT_COND_WAIT] = _lwp_cond_wait;
- thr_jmp_table[RT_COND_BROAD] = _lwp_cond_broadcast;
-
- /*
- * If concurrency is requested inable it now.
- */
- if ((rtld_flags & RT_FL_NOCONCUR) == 0)
- rtld_flags |= RT_FL_CONCUR;
- }
-
- /*
- * Make all common interfaces go live.
- */
- thr_jmp_table[RT_BIND_CLEAR] = table[TI_BIND_CLEAR];
- thr_jmp_table[RT_BIND_GUARD] = table[TI_BIND_GUARD];
- thr_jmp_table[RT_THR_SELF] = table[TI_THRSELF];
-
- rtld_flags |= RT_FL_THREADS;
-
- } else {
- /*
- * If libthread were to be dlclosed() we'd get here to reset
- * our interfaces back to the internal noops (as libthread
- * typically can't be dlclosed() it's unlikely we'll ever
- * exercise this. If a bindlock is currently in place clear it.
- */
- if (rt_bind_clear(0x0) & THR_FLG_RTLD) {
- (void) rt_mutex_unlock(&rtldlock);
- (void) rt_bind_clear(THR_FLG_RTLD);
- }
- rtld_flags &= ~RT_FL_THREADS;
- for (tag = 0; tag < SRT_MAX; tag++)
- thr_jmp_table[tag] = thr_def_table[tag];
- }
-#endif
-}
-
-void
-get_lcinterface(Rt_map *lmp, Lc_interface *funcs)
-{
- int tag;
- char *nlocale;
- void *tlsmodadd = 0;
- void *tlsmodrem = 0;
- void *tlsstatmod = 0;
- Lm_list *lml, *lml2;
- Listnode *lnp;
-
- if (!funcs || !lmp)
- return;
-
- lml = LIST(lmp);
-
- for (tag = funcs->ci_tag; tag; tag = (++funcs)->ci_tag) {
- switch (tag) {
- case CI_ATEXIT:
- /*
- * If we obtained a _preexec_exit_handlers()
- * call back (typically supplied via libc's
- * .init) then register it for use in dlclose().
- */
- if (lml->lm_peh == 0) {
- lml->lm_peh = funcs->ci_un.ci_func;
- lml->lm_peh_lmp = lmp;
- }
- break;
- case CI_LCMESSAGES:
- /*
- * If we've obtained a message locale (typically
- * supplied via libc's setlocale()) then
- * register it for use in dgettext() to
- * reestablish a locale for ld.so.1's messages.
- */
- if (lml->lm_flags & LML_FLG_BASELM) {
- nlocale = funcs->ci_un.ci_ptr;
- if ((locale == 0) ||
- strcmp(locale, nlocale)) {
- if (locale) {
- free((void *)locale);
- rtld_flags |= RT_FL_NEWLOCALE;
- }
- locale = strdup(nlocale);
-
- /*
- * Clear any cached messages.
- */
- err_strs[ERR_NONE] = 0;
- err_strs[ERR_WARNING] = 0;
- err_strs[ERR_FATAL] = 0;
- err_strs[ERR_ELF] = 0;
-
- nosym_str = 0;
- }
- }
- break;
- case CI_BIND_GUARD:
- thr_jmp_table[RT_BIND_GUARD] =
- (int(*)())funcs->ci_un.ci_ptr;
- /*
- * Go directly to our internal interfaces.
- */
- thr_jmp_table[RT_MUTEX_LOCK] = _lwp_mutex_lock;
- thr_jmp_table[RT_MUTEX_UNLOCK] = _lwp_mutex_unlock;
- thr_jmp_table[RT_COND_WAIT] = _lwp_cond_wait;
- thr_jmp_table[RT_COND_BROAD] = _lwp_cond_broadcast;
-
- /*
- * If concurrency is requested inable it now.
- */
- if ((rtld_flags & RT_FL_NOCONCUR) == 0)
- rtld_flags |= RT_FL_CONCUR;
- rtld_flags |= RT_FL_THREADS;
- break;
- case CI_BIND_CLEAR:
- thr_jmp_table[RT_BIND_CLEAR] =
- (int(*)()) funcs->ci_un.ci_ptr;
- break;
- case CI_THR_SELF:
- thr_jmp_table[RT_THR_SELF] =
- (int(*)()) funcs->ci_un.ci_ptr;
- break;
- case CI_TLS_MODADD:
- tlsmodadd = funcs->ci_un.ci_ptr;
- break;
- case CI_TLS_MODREM:
- tlsmodrem = funcs->ci_un.ci_ptr;
- break;
- case CI_TLS_STATMOD:
- tlsstatmod = funcs->ci_un.ci_ptr;
- break;
-#ifdef CI_THRINIT
- case CI_THRINIT:
- thrinit = (void(*)())funcs->ci_un.ci_ptr;
- break;
-#endif
-#ifdef CI_V_FOUR
- case CI_VERSION:
- if ((rtld_flags2 & RT_FL2_RTLDSEEN) == 0) {
- rtld_flags2 |= RT_FL2_RTLDSEEN;
- if (funcs->ci_un.ci_val >= CI_V_FOUR) {
- rtld_flags2 |= RT_FL2_UNIFPROC;
-
- /*
- * We might have seen auditor which
- * is not dependent on libc. Such auditor's
- * link map list has LML_FLG_HOLDLOCK on.
- * It needs to be dropped. Refer to:
- * audit_setup() in audit.c.
- */
- if ((rtld_flags2 & RT_FL2_HASAUDIT) == 0)
- break;
-
- /*
- * Yes, we did. Take care of them.
- */
- for (LIST_TRAVERSE(&dynlm_list, lnp, lml2)) {
- Rt_map *map = (Rt_map *)lml2->lm_head;
-
- if (FLAGS(map) & FLG_RT_AUDIT) {
- lml2->lm_flags &=
- ~LML_FLG_HOLDLOCK;
- }
- }
- }
- }
- break;
-#endif
- default:
- break;
- }
- }
- if (tlsmodadd && tlsmodrem && tlsstatmod)
- tls_setroutines(lml, tlsmodadd, tlsmodrem, tlsstatmod);
-}
-
-/*
- * Define the local interface for each of the threads interfaces.
- */
-thread_t
-rt_thr_self()
-{
- return ((* thr_jmp_table[RT_THR_SELF])());
-}
-
-int
-rt_mutex_lock(Rt_lock * mp)
-{
- return ((* thr_jmp_table[RT_MUTEX_LOCK])(mp));
-}
-
-int
-rt_mutex_unlock(Rt_lock * mp)
-{
- return ((* thr_jmp_table[RT_MUTEX_UNLOCK])(mp));
-}
-
-int
-rt_bind_guard(int bindflag)
-{
- return ((* thr_jmp_table[RT_BIND_GUARD])(bindflag));
-}
-
-int
-rt_bind_clear(int bindflag)
-{
- return ((* thr_jmp_table[RT_BIND_CLEAR])(bindflag));
-}
-
-Rt_cond *
-rt_cond_create()
-{
- return (calloc(1, sizeof (Rt_cond)));
-}
-
-int
-rt_cond_wait(Rt_cond * cvp, Rt_lock * mp)
-{
- return ((* thr_jmp_table[RT_COND_WAIT])(cvp, mp));
-}
-
-int
-rt_cond_broadcast(Rt_cond * cvp)
-{
- return ((* thr_jmp_table[RT_COND_BROAD])(cvp));
-}
-
-#ifdef EXPAND_RELATIVE
-
-/*
- * Mutex interfaces to resolve references from any objects extracted from
- * libc_pic.a. Note, as ld.so.1 is essentially single threaded these can be
- * noops.
- */
-
-#pragma weak lmutex_lock = __mutex_lock
-#pragma weak _private_mutex_lock = __mutex_lock
-#pragma weak mutex_lock = __mutex_lock
-#pragma weak _mutex_lock = __mutex_lock
-/* ARGSUSED */
-int
-__mutex_lock(mutex_t *mp)
-{
- return (0);
-}
-
-#pragma weak lmutex_unlock = __mutex_unlock
-#pragma weak _private_mutex_unlock = __mutex_unlock
-#pragma weak mutex_unlock = __mutex_unlock
-#pragma weak _mutex_unlock = __mutex_unlock
-/* ARGSUSED */
-int
-__mutex_unlock(mutex_t *mp)
-{
- return (0);
-}
-
-/*
- * This is needed to satisfy sysconf() (case _SC_THREAD_STACK_MIN)
- */
-#pragma weak thr_min_stack = _thr_min_stack
-size_t
-_thr_min_stack()
-{
-#ifdef _LP64
- return (8 * 1024);
-#else
- return (4 * 1024);
-#endif
-}
-
-#endif /* EXPAND_RELATIVE */
--- a/usr/src/cmd/sgs/rtld/common/remove.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/common/remove.c Tue Apr 18 08:51:16 2006 -0700
@@ -76,11 +76,12 @@
Rt_map **_tobj;
Lc_addr_range_t *addr, *_addr;
int error;
+ int (*fptr)(Lc_addr_range_t *, uint_t);
/*
* Has a callback been established?
*/
- if (lml->lm_peh == 0)
+ if ((fptr = lml->lm_lcs[CI_ATEXIT].lc_un.lc_func) == NULL)
return (0);
/*
@@ -120,9 +121,7 @@
_addr->lb = _addr->ub = 0;
leave(LIST(*tobj));
-
- error = (* lml->lm_peh)(addr, (num - 1));
-
+ error = (*fptr)(addr, (num - 1));
(void) enter();
/*
@@ -191,11 +190,11 @@
free(lml->lm_lists);
/*
- * Cleanup rtldinfo in the case where it was allocated but
- * not called (see _relocate_so()).
+ * Cleanup any pending RTLDINFO in the case where it was
+ * allocated but not called (see _relocate_lmc()).
*/
- if (lml->lm_rtldinfo)
- free(lml->lm_rtldinfo);
+ if (lml->lm_rti)
+ free(lml->lm_rti);
if (lml->lm_fpavl) {
/*
* As we are freeing the link-map list, all nodes must
@@ -235,13 +234,25 @@
lm_delete(lml, lmp);
/*
- * If this object contributed the preexec_exit_handler() routine for
- * the current link-map list, mark the list as no-longer containing a
- * preexec_exit_handler() routine.
+ * If this object contributed any local external vectors for the current
+ * link-map list, remove the vectors. If this object contributed any
+ * global external vectors we should find some new candidates, or leave
+ * this object lying around.
*/
- if (lml && (lml->lm_peh_lmp == lmp)) {
- lml->lm_peh = 0;
- lml->lm_peh_lmp = 0;
+ if (lml) {
+ int tag;
+
+ for (tag = 0; tag < CI_MAX; tag++) {
+ if (lml->lm_lcs[tag].lc_lmp == lmp) {
+ lml->lm_lcs[tag].lc_lmp = 0;
+ lml->lm_lcs[tag].lc_un.lc_val = 0;
+ }
+ if (glcs[tag].lc_lmp == lmp) {
+ ASSERT(glcs[tag].lc_lmp != 0);
+ glcs[tag].lc_lmp = 0;
+ glcs[tag].lc_un.lc_val = 0;
+ }
+ }
}
DBG_CALL(Dbg_file_delete(lmp));
@@ -1291,7 +1302,7 @@
* Complete the link-map deletion if appropriate.
*/
if (FLAGS(lmp) & FLG_RT_DELETE) {
- tls_modactivity(lmp, TM_FLG_MODREM);
+ tls_modaddrem(lmp, TM_FLG_MODREM);
remove_so(LIST(lmp), lmp);
}
}
--- a/usr/src/cmd/sgs/rtld/common/setup.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/common/setup.c Tue Apr 18 08:51:16 2006 -0700
@@ -176,6 +176,7 @@
size_t eaddr, esize;
char *str, *argvname;
Mmap *mmaps;
+ Word lmflags;
/*
* Now that ld.so has relocated itself, initialize our own 'environ' so
@@ -612,14 +613,16 @@
mmaps[mmapcnt].m_perm = perm;
mmapcnt++;
- } else if (pptr->p_type == PT_DYNAMIC)
+ } else if (pptr->p_type == PT_DYNAMIC) {
dyn = (Dyn *)(pptr->p_vaddr + base);
- else if (pptr->p_type == PT_TLS)
+ } else if ((pptr->p_type == PT_TLS) &&
+ pptr->p_memsz) {
tlsphdr = pptr;
- else if (pptr->p_type == PT_SUNW_UNWIND)
+ } else if (pptr->p_type == PT_SUNW_UNWIND) {
unwindphdr = pptr;
- else if (pptr->p_type == PT_SUNWCAP)
+ } else if (pptr->p_type == PT_SUNWCAP) {
cap = (Cap *)(pptr->p_vaddr + base);
+ }
pptr = (Phdr *)((ulong_t)pptr + phsize);
}
@@ -639,6 +642,7 @@
if (tlsphdr) {
PTTLS(mlmp) = tlsphdr;
tls_assign_soffset(mlmp);
+ lml_main.lm_tls++;
}
if (unwindphdr)
PTUNWIND(mlmp) = unwindphdr;
@@ -948,7 +952,6 @@
* loaded.
*/
if ((rtld_flags & RT_FL_CONFGEN) == 0) {
- Word lmflags;
DBG_CALL(Dbg_util_nl(&lml_main, DBG_NL_STD));
@@ -956,29 +959,6 @@
return (0);
/*
- * Sort the .init sections of all objects we've added. If
- * we're tracing we only need to execute this under ldd(1)
- * with the -i or -u options.
- */
- lmflags = lml_main.lm_flags;
- if (((lmflags & LML_FLG_TRC_ENABLE) == 0) ||
- (lmflags & (LML_FLG_TRC_INIT | LML_FLG_TRC_UNREF))) {
- if ((tobj = tsort(mlmp, LIST(mlmp)->lm_init,
- RT_SORT_REV)) == (Rt_map **)S_ERROR)
- return (0);
- }
-
- /*
- * If we are tracing we're done. This is the one legitimate use
- * of a direct call to rtldexit() rather than return, as we
- * don't want to return and jump to the application.
- */
- if (lmflags & LML_FLG_TRC_ENABLE) {
- unused(&lml_main);
- rtldexit(&lml_main, 0);
- }
-
- /*
* Inform the debuggers we're here and stable. Newer debuggers
* can indicate their presence by setting the DT_DEBUG entry in
* the dynamic executable (see elf_new_lm()). In this case call
@@ -993,20 +973,20 @@
r_debug.rtd_rdebug.r_flags |= RD_FL_ODBG;
(void) getpid();
}
-
- /*
- * Initialize any initial TLS storage.
- */
- if (tls_report_modules() == 0)
- return (0);
}
/*
- * Call any necessary auditing routines, clean up any file descriptors
- * and such, and then fire all dependencies .init sections.
+ * Indicate preinit activity, and call any auditing routines. These
+ * routines are called before initializing any threads via libc, or
+ * before collecting the complete set of .inits on the primary link-map.
+ * Although most libc interfaces are encapsulated in local routines
+ * within libc, they have been known to escape (ie. call a .plt). As
+ * the appcert auditor uses preinit as a trigger to establish some
+ * external interfaces to the main link-maps libc, we need to activate
+ * this trigger before exercising any code within libc. Additionally,
+ * I wouldn't put it past an auditor to add additional objects to the
+ * primary link-map. Hence, we collect .inits after the audit call.
*/
- rtld_flags |= RT_FL_APPLIC;
-
rd_event(&lml_main, RD_PREINIT, 0);
if ((lml_main.lm_tflags | FLAGS1(mlmp)) & LML_TFLG_AUD_ACTIVITY)
@@ -1014,6 +994,59 @@
if ((lml_main.lm_tflags | FLAGS1(mlmp)) & LML_TFLG_AUD_PREINIT)
audit_preinit(mlmp);
+ /*
+ * If we're creating initial configuration information, we're done
+ * now that the auditing step has been called.
+ */
+ if (rtld_flags & RT_FL_CONFGEN) {
+ leave(LIST(mlmp));
+ return (mlmp);
+ }
+
+ /*
+ * Sort the .init sections of all objects we've added. If we're
+ * tracing we only need to execute this under ldd(1) with the -i or -u
+ * options.
+ */
+ lmflags = lml_main.lm_flags;
+ if (((lmflags & LML_FLG_TRC_ENABLE) == 0) ||
+ (lmflags & (LML_FLG_TRC_INIT | LML_FLG_TRC_UNREF))) {
+ if ((tobj = tsort(mlmp, LIST(mlmp)->lm_init,
+ RT_SORT_REV)) == (Rt_map **)S_ERROR)
+ return (0);
+ }
+
+ /*
+ * If we are tracing we're done. This is the one legitimate use of a
+ * direct call to rtldexit() rather than return, as we don't want to
+ * return and jump to the application.
+ */
+ if (lmflags & LML_FLG_TRC_ENABLE) {
+ unused(&lml_main);
+ rtldexit(&lml_main, 0);
+ }
+
+ /*
+ * Establish any static TLS for this primary link-map. Note, regardless
+ * of whether TLS is available, an initial handshake occurs with libc to
+ * indicate we're processing the primary link-map. Having identified
+ * the primary link-map, initialize threads.
+ */
+ if (rt_get_extern(&lml_main, mlmp) == 0)
+ return (0);
+ if (tls_statmod(&lml_main, mlmp) == 0)
+ return (0);
+
+ rt_thr_init(&lml_main);
+
+ rtld_flags2 |= RT_FL2_PLMSETUP;
+ rtld_flags |= RT_FL_APPLIC;
+
+ /*
+ * Fire all dependencies .init sections. Identify any unused
+ * dependencies, and leave the runtime linker - effectively calling
+ * the dynamic executables entry point.
+ */
call_array(PREINITARRAY(mlmp), (uint_t)PREINITARRAYSZ(mlmp), mlmp,
SHT_PREINIT_ARRAY);
--- a/usr/src/cmd/sgs/rtld/common/tls.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/common/tls.c Tue Apr 18 08:51:16 2006 -0700
@@ -36,13 +36,7 @@
#include <msg.h>
#include <debug.h>
-
-static void (* fptr_tls_modadd)(TLS_modinfo *) = 0;
-static void (* fptr_tls_modrem)(TLS_modinfo *) = 0;
-static void (* fptr_tls_statmods)(TLS_modinfo **, unsigned long) = 0;
-
-static int tlsinitialized = 0;
-static unsigned long tls_static_size = 0; /* static TLS buffer size */
+static ulong_t tls_static_size = 0; /* static TLS buffer size */
#define TLSBLOCKCNT 16 /* number of blocks of tmi_bits to allocate */
/* at a time. */
@@ -54,16 +48,15 @@
static Tlsmodid tmid = {0, 0, 0};
-unsigned long
+ulong_t
tls_getmodid()
{
ulong_t ndx;
ulong_t i;
if (tmid.tmi_bits == 0) {
- if ((tmid.tmi_bits =
- (uint_t *)calloc(TLSBLOCKCNT, sizeof (uint_t))) == 0)
- return ((unsigned long)-1);
+ if ((tmid.tmi_bits = calloc(TLSBLOCKCNT, sizeof (uint_t))) == 0)
+ return ((ulong_t)-1);
tmid.tmi_bits[0] = 1;
tmid.tmi_lowfree = 1;
tmid.tmi_cnt = TLSBLOCKCNT;
@@ -91,12 +84,13 @@
/*
* All bits taken - must allocate a new block
*/
- if ((tmid.tmi_bits = (uint_t *)realloc(tmid.tmi_bits,
+ if ((tmid.tmi_bits = realloc(tmid.tmi_bits,
((tmid.tmi_cnt * sizeof (uint_t)) +
(TLSBLOCKCNT * sizeof (uint_t))))) == 0)
- return ((unsigned long)-1);
+ return ((ulong_t)-1);
+
/*
- * clear out the tail of the new allocation
+ * Clear out the tail of the new allocation.
*/
bzero(&(tmid.tmi_bits[tmid.tmi_cnt]), TLSBLOCKCNT * sizeof (uint_t));
tmid.tmi_bits[tmid.tmi_cnt] = 1;
@@ -107,9 +101,8 @@
return (ndx);
}
-
void
-tls_freemodid(unsigned long modid)
+tls_freemodid(ulong_t modid)
{
ulong_t i;
uint_t j;
@@ -123,54 +116,21 @@
tmid.tmi_lowfree = modid;
}
-
void
-tls_setroutines(Lm_list *lml, void * modadd, void * modrem, void * statmod)
+tls_modaddrem(Rt_map *lmp, uint_t flag)
{
- /*
- * If a version of libc/libthread gives us only a subset
- * of the TLS interfaces - it's confused and we discard
- * the whole lot.
- */
- if (!modadd || !modrem || !statmod)
- return;
+ Lm_list *lml = LIST(lmp);
+ TLS_modinfo tmi;
+ Phdr *tlsphdr;
+ void (*fptr)(TLS_modinfo *);
- if ((fptr_tls_modadd == 0) || (lml->lm_flags & LML_FLG_BASELM))
- fptr_tls_modadd = (void(*)(TLS_modinfo *)) modadd;
- if ((fptr_tls_modrem == 0) || (lml->lm_flags & LML_FLG_BASELM))
- fptr_tls_modrem = (void(*)(TLS_modinfo *)) modrem;
- /*
- * The 'statmods' interface is only relevent for the
- * primary link-map - ignore all other instances.
- */
- if (lml->lm_flags & LML_FLG_BASELM)
- fptr_tls_statmods =
- (void(*)(TLS_modinfo **, unsigned long)) statmod;
-}
-
-
-void
-tls_modactivity(Rt_map * lmp, uint_t flag)
-{
- TLS_modinfo tmi;
- Phdr * tlsphdr;
- void (* fptr)(TLS_modinfo *);
-
- if (flag & TM_FLG_MODADD)
- fptr = fptr_tls_modadd;
- else
- fptr = fptr_tls_modrem;
-
- /*
- * We only report TLS modactivity for the primary link-map
- * after all the objects have been loaded and we've reported
- * the STATIC tls modlist (see tls_report_modules()).
- */
- if (((tlsinitialized == 0) &&
- (LIST(lmp)->lm_flags & LML_FLG_BASELM)) ||
- (fptr == 0) || (lmp == 0) || (FCT(lmp) != &elf_fct) ||
- (PTTLS(lmp) == 0))
+ if (flag & TM_FLG_MODADD) {
+ fptr = (void (*)())lml->lm_lcs[CI_TLS_MODADD].lc_un.lc_func;
+ } else if (FLAGS1(lmp) & FL1_RT_TLSADD) {
+ fptr = (void (*)())lml->lm_lcs[CI_TLS_MODREM].lc_un.lc_func;
+ } else {
return;
+ }
tlsphdr = PTTLS(lmp);
@@ -178,86 +138,67 @@
tmi.tm_modname = PATHNAME(lmp);
tmi.tm_modid = TLSMODID(lmp);
tmi.tm_tlsblock = (void *)(tlsphdr->p_vaddr);
+
if (!(FLAGS(lmp) & FLG_RT_FIXED))
tmi.tm_tlsblock = (void *)((uintptr_t)tmi.tm_tlsblock +
ADDR(lmp));
+
tmi.tm_filesz = tlsphdr->p_filesz;
tmi.tm_memsz = tlsphdr->p_memsz;
tmi.tm_flags = 0;
tmi.tm_stattlsoffset = 0;
DBG_CALL(Dbg_tls_modactivity(LIST(lmp), &tmi, flag));
- fptr(&tmi);
+ (*fptr)(&tmi);
/*
- * Free up the moduleid
+ * Tag that this link-map has registered its TLS, and free up the
+ * moduleid
*/
+ FLAGS1(lmp) |= FL1_RT_TLSADD;
+
if (flag & TM_FLG_MODREM)
tls_freemodid(TLSMODID(lmp));
}
-
void
-tls_assign_soffset(Rt_map * lmp)
+tls_assign_soffset(Rt_map *lmp)
{
- if (PTTLS(lmp) == 0)
- return;
-
/*
* Only objects on the primary link-map list are associated
* with the STATIC tls block.
*/
- if (LIST(lmp)->lm_flags & LML_FLG_BASELM) {
+ if ((LIST(lmp)->lm_flags & LML_FLG_BASELM) &&
+ ((rtld_flags2 & RT_FL2_PLMSETUP) == 0)) {
tls_static_size += S_ROUND(PTTLS(lmp)->p_memsz, M_TLSSTATALIGN);
TLSSTATOFF(lmp) = tls_static_size;
}
/*
- * Everyone get's a dynamic TLS modid
+ * Everyone get's a dynamic TLS modid.
*/
TLSMODID(lmp) = tls_getmodid();
}
int
-tls_report_modules()
+tls_statmod(Lm_list *lml, Rt_map *lmp)
{
- Rt_map *lmp;
- uint_t tlsmodcnt, tlsmodndx;
- TLS_modinfo **tlsmodlist;
- TLS_modinfo *tlsbuflist;
+ uint_t tlsmodndx, tlsmodcnt = lml->lm_tls;
+ TLS_modinfo **tlsmodlist, *tlsbuflist;
Phdr *tlsphdr;
+ void (*fptr)(TLS_modinfo **, ulong_t);
- tlsinitialized++;
- /*
- * Scan through all objects to determine how many have TLS storage.
- */
- tlsmodcnt = 0;
- for (lmp = lml_main.lm_head; lmp; lmp = (Rt_map *)NEXT(lmp)) {
- if ((FCT(lmp) != &elf_fct) ||
- (PTTLS(lmp) == 0) || (PTTLS(lmp)->p_memsz == 0))
- continue;
- tlsmodcnt++;
-
- if (fptr_tls_statmods)
- continue;
-
- /*
- * If a module has TLS - but the TLS interfaces are not present
- * (no libthread?). Then this is a fatal condition.
- */
- eprintf(&lml_main, ERR_FATAL, MSG_INTL(MSG_ERR_TLS_NOTLS),
- NAME(lmp));
- return (0);
- }
+ fptr = (void (*)())lml->lm_lcs[CI_TLS_STATMOD].lc_un.lc_func;
/*
* If we don't have any TLS modules - report that and return.
*/
if (tlsmodcnt == 0) {
- if (fptr_tls_statmods != 0)
- fptr_tls_statmods(0, 0);
+ if (fptr)
+ (*fptr)(0, 0);
return (1);
}
+ lml->lm_tls = 0;
/*
* Allocate a buffer to report the TLS modules, the buffer consists of:
@@ -268,12 +209,13 @@
* The ptrs are initialized to the bufs - except the last
* one which null terminates the array.
*/
- if ((tlsmodlist = calloc((sizeof (TLS_modinfo *) * tlsmodcnt + 1) +
+ if ((tlsmodlist = calloc((sizeof (TLS_modinfo *) * (tlsmodcnt + 1)) +
(sizeof (TLS_modinfo) * tlsmodcnt), 1)) == 0)
return (0);
tlsbuflist = (TLS_modinfo *)((uintptr_t)tlsmodlist +
- ((tlsmodcnt + 1) * sizeof (TLS_modinfo *)));
+ ((tlsmodcnt + 1) * sizeof (TLS_modinfo *)));
+
for (tlsmodndx = 0; tlsmodndx < tlsmodcnt; tlsmodndx++)
tlsmodlist[tlsmodndx] = &tlsbuflist[tlsmodndx];
@@ -281,7 +223,7 @@
* Account for the initial dtv ptr in the TLSSIZE calculation.
*/
tlsmodndx = 0;
- for (lmp = lml_main.lm_head; lmp; lmp = (Rt_map *)NEXT(lmp)) {
+ for (lmp = lml->lm_head; lmp; lmp = (Rt_map *)NEXT(lmp)) {
if ((FCT(lmp) != &elf_fct) ||
(PTTLS(lmp) == 0) || (PTTLS(lmp)->p_memsz == 0))
continue;
@@ -290,23 +232,23 @@
tlsmodlist[tlsmodndx]->tm_modname = PATHNAME(lmp);
tlsmodlist[tlsmodndx]->tm_modid = TLSMODID(lmp);
- tlsmodlist[tlsmodndx]->tm_tlsblock =
- (void *)(tlsphdr->p_vaddr);
- if (!(FLAGS(lmp) & FLG_RT_FIXED))
- tlsmodlist[tlsmodndx]->tm_tlsblock =
- (void *)((uintptr_t)tlsmodlist[
- tlsmodndx]->tm_tlsblock + ADDR(lmp));
+ tlsmodlist[tlsmodndx]->tm_tlsblock = (void *)(tlsphdr->p_vaddr);
+
+ if (!(FLAGS(lmp) & FLG_RT_FIXED)) {
+ tlsmodlist[tlsmodndx]->tm_tlsblock = (void *)
+ ((uintptr_t)tlsmodlist[tlsmodndx]->tm_tlsblock +
+ ADDR(lmp));
+ }
tlsmodlist[tlsmodndx]->tm_filesz = tlsphdr->p_filesz;
tlsmodlist[tlsmodndx]->tm_memsz = tlsphdr->p_memsz;
tlsmodlist[tlsmodndx]->tm_flags = TM_FLG_STATICTLS;
- tlsmodlist[tlsmodndx]->tm_stattlsoffset =
- TLSSTATOFF(lmp);
+ tlsmodlist[tlsmodndx]->tm_stattlsoffset = TLSSTATOFF(lmp);
tlsmodndx++;
}
DBG_CALL(Dbg_tls_static_block(&lml_main, (void *)tlsmodlist,
tls_static_size));
- fptr_tls_statmods(tlsmodlist, tls_static_size);
+ (*fptr)(tlsmodlist, tls_static_size);
/*
* We're done with the list - clean it up.
--- a/usr/src/cmd/sgs/rtld/common/util.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/common/util.c Tue Apr 18 08:51:16 2006 -0700
@@ -50,6 +50,7 @@
#include <conv.h>
#include "_rtld.h"
#include "_audit.h"
+#include "_elf.h"
#include "msg.h"
static int ld_flags_env(const char *, Word *, Word *, uint_t, int);
@@ -137,7 +138,7 @@
void
rd_event(Lm_list *lml, rd_event_e event, r_state_e state)
{
- void (*fptr)();
+ void (*fptr)(Lm_list *);
switch (event) {
case RD_PREINIT:
@@ -594,7 +595,7 @@
* Call the .*array[] entries
*/
for (ndx = start; ndx != stop; ndx += incr) {
- void (* fptr)() = (void(*)())array[ndx];
+ void (*fptr)(void) = (void(*)())array[ndx];
DBG_CALL(Dbg_util_call_array(lmp, (void *)fptr, ndx, shtype));
@@ -627,21 +628,6 @@
}
/*
- * If a 'thread initialization' is pending - call it now before any
- * .init code is fired. Also clear the thrinit() to mark it as done.
- * Note, this is called for each link-map list, which is what libc
- * expects.
- */
- if (thrinit) {
- void (*_thrinit)() = thrinit;
-
- thrinit = 0;
- leave((Lm_list *)0);
- _thrinit();
- (void) enter();
- }
-
- /*
* Traverse the tobj array firing each objects init.
*/
for (_tobj = _nobj = tobj, _nobj++; *_tobj != NULL; _tobj++, _nobj++) {
@@ -763,7 +749,7 @@
*/
if ((rtld_flags & RT_FL_CONCUR) ||
(FLAGS(lmp) & FLG_RT_INITDONE)) {
- void (*fptr)() = FINI(lmp);
+ void (*fptr)(void) = FINI(lmp);
if (FINIARRAY(lmp) || fptr) {
/*
@@ -880,6 +866,11 @@
* Traverse any alternative link-map lists.
*/
for (LIST_TRAVERSE(&dynlm_list, lnp, lml)) {
+ /*
+ * Ignore the base-link-map list, which has already been
+ * processed, and the runtime linkers link-map list, which is
+ * typically processed last.
+ */
if (lml->lm_flags & (LML_FLG_BASELM | LML_FLG_RTLDLM))
continue;
@@ -920,9 +911,10 @@
* and from any internal dl*() requests.
*/
void
-load_completion(Rt_map * nlmp, Rt_map * clmp)
+load_completion(Rt_map *nlmp, Rt_map *clmp)
{
Rt_map **tobj = 0;
+ Lm_list *nlml, *clml;
/*
* Establish any .init processing. Note, in a world of lazy loading,
@@ -932,26 +924,58 @@
* any tsorting starts from the nlmp (new link-maps) pointer and not
* necessarily from the link-map that may have satisfied the request.
*
- * Note, if the caller is an auditor, and the destination isn't, then
- * don't run any .inits. This scenario is typical of an auditor trying
- * to inspect another link-map for symbols. Allow this inspection
- * without running any code on the inspected link-map, as running this
- * code may reenter the auditor, who has not yet finished their own
+ * Note, the primary link-map has an initialization phase where dynamic
+ * .init firing is suppressed. This provides for a simple and clean
+ * handshake with the primary link-maps libc, which is important for
+ * establishing uberdata. In addition, auditors often obtain handles
+ * to primary link-map objects as the objects are loaded, so as to
+ * inspect the link-map for symbols. This inspection is allowed without
+ * running any code on the primary link-map, as running this code may
+ * reenter the auditor, who may not yet have finished its own
* initialization.
*/
- if (nlmp && ((clmp == 0) ||
- ((LIST(clmp)->lm_flags & LML_FLG_NOAUDIT) == 0) ||
- (LIST(clmp) == LIST(nlmp)))) {
+ if (nlmp)
+ nlml = LIST(nlmp);
+ if (clmp)
+ clml = LIST(clmp);
+
+ if (nlmp && nlml->lm_init &&
+ ((nlml != &lml_main) || (rtld_flags2 & RT_FL2_PLMSETUP))) {
if ((tobj = tsort(nlmp, LIST(nlmp)->lm_init,
RT_SORT_REV)) == (Rt_map **)S_ERROR)
tobj = 0;
}
/*
+ * Make sure any alternative link-map retrieves any external interfaces
+ * and initializes threads.
+ */
+ if (nlmp && (nlml != &lml_main)) {
+ (void) rt_get_extern(nlml, nlmp);
+ rt_thr_init(nlml);
+ }
+
+ /*
+ * Traverse the list of new link-maps and register any dynamic TLS.
+ * This storage is established for any objects not on the primary
+ * link-map, and for any objects added to the primary link-map after
+ * static TLS has been registered.
+ */
+ if (nlmp && nlml->lm_tls &&
+ ((nlml != &lml_main) || (rtld_flags2 & RT_FL2_PLMSETUP))) {
+ Rt_map *lmp;
+
+ for (lmp = nlmp; lmp; lmp = (Rt_map *)NEXT(lmp)) {
+ if (PTTLS(lmp) && PTTLS(lmp)->p_memsz)
+ tls_modaddrem(lmp, TM_FLG_MODADD);
+ }
+ nlml->lm_tls = 0;
+ }
+
+ /*
* Indicate the link-map list is consistent.
*/
- if (clmp &&
- ((LIST(clmp)->lm_tflags | FLAGS1(clmp)) & LML_TFLG_AUD_ACTIVITY))
+ if (clmp && ((clml->lm_tflags | FLAGS1(clmp)) & LML_TFLG_AUD_ACTIVITY))
audit_activity(clmp, LA_ACT_CONSISTENT);
/*
@@ -1255,7 +1279,6 @@
* Indicate each new link-map has been moved to the previous link-map
* control list.
*/
-
for (lmp = nlmc->lc_head; lmp; lmp = (Rt_map *)NEXT(lmp))
CNTL(lmp) = plmco;
@@ -1446,9 +1469,9 @@
Word *lmtflags, uint_t env_flags, int aout)
{
u_longlong_t variable = 0;
- unsigned short select = 0;
- const char **str;
- Word val = 0;
+ ushort_t select = 0;
+ const char **str;
+ Word val = 0;
/*
* Determine whether we're dealing with a replaceable or permanent
@@ -2160,7 +2183,7 @@
int aout)
{
const char *s2;
- static size_t loc = 0;
+ static size_t loc = 0;
if (*s1++ != 'L')
return;
@@ -2175,14 +2198,14 @@
if (strncmp(s2, MSG_ORIG(MSG_LC_ALL), MSG_LC_ALL_SIZE) == 0) {
s2 += MSG_LC_ALL_SIZE;
if ((*s2 != '\0') && (loc < LOC_ALL)) {
- locale = s2;
+ glcs[CI_LCMESSAGES].lc_un.lc_ptr = (char *)s2;
loc = LOC_ALL;
}
} else if (strncmp(s2, MSG_ORIG(MSG_LC_MESSAGES),
MSG_LC_MESSAGES_SIZE) == 0) {
s2 += MSG_LC_MESSAGES_SIZE;
if ((*s2 != '\0') && (loc < LOC_MESG)) {
- locale = s2;
+ glcs[CI_LCMESSAGES].lc_un.lc_ptr = (char *)s2;
loc = LOC_MESG;
}
}
@@ -2192,7 +2215,7 @@
s2 = s1;
if ((*s2++ == 'A') && (*s2++ == 'N') && (*s2++ == 'G') &&
(*s2++ == '=') && (*s2 != '\0') && (loc < LOC_LANG)) {
- locale = s2;
+ glcs[CI_LCMESSAGES].lc_un.lc_ptr = (char *)s2;
loc = LOC_LANG;
return;
}
@@ -2242,6 +2265,8 @@
int
readenv_user(const char ** envp, Word *lmflags, Word *lmtflags, int aout)
{
+ char *locale;
+
if (envp == (const char **)0)
return (0);
@@ -2277,12 +2302,12 @@
* Duplicate the string so that new locale setting can generically
* cleanup any previous locales.
*/
- if (locale) {
+ if ((locale = glcs[CI_LCMESSAGES].lc_un.lc_ptr) != 0) {
if (((*locale == 'C') && (*(locale + 1) == '\0')) ||
(strcmp(locale, MSG_ORIG(MSG_TKN_POSIX)) == 0))
- locale = 0;
+ glcs[CI_LCMESSAGES].lc_un.lc_ptr = 0;
else
- locale = strdup(locale);
+ glcs[CI_LCMESSAGES].lc_un.lc_ptr = strdup(locale);
}
return (0);
}
@@ -2377,16 +2402,15 @@
#define FLG_UT_DOTSEEN 0x0008 /* dot appeared in format spec */
/*
- * This macro is for use from within doprf only. it's to be used
- * for checking the output buffer size and placing characters into
- * the buffer.
+ * This macro is for use from within doprf only. It is to be used for checking
+ * the output buffer size and placing characters into the buffer.
*/
#define PUTC(c) \
{ \
- register char tmpc; \
+ char tmpc; \
\
tmpc = (c); \
- if ((bufsiz) && ((bp + 1) >= bufend)) { \
+ if (bufsiz && (bp >= bufend)) { \
prf->pr_cur = bp; \
if (dowrite(prf) == 0) \
return (0); \
@@ -2594,6 +2618,7 @@
}
}
}
+
PUTC('\0');
prf->pr_cur = bp;
return (1);
--- a/usr/src/cmd/sgs/rtld/i386/Makefile Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/i386/Makefile Tue Apr 18 08:51:16 2006 -0700
@@ -32,8 +32,8 @@
# secondary lists (less frequently used code, ie. profiling support).
P_COMOBJS= debugdata.o \
- analyze.o elf.o globals.o malloc.o \
- mutex.o paths.o setup.o util.o \
+ analyze.o elf.o external.o globals.o \
+ malloc.o paths.o setup.o util.o \
dlfcns.o config_elf.o locale.o tsort.o \
getcwd.o remove.o move.o tls.o \
cap.o
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c Tue Apr 18 08:51:16 2006 -0700
@@ -972,7 +972,7 @@
}
mdb_printf(MSG_ORIG(MSG_LMLIST_LINE1), lml.lm_head, lml.lm_tail);
- mdb_printf(MSG_ORIG(MSG_LMLIST_LINE2), lml.lm_alp, lml.lm_peh_lmp);
+ mdb_printf(MSG_ORIG(MSG_LMLIST_LINE2), lml.lm_alp, lml.lm_rti);
mdb_printf(MSG_ORIG(MSG_LMLIST_LINE3), lml.lm_handle, lml.lm_obj,
lml.lm_init, lml.lm_lazy);
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg Tue Apr 18 08:51:16 2006 -0700
@@ -1,13 +1,9 @@
-#
-# Copyright 2005 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, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -22,6 +18,11 @@
#
# CDDL HEADER END
#
+
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
# pragma ident "%Z%%M% %I% %E% SMI"
#
@@ -344,13 +345,13 @@
@ MSG_LMLIST_LINE0 " lists: 0x%0?p Alist[used %u: total %u]\n"
@ MSG_LMC_LINE1 "Lm_cntl: 0x%p\n"
-@ MSG_LMC_LINE2 " head: 0x%0?p\t tail: 0x%0?p\n"
-@ MSG_LMC_LINE3 " flags: 0x%08x\t now: 0x%0?p\n"
+@ MSG_LMC_LINE2 " head: 0x%0?p\t tail: 0x%0?p\n"
+@ MSG_LMC_LINE3 " flags: 0x%08x\t now: 0x%0?p\n"
@ MSG_LMC_LINE4 " [ %#b ]\n"
-@ MSG_LMLIST_LINE1 " head: 0x%0?p\t tail: 0x%0?p\n"
-@ MSG_LMLIST_LINE2 " audit: 0x%0?p\t preexec: 0x%0?p\n"
-@ MSG_LMLIST_LINE3 " handle: 0x%0?p\t obj: %4d init: %4d \
+@ MSG_LMLIST_LINE1 " head: 0x%0?p\t tail: 0x%0?p\n"
+@ MSG_LMLIST_LINE2 " audit: 0x%0?p\t rtldinfo: 0x%0?p\n"
+@ MSG_LMLIST_LINE3 " handle: 0x%0?p\t obj: %4d init: %4d \
lazy: %4d\n"
@ MSG_LMLIST_LINE4 " flags: 0x%08x\n"
@ MSG_LMLIST_LINE5 " tflags: 0x%08x\n"
--- a/usr/src/cmd/sgs/rtld/sparc/Makefile Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/sparc/Makefile Tue Apr 18 08:51:16 2006 -0700
@@ -30,8 +30,8 @@
# secondary lists (less frequently used code, ie. a.out support).
P_COMOBJS= debugdata.o \
- analyze.o elf.o globals.o malloc.o \
- mutex.o paths.o setup.o util.o \
+ analyze.o elf.o external.o globals.o \
+ malloc.o paths.o setup.o util.o \
dlfcns.o config_elf.o locale.o tsort.o \
getcwd.o remove.o move.o tls.o \
cap.o
--- a/usr/src/cmd/sgs/rtld/sparcv9/Makefile Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/sparcv9/Makefile Tue Apr 18 08:51:16 2006 -0700
@@ -30,8 +30,8 @@
# secondary lists (less frequently used code, ie. a.out support).
P_COMOBJS= debugdata.o \
- analyze.o elf.o globals.o malloc.o \
- mutex.o paths.o setup.o util.o \
+ analyze.o elf.o external.o globals.o \
+ malloc.o paths.o setup.o util.o \
dlfcns.o config_elf.o locale.o tsort.o \
getcwd.o remove.o move.o tls.o \
cap.o
--- a/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c Tue Apr 18 07:10:32 2006 -0700
+++ b/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c Tue Apr 18 08:51:16 2006 -0700
@@ -328,60 +328,58 @@
/*
* Relocate the instructions given by the VAL64_TO_G1 macro above.
+ * The arguments parallel those of do_reloc().
*
* entry:
+ * off - Address of 1st instruction in sequence.
+ * value - Value being relocated (addend)
+ * sym - Name of value being relocated.
* lml - link map list
- * dyndata - Value being relocated (addend)
- * code_base - Address of 1st instruction in sequence.
*
* exit:
* Returns TRUE for success, FALSE for failure.
*/
static int
-reloc_val64_to_g1(Lm_list *lml, Addr *dyndata, Byte *code_base)
+reloc_val64_to_g1(Byte *off, Addr *value, const char *sym, Lm_list *lml)
{
- Xword symvalue;
+ Xword tmp_value;
/*
* relocating:
- * sethi %hh(dyndata), %g5
+ * sethi %hh(value), %g5
*/
- symvalue = (Xword)dyndata;
- if (do_reloc(R_SPARC_HH22, code_base,
- &symvalue, MSG_ORIG(MSG_SYM_LADYNDATA),
+ tmp_value = (Xword)value;
+ if (do_reloc(R_SPARC_HH22, off, &tmp_value, sym,
MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) {
return (0);
}
/*
* relocating:
- * or %g5, %hm(dyndata), %g5
+ * or %g5, %hm(value), %g5
*/
- symvalue = (Xword)dyndata;
- if (do_reloc(R_SPARC_HM10, code_base + 4,
- &symvalue, MSG_ORIG(MSG_SYM_LADYNDATA),
+ tmp_value = (Xword)value;
+ if (do_reloc(R_SPARC_HM10, off + 4, &tmp_value, sym,
MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) {
return (0);
}
/*
* relocating:
- * sethi %lm(dyndata), %g1
+ * sethi %lm(value), %g1
*/
- symvalue = (Xword)dyndata;
- if (do_reloc(R_SPARC_LM22, code_base + 12,
- &symvalue, MSG_ORIG(MSG_SYM_LADYNDATA),
+ tmp_value = (Xword)value;
+ if (do_reloc(R_SPARC_LM22, off + 12, &tmp_value, sym,
MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) {
return (0);
}
/*
* relocating:
- * or %g1, %lo(dyndata), %g1
+ * or %g1, %lo(value), %g1
*/
- symvalue = (Xword)dyndata;
- if (do_reloc(R_SPARC_LO10, code_base + 16,
- &symvalue, MSG_ORIG(MSG_SYM_LADYNDATA),
+ tmp_value = (Xword)value;
+ if (do_reloc(R_SPARC_LO10, off + 16, &tmp_value, sym,
MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) {
return (0);
}
@@ -434,10 +432,11 @@
* VAL64_TO_G1(dyndata)
* VAL64_TO_G1(&elf_plt_trace)
*/
- if (!(reloc_val64_to_g1(lml, dyndata,
- (Byte *) (dyn_plt + 0x14)) &&
- reloc_val64_to_g1(lml, (Addr *)&elf_plt_trace,
- (Byte *) (dyn_plt + 0x30)))) {
+ if (!(reloc_val64_to_g1((Byte *) (dyn_plt + 0x14), dyndata,
+ MSG_ORIG(MSG_SYM_LADYNDATA), lml) &&
+ reloc_val64_to_g1((Byte *) (dyn_plt + 0x30),
+ (Addr *)&elf_plt_trace,
+ MSG_ORIG(MSG_SYM_ELFPLTTRACE), lml))) {
*fail = 1;
return (0);
}