diff options
| -rw-r--r-- | usr/src/cmd/sgs/elfdump/common/elfdump.c | 34 | ||||
| -rw-r--r-- | usr/src/cmd/sgs/elfdump/common/elfdump.msg | 15 | ||||
| -rw-r--r-- | usr/src/cmd/sgs/libld/amd64/machrel.c | 222 | ||||
| -rw-r--r-- | usr/src/cmd/sgs/libld/common/_libld.h | 5 | ||||
| -rw-r--r-- | usr/src/cmd/sgs/libld/common/relocate.c | 194 | ||||
| -rw-r--r-- | usr/src/cmd/sgs/libld/i386/machrel.c | 247 | ||||
| -rw-r--r-- | usr/src/cmd/sgs/libld/sparc/machrel.c | 199 | ||||
| -rw-r--r-- | usr/src/cmd/sgs/packages/common/SUNWonld-README | 2 | ||||
| -rw-r--r-- | usr/src/uts/common/krtld/reloc.h | 7 | ||||
| -rw-r--r-- | usr/src/uts/sparc/krtld/doreloc.c | 17 |
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, |
