1999-09-04 Steve Chamberlain <sac@pobox.com>
[deliverable/binutils-gdb.git] / bfd / elflink.h
index 60de241ad09f9e365d9d012322a57200050c9feb..e9ba45adffb8b03354ea0cb2068c17fc76bd92c1 100644 (file)
@@ -384,10 +384,35 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
   else
     newdyn = false;
 
-  if (oldbfd == NULL || (oldbfd->flags & DYNAMIC) == 0)
-    olddyn = false;
+  if (oldbfd != NULL)
+    olddyn = (oldbfd->flags & DYNAMIC) != 0;
   else
-    olddyn = true;
+    {
+      asection *hsec;
+
+      /* This code handles the special SHN_MIPS_{TEXT,DATA} section
+         indices used by MIPS ELF.  */
+      switch (h->root.type)
+       {
+       default:
+         hsec = NULL;
+         break;
+
+       case bfd_link_hash_defined:
+       case bfd_link_hash_defweak:
+         hsec = h->root.u.def.section;
+         break;
+
+       case bfd_link_hash_common:
+         hsec = h->root.u.c.p->section;
+         break;
+       }
+
+      if (hsec == NULL)
+       olddyn = false;
+      else
+       olddyn = (hsec->symbol->flags & BSF_DYNAMIC) != 0;
+    }
 
   /* NEWDEF and OLDDEF indicate whether the new or old symbol,
      respectively, appear to be a definition rather than reference.  */
@@ -929,6 +954,23 @@ elf_link_add_object_symbols (abfd, info)
            goto error_return;
          link = elf_elfsections (abfd)[elfsec]->sh_link;
 
+         {
+           /* The shared libraries distributed with hpux11 have a bogus
+              sh_link field for the ".dynamic" section.  This code detects
+              when LINK refers to a section that is not a string table and
+              tries to find the string table for the ".dynsym" section
+              instead.  */
+           Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[link];
+           if (hdr->sh_type != SHT_STRTAB)
+             {
+               asection *s = bfd_get_section_by_name (abfd, ".dynsym");
+               int elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
+               if (elfsec == -1)
+                 goto error_return;
+               link = elf_elfsections (abfd)[elfsec]->sh_link;
+             }
+         }
+
          extdyn = dynbuf;
          extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);
          for (; extdyn < extdynend; extdyn++)
@@ -2346,7 +2388,10 @@ NAME(bfd_elf,record_link_assignment) (output_bfd, info, name, provide)
     h->verinfo.verdef = NULL;
 
   h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
-  h->type = STT_OBJECT;
+
+  /* When possible, keep the original type of the symbol */
+  if (h->type == STT_NOTYPE)
+    h->type = STT_OBJECT;
 
   if (((h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_DYNAMIC
                                  | ELF_LINK_HASH_REF_DYNAMIC)) != 0
@@ -3304,10 +3349,11 @@ elf_adjust_dynamic_symbol (h, data)
        {
          /* There is an implicit reference by a regular object file
             via the weak symbol.  */
-         weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
-         if (h->weakdef->elf_link_hash_flags
-             & ELF_LINK_HASH_REF_REGULAR_NONWEAK)
-           weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR_NONWEAK;
+         weakdef->elf_link_hash_flags |=
+           (ELF_LINK_HASH_REF_REGULAR
+            | (h->elf_link_hash_flags
+               & (ELF_LINK_HASH_REF_REGULAR_NONWEAK
+                  | ELF_LINK_NON_GOT_REF)));
          if (! elf_adjust_dynamic_symbol (weakdef, (PTR) eif))
            return false;
        }
@@ -3761,34 +3807,38 @@ elf_link_size_reloc_section (abfd, rel_hdr, o)
      asection *o;
 {
   register struct elf_link_hash_entry **p, **pend;
+  unsigned reloc_count;
+
+  /* Figure out how many relocations there will be.  */
+  if (rel_hdr == &elf_section_data (o)->rel_hdr)
+    reloc_count = elf_section_data (o)->rel_count;
+  else
+    reloc_count = elf_section_data (o)->rel_count2;
 
-  /* We are overestimating the size required for the relocation
-     sections, in the case that we are using both REL and RELA
-     relocations for a single section.  In that case, RELOC_COUNT will
-     be the total number of relocations required, and we allocate
-     space for that many REL relocations as well as that many RELA
-     relocations.  This approximation is wasteful of disk space.
-     However, until we keep track of how many of each kind of
-     relocation is required, it's difficult to calculate the right
-     value.  */
-  rel_hdr->sh_size = rel_hdr->sh_entsize * o->reloc_count;
+  /* That allows us to calculate the size of the section.  */
+  rel_hdr->sh_size = rel_hdr->sh_entsize * reloc_count;
 
   /* The contents field must last into write_object_contents, so we
      allocate it with bfd_alloc rather than malloc.  */
   rel_hdr->contents = (PTR) bfd_alloc (abfd, rel_hdr->sh_size);
   if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0)
     return false;
+  
+  /* We only allocate one set of hash entries, so we only do it the
+     first time we are called.  */
+  if (elf_section_data (o)->rel_hashes == NULL)
+    {
+      p = ((struct elf_link_hash_entry **)
+          bfd_malloc (o->reloc_count
+                      * sizeof (struct elf_link_hash_entry *)));
+      if (p == NULL && o->reloc_count != 0)
+       return false;
 
-  p = ((struct elf_link_hash_entry **)
-       bfd_malloc (o->reloc_count
-                  * sizeof (struct elf_link_hash_entry *)));
-  if (p == NULL && o->reloc_count != 0)
-    return false;
-
-  elf_section_data (o)->rel_hashes = p;
-  pend = p + o->reloc_count;
-  for (; p < pend; p++)
-    *p = NULL;
+      elf_section_data (o)->rel_hashes = p;
+      pend = p + o->reloc_count;
+      for (; p < pend; p++)
+       *p = NULL;
+    }
 
   return true;
 }
