summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/cmd/sgs/elfdump/common/elfdump.c34
-rw-r--r--usr/src/cmd/sgs/elfdump/common/elfdump.msg15
-rw-r--r--usr/src/cmd/sgs/libld/amd64/machrel.c222
-rw-r--r--usr/src/cmd/sgs/libld/common/_libld.h5
-rw-r--r--usr/src/cmd/sgs/libld/common/relocate.c194
-rw-r--r--usr/src/cmd/sgs/libld/i386/machrel.c247
-rw-r--r--usr/src/cmd/sgs/libld/sparc/machrel.c199
-rw-r--r--usr/src/cmd/sgs/packages/common/SUNWonld-README2
-rw-r--r--usr/src/uts/common/krtld/reloc.h7
-rw-r--r--usr/src/uts/sparc/krtld/doreloc.c17
10 files changed, 430 insertions, 512 deletions
diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.c b/usr/src/cmd/sgs/elfdump/common/elfdump.c
index 0ad3884bee..c5d3315b60 100644
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.c
+++ b/usr/src/cmd/sgs/elfdump/common/elfdump.c
@@ -19,8 +19,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -346,6 +347,19 @@ sections(const char *file, Cache *cache, GElf_Word shnum, GElf_Word phnum,
sname = MSG_ORIG(MSG_STR_EMPTY);
}
+ /*
+ * Identify any sections that are suspicious. A .got section
+ * shouldn't exist in a relocatable object.
+ */
+ if (ehdr->e_type == ET_REL) {
+ if (strncmp(sname, MSG_ORIG(MSG_ELF_GOT),
+ MSG_ELF_GOT_SIZE) == 0) {
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_GOT_UNEXPECTED), file, sname);
+ (void) fflush(stderr);
+ }
+ }
+
dbg_print(MSG_ORIG(MSG_STR_EMPTY));
/* LINTED */
dbg_print(MSG_INTL(MSG_ELF_SHDR), (uint_t)cnt, sname);
@@ -2138,7 +2152,8 @@ hash(Cache *cache, GElf_Word shnum, const char *name, const char *file,
if (_cnt >= MAXCOUNT) {
(void) fprintf(stderr,
- MSG_INTL(MSG_HASH_OVERFLW),
+ MSG_INTL(MSG_HASH_OVERFLW), file,
+ _cache->c_name,
/* LINTED */
(int)ndx, _cnt);
(void) fflush(stderr);
@@ -2295,17 +2310,28 @@ got(Cache *cache, GElf_Word shnum, GElf_Word phnum, GElf_Ehdr *ehdr,
GElf_Xword gsymaddr;
/*
- * First we find the got
+ * First, find the got.
*/
for (cnt = 1; cnt < shnum; cnt++) {
_cache = &cache[cnt];
- if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT), 4) == 0) {
+ if (strncmp(_cache->c_name, MSG_ORIG(MSG_ELF_GOT),
+ MSG_ELF_GOT_SIZE) == 0) {
gotcache = _cache;
break;
}
}
if (!gotcache)
return;
+
+ /*
+ * A got section within a relocatable object is suspicious.
+ */
+ if (ehdr->e_type == ET_REL) {
+ (void) fprintf(stderr, MSG_INTL(MSG_GOT_UNEXPECTED), file,
+ _cache->c_name);
+ (void) fflush(stderr);
+ }
+
gotshdr = &gotcache->c_shdr;
gotbgn = gotshdr->sh_addr;
diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.msg b/usr/src/cmd/sgs/elfdump/common/elfdump.msg
index 99fe4591e7..4e1be11685 100644
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg
+++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg
@@ -1,7 +1,4 @@
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
@@ -22,6 +19,11 @@
#
# CDDL HEADER END
#
+
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
# ident "%Z%%M% %I% %E% SMI"
@ _START_
@@ -147,16 +149,19 @@
@ MSG_ELF_HASH_BKTS1 "%10.10s buckets contain %8d symbols"
@ MSG_ELF_HASH_BKTS2 "%10.10s buckets %8d symbols (globals)"
@ MSG_ELF_HASH_INFO " bucket symndx name"
-@ MSG_HASH_OVERFLW "warning: too many symbols to count, bucket=%d count=%d"
+@ MSG_HASH_OVERFLW "%s: warning: section %s: too many symbols to count, \
+ bucket=%d count=%d"
@ MSG_ELF_ERR_SHDR "\tunable to obtain section header: shstrtab[%lld]\n"
@ MSG_ELF_ERR_DATA "\tunable to obtain section data: shstrtab[%lld]\n"
@ MSG_ELF_ERR_SCN "\tunable to obtain section header: section[%d]\n"
@ MSG_ELF_ERR_SCNDATA "\tunable to obtain section data: section[%d]\n"
@ MSG_ARCHIVE_SYMTAB "\nSymbol Table: (archive)"
@ MSG_ARCHIVE_FIELDS " index offset member name and symbol"
+
@ MSG_GOT_MULTIPLE "%s: multiple relocations against \
the same GOT entry ndx: %d addr: 0x%llx\n"
-
+@ MSG_GOT_UNEXPECTED "%s: warning: section %s: section unexpected within \
+ relocatable object\n"
# Miscellaneous clutter
diff --git a/usr/src/cmd/sgs/libld/amd64/machrel.c b/usr/src/cmd/sgs/libld/amd64/machrel.c
index 0cdc10cab0..eafb8bb533 100644
--- a/usr/src/cmd/sgs/libld/amd64/machrel.c
+++ b/usr/src/cmd/sgs/libld/amd64/machrel.c
@@ -19,8 +19,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -617,16 +618,16 @@ tls_fixups(Rel_desc *arsp)
uintptr_t
do_activerelocs(Ofl_desc *ofl)
{
- Rel_desc * arsp;
- Rel_cache * rcp;
- Listnode * lnp;
+ Rel_desc *arsp;
+ Rel_cache *rcp;
+ Listnode *lnp;
uintptr_t return_code = 1;
Word flags = ofl->ofl_flags;
Word dtflags1 = ofl->ofl_dtflags_1;
DBG_CALL(Dbg_reloc_doactiverel());
/*
- * process active relocs
+ * Process active relocations.
*/
for (LIST_TRAVERSE(&ofl->ofl_actrels, lnp, rcp)) {
/* LINTED */
@@ -676,6 +677,7 @@ do_activerelocs(Ofl_desc *ofl)
*/
if (arsp->rel_flags & FLG_REL_TLSFIX) {
Fixupret ret;
+
if ((ret = tls_fixups(arsp)) == FIX_ERROR)
return (S_ERROR);
if (ret == FIX_DONE)
@@ -698,7 +700,7 @@ do_activerelocs(Ofl_desc *ofl)
value = 0;
else if (ELF_ST_TYPE(sdp->sd_sym->st_info) ==
STT_SECTION) {
- Sym_desc * sym;
+ Sym_desc *sym;
/*
* The value for a symbol pointing to a SECTION
@@ -721,8 +723,8 @@ do_activerelocs(Ofl_desc *ofl)
value = sym->sd_sym->st_value;
moved = 1;
} else {
- value = (Off)_elf_getxoff(sdp->sd_isc->
- is_indata);
+ value = _elf_getxoff(
+ sdp->sd_isc->is_indata);
if (sdp->sd_isc->is_shdr->sh_flags &
SHF_ALLOC)
value += sdp->sd_isc->is_osdesc->
@@ -730,11 +732,12 @@ do_activerelocs(Ofl_desc *ofl)
}
if (sdp->sd_isc->is_shdr->sh_flags & SHF_TLS)
value -= ofl->ofl_tlsphdr->p_vaddr;
- } else
+ } else {
/*
* else the value is the symbols value
*/
value = sdp->sd_sym->st_value;
+ }
/*
* Relocation against the GLOBAL_OFFSET_TABLE.
@@ -748,11 +751,10 @@ do_activerelocs(Ofl_desc *ofl)
* address.
*/
if ((arsp->rel_flags & FLG_REL_LOAD) &&
- !(flags & FLG_OF_RELOBJ))
+ ((flags & FLG_OF_RELOBJ) == 0))
refaddr += arsp->rel_isdesc->is_osdesc->
os_shdr->sh_addr;
-
/*
* If this entry has a PLT assigned to it, it's
* value is actually the address of the PLT (and
@@ -775,7 +777,17 @@ do_activerelocs(Ofl_desc *ofl)
if ((arsp->rel_flags & FLG_REL_GOT) == 0)
value += arsp->rel_raddend;
- if (arsp->rel_flags & FLG_REL_GOT) {
+ /*
+ * Determine whether the value needs further adjustment.
+ * Filter through the attributes of the relocation to
+ * determine what adjustment is required. Note, many
+ * of the following cases are only applicable when a
+ * .got is present. As a .got is not generated when a
+ * relocatable object is being built, any adjustments
+ * that require a .got need to be skipped.
+ */
+ if ((arsp->rel_flags & FLG_REL_GOT) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
Xword R1addr;
uintptr_t R2addr;
Word gotndx;
@@ -814,60 +826,75 @@ do_activerelocs(Ofl_desc *ofl)
/*
* And do it.
*/
- *(Xword *)R2addr = (Xword)value;
+ *(Xword *)R2addr = value;
continue;
- } else if (IS_GOT_BASED(arsp->rel_rtype)) {
+ } else if (IS_GOT_BASED(arsp->rel_rtype) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
value -= ofl->ofl_osgot->os_shdr->sh_addr;
- } else if (IS_GOTPCREL(arsp->rel_rtype)) {
- Gotndx * gnp;
+
+ } else if (IS_GOTPCREL(arsp->rel_rtype) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
+ Gotndx *gnp;
+
/*
* Calculation:
* G + GOT + A - P
*/
gnp = find_gotndx(&(sdp->sd_GOTndxs),
gref, ofl, arsp);
- assert(gnp != 0);
+ assert(gnp);
value = (Xword)(ofl->ofl_osgot->os_shdr->
sh_addr) + ((Xword)gnp->gn_gotndx *
M_GOT_ENTSIZE) + arsp->rel_raddend -
refaddr;
- } else if (IS_GOT_PC(arsp->rel_rtype)) {
- value = (Xword) (ofl->ofl_osgot->os_shdr->
+
+ } else if (IS_GOT_PC(arsp->rel_rtype) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
+ value = (Xword)(ofl->ofl_osgot->os_shdr->
sh_addr) - refaddr + arsp->rel_raddend;
+
} else if ((IS_PC_RELATIVE(arsp->rel_rtype)) &&
- (!(ofl->ofl_flags & FLG_OF_RELOBJ) ||
+ (((flags & FLG_OF_RELOBJ) == 0) ||
(arsp->rel_osdesc == sdp->sd_isc->is_osdesc))) {
value -= refaddr;
+
} else if (IS_TLS_INS(arsp->rel_rtype) &&
- IS_GOT_RELATIVE(arsp->rel_rtype)) {
+ IS_GOT_RELATIVE(arsp->rel_rtype) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
Gotndx *gnp;
gnp = find_gotndx(&(sdp->sd_GOTndxs), gref,
ofl, arsp);
- assert(gnp != 0);
+ assert(gnp);
value = (Xword)gnp->gn_gotndx * M_GOT_ENTSIZE;
- } else if (IS_GOT_RELATIVE(arsp->rel_rtype)) {
- Gotndx * gnp;
+
+ } else if (IS_GOT_RELATIVE(arsp->rel_rtype) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
+ Gotndx *gnp;
gnp = find_gotndx(&(sdp->sd_GOTndxs),
gref, ofl, arsp);
assert(gnp);
value = (Xword)gnp->gn_gotndx * M_GOT_ENTSIZE;
- } else if (arsp->rel_flags & FLG_REL_STLS) {
+
+ } else if ((arsp->rel_flags & FLG_REL_STLS) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
Xword tlsstatsize;
+
/*
* This is the LE TLS reference model. Static
* offset is hard-coded.
*/
- tlsstatsize = S_ROUND(ofl->
- ofl_tlsphdr->p_memsz,
+ tlsstatsize =
+ S_ROUND(ofl->ofl_tlsphdr->p_memsz,
M_TLSSTATALIGN);
value = tlsstatsize - value;
+
/*
- * Since this code is fixedup
- * it assumes a negative offset
- * that can be added to the thread pointer
+ * Since this code is fixed up, it assumes a
+ * negative offset that can be added to the
+ * thread pointer.
*/
if (arsp->rel_rtype == R_AMD64_TPOFF32)
value = -value;
@@ -901,7 +928,6 @@ do_activerelocs(Ofl_desc *ofl)
(uintptr_t)_elf_getxoff(arsp->rel_isdesc->
is_indata));
- /* LINTED */
DBG_CALL(Dbg_reloc_doact(M_MACH, arsp->rel_rtype,
(uintptr_t)addr, value, arsp->rel_sname,
arsp->rel_osdesc));
@@ -956,11 +982,11 @@ do_activerelocs(Ofl_desc *ofl)
}
uintptr_t
-add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
+add_outrel(Word flags, Rel_desc *rsp, Ofl_desc *ofl)
{
- Rel_desc * orsp;
- Rel_cache * rcp;
- Sym_desc * sdp = rsp->rel_sym;
+ Rel_desc *orsp;
+ Rel_cache *rcp;
+ Sym_desc *sdp = rsp->rel_sym;
/*
* Static executables *do not* want any relocations against them.
@@ -1031,13 +1057,13 @@ add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
* be tagged with the FLG_OS_OUTREL flag.
*/
if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
- (sdp->sd_shndx == SHN_COMMON))
+ (sdp->sd_shndx == SHN_COMMON)) {
if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_TLS)
ofl->ofl_flags1 |= FLG_OF1_BSSOREL;
else
ofl->ofl_flags1 |= FLG_OF1_TLSOREL;
- else {
- Os_desc * osp = sdp->sd_isc->is_osdesc;
+ } else {
+ Os_desc *osp = sdp->sd_isc->is_osdesc;
if ((osp->os_flags & FLG_OS_OUTREL) == 0) {
ofl->ofl_dynshdrcnt++;
@@ -1075,6 +1101,12 @@ add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
ofl->ofl_reloccnt++;
/*
+ * Insure a GLOBAL_OFFSET_TABLE is generated if required.
+ */
+ if (IS_GOT_REQUIRED(orsp->rel_rtype))
+ ofl->ofl_flags |= FLG_OF_BLDGOT;
+
+ /*
* Identify and possibly warn of a displacement relocation.
*/
if (orsp->rel_flags & FLG_REL_DISP) {
@@ -1087,72 +1119,6 @@ add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
return (1);
}
-
-uintptr_t
-add_actrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
-{
- Rel_desc * arsp;
- Rel_cache * rcp;
-
- /*
- * If no relocation cache structures are available allocate a
- * new one and link it into the bucket list.
- */
- if ((ofl->ofl_actrels.tail == 0) ||
- ((rcp = (Rel_cache *)ofl->ofl_actrels.tail->data) == 0) ||
- ((arsp = rcp->rc_free) == rcp->rc_end)) {
- static size_t nextsize = 0;
- size_t size;
-
- /*
- * Typically, when generating an executable or shared object
- * there will be a active relocation for every input relocation.
- */
- if (nextsize == 0) {
- if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
- if ((size = ofl->ofl_relocincnt) == 0)
- size = REL_LAIDESCNO;
- if (size > REL_HAIDESCNO)
- nextsize = REL_HAIDESCNO;
- else
- nextsize = REL_LAIDESCNO;
- } else
- nextsize = size = REL_HAIDESCNO;
- } else
- size = nextsize;
-
- size = size * sizeof (Rel_desc);
-
- if (((rcp = libld_malloc(sizeof (Rel_cache) + size)) == 0) ||
- (list_appendc(&ofl->ofl_actrels, rcp) == 0))
- return (S_ERROR);
-
- /* LINTED */
- rcp->rc_free = arsp = (Rel_desc *)(rcp + 1);
- /* LINTED */
- rcp->rc_end = (Rel_desc *)((char *)rcp->rc_free + size);
- }
-
- *arsp = *rsp;
- arsp->rel_flags |= flags;
-
- rcp->rc_free++;
- ofl->ofl_actrelscnt++;
-
- /*
- * If this is a displacement relocation relocation, warn.
- */
- if (arsp->rel_flags & FLG_REL_DISP) {
- ofl->ofl_dtflags_1 |= DF_1_DISPRELDNE;
-
- if (ofl->ofl_flags & FLG_OF_VERBOSE)
- disp_errmsg(MSG_INTL(MSG_REL_DISPREL3), arsp, ofl);
- }
- DBG_CALL(Dbg_reloc_ars_entry(M_MACH, arsp));
- return (1);
-}
-
-
/*
* Stub routine since register symbols are not supported on amd64.
*/
@@ -1429,53 +1395,6 @@ reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
return (add_actrel(FLG_REL_DTLS, rsp, ofl));
}
-uintptr_t
-reloc_relobj(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
-{
- Word rtype = rsp->rel_rtype;
- Sym_desc * sdp = rsp->rel_sym;
- Is_desc * isp = rsp->rel_isdesc;
- Word flags = ofl->ofl_flags;
-
- /*
- * Try to determine if we can do any relocations at
- * this point. We can if:
- *
- * (local_symbol) and (non_GOT_relocation) and
- * (IS_PC_RELATIVE()) and
- * (relocation to symbol in same section)
- */
- if (local && !IS_GOT_RELATIVE(rtype) && !IS_GOT_BASED(rtype) &&
- !IS_GOT_PC(rtype) && IS_PC_RELATIVE(rtype) &&
- ((sdp->sd_isc) && (sdp->sd_isc->is_osdesc == isp->is_osdesc))) {
- return (add_actrel(NULL, rsp, ofl));
- }
-
- /*
- * If '-zredlocsym' is in effect make all local sym relocations
- * against the 'section symbols', since they are the only symbols
- * which will be added to the .symtab.
- */
- if (local && (((ofl->ofl_flags1 & FLG_OF1_REDLSYM) &&
- (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL)) ||
- ((sdp->sd_flags & FLG_SY1_ELIM) && (flags & FLG_OF_PROCRED)))) {
- /*
- * But if this is a PIC code, don't allow it for now.
- */
- if (IS_GOT_RELATIVE(rsp->rel_rtype)) {
- eprintf(ERR_FATAL, MSG_INTL(MSG_REL_PICREDLOC),
- demangle(rsp->rel_sname),
- rsp->rel_isdesc->is_file->ifl_name,
- conv_reloc_386_type_str(rsp->rel_rtype));
- return (S_ERROR);
- }
- return (add_actrel(FLG_REL_SCNNDX | FLG_REL_ADVAL, rsp, ofl));
- }
-
- return (add_outrel(NULL, rsp, ofl));
-}
-
-
/* ARGSUSED3 */
Gotndx *
find_gotndx(List * lst, Gotref gref, Ofl_desc * ofl, Rel_desc * rdesc)
@@ -1599,6 +1518,7 @@ assign_plt_ndx(Sym_desc * sdp, Ofl_desc *ofl)
{
sdp->sd_aux->sa_PLTndx = 1 + ofl->ofl_pltcnt++;
sdp->sd_aux->sa_PLTGOTndx = ofl->ofl_gotcnt++;
+ ofl->ofl_flags |= FLG_OF_BLDGOT;
}
static uchar_t plt0_template[M_PLT_ENTSIZE] = {
diff --git a/usr/src/cmd/sgs/libld/common/_libld.h b/usr/src/cmd/sgs/libld/common/_libld.h
index ee101e5037..c827e0518b 100644
--- a/usr/src/cmd/sgs/libld/common/_libld.h
+++ b/usr/src/cmd/sgs/libld/common/_libld.h
@@ -19,12 +19,12 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
- *
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -266,7 +266,6 @@ extern Sym_desc * reg_find(Sym *, Ofl_desc *);
extern uintptr_t reloc_local(Rel_desc *, Ofl_desc *);
extern uintptr_t reloc_plt(Rel_desc *, Ofl_desc *);
extern uintptr_t reloc_register(Rel_desc *, Is_desc *, Ofl_desc *);
-extern uintptr_t reloc_relobj(Boolean, Rel_desc *, Ofl_desc *);
extern void reloc_remain_entry(Rel_desc *, Os_desc *, Ofl_desc *);
extern uintptr_t reloc_GOT_relative(Boolean, Rel_desc *, Ofl_desc *);
extern uintptr_t reloc_GOTOP(Boolean, Rel_desc *, Ofl_desc *);
diff --git a/usr/src/cmd/sgs/libld/common/relocate.c b/usr/src/cmd/sgs/libld/common/relocate.c
index 2f651c36dd..c389f8f361 100644
--- a/usr/src/cmd/sgs/libld/common/relocate.c
+++ b/usr/src/cmd/sgs/libld/common/relocate.c
@@ -24,8 +24,7 @@
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
- *
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -197,7 +196,7 @@ disp_bsearch(const void *key, const void *array)
*/
static Sym_desc *
disp_scansyms(Ifl_desc * ifl, Rel_desc *rld, Boolean rlocal, int inspect,
- Ofl_desc * ofl)
+ Ofl_desc *ofl)
{
Sym_desc *tsdp, *rsdp;
Sym *rsym, *tsym;
@@ -243,7 +242,7 @@ disp_scansyms(Ifl_desc * ifl, Rel_desc *rld, Boolean rlocal, int inspect,
} else {
/*
* If both symbols are local, no copy relocations can occur to
- * either.
+ * either symbol.
*/
if ((rlocal == TRUE) && ((tsdp->sd_flags1 & FLG_SY1_LOCL) ||
((ofl->ofl_flags & FLG_OF_AUTOLCL) &&
@@ -258,7 +257,18 @@ disp_scansyms(Ifl_desc * ifl, Rel_desc *rld, Boolean rlocal, int inspect,
ttype = ELF_ST_TYPE(tsym->st_info);
/*
- * One of the symbols must reference a data element.
+ * If the reference symbol is local, and the target isn't a
+ * data element, then no copy relocations can occur to either
+ * symbol. Note, this catches pc-relative relocations against
+ * the _GLOBAL_OFFSET_TABLE_, which is effectively treated as
+ * a local symbol.
+ */
+ if ((rlocal == TRUE) && (ttype != STT_OBJECT) &&
+ (ttype != STT_SECTION))
+ return (tsdp);
+
+ /*
+ * Finally, one of the symbols must reference a data element.
*/
if ((rtype != STT_OBJECT) && (rtype != STT_SECTION) &&
(ttype != STT_OBJECT) && (ttype != STT_SECTION))
@@ -410,6 +420,85 @@ disp_inspect(Ofl_desc *ofl, Rel_desc *rld, Boolean rlocal)
return (1);
}
+/*
+ * Add an active relocation record.
+ */
+uintptr_t
+add_actrel(Word flags, Rel_desc *rsp, Ofl_desc *ofl)
+{
+ Rel_desc *arsp;
+ Rel_cache *rcp;
+
+ /*
+ * If no relocation cache structures are available, allocate a new
+ * one and link it into the bucket list.
+ */
+ if ((ofl->ofl_actrels.tail == 0) ||
+ ((rcp = (Rel_cache *)ofl->ofl_actrels.tail->data) == 0) ||
+ ((arsp = rcp->rc_free) == rcp->rc_end)) {
+ static size_t nextsize = 0;
+ size_t size;
+
+ /*
+ * Typically, when generating an executable or shared object
+ * there will be an active relocation for every input
+ * relocation.
+ */
+ if (nextsize == 0) {
+ if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
+ if ((size = ofl->ofl_relocincnt) == 0)
+ size = REL_LAIDESCNO;
+ if (size > REL_HAIDESCNO)
+ nextsize = REL_HAIDESCNO;
+ else
+ nextsize = REL_LAIDESCNO;
+ } else
+ nextsize = size = REL_HAIDESCNO;
+ } else
+ size = nextsize;
+
+ size = size * sizeof (Rel_desc);
+
+ if (((rcp = libld_malloc(sizeof (Rel_cache) + size)) == 0) ||
+ (list_appendc(&ofl->ofl_actrels, rcp) == 0))
+ return (S_ERROR);
+
+ /* LINTED */
+ rcp->rc_free = arsp = (Rel_desc *)(rcp + 1);
+ /* LINTED */
+ rcp->rc_end = (Rel_desc *)((char *)rcp->rc_free + size);
+ }
+
+ *arsp = *rsp;
+ arsp->rel_flags |= flags;
+
+ rcp->rc_free++;
+ ofl->ofl_actrelscnt++;
+
+ /*
+ * Any GOT relocation reference requires the creation of a .got table.
+ * Most references to a .got require a .got entry, which is accounted
+ * for with the ofl_gotcnt counter. However, some references are
+ * relative to the .got table, but require no .got entry. This test
+ * insures a .got is created regardless of the type of reference.
+ */
+ if (IS_GOT_REQUIRED(arsp->rel_rtype))
+ ofl->ofl_flags |= FLG_OF_BLDGOT;
+
+ /*
+ * If this is a displacement relocation generate a warning.
+ */
+ if (arsp->rel_flags & FLG_REL_DISP) {
+ ofl->ofl_dtflags_1 |= DF_1_DISPRELDNE;
+
+ if (ofl->ofl_flags & FLG_OF_VERBOSE)
+ disp_errmsg(MSG_INTL(MSG_REL_DISPREL3), arsp, ofl);
+ }
+
+ DBG_CALL(Dbg_reloc_ars_entry(M_MACH, arsp));
+ return (1);
+}
+
uintptr_t
reloc_GOT_relative(Boolean local, Rel_desc *rsp, Ofl_desc *ofl)
{
@@ -815,6 +904,81 @@ reloc_generic(Rel_desc *rsp, Ofl_desc *ofl)
return (add_actrel(NULL, rsp, ofl));
}
+/*
+ * Process relocations when building a relocatable object. Typically, there
+ * aren't many relocations that can be caught at this point, most are simply
+ * passed through to the output relocatable object.
+ */
+static uintptr_t
+reloc_relobj(Boolean local, Rel_desc *rsp, Ofl_desc *ofl)
+{
+ Word rtype = rsp->rel_rtype;
+ Sym_desc *sdp = rsp->rel_sym;
+ Is_desc *isp = rsp->rel_isdesc;
+ Word oflags = NULL;
+
+ /*
+ * Determine if we can do any relocations at this point. We can if:
+ *
+ * this is local_symbol and a non-GOT relocation, and
+ * the relocation is pc-relative, and
+ * the relocation is against a symbol in same section
+ */
+ if (local && !IS_GOT_RELATIVE(rtype) && !IS_GOT_BASED(rtype) &&
+ !IS_GOT_PC(rtype) && IS_PC_RELATIVE(rtype) &&
+ ((sdp->sd_isc) && (sdp->sd_isc->is_osdesc == isp->is_osdesc)))
+ return (add_actrel(NULL, rsp, ofl));
+
+ /*
+ * If -zredlocsym is in effect, translate all local symbol relocations
+ * to be against section symbols, since section symbols are the only
+ * symbols which will be added to the .symtab.
+ */
+ if (local && (((ofl->ofl_flags1 & FLG_OF1_REDLSYM) &&
+ (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL)) ||
+ ((sdp->sd_flags1 & FLG_SY1_ELIM) &&
+ (ofl->ofl_flags & FLG_OF_PROCRED)))) {
+ /*
+ * But if this is PIC code, don't allow it for now.
+ */
+ if (IS_GOT_RELATIVE(rsp->rel_rtype)) {
+ Ifl_desc *ifl = rsp->rel_isdesc->is_file;
+
+ eprintf(ERR_FATAL, MSG_INTL(MSG_REL_PICREDLOC),
+ demangle(rsp->rel_sname), ifl->ifl_name,
+ conv_reloc_type_str(ifl->ifl_ehdr->e_machine,
+ rsp->rel_rtype));
+ return (S_ERROR);
+ }
+
+ /*
+ * Indicate that this relocation should be processed the same
+ * as a section symbol. For SPARC and AMD (Rela), indicate
+ * that the addend also needs to be applied to this relocation.
+ */
+#if defined(__i386)
+ oflags = FLG_REL_SCNNDX;
+#else
+ oflags = FLG_REL_SCNNDX | FLG_REL_ADVAL;
+#endif
+ }
+
+#if defined(__i386)
+ /*
+ * Intel (Rel) relocations do not contain an addend. Any addend is
+ * contained within the file at the location identified by the
+ * relocation offset. Therefore, if we're processing a section symbol,
+ * or a -zredlocsym relocation (that basically transforms a local symbol
+ * reference into a section reference), perform an active relocation to
+ * propagate any addend.
+ */
+ if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) ||
+ (oflags == FLG_REL_SCNNDX))
+ if (add_actrel(NULL, rsp, ofl) == S_ERROR)
+ return (S_ERROR);
+#endif
+ return (add_outrel(oflags, rsp, ofl));
+}
uintptr_t
process_sym_reloc(Ofl_desc * ofl, Rel_desc * reld, Rel * reloc,
@@ -1474,20 +1638,14 @@ reloc_init(Ofl_desc *ofl)
}
/*
- * Make a got section if:
- *
- * BLDGOT flag set
- * or
- * ofl_gotcnt != GOT_XNumber
- * or
- * not-relobj & GOT symbol referenced
- *
+ * GOT sections are created for dynamic executables and shared objects
+ * if the FLG_OF_BLDGOT is set, or explicit reference has been made to
+ * a GOT symbol.
*/
- if ((ofl->ofl_flags & FLG_OF_BLDGOT) ||
- (ofl->ofl_gotcnt != M_GOT_XNumber) ||
- (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) &&
- ((sym_find(MSG_ORIG(MSG_SYM_GOFTBL), SYM_NOHASH, 0, ofl) != 0) ||
- (sym_find(MSG_ORIG(MSG_SYM_GOFTBL_U), SYM_NOHASH, 0, ofl) != 0)))) {
+ if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) &&
+ ((ofl->ofl_flags & FLG_OF_BLDGOT) ||
+ (sym_find(MSG_ORIG(MSG_SYM_GOFTBL), SYM_NOHASH, 0, ofl) != 0) ||
+ (sym_find(MSG_ORIG(MSG_SYM_GOFTBL_U), SYM_NOHASH, 0, ofl) != 0))) {
if (make_got(ofl) == S_ERROR)
return (S_ERROR);
diff --git a/usr/src/cmd/sgs/libld/i386/machrel.c b/usr/src/cmd/sgs/libld/i386/machrel.c
index 48cbf97791..60a06b8165 100644
--- a/usr/src/cmd/sgs/libld/i386/machrel.c
+++ b/usr/src/cmd/sgs/libld/i386/machrel.c
@@ -19,12 +19,13 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -642,26 +643,26 @@ tls_fixups(Rel_desc *arsp)
uintptr_t
do_activerelocs(Ofl_desc *ofl)
{
- Rel_desc * arsp;
- Rel_cache * rcp;
- Listnode * lnp;
+ Rel_desc *arsp;
+ Rel_cache *rcp;
+ Listnode *lnp;
uintptr_t return_code = 1;
Word flags = ofl->ofl_flags;
Word dtflags1 = ofl->ofl_dtflags_1;
DBG_CALL(Dbg_reloc_doactiverel());
/*
- * process active relocs
+ * Process active relocations.
*/
for (LIST_TRAVERSE(&ofl->ofl_actrels, lnp, rcp)) {
/* LINTED */
for (arsp = (Rel_desc *)(rcp + 1);
arsp < rcp->rc_free; arsp++) {
uchar_t *addr;
- Word value;
+ Xword value;
Sym_desc *sdp;
const char *ifl_name;
- Word refaddr;
+ Xword refaddr;
int moved = 0;
Gotref gref;
@@ -723,7 +724,7 @@ do_activerelocs(Ofl_desc *ofl)
value = 0;
else if (ELF_ST_TYPE(sdp->sd_sym->st_info) ==
STT_SECTION) {
- Sym_desc * sym;
+ Sym_desc *sym;
/*
* The value for a symbol pointing to a SECTION
@@ -746,20 +747,21 @@ do_activerelocs(Ofl_desc *ofl)
value = sym->sd_sym->st_value;
moved = 1;
} else {
- value = (Off)_elf_getxoff(sdp->sd_isc->
- is_indata);
+ value = _elf_getxoff(
+ sdp->sd_isc->is_indata);
if (sdp->sd_isc->is_shdr->sh_flags &
SHF_ALLOC)
- value += sdp->sd_isc->is_osdesc->
- os_shdr->sh_addr;
+ value += sdp->sd_isc->
+ is_osdesc->os_shdr->sh_addr;
}
if (sdp->sd_isc->is_shdr->sh_flags & SHF_TLS)
value -= ofl->ofl_tlsphdr->p_vaddr;
- } else
+ } else {
/*
* else the value is the symbols value
*/
value = sdp->sd_sym->st_value;
+ }
/*
* Relocation against the GLOBAL_OFFSET_TABLE.
@@ -773,11 +775,10 @@ do_activerelocs(Ofl_desc *ofl)
* address.
*/
if ((arsp->rel_flags & FLG_REL_LOAD) &&
- !(flags & FLG_OF_RELOBJ))
+ ((flags & FLG_OF_RELOBJ) == 0))
refaddr += arsp->rel_isdesc->is_osdesc->
os_shdr->sh_addr;
-
/*
* If this entry has a PLT assigned to it, it's
* value is actually the address of the PLT (and
@@ -788,7 +789,17 @@ do_activerelocs(Ofl_desc *ofl)
value = calc_plt_addr(sdp, ofl);
}
- if (arsp->rel_flags & FLG_REL_GOT) {
+ /*
+ * Determine whether the value needs further adjustment.
+ * Filter through the attributes of the relocation to
+ * determine what adjustment is required. Note, many
+ * of the following cases are only applicable when a
+ * .got is present. As a .got is not generated when a
+ * relocatable object is being built, any adjustments
+ * that require a .got need to be skipped.
+ */
+ if ((arsp->rel_flags & FLG_REL_GOT) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
Xword R1addr;
uintptr_t R2addr;
Word gotndx;
@@ -827,51 +838,64 @@ do_activerelocs(Ofl_desc *ofl)
/*
* And do it.
*/
- *(Word *)R2addr = (Word)value;
+ *(Xword *)R2addr = value;
continue;
- } else if (IS_GOT_BASED(arsp->rel_rtype)) {
+ } else if (IS_GOT_BASED(arsp->rel_rtype) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
value -= ofl->ofl_osgot->os_shdr->sh_addr;
- } else if (IS_GOT_PC(arsp->rel_rtype)) {
- value = (Word) (ofl->ofl_osgot->os_shdr->
- sh_addr) - refaddr;
+
+ } else if (IS_GOT_PC(arsp->rel_rtype) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
+ value =
+ (Xword)(ofl->ofl_osgot->os_shdr->sh_addr) -
+ refaddr;
+
} else if ((IS_PC_RELATIVE(arsp->rel_rtype)) &&
- (!(flags & FLG_OF_RELOBJ) ||
+ (((flags & FLG_OF_RELOBJ) == 0) ||
(arsp->rel_osdesc == sdp->sd_isc->is_osdesc))) {
value -= refaddr;
+
} else if (IS_TLS_INS(arsp->rel_rtype) &&
- IS_GOT_RELATIVE(arsp->rel_rtype)) {
+ IS_GOT_RELATIVE(arsp->rel_rtype) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
Gotndx *gnp;
gnp = find_gotndx(&(sdp->sd_GOTndxs), gref,
ofl, 0);
assert(gnp);
- value = (Word)gnp->gn_gotndx * M_GOT_ENTSIZE;
+ value = (Xword)gnp->gn_gotndx * M_GOT_ENTSIZE;
if (arsp->rel_rtype == R_386_TLS_IE) {
- value += ofl->ofl_osgot->os_shdr->
- sh_addr;
+ value +=
+ ofl->ofl_osgot->os_shdr->sh_addr;
}
- } else if (IS_GOT_RELATIVE(arsp->rel_rtype)) {
- Gotndx * gnp;
+
+ } else if (IS_GOT_RELATIVE(arsp->rel_rtype) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
+ Gotndx *gnp;
gnp = find_gotndx(&(sdp->sd_GOTndxs),
GOT_REF_GENERIC, ofl, 0);
assert(gnp);
- value = (Word)gnp->gn_gotndx * M_GOT_ENTSIZE;
- } else if (arsp->rel_flags & FLG_REL_STLS) {
+ value = (Xword)gnp->gn_gotndx * M_GOT_ENTSIZE;
+
+ } else if ((arsp->rel_flags & FLG_REL_STLS) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
Xword tlsstatsize;
+
/*
* This is the LE TLS reference model. Static
* offset is hard-coded.
*/
- tlsstatsize = S_ROUND(ofl->
- ofl_tlsphdr->p_memsz,
+ tlsstatsize =
+ S_ROUND(ofl->ofl_tlsphdr->p_memsz,
M_TLSSTATALIGN);
value = tlsstatsize - value;
+
/*
- * Since this code is fixedup
- * it assumes a negative offset
- * that can be added to the thread pointer
+ * Since this code is fixed up, it assumes a
+ * negative offset that can be added to the
+ * thread pointer.
*/
if ((arsp->rel_rtype == R_386_TLS_LDO_32) ||
(arsp->rel_rtype == R_386_TLS_LE))
@@ -943,7 +967,6 @@ do_activerelocs(Ofl_desc *ofl)
if (moved)
value -= *addr;
-
/*
* If '-z noreloc' is specified - skip the do_reloc
* stage.
@@ -960,12 +983,15 @@ do_activerelocs(Ofl_desc *ofl)
return (return_code);
}
+/*
+ * Add an output relocation record.
+ */
uintptr_t
-add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
+add_outrel(Word flags, Rel_desc *rsp, Ofl_desc *ofl)
{
- Rel_desc * orsp;
- Rel_cache * rcp;
- Sym_desc * sdp = rsp->rel_sym;
+ Rel_desc *orsp;
+ Rel_cache *rcp;
+ Sym_desc *sdp = rsp->rel_sym;
/*
* Static executables *do not* want any relocations against them.
@@ -1036,13 +1062,13 @@ add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
* be tagged with the FLG_OS_OUTREL flag.
*/
if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
- (sdp->sd_shndx == SHN_COMMON))
+ (sdp->sd_shndx == SHN_COMMON)) {
if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_TLS)
ofl->ofl_flags1 |= FLG_OF1_BSSOREL;
else
ofl->ofl_flags1 |= FLG_OF1_TLSOREL;
- else {
- Os_desc * osp = sdp->sd_isc->is_osdesc;
+ } else {
+ Os_desc *osp = sdp->sd_isc->is_osdesc;
if ((osp->os_flags & FLG_OS_OUTREL) == 0) {
ofl->ofl_dynshdrcnt++;
@@ -1080,11 +1106,9 @@ add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
ofl->ofl_reloccnt++;
/*
- * A R_386_GOTPC or R_386_GOTOFF relocation triggers the creation of
- * the GLOBAL_OFFSET_TABLE (as defined by the ABI).
+ * Insure a GLOBAL_OFFSET_TABLE is generated if required.
*/
- if ((orsp->rel_rtype == R_386_GOTPC) ||
- (orsp->rel_rtype == R_386_GOTOFF))
+ if (IS_GOT_REQUIRED(orsp->rel_rtype))
ofl->ofl_flags |= FLG_OF_BLDGOT;
/*
@@ -1100,81 +1124,6 @@ add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
return (1);
}
-
-uintptr_t
-add_actrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
-{
- Rel_desc * arsp;
- Rel_cache * rcp;
-
- /*
- * If no relocation cache structures are available allocate a
- * new one and link it into the bucket list.
- */
- if ((ofl->ofl_actrels.tail == 0) ||
- ((rcp = (Rel_cache *)ofl->ofl_actrels.tail->data) == 0) ||
- ((arsp = rcp->rc_free) == rcp->rc_end)) {
- static size_t nextsize = 0;
- size_t size;
-
- /*
- * Typically, when generating an executable or shared object
- * there will be a active relocation for every input relocation.
- */
- if (nextsize == 0) {
- if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
- if ((size = ofl->ofl_relocincnt) == 0)
- size = REL_LAIDESCNO;
- if (size > REL_HAIDESCNO)
- nextsize = REL_HAIDESCNO;
- else
- nextsize = REL_LAIDESCNO;
- } else
- nextsize = size = REL_HAIDESCNO;
- } else
- size = nextsize;
-
- size = size * sizeof (Rel_desc);
-
- if (((rcp = libld_malloc(sizeof (Rel_cache) + size)) == 0) ||
- (list_appendc(&ofl->ofl_actrels, rcp) == 0))
- return (S_ERROR);
-
- /* LINTED */
- rcp->rc_free = arsp = (Rel_desc *)(rcp + 1);
- /* LINTED */
- rcp->rc_end = (Rel_desc *)((char *)rcp->rc_free + size);
- }
-
- *arsp = *rsp;
- arsp->rel_flags |= flags;
-
- rcp->rc_free++;
- ofl->ofl_actrelscnt++;
-
- /*
- * A R_386_GOTPC or R_386_GOTOFF relocation triggers the creation of
- * the GLOBAL_OFFSET_TABLE (as defined by the ABI).
- */
- if ((arsp->rel_rtype == R_386_GOTPC) ||
- (arsp->rel_rtype == R_386_GOTOFF))
- ofl->ofl_flags |= FLG_OF_BLDGOT;
-
- /*
- * If this is a displacement relocation relocation, warn.
- */
- if (arsp->rel_flags & FLG_REL_DISP) {
- ofl->ofl_dtflags_1 |= DF_1_DISPRELDNE;
-
- if (ofl->ofl_flags & FLG_OF_VERBOSE)
- disp_errmsg(MSG_INTL(MSG_REL_DISPREL3), arsp, ofl);
- }
-
- DBG_CALL(Dbg_reloc_ars_entry(M_MACH, arsp));
- return (1);
-}
-
-
/*
* Stub routine since register symbols are not supported on i386.
*/
@@ -1463,59 +1412,6 @@ reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
return (add_actrel(FLG_REL_DTLS, rsp, ofl));
}
-uintptr_t
-reloc_relobj(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
-{
- Word rtype = rsp->rel_rtype;
- Sym_desc * sdp = rsp->rel_sym;
- Is_desc * isp = rsp->rel_isdesc;
- Word flags = ofl->ofl_flags;
-
- /*
- * Try to determine if we can do any relocations at
- * this point. We can if:
- *
- * (local_symbol) and (non_GOT_relocation) and
- * (IS_PC_RELATIVE()) and
- * (relocation to symbol in same section)
- */
- if (local && !IS_GOT_RELATIVE(rtype) && !IS_GOT_BASED(rtype) &&
- !IS_GOT_PC(rtype) && IS_PC_RELATIVE(rtype) &&
- ((sdp->sd_isc) && (sdp->sd_isc->is_osdesc == isp->is_osdesc))) {
- return (add_actrel(NULL, rsp, ofl));
- }
-
- /*
- * If '-zredlocsym' is in effect make all local sym relocations
- * against the 'section symbols', since they are the only symbols
- * which will be added to the .symtab.
- */
- if (local && (((ofl->ofl_flags1 & FLG_OF1_REDLSYM) &&
- (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL)) ||
- ((sdp->sd_flags1 & FLG_SY1_ELIM) && (flags & FLG_OF_PROCRED)))) {
- /*
- * But if this is a PIC code, don't allow it for now.
- */
- if (IS_GOT_RELATIVE(rsp->rel_rtype)) {
- eprintf(ERR_FATAL, MSG_INTL(MSG_REL_PICREDLOC),
- demangle(rsp->rel_sname),
- rsp->rel_isdesc->is_file->ifl_name,
- conv_reloc_386_type_str(rsp->rel_rtype));
- return (S_ERROR);
- }
- if (add_actrel(NULL, rsp, ofl) == S_ERROR)
- return (S_ERROR);
- return (add_outrel(FLG_REL_SCNNDX, rsp, ofl));
- }
-
- if (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION)
- if (add_actrel(NULL, rsp, ofl) == S_ERROR)
- return (S_ERROR);
-
- return (add_outrel(NULL, rsp, ofl));
-}
-
-
/* ARGSUSED3 */
Gotndx *
find_gotndx(List * lst, Gotref gref, Ofl_desc * ofl, Rel_desc * rdesc)
@@ -1604,6 +1500,7 @@ assign_plt_ndx(Sym_desc * sdp, Ofl_desc *ofl)
{
sdp->sd_aux->sa_PLTndx = 1 + ofl->ofl_pltcnt++;
sdp->sd_aux->sa_PLTGOTndx = ofl->ofl_gotcnt++;
+ ofl->ofl_flags |= FLG_OF_BLDGOT;
}
/*
diff --git a/usr/src/cmd/sgs/libld/sparc/machrel.c b/usr/src/cmd/sgs/libld/sparc/machrel.c
index 17c40c7046..52fd389425 100644
--- a/usr/src/cmd/sgs/libld/sparc/machrel.c
+++ b/usr/src/cmd/sgs/libld/sparc/machrel.c
@@ -19,12 +19,12 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
- *
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -965,16 +965,16 @@ gotop_fixups(Rel_desc *arsp)
uintptr_t
do_activerelocs(Ofl_desc *ofl)
{
- Rel_desc * arsp;
- Rel_cache * rcp;
- Listnode * lnp;
+ Rel_desc *arsp;
+ Rel_cache *rcp;
+ Listnode *lnp;
uintptr_t return_code = 1;
Word flags = ofl->ofl_flags;
Word dtflags1 = ofl->ofl_dtflags_1;
DBG_CALL(Dbg_reloc_doactiverel());
/*
- * process active relocs
+ * Process active relocations.
*/
for (LIST_TRAVERSE(&ofl->ofl_actrels, lnp, rcp)) {
/* LINTED */
@@ -1039,7 +1039,7 @@ do_activerelocs(Ofl_desc *ofl)
value = 0;
else if (ELF_ST_TYPE(sdp->sd_sym->st_info) ==
STT_SECTION) {
- Sym_desc * sym;
+ Sym_desc *sym;
/*
* The value for a symbol pointing to a SECTION
@@ -1052,28 +1052,29 @@ do_activerelocs(Ofl_desc *ofl)
* If the symbol is moved,
* adjust the value
*/
- value = (Off)_elf_getxoff(sym->sd_isc->
- is_indata);
- if (sym->sd_isc->is_shdr->sh_flags &
- SHF_ALLOC)
- value += sym->sd_isc->is_osdesc->
- os_shdr->sh_addr;
+ value = _elf_getxoff(
+ sym->sd_isc->is_indata);
+ if (sym->sd_isc->is_shdr->sh_flags &
+ SHF_ALLOC)
+ value += sym->sd_isc->
+ is_osdesc->os_shdr->sh_addr;
} else {
- value = (Off)_elf_getxoff(sdp->sd_isc->
- is_indata);
+ value = _elf_getxoff(
+ sdp->sd_isc->is_indata);
if (sdp->sd_isc->is_shdr->sh_flags &
SHF_ALLOC)
- value += sdp->sd_isc->is_osdesc->
- os_shdr->sh_addr;
+ value += sdp->sd_isc->
+ is_osdesc->os_shdr->sh_addr;
}
if (sdp->sd_isc->is_shdr->sh_flags & SHF_TLS)
value -= ofl->ofl_tlsphdr->p_vaddr;
- } else
+ } else {
/*
* else the value is the symbols value
*/
value = sdp->sd_sym->st_value;
+ }
/*
* Relocation against the GLOBAL_OFFSET_TABLE.
@@ -1087,7 +1088,7 @@ do_activerelocs(Ofl_desc *ofl)
* address.
*/
if ((arsp->rel_flags & FLG_REL_LOAD) &&
- !(flags & FLG_OF_RELOBJ))
+ ((flags & FLG_OF_RELOBJ) == 0))
refaddr += arsp->rel_isdesc->is_osdesc->
os_shdr->sh_addr;
@@ -1109,7 +1110,17 @@ do_activerelocs(Ofl_desc *ofl)
if (IS_EXTOFFSET(arsp->rel_rtype))
value += arsp->rel_typedata;
- if (arsp->rel_flags & FLG_REL_GOT) {
+ /*
+ * Determine whether the value needs further adjustment.
+ * Filter through the attributes of the relocation to
+ * determine what adjustment is required. Note, many
+ * of the following cases are only applicable when a
+ * .got is present. As a .got is not generated when a
+ * relocatable object is being built, any adjustments
+ * that require a .got need to be skipped.
+ */
+ if ((arsp->rel_flags & FLG_REL_GOT) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
Xword R1addr;
uintptr_t R2addr;
Sword gotndx;
@@ -1162,13 +1173,17 @@ do_activerelocs(Ofl_desc *ofl)
*(Xword *)R2addr = value;
continue;
- } else if (IS_GOT_BASED(arsp->rel_rtype)) {
+ } else if (IS_GOT_BASED(arsp->rel_rtype) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
value -= (ofl->ofl_osgot->os_shdr->sh_addr +
(-neggotoffset * M_GOT_ENTSIZE));
+
} else if (IS_PC_RELATIVE(arsp->rel_rtype)) {
value -= refaddr;
+
} else if (IS_TLS_INS(arsp->rel_rtype) &&
- IS_GOT_RELATIVE(arsp->rel_rtype)) {
+ IS_GOT_RELATIVE(arsp->rel_rtype) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
Gotndx *gnp;
Gotref gref;
@@ -1185,8 +1200,9 @@ do_activerelocs(Ofl_desc *ofl)
value = gnp->gn_gotndx * M_GOT_ENTSIZE;
- } else if (IS_GOT_RELATIVE(arsp->rel_rtype)) {
- Gotndx * gnp;
+ } else if (IS_GOT_RELATIVE(arsp->rel_rtype) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
+ Gotndx *gnp;
gnp = find_gotndx(&(sdp->sd_GOTndxs),
GOT_REF_GENERIC, ofl, arsp);
@@ -1194,8 +1210,10 @@ do_activerelocs(Ofl_desc *ofl)
value = gnp->gn_gotndx * M_GOT_ENTSIZE;
- } else if (arsp->rel_flags & FLG_REL_STLS) {
+ } else if ((arsp->rel_flags & FLG_REL_STLS) &&
+ ((flags & FLG_OF_RELOBJ) == 0)) {
Xword tlsstatsize;
+
/*
* This is the LE TLS
* reference model. Static offset
@@ -1280,13 +1298,12 @@ do_activerelocs(Ofl_desc *ofl)
return (return_code);
}
-
uintptr_t
-add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
+add_outrel(Word flags, Rel_desc *rsp, Ofl_desc *ofl)
{
- Rel_desc * orsp;
- Rel_cache * rcp;
- Sym_desc * sdp = rsp->rel_sym;
+ Rel_desc *orsp;
+ Rel_cache *rcp;
+ Sym_desc *sdp = rsp->rel_sym;
/*
* Static executables *do not* want any relocations against them.
@@ -1337,7 +1354,6 @@ add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
#endif
}
-
/*
* If no relocation cache structures are available allocate
* a new one and link it into the cache list.
@@ -1403,7 +1419,7 @@ add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
else
ofl->ofl_flags1 |= FLG_OF1_TLSOREL;
} else {
- Os_desc * osp = sdp->sd_isc->is_osdesc;
+ Os_desc *osp = sdp->sd_isc->is_osdesc;
if ((osp->os_flags & FLG_OS_OUTREL) == 0) {
ofl->ofl_dynshdrcnt++;
@@ -1445,7 +1461,6 @@ add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
orsp->rel_sym->sd_flags |= FLG_SY_PLTPAD;
}
#endif
-
/*
* We don't perform sorting on PLT relocations because
* they have already been assigned a PLT index and if we
@@ -1455,6 +1470,12 @@ add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
ofl->ofl_reloccnt++;
/*
+ * Insure a GLOBAL_OFFSET_TABLE is generated if required.
+ */
+ if (IS_GOT_REQUIRED(orsp->rel_rtype))
+ ofl->ofl_flags |= FLG_OF_BLDGOT;
+
+ /*
* Identify and possibly warn of a displacement relocation.
*/
if (orsp->rel_flags & FLG_REL_DISP) {
@@ -1467,72 +1488,6 @@ add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
return (1);
}
-
-uintptr_t
-add_actrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
-{
- Rel_desc * arsp;
- Rel_cache * rcp;
-
- /*
- * If no relocation cache structures are available allocate a
- * new one and link it into the bucket list.
- */
- if ((ofl->ofl_actrels.tail == 0) ||
- ((rcp = (Rel_cache *)ofl->ofl_actrels.tail->data) == 0) ||
- ((arsp = rcp->rc_free) == rcp->rc_end)) {
- static size_t nextsize = 0;
- size_t size;
-
- /*
- * Typically, when generating an executable or shared object
- * there will be a active relocation for every input relocation.
- */
- if (nextsize == 0) {
- if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
- if ((size = ofl->ofl_relocincnt) == 0)
- size = REL_LAIDESCNO;
- if (size > REL_HAIDESCNO)
- nextsize = REL_HAIDESCNO;
- else
- nextsize = REL_LAIDESCNO;
- } else
- nextsize = size = REL_HAIDESCNO;
- } else
- size = nextsize;
-
- size = size * sizeof (Rel_desc);
-
- if (((rcp = libld_malloc(sizeof (Rel_cache) + size)) == 0) ||
- (list_appendc(&ofl->ofl_actrels, rcp) == 0))
- return (S_ERROR);
-
- /* LINTED */
- rcp->rc_free = arsp = (Rel_desc *)(rcp + 1);
- /* LINTED */
- rcp->rc_end = (Rel_desc *)((char *)rcp->rc_free + size);
- }
-
- *arsp = *rsp;
- arsp->rel_flags |= flags;
-
- rcp->rc_free++;
- ofl->ofl_actrelscnt++;
-
- /*
- * If this is a displacement relocation relocation, warn.
- */
- if (arsp->rel_flags & FLG_REL_DISP) {
- ofl->ofl_dtflags_1 |= DF_1_DISPRELDNE;
-
- if (ofl->ofl_flags & FLG_OF_VERBOSE)
- disp_errmsg(MSG_INTL(MSG_REL_DISPREL3), arsp, ofl);
- }
- DBG_CALL(Dbg_reloc_ars_entry(M_MACH, arsp));
- return (1);
-}
-
-
/*
* Process relocation against a register symbol. Note, of -z muldefs is in
* effect there may have been multiple register definitions, which would have
@@ -1907,52 +1862,6 @@ reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
return (add_actrel(FLG_REL_DTLS, rsp, ofl));
}
-uintptr_t
-reloc_relobj(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
-{
- Word rtype = rsp->rel_rtype;
- Sym_desc * sdp = rsp->rel_sym;
- Is_desc * isp = rsp->rel_isdesc;
- Word flags = ofl->ofl_flags;
-
- /*
- * Try to determine if we can do any relocations at
- * this point. We can if:
- *
- * (local_symbol) and (non_GOT_relocation) and
- * (IS_PC_RELATIVE()) and
- * (relocation to symbol in same section)
- */
- if (local && !IS_GOT_RELATIVE(rtype) && !IS_GOT_BASED(rtype) &&
- IS_PC_RELATIVE(rtype) &&
- ((sdp->sd_isc) && (sdp->sd_isc->is_osdesc == isp->is_osdesc)))
- return (add_actrel(NULL, rsp, ofl));
-
- /*
- * If '-zredlocsym' is in effect make all local sym relocations
- * against the 'section symbols', since they are the only symbols
- * which will be added to the .symtab.
- */
- if (local && (((ofl->ofl_flags1 & FLG_OF1_REDLSYM) &&
- (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL)) ||
- ((sdp->sd_flags1 & FLG_SY1_ELIM) && (flags & FLG_OF_PROCRED)))) {
- /*
- * But if this is a PIC code, don't allow it for now.
- */
- if (IS_GOT_RELATIVE(rsp->rel_rtype)) {
- eprintf(ERR_FATAL, MSG_INTL(MSG_REL_PICREDLOC),
- demangle(rsp->rel_sname),
- rsp->rel_isdesc->is_file->ifl_name,
- conv_reloc_SPARC_type_str(rsp->rel_rtype));
- return (S_ERROR);
- }
- return (add_outrel(FLG_REL_SCNNDX | FLG_REL_ADVAL, rsp, ofl));
- }
-
- return (add_outrel(NULL, rsp, ofl));
-}
-
-
/*
* allocate_got: if a GOT is to be made, after the section is built this
* function is called to allocate all the GOT slots. The allocation is
diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README
index 28f49f0707..6a625b6170 100644
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README
@@ -1084,3 +1084,5 @@ Bugid Risk Synopsis
6326497 ld.so not properly processing LD_LIBRARY_PATH ending in :
6307146 mcs dumps core when appending null string to comment section
6371877 LD_PROFILE_64 with gprof does not produce correct results on amd64
+6372082 ld -r erroneously creates .got section on i386
+6201866 amd64: linker symbol elimination is broken
diff --git a/usr/src/uts/common/krtld/reloc.h b/usr/src/uts/common/krtld/reloc.h
index d83e5ae508..8b13de461d 100644
--- a/usr/src/uts/common/krtld/reloc.h
+++ b/usr/src/uts/common/krtld/reloc.h
@@ -21,7 +21,7 @@
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -96,8 +96,11 @@ extern const Rel_entry reloc_table[];
(FLG_RE_GOTPC | FLG_RE_GOTADD))
#define IS_GOT_BASED(X) ((reloc_table[(X)].re_flags & \
FLG_RE_GOTREL) != 0)
-#define IS_GOT_INS(X) ((reloc_table[(X)].re_flags &\
+#define IS_GOT_INS(X) ((reloc_table[(X)].re_flags & \
FLG_RE_GOTOPINS) != 0)
+#define IS_GOT_REQUIRED(X) ((reloc_table[(X)].re_flags & \
+ (FLG_RE_GOTADD | FLG_RE_GOTREL | \
+ FLG_RE_GOTPC | FLG_RE_GOTOPINS)) != 0)
#define IS_PC_RELATIVE(X) ((reloc_table[(X)].re_flags & \
FLG_RE_PCREL) != 0)
#define IS_ADD_RELATIVE(X) ((reloc_table[(X)].re_flags & \
diff --git a/usr/src/uts/sparc/krtld/doreloc.c b/usr/src/uts/sparc/krtld/doreloc.c
index 083d0dcbf4..446f9a82bc 100644
--- a/usr/src/uts/sparc/krtld/doreloc.c
+++ b/usr/src/uts/sparc/krtld/doreloc.c
@@ -21,7 +21,7 @@
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -72,11 +72,10 @@ const Rel_entry reloc_table[R_SPARC_NUM] = {
/* R_SPARC_GOT13 */ {0x0, FLG_RE_GOTADD | FLG_RE_VERIFY | FLG_RE_SIGN,
4, 0, 13},
/* R_SPARC_GOT22 */ {0x0, FLG_RE_GOTADD, 4, 10, 22},
-/* R_SPARC_PC10 */ {0x3ff, FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_SIGN |
- FLG_RE_LOCLBND, 4, 0, 13},
-/* R_SPARC_PC22 */ {0x0, FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_SIGN |
- FLG_RE_VERIFY | FLG_RE_LOCLBND,
- 4, 10, 22},
+/* R_SPARC_PC10 */ {0x3ff, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_LOCLBND,
+ 4, 0, 13},
+/* R_SPARC_PC22 */ {0x0, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_VERIFY |
+ FLG_RE_LOCLBND, 4, 10, 22},
/* R_SPARC_WPLT30 */ {0x0, FLG_RE_PCREL | FLG_RE_PLTREL |
FLG_RE_VERIFY | FLG_RE_SIGN,
4, 2, 30},
@@ -111,11 +110,11 @@ const Rel_entry reloc_table[R_SPARC_NUM] = {
/* R_SPARC_HH22 */ {0x0, FLG_RE_VERIFY, 4, 42, 22}, /* V9 */
/* R_SPARC_HM10 */ {0x3ff, FLG_RE_SIGN, 4, 32, 13}, /* V9 */
/* R_SPARC_LM22 */ {0x0, FLG_RE_NOTREL, 4, 10, 22}, /* V9 */
-/* R_SPARC_PC_HH22 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_GOTPC,
+/* R_SPARC_PC_HH22 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY,
4, 42, 22}, /* V9 */
-/* R_SPARC_PC_HM10 */ {0x3ff, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_GOTPC,
+/* R_SPARC_PC_HM10 */ {0x3ff, FLG_RE_PCREL | FLG_RE_SIGN,
4, 32, 13}, /* V9 */
-/* R_SPARC_PC_LM22 */ {0x0, FLG_RE_PCREL | FLG_RE_GOTPC,
+/* R_SPARC_PC_LM22 */ {0x0, FLG_RE_PCREL,
4, 10, 22}, /* V9 */
/* R_SPARC_WDISP16 */ {0x0, FLG_RE_PCREL | FLG_RE_WDISP16 |
FLG_RE_VERIFY | FLG_RE_SIGN,