s/boolean/bfd_boolean/ s/true/TRUE/ s/false/FALSE/. Simplify
[deliverable/binutils-gdb.git] / bfd / elf64-hppa.c
index 4c75c0ec7a94ebdfec2eac6e697e36fef58fa3f6..98f46dc8fc0818b708a2d01aea89969dbe894357 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, 2002 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -30,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
@@ -62,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
@@ -156,7 +156,7 @@ struct elf64_hppa_link_hash_table
 typedef struct bfd_hash_entry *(*new_hash_entry_func)
   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
 
-static boolean elf64_hppa_dyn_hash_table_init
+static bfd_boolean elf64_hppa_dyn_hash_table_init
   PARAMS ((struct elf64_hppa_dyn_hash_table *ht, bfd *abfd,
           new_hash_entry_func new));
 static struct bfd_hash_entry *elf64_hppa_new_dyn_hash_entry
@@ -166,107 +166,124 @@ static struct bfd_link_hash_table *elf64_hppa_hash_table_create
   PARAMS ((bfd *abfd));
 static struct elf64_hppa_dyn_hash_entry *elf64_hppa_dyn_hash_lookup
   PARAMS ((struct elf64_hppa_dyn_hash_table *table, const char *string,
-          boolean create, boolean copy));
+          bfd_boolean create, bfd_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),
+          bfd_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
+static bfd_boolean elf64_hppa_object_p
   PARAMS ((bfd *));
 
-static boolean elf64_hppa_section_from_shdr
-  PARAMS ((bfd *, Elf64_Internal_Shdr *, char *));
+static bfd_boolean elf64_hppa_section_from_shdr
+  PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
 
 static void elf64_hppa_post_process_headers
   PARAMS ((bfd *, struct bfd_link_info *));
 
-static boolean elf64_hppa_create_dynamic_sections
+static bfd_boolean elf64_hppa_create_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 
-static boolean elf64_hppa_adjust_dynamic_symbol
+static bfd_boolean elf64_hppa_adjust_dynamic_symbol
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
 
-static boolean elf64_hppa_size_dynamic_sections
+static bfd_boolean elf64_hppa_mark_milli_and_exported_functions
+  PARAMS ((struct elf_link_hash_entry *, PTR));
+
+static bfd_boolean elf64_hppa_size_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 
-static boolean elf64_hppa_finish_dynamic_symbol
+static bfd_boolean elf64_hppa_link_output_symbol_hook
+  PARAMS ((bfd *abfd, struct bfd_link_info *, const char *,
+          Elf_Internal_Sym *, asection *input_sec));
+
+static bfd_boolean elf64_hppa_finish_dynamic_symbol
   PARAMS ((bfd *, struct bfd_link_info *,
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
-       
-static boolean elf64_hppa_finish_dynamic_sections
+
+static int elf64_hppa_additional_program_headers
+  PARAMS ((bfd *));
+
+static bfd_boolean elf64_hppa_modify_segment_map
+  PARAMS ((bfd *));
+
+static enum elf_reloc_type_class elf64_hppa_reloc_type_class
+  PARAMS ((const Elf_Internal_Rela *));
+
+static bfd_boolean elf64_hppa_finish_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 
-static boolean elf64_hppa_check_relocs
+static bfd_boolean elf64_hppa_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *,
           asection *, const Elf_Internal_Rela *));
 
-static boolean elf64_hppa_dynamic_symbol_p
+static bfd_boolean elf64_hppa_dynamic_symbol_p
   PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *));
 
-static boolean elf64_hppa_mark_exported_functions
+static bfd_boolean elf64_hppa_mark_exported_functions
   PARAMS ((struct elf_link_hash_entry *, PTR));
 
-static boolean elf64_hppa_finalize_opd
+static bfd_boolean elf64_hppa_finalize_opd
   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
 
-static boolean elf64_hppa_finalize_dlt
+static bfd_boolean elf64_hppa_finalize_dlt
   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
 
-static boolean allocate_global_data_dlt
+static bfd_boolean allocate_global_data_dlt
   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
 
-static boolean allocate_global_data_plt
+static bfd_boolean allocate_global_data_plt
   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
 
-static boolean allocate_global_data_stub
+static bfd_boolean allocate_global_data_stub
   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
 
-static boolean allocate_global_data_opd
+static bfd_boolean allocate_global_data_opd
   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
 
-static boolean get_reloc_section
+static bfd_boolean get_reloc_section
   PARAMS ((bfd *, struct elf64_hppa_link_hash_table *, asection *));
 
-static boolean count_dyn_reloc
+static bfd_boolean count_dyn_reloc
   PARAMS ((bfd *, struct elf64_hppa_dyn_hash_entry *,
           int, asection *, int, bfd_vma, bfd_vma));
 
-static boolean allocate_dynrel_entries
+static bfd_boolean allocate_dynrel_entries
   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
 
-static boolean elf64_hppa_finalize_dynreloc
+static bfd_boolean elf64_hppa_finalize_dynreloc
   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
 
-static boolean get_opd
+static bfd_boolean get_opd
   PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));
 
-static boolean get_plt
+static bfd_boolean get_plt
   PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));
 
-static boolean get_dlt
+static bfd_boolean get_dlt
   PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));
 
-static boolean get_stub
+static bfd_boolean get_stub
   PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));
 
-static boolean
+static int elf64_hppa_elf_get_symbol_type
+  PARAMS ((Elf_Internal_Sym *, int));
+
+static bfd_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);
 }
 
@@ -289,7 +306,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 *)
@@ -308,7 +325,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,
@@ -330,7 +347,7 @@ static struct elf64_hppa_dyn_hash_entry *
 elf64_hppa_dyn_hash_lookup(table, string, create, copy)
      struct elf64_hppa_dyn_hash_table *table;
      const char *string;
