Switch sources over to use the GPL version 3
[deliverable/binutils-gdb.git] / bfd / elf64-hppa.c
index 08421b5dfae729376dba18333f9e41abc4b1108d..929de1e6127276e055d8cde7ef685fc31ce5afca 100644 (file)
@@ -1,12 +1,12 @@
 /* Support for HPPA 64-bit ELF
-   Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 #include "alloca-conf.h"
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/hppa.h"
@@ -157,9 +158,6 @@ 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 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
   PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
           const char *string));
@@ -207,12 +205,6 @@ static bfd_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 bfd_boolean elf64_hppa_modify_segment_map
-  PARAMS ((bfd *, struct bfd_link_info *));
-
 static enum elf_reloc_type_class elf64_hppa_reloc_type_class
   PARAMS ((const Elf_Internal_Rela *));
 
@@ -276,13 +268,13 @@ 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;
+elf64_hppa_dyn_hash_table_init (struct elf64_hppa_dyn_hash_table *ht,
+                               bfd *abfd ATTRIBUTE_UNUSED,
+                               new_hash_entry_func new,
+                               unsigned int entsize)
 {
   memset (ht, 0, sizeof (*ht));
-  return bfd_hash_table_init (&ht->root, new);
+  return bfd_hash_table_init (&ht->root, new, entsize);
 }
 
 static struct bfd_hash_entry*
@@ -328,14 +320,16 @@ elf64_hppa_hash_table_create (abfd)
   if (!ret)
     return 0;
   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
-                                     _bfd_elf_link_hash_newfunc))
+                                     _bfd_elf_link_hash_newfunc,
+                                     sizeof (struct elf_link_hash_entry)))
     {
       bfd_release (abfd, ret);
       return 0;
     }
 
   if (!elf64_hppa_dyn_hash_table_init (&ret->dyn_hash_table, abfd,
-                                      elf64_hppa_new_dyn_hash_entry))
+                                      elf64_hppa_new_dyn_hash_entry,
+                                      sizeof (struct elf64_hppa_dyn_hash_entry)))
     return 0;
   return &ret->root.root;
 }
@@ -381,13 +375,16 @@ elf64_hppa_object_p (abfd)
     {
       /* GCC on hppa-linux produces binaries with OSABI=Linux,
         but the kernel produces corefiles with OSABI=SysV.  */
-      if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_LINUX &&
-         i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_NONE) /* aka SYSV */
+      if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_LINUX
+         && i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_NONE) /* aka SYSV */
        return FALSE;
     }
   else
     {
-      if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_HPUX)
+      /* HPUX produces binaries with OSABI=HPUX,
+        but the kernel produces corefiles with OSABI=SysV.  */
+      if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_HPUX
+         && i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_NONE) /* aka SYSV */
        return FALSE;
     }
 
@@ -399,7 +396,10 @@ elf64_hppa_object_p (abfd)
     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);
+      if (i_ehdrp->e_ident[EI_CLASS] == ELFCLASS64)
+        return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 25);
+      else
+        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);
     }
@@ -518,12 +518,12 @@ get_reloc_section (abfd, hppa_info, sec)
   if (srel_name == NULL)
     return FALSE;
 
-  BFD_ASSERT ((strncmp (srel_name, ".rela", 5) == 0
+  BFD_ASSERT ((CONST_STRNEQ (srel_name, ".rela")
               && strcmp (bfd_get_section_name (abfd, sec),
-                         srel_name+5) == 0)
-             || (strncmp (srel_name, ".rel", 4) == 0
+                         srel_name + 5) == 0)
+             || (CONST_STRNEQ (srel_name, ".rel")
                  && strcmp (bfd_get_section_name (abfd, sec),
-                            srel_name+4) == 0));
+                            srel_name + 4) == 0));
 
   dynobj = hppa_info->root.dynobj;
   if (!dynobj)
@@ -1124,6 +1124,7 @@ 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
+               || h->root.type == bfd_link_hash_undefweak
                || h->root.u.def.section->output_section == NULL))
        dyn_h->want_opd = 0;
 
@@ -1198,16 +1199,9 @@ elf64_hppa_post_process_headers (abfd, link_info)
   Elf_Internal_Ehdr * i_ehdrp;
 
   i_ehdrp = elf_elfheader (abfd);
