]> Git Repo - binutils.git/blobdiff - bfd/elf.c
* configure.host (i386-windows): Don't set host64=true.
[binutils.git] / bfd / elf.c
index 4313d5e733312e39030521cbaa32f42475dd462d..3015461cd5e839cb2ef1ea31ed44b1597fa19900 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -39,13 +39,20 @@ SECTION
 #include "elf-bfd.h"
 
 static INLINE struct elf_segment_map *make_mapping
-  PARAMS ((bfd *, asection **, unsigned int, unsigned int));
+  PARAMS ((bfd *, asection **, unsigned int, unsigned int, boolean));
+static boolean map_sections_to_segments PARAMS ((bfd *));
 static int elf_sort_sections PARAMS ((const PTR, const PTR));
 static boolean assign_file_positions_for_segments PARAMS ((bfd *));
 static boolean assign_file_positions_except_relocs PARAMS ((bfd *));
 static boolean prep_headers PARAMS ((bfd *));
 static boolean swap_out_syms PARAMS ((bfd *, struct bfd_strtab_hash **));
 static boolean copy_private_bfd_data PARAMS ((bfd *, bfd *));
+static char *elf_read PARAMS ((bfd *, long, unsigned int));
+static void elf_fake_sections PARAMS ((bfd *, asection *, PTR));
+static boolean assign_section_numbers PARAMS ((bfd *));
+static INLINE int sym_is_global PARAMS ((bfd *, asymbol *));
+static boolean elf_map_symbols PARAMS ((bfd *));
+static bfd_size_type get_program_header_size PARAMS ((bfd *));
 
 /* Standard ELF hash function.  Do not change this function; you will
    cause invalid hash tables to be generated.  (Well, you would if this
@@ -96,7 +103,7 @@ elf_read (abfd, offset, size)
 }
 
 boolean
-elf_mkobject (abfd)
+bfd_elf_mkobject (abfd)
      bfd * abfd;
 {
   /* this just does initialization */
@@ -211,6 +218,15 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
       || strncmp (name, ".stab", sizeof ".stab" - 1) == 0)
     flags |= SEC_DEBUGGING;
 
+  /* As a GNU extension, if the name begins with .gnu.linkonce, we
+     only link a single copy of the section.  This is used to support
+     g++.  g++ will emit each template expansion in its own section.
+     The symbols will be defined as weak, so that multiple definitions
+     are permitted.  The GNU linker extension is to actually discard
+     all but one of the sections.  */
+  if (strncmp (name, ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) == 0)
+    flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
+
   if (! bfd_set_section_flags (abfd, newsect, flags))
     return false;
 
@@ -227,7 +243,11 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
              && phdr->p_paddr != 0
              && phdr->p_vaddr != phdr->p_paddr
              && phdr->p_vaddr <= hdr->sh_addr
-             && phdr->p_vaddr + phdr->p_memsz >= hdr->sh_addr + hdr->sh_size)
+             && phdr->p_vaddr + phdr->p_memsz >= hdr->sh_addr + hdr->sh_size
+             && ((flags & SEC_LOAD) == 0
+                 || (phdr->p_offset <= hdr->sh_offset
+                     && (phdr->p_offset + phdr->p_filesz
+                         >= hdr->sh_offset + hdr->sh_size))))
            {
              newsect->lma += phdr->p_paddr - phdr->p_vaddr;
              break;
@@ -453,6 +473,8 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case DT_DEBUG: name = "DEBUG"; break;
            case DT_TEXTREL: name = "TEXTREL"; break;
            case DT_JMPREL: name = "JMPREL"; break;
+           case DT_AUXILIARY: name = "AUXILIARY"; stringp = true; break;
+           case DT_FILTER: name = "FILTER"; stringp = true; break;
            }
 
          fprintf (f, "  %-11s ", name);
@@ -516,6 +538,11 @@ bfd_elf_print_symbol (ignore_abfd, filep, symbol, how)
                     (bfd_is_com_section (symbol->section)
                      ? ((elf_symbol_type *) symbol)->internal_elf_sym.st_value
                      : ((elf_symbol_type *) symbol)->internal_elf_sym.st_size));
