* Makefile.am: Run "make dep-am".
[deliverable/binutils-gdb.git] / bfd / elf64-hppa.c
index b5edaf14578f30722cfe1eec113fabb73944a1b5..defd72d18a5253bea3710b090be797a966a1085c 100644 (file)
@@ -1,5 +1,5 @@
-/* Generic support for 64-bit ELF
-   Copyright 1999, 2000 Free Software Foundation, Inc.
+/* Support for HPPA 64-bit ELF
+   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+#include "alloca-conf.h"
 #include "bfd.h"
 #include "sysdep.h"
 #include "libbfd.h"
@@ -29,7 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define PLT_ENTRY_SIZE 0x10
 #define DLT_ENTRY_SIZE 0x8
 #define OPD_ENTRY_SIZE 0x20
+
 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/pa20_64/dld.sl"
 
 /* The stub is supposed to load the target address and target's DP
@@ -61,7 +62,7 @@ struct elf64_hppa_dyn_hash_entry
   /* The index of the (possibly local) symbol in the input bfd and its
      associated BFD.  Needed so that we can have relocs against local
      symbols in shared libraries.  */
-  unsigned long sym_indx;
+  long sym_indx;
   bfd *owner;
 
   /* Dynamic symbols may need to have two different values.  One for
@@ -168,19 +169,17 @@ static struct elf64_hppa_dyn_hash_entry *elf64_hppa_dyn_hash_lookup
           boolean create, boolean copy));
 static void elf64_hppa_dyn_hash_traverse
   PARAMS ((struct elf64_hppa_dyn_hash_table *table,
-          boolean (*func)(struct elf64_hppa_dyn_hash_entry *, PTR),
+          boolean (*func) (struct elf64_hppa_dyn_hash_entry *, PTR),
           PTR info));
 
 static const char *get_dyn_name
   PARAMS ((asection *, struct elf_link_hash_entry *,
           const Elf_Internal_Rela *, char **, size_t *));
 
-
 /* This must follow the definitions of the various derived linker
    hash tables and shared functions.  */
 #include "elf-hppa.h"
 
-
 static boolean elf64_hppa_object_p
   PARAMS ((bfd *));
 
@@ -199,10 +198,18 @@ static boolean elf64_hppa_adjust_dynamic_symbol
 static boolean elf64_hppa_size_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 
+static boolean elf64_hppa_link_output_symbol_hook
+PARAMS ((bfd *abfd, struct bfd_link_info *, const char *,
+        Elf_Internal_Sym *, asection *input_sec));
+
 static boolean elf64_hppa_finish_dynamic_symbol
   PARAMS ((bfd *, struct bfd_link_info *,
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
-       
+
+static int elf64_hppa_additional_program_headers PARAMS ((bfd *));
+
+static boolean elf64_hppa_modify_segment_map PARAMS ((bfd *));
+
 static boolean elf64_hppa_finish_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 
@@ -259,13 +266,16 @@ static boolean get_dlt
 static boolean get_stub
   PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));
 
+static int elf64_hppa_elf_get_symbol_type
+  PARAMS ((Elf_Internal_Sym *, int));
+
 static boolean
 elf64_hppa_dyn_hash_table_init (ht, abfd, new)
      struct elf64_hppa_dyn_hash_table *ht;
      bfd *abfd ATTRIBUTE_UNUSED;
      new_hash_entry_func new;
 {
-  memset (ht, 0, sizeof(*ht));
+  memset (ht, 0, sizeof (*ht));
   return bfd_hash_table_init (&ht->root, new);
 }
 
@@ -288,7 +298,7 @@ elf64_hppa_new_dyn_hash_entry (entry, table, string)
 
   /* Initialize our local data.  All zeros, and definitely easier
      than setting 8 bit fields.  */
