start-sanitize-powerpc-netware
authorIan Lance Taylor <ian@airs.com>
Wed, 20 Apr 1994 18:38:22 +0000 (18:38 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 20 Apr 1994 18:38:22 +0000 (18:38 +0000)
* nlm32-ppc.c: Complete rewrite for new version of PowerPC
NetWare.  Old code still present, but ifdeffed out.
end-sanitize-powerpc-netware

* nlmcode.h (nlm_swap_auxiliary_headers_in): Don't assume a
particular format for the customer header.  Allocate a block of
memory and read it into that.
(nlm_swap_auxiliary_headers_out): Write out the block of memory.
(nlm_compute_section_file_positions): Include length of customer
header when computing its size.

bfd/ChangeLog
bfd/nlm32-ppc.c
bfd/nlmcode.h

index c8f8c185bc190c92bb8c33b0896a14885799569c..2602e18b79791ea5721d998a3c38b65f4d3ff0a3 100644 (file)
@@ -1,3 +1,17 @@
+Wed Apr 20 14:15:21 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+start-sanitize-powerpc-netware
+
+       * nlm32-ppc.c: Complete rewrite for new version of PowerPC
+       NetWare.  Old code still present, but ifdeffed out.
+end-sanitize-powerpc-netware
+
+       * nlmcode.h (nlm_swap_auxiliary_headers_in): Don't assume a
+       particular format for the customer header.  Allocate a block of
+       memory and read it into that.
+       (nlm_swap_auxiliary_headers_out): Write out the block of memory.
+       (nlm_compute_section_file_positions): Include length of customer
+       header when computing its size.
+
 Mon Apr 18 14:27:17 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
 
        * som.c (som_prep_headers): Get the space's number from the
index c46f94b5422921d01b89425a4cf9735f84d2b6d1..62ac3d4d8d92ba0a947747856a54965f99d08b39 100644 (file)
@@ -21,6 +21,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "sysdep.h"
 #include "libbfd.h"
 
+/* The format of a PowerPC NLM changed.  Define OLDFORMAT to get the
+   old format.  */
+
 #define ARCH_SIZE 32
 
 #include "nlm/ppc-ext.h"
@@ -28,23 +31,41 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "libnlm.h"
 
+#ifdef OLDFORMAT
 static boolean nlm_powerpc_backend_object_p
   PARAMS ((bfd *));
 static boolean nlm_powerpc_write_prefix
   PARAMS ((bfd *));
+#endif
+
 static boolean nlm_powerpc_read_reloc
   PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
 static boolean nlm_powerpc_mangle_relocs
   PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
 static boolean nlm_powerpc_read_import
   PARAMS ((bfd *, nlmNAME(symbol_type) *));
+
+#ifdef OLDFORMAT
 static boolean nlm_powerpc_write_reloc
   PARAMS ((bfd *, asection *, arelent *, int));
+#endif
+
 static boolean nlm_powerpc_write_import
   PARAMS ((bfd *, asection *, arelent *));
 static boolean nlm_powerpc_write_external
   PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
+
+#ifndef OLDFORMAT
+static boolean nlm_powerpc_set_public_section
+  PARAMS ((bfd *, nlmNAME(symbol_type) *));
+static bfd_vma nlm_powerpc_get_public_offset
+  PARAMS ((bfd *, asymbol *));
+#endif
 \f
+#ifdef OLDFORMAT
+
+/* The prefix header is only used in the old format.  */
+
 /* PowerPC NLM's have a prefix header before the standard NLM.  This
    function reads it in, verifies the version, and seeks the bfd to
    the location before the regular NLM header.  */
@@ -85,7 +106,94 @@ nlm_powerpc_write_prefix (abfd)
 
   return true;
 }
+
+#endif /* OLDFORMAT */
 \f
