diff options
author | Rod Evans <Rod.Evans@Sun.COM> | 2010-05-26 10:36:21 -0700 |
---|---|---|
committer | Rod Evans <Rod.Evans@Sun.COM> | 2010-05-26 10:36:21 -0700 |
commit | 02938ba214e4690cccd8cbd233d1242246ef6ff1 (patch) | |
tree | fc04855e7dda45ec3d18970b303eecf7cfe3cf3d /usr/src | |
parent | 214c21966e601d9d9946efda70b0d87b019d10dc (diff) | |
download | illumos-joyent-02938ba214e4690cccd8cbd233d1242246ef6ff1.tar.gz |
6949596 wrong section alignment generated in joint compilation with shared library
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/sgs/include/debug.h | 6 | ||||
-rw-r--r-- | usr/src/cmd/sgs/ldd/common/ldd.c | 2 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/relocate.c | 77 | ||||
-rw-r--r-- | usr/src/cmd/sgs/liblddbg/common/liblddbg.msg | 4 | ||||
-rw-r--r-- | usr/src/cmd/sgs/liblddbg/common/llib-llddbg | 4 | ||||
-rw-r--r-- | usr/src/cmd/sgs/liblddbg/common/mapfile-vers | 6 | ||||
-rw-r--r-- | usr/src/cmd/sgs/liblddbg/common/syms.c | 18 | ||||
-rw-r--r-- | usr/src/cmd/sgs/packages/common/SUNWonld-README | 6 | ||||
-rw-r--r-- | usr/src/cmd/sgs/rtld/common/dlfcns.c | 14 |
9 files changed, 105 insertions, 32 deletions
diff --git a/usr/src/cmd/sgs/include/debug.h b/usr/src/cmd/sgs/include/debug.h index 0e13600956..9544cfec4c 100644 --- a/usr/src/cmd/sgs/include/debug.h +++ b/usr/src/cmd/sgs/include/debug.h @@ -458,6 +458,7 @@ extern void Dbg_help(void); #define Dbg_syms_cap_local Dbg64_syms_cap_local #define Dbg_syms_cap_lookup Dbg64_syms_cap_lookup #define Dbg_syms_cap_title Dbg64_syms_cap_title +#define Dbg_syms_copy_reloc Dbg64_syms_copy_reloc #define Dbg_syms_created Dbg64_syms_created #define Dbg_syms_discarded Dbg64_syms_discarded #define Dbg_syms_dup_discarded Dbg64_syms_dup_discarded @@ -473,7 +474,6 @@ extern void Dbg_help(void); #define Dbg_syms_old Dbg64_syms_old #define Dbg_syms_process Dbg64_syms_process #define Dbg_syms_reduce Dbg64_syms_reduce -#define Dbg_syms_reloc Dbg64_syms_reloc #define Dbg_syms_resolved Dbg64_syms_resolved #define Dbg_syms_resolving Dbg64_syms_resolving #define Dbg_syms_sec_entry Dbg64_syms_sec_entry @@ -690,6 +690,7 @@ extern void Dbg_help(void); #define Dbg_syms_cap_local Dbg32_syms_cap_local #define Dbg_syms_cap_lookup Dbg32_syms_cap_lookup #define Dbg_syms_cap_title Dbg32_syms_cap_title +#define Dbg_syms_copy_reloc Dbg32_syms_copy_reloc #define Dbg_syms_created Dbg32_syms_created #define Dbg_syms_discarded Dbg32_syms_discarded #define Dbg_syms_dup_discarded Dbg32_syms_dup_discarded @@ -706,7 +707,6 @@ extern void Dbg_help(void); #define Dbg_syms_old Dbg32_syms_old #define Dbg_syms_process Dbg32_syms_process #define Dbg_syms_reduce Dbg32_syms_reduce -#define Dbg_syms_reloc Dbg32_syms_reloc #define Dbg_syms_resolved Dbg32_syms_resolved #define Dbg_syms_resolving Dbg32_syms_resolving #define Dbg_syms_sec_entry Dbg32_syms_sec_entry @@ -981,6 +981,7 @@ extern void Dbg_syms_cap_local(Ofl_desc *, Word, const char *, Sym *, extern void Dbg_syms_cap_lookup(Rt_map *, uint_t, const char *, uint_t, Half, Syscapset *); extern void Dbg_syms_cap_title(Ofl_desc *); +extern void Dbg_syms_copy_reloc(Ofl_desc *, Sym_desc *, Word); extern void Dbg_syms_created(Lm_list *, const char *); extern void Dbg_syms_discarded(Lm_list *, Sym_desc *); extern void Dbg_syms_dup_discarded(Lm_list *, Word ndx, Sym_desc *); @@ -1001,7 +1002,6 @@ extern void Dbg_syms_old(Ofl_desc *, Sym_desc *); extern void Dbg_syms_process(Lm_list *, Ifl_desc *); extern void Dbg_syms_reduce(Ofl_desc *, int, Sym_desc *, int, const char *); -extern void Dbg_syms_reloc(Ofl_desc *, Sym_desc *); extern void Dbg_syms_resolved(Ofl_desc *, Sym_desc *); extern void Dbg_syms_resolving(Ofl_desc *, Word, const char *, int, int, Sym *, Sym *, Sym_desc *, Ifl_desc *); diff --git a/usr/src/cmd/sgs/ldd/common/ldd.c b/usr/src/cmd/sgs/ldd/common/ldd.c index 1c9ded6026..27d7ce74f8 100644 --- a/usr/src/cmd/sgs/ldd/common/ldd.c +++ b/usr/src/cmd/sgs/ldd/common/ldd.c @@ -29,7 +29,7 @@ * Print the list of shared objects required by a dynamic executable or shared * object. * - * usage is: ldd [-d | -r] [-D] [-c] [-e envar] [-i] [-f] [-L] [-l] [-p] [-s] + * usage is: ldd [-d | -r] [-c] [-D] [-e envar] [-i] [-f] [-L] [-l] [-p] [-s] * [-U | -u] [-v] [-w] file(s) * * ldd opens the file and verifies the information in the elf header. diff --git a/usr/src/cmd/sgs/libld/common/relocate.c b/usr/src/cmd/sgs/libld/common/relocate.c index 5c2ca2b711..64cc687204 100644 --- a/usr/src/cmd/sgs/libld/common/relocate.c +++ b/usr/src/cmd/sgs/libld/common/relocate.c @@ -1007,6 +1007,22 @@ ld_reloc_plt(Rel_desc *rsp, Ofl_desc *ofl) } /* + * Round up to the next power of 2. Used to ensure section alignments that can + * be used for copy relocation symbol alignments are sane values. + */ +static Word +nlpo2(Word val) +{ + val--; + val |= (val >> 1); + val |= (val >> 2); + val |= (val >> 4); + val |= (val >> 8); + val |= (val >> 16); + return (++val); +} + +/* * process GLOBAL undefined and ref_dyn_need symbols. */ static uintptr_t @@ -1056,7 +1072,7 @@ reloc_exec(Rel_desc *rsp, Ofl_desc *ofl) /* * If the reference isn't to an object (normally because a .type - * directive hasn't defined in some assembler source), then simply apply + * directive wasn't defined in some assembler source), then apply * a generic relocation (this has a tendency to result in text * relocations). */ @@ -1074,7 +1090,7 @@ reloc_exec(Rel_desc *rsp, Ofl_desc *ofl) /* * Prepare for generating a copy relocation. * - * If this symbol is one of an alias pair, we need to insure both + * If this symbol is one of an alias pair, we need to ensure both * symbols become part of the output (the strong symbol will be used to * maintain the symbols state). And, if we did raise the precedence of * a symbol we need to check and see if this is a weak symbol. If it is @@ -1131,10 +1147,16 @@ reloc_exec(Rel_desc *rsp, Ofl_desc *ofl) * to the executables .bss at runtime. */ if (!(RELAUX_GET_USYM(rsp)->sd_flags & FLG_SY_MVTOCOMM)) { - Word rtype = rsp->rel_rtype; + Word rtype = rsp->rel_rtype, w2align; Copy_rel cr; /* + * Diagnose the original copy reference, as this symbol + * information will be overridden with the new destination. + */ + DBG_CALL(Dbg_syms_copy_reloc(ofl, sdp, 0)); + + /* * Indicate that the symbol(s) against which we're relocating * have been moved to the executables common. Also, insure that * the symbol(s) remain marked as global, as the shared object @@ -1171,9 +1193,7 @@ reloc_exec(Rel_desc *rsp, Ofl_desc *ofl) } /* - * Assign the symbol to the bss and insure sufficient alignment - * (we don't know the real alignment so we have to make the - * worst case guess). + * Assign the symbol to the bss. */ _sdp = RELAUX_GET_USYM(rsp); stval = _sdp->sd_sym->st_value; @@ -1181,9 +1201,37 @@ reloc_exec(Rel_desc *rsp, Ofl_desc *ofl) return (S_ERROR); _sdp->sd_shndx = _sdp->sd_sym->st_shndx = SHN_COMMON; _sdp->sd_flags |= FLG_SY_SPECSEC; - _sdp->sd_sym->st_value = - (_sdp->sd_sym->st_size < (ld_targ.t_m.m_word_align * 2)) ? - ld_targ.t_m.m_word_align : ld_targ.t_m.m_word_align * 2; + + /* + * Ensure the symbol has sufficient alignment. The symbol + * definition has no alignment information that can be used, + * hence we use a heuristic. Historically, twice the native + * word alignment was sufficient for any data type, however, + * the developer may have requested larger alignments (pragma + * align). The most conservative approach is to use a power + * of two alignment, determined from the alignment of the + * section containing the symbol definition. Note that this + * can result in some bloat to the .bss as the not every item + * of copied data might need the section alignment. + * + * COMMON symbols carry their alignment requirements in the + * symbols st_value field. This alignment is applied to the + * symbol when it is eventually transformed into .bss. + */ + w2align = ld_targ.t_m.m_word_align * 2; + if (_sdp->sd_sym->st_size < w2align) + _sdp->sd_sym->st_value = ld_targ.t_m.m_word_align; + else { + Shdr *shdr; + Word isalign; + + if (_sdp->sd_isc && + ((shdr = _sdp->sd_isc->is_shdr) != NULL) && + ((isalign = shdr->sh_addralign) != 0)) + _sdp->sd_sym->st_value = nlpo2(isalign); + else + _sdp->sd_sym->st_value = w2align; + } /* * Whether or not the symbol references initialized data we @@ -1213,7 +1261,13 @@ reloc_exec(Rel_desc *rsp, Ofl_desc *ofl) rsp->rel_rtype = rtype; /* - * If this symbol is a protected symbol, warn it. + * If this symbol is a protected symbol, warn the user. A + * potential issue exists as the copy relocated symbol within + * the executable can be visible to others, whereas the shared + * object that defined the original copy data symbol is pre- + * bound to reference it's own definition. Any modification + * of the symbols data could lead to inconsistencies for the + * various users. */ if (_sdp->sd_flags & FLG_SY_PROT) { Conv_inv_buf_t inv_buf; @@ -1224,7 +1278,8 @@ reloc_exec(Rel_desc *rsp, Ofl_desc *ofl) ld_targ.t_m.m_r_copy, 0, &inv_buf), _sdp->sd_file->ifl_name, _sdp->sd_name); } - DBG_CALL(Dbg_syms_reloc(ofl, sdp)); + DBG_CALL(Dbg_syms_copy_reloc(ofl, _sdp, + _sdp->sd_sym->st_value)); } return (ld_add_actrel(NULL, rsp, ofl)); } diff --git a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg index b4222142e0..d24d241be1 100644 --- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg +++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg @@ -975,6 +975,8 @@ (-z symbolcap)" @ MSG_SYM_CAP_LOCAL "symbol[%d]=%s creating local capability \ (-z symbolcap)" +@ MSG_SYM_COPY_DST "symbol=%s; copy destination: alignment: 0x%x" +@ MSG_SYM_COPY_REF "symbol=%s; copy reference" @ MSG_SYM_AOUT "symbol=%s; (original AOUT name)" @ MSG_SYM_LOOKUP "symbol=%s; lookup in file=%s [ %s ]" @@ -1592,7 +1594,7 @@ @ MSG_SYM_GLOBAL "global" @ MSG_SYM_LOCAL "local" -@ MSG_SYM_COPY "copy rel" +@ MSG_SYM_COPY "copy" @ MSG_DLSYM_NEXT "[ RTLD_NEXT ]" @ MSG_DLSYM_DEFAULT "[ RTLD_DEFAULT ]" diff --git a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg index d642fbc66a..9c090f2571 100644 --- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg +++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg @@ -419,6 +419,8 @@ void Dbg64_syms_cap_lookup(Rt_map *, uint_t, const char *, uint_t, Half, Syscapset *); void Dbg32_syms_cap_title(Ofl_desc *); void Dbg64_syms_cap_title(Ofl_desc *); +void Dbg32_syms_copy_reloc(Ofl_desc *, Sym_desc *, Word); +void Dbg64_syms_copy_reloc(Ofl_desc *, Sym_desc *, Word); void Dbg32_syms_created(Lm_list *, const char *); void Dbg64_syms_created(Lm_list *, const char *); void Dbg32_syms_discarded(Lm_list *, Sym_desc *); @@ -444,8 +446,6 @@ void Dbg32_syms_process(Lm_list *, Ifl_desc *); void Dbg64_syms_process(Lm_list *, Ifl_desc *); void Dbg32_syms_reduce(Ofl_desc *, int, Sym_desc *, int, const char *); void Dbg64_syms_reduce(Ofl_desc *, int, Sym_desc *, int, const char *); -void Dbg32_syms_reloc(Ofl_desc *, Sym_desc *); -void Dbg64_syms_reloc(Ofl_desc *, Sym_desc *); void Dbg32_syms_resolved(Ofl_desc *, Sym_desc *); void Dbg64_syms_resolved(Ofl_desc *, Sym_desc *); void Dbg32_syms_resolving(Ofl_desc *, Elf32_Word, const char *, int, int, diff --git a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers index 5adf699ee4..ad9fa30e92 100644 --- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers +++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers @@ -40,7 +40,7 @@ # MAPFILE HEADER END # -SUNWprivate_4.79 { +SUNWprivate_4.80 { global: dbg_desc = NODIRECT; # interposed - ld.so.1(1) dbg_print = NODIRECT; # interposed - ld(1) and ld.so.1(1) @@ -398,6 +398,8 @@ SUNWprivate_4.79 { Dbg64_syms_cap_lookup; Dbg32_syms_cap_title; Dbg64_syms_cap_title; + Dbg32_syms_copy_reloc; + Dbg64_syms_copy_reloc; Dbg32_syms_created; Dbg64_syms_created; Dbg32_syms_discarded; @@ -429,8 +431,6 @@ SUNWprivate_4.79 { Dbg64_syms_process; Dbg32_syms_reduce; Dbg64_syms_reduce; - Dbg32_syms_reloc; - Dbg64_syms_reloc; Dbg32_syms_resolved; Dbg64_syms_resolved; Dbg32_syms_resolving; diff --git a/usr/src/cmd/sgs/liblddbg/common/syms.c b/usr/src/cmd/sgs/liblddbg/common/syms.c index 3fffd6eb7b..3083eec1fa 100644 --- a/usr/src/cmd/sgs/liblddbg/common/syms.c +++ b/usr/src/cmd/sgs/liblddbg/common/syms.c @@ -481,7 +481,7 @@ Dbg_syms_resolved(Ofl_desc *ofl, Sym_desc *sdp) } void -Dbg_syms_reloc(Ofl_desc *ofl, Sym_desc *sdp) +Dbg_syms_copy_reloc(Ofl_desc *ofl, Sym_desc *sdp, Word align) { static Boolean symbol_title = TRUE; Conv_inv_buf_t inv_buf; @@ -496,8 +496,20 @@ Dbg_syms_reloc(Ofl_desc *ofl, Sym_desc *sdp) symbol_title = FALSE; } - dbg_print(lml, MSG_INTL(MSG_SYM_UPDATE), - Dbg_demangle_name(sdp->sd_name)); + + /* + * Copy relocation symbols come in pairs, the original reference + * (within a dependency), and the new destination (within the .bss of + * the executable). The latter is accompanied with a computed + * alignment. + */ + if (align) { + dbg_print(lml, MSG_INTL(MSG_SYM_COPY_DST), + Dbg_demangle_name(sdp->sd_name), EC_WORD(align)); + } else { + dbg_print(lml, MSG_INTL(MSG_SYM_COPY_REF), + Dbg_demangle_name(sdp->sd_name)); + } if (DBG_NOTDETAIL()) return; diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README index c275915fb5..ec62f28dc2 100644 --- a/usr/src/cmd/sgs/packages/common/SUNWonld-README +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README @@ -1295,6 +1295,8 @@ Bugid Risk Synopsis when mmap fails in anon_map() 6826513 ldd gets confused by a crle(1) LD_PRELOAD setting 6684577 ld should propagate SHF_LINK_ORDER flag to ET_REL objects +6524709 executables using /usr/lib/libc.so.1 as the ELF interpreter dump core + (link-editor components only) -------------------------------------------------------------------------------- All the above changes are incorporated in the following patches: Solaris/SunOS 5.10_sparc patch T143895-01 @@ -1342,8 +1344,6 @@ Bugid Risk Synopsis PSARC/2007/074 -L option for nm(1) to display SHT_SUNW_LDYNSYM symbols 6523787 dlopen() handle gets mistakenly orphaned - results in access to freed memory -6524709 executables using /usr/lib/libc.so.1 as the ELF interpreter dump core - (link-editor components only) 6531189 SEGV in dladdr() 6527318 dlopen(name, RTLD_NOLOAD) returns handle for unloaded library 6518359 extern mapfiles references to _init/_fini can create INIT/FINI @@ -1590,3 +1590,5 @@ Bugid Risk Synopsis 6943432 dlsym(RTLD_PROBE) should only bind to symbol definitions 6668759 an external method for determining whether an ELF dependency is optional 6954032 Support library with ld_open and -z allextract in snv_139 do not mix +6949596 wrong section alignment generated in joint compilation with shared + library diff --git a/usr/src/cmd/sgs/rtld/common/dlfcns.c b/usr/src/cmd/sgs/rtld/common/dlfcns.c index 592d0cb96c..06920e6b59 100644 --- a/usr/src/cmd/sgs/rtld/common/dlfcns.c +++ b/usr/src/cmd/sgs/rtld/common/dlfcns.c @@ -1542,12 +1542,14 @@ dladdr_core(Rt_map *almp, void *addr, Dl_info_t *dlip, void **info, int flags) int dladdr(void *addr, Dl_info_t *dlip) { - int entry, error; + int entry, ret; Rt_map *clmp, *almp; + Lm_list *clml; entry = enter(0); clmp = _caller(caller(), CL_EXECDEF); + clml = LIST(clmp); DBG_CALL(Dbg_dl_dladdr(clmp, addr)); @@ -1557,17 +1559,17 @@ dladdr(void *addr, Dl_info_t *dlip) * indicate the failure. */ if ((almp = _caller(addr, CL_NONE)) == NULL) { - eprintf(LIST(clmp), ERR_FATAL, MSG_INTL(MSG_ARG_INVADDR), + eprintf(clml, ERR_FATAL, MSG_INTL(MSG_ARG_INVADDR), EC_NATPTR(addr)); - error = 0; + ret = 0; } else { dladdr_core(almp, addr, dlip, 0, 0); - error = 1; + ret = 1; } if (entry) - leave(0, 0); - return (error); + leave(clml, 0); + return (ret); } #pragma weak _dladdr1 = dladdr1 |