+       /* If the st_other field is not zero, print it.  */
+       if (((elf_symbol_type *) symbol)->internal_elf_sym.st_other != 0)
+         fprintf (file, " 0x%02x",
+                  ((unsigned int)
+                   ((elf_symbol_type *) symbol)->internal_elf_sym.st_other));
        fprintf (file, " %s", symbol->name);
       }
       break;
@@ -556,6 +583,7 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
       ret->plt_offset = (bfd_vma) -1;
       ret->linker_section_pointer = (elf_linker_section_pointers_t *)0;
       ret->type = STT_NOTYPE;
+      ret->other = 0;
       /* Assume that we have been called by a non-ELF symbol reader.
          This flag is then reset by the code which reads an ELF input
          file.  This ensures that a symbol created by a non-ELF symbol
@@ -583,6 +611,8 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc)
   table->dynstr = NULL;
   table->bucketcount = 0;
   table->needed = NULL;
+  table->hgot = NULL;
+  table->stab_info = NULL;
   return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
 }
 
@@ -618,11 +648,13 @@ bfd_elf_set_dt_needed_name (abfd, name)
      bfd *abfd;
      const char *name;
 {
-  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
-    elf_dt_needed_name (abfd) = name;
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+      && bfd_get_format (abfd) == bfd_object)
+    elf_dt_name (abfd) = name;
 }
 
-/* Get the list of DT_NEEDED entries for a link.  */
+/* Get the list of DT_NEEDED entries for a link.  This is a hook for
+   the ELF emulation code.  */
 
 struct bfd_link_needed_list *
 bfd_elf_get_needed_list (abfd, info)
@@ -633,6 +665,20 @@ bfd_elf_get_needed_list (abfd, info)
     return NULL;
   return elf_hash_table (info)->needed;
 }
+
+/* Get the name actually used for a dynamic object for a link.  This
+   is the SONAME entry if there is one.  Otherwise, it is the string
+   passed to bfd_elf_set_dt_needed_name, or it is the filename.  */
+
+const char *
+bfd_elf_get_dt_soname (abfd)
+     bfd *abfd;
+{
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+      && bfd_get_format (abfd) == bfd_object)
+    return elf_dt_name (abfd);
+  return NULL;
+}
 \f
 /* Allocate an ELF string table--force the first byte to be zero.  */
 
@@ -783,7 +829,6 @@ bfd_section_from_shdr (abfd, shindex)
       {
        asection *target_sect;
        Elf_Internal_Shdr *hdr2;
-       int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
 
        /* For some incomprehensible reason Oracle distributes
           libraries for Solaris in which some of the objects have
@@ -828,30 +873,24 @@ bfd_section_from_shdr (abfd, shindex)
        if (hdr->sh_link != elf_onesymtab (abfd))
          return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
 
-       /* Don't allow REL relocations on a machine that uses RELA and
-          vice versa.  */
-       /* @@ Actually, the generic ABI does suggest that both might be
-          used in one file.  But the four ABI Processor Supplements I
-          have access to right now all specify that only one is used on
-          each of those architectures.  It's conceivable that, e.g., a
-          bunch of absolute 32-bit relocs might be more compact in REL
-          form even on a RELA machine...  */
-       BFD_ASSERT (use_rela_p
-                   ? (hdr->sh_type == SHT_RELA
-                      && hdr->sh_entsize == bed->s->sizeof_rela)
-                   : (hdr->sh_type == SHT_REL
-                      && hdr->sh_entsize == bed->s->sizeof_rel));
-
        if (! bfd_section_from_shdr (abfd, hdr->sh_info))
          return false;
        target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info);
        if (target_sect == NULL)
          return false;
 
-       hdr2 = &elf_section_data (target_sect)->rel_hdr;
+       if ((target_sect->flags & SEC_RELOC) == 0
+           || target_sect->reloc_count == 0)
+         hdr2 = &elf_section_data (target_sect)->rel_hdr;
+       else
+         {
+           BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL);
+           hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*hdr2));
+           elf_section_data (target_sect)->rel_hdr2 = hdr2;
+         }
        *hdr2 = *hdr;
        elf_elfsections (abfd)[shindex] = hdr2;
-       target_sect->reloc_count = hdr->sh_size / hdr->sh_entsize;
+       target_sect->reloc_count += hdr->sh_size / hdr->sh_entsize;
        target_sect->flags |= SEC_RELOC;
        target_sect->relocation = NULL;
        target_sect->rel_filepos = hdr->sh_offset;