-  memset (ret, 0, sizeof(*ret));
+  memset (ret, 0, sizeof (*ret));
 
   /* Call the allocation method of the superclass.  */
   ret = ((struct elf64_hppa_dyn_hash_entry *)
@@ -307,7 +317,7 @@ elf64_hppa_hash_table_create (abfd)
 {
   struct elf64_hppa_link_hash_table *ret;
 
-  ret = bfd_zalloc (abfd, sizeof (*ret));
+  ret = bfd_zalloc (abfd, (bfd_size_type) sizeof (*ret));
   if (!ret)
     return 0;
   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
@@ -356,8 +366,35 @@ static boolean
 elf64_hppa_object_p (abfd)
      bfd *abfd;
 {
-  /* Set the right machine number for an HPPA ELF file.  */
-  return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 25);
+  Elf_Internal_Ehdr * i_ehdrp;
+  unsigned int flags;
+
+  i_ehdrp = elf_elfheader (abfd);
+  if (strcmp (bfd_get_target (abfd), "elf64-hppa-linux") == 0)
+    {
+      if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_LINUX)
+       return false;
+    }
+  else
+    {
+      if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_HPUX)
+       return false;
+    }
+
+  flags = i_ehdrp->e_flags;
+  switch (flags & (EF_PARISC_ARCH | EF_PARISC_WIDE))
+    {
+    case EFA_PARISC_1_0:
+      return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 10);
+    case EFA_PARISC_1_1:
+      return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 11);
+    case EFA_PARISC_2_0:
+      return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 20);
+    case EFA_PARISC_2_0 | EF_PARISC_WIDE:
+      return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 25);
+    }
+  /* Don't be fussy.  */
+  return true;
 }
 
 /* Given section type (hdr->sh_type), return a boolean indicating
@@ -393,9 +430,8 @@ elf64_hppa_section_from_shdr (abfd, hdr, name)
   return true;
 }
 
-
 /* Construct a string for use in the elf64_hppa_dyn_hash_table.  The
-   name describes what was once potentially anonymous memory.  We 
+   name describes what was once potentially anonymous memory.  We
    allocate memory as necessary, possibly reusing PBUF/PLEN.  */
 
 static const char *
@@ -502,7 +538,7 @@ get_reloc_section (abfd, hppa_info, sec)
   return true;
 }
 
-/* Add a new entry to the list of dynamic relocations against DYN_H. 
+/* Add a new entry to the list of dynamic relocations against DYN_H.
 
    We use this to keep a record of all the FPTR relocations against a
    particular symbol so that we can create FPTR relocations in the
@@ -521,7 +557,7 @@ count_dyn_reloc (abfd, dyn_h, type, sec, sec_symndx, offset, addend)
   struct elf64_hppa_dyn_reloc_entry *rent;
 
   rent = (struct elf64_hppa_dyn_reloc_entry *)
-  bfd_alloc (abfd, sizeof (*rent));
+  bfd_alloc (abfd, (bfd_size_type) sizeof (*rent));
   if (!rent)
     return false;
 
@@ -549,6 +585,7 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
   struct elf64_hppa_link_hash_table *hppa_info;
   const Elf_Internal_Rela *relend;
   Elf_Internal_Shdr *symtab_hdr;
+  Elf_Internal_Shdr *shndx_hdr;
   const Elf_Internal_Rela *rel;
   asection *dlt, *plt, *stubs;
   char *buf;
@@ -571,13 +608,15 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
 
   /* If necessary, build a new table holding section symbols indices
      for this BFD.  This is disgusting.  */
