diff options
Diffstat (limited to 'usr/src')
35 files changed, 917 insertions, 685 deletions
diff --git a/usr/src/cmd/sgs/include/debug.h b/usr/src/cmd/sgs/include/debug.h index 61306f0ab4..c880c1de0c 100644 --- a/usr/src/cmd/sgs/include/debug.h +++ b/usr/src/cmd/sgs/include/debug.h @@ -642,7 +642,7 @@ extern void Dbg_file_rejected(Lm_list *, Rej_desc *); extern void Dbg_file_reuse(Lm_list *, const char *, const char *); extern void Dbg_file_skip(Lm_list *, const char *, const char *); -extern void Dbg_got_display(Ofl_desc *, Gottable *); +extern void Dbg_got_display(Ofl_desc *, Off, int); extern void Dbg_libs_audit(Lm_list *, const char *, const char *); extern void Dbg_libs_find(Lm_list *, const char *); @@ -767,7 +767,8 @@ extern void Dbg_syms_updated(Ofl_desc *, Sym_desc *, const char *); extern void Dbg_syms_up_title(Lm_list *); extern void Dbg_tls_modactivity(Lm_list *, void *, uint_t); -extern void Dbg_tls_static_block(Lm_list *, void *, ulong_t); +extern void Dbg_tls_static_block(Lm_list *, void *, ulong_t, ulong_t); +extern void Dbg_tls_static_resv(Rt_map *, ulong_t, ulong_t); extern void Dbg_util_broadcast(Rt_map *); extern void Dbg_util_call_array(Rt_map *, void *, int, Word); diff --git a/usr/src/cmd/sgs/include/libld.h b/usr/src/cmd/sgs/include/libld.h index cd62a909c2..393b43588e 100644 --- a/usr/src/cmd/sgs/include/libld.h +++ b/usr/src/cmd/sgs/include/libld.h @@ -132,7 +132,6 @@ typedef struct { Gotndx gt_gndx; } Gottable; - /* * Output file processing structure */ @@ -274,6 +273,7 @@ struct ofl_desc { Xword ofl_hwcap_1; /* hardware capabilities */ Xword ofl_sfcap_1; /* software capabilities */ Lm_list *ofl_lml; /* runtime link-map list */ + Gottable *ofl_gottable; /* debugging got information */ }; #define FLG_OF_DYNAMIC 0x00000001 /* generate dynamic output module */ @@ -667,10 +667,9 @@ struct sym_desc { List sd_GOTndxs; /* list of associated GOT entries */ Sym *sd_sym; /* pointer to symbol table entry */ Sym *sd_osym; /* copy of the original symbol entry */ - /* Used only for local partial */ - Psym_info *sd_psyminfo; /* If this is partial symbol, this */ - /* field holds the pointer to */ - /* parsym_info */ + /* used only for local partial */ + Psym_info *sd_psyminfo; /* for partial symbols, maintain a */ + /* pointer to parsym_info */ const char *sd_name; /* symbols name */ Ifl_desc *sd_file; /* file where symbol is taken */ Is_desc *sd_isc; /* input section of symbol definition */ diff --git a/usr/src/cmd/sgs/include/rtld.h b/usr/src/cmd/sgs/include/rtld.h index 61c29a126c..4d03349d4f 100644 --- a/usr/src/cmd/sgs/include/rtld.h +++ b/usr/src/cmd/sgs/include/rtld.h @@ -680,6 +680,7 @@ typedef struct rt_map32 { #define MSK_RT_FILTER 0x0000f000 /* mask for all filter possibilites */ #define FL1_RT_TLSADD 0x00010000 /* objects TLS has been registered */ +#define FL1_RT_TLSSTAT 0x00020000 /* object requires static TLS */ /* * The following range of bits are reserved to hold LML_TFLG_AUD_ values diff --git a/usr/src/cmd/sgs/libld/common/_libld.h b/usr/src/cmd/sgs/libld/common/_libld.h index b2f9ce39d9..2f20d7d11a 100644 --- a/usr/src/cmd/sgs/libld/common/_libld.h +++ b/usr/src/cmd/sgs/libld/common/_libld.h @@ -228,7 +228,8 @@ extern Sdf_desc *sdf_find(const char *, List *); #define ld_allocate_got ld64_allocate_got #endif #define ld_assign_got ld64_assign_got -#define ld_assign_gotndx ld64_assign_gotndx +#define ld_assign_got_ndx ld64_assign_got_ndx +#define ld_assign_got_TLS ld64_assign_got_TLS #define ld_assign_plt_ndx ld64_assign_plt_ndx #define ld_calc_got_offset ld64_calc_got_offset #define ld_calc_plt_addr ld64_calc_plt_addr @@ -322,7 +323,8 @@ extern Sdf_desc *sdf_find(const char *, List *); #define ld_allocate_got ld32_allocate_got #endif #define ld_assign_got ld32_assign_got -#define ld_assign_gotndx ld32_assign_gotndx +#define ld_assign_got_ndx ld32_assign_got_ndx +#define ld_assign_got_TLS ld32_assign_got_TLS #define ld_assign_plt_ndx ld32_assign_plt_ndx #define ld_calc_got_offset ld32_calc_got_offset #define ld_calc_plt_addr ld32_calc_plt_addr @@ -419,8 +421,11 @@ extern Ar_desc *ld_ar_setup(const char *, Elf *, Ofl_desc *); extern uintptr_t ld_allocate_got(Ofl_desc *); #endif extern uintptr_t ld_assign_got(Ofl_desc *, Sym_desc *); -extern uintptr_t ld_assign_gotndx(List *, Gotndx *, Gotref, Ofl_desc *, +extern uintptr_t ld_assign_got_ndx(List *, Gotndx *, Gotref, Ofl_desc *, Rel_desc *, Sym_desc *); +extern uintptr_t ld_assign_got_TLS(Boolean, Rel_desc *, Ofl_desc *, + Sym_desc *, Gotndx *, Gotref, Word, Word, + Word, Word); extern void ld_assign_plt_ndx(Sym_desc *, Ofl_desc *); extern Xword ld_calc_got_offset(Rel_desc *, Ofl_desc *); diff --git a/usr/src/cmd/sgs/libld/common/libld.msg b/usr/src/cmd/sgs/libld/common/libld.msg index 82e7a176e3..0a0138e84b 100644 --- a/usr/src/cmd/sgs/libld/common/libld.msg +++ b/usr/src/cmd/sgs/libld/common/libld.msg @@ -223,7 +223,7 @@ relocation not currently supported" @ MSG_REL_PICREDLOC "relocation error: %s: file %s symbol %s: \ -z redlocsym may not be used for pic code" -@ MSG_REL_TLSIE "relocation error: %s: file %s: symbol %s: \ +@ MSG_REL_TLSLE "relocation error: %s: file %s: symbol %s: \ relocation illegal when building a shared object" @ MSG_REL_TLSBND "relocation error: %s: file %s: symbol %s: \ bound to: %s: relocation illegal when not bound \ @@ -280,6 +280,9 @@ relocation bound to a symbol with \ STV_PROTECTED visibility" +@ MSG_REL_TLSIE "relocation: %s: file %s: symbol %s: relocation \ + has restricted use when building a shared object" + # # TRANSLATION_NOTE # The following 7 messages are the message to print the diff --git a/usr/src/cmd/sgs/libld/common/machrel.amd.c b/usr/src/cmd/sgs/libld/common/machrel.amd.c index fbe91c1fd0..6124a26893 100644 --- a/usr/src/cmd/sgs/libld/common/machrel.amd.c +++ b/usr/src/cmd/sgs/libld/common/machrel.amd.c @@ -1220,6 +1220,7 @@ ld_reloc_GOTOP(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) * Stub routine for common code compatibility, we shouldn't * actually get here on amd64. */ + assert(0); return (S_ERROR); } @@ -1229,167 +1230,74 @@ ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) Word rtype = rsp->rel_rtype; Sym_desc *sdp = rsp->rel_sym; Word flags = ofl->ofl_flags; - Word rflags; Gotndx *gnp; /* - * all TLS relocations are illegal in a static executable. + * If we're building an executable - use either the IE or LE access + * model. If we're building a shared object process any IE model. */ - if ((ofl->ofl_flags & (FLG_OF_STATIC | FLG_OF_EXEC)) == - (FLG_OF_STATIC | FLG_OF_EXEC)) { - eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSSTAT), - conv_reloc_amd64_type(rsp->rel_rtype, 0), - rsp->rel_isdesc->is_file->ifl_name, - demangle(rsp->rel_sname)); - return (S_ERROR); - } - - /* - * Any TLS relocation must be against a STT_TLS symbol, all others - * are illegal. - */ - if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_TLS) { - Ifl_desc *ifl = rsp->rel_isdesc->is_file; - - eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSBADSYM), - conv_reloc_amd64_type(rsp->rel_rtype, 0), - ifl->ifl_name, demangle(rsp->rel_sname), - conv_sym_info_type(ifl->ifl_ehdr->e_machine, - ELF_ST_TYPE(sdp->sd_sym->st_info), 0)); - return (S_ERROR); - } - - /* - * We're a executable - use either the IE or LE - * access model. - */ - if (flags & FLG_OF_EXEC) { + if ((flags & FLG_OF_EXEC) || (IS_TLS_IE(rtype))) { /* - * If we are using either IE or LE reference - * model set the DF_STATIC_TLS flag. + * Set the DF_STATIC_TLS flag. */ ofl->ofl_dtflags |= DF_STATIC_TLS; - if (!local) { - Gotref gref; - /* - * IE access model - */ + if (!local || ((flags & FLG_OF_EXEC) == 0)) { /* - * It's not possible for LD or LE reference - * models to reference a symbol external to - * the current object. + * Assign a GOT entry for static TLS references. */ - if (IS_TLS_LD(rtype) || IS_TLS_LE(rtype)) { - eprintf(ofl->ofl_lml, ERR_FATAL, - MSG_INTL(MSG_REL_TLSBND), - conv_reloc_amd64_type(rsp->rel_rtype, 0), - rsp->rel_isdesc->is_file->ifl_name, - demangle(rsp->rel_sname), - sdp->sd_file->ifl_name); - return (S_ERROR); - } + if ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), + GOT_REF_TLSIE, ofl, rsp)) == 0) { - gref = GOT_REF_TLSIE; + if (ld_assign_got_TLS(local, rsp, ofl, sdp, + gnp, GOT_REF_TLSIE, FLG_REL_STLS, + rtype, R_AMD64_TPOFF64, 0) == S_ERROR) + return (S_ERROR); + } /* - * Assign a GOT entry for static TLS references + * IE access model. */ - if ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), - gref, ofl, rsp)) == 0) { - if (ld_assign_gotndx(&(sdp->sd_GOTndxs), - gnp, gref, ofl, rsp, sdp) == S_ERROR) - return (S_ERROR); - rsp->rel_rtype = R_AMD64_TPOFF64; - if (ld_add_outrel((FLG_REL_GOT | FLG_REL_STLS), - rsp, ofl) == S_ERROR) - return (S_ERROR); - rsp->rel_rtype = rtype; - } if (IS_TLS_IE(rtype)) return (ld_add_actrel(FLG_REL_STLS, rsp, ofl)); /* - * If (GD or LD) reference models - fixups - * are required. + * Fixups are required for other executable models. */ return (ld_add_actrel((FLG_REL_TLSFIX | FLG_REL_STLS), rsp, ofl)); } + /* - * LE access model + * LE access model. */ if (IS_TLS_LE(rtype)) return (ld_add_actrel(FLG_REL_STLS, rsp, ofl)); + return (ld_add_actrel((FLG_REL_TLSFIX | FLG_REL_STLS), rsp, ofl)); } /* - * Building a shared object - */ - - /* - * Building a shared object - only GD & LD access models - * will work here. - */ - if (IS_TLS_IE(rtype) || IS_TLS_LE(rtype)) { - eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSIE), - conv_reloc_amd64_type(rsp->rel_rtype, 0), - rsp->rel_isdesc->is_file->ifl_name, - demangle(rsp->rel_sname)); - return (S_ERROR); - } - - /* - * LD access mode can only bind to local symbols. + * Building a shared object. + * + * Assign a GOT entry for a dynamic TLS reference. */ - if (!local && IS_TLS_LD(rtype)) { - eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSBND), - conv_reloc_amd64_type(rsp->rel_rtype, 0), - rsp->rel_isdesc->is_file->ifl_name, - demangle(rsp->rel_sname), - sdp->sd_file->ifl_name); - return (S_ERROR); - } - - if (IS_TLS_LD(rtype) && ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), GOT_REF_TLSLD, ofl, rsp)) == 0)) { - if (ld_assign_gotndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_TLSLD, - ofl, rsp, sdp) == S_ERROR) - return (S_ERROR); - rflags = FLG_REL_GOT | FLG_REL_MTLS; - if (local) - rflags |= FLG_REL_SCNNDX; - rsp->rel_rtype = R_AMD64_DTPMOD64; - if (ld_add_outrel(rflags, rsp, ofl) == S_ERROR) + + if (ld_assign_got_TLS(local, rsp, ofl, sdp, gnp, GOT_REF_TLSLD, + FLG_REL_MTLS, rtype, R_AMD64_DTPMOD64, 0) == S_ERROR) return (S_ERROR); - rsp->rel_rtype = rtype; + } else if (IS_TLS_GD(rtype) && - ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), GOT_REF_TLSGD, ofl, - rsp)) == 0)) { - if (ld_assign_gotndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_TLSGD, - ofl, rsp, sdp) == S_ERROR) - return (S_ERROR); - rflags = FLG_REL_GOT | FLG_REL_DTLS; - if (local) - rflags |= FLG_REL_SCNNDX; - rsp->rel_rtype = R_AMD64_DTPMOD64; - if (ld_add_outrel(rflags, rsp, ofl) == S_ERROR) + ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), GOT_REF_TLSGD, + ofl, rsp)) == 0)) { + + if (ld_assign_got_TLS(local, rsp, ofl, sdp, gnp, GOT_REF_TLSGD, + FLG_REL_DTLS, rtype, R_AMD64_DTPMOD64, + R_AMD64_DTPOFF64) == S_ERROR) return (S_ERROR); - if (local == TRUE) { - rsp->rel_rtype = R_AMD64_DTPOFF64; - if (ld_add_actrel((FLG_REL_GOT | FLG_REL_DTLS), rsp, - ofl) == S_ERROR) - return (S_ERROR); - } else { - rsp->rel_rtype = R_AMD64_DTPOFF64; - if (ld_add_outrel((FLG_REL_GOT | FLG_REL_DTLS), rsp, - ofl) == S_ERROR) - return (S_ERROR); - } - rsp->rel_rtype = rtype; } if (IS_TLS_LD(rtype)) @@ -1452,7 +1360,7 @@ ld_calc_got_offset(Rel_desc * rdesc, Ofl_desc * ofl) /* ARGSUSED5 */ uintptr_t -ld_assign_gotndx(List * lst, Gotndx * pgnp, Gotref gref, Ofl_desc * ofl, +ld_assign_got_ndx(List * lst, Gotndx * pgnp, Gotref gref, Ofl_desc * ofl, Rel_desc * rsp, Sym_desc * sdp) { Xword raddend; @@ -1536,18 +1444,19 @@ static uchar_t plt0_template[M_PLT_ENTSIZE] = { * Initializes .got[0] with the _DYNAMIC symbol value. */ uintptr_t -ld_fillin_gotplt(Ofl_desc * ofl) +ld_fillin_gotplt(Ofl_desc *ofl) { Word flags = ofl->ofl_flags; Word dtflags1 = ofl->ofl_dtflags_1; if (ofl->ofl_osgot) { - Sym_desc * sdp; + Sym_desc *sdp; if ((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_DYNAMIC_U), SYM_NOHASH, 0, ofl)) != NULL) { - uchar_t *genptr = - ((uchar_t *)ofl->ofl_osgot->os_outdata->d_buf + + uchar_t *genptr; + + genptr = ((uchar_t *)ofl->ofl_osgot->os_outdata->d_buf + (M_GOT_XDYNAMIC * M_GOT_ENTSIZE)); /* LINTED */ *(Xword *)genptr = sdp->sd_sym->st_value; @@ -1565,8 +1474,8 @@ ld_fillin_gotplt(Ofl_desc * ofl) * 0x0f NOP */ if ((flags & FLG_OF_DYNAMIC) && ofl->ofl_osplt) { - uchar_t *pltent; - Xword val1; + uchar_t *pltent; + Xword val1; pltent = (uchar_t *)ofl->ofl_osplt->os_outdata->d_buf; bcopy(plt0_template, pltent, sizeof (plt0_template)); diff --git a/usr/src/cmd/sgs/libld/common/machrel.intel.c b/usr/src/cmd/sgs/libld/common/machrel.intel.c index aff9338a18..ca5a84a5be 100644 --- a/usr/src/cmd/sgs/libld/common/machrel.intel.c +++ b/usr/src/cmd/sgs/libld/common/machrel.intel.c @@ -70,7 +70,7 @@ ld_mach_make_dynamic(Ofl_desc *ofl, size_t *cnt) } void -ld_mach_update_odynamic(Ofl_desc * ofl, Dyn ** dyn) +ld_mach_update_odynamic(Ofl_desc *ofl, Dyn **dyn) { if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && ofl->ofl_pltcnt) { (*dyn)->d_tag = DT_PLTGOT; @@ -1219,95 +1219,60 @@ ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) Word rtype = rsp->rel_rtype; Sym_desc *sdp = rsp->rel_sym; Word flags = ofl->ofl_flags; - Word rflags; Gotndx *gnp; /* - * all TLS relocations are illegal in a static executable. + * If we're building an executable - use either the IE or LE access + * model. If we're building a shared object process any IE model. */ - if ((ofl->ofl_flags & (FLG_OF_STATIC | FLG_OF_EXEC)) == - (FLG_OF_STATIC | FLG_OF_EXEC)) { - eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSSTAT), - conv_reloc_386_type(rsp->rel_rtype, 0), - rsp->rel_isdesc->is_file->ifl_name, - demangle(rsp->rel_sname)); - return (S_ERROR); - } - - /* - * Any TLS relocation must be against a STT_TLS symbol, all others - * are illegal. - */ - if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_TLS) { - Ifl_desc *ifl = rsp->rel_isdesc->is_file; - - eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSBADSYM), - conv_reloc_386_type(rsp->rel_rtype, 0), - ifl->ifl_name, demangle(rsp->rel_sname), - conv_sym_info_type(ifl->ifl_ehdr->e_machine, - ELF_ST_TYPE(sdp->sd_sym->st_info), 0)); - return (S_ERROR); - } - - /* - * We're a executable - use either the IE or LE - * access model. - */ - if (flags & FLG_OF_EXEC) { + if ((flags & FLG_OF_EXEC) || (IS_TLS_IE(rtype))) { /* - * If we are using either IE or LE reference - * model set the DF_STATIC_TLS flag. + * Set the DF_STATIC_TLS flag. */ ofl->ofl_dtflags |= DF_STATIC_TLS; - if (!local) { - Gotref gref; - /* - * IE access model - */ + if (!local || ((flags & FLG_OF_EXEC) == 0)) { /* - * It's not possible for LD or LE reference - * models to reference a symbol external to - * the current object. + * Assign a GOT entry for static TLS references. */ - if (IS_TLS_LD(rtype) || IS_TLS_LE(rtype)) { - eprintf(ofl->ofl_lml, ERR_FATAL, - MSG_INTL(MSG_REL_TLSBND), - conv_reloc_386_type(rsp->rel_rtype, 0), - rsp->rel_isdesc->is_file->ifl_name, - demangle(rsp->rel_sname), - sdp->sd_file->ifl_name); - return (S_ERROR); - } + if ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), + GOT_REF_TLSIE, ofl, 0)) == 0) { - gref = GOT_REF_TLSIE; + if (ld_assign_got_TLS(local, rsp, ofl, sdp, + gnp, GOT_REF_TLSIE, FLG_REL_STLS, + rtype, R_386_TLS_TPOFF, 0) == S_ERROR) + return (S_ERROR); + } /* - * Assign a GOT entry for static TLS references + * IE access model. */ - if ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), - gref, ofl, 0)) == 0) { - if (ld_assign_gotndx(&(sdp->sd_GOTndxs), - gnp, gref, ofl, rsp, sdp) == S_ERROR) - return (S_ERROR); - rsp->rel_rtype = R_386_TLS_TPOFF; - if (ld_add_outrel((FLG_REL_GOT | FLG_REL_STLS), + if (IS_TLS_IE(rtype)) { + if (ld_add_actrel(FLG_REL_STLS, rsp, ofl) == S_ERROR) return (S_ERROR); - rsp->rel_rtype = rtype; + + /* + * A non-pic shared object needs to adjust the + * active relocation (indntpoff). + */ + if (((flags & FLG_OF_EXEC) == 0) && + (rtype == R_386_TLS_IE)) { + rsp->rel_rtype = R_386_RELATIVE; + return (ld_add_outrel(NULL, rsp, ofl)); + } + return (1); } - if (IS_TLS_IE(rtype)) - return (ld_add_actrel(FLG_REL_STLS, rsp, ofl)); /* - * If (GD or LD) reference models - fixups - * are required. + * Fixups are required for other executable models. */ return (ld_add_actrel((FLG_REL_TLSFIX | FLG_REL_STLS), rsp, ofl)); } + /* - * LE access model + * LE access model. */ if (IS_TLS_LE(rtype) || (rtype == R_386_TLS_LDO_32)) return (ld_add_actrel(FLG_REL_STLS, rsp, ofl)); @@ -1317,75 +1282,31 @@ ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) } /* - * Building a shared object - */ - - /* - * Building a shared object - only GD & LD access models - * will work here. - */ - if (IS_TLS_IE(rtype) || IS_TLS_LE(rtype)) { - eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSIE), - conv_reloc_386_type(rsp->rel_rtype, 0), - rsp->rel_isdesc->is_file->ifl_name, - demangle(rsp->rel_sname)); - return (S_ERROR); - } - - /* - * LD access mode can only bind to local symbols. + * Building a shared object. + * + * Assign a GOT entry for a dynamic TLS reference. */ - if (!local && IS_TLS_LD(rtype)) { - eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSBND), - conv_reloc_386_type(rsp->rel_rtype, 0), - rsp->rel_isdesc->is_file->ifl_name, - demangle(rsp->rel_sname), - sdp->sd_file->ifl_name); - return (S_ERROR); - } - - if (IS_TLS_LD(rtype) && ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), GOT_REF_TLSLD, ofl, 0)) == 0)) { - if (ld_assign_gotndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_TLSLD, - ofl, rsp, sdp) == S_ERROR) - return (S_ERROR); - rflags = FLG_REL_GOT | FLG_REL_MTLS; - if (local) - rflags |= FLG_REL_SCNNDX; - rsp->rel_rtype = R_386_TLS_DTPMOD32; - if (ld_add_outrel(rflags, rsp, ofl) == S_ERROR) + + if (ld_assign_got_TLS(local, rsp, ofl, sdp, gnp, GOT_REF_TLSLD, + FLG_REL_MTLS, rtype, R_386_TLS_DTPMOD32, 0) == S_ERROR) return (S_ERROR); - rsp->rel_rtype = rtype; + } else if (IS_TLS_GD(rtype) && ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), GOT_REF_TLSGD, ofl, 0)) == 0)) { - if (ld_assign_gotndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_TLSGD, - ofl, rsp, sdp) == S_ERROR) - return (S_ERROR); - rflags = FLG_REL_GOT | FLG_REL_DTLS; - if (local) - rflags |= FLG_REL_SCNNDX; - rsp->rel_rtype = R_386_TLS_DTPMOD32; - if (ld_add_outrel(rflags, rsp, ofl) == S_ERROR) + + if (ld_assign_got_TLS(local, rsp, ofl, sdp, gnp, GOT_REF_TLSGD, + FLG_REL_DTLS, rtype, R_386_TLS_DTPMOD32, + R_386_TLS_DTPOFF32) == S_ERROR) return (S_ERROR); - if (local == TRUE) { - rsp->rel_rtype = R_386_TLS_DTPOFF32; - if (ld_add_actrel((FLG_REL_GOT | FLG_REL_DTLS), rsp, - ofl) == S_ERROR) - return (S_ERROR); - } else { - rsp->rel_rtype = R_386_TLS_DTPOFF32; - if (ld_add_outrel((FLG_REL_GOT | FLG_REL_DTLS), rsp, - ofl) == S_ERROR) - return (S_ERROR); - } - rsp->rel_rtype = rtype; } + /* * For GD/LD TLS reference - TLS_{GD,LD}_CALL, this will eventually - * cause a call to __tls_get_addr(). Let's convert this - * relocation to that symbol now, and prepare for the PLT magic. + * cause a call to __tls_get_addr(). Convert this relocation to that + * symbol now, and prepare for the PLT magic. */ if ((rtype == R_386_TLS_GD_PLT) || (rtype == R_386_TLS_LDM_PLT)) { Sym_desc * tlsgetsym; @@ -1393,11 +1314,14 @@ ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) if ((tlsgetsym = ld_sym_add_u(MSG_ORIG(MSG_SYM_TLSGETADDR_UU), ofl)) == (Sym_desc *)S_ERROR) return (S_ERROR); + rsp->rel_sym = tlsgetsym; rsp->rel_sname = tlsgetsym->sd_name; rsp->rel_rtype = R_386_PLT32; + if (ld_reloc_plt(rsp, ofl) == S_ERROR) return (S_ERROR); + rsp->rel_sym = sdp; rsp->rel_sname = sdp->sd_name; rsp->rel_rtype = rtype; @@ -1460,7 +1384,7 @@ ld_calc_got_offset(Rel_desc * rdesc, Ofl_desc * ofl) /* ARGSUSED4 */ uintptr_t -ld_assign_gotndx(List * lst, Gotndx * pgnp, Gotref gref, Ofl_desc * ofl, +ld_assign_got_ndx(List * lst, Gotndx * pgnp, Gotref gref, Ofl_desc * ofl, Rel_desc * rsp, Sym_desc * sdp) { Gotndx *gnp; @@ -1504,15 +1428,18 @@ ld_assign_plt_ndx(Sym_desc * sdp, Ofl_desc *ofl) * Initializes .got[0] with the _DYNAMIC symbol value. */ uintptr_t -ld_fillin_gotplt(Ofl_desc * ofl) +ld_fillin_gotplt(Ofl_desc *ofl) { + Word flags = ofl->ofl_flags; + if (ofl->ofl_osgot) { - Sym_desc * sdp; + Sym_desc *sdp; if ((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_DYNAMIC_U), SYM_NOHASH, 0, ofl)) != NULL) { - uchar_t *genptr = ((uchar_t *) - ofl->ofl_osgot->os_outdata->d_buf + + uchar_t *genptr; + + genptr = ((uchar_t *)ofl->ofl_osgot->os_outdata->d_buf + (M_GOT_XDYNAMIC * M_GOT_ENTSIZE)); /* LINTED */ *(Word *)genptr = (Word)sdp->sd_sym->st_value; @@ -1530,11 +1457,11 @@ ld_fillin_gotplt(Ofl_desc * ofl) * JMP * got[2]@GOT(%ebx) # the address of rtbinder * } */ - if ((ofl->ofl_flags & FLG_OF_DYNAMIC) && ofl->ofl_osplt) { + if ((flags & FLG_OF_DYNAMIC) && ofl->ofl_osplt) { uchar_t *pltent; pltent = (uchar_t *)ofl->ofl_osplt->os_outdata->d_buf; - if (!(ofl->ofl_flags & FLG_OF_SHAROBJ)) { + if (!(flags & FLG_OF_SHAROBJ)) { pltent[0] = M_SPECIAL_INST; pltent[1] = M_PUSHL_DISP; pltent += 2; diff --git a/usr/src/cmd/sgs/libld/common/machrel.sparc.c b/usr/src/cmd/sgs/libld/common/machrel.sparc.c index a39ab3c7c5..c909aa5be0 100644 --- a/usr/src/cmd/sgs/libld/common/machrel.sparc.c +++ b/usr/src/cmd/sgs/libld/common/machrel.sparc.c @@ -123,7 +123,7 @@ ld_mach_make_dynamic(Ofl_desc *ofl, size_t *cnt) } void -ld_mach_update_odynamic(Ofl_desc * ofl, Dyn ** dyn) +ld_mach_update_odynamic(Ofl_desc *ofl, Dyn **dyn) { if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && ofl->ofl_pltcnt) { (*dyn)->d_tag = DT_PLTGOT; @@ -1621,53 +1621,21 @@ ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) Word rtype = rsp->rel_rtype; Sym_desc *sdp = rsp->rel_sym; Word flags = ofl->ofl_flags; - Word rflags; Gotndx *gnp; /* - * all TLS relocations are illegal in a static executable. + * If we're building an executable - use either the IE or LE access + * model. If we're building a shared object process any IE model. */ - if ((ofl->ofl_flags & (FLG_OF_STATIC | FLG_OF_EXEC)) == - (FLG_OF_STATIC | FLG_OF_EXEC)) { - eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSSTAT), - conv_reloc_SPARC_type(rsp->rel_rtype, 0), - rsp->rel_isdesc->is_file->ifl_name, - demangle(rsp->rel_sname)); - return (S_ERROR); - } - - /* - * Any TLS relocation must be against a STT_TLS symbol, all others - * are illegal. - */ - if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_TLS) { - Ifl_desc *ifl = rsp->rel_isdesc->is_file; - - eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSBADSYM), - conv_reloc_SPARC_type(rsp->rel_rtype, 0), - ifl->ifl_name, demangle(rsp->rel_sname), - conv_sym_info_type(ifl->ifl_ehdr->e_machine, - ELF_ST_TYPE(sdp->sd_sym->st_info), 0)); - return (S_ERROR); - } - - /* - * We're a executable - use either the IE or LE - * access model. - */ - if (flags & FLG_OF_EXEC) { + if ((flags & FLG_OF_EXEC) || (IS_TLS_IE(rtype))) { /* - * If we are using either IE or LE reference - * model set the DF_STATIC_TLS flag. + * Set the DF_STATIC_TLS flag. */ ofl->ofl_dtflags |= DF_STATIC_TLS; - if (!local) { + if (!local || ((flags & FLG_OF_EXEC) == 0)) { /* - * IE access model - */ - /* - * When building a executable - these relocations + * When processing static TLS - these relocations * can be ignored. */ if ((rtype == R_SPARC_TLS_IE_LD) || @@ -1676,22 +1644,7 @@ ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) return (1); /* - * It's not possible for LD or LE reference - * models to reference a symbol external to - * the current object. - */ - if (IS_TLS_LD(rtype) || IS_TLS_LE(rtype)) { - eprintf(ofl->ofl_lml, ERR_FATAL, - MSG_INTL(MSG_REL_TLSBND), - conv_reloc_SPARC_type(rsp->rel_rtype, 0), - rsp->rel_isdesc->is_file->ifl_name, - demangle(rsp->rel_sname), - sdp->sd_file->ifl_name); - return (S_ERROR); - } - - /* - * Assign a GOT entry for static TLS references + * Assign a GOT entry for IE static TLS references. */ if (((rtype == R_SPARC_TLS_GD_HI22) || (rtype == R_SPARC_TLS_GD_LO10) || @@ -1699,35 +1652,35 @@ ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) (rtype == R_SPARC_TLS_IE_LO10)) && ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), GOT_REF_TLSIE, ofl, rsp)) == 0)) { - if (ld_assign_gotndx(&(sdp->sd_GOTndxs), gnp, - GOT_REF_TLSIE, ofl, rsp, sdp) == S_ERROR) - return (S_ERROR); - rsp->rel_rtype = M_R_TPOFF; - if (ld_add_outrel((FLG_REL_GOT | FLG_REL_STLS), - rsp, ofl) == S_ERROR) + + if (ld_assign_got_TLS(local, rsp, ofl, sdp, + gnp, GOT_REF_TLSIE, FLG_REL_STLS, + rtype, M_R_TPOFF, 0) == S_ERROR) return (S_ERROR); - rsp->rel_rtype = rtype; } + /* + * IE access model. + */ if (IS_TLS_IE(rtype)) return (ld_add_actrel(FLG_REL_STLS, rsp, ofl)); /* - * If (GD) reference models - fixups - * are required. + * Fixups are required for other executable models. */ return (ld_add_actrel((FLG_REL_TLSFIX | FLG_REL_STLS), rsp, ofl)); } + /* - * LE access model + * LE access model. */ if (IS_TLS_LE(rtype)) return (ld_add_actrel(FLG_REL_STLS, rsp, ofl)); /* - * When building a executable - these relocations - * can be ignored. + * When processing static TLS - these relocations can be + * ignored. */ if (rtype == R_SPARC_TLS_IE_ADD) return (1); @@ -1737,36 +1690,9 @@ ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) } /* - * Building a shared object - */ - - /* - * Building a shared object - only GD & LD access models - * will work here. - */ - if (IS_TLS_IE(rtype) || IS_TLS_LE(rtype)) { - eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSIE), - conv_reloc_SPARC_type(rsp->rel_rtype, 0), - rsp->rel_isdesc->is_file->ifl_name, - demangle(rsp->rel_sname)); - return (S_ERROR); - } - - /* - * LD access mode can only bind to local symbols. - */ - if (!local && IS_TLS_LD(rtype)) { - eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSBND), - conv_reloc_SPARC_type(rsp->rel_rtype, 0), - rsp->rel_isdesc->is_file->ifl_name, - demangle(rsp->rel_sname), - sdp->sd_file->ifl_name); - return (S_ERROR); - } - - /* - * For dynamic TLS references - ADD relocations - * are ignored. + * Building a shared object. + * + * For dynamic TLS references, ADD relocations are ignored. */ if ((rtype == R_SPARC_TLS_GD_ADD) || (rtype == R_SPARC_TLS_LDM_ADD) || (rtype == R_SPARC_TLS_LDO_ADD)) @@ -1777,52 +1703,27 @@ ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) */ if (((rtype == R_SPARC_TLS_LDM_HI22) || (rtype == R_SPARC_TLS_LDM_LO10)) && - ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), - GOT_REF_TLSLD, ofl, rsp)) == 0)) { - if (ld_assign_gotndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_TLSLD, - ofl, rsp, sdp) == S_ERROR) - return (S_ERROR); - rsp->rel_rtype = M_R_DTPMOD; - rflags = FLG_REL_GOT | FLG_REL_MTLS; - if (local) - rflags |= FLG_REL_SCNNDX; + ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), GOT_REF_TLSLD, + ofl, rsp)) == 0)) { - if (ld_add_outrel(rflags, rsp, ofl) == S_ERROR) + if (ld_assign_got_TLS(local, rsp, ofl, sdp, gnp, GOT_REF_TLSLD, + FLG_REL_MTLS, rtype, M_R_DTPMOD, 0) == S_ERROR) return (S_ERROR); - rsp->rel_rtype = rtype; - - } else if (((rtype == R_SPARC_TLS_GD_HI22) || (rtype == - R_SPARC_TLS_GD_LO10)) && ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), - GOT_REF_TLSGD, ofl, rsp)) == 0)) { - if (ld_assign_gotndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_TLSGD, - ofl, rsp, sdp) == S_ERROR) - return (S_ERROR); - rsp->rel_rtype = M_R_DTPMOD; - rflags = FLG_REL_GOT | FLG_REL_DTLS; - if (local) - rflags |= FLG_REL_SCNNDX; + } else if (((rtype == R_SPARC_TLS_GD_HI22) || + (rtype == R_SPARC_TLS_GD_LO10)) && + ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), GOT_REF_TLSGD, + ofl, rsp)) == 0)) { - if (ld_add_outrel(rflags, rsp, ofl) == S_ERROR) + if (ld_assign_got_TLS(local, rsp, ofl, sdp, gnp, GOT_REF_TLSGD, + FLG_REL_DTLS, rtype, M_R_DTPMOD, M_R_DTPOFF) == S_ERROR) return (S_ERROR); - - if (local == TRUE) { - rsp->rel_rtype = M_R_DTPOFF; - if (ld_add_actrel((FLG_REL_GOT | FLG_REL_DTLS), rsp, - ofl) == S_ERROR) - return (S_ERROR); - } else { - rsp->rel_rtype = M_R_DTPOFF; - if (ld_add_outrel((FLG_REL_GOT | FLG_REL_DTLS), rsp, - ofl) == S_ERROR) - return (S_ERROR); - } - rsp->rel_rtype = rtype; } + /* * For GD/LD TLS reference - TLS_{GD,LD}_CALL, this will eventually - * cause a call to __tls_get_addr(). Let's convert this - * relocation to that symbol now, and prepare for the PLT magic. + * cause a call to __tls_get_addr(). Convert this relocation to that + * symbol now, and prepare for the PLT magic. */ if ((rtype == R_SPARC_TLS_GD_CALL) || (rtype == R_SPARC_TLS_LDM_CALL)) { Sym_desc * tlsgetsym; @@ -1830,11 +1731,14 @@ ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) if ((tlsgetsym = ld_sym_add_u(MSG_ORIG(MSG_SYM_TLSGETADDR_U), ofl)) == (Sym_desc *)S_ERROR) return (S_ERROR); + rsp->rel_sym = tlsgetsym; rsp->rel_sname = tlsgetsym->sd_name; rsp->rel_rtype = R_SPARC_WPLT30; + if (ld_reloc_plt(rsp, ofl) == S_ERROR) return (S_ERROR); + rsp->rel_sym = sdp; rsp->rel_sname = sdp->sd_name; rsp->rel_rtype = rtype; @@ -1947,7 +1851,7 @@ ld_calc_got_offset(Rel_desc * rdesc, Ofl_desc * ofl) } uintptr_t -ld_assign_gotndx(List * lst, Gotndx * pgnp, Gotref gref, Ofl_desc * ofl, +ld_assign_got_ndx(List * lst, Gotndx * pgnp, Gotref gref, Ofl_desc * ofl, Rel_desc * rsp, Sym_desc * sdp) { Xword raddend; @@ -2076,20 +1980,20 @@ ld_allocate_got(Ofl_desc * ofl) return (1); } - /* * Initializes .got[0] with the _DYNAMIC symbol value. */ uintptr_t -ld_fillin_gotplt(Ofl_desc * ofl) +ld_fillin_gotplt(Ofl_desc *ofl) { if (ofl->ofl_osgot) { - Sym_desc * sdp; + Sym_desc *sdp; if ((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_DYNAMIC_U), SYM_NOHASH, 0, ofl)) != NULL) { - uchar_t *genptr = ((uchar_t *) - ofl->ofl_osgot->os_outdata->d_buf + + uchar_t *genptr; + + genptr = ((uchar_t *)ofl->ofl_osgot->os_outdata->d_buf + (-neggotoffset * M_GOT_ENTSIZE) + (M_GOT_XDYNAMIC * M_GOT_ENTSIZE)); /* LINTED */ diff --git a/usr/src/cmd/sgs/libld/common/relocate.c b/usr/src/cmd/sgs/libld/common/relocate.c index 065058f993..9b197006b3 100644 --- a/usr/src/cmd/sgs/libld/common/relocate.c +++ b/usr/src/cmd/sgs/libld/common/relocate.c @@ -518,7 +518,7 @@ ld_reloc_GOT_relative(Boolean local, Rel_desc *rsp, Ofl_desc *ofl) ofl, rsp)) == 0) { Word rtype = rsp->rel_rtype; - if (ld_assign_gotndx(&(sdp->sd_GOTndxs), 0, GOT_REF_GENERIC, + if (ld_assign_got_ndx(&(sdp->sd_GOTndxs), 0, GOT_REF_GENERIC, ofl, rsp, sdp) == S_ERROR) return (S_ERROR); @@ -571,7 +571,7 @@ ld_reloc_GOT_relative(Boolean local, Rel_desc *rsp, Ofl_desc *ofl) rsp->rel_rtype = rtype; } } else { - if (ld_assign_gotndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_GENERIC, + if (ld_assign_got_ndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_GENERIC, ofl, rsp, sdp) == S_ERROR) return (S_ERROR); } @@ -981,6 +981,88 @@ reloc_relobj(Boolean local, Rel_desc *rsp, Ofl_desc *ofl) return (ld_add_outrel(oflags, rsp, ofl)); } +/* + * Perform any generic TLS validations before passing control to machine + * specific routines. At this point we know we are dealing with an executable + * or shared object - relocatable objects have already been processed. + */ +static uintptr_t +reloc_TLS(Boolean local, Rel_desc *rsp, Ofl_desc *ofl) +{ + Word rtype = rsp->rel_rtype, flags = ofl->ofl_flags; + Ifl_desc *ifl = rsp->rel_isdesc->is_file; + Half mach = ifl->ifl_ehdr->e_machine; + Sym_desc *sdp = rsp->rel_sym; + unsigned char type; + + /* + * All TLS relocations are illegal in a static executable. + */ + if ((flags & (FLG_OF_STATIC | FLG_OF_EXEC)) == + (FLG_OF_STATIC | FLG_OF_EXEC)) { + eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSSTAT), + conv_reloc_type(mach, rtype, 0), ifl->ifl_name, + demangle(rsp->rel_sname)); + return (S_ERROR); + } + + /* + * Any TLS relocation must be against a STT_TLS symbol, all others + * are illegal. + */ + if ((type = ELF_ST_TYPE(sdp->sd_sym->st_info)) != STT_TLS) { + eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSBADSYM), + conv_reloc_type(mach, rtype, 0), ifl->ifl_name, + demangle(rsp->rel_sname), + conv_sym_info_type(mach, type, 0)); + return (S_ERROR); + } + + /* + * A dynamic executable can not use the LD or LE reference models to + * reference an external symbol. A shared object can not use the LD + * reference model to reference an external symbol. + */ + if (!local && (IS_TLS_LD(rtype) || + ((flags & FLG_OF_EXEC) && IS_TLS_LE(rtype)))) { + eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_TLSBND), + conv_reloc_type(mach, rtype, 0), ifl->ifl_name, + demangle(rsp->rel_sname), sdp->sd_file->ifl_name); + return (S_ERROR); + } + + /* + * The TLS LE model is only allowed for dynamic executables. The TLS IE + * model is allowed for shared objects, but this model has restrictions. + * This model can only be used freely in dependencies that are loaded + * immediately as part of process initialization. However, during the + * initial runtime handshake with libc that establishes the thread + * pointer, a small backup TLS reservation is created. This area can + * be used by objects that are loaded after threads are initialized. + * However, this area is limited in size and may have already been + * used. This area is intended for specialized applications, and does + * not provide the degree of flexibility dynamic TLS can offer. Under + * -z verbose indicate this restriction to the user. + */ + if ((flags & FLG_OF_EXEC) == 0) { + if (IS_TLS_LE(rtype)) { + eprintf(ofl->ofl_lml, ERR_FATAL, + MSG_INTL(MSG_REL_TLSLE), + conv_reloc_type(mach, rtype, 0), ifl->ifl_name, + demangle(rsp->rel_sname)); + return (S_ERROR); + + } else if ((IS_TLS_IE(rtype)) && (flags & FLG_OF_VERBOSE)) { + eprintf(ofl->ofl_lml, ERR_WARNING, + MSG_INTL(MSG_REL_TLSIE), + conv_reloc_type(mach, rtype, 0), ifl->ifl_name, + demangle(rsp->rel_sname)); + } + } + + return (ld_reloc_TLS(local, rsp, ofl)); +} + uintptr_t ld_process_sym_reloc(Ofl_desc *ofl, Rel_desc *reld, Rel *reloc, Is_desc *isp, const char *isname) @@ -1107,7 +1189,8 @@ ld_process_sym_reloc(Ofl_desc *ofl, Rel_desc *reld, Rel *reloc, Is_desc *isp, /* * TLS symbols can only have TLS relocations. */ - if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_TLS) && !IS_TLS(rtype)) { + if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_TLS) && + (IS_TLS_INS(rtype) == 0)) { /* * The above test is relaxed if the target section is * non-allocable. @@ -1133,7 +1216,7 @@ ld_process_sym_reloc(Ofl_desc *ofl, Rel_desc *reld, Rel *reloc, Is_desc *isp, return (reloc_relobj(local, reld, ofl)); if (IS_TLS_INS(rtype)) - return (ld_reloc_TLS(local, reld, ofl)); + return (reloc_TLS(local, reld, ofl)); if (IS_GOT_INS(rtype)) return (ld_reloc_GOTOP(local, reld, ofl)); @@ -1826,6 +1909,7 @@ ld_reloc_process(Ofl_desc *ofl) { Listnode *lnp1; Sg_desc *sgp; + Os_desc *osp; Word ndx = 0, flags = ofl->ofl_flags; Shdr *shdr; @@ -1872,7 +1956,7 @@ ld_reloc_process(Ofl_desc *ofl) Aliste off; for (ALIST_TRAVERSE(sgp->sg_osdescs, off, ospp)) { - Os_desc *osp = *ospp; + osp = *ospp; if (osp->os_relosdesc == 0) continue; @@ -1886,10 +1970,10 @@ ld_reloc_process(Ofl_desc *ofl) /* * Since the .rel[a] section is not tied to any specific - * section, we'd of not found it above. + * section, we'd not have found it above. */ - if (ofl->ofl_osrel) { - shdr = ofl->ofl_osrel->os_shdr; + if ((osp = ofl->ofl_osrel) != NULL) { + shdr = osp->os_shdr; shdr->sh_link = ndx; shdr->sh_info = 0; } @@ -1899,17 +1983,16 @@ ld_reloc_process(Ofl_desc *ofl) * coalesced) so just hit them directly instead of stepping * over the output sections. */ - if (ofl->ofl_osrelhead) { - shdr = ofl->ofl_osrelhead->os_shdr; + if ((osp = ofl->ofl_osrelhead) != NULL) { + shdr = osp->os_shdr; shdr->sh_link = ndx; shdr->sh_info = 0; } - if (ofl->ofl_osplt && ofl->ofl_osplt->os_relosdesc) { - shdr = ofl->ofl_osplt->os_relosdesc->os_shdr; + if (((osp = ofl->ofl_osplt) != NULL) && osp->os_relosdesc) { + shdr = osp->os_relosdesc->os_shdr; shdr->sh_link = ndx; /* LINTED */ - shdr->sh_info = - (Word)elf_ndxscn(ofl->ofl_osplt->os_scn); + shdr->sh_info = (Word)elf_ndxscn(osp->os_scn); } } @@ -1934,6 +2017,13 @@ ld_reloc_process(Ofl_desc *ofl) return (S_ERROR); } + /* + * Now that any GOT information has been written, display the debugging + * information if required. + */ + if ((osp = ofl->ofl_osgot) != NULL) + DBG_CALL(Dbg_got_display(ofl, osp->os_shdr->sh_addr, 1)); + return (1); } @@ -2021,9 +2111,54 @@ ld_reloc_remain_entry(Rel_desc *orsp, Os_desc *osp, Ofl_desc *ofl) } /* - * The following functions are called from - * machine functions defined in {sparc,i386,sparcv9}/machrel.c + * Generic encapsulation for generating a TLS got index. */ +uintptr_t +ld_assign_got_TLS(Boolean local, Rel_desc *rsp, Ofl_desc *ofl, Sym_desc *sdp, + Gotndx *gnp, Gotref gref, Word rflag, Word ortype, Word rtype1, Word rtype2) +{ + Word rflags; + + if (ld_assign_got_ndx(&(sdp->sd_GOTndxs), gnp, gref, ofl, + rsp, sdp) == S_ERROR) + return (S_ERROR); + + rflags = FLG_REL_GOT | rflag; + if (local) + rflags |= FLG_REL_SCNNDX; + rsp->rel_rtype = rtype1; + + if (ld_add_outrel(rflags, rsp, ofl) == S_ERROR) + return (S_ERROR); + + if (local && (gref == GOT_REF_TLSIE)) { + /* + * If this is a local LE TLS symbol, then the symbol won't be + * available at runtime. The value of the local symbol will + * be placed in the associated got entry, and the got + * relocation is reassigned to a section symbol. + */ + if (ld_add_actrel(rflags, rsp, ofl) == S_ERROR) + return (S_ERROR); + } + + if (rtype2) { + rflags = FLG_REL_GOT | rflag; + rsp->rel_rtype = rtype2; + + if (local) { + if (ld_add_actrel(rflags, rsp, ofl) == S_ERROR) + return (S_ERROR); + } else { + if (ld_add_outrel(rflags, rsp, ofl) == S_ERROR) + return (S_ERROR); + } + } + + rsp->rel_rtype = ortype; + + return (1); +} /* * Move Section related function diff --git a/usr/src/cmd/sgs/libld/common/update.c b/usr/src/cmd/sgs/libld/common/update.c index 7f63d8d8b1..2ad3621fc3 100644 --- a/usr/src/cmd/sgs/libld/common/update.c +++ b/usr/src/cmd/sgs/libld/common/update.c @@ -98,7 +98,6 @@ update_osym(Ofl_desc *ofl) Versym *versym; Gottable *gottable; /* used for display got debugging */ /* information */ - Gottable *_gottable; Syminfo *syminfo; Sym_s_list *sorted_syms; /* table to hold sorted symbols */ Word ssndx; /* global index into sorted_syms */ @@ -196,8 +195,8 @@ update_osym(Ofl_desc *ofl) * the buffer to 'cache' the GOT symbols into now. */ if (DBG_ENABLED) { - if ((_gottable = gottable = libld_calloc(ofl->ofl_gotcnt, - sizeof (Gottable))) == 0) + if ((ofl->ofl_gottable = gottable = + libld_calloc(ofl->ofl_gotcnt, sizeof (Gottable))) == 0) return ((Addr)S_ERROR); } @@ -481,10 +480,10 @@ update_osym(Ofl_desc *ofl) #endif if (DBG_ENABLED) { for (LIST_TRAVERSE(&sdp->sd_GOTndxs, lnp2, gnp)) { - _gottable->gt_sym = sdp; - _gottable->gt_gndx.gn_gotndx = gnp->gn_gotndx; - _gottable->gt_gndx.gn_addend = gnp->gn_addend; - _gottable++; + gottable->gt_sym = sdp; + gottable->gt_gndx.gn_gotndx = gnp->gn_gotndx; + gottable->gt_gndx.gn_addend = gnp->gn_addend; + gottable++; } } @@ -902,17 +901,17 @@ update_osym(Ofl_desc *ofl) #endif if (DBG_ENABLED) { for (LIST_TRAVERSE(&sdp->sd_GOTndxs, lnp2, gnp)) { - _gottable->gt_sym = sdp; - _gottable->gt_gndx.gn_gotndx = gnp->gn_gotndx; - _gottable->gt_gndx.gn_addend = gnp->gn_addend; - _gottable++; + gottable->gt_sym = sdp; + gottable->gt_gndx.gn_gotndx = gnp->gn_gotndx; + gottable->gt_gndx.gn_addend = gnp->gn_addend; + gottable++; } if (sdp->sd_aux && sdp->sd_aux->sa_PLTGOTndx) { - _gottable->gt_sym = sdp; - _gottable->gt_gndx.gn_gotndx = + gottable->gt_sym = sdp; + gottable->gt_gndx.gn_gotndx = sdp->sd_aux->sa_PLTGOTndx; - _gottable++; + gottable++; } } @@ -1526,7 +1525,7 @@ update_osym(Ofl_desc *ofl) /* * Now display GOT debugging information if required. */ - DBG_CALL(Dbg_got_display(ofl, gottable)); + DBG_CALL(Dbg_got_display(ofl, 0, 0)); /* * Update the section headers information. diff --git a/usr/src/cmd/sgs/liblddbg/common/_debug.h b/usr/src/cmd/sgs/liblddbg/common/_debug.h index 9a1f172fae..451b17e967 100644 --- a/usr/src/cmd/sgs/liblddbg/common/_debug.h +++ b/usr/src/cmd/sgs/liblddbg/common/_debug.h @@ -105,6 +105,10 @@ typedef struct { #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 +#define MSG_GOT_COLUMNS1 MSG_GOT_COLUMNS1_64 +#define MSG_GOT_COLUMNS2 MSG_GOT_COLUMNS2_64 +#define MSG_GOT_FORMAT1 MSG_GOT_FORMAT1_64 +#define MSG_GOT_FORMAT2 MSG_GOT_FORMAT2_64 #define MSG_PHD_VADDR MSG_PHD_VADDR_64 #define MSG_PHD_PADDR MSG_PHD_PADDR_64 @@ -155,6 +159,10 @@ typedef struct { #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 +#define MSG_GOT_COLUMNS1 MSG_GOT_COLUMNS1_32 +#define MSG_GOT_COLUMNS2 MSG_GOT_COLUMNS2_32 +#define MSG_GOT_FORMAT1 MSG_GOT_FORMAT1_32 +#define MSG_GOT_FORMAT2 MSG_GOT_FORMAT2_32 #define MSG_PHD_VADDR MSG_PHD_VADDR_32 #define MSG_PHD_PADDR MSG_PHD_PADDR_32 diff --git a/usr/src/cmd/sgs/liblddbg/common/got.c b/usr/src/cmd/sgs/liblddbg/common/got.c index 6079aa530a..b66dc7b9c2 100644 --- a/usr/src/cmd/sgs/liblddbg/common/got.c +++ b/usr/src/cmd/sgs/liblddbg/common/got.c @@ -46,10 +46,12 @@ Dbg_got_compare(Gottable *gtp1, Gottable *gtp2) } void -Dbg_got_display(Ofl_desc *ofl, Gottable *gtp) +Dbg_got_display(Ofl_desc *ofl, Off goff, int stage) { - Lm_list *lml = ofl->ofl_lml; - Word gotndx; + Lm_list *lml = ofl->ofl_lml; + Gottable *gtp = ofl->ofl_gottable; + Word gotndx; + Xword *gptr; if (DBG_NOTCLASS(DBG_C_GOT)) return; @@ -66,35 +68,50 @@ Dbg_got_display(Ofl_desc *ofl, Gottable *gtp) qsort((char *)gtp, ofl->ofl_gotcnt, sizeof (Gottable), (int(*)(const void *, const void *))Dbg_got_compare); - dbg_print(lml, MSG_ORIG(MSG_GOT_COLUMNS)); + if (stage == 0) + dbg_print(lml, MSG_INTL(MSG_GOT_COLUMNS1)); + else + dbg_print(lml, MSG_INTL(MSG_GOT_COLUMNS2)); - for (gotndx = 0; gotndx < ofl->ofl_gotcnt; gotndx++, gtp++) { - Sym_desc *sdp; + gptr = (Xword *)ofl->ofl_osgot->os_outdata->d_buf; + + for (gotndx = 0; gotndx < ofl->ofl_gotcnt; gotndx++, gtp++, gptr++) { + Sym_desc *sdp = gtp->gt_sym; const char *refstr, *name; Gotndx *gnp = >p->gt_gndx; + Lword gotaddval; + Off off = goff + (gotndx * M_GOT_ENTSIZE); + char index[INDEX_STR_SIZE]; - if ((sdp = gtp->gt_sym) == 0) - continue; + (void) snprintf(index, INDEX_STR_SIZE, MSG_ORIG(MSG_GOT_INDEX), + EC_SWORD(gnp->gn_gotndx)); - if (sdp->sd_flags & FLG_SY_SMGOT) + if (sdp == 0) + refstr = MSG_ORIG(MSG_STR_EMPTY); + else if (sdp->sd_flags & FLG_SY_SMGOT) refstr = MSG_ORIG(MSG_GOT_SMALL_PIC); else refstr = MSG_ORIG(MSG_GOT_BIG_PIC); - if (sdp->sd_name) + if (sdp == 0) + name = MSG_ORIG(MSG_STR_EMPTY); + else if (sdp->sd_name) name = Dbg_demangle_name(sdp->sd_name); else name = MSG_INTL(MSG_STR_UNKNOWN); - if ((sdp->sd_sym->st_shndx == SHN_UNDEF) || + if (stage == 0) + gotaddval = gnp->gn_addend; + else + gotaddval = *gptr; + + if ((sdp == 0) || (sdp->sd_sym->st_shndx == SHN_UNDEF) || (sdp->sd_file == 0)) { - dbg_print(lml, MSG_ORIG(MSG_GOT_FORMAT1), - EC_SWORD(gnp->gn_gotndx), refstr, - EC_LWORD(gnp->gn_addend), name); + dbg_print(lml, MSG_INTL(MSG_GOT_FORMAT1), index, + refstr, EC_OFF(off), EC_XWORD(gotaddval), name); } else { - dbg_print(lml, MSG_ORIG(MSG_GOT_FORMAT2), - EC_SWORD(gnp->gn_gotndx), refstr, - EC_LWORD(gnp->gn_addend), + dbg_print(lml, MSG_INTL(MSG_GOT_FORMAT2), index, + refstr, EC_OFF(off), EC_XWORD(gotaddval), sdp->sd_file->ifl_name, name); } } diff --git a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg index f84881edd0..940e52097f 100644 --- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg +++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg @@ -311,7 +311,7 @@ u44=%d, full=%d, far=%d, Total=%d" @ MSG_BND_PSUM_SPARC "Summary of PLT types bound: 21d=%d, 24d=%d, \ full=%d, Total=%d" -@ MSG_BND_PSUM_DEFAULT "Summary of PLT types bound: Total=%d" +@ MSG_BND_PSUM_DEFAULT "Summary of PLT types bound: total=%d" # Relocation messages @@ -430,7 +430,7 @@ @ MSG_FIL_CONFIG_ERR_3 "unable to process file" @ MSG_FIL_CONFIG_ERR_4 "corrupt or truncated file" @ MSG_FIL_CONFIG_ERR_5 "incompatible ELF class, byte order, or machine \ - architecture" + architecture" @ MSG_CNTL_TITLE "control list processing complete: moving lmco 0x%llx \ to lmco 0x%llx" @@ -502,9 +502,13 @@ # Move messages @ MSG_MOVE_FILE "file=%s processing move data" -@ MSG_MOVE_TITLE2 " address value repeat stride symbol" -@ MSG_MOVE_ENTRY2 " in %#10llx %#10llx %6d %6d %s" -@ MSG_MOVE_EXPAND " %#10llx %#10llx (expanded)" + +@ MSG_MOVE_TITLE1 " i/o offset value repeat stride symbol" +@ MSG_MOVE_TITLE2 " address value repeat stride symbol" + +@ MSG_MOVE_ENTRYIN " in %#10llx %#10llx %6d %6d %s" +@ MSG_MOVE_ENTRYOUT " out %#10llx %#10llx %6d %6d %s" +@ MSG_MOVE_EXPAND " %#10llx %#10llx (expanded)" @ MSG_MOVE_ADJEXPAND "for symbol=%s roffset: new=0x%llx" @ MSG_MOVE_ADJMOVE "for symbol=%s roffset: from=0x%llx, to=0x%llx" @@ -513,10 +517,6 @@ @ MSG_MOVE_OUTMOVE "copying move entries for %s into .SUNW_move" @ MSG_MOVE_INPUT "collecting move entries: file=%s" -@ MSG_MOVE_TITLE1 "\t i/o offset\tvalue\trepeat\tstride\tsymbol" -@ MSG_MOVE_ENTRY1IN "\t in 0x%llx\t0x%llx\t0x%x\t0x%x\t%s" -@ MSG_MOVE_ENTRY1OUT "\t out 0x%llx\t0x%llx\t0x%x\t0x%x\t%s" - # Section messages @ MSG_SEC_INPUT "section=%s; input from file=%s" @@ -628,22 +628,23 @@ @ MSG_ORD_SORT_BEFORE "Output section to be sorted=%s" @ MSG_ORD_SORT_AFTER "Output section sorted=%s" -@ MSG_ORD_HDR_1 " No. of SHN_BEGIN=%u, SHN_AFTER=%u, sh_info/sh_link=%u" +@ MSG_ORD_HDR_1 " number of SHN_BEGIN=%u, SHN_AFTER=%u, \ + sh_info/sh_link=%u" @ MSG_ORD_TITLE_0 " section=%s from %s is not an ordered section" @ MSG_ORD_TITLE_1 " section=%s from %s, sh_info=SHN_BEGIN" @ MSG_ORD_TITLE_2 " section=%s from %s, sh_info=SHN_AFTER" @ MSG_ORD_TITLE_3 " section=%s from %s, sh_info=%s, sort_val=%d" @ MSG_ORD_TITLE_4 " section=%s from %s, sh_link=%s, sort_val=%d" -@ MSG_ORD_ERR_TITLE "The SHF_ORDERED section %s from %s has \ +@ MSG_ORD_ERR_TITLE "the SHF_ORDERED section %s from %s has \ an error; flag ignored" -@ MSG_ORD_ERR_INFORANGE " The sh_info field is out of range" -@ MSG_ORD_ERR_ORDER " The section pointed by sh_info is an ordered section" -@ MSG_ORD_ERR_LINKRANGE " The sh_link field is out of range" -@ MSG_ORD_ERR_FLAGS " The sh_flag is incorrect" -@ MSG_ORD_ERR_CYCLIC " The sh_link is cyclic" -@ MSG_ORD_ERR_LINKINV " A section pointed to by sh_link has an error" +@ MSG_ORD_ERR_INFORANGE " the sh_info field is out of range" +@ MSG_ORD_ERR_ORDER " the section pointed by sh_info is an ordered section" +@ MSG_ORD_ERR_LINKRANGE " the sh_link field is out of range" +@ MSG_ORD_ERR_FLAGS " the sh_flag is incorrect" +@ MSG_ORD_ERR_CYCLIC " the sh_link is cyclic" +@ MSG_ORD_ERR_LINKINV " a section pointed to by sh_link has an error" # Link-Auditing Messages @@ -720,10 +721,14 @@ # TLS related messages -@ MSG_TLS_STATBLOCK1 "static TLS module: [%2d] %s" -@ MSG_TLS_STATBLOCK2 "static TLS module: Total Static Size: %#llx" -@ MSG_TLS_STMODENT1 " block: %#10llx soff: %#10llx flags: %#4llx" -@ MSG_TLS_STMODENT2 " filesz: %#10llx memsz: %#10llx modid: %#4llx" +@ MSG_TLS_STATBLOCK1 "static TLS module: [%ld] %s" +@ MSG_TLS_STATBLOCK2 "static TLS reservation: in use %#llx: \ + additional backup: %#llx" +@ MSG_TLS_STATBLOCK3 "static TLS requirement: [%ld] %s: size %#llx: \ + satisfied from backup reservation: remaining %#llx" +@ MSG_TLS_MODENT1 " block: %#18llx soff: %#10llx flags: %#llx \ + %s" +@ MSG_TLS_MODENT2 " filesz: %#18llx memsz: %#10llx modid: %lld" @ MSG_TLS_MODACT "%s TLS module: %s" @ MSG_TLS_ADD "add" @ MSG_TLS_REMOVE "remove" @@ -829,22 +834,43 @@ # Global offset table entries. -# TRANSLATION_NOTE - the following two entries provide for a series of one or -# more 32-bit got table entries that align with the initial title. +# TRANSLATION_NOTE - the following two entries are used by elfdump(1), and +# provide for a series of one or more 32-bit got table entries that align with +# the initial title. @ MSG_GOT_TITLE_32 " index addr value \ pending relocation" @ MSG_GOT_ENTRY_RE_32 "%10.10s 0x%08llx 0x%08llx %-24s %s" @ MSG_GOT_ENTRY_NR_32 "%10.10s 0x%08llx 0x%08llx" -# TRANSLATION_NOTE - the following two entries provide for a series of one or -# more 64-bit got table entries that align with the initial title. +# TRANSLATION_NOTE - the following two entries are used by elfdump(1), and +# provide for a series of one or more 64-bit got table entries that align with +# the initial title. @ MSG_GOT_TITLE_64 " index addr \ value pending relocation" @ MSG_GOT_ENTRY_RE_64 "%10.10s 0x%016llx 0x%016llx %-24s %s" @ MSG_GOT_ENTRY_NR_64 "%10.10s 0x%016llx 0x%016llx" +# TRANSLATION_NOTE - the following three entries are used by ld(1), and provide +# for a series of one or more 32-bit got table entries that align with one of +# the initial titles. + +@ MSG_GOT_COLUMNS1_32 " index ref offset addend symbol" +@ MSG_GOT_COLUMNS2_32 " index ref offset value symbol" +@ MSG_GOT_FORMAT1_32 "%10.10s %3s 0x%08llx 0x%08llx %s" +@ MSG_GOT_FORMAT2_32 "%10.10s %3s 0x%08llx 0x%08llx %s:%s" + +# TRANSLATION_NOTE - the following three entries are used by ld(1), and provide +# for a series of one or more 64-bit got table entries that align with one of +# the initial titles. + +@ MSG_GOT_COLUMNS1_64 " index ref offset \ + addend symbol" +@ MSG_GOT_COLUMNS2_64 " index ref offset \ + value symbol" +@ MSG_GOT_FORMAT1_64 "%10.10s %3s 0x%016llx 0x%016llx %s" +@ MSG_GOT_FORMAT2_64 "%10.10s %3s 0x%016llx 0x%016llx %s:%s" # Version table entries. @ MSG_VER_DEF " index version dependency" @@ -1131,20 +1157,16 @@ @ MSG_VER_ALL " ALL %-26.26s" @ MSG_VER_L_ALL " ALL %-26s" -# GOT messages +# Global offset table entries. -@ MSG_GOT_COLUMNS "index ref addend symbol" +@ MSG_GOT_INDEX " [%ld]" @ MSG_GOT_SMALL_PIC "pic" @ MSG_GOT_BIG_PIC "PIC" -@ MSG_GOT_FORMAT1 "[%05d] %3s 0x%08llx %s" -@ MSG_GOT_FORMAT2 "[%05d] %3s 0x%08llx %s:%s" @ MSG_CNTL_ENTRY " [0x%llx] %s" -@ MSG_STR_EMPTY "" @ MSG_STR_NL "\n" -@ MSG_GOT_INDEX " [%ld]" @ MSG_FMT_INDEX " [%d]" @ MSG_SUNW_OST_SGS "SUNW_OST_SGS" @@ -1222,3 +1244,11 @@ @ MSG_CI_TLS_MODREM "TLS_MODREM" @ MSG_CI_TLS_STATMOD "TLS_STATMOD" @ MSG_CI_THRINIT "THRINIT" + +# TLS information flags + +@ MSG_TLS_FLAG_START "[" +@ MSG_TLS_FLAG_END "]" +@ MSG_TLS_FLAG_SEP " " + +@ MSG_TLS_FLAG_STATIC " STATIC-TLS " diff --git a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg index 994066a1ff..447d35b14b 100644 --- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg +++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg @@ -46,6 +46,10 @@ void Dbg_audit_symval(Lm_list *, const char *, const char *, const char *, Addr, Addr); void Dbg_audit_version(Lm_list *, const char *, ulong_t); +void Dbg_tls_modactivity(Lm_list *, void *, uint_t); +void Dbg_tls_static_block(Lm_list *, void *, ulong_t, ulong_t); +void Dbg_tls_static_resv(Rt_map *, ulong_t, ulong_t); + void Dbg32_bind_global(Rt_map *, Elf32_Addr, Elf32_Off, Elf32_Word, Pltbindtype, Rt_map *, Elf32_Addr, Elf32_Off, const char *, uint_t); void Dbg64_bind_global(Rt_map *, Elf64_Addr, Elf64_Off, Elf64_Xword, @@ -140,8 +144,8 @@ void Dbg64_file_reuse(Lm_list *, const char *, const char *); void Dbg32_file_skip(Lm_list *, const char *, const char *); void Dbg64_file_skip(Lm_list *, const char *, const char *); -void Dbg32_got_display(Ofl_desc *, Gottable *); -void Dbg64_got_display(Ofl_desc *, Gottable *); +void Dbg32_got_display(Ofl_desc *, Elf32_Off, int); +void Dbg64_got_display(Ofl_desc *, Elf64_Off, int); void Dbg32_libs_audit(Lm_list *, const char *, const char *); void Dbg64_libs_audit(Lm_list *, const char *, const char *); diff --git a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers index c37bf8407f..c39f5778bc 100644 --- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers +++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers @@ -38,7 +38,7 @@ # Policy for Shared Library Version Names and Interface Definitions -SUNWprivate_4.51 { +SUNWprivate_4.52 { global: dbg_desc = NODIRECT; # interposed - ld.so.1(1) dbg_print = NODIRECT; # interposed - ld(1) and ld.so.1(1) @@ -352,6 +352,7 @@ SUNWprivate_4.51 { Dbg_tls_modactivity; Dbg_tls_static_block; + Dbg_tls_static_resv; Dbg32_util_broadcast; Dbg64_util_broadcast; diff --git a/usr/src/cmd/sgs/liblddbg/common/move.c b/usr/src/cmd/sgs/liblddbg/common/move.c index bc897c0457..17434bbfeb 100644 --- a/usr/src/cmd/sgs/liblddbg/common/move.c +++ b/usr/src/cmd/sgs/liblddbg/common/move.c @@ -142,9 +142,9 @@ Dbg_move_entry1(Lm_list *lml, int which, Move *mv, Sym_desc *s) return; if (which) - str = MSG_INTL(MSG_MOVE_ENTRY1IN); + str = MSG_INTL(MSG_MOVE_ENTRYIN); else - str = MSG_INTL(MSG_MOVE_ENTRY1OUT); + str = MSG_INTL(MSG_MOVE_ENTRYOUT); dbg_print(lml, str, EC_XWORD(mv->m_poffset), EC_LWORD(mv->m_value), mv->m_repeat, mv->m_stride, s->sd_name); @@ -165,6 +165,6 @@ Dbg_move_entry2(Lm_list *lml, Move *mv, Word st_name, const char *name) else sname = MSG_INTL(MSG_STR_UNKNOWN); - dbg_print(lml, MSG_INTL(MSG_MOVE_ENTRY2), EC_XWORD(mv->m_poffset), + dbg_print(lml, MSG_INTL(MSG_MOVE_ENTRYIN), EC_XWORD(mv->m_poffset), EC_LWORD(mv->m_value), mv->m_repeat, mv->m_stride, sname); } diff --git a/usr/src/cmd/sgs/liblddbg/common/tls.c b/usr/src/cmd/sgs/liblddbg/common/tls.c index 5af330e3a3..94831f6e1f 100644 --- a/usr/src/cmd/sgs/liblddbg/common/tls.c +++ b/usr/src/cmd/sgs/liblddbg/common/tls.c @@ -29,39 +29,79 @@ #include <link.h> #include <libc_int.h> #include <rtld.h> +#include <strings.h> #include <debug.h> #include "msg.h" #include "_debug.h" +#define FLAGSZ MSG_TLS_FLAG_START_SIZE + \ + MSG_TLS_FLAG_STATIC_SIZE + \ + CONV_INV_STRSIZE + MSG_TLS_FLAG_END_SIZE + static void Dbg_tls_modent(Lm_list *lml, TLS_modinfo * tmodent) { - dbg_print(lml, MSG_INTL(MSG_TLS_STMODENT1), + static Val_desc vda[] = { + { TM_FLG_STATICTLS, MSG_ORIG(MSG_TLS_FLAG_STATIC) }, + { 0, 0 } + }; + char flagstr[FLAGSZ]; + ulong_t flags; + + if ((flags = tmodent->tm_flags) != 0) { + (void) strlcpy(flagstr, MSG_ORIG(MSG_TLS_FLAG_START), FLAGSZ); + + if (conv_expn_field(flagstr, FLAGSZ, vda, flags, flags, + MSG_ORIG(MSG_TLS_FLAG_SEP), 0)) + (void) strcat(flagstr, MSG_ORIG(MSG_TLS_FLAG_END)); + } else + flagstr[0] = '\0'; + + dbg_print(lml, MSG_INTL(MSG_TLS_MODENT1), EC_XWORD((uintptr_t)tmodent->tm_tlsblock), - EC_XWORD(tmodent->tm_stattlsoffset), EC_XWORD(tmodent->tm_flags)); - dbg_print(lml, MSG_INTL(MSG_TLS_STMODENT2), + EC_XWORD(tmodent->tm_stattlsoffset), EC_XWORD(tmodent->tm_flags), + flagstr); + dbg_print(lml, MSG_INTL(MSG_TLS_MODENT2), EC_XWORD(tmodent->tm_filesz), EC_XWORD(tmodent->tm_memsz), EC_XWORD(tmodent->tm_modid)); } void -Dbg_tls_static_block(Lm_list *lml, void *vtlsmodlist, ulong_t tlsstatsize) +Dbg_tls_static_block(Lm_list *lml, void *list, ulong_t size, ulong_t resv) { - uint_t i; - TLS_modinfo ** tlsmodlist; - if (DBG_NOTCLASS(DBG_C_TLS)) return; - tlsmodlist = (TLS_modinfo **)vtlsmodlist; Dbg_util_nl(lml, DBG_NL_STD); - for (i = 0; tlsmodlist[i]; i++) { - dbg_print(lml, MSG_INTL(MSG_TLS_STATBLOCK1), i, - tlsmodlist[i]->tm_modname); - Dbg_tls_modent(lml, tlsmodlist[i]); + if (list) { + ulong_t ndx; + TLS_modinfo **tlsmodlist; + + tlsmodlist = (TLS_modinfo **)list; + + for (ndx = 0; tlsmodlist[ndx]; ndx++) { + dbg_print(lml, MSG_INTL(MSG_TLS_STATBLOCK1), ndx, + tlsmodlist[ndx]->tm_modname); + Dbg_tls_modent(lml, tlsmodlist[ndx]); + Dbg_util_nl(lml, DBG_NL_STD); + } } - dbg_print(lml, MSG_INTL(MSG_TLS_STATBLOCK2), EC_XWORD(tlsstatsize)); + dbg_print(lml, MSG_INTL(MSG_TLS_STATBLOCK2), EC_XWORD(size), + EC_XWORD(resv)); +} + +void +Dbg_tls_static_resv(Rt_map *lmp, ulong_t size, ulong_t resv) +{ + Lm_list *lml = LIST(lmp); + + if (DBG_NOTCLASS(DBG_C_TLS)) + return; + + Dbg_util_nl(lml, DBG_NL_STD); + dbg_print(lml, MSG_INTL(MSG_TLS_STATBLOCK3), TLSMODID(lmp), NAME(lmp), + EC_XWORD(size), EC_XWORD(resv)); } void diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README index 6e4676b6b5..c6ca28660f 100644 --- a/usr/src/cmd/sgs/packages/common/SUNWonld-README +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README @@ -1105,3 +1105,4 @@ Bugid Risk Synopsis 6429418 ld.so.1: need work-around for Nvidia drivers use of static TLS 6429504 crle(1) shows wrong defaults for non-existent 64-bit config file 6431835 data corruption on x64 in 64-bit mode while LD_PROFILE is in effect +6423051 static TLS support within the link-editors needs a major face lift (D) diff --git a/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c b/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c index e69271ed54..6e502b3db0 100644 --- a/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c +++ b/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c @@ -615,6 +615,7 @@ elf_reloc(Rt_map *lmp, uint_t plt) relbgn = elf_reloc_relative(relbgn, relend, relsiz, basebgn, etext, emap); } + if (relbgn >= relend) break; rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info); @@ -721,11 +722,22 @@ elf_reloc(Rt_map *lmp, uint_t plt) name = (char *)0; /* - * TLS relocation - value for DTPMOD64 - * relocation is the TLS modid. + * Special case TLS relocations. */ - if (rtype == R_AMD64_DTPMOD64) + if (rtype == R_AMD64_DTPMOD64) { + /* + * Use the TLS modid. + */ value = TLSMODID(lmp); + + } else if ((rtype == R_AMD64_TPOFF64) || + (rtype == R_AMD64_TPOFF32)) { + if ((value = elf_static_tls(lmp, symref, + rel, rtype, 0, roffset, 0)) == 0) { + ret = 0; + break; + } + } } else { /* * If the symbol index is equal to the previous @@ -821,6 +833,10 @@ elf_reloc(Rt_map *lmp, uint_t plt) NAME(lmp)); continue; } else { + DBG_CALL(Dbg_reloc_in(lml, + ELF_DBG_RTLD, M_MACH, + M_REL_SHT_TYPE, rel, + NULL, name)); eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), @@ -900,29 +916,41 @@ elf_reloc(Rt_map *lmp, uint_t plt) value -= roffset; /* - * TLS relocation - value for DTPMOD64 - * relocation is the TLS modid. + * Special case TLS relocations. */ - if (rtype == R_AMD64_DTPMOD64) + if (rtype == R_AMD64_DTPMOD64) { + /* + * Relocation value is the TLS modid. + */ value = TLSMODID(_lmp); - else if ((rtype == R_AMD64_TPOFF64) || - (rtype == R_AMD64_TPOFF32)) - value = -(TLSSTATOFF(_lmp) - value); + + } else if ((rtype == R_AMD64_TPOFF64) || + (rtype == R_AMD64_TPOFF32)) { + if ((value = elf_static_tls(_lmp, + symdef, rel, rtype, name, roffset, + value)) == 0) { + ret = 0; + break; + } + } } } else { /* - * Special case: - * - * A DTPMOD32 relocation is a local binding to a TLS - * symbol. Fill in the TLSMODID for the current object. + * Special cases. */ - if (rtype == R_AMD64_DTPMOD64) + if (rtype == R_AMD64_DTPMOD64) { + /* + * TLS relocation value is the TLS modid. + */ value = TLSMODID(lmp); - else + } else value = basebgn; name = (char *)0; } + DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, + M_REL_SHT_TYPE, rel, NULL, name)); + /* * If this object has relocations in the text segment, turn * off the write protect. @@ -938,9 +966,6 @@ elf_reloc(Rt_map *lmp, uint_t plt) /* * Call relocation routine to perform required relocation. */ - DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, - M_REL_SHT_TYPE, rel, NULL, name)); - switch (rtype) { case R_AMD64_COPY: if (elf_copy_reloc(name, symref, lmp, (void *)roffset, diff --git a/usr/src/cmd/sgs/rtld/common/_rtld.h b/usr/src/cmd/sgs/rtld/common/_rtld.h index 0679bbc3b1..94354aaea4 100644 --- a/usr/src/cmd/sgs/rtld/common/_rtld.h +++ b/usr/src/cmd/sgs/rtld/common/_rtld.h @@ -541,6 +541,8 @@ extern ulong_t elf_reloc_relative(ulong_t, ulong_t, ulong_t, ulong_t, ulong_t, ulong_t); extern ulong_t elf_reloc_relacount(ulong_t, ulong_t, ulong_t, ulong_t); +extern long elf_static_tls(Rt_map *, Sym*, void *, uchar_t, char *, + ulong_t, long); extern int enter(void); extern uint_t expand(char **, size_t *, char **, uint_t, uint_t, Rt_map *); @@ -627,7 +629,7 @@ extern Rt_map *setup(char **, auxv_t *, Word, char *, int, char *, Dyn *, ulong_t, ulong_t, int fd, Phdr *, char *, char **, int, uid_t, uid_t, gid_t, gid_t, void *, int, uint_t); -extern void tls_assign_soffset(Rt_map *); +extern int tls_assign(Lm_list *, Rt_map *, Phdr *); extern void tls_modaddrem(Rt_map *, uint_t); extern int tls_statmod(Lm_list *, Rt_map *); extern Rt_map **tsort(Rt_map *, int, int); diff --git a/usr/src/cmd/sgs/rtld/common/elf.c b/usr/src/cmd/sgs/rtld/common/elf.c index abdf6c0d3c..54be0c2aa9 100644 --- a/usr/src/cmd/sgs/rtld/common/elf.c +++ b/usr/src/cmd/sgs/rtld/common/elf.c @@ -2254,6 +2254,14 @@ elf_new_lm(Lm_list *lml, const char *pname, const char *oname, Dyn *ld, MODE(lmp) |= RTLD_NOW; MODE(lmp) &= ~RTLD_LAZY; } + /* + * Capture any static TLS use, and enforce that + * this object be non-deletable. + */ + if (ld->d_un.d_val & DF_STATIC_TLS) { + FLAGS1(lmp) |= FL1_RT_TLSSTAT; + MODE(lmp) |= RTLD_NODELETE; + } break; case DT_FLAGS_1: if (ld->d_un.d_val & DF_1_DISPRELPND) @@ -2755,16 +2763,15 @@ elf_map_so(Lm_list *lml, Aliste lmco, const char *pname, const char *oname, } /* - * If this shared object contains a any special segments, record them. + * If this shared object contains any special segments, record them. */ if (swph) { FLAGS(lmp) |= FLG_RT_SUNWBSS; SUNWBSS(lmp) = phdr + (swph - phdr0); } - if (tlph) { - PTTLS(lmp) = phdr + (tlph - phdr0); - tls_assign_soffset(lmp); - lml->lm_tls++; + if (tlph && (tls_assign(lml, lmp, (phdr + (tlph - phdr0))) == 0)) { + remove_so(lml, lmp); + return (0); } if (unwindph) @@ -2776,7 +2783,6 @@ elf_map_so(Lm_list *lml, Aliste lmco, const char *pname, const char *oname, return (lmp); } - /* * Function to correct protection settings. Segments are all mapped initially * with permissions as given in the segment header. We need to turn on write @@ -3169,3 +3175,65 @@ elf_reloc_bad(Rt_map *lmp, void *rel, uchar_t rtype, ulong_t roffset, Dbg_reloc_error(lml, ELF_DBG_RTLD, M_MACH, M_REL_SHT_TYPE, rel, name); } + +/* + * Resolve a static TLS relocation. + */ +long +elf_static_tls(Rt_map *lmp, Sym *sym, void *rel, uchar_t rtype, char *name, + ulong_t roffset, long value) +{ + Lm_list *lml = LIST(lmp); + + /* + * Relocations against a static TLS block have limited support once + * process initialization has completed. Any error condition should be + * discovered by testing for DF_STATIC_TLS as part of loading an object, + * however individual relocations are tested in case the dynamic flag + * had not been set when this object was built. + */ + if (PTTLS(lmp) == 0) { + DBG_CALL(Dbg_reloc_in(lml, ELF_DBG_RTLD, M_MACH, + M_REL_SHT_TYPE, rel, NULL, name)); + eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_BADTLS), + _conv_reloc_type((uint_t)rtype), NAME(lmp), + name ? demangle(name) : MSG_INTL(MSG_STR_UNKNOWN)); + return (0); + } + + /* + * If no static TLS has been set aside for this object, determine if + * any can be obtained. Enforce that any object using static TLS is + * non-deletable. + */ + if (TLSSTATOFF(lmp) == 0) { + FLAGS1(lmp) |= FL1_RT_TLSSTAT; + MODE(lmp) |= RTLD_NODELETE; + + if (tls_assign(lml, lmp, PTTLS(lmp)) == 0) { + DBG_CALL(Dbg_reloc_in(lml, ELF_DBG_RTLD, M_MACH, + M_REL_SHT_TYPE, rel, NULL, name)); + eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_BADTLS), + _conv_reloc_type((uint_t)rtype), NAME(lmp), + name ? demangle(name) : MSG_INTL(MSG_STR_UNKNOWN)); + return (0); + } + } + + /* + * Typically, a static TLS offset is maintained as a symbols value. + * For local symbols that are not apart of the dynamic symbol table, + * the TLS relocation points to a section symbol, and the static TLS + * offset was deposited in the associated GOT table. Make sure the GOT + * is cleared, so that the value isn't reused in do_reloc(). + */ + if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) { + if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION)) { + value = *(long *)roffset; + *(long *)roffset = 0; + } else { + value = sym->st_value; + } + } + return (-(TLSSTATOFF(lmp) - value)); +} diff --git a/usr/src/cmd/sgs/rtld/common/external.c b/usr/src/cmd/sgs/rtld/common/external.c index b811d51284..8434255623 100644 --- a/usr/src/cmd/sgs/rtld/common/external.c +++ b/usr/src/cmd/sgs/rtld/common/external.c @@ -381,7 +381,7 @@ rt_get_extern(Lm_list *lml, Rt_map *lmp) * 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), + eprintf(lml, ERR_FATAL, MSG_INTL(MSG_TLS_NOSUPPORT), NAME(lmp)); return (0); } diff --git a/usr/src/cmd/sgs/rtld/common/rtld.msg b/usr/src/cmd/sgs/rtld/common/rtld.msg index 14b3bd207a..f9228905d7 100644 --- a/usr/src/cmd/sgs/rtld/common/rtld.msg +++ b/usr/src/cmd/sgs/rtld/common/rtld.msg @@ -100,7 +100,8 @@ called from 0x%llx" @ MSG_REL_UNSUPSZ "relocation error: %s: file %s: symbol %s: \ offset size (%d bytes) is not supported" - +@ MSG_REL_BADTLS "relocation error: %s: file %s: symbol %s: \ + file contains insufficient TLS support information" # System call messages. @@ -218,9 +219,18 @@ # Error TLS failures -@ MSG_ERR_TLS_NOTLS "%s: object requires TLS, but TLS failed to initialize" +@ MSG_TLS_NOSUPPORT "%s: TLS requirement failure : TLS support is \ + unavailable" +@ MSG_TLS_STATBASE "%s: static TLS failure: object is not part of primary \ + link-map list" +@ MSG_TLS_STATSIZE "%s: static TLS failure: object loaded after process \ + initialization: size (%#llx) exceeds available backup \ + reservation (%#llx)" +@ MSG_TLS_STATINIT "%s: static TLS failure: object loaded after process \ + initialization: can not accommodate initialized data" # Error expand() + @ MSG_ERR_EXPAND1 "%s: %s: path name too long" @ MSG_ERR_EXPAND2 "%s: %s: token %s could not be expanded" diff --git a/usr/src/cmd/sgs/rtld/common/setup.c b/usr/src/cmd/sgs/rtld/common/setup.c index 4313889bc7..c6453dc692 100644 --- a/usr/src/cmd/sgs/rtld/common/setup.c +++ b/usr/src/cmd/sgs/rtld/common/setup.c @@ -639,13 +639,13 @@ setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz, (ulong_t)ehdr, memsize, mmaps, mmapcnt)) == 0) { return (0); } - if (tlsphdr) { - PTTLS(mlmp) = tlsphdr; - tls_assign_soffset(mlmp); - lml_main.lm_tls++; - } + if (tlsphdr && + (tls_assign(&lml_main, mlmp, tlsphdr) == 0)) + return (0); + if (unwindphdr) PTUNWIND(mlmp) = unwindphdr; + if (cap) cap_assign(cap, mlmp); } diff --git a/usr/src/cmd/sgs/rtld/common/tls.c b/usr/src/cmd/sgs/rtld/common/tls.c index 02ca4f6a53..10112adbaf 100644 --- a/usr/src/cmd/sgs/rtld/common/tls.c +++ b/usr/src/cmd/sgs/rtld/common/tls.c @@ -36,8 +36,6 @@ #include <msg.h> #include <debug.h> -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. */ typedef struct { @@ -48,11 +46,10 @@ typedef struct { static Tlsmodid tmid = {0, 0, 0}; -ulong_t +static ulong_t tls_getmodid() { - ulong_t ndx; - ulong_t i; + ulong_t ndx, cnt; if (tmid.tmi_bits == 0) { if ((tmid.tmi_bits = calloc(TLSBLOCKCNT, sizeof (uint_t))) == 0) @@ -63,18 +60,20 @@ tls_getmodid() return (0); } - for (i = tmid.tmi_lowfree / (sizeof (uint_t) * 8); - i < tmid.tmi_cnt; i++) { - uint_t j; + for (cnt = tmid.tmi_lowfree / (sizeof (uint_t) * 8); + cnt < tmid.tmi_cnt; cnt++) { + uint_t bits; + /* * If all bits are assigned - move on. */ - if ((tmid.tmi_bits[i] ^ ~((uint_t)0)) == 0) + if ((tmid.tmi_bits[cnt] ^ ~((uint_t)0)) == 0) continue; - for (ndx = 0, j = 1; j; j = j << 1, ndx++) { - if ((tmid.tmi_bits[i] & j) == 0) { - tmid.tmi_bits[i] |= j; - ndx = (i * (sizeof (uint_t)) * 8) + ndx; + + for (ndx = 0, bits = 1; bits; bits = bits << 1, ndx++) { + if ((tmid.tmi_bits[cnt] & bits) == 0) { + tmid.tmi_bits[cnt] |= bits; + ndx = (cnt * (sizeof (uint_t)) * 8) + ndx; tmid.tmi_lowfree = ndx + 1; return (ndx); } @@ -152,8 +151,8 @@ tls_modaddrem(Rt_map *lmp, uint_t flag) (*fptr)(&tmi); /* - * Tag that this link-map has registered its TLS, and free up the - * moduleid + * Tag that this link-map has registered its TLS, and, if this object + * is being removed, free up the module id. */ FLAGS1(lmp) |= FL1_RT_TLSADD; @@ -161,22 +160,96 @@ tls_modaddrem(Rt_map *lmp, uint_t flag) tls_freemodid(TLSMODID(lmp)); } -void -tls_assign_soffset(Rt_map *lmp) +static ulong_t tls_static_size = 0; /* static TLS buffer size */ +static ulong_t tls_static_resv = 512; /* (extra) static TLS reservation */ + +/* + * Track any static TLS use, retain the TLS header, and assign a TLS module + * identifier. + */ +int +tls_assign(Lm_list *lml, Rt_map *lmp, Phdr *phdr) { + ulong_t memsz = S_ROUND(phdr->p_memsz, M_TLSSTATALIGN); + ulong_t filesz = phdr->p_filesz; + ulong_t resv = tls_static_resv; + + /* + * If this object explicitly references static TLS, then there are some + * limitations. + */ + if (FLAGS1(lmp) & FL1_RT_TLSSTAT) { + /* + * Static TLS is only available to objects on the primary + * link-map list. + */ + if ((lml->lm_flags & LML_FLG_BASELM) == 0) { + eprintf(lml, ERR_FATAL, MSG_INTL(MSG_TLS_STATBASE), + NAME(lmp)); + return (0); + } + + /* + * All TLS blocks that are processed before thread + * initialization, are registered with libc. This + * initialization is carried out through a handshake with libc + * prior to executing any user code (ie. before the first .init + * sections are called). As part of this initialization, a + * small backup TLS reservation is added (tls_static_resv). + * Only explicit static TLS references that can be satisfied by + * this TLS backup reservation can be satisfied. + */ + if (rtld_flags2 & RT_FL2_PLMSETUP) { + /* + * Initialized static TLS can not be satisfied from the + * TLS backup reservation. + */ + if (filesz) { + eprintf(lml, ERR_FATAL, + MSG_INTL(MSG_TLS_STATINIT), NAME(lmp)); + return (0); + } + + /* + * Make sure the backup reservation is sufficient. + */ + if (memsz > tls_static_resv) { + eprintf(lml, ERR_FATAL, + MSG_INTL(MSG_TLS_STATSIZE), NAME(lmp), + EC_XWORD(memsz), EC_XWORD(tls_static_resv)); + return (0); + } + + tls_static_resv -= memsz; + } + } + /* - * Only objects on the primary link-map list are associated - * with the STATIC tls block. + * If we haven't yet initialized threads, or this static reservation can + * be satisfied from the TLS backup reservation, determine the total + * static TLS size, and assign this object a static TLS offset. */ - if (LIST(lmp)->lm_flags & LML_FLG_BASELM) { - tls_static_size += S_ROUND(PTTLS(lmp)->p_memsz, M_TLSSTATALIGN); + if (((rtld_flags2 & RT_FL2_PLMSETUP) == 0) || + (FLAGS1(lmp) & FL1_RT_TLSSTAT)) { + tls_static_size += memsz; TLSSTATOFF(lmp) = tls_static_size; } /* - * Everyone get's a dynamic TLS modid. + * Retain the PT_TLS header, obtain a new module identifier, and + * indicate that this link-map list contains a new TLS object. */ + PTTLS(lmp) = phdr; TLSMODID(lmp) = tls_getmodid(); + + /* + * Now that we have a TLS module id, generate any static TLS reservation + * diagnostic. + */ + if (resv != tls_static_resv) + DBG_CALL(Dbg_tls_static_resv(lmp, memsz, tls_static_resv)); + + return (++lml->lm_tls); } int @@ -195,6 +268,8 @@ tls_statmod(Lm_list *lml, Rt_map *lmp) if (tlsmodcnt == 0) { if (fptr) (*fptr)(0, 0); + DBG_CALL(Dbg_tls_static_block(&lml_main, 0, 0, + tls_static_resv)); return (1); } lml->lm_tls = 0; @@ -246,8 +321,8 @@ tls_statmod(Lm_list *lml, Rt_map *lmp) } DBG_CALL(Dbg_tls_static_block(&lml_main, (void *)tlsmodlist, - tls_static_size)); - (*fptr)(tlsmodlist, tls_static_size); + tls_static_size, tls_static_resv)); + (*fptr)(tlsmodlist, (tls_static_size + tls_static_resv)); /* * We're done with the list - clean it up. diff --git a/usr/src/cmd/sgs/rtld/i386/i386_elf.c b/usr/src/cmd/sgs/rtld/i386/i386_elf.c index 62b665abdb..74f39c9334 100644 --- a/usr/src/cmd/sgs/rtld/i386/i386_elf.c +++ b/usr/src/cmd/sgs/rtld/i386/i386_elf.c @@ -583,6 +583,7 @@ elf_reloc(Rt_map *lmp, uint_t plt) } textrel = 1; } + if (relacount) { relbgn = elf_reloc_relacount(relbgn, relacount, relsiz, basebgn); @@ -678,11 +679,21 @@ elf_reloc(Rt_map *lmp, uint_t plt) name = (char *)0; /* - * TLS relocation - value for DTPMOD32 - * relocation is the TLS modid. + * Special case TLS relocations. */ - if (rtype == R_386_TLS_DTPMOD32) + if (rtype == R_386_TLS_DTPMOD32) { + /* + * Use the TLS modid. + */ value = TLSMODID(lmp); + + } else if (rtype == R_386_TLS_TPOFF) { + if ((value = elf_static_tls(lmp, symref, + rel, rtype, 0, roffset, 0)) == 0) { + ret = 0; + break; + } + } } else { /* * If the symbol index is equal to the previous @@ -778,6 +789,10 @@ elf_reloc(Rt_map *lmp, uint_t plt) NAME(lmp)); continue; } else { + DBG_CALL(Dbg_reloc_in(lml, + ELF_DBG_RTLD, M_MACH, + M_REL_SHT_TYPE, rel, + NULL, name)); eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), @@ -857,28 +872,40 @@ elf_reloc(Rt_map *lmp, uint_t plt) value -= roffset; /* - * TLS relocation - value for DTPMOD32 - * relocation is the TLS modid. + * Special case TLS relocations. */ - if (rtype == R_386_TLS_DTPMOD32) + if (rtype == R_386_TLS_DTPMOD32) { + /* + * Relocation value is the TLS modid. + */ value = TLSMODID(_lmp); - else if (rtype == R_386_TLS_TPOFF) - value = -(TLSSTATOFF(_lmp) - value); + + } else if (rtype == R_386_TLS_TPOFF) { + if ((value = elf_static_tls(_lmp, + symdef, rel, rtype, name, roffset, + value)) == 0) { + ret = 0; + break; + } + } } } else { /* - * Special case: - * - * A DTPMOD32 relocation is a local binding to a TLS - * symbol. Fill in the TLSMODID for the current object. + * Special cases. */ - if (rtype == R_386_TLS_DTPMOD32) + if (rtype == R_386_TLS_DTPMOD32) { + /* + * TLS relocation value is the TLS modid. + */ value = TLSMODID(lmp); - else + } else value = basebgn; name = (char *)0; } + DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, + M_REL_SHT_TYPE, rel, NULL, name)); + /* * If this object has relocations in the text segment, turn * off the write protect. @@ -894,9 +921,6 @@ elf_reloc(Rt_map *lmp, uint_t plt) /* * Call relocation routine to perform required relocation. */ - DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, - M_REL_SHT_TYPE, rel, NULL, name)); - switch (rtype) { case R_386_COPY: if (elf_copy_reloc(name, symref, lmp, (void *)roffset, diff --git a/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c b/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c index 1ffa2da2e3..a364002fef 100644 --- a/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c +++ b/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c @@ -758,11 +758,21 @@ elf_reloc(Rt_map *lmp, uint_t plt) name = (char *)0; /* - * TLS relocation - value for DTPMOD relocation - * is the TLS modid. + * Special case TLS relocations. */ - if (rtype == M_R_DTPMOD) + if (rtype == R_SPARC_TLS_DTPMOD32) { + /* + * Use the TLS modid. + */ value = TLSMODID(lmp); + + } else if (rtype == R_SPARC_TLS_TPOFF32) { + if ((value = elf_static_tls(lmp, symref, + rel, rtype, 0, roffset, 0)) == 0) { + ret = 0; + break; + } + } } else { /* * If the symbol index is equal to the previous @@ -856,6 +866,10 @@ elf_reloc(Rt_map *lmp, uint_t plt) NAME(lmp)); continue; } else { + DBG_CALL(Dbg_reloc_in(lml, + ELF_DBG_RTLD, M_MACH, + M_REL_SHT_TYPE, rel, + NULL, name)); eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), @@ -935,33 +949,49 @@ elf_reloc(Rt_map *lmp, uint_t plt) value -= roffset; /* - * TLS relocation - value for DTPMOD relocation - * is the TLS modid. + * Special case TLS relocations. */ - if (rtype == M_R_DTPMOD) + if (rtype == R_SPARC_TLS_DTPMOD32) { + /* + * Relocation value is the TLS modid. + */ value = TLSMODID(_lmp); - else if (rtype == M_R_TPOFF) - value = -(TLSSTATOFF(_lmp) - value); + + } else if (rtype == R_SPARC_TLS_TPOFF32) { + if ((value = elf_static_tls(_lmp, + symdef, rel, rtype, name, roffset, + value)) == 0) { + ret = 0; + break; + } + } } } else { /* - * Special cases, a register symbol associated with - * symbol index 0 is initialized (i.e. relocated) to - * a constant in the r_addend field rather than to a - * symbol value. - * - * A DTPMOD relocation is a local binding to a TLS - * symbol. Fill in the TLSMODID for the current object. + * Special cases. */ - if (rtype == R_SPARC_REGISTER) + if (rtype == R_SPARC_REGISTER) { + /* + * A register symbol associated with symbol + * index 0 is initialized (i.e. relocated) to + * a constant in the r_addend field rather than + * to a symbol value. + */ value = 0; - else if (rtype == M_R_DTPMOD) + + } else if (rtype == R_SPARC_TLS_DTPMOD32) { + /* + * TLS relocation value is the TLS modid. + */ value = TLSMODID(lmp); - else + } else value = basebgn; name = (char *)0; } + DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, + M_REL_SHT_TYPE, rel, NULL, name)); + /* * If this object has relocations in the text segment, turn * off the write protect. @@ -978,9 +1008,6 @@ elf_reloc(Rt_map *lmp, uint_t plt) /* * Call relocation routine to perform required relocation. */ - DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, - M_REL_SHT_TYPE, rel, NULL, name)); - switch (rtype) { case R_SPARC_REGISTER: /* diff --git a/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c b/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c index a078c7891e..cd54e05fc7 100644 --- a/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c +++ b/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c @@ -1003,11 +1003,23 @@ elf_reloc(Rt_map *lmp, uint_t plt) name = (char *)0; /* - * TLS relocation - value for DTPMOD relocation - * is the TLS modid. + * Special case TLS relocations. */ - if (rtype == M_R_DTPMOD) + if ((rtype == R_SPARC_TLS_DTPMOD32) || + (rtype == R_SPARC_TLS_DTPMOD64)) { + /* + * Use the TLS modid. + */ value = TLSMODID(lmp); + + } else if ((rtype == R_SPARC_TLS_TPOFF32) || + (rtype == R_SPARC_TLS_TPOFF64)) { + if ((value = elf_static_tls(lmp, symref, + rel, rtype, 0, roffset, 0)) == 0) { + ret = 0; + break; + } + } } else { /* * If the symbol index is equal to the previous @@ -1102,6 +1114,10 @@ elf_reloc(Rt_map *lmp, uint_t plt) NAME(lmp)); continue; } else { + DBG_CALL(Dbg_reloc_in(lml, + ELF_DBG_RTLD, M_MACH, + M_REL_SHT_TYPE, rel, + NULL, name)); eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), @@ -1182,33 +1198,52 @@ elf_reloc(Rt_map *lmp, uint_t plt) value -= roffset; /* - * TLS relocation - value for DTPMOD relocation - * is the TLS modid. + * Special case TLS relocations. */ - if (rtype == M_R_DTPMOD) + if ((rtype == R_SPARC_TLS_DTPMOD32) || + (rtype == R_SPARC_TLS_DTPMOD64)) { + /* + * Relocation value is the TLS modid. + */ value = TLSMODID(_lmp); - else if (rtype == M_R_TPOFF) - value = -(TLSSTATOFF(_lmp) - value); + + } else if ((rtype == R_SPARC_TLS_TPOFF64) || + (rtype == R_SPARC_TLS_TPOFF32)) { + if ((value = elf_static_tls(_lmp, + symdef, rel, rtype, name, roffset, + value)) == 0) { + ret = 0; + break; + } + } } } else { /* - * Special cases, a regsiter symbol associated with - * symbol index 0 is initialized (i.e. relocated) to - * a constant in the r_addend field rather than to a - * symbol value. - * - * A DTPMOD relocation is a local binding to a TLS - * symbol. Fill in the TLSMODID for the current object. + * Special cases. */ - if (rtype == R_SPARC_REGISTER) + if (rtype == R_SPARC_REGISTER) { + /* + * A register symbol associated with symbol + * index 0 is initialized (i.e. relocated) to + * a constant in the r_addend field rather than + * to a symbol value. + */ value = 0; - else if (rtype == M_R_DTPMOD) + + } else if ((rtype == R_SPARC_TLS_DTPMOD32) || + (rtype == R_SPARC_TLS_DTPMOD64)) { + /* + * TLS relocation value is the TLS modid. + */ value = TLSMODID(lmp); - else + } else value = basebgn; name = (char *)0; } + DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, + M_REL_SHT_TYPE, rel, NULL, name)); + /* * If this object has relocations in the text segment, turn * off the write protect. @@ -1225,9 +1260,6 @@ elf_reloc(Rt_map *lmp, uint_t plt) /* * Call relocation routine to perform required relocation. */ - DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, - M_REL_SHT_TYPE, rel, NULL, name)); - switch (rtype) { case R_SPARC_REGISTER: /* diff --git a/usr/src/uts/common/krtld/reloc.h b/usr/src/uts/common/krtld/reloc.h index b86c0b576a..c249e3eec6 100644 --- a/usr/src/uts/common/krtld/reloc.h +++ b/usr/src/uts/common/krtld/reloc.h @@ -63,8 +63,8 @@ extern "C" { #define FLG_RE_WDISP16 0x00000100 /* funky sparc DISP16 rel */ #define FLG_RE_SIGN 0x00000200 /* value is signed */ #define FLG_RE_ADDRELATIVE 0x00000400 /* RELATIVE relocation */ - /* required for non-fixed */ - /* objects */ + /* required for non- */ + /* fixed objects */ #define FLG_RE_EXTOFFSET 0x00000800 /* extra offset required */ #define FLG_RE_REGISTER 0x00001000 /* relocation initializes */ /* a REGISTER by OLO10 */ @@ -72,7 +72,7 @@ extern "C" { #define FLG_RE_SEGREL 0x00040000 /* segment relative */ #define FLG_RE_SECREL 0x00080000 /* section relative */ -#define FLG_RE_TLSINS 0x00100000 /* TLS instructino rel */ + #define FLG_RE_TLSGD 0x00200000 /* TLS GD relocation */ #define FLG_RE_TLSLD 0x00400000 /* TLS LD relocation */ #define FLG_RE_TLSIE 0x00800000 /* TLS IE relocation */ @@ -133,7 +133,8 @@ extern const Rel_entry reloc_table[]; #define IS_SEC_RELATIVE(X) ((reloc_table[(X)].re_flags & \ FLG_RE_SECREL) != 0) #define IS_TLS_INS(X) ((reloc_table[(X)].re_flags & \ - FLG_RE_TLSINS) != 0) + (FLG_RE_TLSGD | FLG_RE_TLSLD | \ + FLG_RE_TLSIE | FLG_RE_TLSLE)) != 0) #define IS_TLS_GD(X) ((reloc_table[(X)].re_flags & \ FLG_RE_TLSGD) != 0) #define IS_TLS_LD(X) ((reloc_table[(X)].re_flags & \ @@ -142,10 +143,6 @@ extern const Rel_entry reloc_table[]; FLG_RE_TLSIE) != 0) #define IS_TLS_LE(X) ((reloc_table[(X)].re_flags & \ FLG_RE_TLSLE) != 0) -#define IS_TLS(X) ((reloc_table[(X)].re_flags & \ - (FLG_RE_TLSINS|FLG_RE_TLSGD| \ - FLG_RE_TLSLD|FLG_RE_TLSIE| \ - FLG_RE_TLSLE)) != 0) #define IS_LOCALBND(X) ((reloc_table[(X)].re_flags & \ FLG_RE_LOCLBND) != 0) diff --git a/usr/src/uts/intel/amd64/krtld/doreloc.c b/usr/src/uts/intel/amd64/krtld/doreloc.c index ee88014938..606be961b8 100644 --- a/usr/src/uts/intel/amd64/krtld/doreloc.c +++ b/usr/src/uts/intel/amd64/krtld/doreloc.c @@ -65,14 +65,11 @@ const Rel_entry reloc_table[R_AMD64_NUM] = { /* R_AMD64_DTPMOD64 */ {FLG_RE_NOTREL, 8}, /* R_AMD64_DTPOFF64 */ {FLG_RE_NOTREL, 8}, /* R_AMD64_TPOFF64 */ {FLG_RE_NOTREL, 8}, -/* R_AMD64_TLSGD */ {FLG_RE_GOTPC | FLG_RE_GOTADD | - FLG_RE_TLSINS | FLG_RE_TLSGD, 4}, -/* R_AMD64_TLSLD */ {FLG_RE_GOTPC | FLG_RE_GOTADD | - FLG_RE_TLSINS | FLG_RE_TLSLD, 4}, -/* R_AMD64_DTPOFF32 */ {FLG_RE_TLSINS | FLG_RE_TLSLD, 4}, -/* R_AMD64_GOTTPOFF */ {FLG_RE_GOTPC | FLG_RE_GOTADD | - FLG_RE_TLSINS | FLG_RE_TLSIE, 4}, -/* R_AMD64_TPOFF32 */ {FLG_RE_TLSINS | FLG_RE_TLSLE, 4}, +/* R_AMD64_TLSGD */ {FLG_RE_GOTPC | FLG_RE_GOTADD | FLG_RE_TLSGD, 4}, +/* R_AMD64_TLSLD */ {FLG_RE_GOTPC | FLG_RE_GOTADD | FLG_RE_TLSLD, 4}, +/* R_AMD64_DTPOFF32 */ {FLG_RE_TLSLD, 4}, +/* R_AMD64_GOTTPOFF */ {FLG_RE_GOTPC | FLG_RE_GOTADD | FLG_RE_TLSIE, 4}, +/* R_AMD64_TPOFF32 */ {FLG_RE_TLSLE, 4}, /* R_AMD64_PC64 */ {FLG_RE_PCREL, 8}, /* R_AMD64_GOTOFF64 */ {FLG_RE_GOTREL, 8}, /* R_AMD64_GOTPC32 */ {FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_LOCLBND, 4}, diff --git a/usr/src/uts/intel/amd64/krtld/kobj_reloc.c b/usr/src/uts/intel/amd64/krtld/kobj_reloc.c index f2033e5223..5cf7541f13 100644 --- a/usr/src/uts/intel/amd64/krtld/kobj_reloc.c +++ b/usr/src/uts/intel/amd64/krtld/kobj_reloc.c @@ -158,7 +158,7 @@ do_relocate(struct module *mp, char *reltbl, Word relshtype, int nreloc, symnum); return (-1); } - if ((rtype > R_AMD64_NUM) || IS_TLS(rtype)) { + if ((rtype > R_AMD64_NUM) || IS_TLS_INS(rtype)) { _kobj_printf(ops, "krtld: invalid relocation type %d", rtype); _kobj_printf(ops, " at 0x%llx:", off); diff --git a/usr/src/uts/intel/ia32/krtld/doreloc.c b/usr/src/uts/intel/ia32/krtld/doreloc.c index 0fc1d362a3..c3bb0d8ed1 100644 --- a/usr/src/uts/intel/ia32/krtld/doreloc.c +++ b/usr/src/uts/intel/ia32/krtld/doreloc.c @@ -57,16 +57,14 @@ const Rel_entry reloc_table[R_386_NUM] = { /* R_386_GOTOFF */ {FLG_RE_GOTREL, 4}, /* R_386_GOTPC */ {FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_LOCLBND, 4}, /* R_386_32PLT */ {FLG_RE_PLTREL, 4}, -/* R_386_TLS_GD_PLT */ {FLG_RE_TLSINS | FLG_RE_PLTREL | - FLG_RE_PCREL | FLG_RE_TLSGD, 4}, -/* R_386_TLS_LDM_PLT */ {FLG_RE_TLSINS | FLG_RE_PLTREL | - FLG_RE_PCREL | FLG_RE_TLSLD, 4}, +/* R_386_TLS_GD_PLT */ {FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_TLSGD, 4}, +/* R_386_TLS_LDM_PLT */ {FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_TLSLD, 4}, /* R_386_TLS_TPOFF */ {FLG_RE_NOTREL, 4}, -/* R_386_TLS_IE */ {FLG_RE_GOTADD | FLG_RE_TLSINS | FLG_RE_TLSIE, 4}, -/* R_386_TLS_GOTIE */ {FLG_RE_GOTADD | FLG_RE_TLSINS | FLG_RE_TLSIE, 4}, -/* R_386_TLS_LE */ {FLG_RE_TLSINS | FLG_RE_TLSLE, 4}, -/* R_386_TLS_GD */ {FLG_RE_GOTADD | FLG_RE_TLSINS | FLG_RE_TLSGD, 4}, -/* R_386_TLS_LDM */ {FLG_RE_GOTADD | FLG_RE_TLSLD | FLG_RE_TLSINS, 4}, +/* R_386_TLS_IE */ {FLG_RE_GOTADD | FLG_RE_TLSIE, 4}, +/* R_386_TLS_GOTIE */ {FLG_RE_GOTADD | FLG_RE_TLSIE, 4}, +/* R_386_TLS_LE */ {FLG_RE_TLSLE, 4}, +/* R_386_TLS_GD */ {FLG_RE_GOTADD | FLG_RE_TLSGD, 4}, +/* R_386_TLS_LDM */ {FLG_RE_GOTADD | FLG_RE_TLSLD, 4}, /* R_386_16 */ {FLG_RE_NOTREL, 2}, /* R_386_PC16 */ {FLG_RE_PCREL, 2}, /* R_386_8 */ {FLG_RE_NOTREL, 1}, @@ -79,7 +77,7 @@ const Rel_entry reloc_table[R_386_NUM] = { /* R_386_UNKNOWN29 */ {FLG_RE_NOTSUP, 0}, /* R_386_UNKNOWN30 */ {FLG_RE_NOTSUP, 0}, /* R_386_UNKNOWN31 */ {FLG_RE_NOTSUP, 0}, -/* R_386_TLS_LDO_32 */ {FLG_RE_TLSINS | FLG_RE_TLSLD, 4}, +/* R_386_TLS_LDO_32 */ {FLG_RE_TLSLD, 4}, /* R_386_UNKNOWN33 */ {FLG_RE_NOTSUP, 0}, /* R_386_UNKNOWN34 */ {FLG_RE_NOTSUP, 0}, /* R_386_TLS_DTPMOD32 */ {FLG_RE_NOTREL, 4}, diff --git a/usr/src/uts/intel/ia32/krtld/kobj_reloc.c b/usr/src/uts/intel/ia32/krtld/kobj_reloc.c index 547bf9ce9c..53955cf08d 100644 --- a/usr/src/uts/intel/ia32/krtld/kobj_reloc.c +++ b/usr/src/uts/intel/ia32/krtld/kobj_reloc.c @@ -155,7 +155,7 @@ do_relocate(struct module *mp, char *reltbl, Word relshtype, int nreloc, symnum); return (-1); } - if ((rtype > R_386_NUM) || IS_TLS(rtype)) { + if ((rtype > R_386_NUM) || IS_TLS_INS(rtype)) { _kobj_printf(ops, "krtld: invalid relocation type %d", rtype); _kobj_printf(ops, " at 0x%llx:", off); diff --git a/usr/src/uts/sparc/krtld/doreloc.c b/usr/src/uts/sparc/krtld/doreloc.c index 7b98eee72a..70ddf91e3c 100644 --- a/usr/src/uts/sparc/krtld/doreloc.c +++ b/usr/src/uts/sparc/krtld/doreloc.c @@ -140,35 +140,28 @@ const Rel_entry reloc_table[R_SPARC_NUM] = { 8, 0, 0}, /* V9 */ /* R_SPARC_UA16 */ {0x0, FLG_RE_VERIFY | FLG_RE_UNALIGN, 2, 0, 0}, -/* R_SPARC_TLS_GD_HI22 */ {0x0, FLG_RE_GOTADD | FLG_RE_TLSINS | FLG_RE_TLSGD, - 4, 10, 22}, -/* R_SPARC_TLS_GD_LO10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSINS | - FLG_RE_TLSGD | FLG_RE_SIGN, 4, 0, 13}, -/* R_SPARC_TLS_GD_ADD */ {0x0, FLG_RE_TLSINS | FLG_RE_TLSGD, 0, 0, 0}, -/* R_SPARC_TLS_GD_CALL */ {0x0, FLG_RE_TLSINS | FLG_RE_TLSGD, 0, 0, 0}, -/* R_SPARC_TLS_LDM_HI22 */ {0x0, FLG_RE_GOTADD | FLG_RE_TLSINS | FLG_RE_TLSLD, - 4, 10, 22}, -/* R_SPARC_TLS_LDM_LO10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSINS | - FLG_RE_TLSLD | FLG_RE_SIGN, 4, 0, 13}, -/* R_SPARC_TLS_LDM_ADD */ {0x0, FLG_RE_TLSINS | FLG_RE_TLSLD, 0, 0, 0}, -/* R_SPARC_TLS_LDM_CALL */ {0x0, FLG_RE_TLSINS | FLG_RE_TLSLD, 0, 0, 0}, -/* R_SPARC_TLS_LDO_HIX22 */ {0x0, FLG_RE_VERIFY | FLG_RE_TLSINS | FLG_RE_TLSLD, - 4, 10, 22}, -/* R_SPARC_TLS_LDO_LOX10 */ {0x3ff, FLG_RE_TLSINS | FLG_RE_SIGN | FLG_RE_TLSLD, - 4, 0, 13}, -/* R_SPARC_TLS_LDO_ADD */ {0x0, FLG_RE_TLSINS | FLG_RE_TLSLD, 0, 0, 0}, -/* R_SPARC_TLS_IE_HI22 */ {0x0, FLG_RE_TLSINS | FLG_RE_GOTADD | FLG_RE_TLSIE, - 4, 10, 22}, -/* R_SPARC_TLS_IE_LO10 */ {0x3ff, FLG_RE_TLSINS | FLG_RE_GOTADD | - FLG_RE_TLSIE | FLG_RE_SIGN, 4, 0, 13}, -/* R_SPARC_TLS_IE_LD */ {0x0, FLG_RE_TLSINS | FLG_RE_TLSIE, 0, 0, 0}, -/* R_SPARC_TLS_IE_LDX */ {0x0, FLG_RE_TLSINS | FLG_RE_TLSIE, 0, 0, 0}, -/* R_SPARC_TLS_IE_ADD */ {0x0, FLG_RE_TLSINS | FLG_RE_TLSIE, 0, 0, 0}, +/* R_SPARC_TLS_GD_HI22 */ {0x0, FLG_RE_GOTADD | FLG_RE_TLSGD, 4, 10, 22}, +/* R_SPARC_TLS_GD_LO10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSGD | + FLG_RE_SIGN, 4, 0, 13}, +/* R_SPARC_TLS_GD_ADD */ {0x0, FLG_RE_TLSGD, 0, 0, 0}, +/* R_SPARC_TLS_GD_CALL */ {0x0, FLG_RE_TLSGD, 0, 0, 0}, +/* R_SPARC_TLS_LDM_HI22 */ {0x0, FLG_RE_GOTADD | FLG_RE_TLSLD, 4, 10, 22}, +/* R_SPARC_TLS_LDM_LO10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSLD | + FLG_RE_SIGN, 4, 0, 13}, +/* R_SPARC_TLS_LDM_ADD */ {0x0, FLG_RE_TLSLD, 0, 0, 0}, +/* R_SPARC_TLS_LDM_CALL */ {0x0, FLG_RE_TLSLD, 0, 0, 0}, +/* R_SPARC_TLS_LDO_HIX22 */ {0x0, FLG_RE_VERIFY | FLG_RE_TLSLD, 4, 10, 22}, +/* R_SPARC_TLS_LDO_LOX10 */ {0x3ff, FLG_RE_SIGN | FLG_RE_TLSLD, 4, 0, 13}, +/* R_SPARC_TLS_LDO_ADD */ {0x0, FLG_RE_TLSLD, 0, 0, 0}, +/* R_SPARC_TLS_IE_HI22 */ {0x0, FLG_RE_GOTADD | FLG_RE_TLSIE, 4, 10, 22}, +/* R_SPARC_TLS_IE_LO10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSIE | + FLG_RE_SIGN, 4, 0, 13}, +/* R_SPARC_TLS_IE_LD */ {0x0, FLG_RE_TLSIE, 0, 0, 0}, +/* R_SPARC_TLS_IE_LDX */ {0x0, FLG_RE_TLSIE, 0, 0, 0}, +/* R_SPARC_TLS_IE_ADD */ {0x0, FLG_RE_TLSIE, 0, 0, 0}, /* R_SPARC_TLS_LE_HIX22 */ {(Xword)(-1LL), - FLG_RE_VERIFY | FLG_RE_TLSINS | FLG_RE_TLSLE, - 4, 10, 22}, -/* R_SPARC_TLS_LE_LOX10 */ {0x3ff, FLG_RE_TLSINS | FLG_RE_SIGN | FLG_RE_TLSLE, - 4, 0, 13}, + FLG_RE_VERIFY | FLG_RE_TLSLE, 4, 10, 22}, +/* R_SPARC_TLS_LE_LOX10 */ {0x3ff, FLG_RE_SIGN | FLG_RE_TLSLE, 4, 0, 13}, /* R_SPARC_TLS_DTPMOD32 */ {0x0, FLG_RE_NOTREL, 4, 0, 0}, /* R_SPARC_TLS_DTPMOD64 */ {0x0, FLG_RE_NOTREL, 8, 0, 0}, /* R_SPARC_TLS_DTPOFF32 */ {0x0, FLG_RE_NOTREL, 4, 0, 0}, diff --git a/usr/src/uts/sparc/krtld/kobj_reloc.c b/usr/src/uts/sparc/krtld/kobj_reloc.c index 12d2a19d5a..fd3846a383 100644 --- a/usr/src/uts/sparc/krtld/kobj_reloc.c +++ b/usr/src/uts/sparc/krtld/kobj_reloc.c @@ -212,7 +212,7 @@ do_relocate( "do_relocate: bad strndx %d\n", symnum); return (-1); } - if ((rtype > R_SPARC_NUM) || IS_TLS(rtype)) { + if ((rtype > R_SPARC_NUM) || IS_TLS_INS(rtype)) { _kobj_printf(ops, "krtld: invalid relocation type %d", rtype); _kobj_printf(ops, " at 0x%llx:", off); |