-
-  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;
-    }
+  
+  i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
+  i_ehdrp->e_ident[EI_ABIVERSION] = 1;
 }
 
 /* Create function descriptor section (.opd).  This section is called .opd
@@ -1713,13 +1707,13 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
          plt = s->size != 0;
        }
       else if (strcmp (name, ".opd") == 0
-              || strncmp (name, ".dlt", 4) == 0
+              || CONST_STRNEQ (name, ".dlt")
               || strcmp (name, ".stub") == 0
               || strcmp (name, ".got") == 0)
        {
          /* Strip this section if we don't need it; see the comment below.  */
        }
-      else if (strncmp (name, ".rela", 5) == 0)
+      else if (CONST_STRNEQ (name, ".rela"))
        {
          if (s->size != 0)
            {
@@ -2536,6 +2530,68 @@ elf64_hppa_finish_dynamic_sections (output_bfd, info)
   return TRUE;
 }
 
+/* Support for core dump NOTE sections.  */
+
+static bfd_boolean
+elf64_hppa_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
+{
+  int offset;
+  size_t size;
+
+  switch (note->descsz)
+    {
+      default:
+       return FALSE;
+
+      case 760:                /* Linux/hppa */
+       /* pr_cursig */
+       elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+
+       /* pr_pid */
+       elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 32);
+
+       /* pr_reg */
+       offset = 112;
+       size = 640;
+
+       break;
+    }
+
+  /* Make a ".reg/999" section.  */
+  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
+                                         size, note->descpos + offset);
+}
+
+static bfd_boolean
+elf64_hppa_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
+{
+  char * command;
+  int n;
+
+  switch (note->descsz)
+    {
+    default:
+      return FALSE;
+
+    case 136:          /* Linux/hppa elf_prpsinfo.  */
+      elf_tdata (abfd)->core_program
+       = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
+      elf_tdata (abfd)->core_command
+       = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
+    }
+
+  /* Note that for some reason, a spurious space is tacked
+     onto the end of the args in some (at least one anyway)
+     implementations, so strip it off if it exists.  */
+  command = elf_tdata (abfd)->core_command;
+  n = strlen (command);
+
+  if (0 < n && command[n - 1] == ' ')
+    command[n - 1] = '\0';
+
+  return TRUE;
+}
+
 /* Return the number of additional phdrs we will need.
 
    The generic ELF code only creates PT_PHDRs for executables.  The HP
@@ -2549,8 +2605,8 @@ elf64_hppa_finish_dynamic_sections (output_bfd, info)
    existence of a .interp section.  */
 
 static int
