diff options
26 files changed, 425 insertions, 51 deletions
diff --git a/usr/src/cmd/sgs/include/debug.h b/usr/src/cmd/sgs/include/debug.h index 10a04df12a..ad97f73257 100644 --- a/usr/src/cmd/sgs/include/debug.h +++ b/usr/src/cmd/sgs/include/debug.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -265,6 +265,11 @@ extern void Dbg_help(void); #define Dbg_cap_sec_entry Dbg64_cap_sec_entry #define Dbg_cap_sec_title Dbg64_cap_sec_title +#define Dbg_cb_iphdr_enter Dbg64_cb_iphdr_enter +#define Dbg_cb_iphdr_callback Dbg64_cb_iphdr_callback +#define Dbg_cb_iphdr_mapchange Dbg64_cb_iphdr_mapchange +#define Dbg_cb_iphdr_unmap_ret Dbg64_cb_iphdr_unmap_ret + #define Dbg_ent_entry Dbg64_ent_entry #define Dbg_ent_print Dbg64_ent_print @@ -274,6 +279,7 @@ extern void Dbg_help(void); #define Dbg_file_ar_rescan Dbg64_file_ar_rescan #define Dbg_file_bind_entry Dbg64_file_bind_entry #define Dbg_file_bindings Dbg64_file_bindings +#define Dbg_file_bindings_done Dbg64_file_bindings_done #define Dbg_file_cleanup Dbg64_file_cleanup #define Dbg_file_cntl Dbg64_file_cntl #define Dbg_file_config_dis Dbg64_file_config_dis @@ -452,6 +458,7 @@ extern void Dbg_help(void); #define Dbg_ver_avail_title Dbg64_ver_avail_title #define Dbg_ver_def_title Dbg64_ver_def_title #define Dbg_ver_desc_entry Dbg64_ver_desc_entry +#define Dbg_ver_need_done Dbg64_ver_need_done #define Dbg_ver_need_entry Dbg64_ver_need_entry #define Dbg_ver_need_title Dbg64_ver_need_title #define Dbg_ver_nointerface Dbg64_ver_nointerface @@ -473,6 +480,11 @@ extern void Dbg_help(void); #define Dbg_cap_sec_entry Dbg32_cap_sec_entry #define Dbg_cap_sec_title Dbg32_cap_sec_title +#define Dbg_cb_iphdr_enter Dbg32_cb_iphdr_enter +#define Dbg_cb_iphdr_callback Dbg32_cb_iphdr_callback +#define Dbg_cb_iphdr_mapchange Dbg32_cb_iphdr_mapchange +#define Dbg_cb_iphdr_unmap_ret Dbg32_cb_iphdr_unmap_ret + #define Dbg_ent_entry Dbg32_ent_entry #define Dbg_ent_print Dbg32_ent_print @@ -482,6 +494,7 @@ extern void Dbg_help(void); #define Dbg_file_ar_rescan Dbg32_file_ar_rescan #define Dbg_file_bind_entry Dbg32_file_bind_entry #define Dbg_file_bindings Dbg32_file_bindings +#define Dbg_file_bindings_done Dbg32_file_bindings_done #define Dbg_file_cleanup Dbg32_file_cleanup #define Dbg_file_cntl Dbg32_file_cntl #define Dbg_file_config_dis Dbg32_file_config_dis @@ -661,6 +674,7 @@ extern void Dbg_help(void); #define Dbg_ver_avail_title Dbg32_ver_avail_title #define Dbg_ver_def_title Dbg32_ver_def_title #define Dbg_ver_desc_entry Dbg32_ver_desc_entry +#define Dbg_ver_need_done Dbg32_ver_need_done #define Dbg_ver_need_entry Dbg32_ver_need_entry #define Dbg_ver_need_title Dbg32_ver_need_title #define Dbg_ver_nointerface Dbg32_ver_nointerface @@ -711,6 +725,11 @@ extern void Dbg_cap_sec_entry(Lm_list *, uint_t, Xword, Xword, Half); extern void Dbg_cap_sec_title(Lm_list *, const char *); extern void Dbg_cap_val_hw1(Lm_list *, Xword, Half); +extern void Dbg_cb_iphdr_enter(Lm_list *, u_longlong_t, u_longlong_t); +extern void Dbg_cb_iphdr_callback(Lm_list *, struct dl_phdr_info *); +extern void Dbg_cb_iphdr_mapchange(Lm_list *, u_longlong_t, u_longlong_t); +extern void Dbg_cb_iphdr_unmap_ret(Lm_list *); + extern const char * Dbg_demangle_name(const char *); @@ -724,6 +743,7 @@ extern void Dbg_file_ar(Lm_list *, const char *, int); extern void Dbg_file_ar_rescan(Lm_list *, int, int); extern void Dbg_file_bind_entry(Lm_list *, Bnd_desc *); extern void Dbg_file_bindings(Rt_map *, int); +extern void Dbg_file_bindings_done(Lm_list *); extern void Dbg_file_cleanup(Lm_list *, const char *, Aliste); extern void Dbg_file_cntl(Lm_list *, Aliste, Aliste); extern void Dbg_file_config_dis(Lm_list *, const char *, int); @@ -932,6 +952,7 @@ extern void Dbg_ver_avail_entry(Lm_list *, Ver_index *, const char *); extern void Dbg_ver_avail_title(Lm_list *, const char *); extern void Dbg_ver_def_title(Lm_list *, const char *); extern void Dbg_ver_desc_entry(Lm_list *, Ver_desc *); +extern void Dbg_ver_need_done(Lm_list *); extern void Dbg_ver_need_entry(Lm_list *, Half, const char *, const char *); extern void Dbg_ver_need_title(Lm_list *, const char *); diff --git a/usr/src/cmd/sgs/libdl/common/llib-ldl b/usr/src/cmd/sgs/libdl/common/llib-ldl index 8676756795..66a16aa60d 100644 --- a/usr/src/cmd/sgs/libdl/common/llib-ldl +++ b/usr/src/cmd/sgs/libdl/common/llib-ldl @@ -22,13 +22,12 @@ /* PROTOLIB1 */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> +#include <link.h> #include <dlfcn.h> void * dlopen(const char *, int); @@ -41,3 +40,4 @@ int dladdr1(void *, Dl_info *, void **, int); int dldump(const char *, const char *, int); int dlinfo(void *, int, void *); void _ld_libc(void *); +int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), void *); diff --git a/usr/src/cmd/sgs/libdl/common/mapfile-vers b/usr/src/cmd/sgs/libdl/common/mapfile-vers index 2ce39b88ae..5a31ace772 100644 --- a/usr/src/cmd/sgs/libdl/common/mapfile-vers +++ b/usr/src/cmd/sgs/libdl/common/mapfile-vers @@ -20,7 +20,7 @@ # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -38,6 +38,18 @@ # MAPFILE HEADER END # +SUNW_1.6 { + global: + dl_iterate_phdr = FUNCTION; +} SUNW_1.5; + + +SUNW_1.5 { + global: + SUNW_1.5; +} SUNW_1.4; + + SUNW_1.4 { global: dladdr1 = FUNCTION; diff --git a/usr/src/cmd/sgs/liblddbg/Makefile.com b/usr/src/cmd/sgs/liblddbg/Makefile.com index 339d8b9537..8230266ee4 100644 --- a/usr/src/cmd/sgs/liblddbg/Makefile.com +++ b/usr/src/cmd/sgs/liblddbg/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -29,19 +29,19 @@ VERS = .4 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 \ - map32.o move32.o phdr32.o relocate32.o \ - sections32.o segments32.o shdr32.o statistics32.o \ - support32.o syms32.o unused32.o util32.o \ - version32.o - -COMOBJS64 = bindings64.o cap64.o dynamic64.o elf64.o \ - entry64.o files64.o got64.o libs64.o \ - map64.o move64.o phdr64.o relocate64.o \ - sections64.o segments64.o shdr64.o statistics64.o \ - support64.o syms64.o unused64.o util64.o \ - version64.o +COMOBJS32 = bindings32.o cap32.o callback32.o dynamic32.o \ + elf32.o entry32.o files32.o got32.o \ + libs32.o map32.o move32.o phdr32.o \ + relocate32.o sections32.o segments32.o shdr32.o \ + statistics32.o support32.o syms32.o unused32.o \ + util32.o version32.o + +COMOBJS64 = bindings64.o cap64.o callback64.o dynamic64.o \ + elf64.o entry64.o files64.o got64.o \ + libs64.o map64.o move64.o phdr64.o \ + relocate64.o sections64.o segments64.o shdr64.o \ + statistics64.o support64.o syms64.o unused64.o \ + util64.o version64.o BLTOBJ = msg.o diff --git a/usr/src/cmd/sgs/liblddbg/common/_debug.h b/usr/src/cmd/sgs/liblddbg/common/_debug.h index 294f0d08f0..0c6109eaac 100644 --- a/usr/src/cmd/sgs/liblddbg/common/_debug.h +++ b/usr/src/cmd/sgs/liblddbg/common/_debug.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -66,6 +66,7 @@ extern "C" { #define DBG_C_TLS 0x00100000 #define DBG_C_UNUSED 0x00200000 #define DBG_C_VERSIONS 0x00400000 +#define DBG_C_CALLBACK 0x00800000 #define DBG_C_ALL 0xffffffff @@ -100,6 +101,9 @@ typedef struct { */ #if defined(_ELF64) +#define MSG_CB_IPHDR_ADDR MSG_CB_IPHDR_ADDR_64 +#define MSG_CB_IPHDR_PHDR MSG_CB_IPHDR_PHDR_64 + #define MSG_GOT_TITLE MSG_GOT_TITLE_64 #define MSG_GOT_ENTRY_RE MSG_GOT_ENTRY_RE_64 #define MSG_GOT_ENTRY_NR MSG_GOT_ENTRY_NR_64 @@ -157,6 +161,9 @@ typedef struct { #else +#define MSG_CB_IPHDR_ADDR MSG_CB_IPHDR_ADDR_32 +#define MSG_CB_IPHDR_PHDR MSG_CB_IPHDR_PHDR_32 + #define MSG_GOT_TITLE MSG_GOT_TITLE_32 #define MSG_GOT_ENTRY_RE MSG_GOT_ENTRY_RE_32 #define MSG_GOT_ENTRY_NR MSG_GOT_ENTRY_NR_32 diff --git a/usr/src/cmd/sgs/liblddbg/common/debug.c b/usr/src/cmd/sgs/liblddbg/common/debug.c index 372a79a26a..d870cf353d 100644 --- a/usr/src/cmd/sgs/liblddbg/common/debug.c +++ b/usr/src/cmd/sgs/liblddbg/common/debug.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -92,6 +92,7 @@ static DBG_options _Dbg_options_ld[] = { /* ld only options */ static DBG_options _Dbg_options_rtld[] = { /* ld.so.1 only options */ {MSG_ORIG(MSG_TOK_AUDIT), DBG_C_AUDITING, 0}, {MSG_ORIG(MSG_TOK_BINDINGS), DBG_C_BINDINGS, 0}, + {MSG_ORIG(MSG_TOK_CALLBACK), DBG_C_CALLBACK, 0}, {MSG_ORIG(MSG_TOK_INIT), DBG_C_INIT, 0}, {NULL, 0, 0}, }; @@ -260,6 +261,8 @@ Dbg_help(void) dbg_print(0, MSG_INTL(MSG_USE_R8_B)); dbg_print(0, MSG_INTL(MSG_USE_R8_B2)); dbg_print(0, MSG_INTL(MSG_USE_R8_C)); + dbg_print(0, MSG_INTL(MSG_USE_R8_C2)); + dbg_print(0, MSG_INTL(MSG_USE_R8_D)); Dbg_util_nl(0, DBG_NL_FRC); dbg_print(0, MSG_INTL(MSG_USE_HDR_LD)); diff --git a/usr/src/cmd/sgs/liblddbg/common/files.c b/usr/src/cmd/sgs/liblddbg/common/files.c index e529e2f0f6..f168234772 100644 --- a/usr/src/cmd/sgs/liblddbg/common/files.c +++ b/usr/src/cmd/sgs/liblddbg/common/files.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -380,6 +380,17 @@ Dbg_file_bindings(Rt_map *lmp, int flag) } void +Dbg_file_bindings_done(Lm_list *lml) +{ + if (DBG_NOTCLASS(DBG_C_INIT)) + return; + if (DBG_NOTDETAIL()) + return; + + DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD)); +} + +void Dbg_file_dlopen(Rt_map *clmp, const char *name, int *in_nfavl, int mode) { Conv_dl_mode_buf_t dl_mode_buf; diff --git a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg index 0add04165c..31b15f134b 100644 --- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg +++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg @@ -20,7 +20,7 @@ # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -465,6 +465,8 @@ # audit runtime link-audit processing # bindings symbol binding; detail flag shows # absolute:relative addresses +# callback user supplied code executed by ld.so.1 +# (i.e. dl_iterate_phdr) # init init and fini processing @@ -480,7 +482,11 @@ @ MSG_USE_R8_B2 " absolute:relative addresses" # TRANSLATION_NOTE -- do not translate the first token "init". -@ MSG_USE_R8_C " init init and fini processing" +@ MSG_USE_R8_C " callback user supplied code executed by ld.so.1" +@ MSG_USE_R8_C2 " (i.e. dl_iterate_phdr)" + +# TRANSLATION_NOTE -- do not translate the first token "init". +@ MSG_USE_R8_D " init init and fini processing" # TRANSLATION_NOTE - End of reference 8 @@ -1376,6 +1382,21 @@ @ MSG_REL_LDLV_TITLE_64 " type \ offset value section / symbol" +# Callback messages + +@ MSG_CB_IPHDR_ENTER "dl_iterate_phdr enter:" +@ MSG_CB_IPHDR_MAPCNG "dl_iterate_phdr object map/unmap in callback:" +@ MSG_CB_IPHDR_UNMAP "dl_iterate_phdr early return due to object unmap" +@ MSG_CB_IPHDR_CALLBACK "dl_iterate_phdr callback:" +@ MSG_CB_IPHDR_NAME " dlpi_name: %s" +@ MSG_CB_IPHDR_MAPCNT " dlpi_adds: %-18llu dlpi_subs: %-18llu" + +@ MSG_CB_IPHDR_ADDR_32 " dlpi_addr: %#-10llx" +@ MSG_CB_IPHDR_PHDR_32 " dlpi_phdr: %#-10llx dlpi_phnum: %u" + +@ MSG_CB_IPHDR_ADDR_64 " dlpi_addr: %#-18llx" +@ MSG_CB_IPHDR_PHDR_64 " dlpi_phdr: %#-18llx dlpi_phnum: %u" + @ _END_ # Debug enabling tokens (for now these are untranslated) @@ -1383,6 +1404,7 @@ @ MSG_TOK_ALL "all" @ MSG_TOK_ARGS "args" @ MSG_TOK_BINDINGS "bindings" +@ MSG_TOK_CALLBACK "callback" @ MSG_TOK_CAP "cap" @ MSG_TOK_BASIC "basic" @ MSG_TOK_ENTRY "entry" diff --git a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg index 266039b4de..e5b44f8664 100644 --- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg +++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg @@ -22,7 +22,7 @@ /* PROTOLIB1 */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -86,6 +86,15 @@ void Dbg64_cap_sec_title(Lm_list *, const char *); void Dbg32_cap_val_hw1(Lm_list *, Elf32_Word, Elf32_Half); void Dbg64_cap_val_hw1(Lm_list *, Elf64_Xword, Elf64_Half); +void Dbg32_cb_iphdr_callback(Lm_list *, struct dl_phdr_info *); +void Dbg64_cb_iphdr_callback(Lm_list *, struct dl_phdr_info *); +void Dbg32_cb_iphdr_enter(Lm_list *, u_longlong_t, u_longlong_t); +void Dbg64_cb_iphdr_enter(Lm_list *, u_longlong_t, u_longlong_t); +void Dbg32_cb_iphdr_mapchange(Lm_list *, u_longlong_t, u_longlong_t); +void Dbg64_cb_iphdr_mapchange(Lm_list *, u_longlong_t, u_longlong_t); +void Dbg32_cb_iphdr_unmap_ret(Lm_list *); +void Dbg64_cb_iphdr_unmap_ret(Lm_list *); + void Dbg32_ent_print(Lm_list *, uchar_t, Elf32_Half, Alist *, Boolean); void Dbg64_ent_print(Lm_list *, uchar_t, Elf64_Half, Alist *, Boolean); @@ -101,6 +110,8 @@ void Dbg32_file_bind_entry(Lm_list *, Bnd_desc *); void Dbg64_file_bind_entry(Lm_list *, Bnd_desc *); void Dbg32_file_bindings(Rt_map *, int); void Dbg64_file_bindings(Rt_map *, int); +void Dbg32_file_bindings_done(Lm_list *); +void Dbg64_file_bindings_done(Lm_list *); void Dbg32_file_config_dis(Lm_list *, const char *, int); void Dbg64_file_config_dis(Lm_list *, const char *, int); void Dbg32_file_config_obj(Lm_list *, const char *, const char *, @@ -455,6 +466,8 @@ void Dbg64_unused_sec(Lm_list *, Is_desc *); void Dbg32_unused_unref(Rt_map *, const char *); void Dbg64_unused_unref(Rt_map *, const char *); +void Dbg32_ver_need_done(Lm_list *); +void Dbg64_ver_need_done(Lm_list *); void Dbg32_ver_need_entry(Lm_list *, Half, const char *, const char *); void Dbg64_ver_need_entry(Lm_list *, Half, const char *, const char *); void Dbg32_ver_need_title(Lm_list *, const char *); diff --git a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers index 2ae1071a2c..3aeb2262ce 100644 --- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers +++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers @@ -20,7 +20,7 @@ # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # @@ -41,7 +41,7 @@ # MAPFILE HEADER END # -SUNWprivate_4.74 { +SUNWprivate_4.75 { global: dbg_desc = NODIRECT; # interposed - ld.so.1(1) dbg_print = NODIRECT; # interposed - ld(1) and ld.so.1(1) @@ -94,6 +94,15 @@ SUNWprivate_4.74 { Dbg32_cap_val_hw1; Dbg64_cap_val_hw1; + Dbg32_cb_iphdr_callback; + Dbg64_cb_iphdr_callback; + Dbg32_cb_iphdr_enter; + Dbg64_cb_iphdr_enter; + Dbg32_cb_iphdr_mapchange; + Dbg64_cb_iphdr_mapchange; + Dbg32_cb_iphdr_unmap_ret; + Dbg64_cb_iphdr_unmap_ret; + Dbg32_demangle_name; Dbg64_demangle_name; @@ -112,6 +121,8 @@ SUNWprivate_4.74 { Dbg64_file_bind_entry; Dbg32_file_bindings; Dbg64_file_bindings; + Dbg32_file_bindings_done; + Dbg64_file_bindings_done; Dbg32_file_cntl; Dbg64_file_cntl; Dbg32_file_config_dis; @@ -456,6 +467,8 @@ SUNWprivate_4.74 { Dbg64_ver_def_title; Dbg32_ver_desc_entry; Dbg64_ver_desc_entry; + Dbg32_ver_need_done; + Dbg64_ver_need_done; Dbg32_ver_need_entry; Dbg64_ver_need_entry; Dbg32_ver_need_title; diff --git a/usr/src/cmd/sgs/liblddbg/common/version.c b/usr/src/cmd/sgs/liblddbg/common/version.c index 810fb3879e..830adc93cc 100644 --- a/usr/src/cmd/sgs/liblddbg/common/version.c +++ b/usr/src/cmd/sgs/liblddbg/common/version.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -219,3 +219,15 @@ Elf_ver_line_5(Lm_list *lml, const char *file, const char *version) else dbg_print(lml, MSG_INTL(MSG_VER_LLINE_5), file, version); } + +/* + * Called after final call to Dbg_ver_need() to inject final newline. + */ +void +Dbg_ver_need_done(Lm_list *lml) +{ + if (DBG_NOTCLASS(DBG_C_VERSIONS)) + return; + + Dbg_util_nl(lml, DBG_NL_STD); +} diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README index c3c0e2285f..aa1316a94a 100644 --- a/usr/src/cmd/sgs/packages/common/SUNWonld-README +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README @@ -1546,3 +1546,5 @@ Bugid Risk Synopsis 6903688 mdb(1) can't resolve certain symbols in solaris10-branded processes from the global zone 6923449 elfdump misinterprets _init/_fini symbols in dynamic section test +6914728 Add dl_iterate_phdr() function to ld.so.1 (D) + PSARC/2010/015 dl_iterate_phdr diff --git a/usr/src/cmd/sgs/rtld/common/_rtld.h b/usr/src/cmd/sgs/rtld/common/_rtld.h index 2dad943572..c34a91fe27 100644 --- a/usr/src/cmd/sgs/rtld/common/_rtld.h +++ b/usr/src/cmd/sgs/rtld/common/_rtld.h @@ -23,7 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef __RTLD_H @@ -535,8 +535,6 @@ extern Fct aout_fct; /* a.out (4.x) file class dependent */ /* data */ #endif -extern const char *locale; /* locale environment setting */ - extern Config *config; /* configuration structure */ extern const char *locale; /* locale environment setting */ @@ -592,6 +590,9 @@ extern ulong_t sfcap; /* software capabilities */ extern avl_tree_t *nfavl; /* not-found AVL path name tree */ +extern u_longlong_t cnt_map; /* Incr. for each object mapped */ +extern u_longlong_t cnt_unmap; /* Incr. for each object unmapped */ + /* * Function declarations. */ diff --git a/usr/src/cmd/sgs/rtld/common/analyze.c b/usr/src/cmd/sgs/rtld/common/analyze.c index a217513d29..9011846164 100644 --- a/usr/src/cmd/sgs/rtld/common/analyze.c +++ b/usr/src/cmd/sgs/rtld/common/analyze.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1626,6 +1626,7 @@ unmap_obj(mmapobj_result_t *mpp, uint_t mapnum) (void) munmap((void *)(uintptr_t)mpp[num].mr_addr, mpp[num].mr_msize); } + cnt_unmap++; } /* @@ -1718,6 +1719,7 @@ map_obj(Lm_list *lml, Fdesc *fdp, size_t fsize, const char *name, int fd, * mmapobj(). */ DBG_CALL(Dbg_file_mmapobj(lml, name, smpp, mapnum)); + cnt_map++; for (mnum = 0, mpp = smpp; mnum < mapnum; mnum++, mpp++) { uint_t flags = (mpp->mr_flags & MR_TYPE_MASK); diff --git a/usr/src/cmd/sgs/rtld/common/dlfcns.c b/usr/src/cmd/sgs/rtld/common/dlfcns.c index 7969cf4051..bdda9b63bc 100644 --- a/usr/src/cmd/sgs/rtld/common/dlfcns.c +++ b/usr/src/cmd/sgs/rtld/common/dlfcns.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1977,3 +1977,173 @@ dlinfo(void *handle, int request, void *p) leave(LIST(clmp), 0); return (error); } + + +/* + * GNU defined function to iterate through the program headers for all + * currently loaded dynamic objects. The caller supplies a callback function + * which is called for each object. + * + * entry: + * callback - Callback function to call. The arguments to the callback + * function are: + * info - Address of dl_phdr_info structure + * size - sizeof (struct dl_phdr_info) + * data - Caller supplied value. + * data - Value supplied by caller, which is passed to callback without + * examination. + * + * exit: + * callback is called for each dynamic ELF object in the process address + * space, halting when a non-zero value is returned, or when the last + * object has been processed. The return value from the last call + * to callback is returned. + * + * note: + * The Linux implementation has added additional fields to the + * dl_phdr_info structure over time. The callback function is + * supposed to use the size field to determine which fields are + * present, and to avoid attempts to access non-existent fields. + * We have added those fields that are compatible with Solaris, and + * which are used by GNU C++ (g++) runtime exception handling support. + * + * note: + * We issue a callback for every ELF object mapped into the process + * address space at the time this routine is entered. These callbacks + * are arbitrary functions that can do anything, including possibly + * causing new objects to be mapped into the process, or unmapped. + * This complicates matters: + * + * - Adding new objects can cause the alists to be reallocated + * or for contents to move. This can happen explicitly via + * dlopen(), or implicitly via lazy loading. One might consider + * simply banning dlopen from a callback, but lazy loading must + * be allowed, in which case there's no reason to ban dlopen(). + * + * - Removing objects can leave us holding references to freed + * memory that must not be accessed, and can cause the list + * items to move in a way that would cause us to miss reporting + * one, or double report others. + * + * - We cannot allocate memory to build a separate data structure, + * because the interface to dl_iterate_phdr() does not have a + * way to communicate allocation errors back to the caller. + * Even if we could, it would be difficult to do so efficiently. + * + * - It is possible for dl_iterate_phdr() to be called recursively + * from a callback, and there is no way for us to detect or manage + * this effectively, particularly as the user might use longjmp() + * to skip past us on return. Hence, we must be reentrant + * (stateless), further precluding the option of building a + * separate data structure. + * + * Despite these constraints, we are able to traverse the link-map + * lists safely: + * + * - Once interposer (preload) objects have been processed at + * startup, we know that new objects are always placed at the + * end of the list. Hence, if we are reading a list when that + * happens, the new object will not alter the part of the list + * that we've already processed. + * + * - The alist _TRAVERSE macros recalculate the address of the + * current item from scratch on each iteration, rather than + * incrementing a pointer. Hence, alist additions that occur + * in mid-traverse will not cause confusion. + * + * There is one limitation: We cannot continue operation if an object + * is removed from the process from within a callback. We detect when + * this happens and return immediately with a -1 return value. + * + * note: + * As currently implemented, if a callback causes an object to be loaded, + * that object may or may not be reported by the current invocation of + * dl_iterate_phdr(), based on whether or not we have already processed + * the link-map list that receives it. If we want to prevent this, it + * can be done efficiently by associating the current value of cnt_map + * with each new Rt_map entered into the system. Then this function can + * use that to detect and skip new objects that enter the system in + * mid-iteration. However, the Linux documentation is ambiguous on whether + * this is necessary, and it does not appear to matter in practice. + * We have therefore chosen not to do so at this time. + */ +int +dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), + void *data) +{ + struct dl_phdr_info info; + u_longlong_t l_cnt_map = cnt_map; + u_longlong_t l_cnt_unmap = cnt_unmap; + Lm_list *lml; + Lm_cntl *lmc; + Rt_map *lmp, *clmp; + Aliste idx1, idx2; + Ehdr *ehdr; + int ret = 0; + int entry; + + + entry = enter(0); + clmp = _caller(caller(), CL_EXECDEF); + DBG_CALL(Dbg_cb_iphdr_enter(LIST(clmp), cnt_map, cnt_unmap)); + + /* Issue a callback for each ELF object in the process */ + for (APLIST_TRAVERSE(dynlm_list, idx1, lml)) { + for (ALIST_TRAVERSE(lml->lm_lists, idx2, lmc)) { + for (lmp = lmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp)) { +#if defined(_sparc) && !defined(_LP64) + /* + * On 32-bit sparc, the possibility exists that + * this object is not ELF. + */ + if (THIS_IS_NOT_ELF(lmp)) + continue; +#endif + + /* Prepare the object information structure */ + ehdr = (Ehdr *) ADDR(lmp); + info.dlpi_addr = (ehdr->e_type == ET_EXEC) ? + 0 : ADDR(lmp); + info.dlpi_name = lmp->rt_pathname; + info.dlpi_phdr = (Phdr *) + (ADDR(lmp) + ehdr->e_phoff); + info.dlpi_phnum = ehdr->e_phnum; + info.dlpi_adds = cnt_map; + info.dlpi_subs = cnt_unmap; + + /* Issue the callback */ + DBG_CALL(Dbg_cb_iphdr_callback(LIST(clmp), + &info)); + leave(LIST(clmp), thr_flg_reenter); + ret = (* callback)(&info, sizeof (info), data); + (void) enter(thr_flg_reenter); + + /* Return immediately on non-zero result */ + if (ret != 0) + goto done; + + /* Adapt to object mapping changes */ + if ((cnt_map != l_cnt_map) || + (cnt_unmap != l_cnt_unmap)) { + DBG_CALL(Dbg_cb_iphdr_mapchange( + LIST(clmp), cnt_map, cnt_unmap)); + + /* Stop if an object was unmapped */ + if (cnt_unmap != l_cnt_unmap) { + ret = -1; + DBG_CALL(Dbg_cb_iphdr_unmap_ret( + LIST(clmp))); + goto done; + } + + l_cnt_map = cnt_map; + } + } + } + } + +done: + if (entry) + leave(LIST(clmp), 0); + return (ret); +} diff --git a/usr/src/cmd/sgs/rtld/common/elf.c b/usr/src/cmd/sgs/rtld/common/elf.c index d150ad4315..7cbf52eb3c 100644 --- a/usr/src/cmd/sgs/rtld/common/elf.c +++ b/usr/src/cmd/sgs/rtld/common/elf.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -610,7 +610,7 @@ elf_verify_vers(const char *name, Rt_map *clmp, Rt_map *nlmp) } } } - DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD)); + DBG_CALL(Dbg_ver_need_done(lml)); return (1); } diff --git a/usr/src/cmd/sgs/rtld/common/mapfile-vers b/usr/src/cmd/sgs/rtld/common/mapfile-vers index ed773380d6..9864da20d1 100644 --- a/usr/src/cmd/sgs/rtld/common/mapfile-vers +++ b/usr/src/cmd/sgs/rtld/common/mapfile-vers @@ -20,7 +20,7 @@ # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Generic interface definition for usr/src/cmd/sgs/rtld. @@ -109,6 +109,7 @@ SUNWprivate_1.3 { strtok_r; ___errno; qsort; + dl_iterate_phdr; local: *; }; diff --git a/usr/src/cmd/sgs/rtld/common/setup.c b/usr/src/cmd/sgs/rtld/common/setup.c index cecdf4f2c0..166fb30c22 100644 --- a/usr/src/cmd/sgs/rtld/common/setup.c +++ b/usr/src/cmd/sgs/rtld/common/setup.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -66,6 +66,17 @@ void *_nd = &_end; #endif /* + * Counters that are incremented every time an object is mapped/unmapped. + * + * Note that exec() will usually map 2 objects before we receive control, + * but this can be 1 if ld.so.1 is executed directly. We count one of these + * here, and add another as necessary in setup(). + */ +u_longlong_t cnt_map = 1; +u_longlong_t cnt_unmap = 0; + + +/* * Define for the executable's interpreter. * Usually it is ld.so.1, but for the first release of ICL binaries * it is libc.so.1. We keep this information so that we don't end @@ -271,6 +282,9 @@ setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz, rtldname = _rtldname; } else rtldname = (char *)MSG_INTL(MSG_STR_UNKNOWN); + + /* exec() brought in two objects for us. Count the second one */ + cnt_map++; } /* diff --git a/usr/src/cmd/sgs/rtld/common/tsort.c b/usr/src/cmd/sgs/rtld/common/tsort.c index 6464730ff1..94e5a7d4ee 100644 --- a/usr/src/cmd/sgs/rtld/common/tsort.c +++ b/usr/src/cmd/sgs/rtld/common/tsort.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -851,6 +851,6 @@ tsort(Rt_map *lmp, int num, int flag) * The caller is responsible for freeing the sorted link-map list once * the associated .init/.fini's have been fired. */ - DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD)); + DBG_CALL(Dbg_file_bindings_done(lml)); return (sort.s_lmpa); } diff --git a/usr/src/cmd/sgs/rtld/common/util.c b/usr/src/cmd/sgs/rtld/common/util.c index 32b871b9d1..ff4e461c45 100644 --- a/usr/src/cmd/sgs/rtld/common/util.c +++ b/usr/src/cmd/sgs/rtld/common/util.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2511,7 +2511,8 @@ again: if ((*format == 'l') || (*format == 'd') || (*format == 'D') || (*format == 'x') || (*format == 'X') || - (*format == 'o') || (*format == 'O')) + (*format == 'o') || (*format == 'O') || + (*format == 'u') || (*format == 'U')) goto again; break; case 'o': diff --git a/usr/src/head/link.h b/usr/src/head/link.h index 5948108b37..66bbf24d88 100644 --- a/usr/src/head/link.h +++ b/usr/src/head/link.h @@ -19,15 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _LINK_H #define _LINK_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/link.h> #ifndef _ASM @@ -267,9 +265,64 @@ extern uintptr_t la_symbind32(); #endif /* __STDC__ */ -#endif /* _ASM */ +/* + * The ElfW() macro is a GNU/Linux feature, provided as support for + * the dl_phdr_info structure used by dl_phdr_iterate(), which also + * originated under Linux. Given an ELF data type, without the ElfXX_ + * prefix, it supplies the appropriate prefix (Elf32_ or Elf64_) for + * the ELFCLASS of the code being compiled. + * + * Note that ElfW() is not suitable in situations in which the ELFCLASS + * of the code being compiled does not match that of the objects that + * code is intended to operate on (e.g. a 32-bit link-editor building + * a 64-bit object). The macros defined in <sys/machelf.h> are + * recommended in such cases. + */ +#ifdef _LP64 +#define ElfW(type) Elf64_ ## type +#else +#define ElfW(type) Elf32_ ## type +#endif + +/* + * The callback function to dl_interate_phdr() receives a pointer + * to a structure of this type. + * + * dlpi_addr is defined such that the address of any segment in + * the program header array can be calculated as: + * + * addr == info->dlpi_addr + info->dlpi_phdr[x].p_vaddr; + * + * It is therefore 0 for ET_EXEC objects, and the base address at + * which the object is mapped otherwise. + */ +struct dl_phdr_info { + ElfW(Addr) dlpi_addr; /* Base address of object */ + const char *dlpi_name; /* Null-terminated obj name */ + const ElfW(Phdr) *dlpi_phdr; /* Ptr to ELF program hdr arr */ + ElfW(Half) dlpi_phnum; /* # of items in dlpi_phdr[] */ + + /* + * Note: Following members were introduced after the first version + * of this structure was available. The dl_iterate_phdr() callback + * function is passed a 'size' argument giving the size of the info + * structure, and must compare that size to the offset of these fields + * before accessing them to ensure that they are present. + */ + + /* Incremented when a new object is mapped into the process */ + u_longlong_t dlpi_adds; + /* Incremented when an object is unmapped from the process */ + u_longlong_t dlpi_subs; +}; + +extern int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), + void *); + +#endif /* _ASM */ #endif /* _KERNEL */ + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/libc/amd64/mapfile-vers b/usr/src/lib/libc/amd64/mapfile-vers index 7c759736c1..f47b181b65 100644 --- a/usr/src/lib/libc/amd64/mapfile-vers +++ b/usr/src/lib/libc/amd64/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -37,6 +37,11 @@ # MAPFILE HEADER END # +SUNW_1.23 { + global: + dl_iterate_phdr = FUNCTION FILTER /usr/lib/amd64/ld.so.1; +}; + SUNW_1.22 { global: dladdr = FUNCTION FILTER /usr/lib/amd64/ld.so.1; diff --git a/usr/src/lib/libc/i386/mapfile-vers b/usr/src/lib/libc/i386/mapfile-vers index 3a722f9aef..1826aa7cf0 100644 --- a/usr/src/lib/libc/i386/mapfile-vers +++ b/usr/src/lib/libc/i386/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -38,6 +38,9 @@ # SUNW_1.23 { + global: + dl_iterate_phdr = FUNCTION FILTER /usr/lib/ld.so.1; + protected: aio_cancel64; aio_error64; diff --git a/usr/src/lib/libc/sparc/mapfile-vers b/usr/src/lib/libc/sparc/mapfile-vers index 8ab81fe11f..916e157908 100644 --- a/usr/src/lib/libc/sparc/mapfile-vers +++ b/usr/src/lib/libc/sparc/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -38,6 +38,9 @@ # SUNW_1.23 { + global: + dl_iterate_phdr = FUNCTION FILTER /usr/lib/ld.so.1; + protected: aio_cancel64; aio_error64; diff --git a/usr/src/lib/libc/sparcv9/mapfile-vers b/usr/src/lib/libc/sparcv9/mapfile-vers index 41be7234d1..7f5ff85af1 100644 --- a/usr/src/lib/libc/sparcv9/mapfile-vers +++ b/usr/src/lib/libc/sparcv9/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -37,6 +37,11 @@ # MAPFILE HEADER END # +SUNW_1.23 { + global: + dl_iterate_phdr = FUNCTION FILTER /usr/lib/sparcv9/ld.so.1; +}; + SUNW_1.22.1 { protected: # Note: The atomic_OP_WIDTH_nv symbols defined here are also defined diff --git a/usr/src/tools/scripts/nightly.sh b/usr/src/tools/scripts/nightly.sh index 051a5b2811..318109eacb 100644 --- a/usr/src/tools/scripts/nightly.sh +++ b/usr/src/tools/scripts/nightly.sh @@ -768,7 +768,7 @@ function build { echo "\n==== Build warnings ($LABEL) ====\n" >>$mail_msg_file egrep -i warning: $SRC/${INSTALLOG}.out \ | egrep -v '^tic:' \ - | egrep -v "symbol \`timezone' has differing types:" \ + | egrep -v "symbol (\`|')timezone' has differing types:" \ | egrep -v "parameter <PSTAMP> set to" \ | egrep -v "Ignoring unknown host" \ | egrep -v "redefining segment flags attribute for" \ @@ -804,7 +804,7 @@ function build { | egrep -v 'tsort: INFORM:' \ | egrep -v 'stripalign:' \ | egrep -v 'chars, width' \ - | egrep -v "symbol \`timezone' has differing types:" \ + | egrep -v "symbol (\`|')timezone' has differing types:" \ | egrep -v 'PSTAMP' \ | egrep -v '|%WHOANDWHERE%|' \ | egrep -v '^Manifying' \ |