@@ -1028,7 +1067,8 @@ elf_fake_sections (abfd, asect, failedptrarg)
 
   this_hdr->sh_flags = 0;
 
-  if ((asect->flags & SEC_ALLOC) != 0)
+  if ((asect->flags & SEC_ALLOC) != 0
+      || asect->user_set_vma)
     this_hdr->sh_addr = asect->vma;
   else
     this_hdr->sh_addr = 0;
@@ -1592,11 +1632,12 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
 /* Create a mapping from a set of sections to a program segment.  */
 
 static INLINE struct elf_segment_map *
-make_mapping (abfd, sections, from, to)
+make_mapping (abfd, sections, from, to, phdr)
      bfd *abfd;
      asection **sections;
      unsigned int from;
      unsigned int to;
+     boolean phdr;
 {
   struct elf_segment_map *m;
   unsigned int i;
@@ -1614,7 +1655,7 @@ make_mapping (abfd, sections, from, to)
     m->sections[i - from] = *hdrpp;
   m->count = to - from;
 
-  if (from == 0)
+  if (from == 0 && phdr)
     {
       /* Include the headers in the first PT_LOAD segment.  */
       m->includes_filehdr = 1;
@@ -1641,6 +1682,9 @@ map_sections_to_segments (abfd)
   unsigned int phdr_index;
   bfd_vma maxpagesize;
   asection **hdrpp;
+  boolean phdr_in_section = true;
+  boolean writable;
+  asection *dynsec;
 
   if (elf_tdata (abfd)->segment_map != NULL)
     return true;
@@ -1713,43 +1757,124 @@ map_sections_to_segments (abfd)
   last_hdr = NULL;
   phdr_index = 0;
   maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
+  writable = false;
+  dynsec = bfd_get_section_by_name (abfd, ".dynamic");
+  if (dynsec != NULL
+      && (dynsec->flags & SEC_LOAD) == 0)
+    dynsec = NULL;
+
+  /* Deal with -Ttext or something similar such that the first section
+     is not adjacent to the program headers.  This is an
+     approximation, since at this point we don't know exactly how many
+     program headers we will need.  */
+  if (count > 0)
+    {
+      bfd_size_type phdr_size;
+
+      phdr_size = elf_tdata (abfd)->program_header_size;
+      if (phdr_size == 0)
+       phdr_size = get_elf_backend_data (abfd)->s->sizeof_phdr;
+      if ((abfd->flags & D_PAGED) == 0
+         || sections[0]->lma % maxpagesize < phdr_size % maxpagesize)
+       phdr_in_section = false;
+    }
+
   for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
     {
       asection *hdr;
+      boolean new_segment;
 
       hdr = *hdrpp;
 
       /* See if this section and the last one will fit in the same
          segment.  */
-      if (last_hdr == NULL
-         || ((BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
-              >= hdr->lma)
-             && ((last_hdr->flags & SEC_LOAD) != 0
-                 || (hdr->flags & SEC_LOAD) == 0)))
+
+      if (last_hdr == NULL)
+       {
+         /* If we don't have a segment yet, then we don't need a new
+            one (we build the last one after this loop).  */
+         new_segment = false;
+       }
+      else if (last_hdr->lma - last_hdr->vma != hdr->lma - hdr->vma)
        {
+         /* If this section has a different relation between the
+             virtual address and the load address, then we need a new
+             segment.  */
+         new_segment = true;
+       }
+      else if (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
+              < hdr->lma)
+       {
+         /* If putting this section in this segment would force us to
+             skip a page in the segment, then we need a new segment.  */
+         new_segment = true;
+       }
+      else if ((abfd->flags & D_PAGED) == 0)
+       {
+         /* If the file is not demand paged, which means that we
+             don't require the sections to be correctly aligned in the
+             file, then there is no other reason for a new segment.  */
+         new_segment = false;
+       }
+      else if ((last_hdr->flags & SEC_LOAD) == 0
+              && (hdr->flags & SEC_LOAD) != 0)
+       {
+         /* We don't want to put a loadable section after a
+             nonloadable section in the same segment.  */
+         new_segment = true;
+       }
+      else if (! writable
+              && (hdr->flags & SEC_READONLY) == 0
+              && (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
+                  == hdr->lma))
+       {
+         /* We don't want to put a writable section in a read only
+             segment, unless they are on the same page in memory
+             anyhow.  We already know that the last section does not
+             bring us past the current section on the page, so the
+             only case in which the new section is not on the same
+             page as the previous section is when the previous section
+             ends precisely on a page boundary.  */
+         new_segment = true;
+       }
+      else
+       {
+         /* Otherwise, we can use the same segment.  */
+         new_segment = false;
+       }
+
+      if (! new_segment)
+       {
+         if ((hdr->flags & SEC_READONLY) == 0)
+           writable = true;
          last_hdr = hdr;
          continue;
        }
 
-      /* This section won't fit in the program segment.  We must
-         create a new program header holding all the sections from
-         phdr_index until hdr.  */
+      /* We need a new program segment.  We must create a new program
+         header holding all the sections from phdr_index until hdr.  */
 
-      m = make_mapping (abfd, sections, phdr_index, i);
+      m = make_mapping (abfd, sections, phdr_index, i, phdr_in_section);
       if (m == NULL)
        goto error_return;
 
       *pm = m;
       pm = &m->next;
 
+      if ((hdr->flags & SEC_READONLY) == 0)
+       writable = true;
+      else
+       writable = false;
+
       last_hdr = hdr;
       phdr_index = i;
+      phdr_in_section = false;
     }
 
   /* Create a final PT_LOAD program segment.  */
   if (last_hdr != NULL)
     {
-      m = make_mapping (abfd, sections, phdr_index, i);
+      m = make_mapping (abfd, sections, phdr_index, i, phdr_in_section);
       if (m == NULL)
        goto error_return;
 
@@ -1758,8 +1883,7 @@ map_sections_to_segments (abfd)
     }
 
   /* If there is a .dynamic section, throw in a PT_DYNAMIC segment.  */
-  s = bfd_get_section_by_name (abfd, ".dynamic");
-  if (s != NULL && (s->flags & SEC_LOAD) != 0)
+  if (dynsec != NULL)
     {
       m = ((struct elf_segment_map *)
           bfd_zalloc (abfd, sizeof (struct elf_segment_map)));
@@ -1768,7 +1892,7 @@ map_sections_to_segments (abfd)
       m->next = NULL;
       m->p_type = PT_DYNAMIC;
       m->count = 1;
-      m->sections[0] = s;
+      m->sections[0] = dynsec;
 
       *pm = m;
       pm = &m->next;
@@ -1801,6 +1925,13 @@ elf_sort_sections (arg1, arg2)
   else if (sec1->vma > sec2->vma)
     return 1;
 
+  /* Sort by LMA.  Normally the LMA and the VMA will be the same, and
+     this will do nothing.  */
+  if (sec1->lma < sec2->lma)
+    return -1;
+  else if (sec1->lma > sec2->lma)
+    return 1;
+
   /* Put !SEC_LOAD sections after SEC_LOAD ones.  */
 
 #define TOEND(x) (((x)->flags & SEC_LOAD) == 0)
@@ -1840,7 +1971,7 @@ assign_file_positions_for_segments (abfd)
   struct elf_segment_map *m;
   unsigned int alloc;
   Elf_Internal_Phdr *phdrs;
-  file_ptr off;
+  file_ptr off, voff;
   bfd_vma filehdr_vaddr, filehdr_paddr;
   bfd_vma phdrs_vaddr, phdrs_paddr;
   Elf_Internal_Phdr *p;
@@ -1918,8 +2049,14 @@ assign_file_positions_for_segments (abfd)
 
       if (p->p_type == PT_LOAD
          && m->count > 0
-         && (m->sections[0]->flags & SEC_LOAD) != 0)
-       off += (m->sections[0]->vma - off) % bed->maxpagesize;
+         && (m->sections[0]->flags & SEC_ALLOC) != 0)
+       {
+         if ((abfd->flags & D_PAGED) != 0)
+           off += (m->sections[0]->vma - off) % bed->maxpagesize;
+         else
+           off += ((m->sections[0]->vma - off)
+                   % (1 << bfd_get_section_alignment (abfd, m->sections[0])));
+       }
 
       if (m->count == 0)
        p->p_vaddr = 0;
@@ -1933,7 +2070,8 @@ assign_file_positions_for_segments (abfd)
       else
        p->p_paddr = m->sections[0]->lma;
 
-      if (p->p_type == PT_LOAD)
+      if (p->p_type == PT_LOAD
+         && (abfd->flags & D_PAGED) != 0)
        p->p_align = bed->maxpagesize;
       else if (m->count == 0)
        p->p_align = bed->s->file_align;
@@ -2011,6 +2149,7 @@ assign_file_positions_for_segments (abfd)
            }
        }
 