-     boolean create, copy;
+     bfd_boolean create, copy;
 {
   return ((struct elf64_hppa_dyn_hash_entry *)
          bfd_hash_lookup (&table->root, string, create, copy));
@@ -341,33 +358,60 @@ elf64_hppa_dyn_hash_lookup(table, string, create, copy)
 static void
 elf64_hppa_dyn_hash_traverse (table, func, info)
      struct elf64_hppa_dyn_hash_table *table;
-     boolean (*func) PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
+     bfd_boolean (*func) PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
      PTR info;
 {
   (bfd_hash_traverse
    (&table->root,
-    (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) func,
+    (bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) func,
     info));
 }
 \f
 /* Return nonzero if ABFD represents a PA2.0 ELF64 file.
 
    Additionally we set the default architecture and machine.  */
-static boolean
+static bfd_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
    whether or not the section is an elf64-hppa specific section.  */
-static boolean
+static bfd_boolean
 elf64_hppa_section_from_shdr (abfd, hdr, name)
      bfd *abfd;
-     Elf64_Internal_Shdr *hdr;
-     char *name;
+     Elf_Internal_Shdr *hdr;
+     const char *name;
 {
   asection *newsect;
 
@@ -375,28 +419,27 @@ elf64_hppa_section_from_shdr (abfd, hdr, name)
     {
     case SHT_PARISC_EXT:
       if (strcmp (name, ".PARISC.archext") != 0)
-       return false;
+       return FALSE;
       break;
     case SHT_PARISC_UNWIND:
       if (strcmp (name, ".PARISC.unwind") != 0)
-       return false;
+       return FALSE;
       break;
     case SHT_PARISC_DOC:
     case SHT_PARISC_ANNOT:
     default:
-      return false;
+      return FALSE;
     }
 
   if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
-    return false;
+    return FALSE;
   newsect = hdr->bfd_section;
 
-  return true;
+  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 *
@@ -456,7 +499,7 @@ get_dyn_name (sec, h, rel, pbuf, plen)
 /* SEC is a section containing relocs for an input BFD when linking; return
    a suitable section for holding relocs in the output BFD for a link.  */
 
-static boolean
+static bfd_boolean
 get_reloc_section (abfd, hppa_info, sec)
      bfd *abfd;
      struct elf64_hppa_link_hash_table *hppa_info;
@@ -470,7 +513,7 @@ get_reloc_section (abfd, hppa_info, sec)
               (abfd, elf_elfheader(abfd)->e_shstrndx,
                elf_section_data(sec)->rel_hdr.sh_name));
   if (srel_name == NULL)
-    return false;
+    return FALSE;
 
   BFD_ASSERT ((strncmp (srel_name, ".rela", 5) == 0
               && strcmp (bfd_get_section_name (abfd, sec),
@@ -496,20 +539,20 @@ get_reloc_section (abfd, hppa_info, sec)
                                      | SEC_LINKER_CREATED
                                      | SEC_READONLY))
          || !bfd_set_section_alignment (dynobj, srel, 3))
-       return false;
+       return FALSE;
     }
 
   hppa_info->other_rel_sec = srel;
-  return true;
+  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
    output file.  */
 
-static boolean
+static bfd_boolean
 count_dyn_reloc (abfd, dyn_h, type, sec, sec_symndx, offset, addend)
      bfd *abfd;
      struct elf64_hppa_dyn_hash_entry *dyn_h;
@@ -522,9 +565,9 @@ 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;
+    return FALSE;
 
   rent->next = dyn_h->reloc_entries;
   rent->type = type;
@@ -534,13 +577,13 @@ count_dyn_reloc (abfd, dyn_h, type, sec, sec_symndx, offset, addend)
   rent->addend = addend;
   dyn_h->reloc_entries = rent;
 
-  return true;
+  return TRUE;
 }
 
 /* Scan the RELOCS and record the type of dynamic entries that each
    referenced symbol needs.  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_check_relocs (abfd, info, sec, relocs)
      bfd *abfd;
      struct bfd_link_info *info;
@@ -557,28 +600,29 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
   int sec_symndx;
 
   if (info->relocateable)
-    return true;
+    return TRUE;
 
   /* If this is the first dynamic object found in the link, create
      the special sections required for dynamic linking.  */
   if (! elf_hash_table (info)->dynamic_sections_created)
     {
       if (! bfd_elf64_link_create_dynamic_sections (abfd, info))
-       return false;
+       return FALSE;
     }
 
   hppa_info = elf64_hppa_hash_table (info);
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 
   /* If necessary, build a new table holding section symbols indices
-     for this BFD.  This is disgusting.  */
+     for this BFD.  */
+
   if (info->shared && hppa_info->section_syms_bfd != abfd)
     {
       unsigned long i;
-      int highest_shndx;
-      Elf_Internal_Sym *local_syms, *isym;
-      Elf64_External_Sym *ext_syms, *esym;
+      unsigned int highest_shndx;
+      Elf_Internal_Sym *local_syms = NULL;
+      Elf_Internal_Sym *isym, *isymend;
+      bfd_size_type amt;
 
       /* We're done with the old cache of section index to section symbol
         index information.  Free it.
@@ -588,65 +632,54 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
       if (hppa_info->section_syms)
        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));
-      if (local_syms == NULL)
-       return false;
-
-      ext_syms
-        = (Elf64_External_Sym *) bfd_malloc (symtab_hdr->sh_info
-                                             * sizeof (Elf64_External_Sym));
-      if (ext_syms == NULL)
+      /* Read this BFD's local symbols.  */
+      if (symtab_hdr->sh_info != 0)
        {
-         free (local_syms);
-         return false;
+         local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
+         if (local_syms == NULL)
+           local_syms = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+                                              symtab_hdr->sh_info, 0,
+                                              NULL, NULL, NULL);
+         if (local_syms == NULL)
+           return FALSE;
        }
 
-      /* 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)))
-        {
-         free (local_syms);
-         free (ext_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;
+      /* Record the highest section index referenced by the local symbols.  */
       highest_shndx = 0;
-      for (i = 0; i < symtab_hdr->sh_info; i++, esym++, isym++)
+      isymend = local_syms + symtab_hdr->sh_info;
+      for (isym = local_syms; isym < isymend; isym++)
        {
-         bfd_elf64_swap_symbol_in (abfd, esym, isym);
          if (isym->st_shndx > highest_shndx)
            highest_shndx = isym->st_shndx;
        }
 
-      /* Now we can free the external symbols.  */
-      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.  */
-      for (isym = local_syms, i = 0; i < symtab_hdr->sh_info; i++, isym++)
+      for (i = 0, isym = local_syms; isym < isymend; i++, isym++)
        {
          if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
            hppa_info->section_syms[isym->st_shndx] = i;
        }
 
-      /* We are finished with the local symbols.  Get rid of them.  */
-      free (local_syms);
+      /* We are finished with the local symbols.  */
+      if (local_syms != NULL
+         && symtab_hdr->contents != (unsigned char *) local_syms)
+       {
+         if (! info->keep_memory)
+           free (local_syms);
+         else
+           {
+             /* Cache the symbols for elf_link_input_bfd.  */
+             symtab_hdr->contents = (unsigned char *) local_syms;
+           }
+       }
 
       /* Record which BFD we built the section_syms mapping for.  */
       hppa_info->section_syms_bfd = abfd;
