summaryrefslogtreecommitdiff
path: root/usr/src/cmd/sgs/libld/common/relocate.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/sgs/libld/common/relocate.c')
-rw-r--r--usr/src/cmd/sgs/libld/common/relocate.c77
1 files changed, 66 insertions, 11 deletions
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));
}