Add prototypes for static functions.
[binutils-gdb.git] / bfd / som.c
index 0a80300dcb854b7647f7d8ec403c674cafd713c4..4cc78c73e45ff4150d145471031bc1e46f29b89f 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -1,5 +1,5 @@
 /* bfd back-end for HP PA-RISC SOM objects.
-   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+   Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 1998
    Free Software Foundation, Inc.
 
    Contributed by the Center for Software Science at the
@@ -19,7 +19,8 @@
 
    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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -36,6 +37,7 @@
 #include <machine/reg.h>
 #include <sys/file.h>
 #include <errno.h>
+#include <ctype.h>
 
 /* Magic not defined in standard HP-UX header files until 8.0 */
 
@@ -174,7 +176,7 @@ static boolean som_bfd_copy_private_section_data PARAMS ((bfd *, asection *,
 static boolean som_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *));
 #define som_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
 #define som_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
-static boolean som_bfd_is_local_label PARAMS ((bfd *, asymbol *));
+static boolean som_bfd_is_local_label_name PARAMS ((bfd *, const char *));
 static boolean som_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
                                                 file_ptr, bfd_size_type));
 static boolean som_get_section_contents PARAMS ((bfd *, sec_ptr, PTR,
@@ -250,8 +252,8 @@ static boolean som_bfd_prep_for_ar_write PARAMS ((bfd *, unsigned int *,
 static unsigned int som_bfd_ar_symbol_hash PARAMS ((asymbol *));
 static boolean som_bfd_ar_write_symbol_stuff PARAMS ((bfd *, unsigned int,
                                                      unsigned int,
-                                                     struct lst_header));
-static CONST char *normalize PARAMS ((CONST char *file));
+                                                     struct lst_header,
+                                                     unsigned int));
 static boolean som_is_space PARAMS ((asection *));
 static boolean som_is_subspace PARAMS ((asection *));
 static boolean som_is_container PARAMS ((asection *, asection *));
@@ -1438,17 +1440,18 @@ hppa_som_reloc (abfd, reloc_entry, symbol_in, data,
    and a field selector, return one or more appropriate SOM relocations.  */
 
 int **
-hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
+hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff, sym)
      bfd *abfd;
      int base_type;
      int format;
      enum hppa_reloc_field_selector_type_alt field;
      int sym_diff;
+     asymbol *sym;
 {
   int *final_type, **final_types;
 
-  final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 6);
-  final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+  final_types = (int **) bfd_alloc (abfd, sizeof (int *) * 6);
+  final_type = (int *) bfd_alloc (abfd, sizeof (int));
   if (!final_types || !final_type)
     return NULL;
 
@@ -1472,7 +1475,7 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
       case e_tsel:
       case e_ltsel:
       case e_rtsel:
-       final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
        if (!final_types[0])
          return NULL;
        if (field == e_tsel)
@@ -1488,7 +1491,7 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
 
       case e_lssel:
       case e_rssel:
-       final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
        if (!final_types[0])
          return NULL;
        *final_types[0] = R_S_MODE;
@@ -1499,7 +1502,7 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
 
       case e_lsel:
       case e_rsel:
-       final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
        if (!final_types[0])
          return NULL;
        *final_types[0] = R_N_MODE;
@@ -1510,7 +1513,7 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
 
       case e_ldsel:
       case e_rdsel:
-       final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
        if (!final_types[0])
          return NULL;
        *final_types[0] = R_D_MODE;
@@ -1521,7 +1524,7 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
 
       case e_lrsel:
       case e_rrsel:
-       final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
        if (!final_types[0])
          return NULL;
        *final_types[0] = R_R_MODE;
@@ -1531,7 +1534,7 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
        break;
 
       case e_nsel:
-       final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
        if (!final_types[0])
          return NULL;
        *final_types[0] = R_N1SEL;
@@ -1542,11 +1545,11 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
 
       case e_nlsel:
       case e_nlrsel:
-       final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
        if (!final_types[0])
          return NULL;
        *final_types[0] = R_N0SEL;
-       final_types[1] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       final_types[1] = (int *) bfd_alloc (abfd, sizeof (int));
        if (!final_types[1])
          return NULL;
        if (field == e_nlsel)
@@ -1565,10 +1568,10 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
       /* The difference of two symbols needs *very* special handling.  */
       if (sym_diff)
        {
-         final_types[0] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
-         final_types[1] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
-         final_types[2] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
-         final_types[3] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+         final_types[0] = (int *)bfd_alloc (abfd, sizeof (int));
+         final_types[1] = (int *)bfd_alloc (abfd, sizeof (int));
+         final_types[2] = (int *)bfd_alloc (abfd, sizeof (int));
+         final_types[3] = (int *)bfd_alloc (abfd, sizeof (int));
          if (!final_types[0] || !final_types[1] || !final_types[2])
             return NULL;
          if (field == e_fsel)
@@ -1581,7 +1584,10 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
          *final_types[2] = R_COMP2;
          *final_types[3] = R_COMP1;
          final_types[4] = final_type;
-         *final_types[4] = R_CODE_EXPR;
+         if (format == 32)
+           *final_types[4] = R_DATA_EXPR;
+         else
+           *final_types[4] = R_CODE_EXPR;
          final_types[5] = NULL;
          break;
        }
@@ -1604,10 +1610,33 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
        *final_type = R_DLT_REL;
       /* A relocation in the data space is always a full 32bits.  */
       else if (format == 32)
-       *final_type = R_DATA_ONE_SYMBOL;
+       {
+         *final_type = R_DATA_ONE_SYMBOL;
+
+         /* If there's no SOM symbol type associated with this BFD
+            symbol, then set the symbol type to ST_DATA.
+
+            Only do this if the type is going to default later when
+            we write the object file.
 
+            This is done so that the linker never encounters an
+            R_DATA_ONE_SYMBOL reloc involving an ST_CODE symbol.
+
+            This allows the compiler to generate exception handling
+            tables.
+
+            Note that one day we may need to also emit BEGIN_BRTAB and
+            END_BRTAB to prevent the linker from optimizing away insns
+            in exception handling regions.  */
+         if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
+             && (sym->flags & BSF_SECTION_SYM) == 0
+             && (sym->flags & BSF_FUNCTION) == 0
+             && ! bfd_is_com_section (sym->section))
+           som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
+       }
       break;
 
+
     case R_HPPA_GOTOFF:
       /* More PLABEL special cases.  */
       if (field == e_psel
@@ -1620,10 +1649,10 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
       /* The difference of two symbols needs *very* special handling.  */
       if (sym_diff)
        {
-         final_types[0] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
-         final_types[1] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
-         final_types[2] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
-         final_types[3] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+         final_types[0] = (int *)bfd_alloc (abfd, sizeof (int));
+         final_types[1] = (int *)bfd_alloc (abfd, sizeof (int));
+         final_types[2] = (int *)bfd_alloc (abfd, sizeof (int));
+         final_types[3] = (int *)bfd_alloc (abfd, sizeof (int));
          if (!final_types[0] || !final_types[1] || !final_types[2])
             return NULL;
          if (field == e_fsel)
@@ -1636,7 +1665,10 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
          *final_types[2] = R_COMP2;
          *final_types[3] = R_COMP1;
          final_types[4] = final_type;
-         *final_types[4] = R_CODE_EXPR;
+         if (format == 32)
+           *final_types[4] = R_DATA_EXPR;
+         else
+           *final_types[4] = R_CODE_EXPR;
          final_types[5] = NULL;
          break;
        }
@@ -1687,7 +1719,7 @@ som_object_setup (abfd, file_hdrp, aux_hdrp)
     return 0;
 
   /* Set BFD flags based on what information is available in the SOM.  */
-  abfd->flags = NO_FLAGS;
+  abfd->flags = BFD_NO_FLAGS;
   if (file_hdrp->symbol_total)
     abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
 
@@ -1990,18 +2022,24 @@ setup_sections (abfd, file_hdr)
            goto error_return;
        }
 
-      /* Yow! there is no subspace within the space which actually 
-         has initialized information in it; this should never happen
-         as far as I know.  */
+      /* This can happen for a .o which defines symbols in otherwise
+         empty subspaces.  */
       if (!save_subspace.file_loc_init_value)
-       goto error_return;
-
-      /* Setup the sizes for the space section based upon the info in the
-         last subspace of the space.  */
-      space_asect->_cooked_size = save_subspace.subspace_start
-       - space_asect->vma + save_subspace.subspace_length;
-      space_asect->_raw_size = save_subspace.file_loc_init_value
-       - space_asect->filepos + save_subspace.initialization_length;
+       {
+         space_asect->_cooked_size = 0;
+         space_asect->_raw_size = 0;
+       }
+      else
+       {
+         /* Setup the sizes for the space section based upon the info in the
+            last subspace of the space.  */
+         space_asect->_cooked_size = (save_subspace.subspace_start
+                                      - space_asect->vma
+                                      + save_subspace.subspace_length);
+         space_asect->_raw_size = (save_subspace.file_loc_init_value
+                                   - space_asect->filepos
+                                   + save_subspace.initialization_length);
+       }
     }
   /* Now that we've read in all the subspace records, we need to assign
      a target index to each subspace.  */
