summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland McGrath <[email protected]>2008-04-11 07:01:58 +0000
committerRoland McGrath <[email protected]>2008-04-11 07:01:58 +0000
commit521c47d2a216fc64098c024fc5ed53532b485f32 (patch)
treea0ac572e77cbdded1f90fb1996d95cbe3890c36b
parent9c4242ef635e2017b1aab2975e4529791b24208f (diff)
src/
* 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. tests/ * testfile48.bz2, testfile48.bz2.debug: New data files. * Makefile.am (EXTRA_DIST): Add them. * run-strip-test8.sh: Use them.
-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 <[email protected]>
+
+ * 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 <[email protected]>
* 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 <[email protected]>, 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 <[email protected]>
+
+ * 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 <[email protected]>
* 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 <[email protected]>, 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