summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorRod Evans <Rod.Evans@Sun.COM>2010-05-26 10:36:21 -0700
committerRod Evans <Rod.Evans@Sun.COM>2010-05-26 10:36:21 -0700
commit02938ba214e4690cccd8cbd233d1242246ef6ff1 (patch)
treefc04855e7dda45ec3d18970b303eecf7cfe3cf3d /usr/src
parent214c21966e601d9d9946efda70b0d87b019d10dc (diff)
downloadillumos-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.h6
-rw-r--r--usr/src/cmd/sgs/ldd/common/ldd.c2
-rw-r--r--usr/src/cmd/sgs/libld/common/relocate.c77
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/liblddbg.msg4
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/llib-llddbg4
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/mapfile-vers6
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/syms.c18
-rw-r--r--usr/src/cmd/sgs/packages/common/SUNWonld-README6
-rw-r--r--usr/src/cmd/sgs/rtld/common/dlfcns.c14
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