+
   if (info->shared && hppa_info->section_syms_bfd != abfd)
     {
-      unsigned int i;
-      int highest_shndx;
+      unsigned long i;
+      unsigned int highest_shndx;
       Elf_Internal_Sym *local_syms, *isym;
       Elf64_External_Sym *ext_syms, *esym;
+      Elf_External_Sym_Shndx *shndx_buf, *shndx;
+      bfd_size_type amt;
 
       /* We're done with the old cache of section index to section symbol
         index information.  Free it.
@@ -588,15 +627,15 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
        free (hppa_info->section_syms);
 
       /* Allocate memory for the internal and external symbols.  */
-      local_syms
-        = (Elf_Internal_Sym *) bfd_malloc (symtab_hdr->sh_info
-                                           * sizeof (Elf_Internal_Sym));
+      amt = symtab_hdr->sh_info;
+      amt *= sizeof (Elf_Internal_Sym);
+      local_syms = (Elf_Internal_Sym *) bfd_malloc (amt);
       if (local_syms == NULL)
        return false;
 
-      ext_syms
-        = (Elf64_External_Sym *) bfd_malloc (symtab_hdr->sh_info
-                                             * sizeof (Elf64_External_Sym));
+      amt = symtab_hdr->sh_info;
+      amt *= sizeof (Elf64_External_Sym);
+      ext_syms = (Elf64_External_Sym *) bfd_malloc (amt);
       if (ext_syms == NULL)
        {
          free (local_syms);
@@ -605,36 +644,59 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
 
       /* Read in the local symbols.  */
       if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-          || bfd_read (ext_syms, 1,
-                       (symtab_hdr->sh_info
-                        * sizeof (Elf64_External_Sym)), abfd)
-          != (symtab_hdr->sh_info * sizeof (Elf64_External_Sym)))
+          || bfd_bread (ext_syms, amt, abfd) != amt)
         {
-         free (local_syms);
          free (ext_syms);
+         free (local_syms);
          return false;
         }
 
+      shndx_buf = NULL;
+      shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+      if (shndx_hdr->sh_size != 0)
+       {
+         amt = symtab_hdr->sh_info;
+         amt *= sizeof (Elf_External_Sym_Shndx);
+         shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+         if (shndx_buf == NULL)
+           {
+             free (ext_syms);
+             free (local_syms);
+             return false;
+           }
+
+         if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
+             || bfd_bread (shndx_buf, amt, abfd) != amt)
+           {
+             free (shndx_buf);
+             free (ext_syms);
+             free (local_syms);
+             return false;
+           }
+       }
+
       /* Swap in the local symbols, also record the highest section index
         referenced by the local symbols.  */
-      isym = local_syms;
-      esym = ext_syms;
       highest_shndx = 0;
-      for (i = 0; i < symtab_hdr->sh_info; i++, esym++, isym++)
+      for (i = 0, isym = local_syms, esym = ext_syms, shndx = shndx_buf;
+          i < symtab_hdr->sh_info;
+          i++, esym++, isym++, shndx = (shndx != NULL ? shndx + 1 : NULL))
        {
-         bfd_elf64_swap_symbol_in (abfd, esym, isym);
+         bfd_elf64_swap_symbol_in (abfd, esym, shndx, isym);
          if (isym->st_shndx > highest_shndx)
            highest_shndx = isym->st_shndx;
        }
 
       /* Now we can free the external symbols.  */
+      free (shndx_buf);
       free (ext_syms);
 
       /* Allocate an array to hold the section index to section symbol index
         mapping.  Bump by one since we start counting at zero.  */
       highest_shndx++;
-      hppa_info->section_syms = (int *) bfd_malloc (highest_shndx
-                                                   * sizeof (int));
+      amt = highest_shndx;
+      amt *= sizeof (int);
+      hppa_info->section_syms = (int *) bfd_malloc (amt);
 
       /* Now walk the local symbols again.  If we find a section symbol,
         record the index of the symbol into the section_syms array.  */
@@ -668,7 +730,7 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
     }
   else
     sec_symndx = 0;
+
   dlt = plt = stubs = NULL;
   buf = NULL;
   buf_len = 0;
@@ -711,7 +773,8 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
         have yet been processed.  Do something with what we know, as
         this may help reduce memory usage and processing time later.  */
       maybe_dynamic = false;
