Files removed as of the 1999-08-23 snapshot.
[deliverable/binutils-gdb.git] / bfd / elflink.h
index 1e88b6318ae64efd989d4d8cdd2b4148a1eb8dc5..f6727a6aec1c245bd673ba025f9f84384fa67117 100644 (file)
@@ -368,8 +368,12 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
   /* In cases involving weak versioned symbols, we may wind up trying
      to merge a symbol with itself.  Catch that here, to avoid the
      confusion that results if we try to override a symbol with
-     itself.  */
-  if (abfd == oldbfd)
+     itself.  The additional tests catch cases like
+     _GLOBAL_OFFSET_TABLE_, which are regular symbols defined in a
+     dynamic object, which we do want to handle here.  */
+  if (abfd == oldbfd
+      && ((abfd->flags & DYNAMIC) == 0
+         || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))
     return true;
 
   /* NEWDYN and OLDDYN indicate whether the new or old symbol,
@@ -380,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.  */
@@ -2112,6 +2141,10 @@ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
   entry->input_indx = input_indx;
   eht->dynsymcount++;
 
+  /* Whatever binding the symbol had before, it's now local.  */
+  entry->isym.st_info
+    = ELF_ST_INFO (STB_LOCAL, ELF_ST_TYPE (entry->isym.st_info));
+
   /* The dynindx will be set at the end of size_dynamic_sections.  */
 
   return true;
@@ -3753,34 +3786,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;
 }
@@ -3989,6 +4026,45 @@ 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 = o->output_section;
+
+         if (output_section && (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)
@@ -4006,6 +4082,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);
@@ -4245,20 +4326,22 @@ elf_bfd_final_link (abfd, info)
              sym.st_size = e->isym.st_size;
              sym.st_other = e->isym.st_other;
 
-             /* Note that we saved a word of storage and overwrote
+             /* Copy the internal symbol as is.
+                Note that we saved a word of storage and overwrote
                  the original st_name with the dynstr_index.  */
-             sym.st_name = e->isym.st_name;
-
-             /* Whatever binding the symbol had before, it's now local.  */
-             sym.st_info = ELF_ST_INFO (STB_LOCAL,
-                                        ELF_ST_TYPE (e->isym.st_info));
+              sym = e->isym;
 
-             s = bfd_section_from_elf_index (e->input_bfd, e->isym.st_shndx);
-
-             sym.st_shndx = elf_section_data (s->output_section)->this_idx;
-             sym.st_value = (s->output_section->vma
-                             + s->output_offset
-                             + e->isym.st_value);
+             if (e->isym.st_shndx > 0 && e->isym.st_shndx < SHN_LORESERVE)
+               {
+                 s = bfd_section_from_elf_index (e->input_bfd,
+                                                 e->isym.st_shndx);
+
+                 sym.st_shndx =
+                   elf_section_data (s->output_section)->this_idx;
+                 sym.st_value = (s->output_section->vma
+                                 + s->output_offset
+                                 + e->isym.st_value);
+               }
 
              if (last_local < e->dynindx)
                last_local = e->dynindx;
@@ -4268,7 +4351,7 @@ elf_bfd_final_link (abfd, info)
        }
 
       elf_section_data (finfo.dynsym_sec->output_section)
-       ->this_hdr.sh_info = last_local;
+       ->this_hdr.sh_info = last_local + 1;
     }
 
   /* We get the global symbols from the hash table.  */
@@ -4280,6 +4363,18 @@ elf_bfd_final_link (abfd, info)
   if (eoinfo.failed)
     return false;
 
+  /* If backend needs to output some symbols not present in the hash
+     table, do it now.  */
+  if (bed->elf_backend_output_arch_syms)
+    {
+      if (! (*bed->elf_backend_output_arch_syms)
+             (abfd, info, (PTR) &finfo,
+              (boolean (*) PARAMS ((PTR, const char *,
+                           Elf_Internal_Sym *, asection *)))
+              elf_link_output_sym))
+       return false;
+    }      
+
   /* Flush all symbols to the file.  */
   if (! elf_link_flush_output_syms (&finfo))
     return false;
@@ -4821,14 +4916,23 @@ elf_link_output_extsym (h, data)
 
   /* If we are marking the symbol as undefined, and there are no
      non-weak references to this symbol from a regular object, then
-     mark the symbol as weak undefined.  We can't do this earlier,
+     mark the symbol as weak undefined; if there are non-weak
+     references, mark the symbol as strong.  We can't do this earlier,
      because it might not be marked as undefined until the
      finish_dynamic_symbol routine gets through with it.  */
   if (sym.st_shndx == SHN_UNDEF
-      && sym.st_info == ELF_ST_INFO (STB_GLOBAL, h->type)
       && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0
-      && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) == 0)
-    sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
+      && (ELF_ST_BIND(sym.st_info) == STB_GLOBAL
+         || ELF_ST_BIND(sym.st_info) == STB_WEAK))
+    {
+      int bindtype;
+
+      if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) != 0)
+       bindtype = STB_GLOBAL;
+      else
+       bindtype = STB_WEAK;
+      sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
+    }
 
   /* If this symbol should be put in the .dynsym section, then put it
      there now.  We have already know the symbol index.  We also fill
This page took 0.026091 seconds and 4 git commands to generate.