@@ -663,13 +696,13 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
       /* If we did not find a section symbol for this section, then
         something went terribly wrong above.  */
       if (sec_symndx == -1)
-       return false;
+       return FALSE;
 
       sec_symndx = hppa_info->section_syms[sec_symndx];
     }
   else
     sec_symndx = 0;
+
   dlt = plt = stubs = NULL;
   buf = NULL;
   buf_len = 0;
@@ -690,7 +723,7 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
       struct elf64_hppa_dyn_hash_entry *dyn_h;
       int need_entry;
       const char *addr_name;
-      boolean maybe_dynamic;
+      bfd_boolean maybe_dynamic;
       int dynrel_type = R_PARISC_NONE;
       static reloc_howto_type *howto;
 
@@ -711,11 +744,12 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
         locally or externally defined, as not all of the input files
         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)
+      maybe_dynamic = FALSE;
+      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;
+       maybe_dynamic = TRUE;
 
       howto = elf_hppa_howto_table + ELF64_R_TYPE (rel->r_info);
       need_entry = 0;
@@ -824,7 +858,7 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
 
       /* Collect the canonical entry data for this address.  */
       dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
-                                         addr_name, true, true);
+                                         addr_name, TRUE, TRUE);
       BFD_ASSERT (dyn_h);
 
       /* Stash away enough information to be able to find this symbol
@@ -869,7 +903,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)
@@ -895,18 +929,18 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
          if (info->shared && dynrel_type == R_PARISC_FPTR64
              && ! (_bfd_elf64_link_record_local_dynamic_symbol
                    (info, abfd, sec_symndx)))
-           return false;
+           return FALSE;
        }
     }
 
   if (buf)
     free (buf);
-  return true;
+  return TRUE;
 
  err_out:
   if (buf)
     free (buf);
-  return false;
+  return FALSE;
 }
 
 struct elf64_hppa_allocate_data
@@ -917,41 +951,41 @@ struct elf64_hppa_allocate_data
 
 /* Should we do dynamic things to this symbol?  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_dynamic_symbol_p (h, info)
      struct elf_link_hash_entry *h;
      struct bfd_link_info *info;
 {
   if (h == NULL)
-    return false;
+    return FALSE;
 
   while (h->root.type == bfd_link_hash_indirect
         || h->root.type == bfd_link_hash_warning)
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
   if (h->dynindx == -1)
-    return false;
+    return FALSE;
 
   if (h->root.type == bfd_link_hash_undefweak
       || h->root.type == bfd_link_hash_defweak)
-    return true;
+    return TRUE;
 
   if (h->root.root.string[0] == '$' && h->root.root.string[1] == '$')
-    return false;
+    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)))
-    return true;
+    return TRUE;
 
-  return false;
+  return FALSE;
 }
 
 /* Mark all funtions exported by this file so that we can later allocate
    entries in .opd for them.  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_mark_exported_functions (h, data)
      struct elf_link_hash_entry *h;
      PTR data;
@@ -961,6 +995,9 @@ elf64_hppa_mark_exported_functions (h, data)
 
   hppa_info = elf64_hppa_hash_table (info);
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   if (h
       && (h->root.type == bfd_link_hash_defined
          || h->root.type == bfd_link_hash_defweak)
@@ -971,13 +1008,13 @@ elf64_hppa_mark_exported_functions (h, data)
 
       /* Add this symbol to the PA64 linker hash table.  */
       dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
-                                         h->root.root.string, true, true);
+                                         h->root.root.string, TRUE, TRUE);
       BFD_ASSERT (dyn_h);
       dyn_h->h = h;
 
       if (! hppa_info->opd_sec
          && ! get_opd (hppa_info->root.dynobj, info, hppa_info))
-       return false;
+       return FALSE;
 
       dyn_h->want_opd = 1;
       /* Put a flag here for output_symbol_hook.  */
@@ -985,12 +1022,12 @@ elf64_hppa_mark_exported_functions (h, data)
       h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Allocate space for a DLT entry.  */
 
-static boolean
+static bfd_boolean
 allocate_global_data_dlt (dyn_h, data)
      struct elf64_hppa_dyn_hash_entry *dyn_h;
      PTR data;
@@ -1007,26 +1044,26 @@ allocate_global_data_dlt (dyn_h, data)
             table since we might need to create a dynamic relocation
             against it.  */
          if (! h
-             || (h && h->dynindx == -1))
+             || (h->dynindx == -1 && h->type != STT_PARISC_MILLI))
            {
              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))
-               return false;
+             if (! (_bfd_elf64_link_record_local_dynamic_symbol
+                    (x->info, owner, dyn_h->sym_indx)))
+               return FALSE;
            }
        }
 
       dyn_h->dlt_offset = x->ofs;
       x->ofs += DLT_ENTRY_SIZE;
     }
-  return true;
+  return TRUE;
 }
 
 /* Allocate space for a DLT.PLT entry.  */
 
-static boolean
+static bfd_boolean
 allocate_global_data_plt (dyn_h, data)
      struct elf64_hppa_dyn_hash_entry *dyn_h;
      PTR data;
@@ -1047,12 +1084,12 @@ allocate_global_data_plt (dyn_h, data)
   else
     dyn_h->want_plt = 0;
 
-  return true;
+  return TRUE;
 }
 
 /* Allocate space for a STUB entry.  */
 
-static boolean
+static bfd_boolean
 allocate_global_data_stub (dyn_h, data)
      struct elf64_hppa_dyn_hash_entry *dyn_h;
      PTR data;
@@ -1070,12 +1107,12 @@ allocate_global_data_stub (dyn_h, data)
     }
   else
     dyn_h->want_stub = 0;
-  return true;
+  return TRUE;
 }
 
 /* Allocate space for a FPTR entry.  */
 
-static boolean
+static bfd_boolean
 allocate_global_data_opd (dyn_h, data)
      struct elf64_hppa_dyn_hash_entry *dyn_h;
      PTR data;
@@ -1085,7 +1122,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)
@@ -1093,7 +1130,8 @@ allocate_global_data_opd (dyn_h, data)
 
       /* We never need an opd entry for a symbol which is not
         defined by this output file.  */