-      if (h && ((info->shared && ! info->symbolic)
+      if (h && ((info->shared
+                   && (!info->symbolic || info->allow_shlib_undefined) )
                || ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
                || h->root.type == bfd_link_hash_defweak))
        maybe_dynamic = true;
@@ -748,6 +811,7 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
        /* These are function calls.  Depending on their precise target we
           may need to make a stub for them.  The stub uses the PLT, so we
           need to create PLT entries for these symbols too.  */
+       case R_PARISC_PCREL12F:
        case R_PARISC_PCREL17F:
        case R_PARISC_PCREL22F:
        case R_PARISC_PCREL32:
@@ -867,7 +931,7 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
 
          /* FPTRs are not allocated by the dynamic linker for PA64, though
             it is possible that will change in the future.  */
-           
+
          /* This could be a local function that had its address taken, in
             which case H will be NULL.  */
          if (h)
@@ -937,7 +1001,7 @@ elf64_hppa_dynamic_symbol_p (h, info)
   if (h->root.root.string[0] == '$' && h->root.root.string[1] == '$')
     return false;
 
-  if ((info->shared && !info->symbolic)
+  if ((info->shared && (!info->symbolic || info->allow_shlib_undefined))
       || ((h->elf_link_hash_flags
           & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))
          == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))
@@ -978,6 +1042,8 @@ elf64_hppa_mark_exported_functions (h, data)
        return false;
 
       dyn_h->want_opd = 1;
+      /* Put a flag here for output_symbol_hook.  */
+      dyn_h->st_shndx = -1;
       h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
     }
 
@@ -1008,8 +1074,8 @@ allocate_global_data_dlt (dyn_h, data)
              bfd *owner;
              owner = (h ? h->root.u.def.section->owner : dyn_h->owner);
 
-             if (!_bfd_elf64_link_record_local_dynamic_symbol
-                   (x->info, owner, dyn_h->sym_indx))
+             if (! (_bfd_elf64_link_record_local_dynamic_symbol
+                    (x->info, owner, dyn_h->sym_indx)))
                return false;
            }
        }
@@ -1081,7 +1147,7 @@ allocate_global_data_opd (dyn_h, data)
   if (dyn_h->want_opd)
     {
       struct elf_link_hash_entry *h = dyn_h->h;
-      
+
       if (h)
        while (h->root.type == bfd_link_hash_indirect
               || h->root.type == bfd_link_hash_warning)
@@ -1165,8 +1231,15 @@ elf64_hppa_post_process_headers (abfd, link_info)
 
   i_ehdrp = elf_elfheader (abfd);
 
-  i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
-  i_ehdrp->e_ident[EI_ABIVERSION] = 1;
+  if (strcmp (bfd_get_target (abfd), "elf64-hppa-linux") == 0)
+    {
+      i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
+    }
+  else
+    {
+      i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
+      i_ehdrp->e_ident[EI_ABIVERSION] = 1;
+    }
 }
 
 /* Create function descriptor section (.opd).  This section is called .opd
@@ -1358,7 +1431,7 @@ get_stub (abfd, info, hppa_info)
        Should contain dynamic IPLT (and EPLT?) relocations.
 
    .opd:
-       FPTRS 
+       FPTRS
 
    .rela.opd:
        EPLT relocations for symbols exported from shared libraries.  */
@@ -1737,10 +1810,14 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
        }
 
       /* Allocate memory for the section contents if it has not
-        been allocated already.  */
+        been allocated already.  We use bfd_zalloc here in case
+        unused entries are not reclaimed before the section's
+        contents are written out.  This should not happen, but this
+        way if it does, we get a R_PARISC_NONE reloc instead of
+        garbage.  */
       if (s->contents == NULL)
        {
-         s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+         s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
          if (s->contents == NULL && s->_raw_size != 0)
            return false;
        }
@@ -1751,8 +1828,11 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
       /* Always create a DT_PLTGOT.  It actually has nothing to do with
         the PLT, it is how we communicate the __gp value of a load
         module to the dynamic linker.  */
