diff options
author | Ali Bahrami <Ali.Bahrami@Sun.COM> | 2009-02-10 14:50:39 -0700 |
---|---|---|
committer | Ali Bahrami <Ali.Bahrami@Sun.COM> | 2009-02-10 14:50:39 -0700 |
commit | 1da7e59911a9f3f267c3ef294dc342767dee7952 (patch) | |
tree | 68e1aaf4b4597c1b1a3111c5391b233d3ab08154 /usr/src | |
parent | ab69d62f363ee70f4e4cded1092a68cc0c63136f (diff) | |
download | illumos-gate-1da7e59911a9f3f267c3ef294dc342767dee7952.tar.gz |
6800388 shstrtab can be sized incorrectly when -z ignore is used
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/sgs/elfdump/common/elfdump.c | 17 | ||||
-rw-r--r-- | usr/src/cmd/sgs/elfdump/common/elfdump.msg | 4 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libconv/common/c_literal.c | 6 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/_libld.h | 8 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/globals.c | 22 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/outfile.c | 67 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/sections.c | 106 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/syms.c | 6 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/update.c | 23 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/version.c | 10 | ||||
-rw-r--r-- | usr/src/cmd/sgs/packages/common/SUNWonld-README | 1 |
11 files changed, 154 insertions, 116 deletions
diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.c b/usr/src/cmd/sgs/elfdump/common/elfdump.c index 58cfdda21e..d7c74f7bad 100644 --- a/usr/src/cmd/sgs/elfdump/common/elfdump.c +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -3866,6 +3866,21 @@ shdr_cache(const char *file, Elf *elf, Ehdr *ehdr, size_t shstrndx, (void) fprintf(stderr, MSG_INTL(MSG_ELF_ERR_SCNDATA), EC_WORD(elf_ndxscn(scn))); } + + /* + * If a string table, verify that it has NULL first and + * final bytes. + */ + if ((_cache->c_shdr->sh_type == SHT_STRTAB) && + (_cache->c_data->d_buf != NULL) && + (_cache->c_data->d_size > 0)) { + const char *s = _cache->c_data->d_buf; + + if ((*s != '\0') || + (*(s + _cache->c_data->d_size - 1) != '\0')) + (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALSTR), + file, _cache->c_name); + } } return (1); diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.msg b/usr/src/cmd/sgs/elfdump/common/elfdump.msg index 5d02a70f30..f3c60c27cb 100644 --- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg @@ -20,7 +20,7 @@ # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -148,6 +148,8 @@ shdr[%d: %s].sh_entsize (%#llx)\n" @ MSG_ERR_DYNSYMVAL "%s: %s: symbol value does not match \ DT_%s entry: %s: value: %#llx\n" +@ MSG_ERR_MALSTR "%s: %s: malformed string table, initial or final byte\n" + @ MSG_WARN_INVINTERP1 "%s: PT_INTERP header has no associated section\n" @ MSG_WARN_INVINTERP2 "%s: interp section: %s: and PT_INTERP program \ diff --git a/usr/src/cmd/sgs/libconv/common/c_literal.c b/usr/src/cmd/sgs/libconv/common/c_literal.c index 8e72749437..8d7d124663 100644 --- a/usr/src/cmd/sgs/libconv/common/c_literal.c +++ b/usr/src/cmd/sgs/libconv/common/c_literal.c @@ -20,12 +20,10 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Translate a string into C literal string constant notation. @@ -132,7 +130,7 @@ conv_str_to_c_literal(const char *buf, size_t n, } else { /* Generic unprintable character: Use octal notation */ (void) snprintf(octal_buf, sizeof (octal_buf), - MSG_ORIG(MSG_FMT_OCTCONST), *buf); + MSG_ORIG(MSG_FMT_OCTCONST), (uchar_t)*buf); (*outfunc)(octal_buf, strlen(octal_buf), uvalue); buf++; n--; diff --git a/usr/src/cmd/sgs/libld/common/_libld.h b/usr/src/cmd/sgs/libld/common/_libld.h index 2788ed3aea..42a1dc82da 100644 --- a/usr/src/cmd/sgs/libld/common/_libld.h +++ b/usr/src/cmd/sgs/libld/common/_libld.h @@ -380,8 +380,8 @@ extern List lib_support; extern int demangle_flag; extern const Msg reject[]; extern int Verbose; -extern const int ldynsym_symtype[STT_NUM]; -extern const int dynsymsort_symtype[STT_NUM]; +extern const int ldynsym_symtype[]; +extern const int dynsymsort_symtype[]; /* @@ -557,7 +557,6 @@ extern Sdf_desc *sdf_find(const char *, List *); #define ld_process_open ld64_process_open #define ld_process_ordered ld64_process_ordered #define ld_process_sym_reloc ld64_process_sym_reloc -#define ld_recalc_shdrcnt ld64_recalc_shdrcnt #define ld_reloc_GOT_relative ld64_reloc_GOT_relative #define ld_reloc_plt ld64_reloc_plt #define ld_reloc_remain_entry ld64_reloc_remain_entry @@ -642,7 +641,6 @@ extern Sdf_desc *sdf_find(const char *, List *); #define ld_process_open ld32_process_open #define ld_process_ordered ld32_process_ordered #define ld_process_sym_reloc ld32_process_sym_reloc -#define ld_recalc_shdrcnt ld32_recalc_shdrcnt #define ld_reloc_GOT_relative ld32_reloc_GOT_relative #define ld_reloc_plt ld32_reloc_plt #define ld_reloc_remain_entry ld32_reloc_remain_entry @@ -748,8 +746,6 @@ extern uintptr_t ld_process_ordered(Ifl_desc *, Ofl_desc *, Word, Word); extern uintptr_t ld_process_sym_reloc(Ofl_desc *, Rel_desc *, Rel *, Is_desc *, const char *); -extern void ld_recalc_shdrcnt(Ofl_desc *); - extern uintptr_t ld_reloc_GOT_relative(Boolean, Rel_desc *, Ofl_desc *); extern uintptr_t ld_reloc_plt(Rel_desc *, Ofl_desc *); extern void ld_reloc_remain_entry(Rel_desc *, Os_desc *, diff --git a/usr/src/cmd/sgs/libld/common/globals.c b/usr/src/cmd/sgs/libld/common/globals.c index 200faf4090..51e81ad867 100644 --- a/usr/src/cmd/sgs/libld/common/globals.c +++ b/usr/src/cmd/sgs/libld/common/globals.c @@ -82,7 +82,7 @@ reject[] = { * (indexed by STT_ values). */ const int -ldynsym_symtype[STT_NUM] = { +ldynsym_symtype[] = { 0, /* STT_NOTYPE (not counting 1st slot) */ 0, /* STT_OBJECT */ 1, /* STT_FUNC */ @@ -90,6 +90,15 @@ ldynsym_symtype[STT_NUM] = { 1, /* STT_FILE */ 0, /* STT_COMMON */ 0, /* STT_TLS */ + 0, /* 7 */ + 0, /* 8 */ + 0, /* 9 */ + 0, /* 10 */ + 0, /* 11 */ + 0, /* 12 */ + 0, /* STT_SPARC_REGISTER */ + 0, /* 14 */ + 0, /* 15 */ }; #if STT_NUM != (STT_TLS + 1) #error "STT_NUM has grown. Update ldynsym_symtype[]." @@ -100,7 +109,7 @@ ldynsym_symtype[STT_NUM] = { * (indexed by STT_ values). */ const int -dynsymsort_symtype[STT_NUM] = { +dynsymsort_symtype[] = { 0, /* STT_NOTYPE */ 1, /* STT_OBJECT */ 1, /* STT_FUNC */ @@ -108,6 +117,15 @@ dynsymsort_symtype[STT_NUM] = { 0, /* STT_FILE */ 1, /* STT_COMMON */ 0, /* STT_TLS */ + 0, /* 7 */ + 0, /* 8 */ + 0, /* 9 */ + 0, /* 10 */ + 0, /* 11 */ + 0, /* 12 */ + 0, /* STT_SPARC_REGISTER */ + 0, /* 14 */ + 0, /* 15 */ }; #if STT_NUM != (STT_TLS + 1) #error "STT_NUM has grown. Update dynsymsort_symtype[]." diff --git a/usr/src/cmd/sgs/libld/common/outfile.c b/usr/src/cmd/sgs/libld/common/outfile.c index edca6b33fb..d3d735f3fa 100644 --- a/usr/src/cmd/sgs/libld/common/outfile.c +++ b/usr/src/cmd/sgs/libld/common/outfile.c @@ -344,73 +344,6 @@ create_outsec(Ofl_desc *ofl, Sg_desc *sgp, Os_desc *osp, Word ptype, int shidx, } /* - * Recalculate the number of output sections and update ofl->ofl_shdrcnt. - * - * As new sections are placed, ofl->ofl_shdrcnt is incremented to - * track the count. If -z ignore is not in effect, then this is - * sufficient. If -z ignore is in effect however, the sections that - * are removed are not reflected in the value of ofl->ofl_shdrcnt. - * Determining whether ofl->ofl_shdrcnt should get decremented in - * that situation takes some work to determine, and if multiple - * sections are discarded (which is typical), then it would be - * necessary to do that work each time. Instead, we use this - * routine to recompute the number of output sections once at the end. - */ -void -ld_recalc_shdrcnt(Ofl_desc *ofl) -{ - Sg_desc *sgp; - Listnode *lnp1, *lnp2; - Word cnt = 0; - Is_desc *isp; - Os_desc *osp; - Aliste idx; - - /* - * This code must be kept in sync with the similar code - * found in ld_create_outfile(). - * - * We look at the input sections for every output section, - * looking for at least one input section that won't - * be eliminated. - */ - for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) { - Word ptype = sgp->sg_phdr.p_type; - - for (APLIST_TRAVERSE(sgp->sg_osdescs, idx, osp)) { - - for (LIST_TRAVERSE(&(osp->os_isdescs), lnp2, isp)) { - Ifl_desc *ifl = isp->is_file; - - /* Input section is tagged for discard? */ - if (isp->is_flags & FLG_IS_DISCARD) - continue; - - /* - * If the file is discarded, it will take - * the section with it. - */ - if (ifl && - (((ifl->ifl_flags & FLG_IF_FILEREF) == 0) || - ((ptype == PT_LOAD) && - ((isp->is_flags & FLG_IS_SECTREF) == 0) && - (isp->is_shdr->sh_size > 0))) && - (ifl->ifl_flags & FLG_IF_IGNORE)) - continue; - - /* - * We have found a kept input section. - * so the output section will be created. - */ - cnt++; - break; - } - } - } - ofl->ofl_shdrcnt = cnt; -} - -/* * Create the elf structures that allow the input data to be associated with the * new image: * diff --git a/usr/src/cmd/sgs/libld/common/sections.c b/usr/src/cmd/sgs/libld/common/sections.c index 933c28dd51..a4cd691c3b 100644 --- a/usr/src/cmd/sgs/libld/common/sections.c +++ b/usr/src/cmd/sgs/libld/common/sections.c @@ -164,11 +164,9 @@ ignore_sym(Ofl_desc *ofl, Ifl_desc *ifl, Sym_desc *sdp, int allow_ldynsym) /* * If -zignore has been in effect, scan all input files to determine if the * file, or sections from the file, have been referenced. If not, the file or - * some of the files sections can be discarded. - * - * which haven't been referenced (and hence can be discarded). If sections are - * to be discarded, rescan the output relocations and the symbol table and - * remove the relocations and symbol entries that are no longer required. + * some of the files sections can be discarded. If sections are to be + * discarded, rescan the output relocations and the symbol table and remove + * the relocations and symbol entries that are no longer required. * * Note: It's possible that a section which is being discarded has contributed * to the GOT table or the PLT table. However, we can't at this point @@ -183,12 +181,15 @@ ignore_sym(Ofl_desc *ofl, Ifl_desc *ifl, Sym_desc *sdp, int allow_ldynsym) static uintptr_t ignore_section_processing(Ofl_desc *ofl) { - Listnode *lnp; + Sg_desc *sgp; + Listnode *lnp1, *lnp2; + Is_desc *isp; + Os_desc *osp; Ifl_desc *ifl; Rel_cache *rcp; int allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl); - for (LIST_TRAVERSE(&ofl->ofl_objs, lnp, ifl)) { + for (LIST_TRAVERSE(&ofl->ofl_objs, lnp1, ifl)) { uint_t num, discard; /* @@ -209,14 +210,10 @@ ignore_section_processing(Ofl_desc *ofl) discard = 0; if (ifl->ifl_flags & FLG_IF_FILEREF) { for (num = 1; num < ifl->ifl_shnum; num++) { - Is_desc *isp = ifl->ifl_isdesc[num]; - Os_desc *osp; - Sg_desc *sgp; - - if (((isp = ifl->ifl_isdesc[num]) != 0) && + if (((isp = ifl->ifl_isdesc[num]) != NULL) && ((isp->is_flags & FLG_IS_SECTREF) == 0) && - ((osp = isp->is_osdesc) != 0) && - ((sgp = osp->os_sgdesc) != 0) && + ((osp = isp->is_osdesc) != NULL) && + ((sgp = osp->os_sgdesc) != NULL) && (sgp->sg_phdr.p_type == PT_LOAD)) { discard++; break; @@ -266,16 +263,14 @@ ignore_section_processing(Ofl_desc *ofl) * Scan all output relocations searching for those against discarded or * ignored sections. If one is found, decrement the total outrel count. */ - for (LIST_TRAVERSE(&ofl->ofl_outrels, lnp, rcp)) { + for (LIST_TRAVERSE(&ofl->ofl_outrels, lnp1, rcp)) { Rel_desc *rsp; - Os_desc *osp; /* LINTED */ for (rsp = (Rel_desc *)(rcp + 1); rsp < rcp->rc_free; rsp++) { Is_desc *isc = rsp->rel_isdesc; uint_t flags, entsize; Shdr *shdr; - Ifl_desc *ifl; if ((isc == 0) || ((isc->is_flags & (FLG_IS_SECTREF))) || @@ -308,6 +303,69 @@ ignore_section_processing(Ofl_desc *ofl) ofl->ofl_relocrelcnt--; } } + + /* + * The number of output sections may have decreased. We must make a + * pass over the output sections, and if we detect this situation, + * decrement ofl->ofl_shdrcnt and remove the section name from the + * .shstrtab string table (ofl->ofl_shdrsttab). + * + * This code must be kept in sync with the similar code + * found in outfile.c:ld_create_outfile(). + * + * For each output section, look at the input sections to find at least + * one input section that has not been eliminated. If none are found, + * the -z ignore processing above has eliminated that output section. + */ + for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) { + Aliste idx; + Word ptype = sgp->sg_phdr.p_type; + + for (APLIST_TRAVERSE(sgp->sg_osdescs, idx, osp)) { + int keep = 0; + + for (LIST_TRAVERSE(&(osp->os_isdescs), lnp2, isp)) { + ifl = isp->is_file; + + /* Input section is tagged for discard? */ + if (isp->is_flags & FLG_IS_DISCARD) + continue; + + /* + * If the file is discarded, it will take + * the section with it. + */ + if (ifl && + (((ifl->ifl_flags & FLG_IF_FILEREF) == 0) || + ((ptype == PT_LOAD) && + ((isp->is_flags & FLG_IS_SECTREF) == 0) && + (isp->is_shdr->sh_size > 0))) && + (ifl->ifl_flags & FLG_IF_IGNORE)) + continue; + + /* + * We have found a kept input section, + * so the output section will be created. + */ + keep = 1; + break; + } + /* + * If no section of this name was kept, decrement + * the count and remove the name from .shstrtab. + */ + if (keep == 0) { + /* LINTED - only used for assert() */ + int err; + + ofl->ofl_shdrcnt--; + err = st_delstring(ofl->ofl_shdrsttab, + osp->os_name); + assert(err != -1); + } + } + } + return (1); } @@ -895,7 +953,7 @@ make_dynamic(Ofl_desc *ofl) * determine if an alternative shared object name has been * specified. */ - if (((sdf = ifl->ifl_sdfdesc) != 0) && + if (((sdf = ifl->ifl_sdfdesc) != NULL) && (sdf->sdf_flags & FLG_SDF_SONAME)) ifl->ifl_soname = sdf->sdf_soname; @@ -1419,18 +1477,6 @@ make_symtab(Ofl_desc *ofl) Word symcnt; /* - * We increment the number of sections in the output object - * (ofl->ofl_shdrcnt) as we add them. However, if -z ignore - * processing is in effect, the number of sections later removed - * is not reflected in that count. Updating the count as we - * remove these sections is a relatively expensive operation. - * Hence, if -z ignore is in use, we recompute the number of - * sections in a single final pass. - */ - if (ofl->ofl_flags1 & FLG_OF1_IGNPRC) - ld_recalc_shdrcnt(ofl); - - /* * Create the section headers. Note that we supply an ent_cnt * of 0. We won't know the count until the section has been placed. */ diff --git a/usr/src/cmd/sgs/libld/common/syms.c b/usr/src/cmd/sgs/libld/common/syms.c index 43a09d3ac3..4c975ec7e4 100644 --- a/usr/src/cmd/sgs/libld/common/syms.c +++ b/usr/src/cmd/sgs/libld/common/syms.c @@ -1910,6 +1910,7 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl) const char *name; Sym_desc *rsdp; int shndx_bad = 0; + int symtab_enter = 1; /* * Determine and validate the associated section index. @@ -1980,7 +1981,7 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl) sdp->sd_ref = REF_DYN_SEEN; /* Will not appear in output object */ - ofl->ofl_locscnt--; + symtab_enter = 0; } } else if (etype == ET_DYN) continue; @@ -2164,7 +2165,8 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl) * (and hence symbol resolution) is complete during * sym_validate(). */ - if (!(ofl->ofl_flags & FLG_OF_REDLSYM)) { + if (!(ofl->ofl_flags & FLG_OF_REDLSYM) && + symtab_enter) { ofl->ofl_locscnt++; if ((((sdp->sd_flags & FLG_SY_REGSYM) == 0) || diff --git a/usr/src/cmd/sgs/libld/common/update.c b/usr/src/cmd/sgs/libld/common/update.c index 6d25653793..63dda77127 100644 --- a/usr/src/cmd/sgs/libld/common/update.c +++ b/usr/src/cmd/sgs/libld/common/update.c @@ -3842,6 +3842,29 @@ ld_update_outfile(Ofl_desc *ofl) } /* + * Sanity test: First and last data byte of a string table + * must be NULL. + */ + assert((ofl->ofl_osshstrtab == NULL) || + (*((char *)ofl->ofl_osshstrtab->os_outdata->d_buf) == '\0')); + assert((ofl->ofl_osshstrtab == NULL) || + (*(((char *)ofl->ofl_osshstrtab->os_outdata->d_buf) + + ofl->ofl_osshstrtab->os_outdata->d_size - 1) == '\0')); + + assert((ofl->ofl_osstrtab == NULL) || + (*((char *)ofl->ofl_osstrtab->os_outdata->d_buf) == '\0')); + assert((ofl->ofl_osstrtab == NULL) || + (*(((char *)ofl->ofl_osstrtab->os_outdata->d_buf) + + ofl->ofl_osstrtab->os_outdata->d_size - 1) == '\0')); + + assert((ofl->ofl_osdynstr == NULL) || + (*((char *)ofl->ofl_osdynstr->os_outdata->d_buf) == '\0')); + assert((ofl->ofl_osdynstr == NULL) || + (*(((char *)ofl->ofl_osdynstr->os_outdata->d_buf) + + ofl->ofl_osdynstr->os_outdata->d_size - DYNSTR_EXTRA_PAD - 1) == + '\0')); + + /* * Emit Strtab diagnostics. */ DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osshstrtab, diff --git a/usr/src/cmd/sgs/libld/common/version.c b/usr/src/cmd/sgs/libld/common/version.c index 6365addc27..26f28bee8f 100644 --- a/usr/src/cmd/sgs/libld/common/version.c +++ b/usr/src/cmd/sgs/libld/common/version.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -461,10 +461,14 @@ ld_vers_check_need(Ofl_desc *ofl) } if (need) { + const char *soname; + ifl->ifl_flags |= FLG_IF_VERNEED; ofl->ofl_verneedsz += sizeof (Verneed); - if (st_insert(ofl->ofl_dynstrtab, - ifl->ifl_soname) == -1) + soname = ((sdf != NULL) && + (sdf->sdf_flags & FLG_SDF_SONAME)) ? + sdf->sdf_soname : ifl->ifl_soname; + if (st_insert(ofl->ofl_dynstrtab, soname) == -1) return (S_ERROR); } } diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README index 74c03bddee..e8345c0b04 100644 --- a/usr/src/cmd/sgs/packages/common/SUNWonld-README +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README @@ -1438,3 +1438,4 @@ Bugid Risk Synopsis 6237063 request extension to dl* family to provide segment bounds information (D) PSARC/2009/054 dlinfo(3c) - segment mapping retrieval +6800388 shstrtab can be sized incorrectly when -z ignore is used |