+#ifndef OLDFORMAT
+
+/* There is only one type of reloc in a PowerPC NLM.  */
+
+static reloc_howto_type nlm_powerpc_howto =
+  HOWTO (0,                    /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        0,                     /* special_function */
+        "32",                  /* name */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false);                /* pcrel_offset */
+
+/* Read a PowerPC NLM reloc.  */
+
+static boolean
+nlm_powerpc_read_reloc (abfd, sym, secp, rel)
+     bfd *abfd;
+     nlmNAME(symbol_type) *sym;
+     asection **secp;
+     arelent *rel;
+{
+  bfd_byte temp[4];
+  bfd_vma val;
+  const char *name;
+
+  if (bfd_read (temp, sizeof (temp), 1, abfd) != sizeof (temp))
+    return false;
+
+  val = bfd_get_32 (abfd, temp);
+
+  /* The value is a word offset into either the code or data segment.
+     This is the location which needs to be adjusted.
+
+     The high bit is 0 if the value is an offset into the data
+     segment, or 1 if the value is an offset into the text segment.
+
+     If this is a relocation fixup rather than an imported symbol (the
+     sym argument is NULL), then the second most significant bit is 0
+     if the address of the data segment should be added to the
+     location addressed by the value, or 1 if the address of the text
+     segment should be added.
+
+     If this is an imported symbol, the second most significant bit is
+     not used and must be 0.  */
+
+  if ((val & NLM_HIBIT) == 0)
+    name = NLM_INITIALIZED_DATA_NAME;
+  else
+    {
+      name = NLM_CODE_NAME;
+      val &=~ NLM_HIBIT;
+    }
+  *secp = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+
+  if (sym == NULL)
+    {
+      if ((val & (NLM_HIBIT >> 1)) == 0)
+       name = NLM_INITIALIZED_DATA_NAME;
+      else
+       {
+         name = NLM_CODE_NAME;
+         val &=~ (NLM_HIBIT >> 1);
+       }
+      rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr;
+    }
+
+  rel->howto = &nlm_powerpc_howto;
+
+  rel->address = val << 2;
+  rel->addend = 0;
+
+  return true;
+}
+
+#else /* OLDFORMAT */
+
+/* This reloc handling is only applicable to the old format.  */
+
 /* How to process the various reloc types.  PowerPC NLMs use XCOFF
    reloc types, and I have just copied the XCOFF reloc table here.  */
 
@@ -525,6 +633,8 @@ nlm_powerpc_read_reloc (abfd, sym, secp, rel)
   return true;
 }
 
+#endif /* OLDFORMAT */
+
 /* Mangle PowerPC NLM relocs for output.  */
 
 static boolean
@@ -595,6 +705,79 @@ nlm_powerpc_read_import (abfd, sym)
   return true;
 }
 
+#ifndef OLDFORMAT
+
+/* Write a PowerPC NLM reloc.  */
+
+static boolean
+nlm_powerpc_write_import (abfd, sec, rel)
+     bfd *abfd;
+     asection *sec;
+     arelent *rel;
+{
+  asymbol *sym;
+  bfd_vma val;
+  bfd_byte temp[4];
+
+  /* PowerPC NetWare only supports one kind of reloc.  */
+  if (rel->addend != 0
+      || rel->howto == NULL
+      || rel->howto->rightshift != 0
+      || rel->howto->size != 2
+      || rel->howto->bitsize != 32
+      || rel->howto->bitpos != 0
+      || rel->howto->pc_relative
+      || (rel->howto->src_mask != 0xffffffff && rel->addend != 0)
+      || rel->howto->dst_mask != 0xffffffff)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return false;
+    }
+
+  sym = *rel->sym_ptr_ptr;
+
+  /* The value we write out is the offset into the appropriate
+     segment, rightshifted by two.  This offset is the section vma,
+     adjusted by the vma of the lowest section in that segment, plus
+     the address of the relocation.  */
+  val = bfd_get_section_vma (abfd, sec) + rel->address;
+  if ((val & 3) != 0)
+    {
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
+  val >>= 2;
+
+  /* The high bit is 0 if the reloc is in the data section, or 1 if
+     the reloc is in the code section.  */
+  if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
+    val -= nlm_get_data_low (abfd);
+  else
+    {
+      val -= nlm_get_text_low (abfd);
+      val |= NLM_HIBIT;
+    }
+    
+  if (bfd_get_section (sym) != &bfd_und_section)
+    {
+      /* This is an internal relocation fixup.  The second most
+        significant bit is 0 if this is a reloc against the data
+        segment, or 1 if it is a reloc against the text segment.  */
+      if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
+       val |= NLM_HIBIT >> 1;
+    }
+
+  bfd_put_32 (abfd, val, temp);
+  if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
+    return false;
+
+  return true;
+}
+
+#else /* OLDFORMAT */
+
+/* This is used for the reloc handling in the old format.  */
+
 /* Write a PowerPC NLM reloc.  */
 
 static boolean