+      voff = off;
       for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
        {
          asection *sec;
@@ -2019,6 +2158,7 @@ assign_file_positions_for_segments (abfd)
 
          sec = *secpp;
          flags = sec->flags;
+         align = 1 << bfd_get_section_alignment (abfd, sec);
 
          if (p->p_type == PT_LOAD)
            {
@@ -2026,17 +2166,21 @@ assign_file_positions_for_segments (abfd)
 
              /* The section VMA must equal the file position modulo
                  the page size.  */
-             if ((flags & SEC_LOAD) != 0)
+             if ((flags & SEC_ALLOC) != 0)
                {
-                 adjust = (sec->vma - off) % bed->maxpagesize;
+                 if ((abfd->flags & D_PAGED) != 0)
+                   adjust = (sec->vma - voff) % bed->maxpagesize;
+                 else
+                   adjust = (sec->vma - voff) % align;
                  if (adjust != 0)
                    {
                      if (i == 0)
                        abort ();
                      p->p_memsz += adjust;
+                     off += adjust;
+                     voff += adjust;
                      if ((flags & SEC_LOAD) != 0)
                        p->p_filesz += adjust;
-                     off += adjust;
                    }
                }
 
@@ -2044,6 +2188,8 @@ assign_file_positions_for_segments (abfd)
 
              if ((flags & SEC_LOAD) != 0)
                off += sec->_raw_size;
+             if ((flags & SEC_ALLOC) != 0)
+               voff += sec->_raw_size;
            }
 
          p->p_memsz += sec->_raw_size;
@@ -2051,7 +2197,6 @@ assign_file_positions_for_segments (abfd)
          if ((flags & SEC_LOAD) != 0)
            p->p_filesz += sec->_raw_size;
 
-         align = 1 << bfd_get_section_alignment (abfd, sec);
          if (align > p->p_align)
            p->p_align = align;
 
@@ -2263,7 +2408,10 @@ assign_file_positions_except_relocs (abfd)
                (hdr->bfd_section == NULL
                 ? "*unknown*"
                 : hdr->bfd_section->name)));
