2009-02-23 Christophe Lyon <christophe.lyon@st.com>
[deliverable/binutils-gdb.git] / bfd / som.c
index 5585bda321ce840dd545158fe216198eaaa1048a..360819dc686ad9feb325c891bd2529fa55196d31 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -1,6 +1,6 @@
 /* bfd back-end for HP PA-RISC SOM objects.
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    Contributed by the Center for Software Science at the
@@ -10,7 +10,7 @@
 
    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., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, 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"
 
 #if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD) || defined (HOST_HPPAOSF) || defined(HOST_HPPAMPEIX)
 
 #include <machine/reg.h>
 #include <sys/file.h>
 
+/* This is the code recommended in the autoconf documentation, almost
+   verbatim.  */
+
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+/* Indented so that pre-ansi C compilers will ignore it, rather than
+   choke on it.  Some versions of AIX require this to be the first
+   thing in the file.  */
+ #pragma alloca
+#  else
+#   ifndef alloca /* predefined by HP cc +Olibcalls */
+#    if !defined (__STDC__) && !defined (__hpux)
+extern char *alloca ();
+#    else
+extern void *alloca ();
+#    endif /* __STDC__, __hpux */
+#   endif /* alloca */
+#  endif /* _AIX */
+# endif /* HAVE_ALLOCA_H */
+#else
+extern void *alloca (size_t);
+#endif /* __GNUC__ */
+
+static bfd_reloc_status_type hppa_som_reloc
+  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+static bfd_boolean som_mkobject (bfd *);
+static bfd_boolean som_is_space (asection *);
+static bfd_boolean som_is_subspace (asection *);
+static int compare_subspaces (const void *, const void *);
+static unsigned long som_compute_checksum (bfd *);
+static bfd_boolean som_build_and_write_symbol_table (bfd *);
+static unsigned int som_slurp_symbol_table (bfd *);
+
 /* Magic not defined in standard HP-UX header files until 8.0.  */
 
 #ifndef CPU_PA_RISC1_0
@@ -318,7 +353,7 @@ static const struct fixup_format som_fixup_formats[256] =
   /* R_DATA_ONE_SYMBOL.  */
   {  0, "L4=Sb=" },            /* 0x25 */
   {  1, "L4=Sd=" },            /* 0x26 */
-  /* R_DATA_PLEBEL.  */
+  /* R_DATA_PLABEL.  */
   {  0, "L4=Sb=" },            /* 0x27 */
   {  1, "L4=Sd=" },            /* 0x28 */
   /* R_SPACE_REF.  */
@@ -402,8 +437,9 @@ static const struct fixup_format som_fixup_formats[256] =
   { 31, "L4=SD=" },            /* 0x6f */
   { 32, "L4=Sb=" },            /* 0x70 */
   { 33, "L4=Sd=" },            /* 0x71 */
+  /* R_DATA_GPREL.  */
+  {  0, "L4=Sd=" },            /* 0x72 */
   /* R_RESERVED.  */
-  {  0, "" },                  /* 0x72 */
   {  0, "" },                  /* 0x73 */
   {  0, "" },                  /* 0x74 */
   {  0, "" },                  /* 0x75 */
@@ -790,7 +826,7 @@ static reloc_howto_type som_hppa_howto_table[] =
   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
-  SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
+  SOM_HOWTO (R_DATA_GPREL, "R_DATA_GPREL"),
   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
@@ -1044,7 +1080,7 @@ som_reloc_queue_find (unsigned char *p,
 
 static unsigned char *
 try_prev_fixup (bfd *abfd ATTRIBUTE_UNUSED,
-               int *subspace_reloc_sizep,
+               unsigned int *subspace_reloc_sizep,
                unsigned char *p,
                unsigned int size,
                struct reloc_queue *queue)
@@ -1313,7 +1349,7 @@ static bfd_reloc_status_type
 hppa_som_reloc (bfd *abfd ATTRIBUTE_UNUSED,
                arelent *reloc_entry,
                asymbol *symbol_in ATTRIBUTE_UNUSED,
-               void * data ATTRIBUTE_UNUSED,
+               void *data ATTRIBUTE_UNUSED,
                asection *input_section,
                bfd *output_bfd,
                char **error_message ATTRIBUTE_UNUSED)
@@ -1536,6 +1572,8 @@ hppa_som_gen_reloc_type (bfd *abfd,
          || field == e_lpsel
          || field == e_rpsel)
        *final_type = R_DATA_PLABEL;
+      else if (field == e_fsel && format == 32)
+       *final_type = R_DATA_GPREL;
       break;
 
     case R_HPPA_COMPLEX:
@@ -1616,6 +1654,22 @@ som_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return NULL;
 }
 