@@ -2834,6 +2872,7 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
                  break;
 
                case R_CODE_EXPR:
+               case R_DATA_EXPR:
                  /* The only time we generate R_COMP1, R_COMP2 and 
                     R_CODE_EXPR relocs is for the difference of two
                     symbols.  Hence we can cheat here.  */
@@ -3729,20 +3768,16 @@ som_bfd_derive_misc_symbol_info (abfd, sym, info)
          info->arg_reloc = som_symbol_data (sym)->tc_data.hppa_arg_reloc;
        }
 
-      /* For unknown symbols, set their type to ST_DATA.
-
-        We used to set the symbol type based on the section this symbol
-        was in (ST_DATA for DATA sections, ST_CODE for CODE sections).
-        Strictly speaking, this is the right approach.  However, the
-        linker chokes if we have an R_DATA_ONE_SYMBOL reloc involving
-        an ST_CODE symbol in a shared library, which happens for
-        exception handling tables.
-
-        I tried an alternate approach to generating exception handling
-        tables using PUSH_SYM and DATA_EXPR relocs, but that fails to
-        relocate exception handling tables in shared libraries.
-
-        What a pain.  */
+      /* For unknown symbols set the symbol's type based on the symbol's
+        section (ST_DATA for DATA sections, ST_CODE for CODE sections).  */
+      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
+       {
+         if (sym->section->flags & SEC_CODE)
+           info->symbol_type = ST_CODE;
+         else
+           info->symbol_type = ST_DATA;
+       }
+  
       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
        info->symbol_type = ST_DATA;
 