-             off += (hdr->sh_addr - off) % bed->maxpagesize;
+             if ((abfd->flags & D_PAGED) != 0)
+               off += (hdr->sh_addr - off) % bed->maxpagesize;
+             else
+               off += (hdr->sh_addr - off) % hdr->sh_addralign;
              off = _bfd_elf_assign_file_position_for_section (hdr, off,
                                                               false);
            }
@@ -2359,11 +2507,38 @@ prep_headers (abfd)
     case bfd_arch_powerpc:
       i_ehdrp->e_machine = EM_PPC;
       break;
+    case bfd_arch_alpha:
+      i_ehdrp->e_machine = EM_ALPHA;
+      break;
+    case bfd_arch_sh:
+      i_ehdrp->e_machine = EM_SH;
+      break;
+/* start-sanitize-d10v */
+    case bfd_arch_d10v:
+      i_ehdrp->e_machine = EM_CYGNUS_D10V;
+      break;
+/* end-sanitize-d10v */
+/* start-sanitize-v850 */
+    case bfd_arch_v850:
+      i_ehdrp->e_machine = EM_CYGNUS_V850;
+      break;
+/* end-sanitize-v850 */
 /* start-sanitize-arc */
     case bfd_arch_arc:
       i_ehdrp->e_machine = EM_CYGNUS_ARC;
       break;
 /* end-sanitize-arc */