@@ -709,6 +892,8 @@ nlm_powerpc_write_import (abfd, sec, rel)
   return nlm_powerpc_write_reloc (abfd, sec, rel, -1);
 }
 
+#endif /* OLDFORMAT */
+
 /* Write a PowerPC NLM external symbol.  This routine keeps a static
    count of the symbol index.  FIXME: I don't know if this is
    necessary, and the index never gets reset.  */
@@ -723,7 +908,9 @@ nlm_powerpc_write_external (abfd, count, sym, relocs)
   int i;
   bfd_byte len;
   unsigned char temp[NLM_TARGET_LONG_SIZE];
+#ifdef OLDFORMAT
   static int indx;
+#endif
 
   len = strlen (sym->name);
   if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
@@ -736,34 +923,121 @@ nlm_powerpc_write_external (abfd, count, sym, relocs)
 
   for (i = 0; i < count; i++)
     {
-      if (nlm_powerpc_write_reloc (abfd, relocs[i].sec,
-                                  relocs[i].rel, indx) == false)
+#ifndef OLDFORMAT
+      if (! nlm_powerpc_write_import (abfd, relocs[i].sec, relocs[i].rel))
        return false;
+#else
+      if (! nlm_powerpc_write_reloc (abfd, relocs[i].sec,
+                                    relocs[i].rel, indx))
+       return false;
+#endif
     }
 
+#ifdef OLDFORMAT
   ++indx;
+#endif
 
   return true;
 }
+\f
+#ifndef OLDFORMAT
 