@@ -4223,11 +4258,11 @@ som_print_symbol (ignore_abfd, afile, symbol, how)
 }
 
 static boolean
-som_bfd_is_local_label (abfd, sym)
+som_bfd_is_local_label_name (abfd, name)
      bfd *abfd;
-     asymbol *sym;
+     const char *name;
 {
-  return (sym->name[0] == 'L' && sym->name[1] == '$');
+  return (name[0] == 'L' && name[1] == '$');
 }
 
 /* Count or process variable-length SOM fixup records.
@@ -5011,7 +5046,7 @@ som_sizeof_headers (abfd, reloc)
      bfd *abfd;
      boolean reloc;
 {
-  (*_bfd_error_handler) ("som_sizeof_headers unimplemented");
+  (*_bfd_error_handler) (_("som_sizeof_headers unimplemented"));
   fflush (stderr);
   abort ();
   return (0);
@@ -5485,27 +5520,15 @@ som_bfd_ar_symbol_hash (symbol)
          | (symbol->name[len-2] << 8) | symbol->name[len-1];
 }
 
-static CONST char *
-normalize (file)
-     CONST char *file;
-{
-  CONST char *filename = strrchr (file, '/');
-
-  if (filename != NULL)
-    filename++;
-  else
-    filename = file;
-  return filename;
-}
-
 /* Do the bulk of the work required to write the SOM library
    symbol table.  */
    
 static boolean