+static reloc_howto_type *
+som_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                          const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < sizeof (som_hppa_howto_table) / sizeof (som_hppa_howto_table[0]);
+       i++)
+    if (som_hppa_howto_table[i].name != NULL
+       && strcasecmp (som_hppa_howto_table[i].name, r_name) == 0)
+      return &som_hppa_howto_table[i];
+
+  return NULL;
+}
+
 /* Perform some initialization for an object.  Save results of this
    initialization in the BFD.  */
 
@@ -2407,7 +2461,7 @@ som_count_subspaces (bfd *abfd)
    count.  Doing so compacts the relocation stream.  */
 
 static int
-compare_syms (const void * arg1, const void * arg2)
+compare_syms (const void *arg1, const void *arg2)
 {
   asymbol **sym1 = (asymbol **) arg1;
   asymbol **sym2 = (asymbol **) arg2;
@@ -2437,7 +2491,7 @@ compare_syms (const void * arg1, const void * arg2)
    and subspace.  */
 
 static int
-compare_subspaces (const void * arg1, const void * arg2)
+compare_subspaces (const void *arg1, const void *arg2)
 {
   asection **subspace1 = (asection **) arg1;
   asection **subspace2 = (asection **) arg2;
@@ -2748,6 +2802,24 @@ som_write_fixups (bfd *abfd,
                    abort ();
                  break;
 
+               case R_DATA_GPREL:
+                 /* Account for any addend.  */
+                 if (bfd_reloc->addend)
+                   p = som_reloc_addend (abfd, bfd_reloc->addend, p,
+                                         &subspace_reloc_size, reloc_queue);
+
+                 if (sym_num < 0x10000000)
+                   {
+                     bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+                     bfd_put_8 (abfd, sym_num >> 16, p + 1);
+                     bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
+                     p = try_prev_fixup (abfd, &subspace_reloc_size,
+                                         p, 4, reloc_queue);
+                   }
+                 else
+                   abort ();
+                 break;
+
                case R_DATA_ONE_SYMBOL:
                case R_DATA_PLABEL:
                case R_CODE_PLABEL:
@@ -2948,8 +3020,8 @@ som_write_space_strings (bfd *abfd,
   /* Chunk of memory that we can use as buffer space, then throw
      away.  */
   size_t tmp_space_size = SOM_TMP_BUFSIZE;
-  unsigned char *tmp_space = alloca (tmp_space_size);
-  unsigned char *p = tmp_space;
+  char *tmp_space = alloca (tmp_space_size);
+  char *p = tmp_space;
   unsigned int strings_size = 0;
   asection *section;
   bfd_size_type amt;
@@ -3053,11 +3125,11 @@ som_write_symbol_strings (bfd *abfd,
   /* Chunk of memory that we can use as buffer space, then throw
      away.  */
   size_t tmp_space_size = SOM_TMP_BUFSIZE;
-  unsigned char *tmp_space = alloca (tmp_space_size);
-  unsigned char *p = tmp_space;
+  char *tmp_space = alloca (tmp_space_size);
+  char *p = tmp_space;
 
   unsigned int strings_size = 0;
-  unsigned char *comp[4];
+  char *comp[4];
   bfd_size_type amt;
 
   /* This gets a bit gruesome because of the compilation unit.  The
@@ -3217,7 +3289,7 @@ static bfd_boolean
 som_begin_writing (bfd *abfd)
 {
   unsigned long current_offset = 0;
-  int strings_size = 0;
+  unsigned int strings_size = 0;
   unsigned long num_spaces, num_subspaces, i;
   asection *section;
   unsigned int total_subspaces = 0;
@@ -3566,12 +3638,12 @@ som_finish_writing (bfd *abfd)
 {
   int num_spaces = som_count_spaces (abfd);
   asymbol **syms = bfd_get_outsymbols (abfd);
-  int i, num_syms, strings_size;
+  int i, num_syms;
   int subspace_index = 0;
   file_ptr location;
   asection *section;
   unsigned long current_offset;
-  unsigned int total_reloc_size;
+  unsigned int strings_size, total_reloc_size;
   bfd_size_type amt;
 
   /* We must set up the version identifier here as objcopy/strip copy
@@ -4364,12 +4436,12 @@ som_slurp_symbol_table (bfd *abfd)
          && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$'
          && !strcmp (sym->symbol.name, sym->symbol.section->name))
        sym->symbol.flags |= BSF_SECTION_SYM;
-      else if (!strncmp (sym->symbol.name, "L$0\002", 4))
+      else if (CONST_STRNEQ (sym->symbol.name, "L$0\002"))
        {
          sym->symbol.flags |= BSF_SECTION_SYM;
          sym->symbol.name = sym->symbol.section->name;
        }
-      else if (!strncmp (sym->symbol.name, "L$0\001", 4))
+      else if (CONST_STRNEQ (sym->symbol.name, "L$0\001"))
        sym->symbol.flags |= BSF_DEBUGGING;
 
       /* Note increment at bottom of loop, since we skip some symbols
@@ -4436,7 +4508,7 @@ som_make_empty_symbol (bfd *abfd)
 
 static void
 som_print_symbol (bfd *abfd,
-                 void * afile,
+                 void *afile,
                  asymbol *symbol,
                  bfd_print_symbol_type how)
 {
@@ -4832,7 +4904,7 @@ som_slurp_reloc_table (bfd *abfd,
                       asymbol **symbols,
                       bfd_boolean just_count)
 {
-  char *external_relocs;
+  unsigned char *external_relocs;
   unsigned int fixup_stream_size;
   arelent *internal_relocs;
   unsigned int num_relocs;
@@ -4913,8 +4985,11 @@ som_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
        return -1;
       return (asect->reloc_count + 1) * sizeof (arelent *);
     }
-  /* There are no relocations.  */
-  return 0;
+
+  /* There are no relocations.  Return enough space to hold the
+     NULL pointer which will be installed if som_canonicalize_reloc
+     is called.  */
+  return sizeof (arelent *);
 }
 
 /* Convert relocations from SOM (external) form into BFD internal
@@ -4949,15 +5024,18 @@ extern const bfd_target som_vec;
 static bfd_boolean
 som_new_section_hook (bfd *abfd, asection *newsect)
 {
-  bfd_size_type amt = sizeof (struct som_section_data_struct);
-
-  newsect->used_by_bfd = bfd_zalloc (abfd, amt);
   if (!newsect->used_by_bfd)
-    return FALSE;
+    {
+      bfd_size_type amt = sizeof (struct som_section_data_struct);
+
+      newsect->used_by_bfd = bfd_zalloc (abfd, amt);
+      if (!newsect->used_by_bfd)
+       return FALSE;
+    }
   newsect->alignment_power = 3;
 
   /* We allow more than three sections internally.  */
-  return TRUE;
+  return _bfd_generic_new_section_hook (abfd, newsect);
 }
 
 /* Copy any private info we understand from the input symbol
@@ -5070,16 +5148,20 @@ som_bfd_print_private_bfd_data (bfd *abfd, void *farg)
       fprintf (f, "\n");
       fprintf (f, "  type               %#x\n", auxhdr->type);
       fprintf (f, "  length             %#x\n", auxhdr->length);
-      fprintf (f, "  text size          %#x\n", exec_header->exec_tsize);
-      fprintf (f, "  text memory offset %#x\n", exec_header->exec_tmem);
-      fprintf (f, "  text file offset   %#x\n", exec_header->exec_tfile);
-      fprintf (f, "  data size          %#x\n", exec_header->exec_dsize);
-      fprintf (f, "  data memory offset %#x\n", exec_header->exec_dmem);
-      fprintf (f, "  data file offset   %#x\n", exec_header->exec_dfile);
-      fprintf (f, "  bss size           %#x\n", exec_header->exec_bsize);
-      fprintf (f, "  entry point        %#x\n", exec_header->exec_entry);
-      fprintf (f, "  loader flags       %#x\n", exec_header->exec_flags);
-      fprintf (f, "  bss initializer    %#x\n", exec_header->exec_bfill);
+
+      /* Note that, depending on the HP-UX version, the following fields can be
+         either ints, or longs.  */
+
+      fprintf (f, "  text size          %#lx\n", (long) exec_header->exec_tsize);
+      fprintf (f, "  text memory offset %#lx\n", (long) exec_header->exec_tmem);
+      fprintf (f, "  text file offset   %#lx\n", (long) exec_header->exec_tfile);
+      fprintf (f, "  data size          %#lx\n", (long) exec_header->exec_dsize);
+      fprintf (f, "  data memory offset %#lx\n", (long) exec_header->exec_dmem);
+      fprintf (f, "  data file offset   %#lx\n", (long) exec_header->exec_dfile);
+      fprintf (f, "  bss size           %#lx\n", (long) exec_header->exec_bsize);
+      fprintf (f, "  entry point        %#lx\n", (long) exec_header->exec_entry);
+      fprintf (f, "  loader flags       %#lx\n", (long) exec_header->exec_flags);
+      fprintf (f, "  bss initializer    %#lx\n", (long) exec_header->exec_bfill);
     }
 
   return TRUE;
@@ -5240,7 +5322,7 @@ bfd_som_attach_compilation_unit (bfd *abfd,
 static bfd_boolean
 som_get_section_contents (bfd *abfd,
                          sec_ptr section,
-                         void * location,
+                         void *location,
                          file_ptr offset,
                          bfd_size_type count)
 {
@@ -5256,7 +5338,7 @@ som_get_section_contents (bfd *abfd,
 static bfd_boolean
 som_set_section_contents (bfd *abfd,
                          sec_ptr section,
-                         const void * location,
+                         const void *location,
                          file_ptr offset,
                          bfd_size_type count)
 {
@@ -5298,20 +5380,62 @@ som_set_arch_mach (bfd *abfd,
 }
 
 static bfd_boolean
-som_find_nearest_line (bfd *abfd ATTRIBUTE_UNUSED,
-                      asection *section ATTRIBUTE_UNUSED,
-                      asymbol **symbols ATTRIBUTE_UNUSED,
-                      bfd_vma offset ATTRIBUTE_UNUSED,
-                      const char **filename_ptr ATTRIBUTE_UNUSED,
-                      const char **functionname_ptr ATTRIBUTE_UNUSED,
-                      unsigned int *line_ptr ATTRIBUTE_UNUSED)
+som_find_nearest_line (bfd *abfd,
+                      asection *section,
+                      asymbol **symbols,
+                      bfd_vma offset,
+                      const char **filename_ptr,
+                      const char **functionname_ptr,
+                      unsigned int *line_ptr)
 {
-  return FALSE;
+  bfd_boolean found;
+  asymbol *func;
+  bfd_vma low_func;
+  asymbol **p;
+
+  if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
+                                             & found, filename_ptr,
+                                             functionname_ptr, line_ptr,
+                                             & somdata (abfd).line_info))
+    return FALSE;
+
+  if (found)
+    return TRUE;
+
+  if (symbols == NULL)
+    return FALSE;
+
+  /* Fallback: find function name from symbols table.  */
+  func = NULL;
+  low_func = 0;
+
+  for (p = symbols; *p != NULL; p++)
+    { 
+      som_symbol_type *q = (som_symbol_type *) *p;
+  
+      if (q->som_type == SYMBOL_TYPE_ENTRY
+         && q->symbol.section == section
+         && q->symbol.value >= low_func
+         && q->symbol.value <= offset)
+       {
+         func = (asymbol *) q;
+         low_func = q->symbol.value;
+       }
+    }
+
+  if (func == NULL)
+    return FALSE;
+
+  *filename_ptr = NULL;
+  *functionname_ptr = bfd_asymbol_name (func);
+  *line_ptr = 0;
+
+  return TRUE;
 }
 
 static int
 som_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
-                   bfd_boolean reloc ATTRIBUTE_UNUSED)
+                   struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   (*_bfd_error_handler) (_("som_sizeof_headers unimplemented"));
   fflush (stderr);
@@ -5341,11 +5465,30 @@ som_decode_symclass (asymbol *symbol)
   if (bfd_is_com_section (symbol->section))
     return 'C';
   if (bfd_is_und_section (symbol->section))
-    return 'U';
+    {
+      if (symbol->flags & BSF_WEAK)
+       {
+         /* If weak, determine if it's specifically an object
+            or non-object weak.  */
+         if (symbol->flags & BSF_OBJECT)
+           return 'v';
+         else
+           return 'w';
+       }
+      else
+        return 'U';
+    }
   if (bfd_is_ind_section (symbol->section))
     return 'I';
   if (symbol->flags & BSF_WEAK)
-    return 'W';
+    {
+      /* If weak, determine if it's specifically an object
+        or non-object weak.  */
+      if (symbol->flags & BSF_OBJECT)
+       return 'V';
+      else
+       return 'W';
+    }
   if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL)))
     return '?';
 