@@ -3997,6 +4047,54 @@ elf_bfd_final_link (abfd, info)
   if (! _bfd_elf_compute_section_file_positions (abfd, info))
     goto error_return;
 
+  /* Figure out how many relocations we will have in each section.
+     Just using RELOC_COUNT isn't good enough since that doesn't
+     maintain a separate value for REL vs. RELA relocations.  */
+  if (info->relocateable)
+    for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+      for (o = sub->sections; o != NULL; o = o->next)
+       {
+         asection *output_section;
+
+         if (! o->linker_mark)
+           {
+             /* This section was omitted from the link.  */
+             continue;
+           }
+
+         output_section = o->output_section;
+
+         if (output_section != NULL
+             && (o->flags & SEC_RELOC) != 0)
+           {
+             struct bfd_elf_section_data *esdi 
+               = elf_section_data (o);
+             struct bfd_elf_section_data *esdo 
+               = elf_section_data (output_section);
+             unsigned int *rel_count;
+             unsigned int *rel_count2;
+
+             /* We must be careful to add the relocation froms the
+                input section to the right output count.  */
+             if (esdi->rel_hdr.sh_entsize == esdo->rel_hdr.sh_entsize)
+               {
+                 rel_count = &esdo->rel_count;
+                 rel_count2 = &esdo->rel_count2;
+               }
+             else
+               {
+                 rel_count = &esdo->rel_count2;
+                 rel_count2 = &esdo->rel_count;
+               }
+             
+             *rel_count += (esdi->rel_hdr.sh_size 
+                            / esdi->rel_hdr.sh_entsize);
+             if (esdi->rel_hdr2)
+               *rel_count2 += (esdi->rel_hdr2->sh_size 
+                               / esdi->rel_hdr2->sh_entsize);
+           }
+       }
+
   /* That created the reloc sections.  Set their sizes, and assign
      them file positions, and allocate some buffers.  */
   for (o = abfd->sections; o != NULL; o = o->next)
@@ -4014,6 +4112,11 @@ elf_bfd_final_link (abfd, info)
                                               o))
            goto error_return;
        }
+
+      /* Now, reset REL_COUNT and REL_COUNT2 so that we can use them
+        to count upwards while actually outputting the relocations. */
+      elf_section_data (o)->rel_count = 0;
+      elf_section_data (o)->rel_count2 = 0;
     }
 
   _bfd_elf_assign_file_positions_for_relocs (abfd);
@@ -4250,6 +4353,9 @@ elf_bfd_final_link (abfd, info)
            {
              asection *s;
 
+             sym.st_size = e->isym.st_size;
+             sym.st_other = e->isym.st_other;
+
              /* Copy the internal symbol as is.
                 Note that we saved a word of storage and overwrote
                  the original st_name with the dynstr_index.  */
@@ -6324,7 +6430,7 @@ elf_gc_record_vtentry (abfd, sec, h, addend)
            return false;
 
          oldbytes = (h->vtable_entries_size/FILE_ALIGN + 1) * sizeof(boolean);
-         memset (ptr + oldbytes, 0, bytes - oldbytes);
+         memset (((char *)ptr) + oldbytes, 0, bytes - oldbytes);
        }
       else
        {
This page took 0.029025 seconds and 4 git commands to generate.