-      if (! bfd_elf64_add_dynamic_entry (info, DT_HP_DLD_FLAGS, 0)
-         || ! bfd_elf64_add_dynamic_entry (info, DT_PLTGOT, 0))
+#define add_dynamic_entry(TAG, VAL) \
+  bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
+      if (!add_dynamic_entry (DT_HP_DLD_FLAGS, 0)
+         || !add_dynamic_entry (DT_PLTGOT, 0))
        return false;
 
       /* Add some entries to the .dynamic section.  We fill in the
@@ -1762,36 +1842,36 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
         dynamic linker and used by the debugger.  */
       if (! info->shared)
        {
-         if (! bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_HP_DLD_HOOK, 0)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_HP_LOAD_MAP, 0))
+         if (!add_dynamic_entry (DT_DEBUG, 0)
+             || !add_dynamic_entry (DT_HP_DLD_HOOK, 0)
+             || !add_dynamic_entry (DT_HP_LOAD_MAP, 0))
            return false;
        }
 
       if (plt)
        {
-         if (! bfd_elf64_add_dynamic_entry (info, DT_PLTRELSZ, 0)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_JMPREL, 0))
+         if (!add_dynamic_entry (DT_PLTRELSZ, 0)
+             || !add_dynamic_entry (DT_PLTREL, DT_RELA)
+             || !add_dynamic_entry (DT_JMPREL, 0))
            return false;
        }
 
       if (relocs)
        {
-         if (! bfd_elf64_add_dynamic_entry (info, DT_RELA, 0)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_RELASZ, 0)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_RELAENT,
-                                               sizeof (Elf64_External_Rela)))
+         if (!add_dynamic_entry (DT_RELA, 0)
+             || !add_dynamic_entry (DT_RELASZ, 0)
+             || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
            return false;
        }
 
       if (reltext)
        {
-         if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
+         if (!add_dynamic_entry (DT_TEXTREL, 0))
            return false;
          info->flags |= DF_TEXTREL;
        }
     }
+#undef add_dynamic_entry
 
   return true;
 }
@@ -1826,13 +1906,18 @@ elf64_hppa_link_output_symbol_hook (abfd, info, name, sym, input_sec)
   dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
                                      name, false, false);
 
-  /* Function symbols for which we created .opd entries were munged
-     by finish_dynamic_symbol and have to be un-munged here.  */
-  if (dyn_h && dyn_h->want_opd)
+  /* Function symbols for which we created .opd entries *may* have been
+     munged by finish_dynamic_symbol and have to be un-munged here.
+
+     Note that finish_dynamic_symbol sometimes turns dynamic symbols
+     into non-dynamic ones, so we initialize st_shndx to -1 in
+     mark_exported_functions and check to see if it was overwritten
+     here instead of just checking dyn_h->h->dynindx.  */
+  if (dyn_h && dyn_h->want_opd && dyn_h->st_shndx != -1)
     {
       /* Restore the saved value and section index.  */
       sym->st_value = dyn_h->st_value;
-      sym->st_shndx = dyn_h->st_shndx; 
+      sym->st_shndx = dyn_h->st_shndx;
     }
 
   return true;
@@ -1905,13 +1990,13 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
       else
        value = (h->root.u.def.value + h->root.u.def.section->vma);
 
-      /* Fill in the entry in the procedure linkage table. 
+      /* Fill in the entry in the procedure linkage table.
 
         The format of a plt entry is
-        <funcaddr> <__gp>. 
+        <funcaddr> <__gp>.
 
         plt_offset is the offset within the PLT section at which to
-        install the PLT entry. 
+        install the PLT entry.
 
         We are modifying the in-memory PLT contents here, so we do not add
         in the output_offset of the PLT section.  */