-      if (h && h->root.type == bfd_link_hash_undefined)
+      if (h && (h->root.type == bfd_link_hash_undefined
+               || h->root.u.def.section->output_section == NULL))
        dyn_h->want_opd = 0;
 
       /* If we are creating a shared library, took the address of a local
@@ -1101,10 +1139,9 @@ allocate_global_data_opd (dyn_h, data)
         we have to create an opd descriptor.  */
       else if (x->info->shared
               || h == NULL
-              || h->dynindx == -1
-              || ((h->root.type == bfd_link_hash_defined
-                   || h->root.type == bfd_link_hash_defweak)
-                  && h->root.u.def.section->output_section != NULL))
+              || (h->dynindx == -1 && h->type != STT_PARISC_MILLI)
+              || (h->root.type == bfd_link_hash_defined
+                  || h->root.type == bfd_link_hash_defweak))
        {
          /* If we are creating a shared library, then we will have to
             create a runtime relocation for the symbol to properly
@@ -1118,7 +1155,7 @@ allocate_global_data_opd (dyn_h, data)
 
              if (!_bfd_elf64_link_record_local_dynamic_symbol
                    (x->info, owner, dyn_h->sym_indx))
-               return false;
+               return FALSE;
            }
 
          /* This may not be necessary or desirable anymore now that
@@ -1136,14 +1173,14 @@ allocate_global_data_opd (dyn_h, data)
              strcpy (new_name + 1, h->root.root.string);
 
              nh = elf_link_hash_lookup (elf_hash_table (x->info),
-                                        new_name, true, true, true);
+                                        new_name, TRUE, TRUE, TRUE);
 
              nh->root.type = h->root.type;
              nh->root.u.def.value = h->root.u.def.value;
              nh->root.u.def.section = h->root.u.def.section;
 
              if (! bfd_elf64_link_record_dynamic_symbol (x->info, nh))
-               return false;
+               return FALSE;
 
             }
          dyn_h->opd_offset = x->ofs;
@@ -1154,7 +1191,7 @@ allocate_global_data_opd (dyn_h, data)
       else
        dyn_h->want_opd = 0;
     }
-  return true;
+  return TRUE;
 }
 
 /* HP requires the EI_OSABI field to be filled in.  The assignment to
@@ -1169,8 +1206,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
@@ -1178,7 +1222,7 @@ elf64_hppa_post_process_headers (abfd, link_info)
    refers to the fact that these descriptors are used when taking the address
    of a procedure, thus ensuring a unique address for each procedure.  */
 
-static boolean
+static bfd_boolean
 get_opd (abfd, info, hppa_info)
      bfd *abfd;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
@@ -1205,18 +1249,18 @@ get_opd (abfd, info, hppa_info)
          || !bfd_set_section_alignment (abfd, opd, 3))
        {
          BFD_ASSERT (0);
-         return false;
+         return FALSE;
        }
 
       hppa_info->opd_sec = opd;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Create the PLT section.  */
 
-static boolean
+static bfd_boolean
 get_plt (abfd, info, hppa_info)
      bfd *abfd;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
@@ -1243,18 +1287,18 @@ get_plt (abfd, info, hppa_info)
          || !bfd_set_section_alignment (abfd, plt, 3))
        {
          BFD_ASSERT (0);
-         return false;
+         return FALSE;
        }
 
       hppa_info->plt_sec = plt;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Create the DLT section.  */
 
-static boolean
+static bfd_boolean
 get_dlt (abfd, info, hppa_info)
      bfd *abfd;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
@@ -1281,18 +1325,18 @@ get_dlt (abfd, info, hppa_info)
          || !bfd_set_section_alignment (abfd, dlt, 3))
        {
          BFD_ASSERT (0);
-         return false;
+         return FALSE;
        }
 
       hppa_info->dlt_sec = dlt;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Create the stubs section.  */
 
-static boolean
+static bfd_boolean
 get_stub (abfd, info, hppa_info)
      bfd *abfd;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
@@ -1320,13 +1364,13 @@ get_stub (abfd, info, hppa_info)
          || !bfd_set_section_alignment (abfd, stub, 3))
        {
          BFD_ASSERT (0);
-         return false;
+         return FALSE;
        }
 
       hppa_info->stub_sec = stub;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Create sections necessary for dynamic linking.  This is only a rough
@@ -1362,12 +1406,12 @@ 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.  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_create_dynamic_sections (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
@@ -1375,16 +1419,16 @@ elf64_hppa_create_dynamic_sections (abfd, info)
   asection *s;
 
   if (! get_stub (abfd, info, elf64_hppa_hash_table (info)))
-    return false;
+    return FALSE;
 
   if (! get_dlt (abfd, info, elf64_hppa_hash_table (info)))
-    return false;
+    return FALSE;
 
   if (! get_plt (abfd, info, elf64_hppa_hash_table (info)))
-    return false;
+    return FALSE;
 
   if (! get_opd (abfd, info, elf64_hppa_hash_table (info)))
-    return false;
+    return FALSE;
 
   s = bfd_make_section(abfd, ".rela.dlt");
   if (s == NULL
@@ -1394,7 +1438,7 @@ elf64_hppa_create_dynamic_sections (abfd, info)
                                           | SEC_READONLY
                                           | SEC_LINKER_CREATED))
       || !bfd_set_section_alignment (abfd, s, 3))
-    return false;
+    return FALSE;
   elf64_hppa_hash_table (info)->dlt_rel_sec = s;
 
   s = bfd_make_section(abfd, ".rela.plt");
@@ -1405,7 +1449,7 @@ elf64_hppa_create_dynamic_sections (abfd, info)
                                           | SEC_READONLY
                                           | SEC_LINKER_CREATED))
       || !bfd_set_section_alignment (abfd, s, 3))
-    return false;
+    return FALSE;
   elf64_hppa_hash_table (info)->plt_rel_sec = s;
 
   s = bfd_make_section(abfd, ".rela.data");
@@ -1416,7 +1460,7 @@ elf64_hppa_create_dynamic_sections (abfd, info)
                                           | SEC_READONLY
                                           | SEC_LINKER_CREATED))
       || !bfd_set_section_alignment (abfd, s, 3))
-    return false;
+    return FALSE;
   elf64_hppa_hash_table (info)->other_rel_sec = s;
 
   s = bfd_make_section(abfd, ".rela.opd");
@@ -1427,16 +1471,16 @@ elf64_hppa_create_dynamic_sections (abfd, info)
                                           | SEC_READONLY
                                           | SEC_LINKER_CREATED))
       || !bfd_set_section_alignment (abfd, s, 3))
-    return false;
+    return FALSE;
   elf64_hppa_hash_table (info)->opd_rel_sec = s;
 
-  return true;
+  return TRUE;
 }
 
 /* Allocate dynamic relocations for those symbols that turned out
    to be dynamic.  */
 