@@ -5617,7 +5760,7 @@ som_slurp_armap (bfd *abfd)
     return FALSE;
 
   /* For archives without .o files there is no symbol table.  */
-  if (strncmp (nextname, "/               ", 16))
+  if (! CONST_STRNEQ (nextname, "/               "))
     {
       bfd_has_map (abfd) = FALSE;
       return TRUE;
@@ -5716,7 +5859,7 @@ som_bfd_prep_for_ar_write (bfd *abfd,
       if (curr_bfd->format != bfd_object
          || curr_bfd->xvec->flavour != bfd_target_som_flavour)
        {
-         curr_bfd = curr_bfd->next;
+         curr_bfd = curr_bfd->archive_next;
          continue;
        }
 
@@ -5761,7 +5904,7 @@ som_bfd_prep_for_ar_write (bfd *abfd,
            (*stringsize)++;
        }
 
-      curr_bfd = curr_bfd->next;
+      curr_bfd = curr_bfd->archive_next;
     }
   return TRUE;
 }
@@ -5870,7 +6013,7 @@ som_bfd_ar_write_symbol_stuff (bfd *abfd,
       if (curr_bfd->format != bfd_object
          || curr_bfd->xvec->flavour != bfd_target_som_flavour)
        {
-         curr_bfd = curr_bfd->next;
+         curr_bfd = curr_bfd->archive_next;
          continue;
        }
 
@@ -5986,7 +6129,7 @@ som_bfd_ar_write_symbol_stuff (bfd *abfd,
         linker requires objects begin on an even boundary.  So round
         up the current offset as necessary.  */
       curr_som_offset = (curr_som_offset + 0x1) &~ (unsigned) 1;
-      curr_bfd = curr_bfd->next;
+      curr_bfd = curr_bfd->archive_next;
       som_index++;
     }
 
@@ -6092,7 +6235,7 @@ som_write_armap (bfd *abfd,
       if (curr_bfd->format == bfd_object
          && curr_bfd->xvec->flavour == bfd_target_som_flavour)
        lst.module_count++;
-      curr_bfd = curr_bfd->next;
+      curr_bfd = curr_bfd->archive_next;
     }
   lst.module_limit = lst.module_count;
   lst.dir_loc = lst_size;
@@ -6229,6 +6372,10 @@ som_bfd_link_split_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
 #define som_bfd_is_group_section               bfd_generic_is_group_section
 #define som_bfd_discard_group                  bfd_generic_discard_group
 #define som_section_already_linked              _bfd_generic_section_already_linked
+#define som_bfd_merge_private_bfd_data         _bfd_generic_bfd_merge_private_bfd_data
+#define som_bfd_copy_private_header_data       _bfd_generic_bfd_copy_private_header_data
+#define som_bfd_set_private_flags              _bfd_generic_bfd_set_private_flags
+#define som_find_inliner_info                  _bfd_nosymbols_find_inliner_info
 
 const bfd_target som_vec =
 {
This page took 0.031352 seconds and 4 git commands to generate.