elf_swap_symbol_in args should be "const PTR", not "const PTR *".
[deliverable/binutils-gdb.git] / bfd / elf64-hppa.c
index 465a2db40af47b4223c13d3bfc60237299fde838..d110d76d9ce214b7bfe2c1ba5d4fa44e3139a060 100644 (file)
@@ -1,5 +1,5 @@
 /* Support for HPPA 64-bit ELF
-   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -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
@@ -184,7 +184,7 @@ static boolean elf64_hppa_object_p
   PARAMS ((bfd *));
 
 static boolean elf64_hppa_section_from_shdr
-  PARAMS ((bfd *, Elf64_Internal_Shdr *, char *));
+  PARAMS ((bfd *, Elf64_Internal_Shdr *, const char *));
 
 static void elf64_hppa_post_process_headers
   PARAMS ((bfd *, struct bfd_link_info *));
@@ -198,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 *));
 
@@ -258,6 +266,9 @@ 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;
@@ -306,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,
@@ -355,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
@@ -365,7 +403,7 @@ static boolean
 elf64_hppa_section_from_shdr (abfd, hdr, name)
      bfd *abfd;
      Elf64_Internal_Shdr *hdr;
-     char *name;
+     const char *name;
 {
   asection *newsect;
 
@@ -519,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;
 
@@ -547,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;
@@ -573,9 +612,11 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
   if (info->shared && hppa_info->section_syms_bfd != abfd)
     {
       unsigned long i;
-      int highest_shndx;
+      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.
@@ -586,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);
@@ -603,36 +644,60 @@ 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, (const PTR) esym, (const PTR) 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.  */
@@ -709,7 +774,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;
@@ -936,7 +1002,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)))
@@ -958,6 +1024,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)
@@ -1009,8 +1078,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;
            }
        }
@@ -1763,8 +1832,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
@@ -1774,36 +1846,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;
 }
@@ -1988,13 +2060,13 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
          /* Wide mode allows 16 bit offsets.  */
          max_offset = 32768;
          insn &= ~ 0xfff1;
-         insn |= re_assemble_16 (value);
+         insn |= re_assemble_16 ((int) value);
        }
       else
        {
          max_offset = 8192;
          insn &= ~ 0x3ff1;
-         insn |= re_assemble_14 (value);
+         insn |= re_assemble_14 ((int) value);
        }
 
       if ((value & 7) || value + max_offset >= 2*max_offset - 8)
@@ -2005,7 +2077,7 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
          return false;
        }
 
-      bfd_put_32 (stub->owner, insn,
+      bfd_put_32 (stub->owner, (bfd_vma) insn,
                  stub->contents + dyn_h->stub_offset);
 
       /* Fix up the second ldd instruction.  */
@@ -2014,14 +2086,14 @@ elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
       if (output_bfd->arch_info->mach >= 25)
        {
          insn &= ~ 0xfff1;
-         insn |= re_assemble_16 (value);
+         insn |= re_assemble_16 ((int) value);
        }
       else
        {
          insn &= ~ 0x3ff1;
-         insn |= re_assemble_14 (value);
+         insn |= re_assemble_14 ((int) value);
        }
-      bfd_put_32 (stub->owner, insn,
+      bfd_put_32 (stub->owner, (bfd_vma) insn,
                  stub->contents + dyn_h->stub_offset + 8);
     }
 
@@ -2533,7 +2605,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;
 
@@ -2569,6 +2642,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 =
@@ -2588,6 +2674,7 @@ 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,
@@ -2615,7 +2702,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
@@ -2662,6 +2749,7 @@ const struct elf_size_info hppa64_elf_size_info =
 #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"
 
This page took 0.029194 seconds and 4 git commands to generate.