summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorAli Bahrami <Ali.Bahrami@Sun.COM>2009-02-10 14:50:39 -0700
committerAli Bahrami <Ali.Bahrami@Sun.COM>2009-02-10 14:50:39 -0700
commit1da7e59911a9f3f267c3ef294dc342767dee7952 (patch)
tree68e1aaf4b4597c1b1a3111c5391b233d3ab08154 /usr/src
parentab69d62f363ee70f4e4cded1092a68cc0c63136f (diff)
downloadillumos-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.c17
-rw-r--r--usr/src/cmd/sgs/elfdump/common/elfdump.msg4
-rw-r--r--usr/src/cmd/sgs/libconv/common/c_literal.c6
-rw-r--r--usr/src/cmd/sgs/libld/common/_libld.h8
-rw-r--r--usr/src/cmd/sgs/libld/common/globals.c22
-rw-r--r--usr/src/cmd/sgs/libld/common/outfile.c67
-rw-r--r--usr/src/cmd/sgs/libld/common/sections.c106
-rw-r--r--usr/src/cmd/sgs/libld/common/syms.c6
-rw-r--r--usr/src/cmd/sgs/libld/common/update.c23
-rw-r--r--usr/src/cmd/sgs/libld/common/version.c10
-rw-r--r--usr/src/cmd/sgs/packages/common/SUNWonld-README1
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