+/* start-sanitize-m32r */
+    case bfd_arch_m32r:
+      i_ehdrp->e_machine = EM_CYGNUS_M32R;
+      break;
+/* end-sanitize-m32r */
+    case bfd_arch_mn10200:
+      i_ehdrp->e_machine = EM_CYGNUS_MN10200;
+      break;
+    case bfd_arch_mn10300:
+      i_ehdrp->e_machine = EM_CYGNUS_MN10300;
+      break;
       /* also note that EM_M32, AT&T WE32100 is unknown to bfd */
     default:
       i_ehdrp->e_machine = EM_NONE;
@@ -2537,13 +2712,15 @@ _bfd_elf_section_from_bfd_section (abfd, asect)
   return -1;
 }
 
-/* given a symbol, return the bfd index for that symbol.  */
- int
+/* Given a BFD symbol, return the index in the ELF symbol table, or -1
+   on error.  */
+
+int
 _bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr)
      bfd *abfd;
-     struct symbol_cache_entry **asym_ptr_ptr;
+     asymbol **asym_ptr_ptr;
 {
-  struct symbol_cache_entry *asym_ptr = *asym_ptr_ptr;
+  asymbol *asym_ptr = *asym_ptr_ptr;
   int idx;
   flagword flags = asym_ptr->flags;
 
@@ -2567,13 +2744,24 @@ _bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr)
     }
 
   idx = asym_ptr->udata.i;
-  BFD_ASSERT (idx != 0);
+
+  if (idx == 0)
+    {
+      /* This case can occur when using --strip-symbol on a symbol
+         which is used in a relocation entry.  */
+      (*_bfd_error_handler)
+       ("%s: symbol `%s' required but not present",
+        bfd_get_filename (abfd), bfd_asymbol_name (asym_ptr));
+      bfd_set_error (bfd_error_no_symbols);
+      return -1;
+    }
 
 #if DEBUG & 4
   {
     fprintf (stderr,
             "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx%s\n",
-     (long) asym_ptr, asym_ptr->name, idx, flags, elf_symbol_flags (flags));
+            (long) asym_ptr, asym_ptr->name, idx, flags,
+            elf_symbol_flags (flags));
     fflush (stderr);
   }
 #endif
@@ -2756,6 +2944,10 @@ _bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
 {
   elf_symbol_type *isym, *osym;
 
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return true;
+
   isym = elf_symbol_from (ibfd, isymarg);
   osym = elf_symbol_from (obfd, osymarg);
 
@@ -2968,7 +3160,11 @@ swap_out_syms (abfd, sttp)
            sym.st_info = ELF_ST_INFO (bind, type);
          }
 
-       sym.st_other = 0;
+       if (type_ptr != NULL)
+         sym.st_other = type_ptr->internal_elf_sym.st_other;
+       else
+         sym.st_other = 0;
+
        bed->s->swap_symbol_out (abfd, &sym, (PTR) outbound_syms);
        outbound_syms += bed->s->sizeof_sym;
       }
@@ -3048,7 +3244,10 @@ _bfd_elf_canonicalize_reloc (abfd, section, relptr, symbols)
   arelent *tblptr;
   unsigned int i;
 
-  if (! get_elf_backend_data (abfd)->s->slurp_reloc_table (abfd, section, symbols))
+  if (! get_elf_backend_data (abfd)->s->slurp_reloc_table (abfd,
+                                                          section,
+                                                          symbols,
+                                                          false))
     return -1;
 
   tblptr = section->relocation;
@@ -3080,6 +3279,86 @@ _bfd_elf_canonicalize_dynamic_symtab (abfd, alocation)
   return get_elf_backend_data (abfd)->s->slurp_symbol_table (abfd, alocation, true);
 }
 