@@ -1944,6 +2029,7 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
     {
       bfd_vma value;
       int insn;
+      unsigned int max_offset;
 
       /* Install the generic stub template.
 
@@ -1954,7 +2040,7 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
       /* Fix up the first ldd instruction.
 
         We are modifying the contents of the STUB section in memory,
-        so we do not need to include its output offset in this computation. 
+        so we do not need to include its output offset in this computation.
 
         Note the plt_offset value is the value of the PLT entry relative to
         the start of the PLT section.  These instructions will reference
@@ -1963,24 +2049,47 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
 
         gp_offset contains the offset of __gp within the PLT section.  */
       value = dyn_h->plt_offset - hppa_info->gp_offset;
-      
+
       insn = bfd_get_32 (stub->owner, stub->contents + dyn_h->stub_offset);
-      insn &= 0xffffc00e;
-      insn |= ((value & 0x2000) >> 13);
-      value &= 0x1ff8;
-      value <<= 1;
-      bfd_put_32 (stub->owner, (insn | value),
+      if (output_bfd->arch_info->mach >= 25)
+       {
+         /* Wide mode allows 16 bit offsets.  */
+         max_offset = 32768;
+         insn &= ~ 0xfff1;
+         insn |= re_assemble_16 ((int) value);
+       }
+      else
+       {
+         max_offset = 8192;
+         insn &= ~ 0x3ff1;
+         insn |= re_assemble_14 ((int) value);
+       }
+
+      if ((value & 7) || value + max_offset >= 2*max_offset - 8)
+       {
+         (*_bfd_error_handler) (_("stub entry for %s cannot load .plt, dp offset = %ld"),
+                                dyn_h->root.string,
+                                (long) value);
+         return false;
+       }
+
+      bfd_put_32 (stub->owner, (bfd_vma) insn,
                  stub->contents + dyn_h->stub_offset);
 
       /* Fix up the second ldd instruction.  */
-      value = dyn_h->plt_offset - hppa_info->gp_offset + 8;
-      
+      value += 8;
       insn = bfd_get_32 (stub->owner, stub->contents + dyn_h->stub_offset + 8);
-      insn &= 0xffffc00e;
-      insn |= ((value & 0x2000) >> 13);
-      value &= 0x1ff8;
-      value <<= 1;
-      bfd_put_32 (stub->owner, (insn | value),
+      if (output_bfd->arch_info->mach >= 25)
+       {
+         insn &= ~ 0xfff1;
+         insn |= re_assemble_16 ((int) value);
+       }
+      else
+       {
+         insn &= ~ 0x3ff1;
+         insn |= re_assemble_14 ((int) value);
+       }
+      bfd_put_32 (stub->owner, (bfd_vma) insn,
                  stub->contents + dyn_h->stub_offset + 8);
     }
 
@@ -2014,7 +2123,7 @@ elf64_hppa_finalize_opd (dyn_h, data)
     {
       bfd_vma value;
 
-      /* The first two words of an .opd entry are zero. 
+      /* The first two words of an .opd entry are zero.
 
         We are modifying the contents of the OPD section in memory, so we
         do not need to include its output offset in this computation.  */
@@ -2067,7 +2176,7 @@ elf64_hppa_finalize_opd (dyn_h, data)
         (if we did, the data in the .opd would reference itself rather
         than the actual address of the function).  Instead we have to use
         a new dynamic symbol which has the same value as the original global
-        function symbol. 
+        function symbol.
 
         We prefix the original symbol with a "." and use the new symbol in
         the EPLT relocation.  This new symbol has already been recorded in
@@ -2139,7 +2248,7 @@ elf64_hppa_finalize_dlt (dyn_h, data)
       bfd_vma value;
 
       /* If we had an LTOFF_FPTR style relocation we want the DLT entry
-        to point to the FPTR entry in the .opd section. 
+        to point to the FPTR entry in the .opd section.
 
         We include the OPD's output offset in this computation as
         we are referring to an absolute address in the resulting
@@ -2184,7 +2293,6 @@ elf64_hppa_finalize_dlt (dyn_h, data)
          = _bfd_elf_link_lookup_local_dynindx (info, dyn_h->owner,
                                                dyn_h->sym_indx);
 
-
       /* Create a dynamic relocation for this entry.  Do include the output
         offset of the DLT entry since we need an absolute address in the
         resulting object file.  */
@@ -2256,7 +2364,7 @@ elf64_hppa_finalize_dynreloc (dyn_h, data)
              break;
            }
 
-         /* Create a dynamic relocation for this entry. 
+         /* Create a dynamic relocation for this entry.
 
             We need the output offset for the reloc's section because
             we are creating an absolute address in the resulting object
@@ -2279,7 +2387,7 @@ elf64_hppa_finalize_dynreloc (dyn_h, data)
             the .opd entry.  At least that seems sensible until you
             realize there's no local dynamic symbols we can use for that
             purpose.  Thus the hair in the check_relocs routine.
-       
+
             We use a section symbol recorded by check_relocs as the
             base symbol for the relocation.  The addend is the difference
             between the section symbol and the address of the .opd entry.  */
@@ -2300,7 +2408,7 @@ elf64_hppa_finalize_dynreloc (dyn_h, data)
              /* Compute the difference between the start of the section
                 with the relocation and the opd entry.  */
              value -= value2;
-               
+
              /* The result becomes the addend of the relocation.  */
              rel.r_addend = value;
 
@@ -2357,7 +2465,6 @@ elf64_hppa_finish_dynamic_sections (output_bfd, info)
                                elf64_hppa_finalize_dlt,
                                info);
 
-
   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
 
   if (elf_hash_table (info)->dynamic_sections_created)
@@ -2440,11 +2547,10 @@ elf64_hppa_finish_dynamic_sections (output_bfd, info)
   return true;
 }
 