-som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
+som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst, elength)
      bfd *abfd;
      unsigned int nsyms, string_size;
      struct lst_header lst;
+     unsigned elength;
 {
   file_ptr lst_filepos;
   char *strings = NULL, *p;
@@ -5514,8 +5537,7 @@ som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
   unsigned int *hash_table = NULL;
   struct som_entry *som_dict = NULL;
   struct lst_symbol_record **last_hash_entry = NULL;
-  unsigned int curr_som_offset, som_index, extended_name_length = 0;
-  unsigned int maxname = abfd->xvec->ar_max_namelen;
+  unsigned int curr_som_offset, som_index = 0;
 
   hash_table =
     (unsigned int *) bfd_malloc (lst.hash_size * sizeof (unsigned int));
@@ -5551,28 +5573,17 @@ som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
      describes.  We have to compute that information as we iterate
      through the SOMs/symbols.  */
   som_index = 0;
-  curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + lst.file_end;
 
-  /* Yow!  We have to know the size of the extended name table
-     too.  */
-  for (curr_bfd = abfd->archive_head;
-       curr_bfd != NULL;
-       curr_bfd = curr_bfd->next)
-    {
-      CONST char *normal = normalize (curr_bfd->filename);
-      unsigned int thislen;
-
-      if (!normal)
-       return false;
-      thislen = strlen (normal);
-      if (thislen > maxname)
-       extended_name_length += thislen + 1;
-    }
+  /* We add in the size of the archive header twice as the location
+     in the SOM dictionary is the actual offset of the SOM, not the
+     archive header before the SOM.  */
+  curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + lst.file_end;
 
   /* Make room for the archive header and the contents of the
-     extended string table.  */
-  if (extended_name_length)
-    curr_som_offset += extended_name_length + sizeof (struct ar_hdr);
+     extended string table.  Note that elength includes the size
+     of the archive header for the extended name table!  */
+  if (elength)
+    curr_som_offset += elength;
 
   /* Make sure we're properly aligned.  */
   curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
@@ -5768,20 +5779,6 @@ som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
   return false;
 }
 
-/* SOM almost uses the SVR4 style extended name support, but not
-   quite.  */
-
-static boolean
-som_construct_extended_name_table (abfd, tabloc, tablen, name)
-     bfd *abfd;
-     char **tabloc;
-     bfd_size_type *tablen;
-     const char **name;
-{
-  *name = "//";
-  return _bfd_construct_extended_name_table (abfd, false, tabloc, tablen);
-}
-
 /* Write out the LST for the archive.
 
    You'll never believe this is really how armaps are handled in SOM...  */
@@ -5903,7 +5900,8 @@ som_write_armap (abfd, elength, map, orl_count, stridx)
     return false;
 
   /* Build and write the armap.  */
-  if (som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst) == false)
+  if (som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst, elength)
+      == false)
     return false;
   
   /* Done.  */
@@ -5958,6 +5956,8 @@ som_bfd_link_split_section (abfd, sec)
 #define som_generic_stat_arch_elt      bfd_generic_stat_arch_elt
 #define som_truncate_arname            bfd_bsd_truncate_arname
 #define som_slurp_extended_name_table  _bfd_slurp_extended_name_table
+#define som_construct_extended_name_table \
+  _bfd_archive_coff_construct_extended_name_table
 #define som_update_armap_timestamp     bfd_true
 #define som_bfd_print_private_bfd_data  _bfd_generic_bfd_print_private_bfd_data