+/* Return the size required for the dynamic reloc entries.  Any
+   section that was actually installed in the BFD, and has type
+   SHT_REL or SHT_RELA, and uses the dynamic symbol table, is
+   considered to be a dynamic reloc section.  */
+
+long
+_bfd_elf_get_dynamic_reloc_upper_bound (abfd)
+     bfd *abfd;
+{
+  long ret;
+  asection *s;
+
+  if (elf_dynsymtab (abfd) == 0)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
+    }
+
+  ret = sizeof (arelent *);
+  for (s = abfd->sections; s != NULL; s = s->next)
+    if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
+       && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
+           || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
+      ret += ((s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize)
+             * sizeof (arelent *));
+
+  return ret;
+}
+
+/* Canonicalize the dynamic relocation entries.  Note that we return
+   the dynamic relocations as a single block, although they are
+   actually associated with particular sections; the interface, which
+   was designed for SunOS style shared libraries, expects that there
+   is only one set of dynamic relocs.  Any section that was actually
+   installed in the BFD, and has type SHT_REL or SHT_RELA, and uses
+   the dynamic symbol table, is considered to be a dynamic reloc
+   section.  */
+
+long
+_bfd_elf_canonicalize_dynamic_reloc (abfd, storage, syms)
+     bfd *abfd;
+     arelent **storage;
+     asymbol **syms;
+{
+  boolean (*slurp_relocs) PARAMS ((bfd *, asection *, asymbol **, boolean));
+  asection *s;
+  long ret;
+
+  if (elf_dynsymtab (abfd) == 0)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
+    }
+
+  slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
+  ret = 0;
+  for (s = abfd->sections; s != NULL; s = s->next)
+    {
+      if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
+         && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
+             || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
+       {
+         arelent *p;
+         long count, i;
+
+         if (! (*slurp_relocs) (abfd, s, syms, true))
+           return -1;
+         count = s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize;
+         p = s->relocation;
+         for (i = 0; i < count; i++)
+           *storage++ = p++;
+         ret += count;
+       }
+    }
+
+  *storage = NULL;
+
+  return ret;
+}
+
 asymbol *
 _bfd_elf_make_empty_symbol (abfd)
      bfd *abfd;
@@ -3264,3 +3543,101 @@ _bfd_elf_no_info_to_howto_rel (abfd, cache_ptr, dst)
   abort ();
 }
 #endif
+
+/* Try to convert a non-ELF reloc into an ELF one.  */
+
+boolean
+_bfd_elf_validate_reloc (abfd, areloc)
+     bfd *abfd;
+     arelent *areloc;
+{
+  /* Check whether we really have an ELF howto. */
+
+  if ((*areloc->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec) 
+    {
+      bfd_reloc_code_real_type code;
+      reloc_howto_type *howto;
+      
+      /* Alien reloc: Try to determine its type to replace it with an
+        equivalent ELF reloc. */
+
+      if (areloc->howto->pc_relative)
+       {
+         switch (areloc->howto->bitsize)
+           {
+           case 8:
+             code = BFD_RELOC_8_PCREL; 
+             break;
+           case 12:
+             code = BFD_RELOC_12_PCREL; 
+             break;
+           case 16:
+             code = BFD_RELOC_16_PCREL; 
+             break;
+           case 24:
+             code = BFD_RELOC_24_PCREL; 
+             break;
+           case 32:
+             code = BFD_RELOC_32_PCREL; 
+             break;
+           case 64:
+             code = BFD_RELOC_64_PCREL; 
+             break;
+           default:
+             goto fail;
+           }
+
+         howto = bfd_reloc_type_lookup (abfd, code);
+
+         if (areloc->howto->pcrel_offset != howto->pcrel_offset)
+           {
+             if (howto->pcrel_offset)
+               areloc->addend += areloc->address;
+             else
+               areloc->addend -= areloc->address; /* addend is unsigned!! */
+           }
+       }
+      else
+       {
+         switch (areloc->howto->bitsize)
+           {
+           case 8:
+             code = BFD_RELOC_8; 
+             break;
+           case 14:
+             code = BFD_RELOC_14; 
+             break;
+           case 16:
+             code = BFD_RELOC_16; 
+             break;
+           case 26:
+             code = BFD_RELOC_26; 
+             break;
+           case 32:
+             code = BFD_RELOC_32; 
+             break;
+           case 64:
+             code = BFD_RELOC_64; 
+             break;
+           default:
+             goto fail;
+           }
+
+         howto = bfd_reloc_type_lookup (abfd, code);
+       }
+
+      if (howto)
+       areloc->howto = howto;
+      else
+       goto fail;
+    }
+
+  return true;
+
+ fail:
+  (*_bfd_error_handler)
+    ("%s: unsupported relocation type %s",
+     bfd_get_filename (abfd), areloc->howto->name);
+  bfd_set_error (bfd_error_bad_value);
+  return false;
+}
This page took 0.050261 seconds and 4 git commands to generate.