-
 /* Return the number of additional phdrs we will need.
 
    The generic ELF code only creates PT_PHDRs for executables.  The HP
-   dynamic linker requires PT_PHDRs for dynamic libraries too. 
+   dynamic linker requires PT_PHDRs for dynamic libraries too.
 
    This routine indicates that the backend needs one additional program
    header for that case.
@@ -2471,10 +2577,10 @@ elf64_hppa_additional_program_headers (abfd)
    specific backend.
 
    The generic ELF code only creates PT_PHDRs for executables.  The HP
-   dynamic linker requires PT_PHDRs for dynamic libraries too. 
+   dynamic linker requires PT_PHDRs for dynamic libraries too.
 
    This allocates the PT_PHDR and initializes it in a manner suitable
-   for the HP linker. 
+   for the HP linker.
 
    Note we do not have access to the link info structure here, so we have
    to guess whether or not we are building a shared library based on the
@@ -2495,7 +2601,8 @@ elf64_hppa_modify_segment_map (abfd)
          break;
       if (m == NULL)
        {
-         m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);
+         m = ((struct elf_segment_map *)
+              bfd_zalloc (abfd, (bfd_size_type) sizeof *m));
          if (m == NULL)
            return false;
 
@@ -2531,6 +2638,19 @@ elf64_hppa_modify_segment_map (abfd)
   return true;
 }
 
+/* Called when writing out an object file to decide the type of a
+   symbol.  */
+static int
+elf64_hppa_elf_get_symbol_type (elf_sym, type)
+     Elf_Internal_Sym *elf_sym;
+     int type;
+{
+  if (ELF_ST_TYPE (elf_sym->st_info) == STT_PARISC_MILLI)
+    return STT_PARISC_MILLI;
+  else
+    return type;
+}
+
 /* The hash bucket size is the standard one, namely 4.  */
 
 const struct elf_size_info hppa64_elf_size_info =
@@ -2577,7 +2697,7 @@ const struct elf_size_info hppa64_elf_size_info =
 #define elf_backend_object_p           elf64_hppa_object_p
 #define elf_backend_final_write_processing \
                                        elf_hppa_final_write_processing
-#define elf_backend_fake_sections      elf_hppa_fake_sections
+#define elf_backend_fake_sections      elf_hppa_fake_sections
 #define elf_backend_add_symbol_hook    elf_hppa_add_symbol_hook
 
 #define elf_backend_relocate_section       elf_hppa_relocate_section
@@ -2618,12 +2738,20 @@ const struct elf_size_info hppa64_elf_size_info =
 #define elf_backend_link_output_symbol_hook \
        elf64_hppa_link_output_symbol_hook
 
-
 #define elf_backend_want_got_plt       0
 #define elf_backend_plt_readonly       0
 #define elf_backend_want_plt_sym       0
 #define elf_backend_got_header_size     0
 #define elf_backend_plt_header_size     0
 #define elf_backend_type_change_ok true
+#define elf_backend_get_symbol_type         elf64_hppa_elf_get_symbol_type
+
+#include "elf64-target.h"
+
+#undef TARGET_BIG_SYM
+#define TARGET_BIG_SYM                 bfd_elf64_hppa_linux_vec
+#undef TARGET_BIG_NAME
+#define TARGET_BIG_NAME                        "elf64-hppa-linux"
 
+#define INCLUDED_TARGET_FILE 1
 #include "elf64-target.h"
This page took 0.033482 seconds and 4 git commands to generate.