-elf64_hppa_additional_program_headers (abfd)
-     bfd *abfd;
+elf64_hppa_additional_program_headers (bfd *abfd,
+                                      struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   asection *s;
 
@@ -2576,9 +2632,8 @@ elf64_hppa_additional_program_headers (abfd)
    existence of a .interp section.  */
 
 static bfd_boolean
-elf64_hppa_modify_segment_map (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+elf64_hppa_modify_segment_map (bfd *abfd,
+                              struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   struct elf_segment_map *m;
   asection *s;
@@ -2641,11 +2696,64 @@ elf64_hppa_elf_get_symbol_type (elf_sym, type)
     return type;
 }
 
+/* Support HP specific sections for core files.  */
+static bfd_boolean
+elf64_hppa_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int index,
+                             const char *typename)
+{
+  if (hdr->p_type == PT_HP_CORE_KERNEL)
+    {
+      asection *sect;
+
+      if (!_bfd_elf_make_section_from_phdr (abfd, hdr, index, typename))
+       return FALSE;
+
+      sect = bfd_make_section_anyway (abfd, ".kernel");
+      if (sect == NULL)
+       return FALSE;
+      sect->size = hdr->p_filesz;
+      sect->filepos = hdr->p_offset;
+      sect->flags = SEC_HAS_CONTENTS | SEC_READONLY;
+      return TRUE;
+    }
+
+  if (hdr->p_type == PT_HP_CORE_PROC)
+    {
+      int sig;
+
+      if (bfd_seek (abfd, hdr->p_offset, SEEK_SET) != 0)
+       return FALSE;
+      if (bfd_bread (&sig, 4, abfd) != 4)
+       return FALSE;
+
+      elf_tdata (abfd)->core_signal = sig;
+
+      if (!_bfd_elf_make_section_from_phdr (abfd, hdr, index, typename))
+       return FALSE;
+
+      /* GDB uses the ".reg" section to read register contents.  */
+      return _bfd_elfcore_make_pseudosection (abfd, ".reg", hdr->p_filesz,
+                                             hdr->p_offset);
+    }
+
+  if (hdr->p_type == PT_HP_CORE_LOADABLE
+      || hdr->p_type == PT_HP_CORE_STACK
+      || hdr->p_type == PT_HP_CORE_MMF)
+    hdr->p_type = PT_LOAD;
+
+  return _bfd_elf_make_section_from_phdr (abfd, hdr, index, typename);
+}
+
 static const struct bfd_elf_special_section elf64_hppa_special_sections[] =
 {
-  { ".fini",    5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
-  { ".init",    5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
-  { NULL,       0, 0, 0,            0 }
+  { STRING_COMMA_LEN (".fini"),  0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".init"),  0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".plt"),   0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
+  { STRING_COMMA_LEN (".dlt"),   0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
+  { STRING_COMMA_LEN (".sdata"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
+  { STRING_COMMA_LEN (".sbss"),  0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
+  { STRING_COMMA_LEN (".tbss"),  0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_HP_TLS },
+  { NULL,                    0,  0, 0,            0 }
 };
 
 /* The hash bucket size is the standard one, namely 4.  */
@@ -2686,7 +2794,10 @@ const struct elf_size_info hppa64_elf_size_info =
 /* This is not strictly correct.  The maximum page size for PA2.0 is
    64M.  But everything still uses 4k.  */
 #define ELF_MAXPAGESIZE                        0x1000
+#define ELF_OSABI                      ELFOSABI_HPUX
+
 #define bfd_elf64_bfd_reloc_type_lookup elf_hppa_reloc_type_lookup
+#define bfd_elf64_bfd_reloc_name_lookup elf_hppa_reloc_name_lookup
 #define bfd_elf64_bfd_is_local_label_name       elf_hppa_is_local_label_name
 #define elf_info_to_howto              elf_hppa_info_to_howto
 #define elf_info_to_howto_rel          elf_hppa_info_to_howto_rel
@@ -2706,6 +2817,8 @@ const struct elf_size_info hppa64_elf_size_info =
                                        elf64_hppa_create_dynamic_sections
 #define elf_backend_post_process_headers       elf64_hppa_post_process_headers
 
+#define elf_backend_omit_section_dynsym \
+  ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
 #define elf_backend_adjust_dynamic_symbol \
                                        elf64_hppa_adjust_dynamic_symbol
 
@@ -2716,7 +2829,9 @@ const struct elf_size_info hppa64_elf_size_info =
                                        elf64_hppa_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections \
                                        elf64_hppa_finish_dynamic_sections
-
+#define elf_backend_grok_prstatus      elf64_hppa_grok_prstatus
+#define elf_backend_grok_psinfo                elf64_hppa_grok_psinfo
 /* Stuff for the BFD linker: */
 #define bfd_elf64_bfd_link_hash_table_create \
        elf64_hppa_hash_table_create
@@ -2746,6 +2861,9 @@ const struct elf_size_info hppa64_elf_size_info =
 #define elf_backend_rela_normal                1
 #define elf_backend_special_sections   elf64_hppa_special_sections
 #define elf_backend_action_discarded   elf_hppa_action_discarded
+#define elf_backend_section_from_phdr   elf64_hppa_section_from_phdr
+
+#define elf64_bed                      elf64_hppa_hpux_bed
 
 #include "elf64-target.h"
 
@@ -2753,8 +2871,11 @@ const struct elf_size_info hppa64_elf_size_info =
 #define TARGET_BIG_SYM                 bfd_elf64_hppa_linux_vec
 #undef TARGET_BIG_NAME
 #define TARGET_BIG_NAME                        "elf64-hppa-linux"
+#undef ELF_OSABI
+#define ELF_OSABI                      ELFOSABI_LINUX
+#undef elf_backend_post_process_headers
+#define elf_backend_post_process_headers _bfd_elf_set_osabi
+#undef elf64_bed
+#define elf64_bed                      elf64_hppa_linux_bed
 
-#undef elf_backend_special_sections
-
-#define INCLUDED_TARGET_FILE 1
 #include "elf64-target.h"
This page took 0.031489 seconds and 4 git commands to generate.