-static boolean
+static bfd_boolean
 allocate_dynrel_entries (dyn_h, data)
      struct elf64_hppa_dyn_hash_entry *dyn_h;
      PTR data;
@@ -1444,7 +1488,7 @@ allocate_dynrel_entries (dyn_h, data)
   struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data;
   struct elf64_hppa_link_hash_table *hppa_info;
   struct elf64_hppa_dyn_reloc_entry *rent;
-  boolean dynamic_symbol, shared;
+  bfd_boolean dynamic_symbol, shared;
 
   hppa_info = elf64_hppa_hash_table (x->info);
   dynamic_symbol = elf64_hppa_dynamic_symbol_p (dyn_h->h, x->info);
@@ -1453,31 +1497,27 @@ allocate_dynrel_entries (dyn_h, data)
   /* We may need to allocate relocations for a non-dynamic symbol
      when creating a shared library.  */
   if (!dynamic_symbol && !shared)
-    return true;
+    return TRUE;
 
   /* Take care of the normal data relocations.  */
 
   for (rent = dyn_h->reloc_entries; rent; rent = rent->next)
     {
-      switch (rent->type)
-       {
-       case R_PARISC_FPTR64:
-         /* Allocate one iff we are not building a shared library and
-            !want_opd, which by this point will be true only if we're
-            actually allocating one statically in the main executable.  */
-         if (!x->info->shared && dyn_h->want_opd)
-           continue;
-         break;
-       }
+      /* Allocate one iff we are building a shared library, the relocation
+        isn't a R_PARISC_FPTR64, or we don't want an opd entry.  */
+      if (!shared && rent->type == R_PARISC_FPTR64 && dyn_h->want_opd)
+       continue;
+
       hppa_info->other_rel_sec->_raw_size += sizeof (Elf64_External_Rela);
 
       /* Make sure this symbol gets into the dynamic symbol table if it is
         not already recorded.  ?!? This should not be in the loop since
         the symbol need only be added once.  */
-      if (dyn_h->h == 0 || dyn_h->h->dynindx == -1)
+      if (dyn_h->h == 0
+         || (dyn_h->h->dynindx == -1 && dyn_h->h->type != STT_PARISC_MILLI))
        if (!_bfd_elf64_link_record_local_dynamic_symbol
            (x->info, rent->sec->owner, dyn_h->sym_indx))
-         return false;
+         return FALSE;
     }
 
   /* Take care of the GOT and PLT relocations.  */
@@ -1506,13 +1546,13 @@ allocate_dynrel_entries (dyn_h, data)
       hppa_info->plt_rel_sec->_raw_size += t;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_adjust_dynamic_symbol (info, h)
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      struct elf_link_hash_entry *h;
@@ -1529,7 +1569,7 @@ elf64_hppa_adjust_dynamic_symbol (info, h)
                  || h->weakdef->root.type == bfd_link_hash_defweak);
       h->root.u.def.section = h->weakdef->root.u.def.section;
       h->root.u.def.value = h->weakdef->root.u.def.value;
-      return true;
+      return TRUE;
     }
 
   /* If this is a reference to a symbol defined by a dynamic object which
@@ -1539,22 +1579,52 @@ elf64_hppa_adjust_dynamic_symbol (info, h)
      But PA64 code is canonically PIC, so as a rule we can avoid this sort
      of hackery.  */
 
-  return true;
+  return TRUE;
+}
+
+/* This function is called via elf_link_hash_traverse to mark millicode
+   symbols with a dynindx of -1 and to remove the string table reference
+   from the dynamic symbol table.  If the symbol is not a millicode symbol,
+   elf64_hppa_mark_exported_functions is called.  */
+
+static bfd_boolean
+elf64_hppa_mark_milli_and_exported_functions (h, data)
+     struct elf_link_hash_entry *h;
+     PTR data;
+{
+  struct bfd_link_info *info = (struct bfd_link_info *)data;
+  struct elf_link_hash_entry *elf = h;
+
+  if (elf->root.type == bfd_link_hash_warning)
+    elf = (struct elf_link_hash_entry *) elf->root.u.i.link;
+
+  if (elf->type == STT_PARISC_MILLI)
+    {
+      if (elf->dynindx != -1)
+       {
+         elf->dynindx = -1;
+         _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
+                                 elf->dynstr_index);
+       }
+      return TRUE;
+    }
+
+  return elf64_hppa_mark_exported_functions (h, data);
 }
 
 /* Set the final sizes of the dynamic sections and allocate memory for
    the contents of our special sections.  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_size_dynamic_sections (output_bfd, info)
      bfd *output_bfd;
      struct bfd_link_info *info;
 {
   bfd *dynobj;
   asection *s;
-  boolean plt;
-  boolean relocs;
-  boolean reltext;
+  bfd_boolean plt;
+  bfd_boolean relocs;
+  bfd_boolean reltext;
   struct elf64_hppa_allocate_data data;
   struct elf64_hppa_link_hash_table *hppa_info;
 
@@ -1563,6 +1633,19 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
   dynobj = elf_hash_table (info)->dynobj;
   BFD_ASSERT (dynobj != NULL);
 
+  /* Mark each function this program exports so that we will allocate
+     space in the .opd section for each function's FPTR.  If we are
+     creating dynamic sections, change the dynamic index of millicode
+     symbols to -1 and remove them from the string table for .dynstr.
+
+     We have to traverse the main linker hash table since we have to
+     find functions which may not have been mentioned in any relocs.  */
+  elf_link_hash_traverse (elf_hash_table (info),
+                         (elf_hash_table (info)->dynamic_sections_created
+                          ? elf64_hppa_mark_milli_and_exported_functions
+                          : elf64_hppa_mark_exported_functions),
+                         info);
+
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
@@ -1607,15 +1690,6 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
       hppa_info->stub_sec->_raw_size = data.ofs;
     }
 
-  /* Mark each function this program exports so that we will allocate
-     space in the .opd section for each function's FPTR.
-
-     We have to traverse the main linker hash table since we have to
-     find functions which may not have been mentioned in any relocs.  */
-  elf_link_hash_traverse (elf_hash_table (info),
-                         elf64_hppa_mark_exported_functions,
-                         info);
-
   /* Allocate space for entries in the .opd section.  */
   if (elf64_hppa_hash_table (info)->opd_sec)
     {
@@ -1631,13 +1705,13 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
                                  allocate_dynrel_entries, &data);
 
   /* The sizes of all the sections are set.  Allocate memory for them.  */