+/* PowerPC Netware uses a word offset, not a byte offset, for public
+   symbols.  */
+
+/* Set the section for a public symbol.  */
+
+static boolean
+nlm_powerpc_set_public_section (abfd, sym)
+     bfd *abfd;
+     nlmNAME(symbol_type) *sym;
+{
+  if (sym->symbol.value & NLM_HIBIT)
+    {
+      sym->symbol.value &= ~NLM_HIBIT;
+      sym->symbol.flags |= BSF_FUNCTION;
+      sym->symbol.section =
+       bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+    }
+  else
+    {
+      sym->symbol.section =
+       bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
+    }
+
+  sym->symbol.value <<= 2;
+
+  return true;
+}
+
+/* Get the offset to write out for a public symbol.  */
+
+static bfd_vma
+nlm_powerpc_get_public_offset (abfd, sym)
+     bfd *abfd;
+     asymbol *sym;
+{
+  bfd_vma offset;
+  asection *sec;
+
+  offset = bfd_asymbol_value (sym);
+  sec = bfd_get_section (sym);
+  if (sec->flags & SEC_CODE)
+    {
+      offset -= nlm_get_text_low (abfd);
+      offset |= NLM_HIBIT;
+    }
+  else if (sec->flags & (SEC_DATA | SEC_ALLOC))
+    {
+      /* SEC_ALLOC is for the .bss section.  */
+      offset -= nlm_get_data_low (abfd);
+    }
+  else
+    {
+      /* We can't handle an exported symbol that is not in the code or
+        data segment.  */
+      bfd_set_error (bfd_error_invalid_operation);
+      /* FIXME: No way to return error.  */
+      abort ();
+    }
+
+  return offset;
+}
+
+#endif /* ! defined (OLDFORMAT) */
+\f
 #include "nlmswap.h"
 
 static const struct nlm_backend_data nlm32_powerpc_backend =
 {
   "NetWare PowerPC Module \032",
   sizeof (Nlm32_powerpc_External_Fixed_Header),
+#ifndef OLDFORMAT
+  0,   /* optional_prefix_size */
+#else
   sizeof (struct nlm32_powerpc_external_prefix_header),
+#endif
   bfd_arch_powerpc,
   0,
   false,
+#ifndef OLDFORMAT
+  0,   /* backend_object_p */
+  0,   /* write_prefix */
+#else
   nlm_powerpc_backend_object_p,
   nlm_powerpc_write_prefix,
+#endif
   nlm_powerpc_read_reloc,
   nlm_powerpc_mangle_relocs,
   nlm_powerpc_read_import,
   nlm_powerpc_write_import,
+#ifndef OLDFORMAT
+  nlm_powerpc_set_public_section,
+  nlm_powerpc_get_public_offset,
+#else
   0,   /* set_public_section */
   0,   /* get_public_offset */
+#endif
   nlm_swap_fixed_header_in,
   nlm_swap_fixed_header_out,
   nlm_powerpc_write_external,
index 13e43191c8e3fb83447c6da202a2a2b59c18447f..61e748f0fda02787587db63fbed5eb7b30fd6489 100644 (file)
@@ -491,16 +491,20 @@ nlm_swap_auxiliary_headers_in (abfd)
       else if (strncmp (tempstr, "CuStHeAd", 8) == 0)
        {
          Nlm_External_Custom_Header thdr;
-         if (bfd_read ((PTR) & thdr, sizeof (thdr), 1, abfd) != sizeof (thdr))
-           return (false);
+         if (bfd_read ((PTR) &thdr, sizeof (thdr), 1, abfd) != sizeof (thdr))
+           return false;
          memcpy (nlm_custom_header (abfd)->stamp, thdr.stamp,
                  sizeof (thdr.stamp));
          nlm_custom_header (abfd)->dataLength =
            get_word (abfd, (bfd_byte *) thdr.dataLength);
-         nlm_custom_header (abfd)->debugRecOffset =
-           get_word (abfd, (bfd_byte *) thdr.debugRecOffset);
-         nlm_custom_header (abfd)->debugRecLength =
-           get_word (abfd, (bfd_byte *) thdr.debugRecLength);
+         nlm_custom_header (abfd)->data =
+           bfd_alloc (abfd, nlm_custom_header (abfd)->dataLength);
+         if (nlm_custom_header (abfd)->data == NULL)
+           return false;
+         if (bfd_read (nlm_custom_header (abfd)->data, 1,
+                       nlm_custom_header (abfd)->dataLength, abfd)
+             != nlm_custom_header (abfd)->dataLength)
+           return false;
        }
       else if (strncmp (tempstr, "CoPyRiGhT=", 10) == 0)
        {
@@ -685,11 +689,11 @@ nlm_swap_auxiliary_headers_out (abfd)
       memcpy (thdr.stamp, "CuStHeAd", 8);
       put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->dataLength,
                (bfd_byte *) thdr.dataLength);
-      put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->debugRecOffset,
-               (bfd_byte *) thdr.debugRecOffset);
-      put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->debugRecLength,
-               (bfd_byte *) thdr.debugRecLength);
-      if (bfd_write ((PTR) & thdr, sizeof (thdr), 1, abfd) != sizeof (thdr))
+      if (bfd_write ((PTR) &thdr, sizeof (thdr), 1, abfd) != sizeof (thdr))
+       return false;
+      if (bfd_write (nlm_custom_header (abfd)->data, 1,
+                    nlm_custom_header (abfd)->dataLength, abfd)
+         != nlm_custom_header (abfd)->dataLength)
        return false;
     }
 
@@ -1249,7 +1253,8 @@ nlm_compute_section_file_positions (abfd)
     sofar += sizeof (Nlm_External_Extended_Header);
   if (find_nonzero ((PTR) nlm_custom_header (abfd),
                    sizeof (Nlm_Internal_Custom_Header)))
-    sofar += sizeof (Nlm_External_Custom_Header);
+    sofar += (sizeof (Nlm_External_Custom_Header)
+             + nlm_custom_header (abfd)->dataLength);
   if (find_nonzero ((PTR) nlm_copyright_header (abfd),
                    sizeof (Nlm_Internal_Copyright_Header)))
     sofar += (sizeof (Nlm_External_Copyright_Header)