summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ChangeLog19
-rw-r--r--src/elflint.c13
-rw-r--r--src/strip.c568
-rw-r--r--tests/ChangeLog13
-rw-r--r--tests/Makefile.am7
-rwxr-xr-xtests/run-strip-test.sh9
-rwxr-xr-xtests/run-strip-test8.sh5
-rw-r--r--tests/testfile16.bz2bin8424 -> 8413 bytes
-rw-r--r--tests/testfile16.debug.bz2bin23520 -> 24257 bytes
-rw-r--r--tests/testfile47.bz2bin0 -> 793 bytes
-rw-r--r--tests/testfile48.bz2bin0 -> 408 bytes
-rw-r--r--tests/testfile48.debug.bz2bin0 -> 758 bytes
12 files changed, 362 insertions, 272 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 41267ea0..94444c58 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,22 @@
+2008-04-10 Roland McGrath <roland@redhat.com>
+
+ * strip.c (handle_elf): Don't keep sections that kept symbol tables
+ refer to. Instead, just be sure to preserve the original symbol
+ table in the debug file so those symbols go with their sections and
+ can be elided from the stripped version of the symbol table.
+
+ * strip.c (handle_elf): When a discarded section kept in the debug
+ file refers to a nondiscard section via sh_link/sh_info, preserve
+ that nondiscarded section unmodified in the debug file as well.
+ Skip adjustment of discarded sections symbol table references when
+ that symbol table is copied in this way.
+
+ * elflint.c (check_symtab): Don't crash from missing symbol names
+ after diagnosing bogus strtab.
+
+ * strip.c (handle_elf): Cosmetic cleanup in special section contents
+ adjustment for symtab changes.
+
2008-03-31 Roland McGrath <roland@redhat.com>
* elflint.c (check_sections): Add checks on SHF_EXECINSTR sections:
diff --git a/src/elflint.c b/src/elflint.c
index b13dfdb5..bc4219b3 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -579,9 +579,12 @@ check_symtab (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
return;
if (strshdr->sh_type != SHT_STRTAB)
- ERROR (gettext ("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
- shdr->sh_link, section_name (ebl, shdr->sh_link),
- idx, section_name (ebl, idx));
+ {
+ ERROR (gettext ("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
+ shdr->sh_link, section_name (ebl, shdr->sh_link),
+ idx, section_name (ebl, idx));
+ strshdr = NULL;
+ }
/* Search for an extended section index table section. */
Elf_Data *xndxdata = NULL;
@@ -659,7 +662,9 @@ section [%2d] '%s': XINDEX for zeroth entry not zero\n"),
}
const char *name = NULL;
- if (sym->st_name >= strshdr->sh_size)
+ if (strshdr == NULL)
+ name = "";
+ else if (sym->st_name >= strshdr->sh_size)
ERROR (gettext ("\
section [%2d] '%s': symbol %zu: invalid name value\n"),
idx, section_name (ebl, idx), cnt);
diff --git a/src/strip.c b/src/strip.c
index 5fddeeeb..0f83e61d 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -1,5 +1,5 @@
/* Discard section not used at runtime from object files.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
+ Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
@@ -390,6 +390,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
Elf_Scn *scn;
GElf_Shdr shdr;
Elf_Data *data;
+ Elf_Data *debug_data;
const char *name;
Elf32_Word idx; /* Index in new file. */
Elf32_Word old_sh_link; /* Original value of shdr.sh_link. */
@@ -720,8 +721,10 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
/* The content of symbol tables we don't remove must not
reference any section which we do remove. Otherwise
we cannot remove the section. */
- if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
- || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
+ if (debug_fname != NULL
+ && shdr_info[cnt].debug_data == NULL
+ && (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
+ || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB))
{
/* Make sure the data is loaded. */
if (shdr_info[cnt].data == NULL)
@@ -779,11 +782,10 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
scnidx = xndx;
if (shdr_info[scnidx].idx == 0)
- {
- /* Mark this section as used. */
- shdr_info[scnidx].idx = 1;
- changes |= scnidx < cnt;
- }
+ /* This symbol table has a real symbol in
+ a discarded section. So preserve the
+ original table in the debug file. */
+ shdr_info[cnt].debug_data = symdata;
}
}
@@ -819,6 +821,36 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
/* Mark the section as investigated. */
shdr_info[cnt].idx = 2;
}
+
+ if (debug_fname != NULL
+ && (shdr_info[cnt].idx == 0 || shdr_info[cnt].debug_data != NULL))
+ {
+ /* This section is being preserved in the debug file.
+ Sections it refers to must be preserved there too.
+
+ In this pass we mark sections to be preserved in both
+ files by setting the .debug_data pointer to the original
+ file's .data pointer. Below, we'll copy the section
+ contents. */
+
+ inline void check_preserved (size_t i)
+ {
+ if (i != 0 && shdr_info[i].idx != 0)
+ {
+ if (shdr_info[i].data == NULL)
+ shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
+ if (shdr_info[i].data == NULL)
+ INTERNAL_ERROR (fname);
+
+ shdr_info[i].debug_data = shdr_info[i].data;
+ changes |= i < cnt;
+ }
+ }
+
+ check_preserved (shdr_info[cnt].shdr.sh_link);
+ if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
+ check_preserved (shdr_info[cnt].shdr.sh_info);
+ }
}
}
while (changes);
@@ -836,6 +868,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
elf_errmsg (-1));
bool discard_section = (shdr_info[cnt].idx > 0
+ && shdr_info[cnt].debug_data == NULL
&& shdr_info[cnt].shdr.sh_type != SHT_NOTE
&& cnt != ehdr->e_shstrndx);
@@ -866,6 +899,13 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
*debugdata = *shdr_info[cnt].data;
if (discard_section)
debugdata->d_buf = NULL;
+ else if (shdr_info[cnt].debug_data != NULL)
+ {
+ /* Copy the original data before it gets modified. */
+ shdr_info[cnt].debug_data = debugdata;
+ debugdata->d_buf = memcpy (xmalloc (debugdata->d_size),
+ debugdata->d_buf, debugdata->d_size);
+ }
}
/* Finish the ELF header. Fill in the fields not handled by
@@ -1078,7 +1118,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
/* We know the size. */
shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
- /* We have to adjust symtol tables. The st_shndx member might
+ /* We have to adjust symbol tables. The st_shndx member might
have to be updated. */
if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
|| shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
@@ -1206,7 +1246,8 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
shdr_info[cnt].shdr.sh_info = destidx - 1;
}
}
- else
+ else if (debug_fname == NULL
+ || shdr_info[cnt].debug_data == NULL)
/* This is a section symbol for a section which has
been removed. */
assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION);
@@ -1248,291 +1289,288 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
/* Adjust symbol references if symbol tables changed. */
if (any_symtab_changes)
- {
- /* Find all relocation sections which use this
- symbol table. */
- for (cnt = 1; cnt <= shdridx; ++cnt)
+ /* Find all relocation sections which use this symbol table. */
+ for (cnt = 1; cnt <= shdridx; ++cnt)
+ {
+ /* Update section headers when the data size has changed.
+ We also update the SHT_NOBITS section in the debug
+ file so that the section headers match in sh_size. */
+ inline void update_section_size (const Elf_Data *newdata)
{
- /* Update section headers when the data size has changed.
- We also update the SHT_NOBITS section in the debug
- file so that the section headers match in sh_size. */
- inline void update_section_size (const Elf_Data *newdata)
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ shdr->sh_size = newdata->d_size;
+ (void) gelf_update_shdr (scn, shdr);
+ if (debugelf != NULL)
{
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- shdr->sh_size = newdata->d_size;
- (void) gelf_update_shdr (scn, shdr);
- if (debugelf != NULL)
- {
- /* libelf will use d_size to set sh_size. */
- Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
- cnt), NULL);
- debugdata->d_size = newdata->d_size;
- }
+ /* libelf will use d_size to set sh_size. */
+ Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
+ cnt), NULL);
+ debugdata->d_size = newdata->d_size;
}
+ }
- if (shdr_info[cnt].idx == 0 && debug_fname == NULL)
- /* Ignore sections which are discarded. When we are saving a
- relocation section in a separate debug file, we must fix up
- the symbol table references. */
- continue;
+ if (shdr_info[cnt].idx == 0 && debug_fname == NULL)
+ /* Ignore sections which are discarded. When we are saving a
+ relocation section in a separate debug file, we must fix up
+ the symbol table references. */
+ continue;
- if (shdr_info[cnt].shdr.sh_type == SHT_REL
- || shdr_info[cnt].shdr.sh_type == SHT_RELA)
+ const Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
+ const Elf32_Word *const newsymidx = shdr_info[symtabidx].newsymidx;
+ switch (shdr_info[cnt].shdr.sh_type)
+ {
+ inline bool no_symtab_updates (void)
{
/* If the symbol table hasn't changed, do not do anything. */
- if (shdr_info[shdr_info[cnt].old_sh_link].newsymidx == NULL)
- continue;
-
- Elf32_Word *newsymidx
- = shdr_info[shdr_info[cnt].old_sh_link].newsymidx;
- Elf_Data *d = elf_getdata (shdr_info[cnt].idx == 0
- ? elf_getscn (debugelf, cnt)
- : elf_getscn (newelf,
- shdr_info[cnt].idx),
- NULL);
- assert (d != NULL);
- size_t nrels = (shdr_info[cnt].shdr.sh_size
- / shdr_info[cnt].shdr.sh_entsize);
-
- if (shdr_info[cnt].shdr.sh_type == SHT_REL)
- for (size_t relidx = 0; relidx < nrels; ++relidx)
- {
- GElf_Rel rel_mem;
- if (gelf_getrel (d, relidx, &rel_mem) == NULL)
- INTERNAL_ERROR (fname);
+ if (shdr_info[symtabidx].newsymidx == NULL)
+ return true;
- size_t symidx = GELF_R_SYM (rel_mem.r_info);
- if (newsymidx[symidx] != symidx)
- {
- rel_mem.r_info
- = GELF_R_INFO (newsymidx[symidx],
- GELF_R_TYPE (rel_mem.r_info));
+ /* If the symbol table is not discarded, but additionally
+ duplicated in the separate debug file and this section
+ is discarded, don't adjust anything. */
+ return (shdr_info[cnt].idx == 0
+ && shdr_info[symtabidx].debug_data != NULL);
+ }
- if (gelf_update_rel (d, relidx, &rel_mem) == 0)
- INTERNAL_ERROR (fname);
- }
- }
- else
- for (size_t relidx = 0; relidx < nrels; ++relidx)
- {
- GElf_Rela rel_mem;
- if (gelf_getrela (d, relidx, &rel_mem) == NULL)
- INTERNAL_ERROR (fname);
+ case SHT_REL:
+ case SHT_RELA:
+ if (no_symtab_updates ())
+ break;
- size_t symidx = GELF_R_SYM (rel_mem.r_info);
- if (newsymidx[symidx] != symidx)
- {
- rel_mem.r_info
- = GELF_R_INFO (newsymidx[symidx],
- GELF_R_TYPE (rel_mem.r_info));
+ Elf_Data *d = elf_getdata (shdr_info[cnt].idx == 0
+ ? elf_getscn (debugelf, cnt)
+ : elf_getscn (newelf,
+ shdr_info[cnt].idx),
+ NULL);
+ assert (d != NULL);
+ size_t nrels = (shdr_info[cnt].shdr.sh_size
+ / shdr_info[cnt].shdr.sh_entsize);
- if (gelf_update_rela (d, relidx, &rel_mem) == 0)
- INTERNAL_ERROR (fname);
- }
- }
- }
- else if (shdr_info[cnt].shdr.sh_type == SHT_HASH)
- {
- /* We have to recompute the hash table. */
- Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
+ if (shdr_info[cnt].shdr.sh_type == SHT_REL)
+ for (size_t relidx = 0; relidx < nrels; ++relidx)
+ {
+ GElf_Rel rel_mem;
+ if (gelf_getrel (d, relidx, &rel_mem) == NULL)
+ INTERNAL_ERROR (fname);
- /* We do not have to do anything if the symbol table was
- not changed. */
- if (shdr_info[symtabidx].newsymidx == NULL)
- continue;
+ size_t symidx = GELF_R_SYM (rel_mem.r_info);
+ if (newsymidx[symidx] != symidx)
+ {
+ rel_mem.r_info
+ = GELF_R_INFO (newsymidx[symidx],
+ GELF_R_TYPE (rel_mem.r_info));
- assert (shdr_info[cnt].idx > 0);
+ if (gelf_update_rel (d, relidx, &rel_mem) == 0)
+ INTERNAL_ERROR (fname);
+ }
+ }
+ else
+ for (size_t relidx = 0; relidx < nrels; ++relidx)
+ {
+ GElf_Rela rel_mem;
+ if (gelf_getrela (d, relidx, &rel_mem) == NULL)
+ INTERNAL_ERROR (fname);
- /* The hash section in the new file. */
- scn = elf_getscn (newelf, shdr_info[cnt].idx);
+ size_t symidx = GELF_R_SYM (rel_mem.r_info);
+ if (newsymidx[symidx] != symidx)
+ {
+ rel_mem.r_info
+ = GELF_R_INFO (newsymidx[symidx],
+ GELF_R_TYPE (rel_mem.r_info));
- /* The symbol table data. */
- Elf_Data *symd = elf_getdata (elf_getscn (newelf,
- shdr_info[symtabidx].idx),
- NULL);
- assert (symd != NULL);
+ if (gelf_update_rela (d, relidx, &rel_mem) == 0)
+ INTERNAL_ERROR (fname);
+ }
+ }
+ break;
- /* The hash table data. */
- Elf_Data *hashd = elf_getdata (scn, NULL);
- assert (hashd != NULL);
+ case SHT_HASH:
+ if (no_symtab_updates ())
+ break;
- if (shdr_info[cnt].shdr.sh_entsize == sizeof (Elf32_Word))
- {
- /* Sane arches first. */
- Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
+ /* We have to recompute the hash table. */
- size_t strshndx = shdr_info[symtabidx].old_sh_link;
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
- ehdr->e_version);
+ assert (shdr_info[cnt].idx > 0);
- /* Adjust the nchain value. The symbol table size
- changed. We keep the same size for the bucket array. */
- bucket[1] = symd->d_size / elsize;
- Elf32_Word nbucket = bucket[0];
- bucket += 2;
- Elf32_Word *chain = bucket + nbucket;
-
- /* New size of the section. */
- hashd->d_size = ((2 + symd->d_size / elsize + nbucket)
- * sizeof (Elf32_Word));
- update_section_size (hashd);
-
- /* Clear the arrays. */
- memset (bucket, '\0',
- (symd->d_size / elsize + nbucket)
- * sizeof (Elf32_Word));
-
- for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
- inner < symd->d_size / elsize; ++inner)
- {
- GElf_Sym sym_mem;
- GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
- assert (sym != NULL);
+ /* The hash section in the new file. */
+ scn = elf_getscn (newelf, shdr_info[cnt].idx);
- const char *name = elf_strptr (elf, strshndx,
- sym->st_name);
- assert (name != NULL);
- size_t hidx = elf_hash (name) % nbucket;
+ /* The symbol table data. */
+ Elf_Data *symd = elf_getdata (elf_getscn (newelf,
+ shdr_info[symtabidx].idx),
+ NULL);
+ assert (symd != NULL);
- if (bucket[hidx] == 0)
- bucket[hidx] = inner;
- else
- {
- hidx = bucket[hidx];
+ /* The hash table data. */
+ Elf_Data *hashd = elf_getdata (scn, NULL);
+ assert (hashd != NULL);
- while (chain[hidx] != 0)
- hidx = chain[hidx];
+ if (shdr_info[cnt].shdr.sh_entsize == sizeof (Elf32_Word))
+ {
+ /* Sane arches first. */
+ Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
- chain[hidx] = inner;
- }
- }
- }
- else
- {
- /* Alpha and S390 64-bit use 64-bit SHT_HASH entries. */
- assert (shdr_info[cnt].shdr.sh_entsize
- == sizeof (Elf64_Xword));
+ size_t strshndx = shdr_info[symtabidx].old_sh_link;
+ size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
+ ehdr->e_version);
- Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
+ /* Adjust the nchain value. The symbol table size
+ changed. We keep the same size for the bucket array. */
+ bucket[1] = symd->d_size / elsize;
+ Elf32_Word nbucket = bucket[0];
+ bucket += 2;
+ Elf32_Word *chain = bucket + nbucket;
+
+ /* New size of the section. */
+ hashd->d_size = ((2 + symd->d_size / elsize + nbucket)
+ * sizeof (Elf32_Word));
+ update_section_size (hashd);
+
+ /* Clear the arrays. */
+ memset (bucket, '\0',
+ (symd->d_size / elsize + nbucket)
+ * sizeof (Elf32_Word));
+
+ for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
+ inner < symd->d_size / elsize; ++inner)
+ {
+ GElf_Sym sym_mem;
+ GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
+ assert (sym != NULL);
- size_t strshndx = shdr_info[symtabidx].old_sh_link;
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
- ehdr->e_version);
+ const char *name = elf_strptr (elf, strshndx,
+ sym->st_name);
+ assert (name != NULL);
+ size_t hidx = elf_hash (name) % nbucket;
- /* Adjust the nchain value. The symbol table size
- changed. We keep the same size for the bucket array. */
- bucket[1] = symd->d_size / elsize;
- Elf64_Xword nbucket = bucket[0];
- bucket += 2;
- Elf64_Xword *chain = bucket + nbucket;
-
- /* New size of the section. */
- hashd->d_size = ((2 + symd->d_size / elsize + nbucket)
- * sizeof (Elf64_Xword));
- update_section_size (hashd);
-
- /* Clear the arrays. */
- memset (bucket, '\0',
- (symd->d_size / elsize + nbucket)
- * sizeof (Elf64_Xword));
-
- for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
- inner < symd->d_size / elsize; ++inner)
- {
- GElf_Sym sym_mem;
- GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
- assert (sym != NULL);
+ if (bucket[hidx] == 0)
+ bucket[hidx] = inner;
+ else
+ {
+ hidx = bucket[hidx];
- const char *name = elf_strptr (elf, strshndx,
- sym->st_name);
- assert (name != NULL);
- size_t hidx = elf_hash (name) % nbucket;
+ while (chain[hidx] != 0)
+ hidx = chain[hidx];
- if (bucket[hidx] == 0)
- bucket[hidx] = inner;
- else
- {
- hidx = bucket[hidx];
+ chain[hidx] = inner;
+ }
+ }
+ }
+ else
+ {
+ /* Alpha and S390 64-bit use 64-bit SHT_HASH entries. */
+ assert (shdr_info[cnt].shdr.sh_entsize
+ == sizeof (Elf64_Xword));
- while (chain[hidx] != 0)
- hidx = chain[hidx];
+ Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
- chain[hidx] = inner;
- }
- }
- }
- }
- else if (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym)
- {
- /* If the symbol table changed we have to adjust the
- entries. */
- Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
+ size_t strshndx = shdr_info[symtabidx].old_sh_link;
+ size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
+ ehdr->e_version);
- /* We do not have to do anything if the symbol table was
- not changed. */
- if (shdr_info[symtabidx].newsymidx == NULL)
- continue;
-
- assert (shdr_info[cnt].idx > 0);
-
- /* The symbol version section in the new file. */
- scn = elf_getscn (newelf, shdr_info[cnt].idx);
-
- /* The symbol table data. */
- Elf_Data *symd = elf_getdata (elf_getscn (newelf,
- shdr_info[symtabidx].idx),
- NULL);
- assert (symd != NULL);
-
- /* The version symbol data. */
- Elf_Data *verd = elf_getdata (scn, NULL);
- assert (verd != NULL);
-
- /* The symbol version array. */
- GElf_Half *verstab = (GElf_Half *) verd->d_buf;
-
- /* New indices of the symbols. */
- Elf32_Word *newsymidx = shdr_info[symtabidx].newsymidx;
-
- /* Walk through the list and */
- size_t elsize = gelf_fsize (elf, verd->d_type, 1,
- ehdr->e_version);
- for (size_t inner = 1; inner < verd->d_size / elsize; ++inner)
- if (newsymidx[inner] != 0)
- /* Overwriting the same array works since the
- reordering can only move entries to lower indices
- in the array. */
- verstab[newsymidx[inner]] = verstab[inner];
-
- /* New size of the section. */
- verd->d_size = gelf_fsize (newelf, verd->d_type,
- symd->d_size
- / gelf_fsize (elf, symd->d_type, 1,
- ehdr->e_version),
- ehdr->e_version);
- update_section_size (verd);
- }
- else if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
- {
- /* Check whether the associated symbol table changed. */
- if (shdr_info[shdr_info[cnt].old_sh_link].newsymidx != NULL)
- {
- /* Yes the symbol table changed. Update the section
- header of the section group. */
- scn = elf_getscn (newelf, shdr_info[cnt].idx);
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- assert (shdr != NULL);
+ /* Adjust the nchain value. The symbol table size
+ changed. We keep the same size for the bucket array. */
+ bucket[1] = symd->d_size / elsize;
+ Elf64_Xword nbucket = bucket[0];
+ bucket += 2;
+ Elf64_Xword *chain = bucket + nbucket;
+
+ /* New size of the section. */
+ hashd->d_size = ((2 + symd->d_size / elsize + nbucket)
+ * sizeof (Elf64_Xword));
+ update_section_size (hashd);
+
+ /* Clear the arrays. */
+ memset (bucket, '\0',
+ (symd->d_size / elsize + nbucket)
+ * sizeof (Elf64_Xword));
+
+ for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
+ inner < symd->d_size / elsize; ++inner)
+ {
+ GElf_Sym sym_mem;
+ GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
+ assert (sym != NULL);
- size_t stabidx = shdr_info[cnt].old_sh_link;
- shdr->sh_info = shdr_info[stabidx].newsymidx[shdr->sh_info];
+ const char *name = elf_strptr (elf, strshndx,
+ sym->st_name);
+ assert (name != NULL);
+ size_t hidx = elf_hash (name) % nbucket;
- (void) gelf_update_shdr (scn, shdr);
- }
- }
- }
- }
+ if (bucket[hidx] == 0)
+ bucket[hidx] = inner;
+ else
+ {
+ hidx = bucket[hidx];
+
+ while (chain[hidx] != 0)
+ hidx = chain[hidx];
+
+ chain[hidx] = inner;
+ }
+ }
+ }
+ break;
+
+ case SHT_GNU_versym:
+ /* If the symbol table changed we have to adjust the entries. */
+ if (no_symtab_updates ())
+ break;
+
+ assert (shdr_info[cnt].idx > 0);
+
+ /* The symbol version section in the new file. */
+ scn = elf_getscn (newelf, shdr_info[cnt].idx);
+
+ /* The symbol table data. */
+ symd = elf_getdata (elf_getscn (newelf, shdr_info[symtabidx].idx),
+ NULL);
+ assert (symd != NULL);
+
+ /* The version symbol data. */
+ Elf_Data *verd = elf_getdata (scn, NULL);
+ assert (verd != NULL);
+
+ /* The symbol version array. */
+ GElf_Half *verstab = (GElf_Half *) verd->d_buf;
+
+ /* Walk through the list and */
+ size_t elsize = gelf_fsize (elf, verd->d_type, 1,
+ ehdr->e_version);
+ for (size_t inner = 1; inner < verd->d_size / elsize; ++inner)
+ if (newsymidx[inner] != 0)
+ /* Overwriting the same array works since the
+ reordering can only move entries to lower indices
+ in the array. */
+ verstab[newsymidx[inner]] = verstab[inner];
+
+ /* New size of the section. */
+ verd->d_size = gelf_fsize (newelf, verd->d_type,
+ symd->d_size
+ / gelf_fsize (elf, symd->d_type, 1,
+ ehdr->e_version),
+ ehdr->e_version);
+ update_section_size (verd);
+ break;
+
+ case SHT_GROUP:
+ if (no_symtab_updates ())
+ break;
+
+ /* Yes, the symbol table changed.
+ Update the section header of the section group. */
+ scn = elf_getscn (newelf, shdr_info[cnt].idx);
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ assert (shdr != NULL);
+
+ shdr->sh_info = newsymidx[shdr->sh_info];
+
+ (void) gelf_update_shdr (scn, shdr);
+ break;
+ }
+ }
/* Now that we have done all adjustments to the data,
we can actually write out the debug file. */
@@ -1659,7 +1697,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
table indices. */
if (any_symtab_changes)
for (cnt = 1; cnt <= shdridx; ++cnt)
- free (shdr_info[cnt].newsymidx);
+ {
+ free (shdr_info[cnt].newsymidx);
+ if (shdr_info[cnt].debug_data != NULL)
+ free (shdr_info[cnt].debug_data->d_buf);
+ }
/* Free the memory. */
if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index d9d74692..c9bba45c 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,16 @@
+2008-04-10 Roland McGrath <roland@redhat.com>
+
+ * testfile48.bz2, testfile48.bz2.debug: New data files.
+ * Makefile.am (EXTRA_DIST): Add them.
+ * run-strip-test8.sh: Use them.
+
+ * testfile16.bz2, testfile16.debug.bz2: Replace data files.
+
+ * run-strip-test.sh: Fail if stripped output has ".debug_*" sections.
+ * run-strip-test8.sh: New file.
+ * testfile47.bz2: New data file.
+ * Makefile.am (TESTS, EXTRA_DIST): Add them.
+
2008-03-31 Roland McGrath <roland@redhat.com>
* run-early-offscn.sh: New file.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f0b20e9d..361c6581 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -71,7 +71,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
run-show-abbrev.sh run-line2addr.sh hash \
newscn run-strip-test.sh run-strip-test2.sh \
run-strip-test3.sh run-strip-test4.sh run-strip-test5.sh \
- run-strip-test6.sh run-strip-test7.sh \
+ run-strip-test6.sh run-strip-test7.sh run-strip-test8.sh \
run-unstrip-test.sh run-unstrip-test2.sh \
run-ecp-test.sh run-ecp-test2.sh \
run-elflint-test.sh run-elflint-self.sh run-ranlib-test.sh \
@@ -110,7 +110,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
testfile13.bz2 run-strip-test3.sh run-allfcts.sh \
run-line2addr.sh run-elflint-test.sh testfile14.bz2 \
run-strip-test4.sh run-strip-test5.sh run-strip-test6.sh \
- run-strip-test7.sh run-unstrip-test.sh run-unstrip-test2.sh \
+ run-strip-test7.sh run-strip-test8.sh \
+ run-unstrip-test.sh run-unstrip-test2.sh \
run-elflint-self.sh run-ranlib-test.sh run-ranlib-test2.sh \
run-ranlib-test3.sh run-ranlib-test4.sh \
run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \
@@ -138,7 +139,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
testfile41.bz2 testfile42.bz2 testfile43.bz2 \
testfile44.S.bz2 testfile44.expect.bz2 run-disasm-x86.sh \
testfile45.S.bz2 testfile45.expect.bz2 run-disasm-x86-64.sh \
- testfile46.bz2
+ testfile46.bz2 testfile47.bz2 testfile48.bz2 testfile48.debug.bz2
installed_TESTS_ENVIRONMENT = libdir=$(DESTDIR)$(libdir) \
bindir=$(DESTDIR)$(bindir) \
diff --git a/tests/run-strip-test.sh b/tests/run-strip-test.sh
index 480101eb..e056f890 100755
--- a/tests/run-strip-test.sh
+++ b/tests/run-strip-test.sh
@@ -1,5 +1,5 @@
#! /bin/sh
-# Copyright (C) 1999, 2000, 2002, 2003, 2005, 2007 Red Hat, Inc.
+# Copyright (C) 1999, 2000, 2002, 2003, 2005, 2007, 2008 Red Hat, Inc.
# This file is part of Red Hat elfutils.
# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
#
@@ -30,7 +30,8 @@ original=${original:-testfile11}
stripped=${stripped:-testfile7}
debugout=${debugfile:+-f testfile.debug.temp -F $debugfile}
-testfiles $original $stripped $debugfile
+testfiles $original
+test x$stripped = xtestfile.temp || testfiles $stripped $debugfile
tempfiles testfile.temp testfile.debug.temp testfile.unstrip
@@ -56,4 +57,8 @@ testrun ../src/unstrip -o testfile.unstrip testfile.temp testfile.debug.temp
testrun ../src/elfcmp --hash-inexact $original testfile.unstrip
}
+tempfiles testfile.sections
+testrun ../src/readelf -S testfile.temp > testfile.sections || status=$?
+fgrep ' .debug_' testfile.sections && status=1
+
exit $status
diff --git a/tests/run-strip-test8.sh b/tests/run-strip-test8.sh
new file mode 100755
index 00000000..fb9fa087
--- /dev/null
+++ b/tests/run-strip-test8.sh
@@ -0,0 +1,5 @@
+original=testfile47
+stripped=testfile48
+debugfile=testfile48.debug
+
+. $srcdir/run-strip-test.sh
diff --git a/tests/testfile16.bz2 b/tests/testfile16.bz2
index 909e2253..4d7160c0 100644
--- a/tests/testfile16.bz2
+++ b/tests/testfile16.bz2
Binary files differ
diff --git a/tests/testfile16.debug.bz2 b/tests/testfile16.debug.bz2
index 48d651fb..f02a9723 100644
--- a/tests/testfile16.debug.bz2
+++ b/tests/testfile16.debug.bz2
Binary files differ
diff --git a/tests/testfile47.bz2 b/tests/testfile47.bz2
new file mode 100644
index 00000000..334bd6c4
--- /dev/null
+++ b/tests/testfile47.bz2
Binary files differ
diff --git a/tests/testfile48.bz2 b/tests/testfile48.bz2
new file mode 100644
index 00000000..da0d9dab
--- /dev/null
+++ b/tests/testfile48.bz2
Binary files differ
diff --git a/tests/testfile48.debug.bz2 b/tests/testfile48.debug.bz2
new file mode 100644
index 00000000..7b84c4ca
--- /dev/null
+++ b/tests/testfile48.debug.bz2
Binary files differ