-  plt = false;
-  relocs = false;
-  reltext = false;
+  plt = FALSE;
+  relocs = FALSE;
+  reltext = FALSE;
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
       const char *name;
-      boolean strip;
+      bfd_boolean strip;
 
       if ((s->flags & SEC_LINKER_CREATED) == 0)
        continue;
@@ -1650,38 +1724,42 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
 
       if (strcmp (name, ".plt") == 0)
        {
+         /* Strip this section if we don't need it; see the comment below.  */
          if (s->_raw_size == 0)
            {
-             /* Strip this section if we don't need it; see the
-                comment below.  */
-             strip = true;
+             strip = TRUE;
            }
          else
            {
              /* Remember whether there is a PLT.  */
-             plt = true;
+             plt = TRUE;
            }
        }
       else if (strcmp (name, ".dlt") == 0)
        {
+         /* Strip this section if we don't need it; see the comment below.  */
          if (s->_raw_size == 0)
            {
-             /* Strip this section if we don't need it; see the
-                comment below.  */
-             strip = true;
+             strip = TRUE;
            }
        }
       else if (strcmp (name, ".opd") == 0)
        {
+         /* Strip this section if we don't need it; see the comment below.  */
          if (s->_raw_size == 0)
            {
-             /* Strip this section if we don't need it; see the
-                comment below.  */
-             strip = true;
+             strip = TRUE;
            }
        }
-      else if (strncmp (name, ".rela", 4) == 0)
+      else if (strncmp (name, ".rela", 5) == 0)
        {
+         /* If we don't need this section, strip it from the output file.
+            This is mostly to handle .rela.bss and .rela.plt.  We must
+            create both sections in create_dynamic_sections, because they
+            must be created before the linker maps input sections to output
+            sections.  The linker does that before adjust_dynamic_symbol
+            is called, and it is that function which decides whether
+            anything needs to go into these sections.  */
          if (s->_raw_size == 0)
            {
              /* If we don't need this section, strip it from the
@@ -1693,7 +1771,7 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
                 adjust_dynamic_symbol is called, and it is that
                 function which decides whether anything needs to go
                 into these sections.  */
-             strip = true;
+             strip = TRUE;
            }
          else
            {
@@ -1705,7 +1783,7 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
                {
                  const char *outname;
 
-                 relocs = true;
+                 relocs = TRUE;
 
                  /* If this relocation section applies to a read only
                     section, then we probably need a DT_TEXTREL
@@ -1718,7 +1796,7 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
                  if (target != NULL
                      && (target->flags & SEC_READONLY) != 0
                      && (target->flags & SEC_ALLOC) != 0)
-                   reltext = true;
+                   reltext = TRUE;
                }
 
              /* We use the reloc_count field as a counter if we need
@@ -1750,7 +1828,7 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
        {
          s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
          if (s->contents == NULL && s->_raw_size != 0)
-           return false;
+           return FALSE;
        }
     }
 
@@ -1759,9 +1837,12 @@ 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))
-       return false;
+#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
         values later, in elf64_hppa_finish_dynamic_sections, but we
@@ -1770,38 +1851,43 @@ 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))
-           return false;
+         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;
        }
 
+      /* Force DT_FLAGS to always be set.
+        Required by HPUX 11.00 patch PHSS_26559.  */
+      if (!add_dynamic_entry (DT_FLAGS, (info)->flags))
+       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))
-           return false;
+         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)))
-           return false;
+         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))
-           return false;
+         if (!add_dynamic_entry (DT_TEXTREL, 0))
+           return FALSE;
          info->flags |= DF_TEXTREL;
        }
     }
+#undef add_dynamic_entry
 
-  return true;
+  return TRUE;
 }
 
 /* Called after we have output the symbol into the dynamic symbol
@@ -1813,7 +1899,7 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
    the symbols have their expected value in the normal symbol
    table.  Ick.  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_link_output_symbol_hook (abfd, info, name, sym, input_sec)
      bfd *abfd ATTRIBUTE_UNUSED;
      struct bfd_link_info *info;
@@ -1827,12 +1913,12 @@ elf64_hppa_link_output_symbol_hook (abfd, info, name, sym, input_sec)
   /* We may be called with the file symbol or section symbols.
      They never need munging, so it is safe to ignore them.  */
   if (!name)
-    return true;
+    return TRUE;
 
   /* Get the PA dyn_symbol (if any) associated with NAME.  */
   hppa_info = elf64_hppa_hash_table (info);
   dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
