summaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2000-10-07 13:40:33 +0000
committerAlan Modra <amodra@bigpond.net.au>2000-10-07 13:40:33 +0000
commita06476052954a4d1ccf66ead6ed45c0600d0986c (patch)
treed67d2c468c3f6876eb6303c54ae1a0a59ada0812 /bfd
parent4ebdbeca98c70c7ea509c1799585e02835478a01 (diff)
downloadgdb-a06476052954a4d1ccf66ead6ed45c0600d0986c.tar.gz
Cure a number of segfaults caused by /DISCARD/ of dynamic sections.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elflink.h58
2 files changed, 44 insertions, 21 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 3347191d75f..c683b4d9071 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,12 @@
2000-10-07 Alan Modra <alan@linuxcare.com.au>
+ * elflink.h (size_dynamic_sections): Don't create various tags if
+ .dynstr is excluded from the link. Don't set first dynsym entry
+ if dynsymcount is zero.
+ (elf_bfd_final_link): Don't try to swap out dynamic syms if
+ .dynsym excluded from the link. Don't try to write any dynamic
+ sections excluded from the link.
+
* elf.c (swap_out_syms): Handle global section symbols.
2000-10-05 DJ Delorie <dj@redhat.com>
diff --git a/bfd/elflink.h b/bfd/elflink.h
index 80c5b1c8fde..9e543a7c8d0 100644
--- a/bfd/elflink.h
+++ b/bfd/elflink.h
@@ -2897,7 +2897,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
{
struct elf_info_failed eif;
struct elf_link_hash_entry *h;
- bfd_size_type strsize;
+ asection *dynstr;
*sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (*sinterpptr != NULL || info->shared);
@@ -3026,14 +3026,24 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
return false;
}
- strsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
- if (! elf_add_dynamic_entry (info, DT_HASH, 0)
- || ! elf_add_dynamic_entry (info, DT_STRTAB, 0)
- || ! elf_add_dynamic_entry (info, DT_SYMTAB, 0)
- || ! elf_add_dynamic_entry (info, DT_STRSZ, strsize)
- || ! elf_add_dynamic_entry (info, DT_SYMENT,
- sizeof (Elf_External_Sym)))
- return false;
+ dynstr = bfd_get_section_by_name (dynobj, ".dynstr");
+ /* If .dynstr is excluded from the link, we don't want any of
+ these tags. Strictly, we should be checking each section
+ individually; This quick check covers for the case where
+ someone does a /DISCARD/ : { *(*) }. */
+ if (dynstr != NULL && dynstr->output_section != bfd_abs_section_ptr)
+ {
+ bfd_size_type strsize;
+
+ strsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
+ if (! elf_add_dynamic_entry (info, DT_HASH, 0)
+ || ! elf_add_dynamic_entry (info, DT_STRTAB, 0)
+ || ! elf_add_dynamic_entry (info, DT_SYMTAB, 0)
+ || ! elf_add_dynamic_entry (info, DT_STRSZ, strsize)
+ || ! elf_add_dynamic_entry (info, DT_SYMENT,
+ sizeof (Elf_External_Sym)))
+ return false;
+ }
}
/* The backend must work out the sizes of all the other dynamic
@@ -3047,7 +3057,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
size_t dynsymcount;
asection *s;
size_t bucketcount = 0;
- Elf_Internal_Sym isym;
size_t hash_entry_size;
/* Set up the version definition section. */
@@ -3384,15 +3393,20 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
if (s->contents == NULL && s->_raw_size != 0)
return false;
- /* The first entry in .dynsym is a dummy symbol. */
- isym.st_value = 0;
- isym.st_size = 0;
- isym.st_name = 0;
- isym.st_info = 0;
- isym.st_other = 0;
- isym.st_shndx = 0;
- elf_swap_symbol_out (output_bfd, &isym,
- (PTR) (Elf_External_Sym *) s->contents);
+ if (dynsymcount != 0)
+ {
+ Elf_Internal_Sym isym;
+
+ /* The first entry in .dynsym is a dummy symbol. */
+ isym.st_value = 0;
+ isym.st_size = 0;
+ isym.st_name = 0;
+ isym.st_info = 0;
+ isym.st_other = 0;
+ isym.st_shndx = 0;
+ elf_swap_symbol_out (output_bfd, &isym,
+ (PTR) (Elf_External_Sym *) s->contents);
+ }
/* Compute the size of the hashing table. As a side effect this
computes the hash values for all the names we export. */
@@ -4602,7 +4616,8 @@ elf_bfd_final_link (abfd, info)
/* The sh_info field records the index of the first non local symbol. */
symtab_hdr->sh_info = bfd_get_symcount (abfd);
- if (dynamic)
+ if (dynamic
+ && finfo.dynsym_sec->output_section != bfd_abs_section_ptr)
{
Elf_Internal_Sym sym;
Elf_External_Sym *dynsym =
@@ -4867,7 +4882,8 @@ elf_bfd_final_link (abfd, info)
for (o = dynobj->sections; o != NULL; o = o->next)
{
if ((o->flags & SEC_HAS_CONTENTS) == 0
- || o->_raw_size == 0)
+ || o->_raw_size == 0
+ || o->output_section == bfd_abs_section_ptr)
continue;
if ((o->flags & SEC_LINKER_CREATED) == 0)
{