Still a lot of bogus code; just a checkpoint.
[deliverable/binutils-gdb.git] / bfd / elflink.h
index 9e372c7792f5389e540567fc2834c601ea7d0724..841a8e728954c0d79a9d820cb7bf6c5697a0f020 100644 (file)
@@ -2259,6 +2259,8 @@ compute_bucket_count (info)
         that the hashing table must at least have NSYMS/4 and at most
         2*NSYMS buckets.  */
       minsize = nsyms / 4;
+      if (minsize == 0)
+       minsize = 1;
       best_size = maxsize = nsyms * 2;
 
       /* Create array where we count the collisions in.  We must use bfd_malloc
@@ -3117,6 +3119,18 @@ elf_adjust_dynamic_symbol (h, data)
        }
     }
 
+  /* If a symbol has no type and no size and does not require a PLT
+     entry, then we are probably about to do the wrong thing here: we
+     are probably going to create a COPY reloc for an empty object.
+     This case can arise when a shared object is built with assembly
+     code, and the assembly code fails to set the symbol type.  */
+  if (h->size == 0
+      && h->type == STT_NOTYPE
+      && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0)
+    (*_bfd_error_handler)
+      (_("warning: type and size of dynamic symbol `%s' are not defined"),
+        h->root.root.string);
+
   dynobj = elf_hash_table (eif->info)->dynobj;
   bed = get_elf_backend_data (dynobj);
   if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
@@ -5724,6 +5738,7 @@ elf_gc_propagate_vtable_entries_used (h, okp)
       /* None of this table's entries were referenced.  Re-use the
         parent's table.  */
       h->vtable_entries_used = h->vtable_parent->vtable_entries_used;
+      h->vtable_entries_size = h->vtable_parent->vtable_entries_size;
     }
   else
     {
@@ -5736,7 +5751,7 @@ elf_gc_propagate_vtable_entries_used (h, okp)
       pu = h->vtable_parent->vtable_entries_used;
       if (pu != NULL)
        {
-         n = h->vtable_parent->size / FILE_ALIGN;
+         n = h->vtable_parent->vtable_entries_size / FILE_ALIGN;
          while (--n != 0)
            {
              if (*pu) *cu = true;
@@ -5779,7 +5794,8 @@ elf_gc_smash_unused_vtentry_relocs (h, okp)
     if (rel->r_offset >= hstart && rel->r_offset < hend)
       {
        /* If the entry is in use, do nothing.  */
-       if (h->vtable_entries_used)
+       if (h->vtable_entries_used
+           && (rel->r_offset - hstart) < h->vtable_entries_size)
          {
            bfd_vma entry = (rel->r_offset - hstart) / FILE_ALIGN;
            if (h->vtable_entries_used[entry])
@@ -5911,17 +5927,51 @@ elf_gc_record_vtentry (abfd, sec, h, addend)
      struct elf_link_hash_entry *h;
      bfd_vma addend;
 {
-  if (h->vtable_entries_used == NULL)
+  if (addend >= h->vtable_entries_size)
     {
+      size_t size, bytes;
+      boolean *ptr = h->vtable_entries_used;
+
+      /* While the symbol is undefined, we have to be prepared to handle
+        a zero size.  */
+      if (h->root.type == bfd_link_hash_undefined)
+       size = addend;
+      else
+       {
+         size = h->size;
+         if (size < addend)
+           {
+             /* Oops!  We've got a reference past the defined end of
+                the table.  This is probably a bug -- shall we warn?  */
+             size = addend;
+           }
+       }
+
       /* Allocate one extra entry for use as a "done" flag for the
         consolidation pass.  */
-      size_t size = (h->size / FILE_ALIGN + 1) * sizeof(boolean);
-      h->vtable_entries_used = (boolean *) bfd_alloc (abfd, size);
-      if (h->vtable_entries_used == NULL)
-       return false;
+      bytes = (size / FILE_ALIGN + 1) * sizeof(boolean);
+
+      if (ptr)
+       {
+         size_t oldbytes;
+
+         ptr = realloc (ptr-1, bytes);
+         if (ptr == NULL)
+           return false;
+
+         oldbytes = (h->vtable_entries_size/FILE_ALIGN + 1) * sizeof(boolean);
+         memset (ptr + oldbytes, 0, bytes - oldbytes);
+       }
+      else
+       {
+         ptr = calloc (1, bytes);
+         if (ptr == NULL)
+           return false;
+       }
 
       /* And arrange for that done flag to be at index -1.  */
-      memset (h->vtable_entries_used++, 0, size);
+      h->vtable_entries_used = ptr+1;
+      h->vtable_entries_size = size;
     }
   h->vtable_entries_used[addend / FILE_ALIGN] = true;
 
This page took 0.024383 seconds and 4 git commands to generate.