-                                     name, false, false);
+                                     name, FALSE, FALSE);
 
   /* Function symbols for which we created .opd entries *may* have been
      munged by finish_dynamic_symbol and have to be un-munged here.
@@ -1845,16 +1931,16 @@ elf64_hppa_link_output_symbol_hook (abfd, info, name, sym, input_sec)
     {
       /* 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;
+  return TRUE;
 }
 
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
      bfd *output_bfd;
      struct bfd_link_info *info;
@@ -1867,7 +1953,7 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
 
   hppa_info = elf64_hppa_hash_table (info);
   dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
-                                     h->root.root.string, false, false);
+                                     h->root.root.string, FALSE, FALSE);
 
   stub = hppa_info->stub_sec;
   splt = hppa_info->plt_sec;
@@ -1876,9 +1962,6 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
   spltrel = hppa_info->plt_rel_sec;
   sdltrel = hppa_info->dlt_rel_sec;
 
-  BFD_ASSERT (stub != NULL && splt != NULL
-             && sopd != NULL && sdlt != NULL)
-
   /* Incredible.  It is actually necessary to NOT use the symbol's real
      value when building the dynamic symbol table for a shared library.
      At least for symbols that refer to functions.
@@ -1888,6 +1971,8 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
      the original values (in elf64_hppa_link_output_symbol_hook).  */
   if (dyn_h && dyn_h->want_opd)
     {
+      BFD_ASSERT (sopd != NULL)
+
       /* Save away the original value and section index so that we
         can restore them later.  */
       dyn_h->st_value = sym->st_value;
@@ -1908,6 +1993,9 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
     {
       bfd_vma value;
       Elf_Internal_Rela rel;
+      bfd_byte *loc;
+
+      BFD_ASSERT (splt != NULL && spltrel != NULL)
 
       /* We do not actually care about the value in the PLT entry
         if we are creating a shared library and the symbol is
@@ -1918,13 +2006,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,11 +2032,9 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
       rel.r_info = ELF64_R_INFO (h->dynindx, R_PARISC_IPLT);
       rel.r_addend = 0;
 
-      bfd_elf64_swap_reloca_out (splt->output_section->owner, &rel,
-                                (((Elf64_External_Rela *)
-                                  spltrel->contents)
-                                 + spltrel->reloc_count));
-      spltrel->reloc_count++;
+      loc = spltrel->contents;
+      loc += spltrel->reloc_count++ * sizeof (Elf64_External_Rela);
+      bfd_elf64_swap_reloca_out (splt->output_section->owner, &rel, loc);
     }
 
   /* Initialize an external call stub entry if requested.  */
@@ -1957,6 +2043,9 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
     {
       bfd_vma value;
       int insn;
+      unsigned int max_offset;
+
+      BFD_ASSERT (stub != NULL)
 
       /* Install the generic stub template.
 
@@ -1967,7 +2056,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
@@ -1976,46 +2065,64 @@ 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);
     }
 
-  /* Millicode symbols should not be put in the dynamic
-     symbol table under any circumstances.  */
-  if (ELF_ST_TYPE (sym->st_info) == STT_PARISC_MILLI)
-    h->dynindx = -1;
-
-  return true;
+  return TRUE;
 }
 
 /* The .opd section contains FPTRs for each function this file
    exports.  Initialize the FPTR entries.  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_finalize_opd (dyn_h, data)
      struct elf64_hppa_dyn_hash_entry *dyn_h;
      PTR data;
 {
   struct bfd_link_info *info = (struct bfd_link_info *)data;
   struct elf64_hppa_link_hash_table *hppa_info;
-  struct elf_link_hash_entry *h = dyn_h->h;
+  struct elf_link_hash_entry *h = dyn_h ? dyn_h->h : NULL;
   asection *sopd;
   asection *sopdrel;
 
@@ -2023,11 +2130,11 @@ elf64_hppa_finalize_opd (dyn_h, data)
   sopd = hppa_info->opd_sec;
   sopdrel = hppa_info->opd_rel_sec;
 
-  if (h && dyn_h && dyn_h->want_opd)
+  if (h && dyn_h->want_opd)
     {
       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.  */
@@ -2050,7 +2157,8 @@ elf64_hppa_finalize_opd (dyn_h, data)
      had their address taken).  */
   if (info->shared && dyn_h && dyn_h->want_opd)
     {
-      Elf64_Internal_Rela rel;
+      Elf_Internal_Rela rel;
+      bfd_byte *loc;
       int dynindx;
 
       /* We may need to do a relocation against a local symbol, in
@@ -2080,7 +2188,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
@@ -2105,7 +2213,7 @@ elf64_hppa_finalize_opd (dyn_h, data)
          strcpy (new_name + 1, h->root.root.string);
 
          nh = elf_link_hash_lookup (elf_hash_table (info),
-                                    new_name, false, false, false);
+                                    new_name, FALSE, FALSE, FALSE);
 
          /* All we really want from the new symbol is its dynamic
             symbol index.  */
@@ -2115,20 +2223,18 @@ elf64_hppa_finalize_opd (dyn_h, data)
       rel.r_addend = 0;
       rel.r_info = ELF64_R_INFO (dynindx, R_PARISC_EPLT);
 
-      bfd_elf64_swap_reloca_out (sopd->output_section->owner, &rel,
-                                (((Elf64_External_Rela *)
-                                  sopdrel->contents)
-                                 + sopdrel->reloc_count));
-      sopdrel->reloc_count++;
+      loc = sopdrel->contents;
+      loc += sopdrel->reloc_count++ * sizeof (Elf64_External_Rela);
+      bfd_elf64_swap_reloca_out (sopd->output_section->owner, &rel, loc);
     }
-  return true;
+  return TRUE;
 }
 
 /* The .dlt section contains addresses for items referenced through the
    dlt.  Note that we can have a DLTIND relocation for a local symbol, thus
    we can not depend on finish_dynamic_symbol to initialize the .dlt.  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_finalize_dlt (dyn_h, data)
      struct elf64_hppa_dyn_hash_entry *dyn_h;
      PTR data;
@@ -2136,7 +2242,7 @@ elf64_hppa_finalize_dlt (dyn_h, data)
   struct bfd_link_info *info = (struct bfd_link_info *)data;
   struct elf64_hppa_link_hash_table *hppa_info;
   asection *sdlt, *sdltrel;
-  struct elf_link_hash_entry *h = dyn_h->h;
+  struct elf_link_hash_entry *h = dyn_h ? dyn_h->h : NULL;
 
   hppa_info = elf64_hppa_hash_table (info);
 
@@ -2147,12 +2253,12 @@ elf64_hppa_finalize_dlt (dyn_h, data)
      address, so there is no need to create a relocation.  Just install
      the proper value into the DLT, note this shortcut can not be
      skipped when building a shared library.  */
-  if (! info->shared && h && dyn_h && dyn_h->want_dlt)
+  if (! info->shared && h && dyn_h->want_dlt)
     {
       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
@@ -2163,16 +2269,17 @@ elf64_hppa_finalize_dlt (dyn_h, data)
                   + hppa_info->opd_sec->output_offset
                   + hppa_info->opd_sec->output_section->vma);
        }
-      else
+      else if (h->root.u.def.section)
        {
-         value = (h->root.u.def.value
-                  + h->root.u.def.section->output_offset);
-
+         value = h->root.u.def.value + h->root.u.def.section->output_offset;
          if (h->root.u.def.section->output_section)
            value += h->root.u.def.section->output_section->vma;
          else
            value += h->root.u.def.section->vma;
        }
+      else
+       /* We have an undefined function reference.  */
+       value = 0;
 
       /* We do not need to include the output offset of the DLT section
         here because we are modifying the in-memory contents.  */
@@ -2184,7 +2291,8 @@ elf64_hppa_finalize_dlt (dyn_h, data)
   if (dyn_h->want_dlt
       && (elf64_hppa_dynamic_symbol_p (dyn_h->h, info) || info->shared))
     {
-      Elf64_Internal_Rela rel;
+      Elf_Internal_Rela rel;
+      bfd_byte *loc;
       int dynindx;
 
       /* We may need to do a relocation against a local symbol, in
@@ -2197,7 +2305,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.  */
@@ -2209,19 +2316,17 @@ elf64_hppa_finalize_dlt (dyn_h, data)
          rel.r_info = ELF64_R_INFO (dynindx, R_PARISC_DIR64);
       rel.r_addend = 0;
 
-      bfd_elf64_swap_reloca_out (sdlt->output_section->owner, &rel,
-                                (((Elf64_External_Rela *)
-                                  sdltrel->contents)
-                                 + sdltrel->reloc_count));
-      sdltrel->reloc_count++;
+      loc = sdltrel->contents;
+      loc += sdltrel->reloc_count++ * sizeof (Elf64_External_Rela);
+      bfd_elf64_swap_reloca_out (sdlt->output_section->owner, &rel, loc);
     }
-  return true;
+  return TRUE;
 }
 
 /* Finalize the dynamic relocations.  Specifically the FPTR relocations
    for dynamic functions used to initialize static data.  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_finalize_dynreloc (dyn_h, data)
      struct elf64_hppa_dyn_hash_entry *dyn_h;
      PTR data;
@@ -2234,7 +2339,7 @@ elf64_hppa_finalize_dynreloc (dyn_h, data)
   dynamic_symbol = elf64_hppa_dynamic_symbol_p (dyn_h->h, info);
 
   if (!dynamic_symbol && !info->shared)
-    return true;
+    return TRUE;
 
   if (dyn_h->reloc_entries)
     {
@@ -2256,20 +2361,15 @@ elf64_hppa_finalize_dynreloc (dyn_h, data)
 
       for (rent = dyn_h->reloc_entries; rent; rent = rent->next)
        {
-         Elf64_Internal_Rela rel;
+         Elf_Internal_Rela rel;
+         bfd_byte *loc;
 
-         switch (rent->type)
-           {
-             case R_PARISC_FPTR64:
-             /* Allocate one iff we are not building a shared library and
-                !want_opd, which by this point will be true only if we're
-                actually allocating one statically in the main executable.  */
-             if (!info->shared && dyn_h->want_opd)
-               continue;
-             break;
-           }
+         /* Allocate one iff we are building a shared library, the relocation
+            isn't a R_PARISC_FPTR64, or we don't want an opd entry.  */
+         if (!info->shared && rent->type == R_PARISC_FPTR64 && dyn_h->want_opd)
+           continue;
 
-         /* 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
@@ -2292,11 +2392,11 @@ 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.  */
-         if (info->shared && rent->type == R_PARISC_FPTR64)
+         if (info->shared && rent->type == R_PARISC_FPTR64 && dyn_h->want_opd)
            {
              bfd_vma value, value2;
 
@@ -2313,7 +2413,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;
 
@@ -2329,21 +2429,41 @@ elf64_hppa_finalize_dynreloc (dyn_h, data)
 
          rel.r_info = ELF64_R_INFO (dynindx, rent->type);
 
+         loc = hppa_info->other_rel_sec->contents;
+         loc += (hppa_info->other_rel_sec->reloc_count++
+                 * sizeof (Elf64_External_Rela));
          bfd_elf64_swap_reloca_out (hppa_info->other_rel_sec->output_section->owner,
-                                    &rel,
-                                    (((Elf64_External_Rela *)
-                                     hppa_info->other_rel_sec->contents)
-                                     + hppa_info->other_rel_sec->reloc_count));
-         hppa_info->other_rel_sec->reloc_count++;
+                                    &rel, loc);
        }
     }
 
-  return true;
+  return TRUE;
+}
+
+/* Used to decide how to sort relocs in an optimal manner for the
+   dynamic linker, before writing them out.  */
+
+static enum elf_reloc_type_class
+elf64_hppa_reloc_type_class (rela)
+     const Elf_Internal_Rela *rela;
+{
+  if (ELF64_R_SYM (rela->r_info) == 0)
+    return reloc_class_relative;
+
+  switch ((int) ELF64_R_TYPE (rela->r_info))
+    {
+    case R_PARISC_IPLT:
+      return reloc_class_plt;
+    case R_PARISC_COPY:
+      return reloc_class_copy;
+    default:
+      return reloc_class_normal;
+    }
 }
 
 /* Finish up the dynamic sections.  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_finish_dynamic_sections (output_bfd, info)
      bfd *output_bfd;
      struct bfd_link_info *info;
@@ -2370,7 +2490,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)
@@ -2425,8 +2544,10 @@ elf64_hppa_finish_dynamic_sections (output_bfd, info)
 
            case DT_RELA:
              s = hppa_info->other_rel_sec;
-             if (! s)
+             if (! s || ! s->_raw_size)
                s = hppa_info->dlt_rel_sec;
+             if (! s || ! s->_raw_size)
+               s = hppa_info->opd_rel_sec;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
@@ -2450,14 +2571,13 @@ elf64_hppa_finish_dynamic_sections (output_bfd, info)
        }
     }
 
-  return true;
+  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.
@@ -2484,16 +2604,16 @@ 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
    existence of a .interp section.  */
 
-static boolean
+static bfd_boolean
 elf64_hppa_modify_segment_map (abfd)
      bfd *abfd;
 {
@@ -2508,9 +2628,10 @@ 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;
+           return FALSE;
 
          m->p_type = PT_PHDR;
          m->p_flags = PF_R | PF_X;
@@ -2541,7 +2662,20 @@ elf64_hppa_modify_segment_map (abfd)
          }
       }
 
-  return true;
+  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.  */
@@ -2563,15 +2697,16 @@ const struct elf_size_info hppa64_elf_size_info =
   bfd_elf64_write_out_phdrs,
   bfd_elf64_write_shdrs_and_ehdr,
   bfd_elf64_write_relocs,
+  bfd_elf64_swap_symbol_in,
   bfd_elf64_swap_symbol_out,
   bfd_elf64_slurp_reloc_table,
   bfd_elf64_slurp_symbol_table,
   bfd_elf64_swap_dyn_in,
   bfd_elf64_swap_dyn_out,
-  NULL,
-  NULL,
-  NULL,
-  NULL
+  bfd_elf64_swap_reloc_in,
+  bfd_elf64_swap_reloc_out,
+  bfd_elf64_swap_reloca_in,
+  bfd_elf64_swap_reloca_out
 };
 
 #define TARGET_BIG_SYM                 bfd_elf64_hppa_vec
@@ -2590,10 +2725,10 @@ 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
+#define elf_backend_relocate_section   elf_hppa_relocate_section
 
 #define bfd_elf64_bfd_final_link       elf_hppa_final_link
 
@@ -2631,12 +2766,22 @@ 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_type_change_ok     TRUE
+#define elf_backend_get_symbol_type    elf64_hppa_elf_get_symbol_type
+#define elf_backend_reloc_type_class   elf64_hppa_reloc_type_class
+#define elf_backend_rela_normal                1
+
+#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.055095 seconds and 4 git commands to generate.