* libnlm.h (struct nlm_backend_data): New fields
authorIan Lance Taylor <ian@airs.com>
Thu, 2 Dec 1993 02:22:35 +0000 (02:22 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 2 Dec 1993 02:22:35 +0000 (02:22 +0000)
optional_prefix_size, nlm_backend_object_p, nlm_write_prefix,
nlm_set_public_section, nlm_get_public_offset.  Removed unused
nlm_write_reloc field.  Changed nlm_write_import to remove
unnecessary symbol argument.  Renamed nlm_write_externals to
nlm_write_external, and changed cound argument from bfd_vma to
bfd_size_type.
(nlm_optional_prefix_size, nlm_backend_object_p_func,
nlm_write_prefix_func, nlm_set_public_section_func,
nlm_get_public_offset_func): New accessor macros.
(nlm_write_reloc_func): Removed.
(nlm_write_external_func): Adjusted for field renaming.
* nlm32-i386.c (nlm_i386_write_import): Renamed from
nlm_i386_write_reloc.  Removed old nlm_i386_write_import which
just called old nlm_i386_write_reloc.
(nlm_i386_write_external): Renamed from nlm_i386_write_externals.
Declared.  Changed second argument from bfd_vma to bfd_size_type.
(nlm32_i386_backend): Adjusted for changes to fields and names.
* nlm32-sparc.c (nlm_sparc_mangle_relocs): Removed unused,
ifdeffed out code.
(nlm_sparc_write_import): Removed second argument.
(nlm_sparc_write_external): Renamed from
nlm_sparc_write_externals.  Changed second argument from bfd_vma
to bfd_size_type.
(nlm32_sparc_backend): Adjusted for changes to fields and names.
* nlmcode.h: Removed some unused code.
(nlm_object_p): Don't destroy tdata pointer.  Call
backend_object_p function if it exists.
(nlm_slurp_symbol_table): Removed unused variable rcount.  Call
set_public_section_func if it exists instead of checking
NLM_HIBIT.
(nlm_compute_section_file_positions): Account for
optional_prefix_size.
(nlm_write_object_contents): Account for optional_prefix_size.
Removed useless variable write_reloc_func.  Changed declaration
and call of write_import_func.  Call write_prefix_func if it
exists.  Removed unused variables len and temp.  Call
get_public_offset_func if it exists rather than setting NLM_HIBIT.

bfd/libnlm.h
bfd/nlm32-i386.c
bfd/nlm32-sparc.c [new file with mode: 0644]
bfd/nlmcode.h

index 53199bc1f1d5f664c346bb9f057d99b0398c4548..22d779d9aae8e3424893b9017a1ebe2c1c5d3df1 100644 (file)
@@ -117,14 +117,41 @@ struct nlm_obj_tdata
 #define nlm_relocation_fixups(bfd)     (nlm_tdata(bfd) -> nlm_reloc_fixups)
 #define nlm_relocation_fixup_secs(bfd) (nlm_tdata(bfd)->nlm_reloc_fixup_secs)
 
+/* This is used when writing out the external relocs. */
+
+struct reloc_and_sec
+{
+  arelent *rel;
+  asection *sec;
+};
+
 /* We store some function pointer in the backend structure.  This lets
    different NLM targets share most of the same code, while providing
    slightly different code where necessary.  */
 
 struct nlm_backend_data
 {
-  /* Machine architecture.  */
+  /* Signature for this backend.  */
+  char signature[NLM_SIGNATURE_SIZE];
+  /* Size of the fixed header.  */
+  bfd_size_type fixed_header_size;
+  /* Size of optional prefix for this backend.  Some backend may
+     require this to be a function, but so far a constant is OK.  This
+     is for a prefix which precedes the standard NLM fixed header.  */
+  bfd_size_type optional_prefix_size;
+  /* Architecture.  */
   enum bfd_architecture arch;
+  /* Machine.  */
+  long mach;
+  /* Some NLM formats have a prefix on the file.  If this function is
+     not NULL, it will be called by nlm_object_p.  It should return
+     true if this file could match this format, and it should leave
+     the BFD such that a bfd_read will pick up the fixed header.  */
+  boolean (*nlm_backend_object_p) PARAMS ((bfd *));
+  /* Write out the prefix.  This function may be NULL.  This must
+     write out the same number of bytes as is in the field
+     optional_prefix_size.  */
+  boolean (*nlm_write_prefix) PARAMS ((bfd *));
   /* Read a relocation fixup from abfd.  The reloc information is
      machine specific.  The second argument is the symbol if this is
      an import, or NULL if this is a reloc fixup.  This function
@@ -134,25 +161,69 @@ struct nlm_backend_data
      import symbol.  */
   boolean (*nlm_read_reloc) PARAMS ((bfd *, nlmNAME(symbol_type) *,
                                     asection **, arelent *));
-  /* Write a relocation fixup to abfd.  */
-  boolean (*nlm_write_reloc) PARAMS ((bfd *, asection *, arelent *));
   /* To make objcopy to an i386 NLM work, the i386 backend needs a
      chance to work over the relocs.  This is a bit icky.  */
   boolean (*nlm_mangle_relocs) PARAMS ((bfd *, asection *, PTR data,
                                        bfd_vma offset,
                                        bfd_size_type count));
+  /* Read an import record from abfd.  It would be nice if this
+     were in a machine-dependent format, but it doesn't seem to be. */
+  boolean (*nlm_read_import) PARAMS ((bfd *, nlmNAME(symbol_type) *));
+  /* Write an import record to abfd. */
+  boolean (*nlm_write_import) PARAMS ((bfd *, asection *, arelent *));
+  /* Set the section for a public symbol.  This may be NULL, in which
+     case a default method will be used.  */
+  boolean (*nlm_set_public_section) PARAMS ((bfd *, nlmNAME(symbol_type) *));
+  /* Get the offset to write out for a public symbol.  This may be
+     NULL, in which case a default method will be used.  */
+  bfd_vma (*nlm_get_public_offset) PARAMS ((bfd *, asymbol *));
+  /* Swap the fixed header in and out */
+  void (*nlm_swap_fhdr_in) PARAMS ((bfd *,
+                                   PTR,
+                                   Nlm_Internal_Fixed_Header *));
+  void (*nlm_swap_fhdr_out) PARAMS ((bfd *,
+                                    struct nlm_internal_fixed_header *,
+                                    PTR));
+  /* Write out an external reference.  */
+  boolean (*nlm_write_external) PARAMS ((bfd *, bfd_size_type,
+                                        asymbol *,
+                                        struct reloc_and_sec *));
 };
 
 #define nlm_backend(bfd) \
   ((struct nlm_backend_data *)((bfd) -> xvec -> backend_data))
+#define nlm_signature(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> signature : "")
+#define nlm_fixed_header_size(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> fixed_header_size : 0)
+#define nlm_optional_prefix_size(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> optional_prefix_size : 0)
 #define nlm_architecture(bfd) \
   (nlm_backend(bfd) ? nlm_backend(bfd) -> arch : bfd_arch_unknown)
+#define nlm_machine(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> mach : 0)
+#define nlm_backend_object_p_func(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_backend_object_p : 0)
+#define nlm_write_prefix_func(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_write_prefix : 0)
 #define nlm_read_reloc_func(bfd) \
   (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_read_reloc : 0)
-#define nlm_write_reloc_func(bfd) \
-  (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_write_reloc : 0)
 #define nlm_mangle_relocs_func(bfd) \
   (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_mangle_relocs : 0)
+#define nlm_read_import_func(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_read_import : 0)
+#define nlm_write_import_func(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_write_import : 0)
+#define nlm_set_public_section_func(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_set_public_section : 0)
+#define nlm_get_public_offset_func(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_get_public_offset : 0)
+#define nlm_swap_fixed_header_in_func(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_swap_fhdr_in : 0)
+#define nlm_swap_fixed_header_out_func(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_swap_fhdr_out : 0)
+#define nlm_write_external_func(bfd) \
+  (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_write_external : 0)
 
 /* The NLM code, data, and uninitialized sections have no names defined
    in the NLM, but bfd wants to give them names, so use the traditional
index 20328b12659a798fab18900d6070b1737bad081d..45260c5cb751ba51c01db582cc03aa8f76f9456c 100644 (file)
@@ -22,14 +22,22 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "libbfd.h"
 
 #define ARCH_SIZE 32
+
+#include "nlm/i386-ext.h"
+#define Nlm_External_Fixed_Header      Nlm32_i386_External_Fixed_Header
+
 #include "libnlm.h"
 
 static boolean nlm_i386_read_reloc
   PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
-static boolean nlm_i386_write_reloc
+static boolean nlm_i386_write_import
   PARAMS ((bfd *, asection *, arelent *));
 static boolean nlm_i386_mangle_relocs
   PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
+static boolean nlm_i386_read_import
+  PARAMS ((bfd *, nlmNAME(symbol_type) *));
+static boolean nlm_i386_write_external
+  PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
 
 /* Adjust the reloc location by an absolute value.  */
 
@@ -146,7 +154,7 @@ nlm_i386_read_reloc (abfd, sym, secp, rel)
 /* Write a NetWare i386 reloc.  */
 
 static boolean
-nlm_i386_write_reloc (abfd, sec, rel)
+nlm_i386_write_import (abfd, sec, rel)
      bfd *abfd;
      asection *sec;
      arelent *rel;
@@ -165,7 +173,6 @@ nlm_i386_write_reloc (abfd, sec, rel)
       || rel->howto->size != 2
       || rel->howto->bitsize != 32
       || rel->howto->bitpos != 0
-      || ! rel->howto->partial_inplace
       || rel->howto->src_mask != 0xffffffff
       || rel->howto->dst_mask != 0xffffffff)
     {
@@ -264,7 +271,7 @@ nlm_i386_mangle_relocs (abfd, sec, data, offset, count)
       sym = *rel->sym_ptr_ptr;
 
       /* Note that no serious harm will ensue if we fail to change a
-        reloc.  We will wind up failing in nlm_i386_write_reloc.  */
+        reloc.  We will wind up failing in nlm_i386_write_import.  */
 
       /* Make sure this reloc is within the data we have.  We only 4
         byte relocs here, so we insist on having 4 bytes.  */
@@ -283,7 +290,7 @@ nlm_i386_mangle_relocs (abfd, sec, data, offset, count)
         that at this point the size of the data section is in the NLM
         header.  */
       if (((bfd_get_section_flags (abfd, bfd_get_section (sym))
-           & (SEC_CODE | SEC_DATA)) == 0)
+           & SEC_LOAD) == 0)
          && ((bfd_get_section_flags (abfd, bfd_get_section (sym))
               & SEC_ALLOC) != 0))
        addend += nlm_fixed_header (abfd)->dataImageSize;
@@ -294,15 +301,14 @@ nlm_i386_mangle_relocs (abfd, sec, data, offset, count)
          && rel->howto->size == 2
          && rel->howto->bitsize == 32
          && rel->howto->bitpos == 0
-         && rel->howto->partial_inplace
          && rel->howto->src_mask == 0xffffffff
          && rel->howto->dst_mask == 0xffffffff)
        {
          bfd_vma val;
 
-         val = bfd_get_32 (abfd, (char *) data + rel->address - offset);
+         val = bfd_get_32 (abfd, (bfd_byte *) data + rel->address - offset);
          val += addend;
-         bfd_put_32 (abfd, val, (char *) data + rel->address - offset);
+         bfd_put_32 (abfd, val, (bfd_byte *) data + rel->address - offset);
          rel->addend = 0;
        }
 
@@ -319,7 +325,6 @@ nlm_i386_mangle_relocs (abfd, sec, data, offset, count)
          && rel->howto->size == 2
          && rel->howto->bitsize == 32
          && rel->howto->bitpos == 0
-         && rel->howto->partial_inplace
          && rel->howto->src_mask == 0xffffffff
          && rel->howto->dst_mask == 0xffffffff)
        {
@@ -328,9 +333,9 @@ nlm_i386_mangle_relocs (abfd, sec, data, offset, count)
          /* When pcrel_offset is not set, it means that the negative
             of the address of the memory location is stored in the
             memory location.  We must add it back in.  */
-         val = bfd_get_32 (abfd, (char *) data + rel->address - offset);
+         val = bfd_get_32 (abfd, (bfd_byte *) data + rel->address - offset);
          val += rel->address;
-         bfd_put_32 (abfd, val, (char *) data + rel->address - offset);
+         bfd_put_32 (abfd, val, (bfd_byte *) data + rel->address - offset);
 
          rel->howto = &nlm_i386_pcrel_howto;
        }
@@ -339,12 +344,117 @@ nlm_i386_mangle_relocs (abfd, sec, data, offset, count)
   return true;
 }
 
+/* Read a NetWare i386 import record */
+static boolean
+nlm_i386_read_import (abfd, sym)
+     bfd *abfd;
+     nlmNAME(symbol_type) *sym;
+{
+  struct nlm_relent *nlm_relocs;       /* relocation records for symbol */
+  bfd_size_type rcount;                        /* number of relocs */
+  bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
+  unsigned char symlength;             /* length of symbol name */
+
+  if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
+      != sizeof (symlength))
+    {
+      bfd_error = system_call_error;
+      return (false);
+    }
+  sym -> symbol.the_bfd = abfd;
+  sym -> symbol.name = bfd_alloc (abfd, symlength + 1);
+  if (bfd_read ((PTR) sym -> symbol.name, symlength, 1, abfd)
+      != symlength)
+    {
+      bfd_error = system_call_error;
+      return (false);
+    }
+  sym -> symbol.flags = 0;
+  sym -> symbol.value = 0;
+  sym -> symbol.section = &bfd_und_section;
+  if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
+    {
+      bfd_error = system_call_error;
+      return (false);
+    }
+  rcount = bfd_h_get_32 (abfd, temp);
+  nlm_relocs = ((struct nlm_relent *)
+               bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
+  sym -> relocs = nlm_relocs;
+  sym -> rcnt = 0;
+  while (sym -> rcnt < rcount)
+    {
+      asection *section;
+      
+      if (nlm_i386_read_reloc (abfd, sym, &section,
+                              &nlm_relocs -> reloc)
+         == false)
+       return false;
+      nlm_relocs -> section = section;
+      nlm_relocs++;
+      sym -> rcnt++;
+    }
+  return true;
+}
+
+/* Write out an external reference.  */
+
+static boolean
+nlm_i386_write_external (abfd, count, sym, relocs)
+     bfd *abfd;
+     bfd_size_type count;
+     asymbol *sym;
+     struct reloc_and_sec *relocs;
+{
+  int i;
+  bfd_byte len;
+  unsigned char temp[NLM_TARGET_LONG_SIZE];
+
+  len = strlen (sym->name);
+  if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
+      || bfd_write (sym->name, len, 1, abfd) != len)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  bfd_put_32 (abfd, count, temp);
+  if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  for (i = 0; i < count; i++)
+    {
+      if (nlm_i386_write_import (abfd, relocs[i].sec,
+                                relocs[i].rel) == false)
+       return false;
+    }
+
+  return true;
+}
+
+#include "nlmswap.h"
+
 static const struct nlm_backend_data nlm32_i386_backend =
 {
+  "NetWare Loadable Module\032",
+  sizeof (Nlm32_i386_External_Fixed_Header),
+  0,   /* optional_prefix_size */
   bfd_arch_i386,
+  0,
+  0,   /* backend_object_p */
+  0,   /* write_prefix_func */
   nlm_i386_read_reloc,
-  nlm_i386_write_reloc,
-  nlm_i386_mangle_relocs
+  nlm_i386_mangle_relocs,
+  nlm_i386_read_import,
+  nlm_i386_write_import,
+  0,   /* set_public_section */
+  0,   /* get_public_offset */
+  nlm_swap_fixed_header_in,
+  nlm_swap_fixed_header_out,
+  nlm_i386_write_external,
 };
 
 #define TARGET_LITTLE_NAME             "nlm32-i386"
diff --git a/bfd/nlm32-sparc.c b/bfd/nlm32-sparc.c
new file mode 100644 (file)
index 0000000..ff0571b
--- /dev/null
@@ -0,0 +1,400 @@
+/* Support for 32-bit SPARC NLM (NetWare Loadable Module)
+   Copyright (C) 1993 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
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#define ARCH_SIZE 32
+
+#include "nlm/sparc32-ext.h"
+#define Nlm_External_Fixed_Header      Nlm32_sparc_External_Fixed_Header
+
+#include "libnlm.h"
+
+static boolean nlm_sparc_read_reloc
+  PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
+static boolean nlm_sparc_write_reloc
+  PARAMS ((bfd *, asection *, arelent *));
+static boolean nlm_sparc_mangle_relocs
+  PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
+static boolean nlm_sparc_read_import
+  PARAMS ((bfd *, nlmNAME(symbol_type) *));
+static boolean nlm_sparc_write_import
+  PARAMS ((bfd *, asection *, arelent *));
+static boolean nlm_sparc_write_external
+  PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
+
+enum reloc_type
+  {
+    R_SPARC_NONE = 0,
+    R_SPARC_8,         R_SPARC_16,             R_SPARC_32, 
+    R_SPARC_DISP8,     R_SPARC_DISP16,         R_SPARC_DISP32, 
+    R_SPARC_WDISP30,   R_SPARC_WDISP22,
+    R_SPARC_HI22,      R_SPARC_22,
+    R_SPARC_13,                R_SPARC_LO10,
+    R_SPARC_GOT10,     R_SPARC_GOT13,          R_SPARC_GOT22,
+    R_SPARC_PC10,      R_SPARC_PC22,
+    R_SPARC_WPLT30,
+    R_SPARC_COPY,
+    R_SPARC_GLOB_DAT,  R_SPARC_JMP_SLOT,
+    R_SPARC_RELATIVE,
+    R_SPARC_UA32,
+    R_SPARC_max
+  };
+
+#if 0
+static CONST char *CONST reloc_type_names[] =
+{
+  "R_SPARC_NONE",
+  "R_SPARC_8",         "R_SPARC_16",           "R_SPARC_32",
+  "R_SPARC_DISP8",     "R_SPARC_DISP16",       "R_SPARC_DISP32",
+  "R_SPARC_WDISP30",   "R_SPARC_WDISP22",
+  "R_SPARC_HI22",      "R_SPARC_22",
+  "R_SPARC_13",                "R_SPARC_LO10",
+  "R_SPARC_GOT10",     "R_SPARC_GOT13",        "R_SPARC_GOT22",
+  "R_SPARC_PC10",      "R_SPARC_PC22",
+  "R_SPARC_WPLT30",
+  "R_SPARC_COPY",
+  "R_SPARC_GLOB_DAT",  "R_SPARC_JMP_SLOT",
+  "R_SPARC_RELATIVE",
+  "R_SPARC_UA32",
+};
+#endif
+
+static reloc_howto_type nlm32_sparc_howto_table[] = 
+{
+  HOWTO(R_SPARC_NONE,    0,0, 0,false,0,complain_overflow_dont,    0,"R_SPARC_NONE",    false,0,0x00000000,true),
+  HOWTO(R_SPARC_8,       0,0, 8,false,0,complain_overflow_bitfield,0,"R_SPARC_8",       false,0,0x000000ff,true),
+  HOWTO(R_SPARC_16,      0,1,16,false,0,complain_overflow_bitfield,0,"R_SPARC_16",      false,0,0x0000ffff,true),
+  HOWTO(R_SPARC_32,      0,2,32,false,0,complain_overflow_bitfield,0,"R_SPARC_32",      false,0,0xffffffff,true),
+  HOWTO(R_SPARC_DISP8,   0,0, 8,true, 0,complain_overflow_signed,  0,"R_SPARC_DISP8",   false,0,0x000000ff,true),
+  HOWTO(R_SPARC_DISP16,  0,1,16,true, 0,complain_overflow_signed,  0,"R_SPARC_DISP16",  false,0,0x0000ffff,true),
+  HOWTO(R_SPARC_DISP32,  0,2,32,true, 0,complain_overflow_signed,  0,"R_SPARC_DISP32",  false,0,0x00ffffff,true),
+  HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed,  0,"R_SPARC_WDISP30", false,0,0x3fffffff,true),
+  HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed,  0,"R_SPARC_WDISP22", false,0,0x003fffff,true),
+  HOWTO(R_SPARC_HI22,   10,2,22,false,0,complain_overflow_dont,    0,"R_SPARC_HI22",    false,0,0x003fffff,true),
+  HOWTO(R_SPARC_22,      0,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_22",      false,0,0x003fffff,true),
+  HOWTO(R_SPARC_13,      0,2,13,false,0,complain_overflow_bitfield,0,"R_SPARC_13",      false,0,0x00001fff,true),
+  HOWTO(R_SPARC_LO10,    0,2,10,false,0,complain_overflow_dont,    0,"R_SPARC_LO10",    false,0,0x000003ff,true),
+  HOWTO(R_SPARC_GOT10,   0,2,10,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT10",   false,0,0x000003ff,true),
+  HOWTO(R_SPARC_GOT13,   0,2,13,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT13",   false,0,0x00001fff,true),
+  HOWTO(R_SPARC_GOT22,  10,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT22",   false,0,0x003fffff,true),
+  HOWTO(R_SPARC_PC10,    0,2,10,false,0,complain_overflow_bitfield,0,"R_SPARC_PC10",    false,0,0x000003ff,true),
+  HOWTO(R_SPARC_PC22,    0,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_PC22",    false,0,0x003fffff,true),
+  HOWTO(R_SPARC_WPLT30,  0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_WPLT30",  false,0,0x00000000,true),
+  HOWTO(R_SPARC_COPY,    0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_COPY",    false,0,0x00000000,true),
+  HOWTO(R_SPARC_GLOB_DAT,0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_GLOB_DAT",false,0,0x00000000,true),
+  HOWTO(R_SPARC_JMP_SLOT,0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_JMP_SLOT",false,0,0x00000000,true),
+  HOWTO(R_SPARC_RELATIVE,0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_RELATIVE",false,0,0x00000000,true),
+  HOWTO(R_SPARC_UA32,    0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_UA32",    false,0,0x00000000,true),
+};
+
+/* Read a NetWare sparc reloc.  */
+
+struct nlm32_sparc_reloc_ext {
+  unsigned char offset[4];
+  unsigned char addend[4];
+  unsigned char type[1];
+  unsigned char pad1[3];
+};
+
+static boolean
+nlm_sparc_read_reloc (abfd, sym, secp, rel)
+     bfd *abfd;
+     nlmNAME(symbol_type) *sym;
+     asection **secp;
+     arelent *rel;
+{
+  bfd_byte temp[4];
+  bfd_vma val, addend;
+  const char *name;
+  int index;
+  unsigned int type;
+  struct nlm32_sparc_reloc_ext tmp_reloc;
+
+  if (bfd_read (&tmp_reloc, 12, 1, abfd) != 12) {
+    bfd_error = system_call_error;
+    return false;
+  }
+
+  *secp = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+
+  val = bfd_get_32 (abfd, tmp_reloc.offset);
+  addend = bfd_get_32 (abfd, tmp_reloc.addend);
+  type = bfd_get_8 (abfd, tmp_reloc.type);
+
+  rel->address = val;
+  rel->addend = addend;
+  rel->howto = NULL;
+
+  for (index = 0;
+       index < sizeof(nlm32_sparc_howto_table) / sizeof(reloc_howto_type);
+       index++)
+    if (nlm32_sparc_howto_table[index].type == type) {
+      rel->howto = &nlm32_sparc_howto_table[index];
+      break;
+    }
+
+#ifdef DEBUG
+  fprintf (stderr, "%s:  address = %08lx, addend = %08lx, type = %d, howto = %08lx\n",
+          __FILE__, rel->address, rel->addend, type, rel->howto);
+#endif
+  return true;
+
+}
+
+/* Write a NetWare sparc reloc.  */
+
+static boolean
+nlm_sparc_write_reloc (abfd, sec, rel)
+     bfd *abfd;
+     asection *sec;
+     arelent *rel;
+{
+  bfd_vma val;
+  struct nlm32_sparc_reloc_ext tmp_reloc = {0};
+  int index;
+  int type = -1;
+  reloc_howto_type *tmp;
+
+  
+  for (index = 0;
+       index < sizeof (nlm32_sparc_howto_table) / sizeof(reloc_howto_type);
+       index++) {
+    tmp = &nlm32_sparc_howto_table[index];
+
+    if (tmp->rightshift == rel->howto->rightshift
+       && tmp->size == rel->howto->size
+       && tmp->bitsize == rel->howto->bitsize
+       && tmp->pc_relative == rel->howto->pc_relative
+       && tmp->bitpos == rel->howto->bitpos
+       && tmp->src_mask == rel->howto->src_mask
+       && tmp->dst_mask == rel->howto->dst_mask) {
+      type = tmp->type;
+      break;
+    }
+  }
+  if (type == -1)
+    abort();
+
+  /*
+   * Netware wants a list of relocs for each address.
+   * Format is:
+   *   long    offset
+   *   long    addend
+   *   char    type
+   * That should be it.
+   */
+
+  /* The value we write out is the offset into the appropriate
+     segment.  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;
+
+#ifdef DEBUG
+  fprintf (stderr, "%s:  val = %08lx, addend = %08lx, type = %d\n",
+          __FILE__, val, rel->addend, rel->howto->type);
+#endif
+  bfd_put_32 (abfd, val, tmp_reloc.offset);
+  bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
+  bfd_put_8 (abfd, (short)(rel->howto->type), tmp_reloc.type);
+
+  if (bfd_write (&tmp_reloc, 12, 1, abfd) != 12)
+    {
+      abort();
+    }
+
+  return true;
+}
+
+/* Mangle relocs for SPARC NetWare.  We can just use the standard
+   SPARC relocs.  */
+
+static boolean
+nlm_sparc_mangle_relocs (abfd, sec, data, offset, count)
+     bfd *abfd;
+     asection *sec;
+     PTR data;
+     bfd_vma offset;
+     bfd_size_type count;
+{
+  return true;
+}
+
+/* Read a NetWare sparc import record */
+static boolean
+nlm_sparc_read_import (abfd, sym)
+     bfd *abfd;
+     nlmNAME(symbol_type) *sym;
+{
+  struct nlm_relent *nlm_relocs;       /* relocation records for symbol */
+  bfd_size_type rcount;                        /* number of relocs */
+  bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
+  unsigned char symlength;             /* length of symbol name */
+  
+  /*
+   * First, read in the number of relocation
+   * entries for this symbol
+   */
+  if (bfd_read ((PTR) temp, 4, 1, abfd)
+      != 4)
+    {
+      bfd_error = system_call_error;
+      return (false);
+    }
+  
+  rcount = bfd_get_32 (abfd, temp);
+  
+  /*
+   * Next, read in the length of the symbol
+   */
+  
+  if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
+      != sizeof (symlength))
+    {
+      bfd_error = system_call_error;
+      return (false);
+    }
+  sym -> symbol.the_bfd = abfd;
+  sym -> symbol.name = bfd_alloc (abfd, symlength + 1);
+  
+  /*
+   * Then read in the symbol
+   */
+  
+  if (bfd_read ((PTR) sym -> symbol.name, symlength, 1, abfd)
+      != symlength)
+    {
+      bfd_error = system_call_error;
+      return (false);
+    }
+  sym -> symbol.flags = 0;
+  sym -> symbol.value = 0;
+  sym -> symbol.section = &bfd_und_section;
+  
+  /*
+   * Next, start reading in the relocs.
+   */
+  
+  nlm_relocs = ((struct nlm_relent *)
+               bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
+  sym -> relocs = nlm_relocs;
+  sym -> rcnt = 0;
+  while (sym -> rcnt < rcount)
+    {
+      asection *section;
+      
+      if (nlm_sparc_read_reloc (abfd, sym, &section,
+                             &nlm_relocs -> reloc)
+         == false)
+       return false;
+      nlm_relocs -> section = section;
+      nlm_relocs++;
+      sym -> rcnt++;
+    }
+  return true;
+}
+
+static boolean
+nlm_sparc_write_import (abfd, sec, rel)
+     bfd *abfd;
+     asection *sec;
+     arelent *rel;
+{
+  char temp[4];
+
+  bfd_put_32 (abfd, (*rel->sym_ptr_ptr)->value, temp);
+  bfd_write ((PTR)temp, 4, 1, abfd);
+  bfd_put_32 (abfd, 1, temp);
+  bfd_write ((PTR)temp, 4, 1, abfd);
+  if (nlm_sparc_write_reloc (abfd, sec, rel) == false)
+    return false;
+  return true;
+}
+
+/* Write out an external reference.  */
+
+static boolean
+nlm_sparc_write_external (abfd, count, sym, relocs)
+     bfd *abfd;
+     bfd_size_type count;
+     asymbol *sym;
+     struct reloc_and_sec *relocs;
+{
+  int i;
+  bfd_byte len;
+  unsigned char temp[NLM_TARGET_LONG_SIZE];
+
+  bfd_put_32 (abfd, count, temp);
+  if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  len = strlen (sym->name);
+  if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
+      || bfd_write (sym->name, len, 1, abfd) != len)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  for (i = 0; i < count; i++)
+    {
+      if (nlm_sparc_write_reloc (abfd, relocs[i].sec,
+                                relocs[i].rel) == false)
+       return false;
+    }
+
+  return true;
+}
+
+#undef nlm_swap_fixed_header_in
+#undef nlm_swap_fixed_header_out
+
+#include "nlmswap.h"
+
+static const struct nlm_backend_data nlm32_sparc_backend =
+{
+  "NetWare SPARC Module   \032",
+  sizeof (Nlm32_sparc_External_Fixed_Header),
+  0,   /* optional_prefix_size */
+  bfd_arch_sparc,
+  0,
+  0,   /* backend_object_p */
+  0,   /* write_prefix_func */
+  nlm_sparc_read_reloc,
+  nlm_sparc_mangle_relocs,
+  nlm_sparc_read_import,
+  nlm_sparc_write_import,
+  0,   /* set_public_section */
+  0,   /* get_public_offset */
+  nlm_swap_fixed_header_in,
+  nlm_swap_fixed_header_out,
+  nlm_sparc_write_external,
+};
+
+#define TARGET_BIG_NAME                "nlm32-sparc"
+#define TARGET_BIG_SYM         nlmNAME(sparc_vec)
+#define TARGET_BACKEND_DATA            &nlm32_sparc_backend
+
+#include "nlm-target.h"
index 7944d5fb5658253f68da8aa750ba2b20a15c14b8..b7568a57cb6582474618e1dbb277076c8110bcbb 100644 (file)
@@ -51,14 +51,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define nlm_set_section_contents       nlmNAME(set_section_contents)
 #define nlm_write_object_contents      nlmNAME(write_object_contents)
 
+#define nlm_swap_fixed_header_in(abfd,src,dst) \
+  (nlm_swap_fixed_header_in_func(abfd))(abfd,src,dst)
+#define nlm_swap_fixed_header_out(abfd,src,dst) \
+  (nlm_swap_fixed_header_out_func(abfd))(abfd,src,dst)
+
 /* Forward declarations of static functions */
 
 static boolean add_bfd_section
   PARAMS ((bfd *, char *, file_ptr, bfd_size_type, flagword));
-static void nlm_swap_fixed_header_in
-  PARAMS ((bfd *, Nlm_External_Fixed_Header *, Nlm_Internal_Fixed_Header *));
-static void nlm_swap_fixed_header_out
-  PARAMS ((bfd *, Nlm_Internal_Fixed_Header *, Nlm_External_Fixed_Header *));
 static boolean nlm_swap_variable_header_in
   PARAMS ((bfd *));
 static boolean nlm_swap_variable_header_out
@@ -92,63 +93,73 @@ static int nlm_external_reloc_compare
 bfd_target *
 DEFUN (nlm_object_p, (abfd), bfd * abfd)
 {
-  Nlm_External_Fixed_Header x_fxdhdr;  /* Nlm file header, external form */
-  Nlm_Internal_Fixed_Header *i_fxdhdrp;        /* Nlm file header, internal form */
+  struct nlm_obj_tdata *preserved_tdata = nlm_tdata (abfd);
+  boolean (*backend_object_p) PARAMS ((bfd *));
+  PTR x_fxdhdr;
+  Nlm_Internal_Fixed_Header *i_fxdhdrp;
+  const char *signature;
   enum bfd_architecture arch;
 
+  /* Some NLM formats have a prefix before the standard NLM fixed
+     header.  */
+  backend_object_p = nlm_backend_object_p_func (abfd);
+  if (backend_object_p)
+    {
+      if (! (*backend_object_p) (abfd))
+       goto got_wrong_format_error;
+    }
+
   /* Read in the fixed length portion of the NLM header in external format.  */
 
-  if (bfd_read ((PTR) &x_fxdhdr, sizeof (x_fxdhdr), 1, abfd) !=
-      sizeof (x_fxdhdr))
+  x_fxdhdr = alloca (nlm_fixed_header_size (abfd));
+
+  if (bfd_read ((PTR) x_fxdhdr, nlm_fixed_header_size (abfd), 1, abfd) !=
+      nlm_fixed_header_size (abfd))
     {
       bfd_error = system_call_error;
-      return (NULL);
+      goto got_no_match;
     }
 
-  /* Check to see if we have an NLM file by matching the NLM signature. */
+  /* Allocate an instance of the nlm_obj_tdata structure and hook it up to
+     the tdata pointer in the bfd.  */
 
-  if (strncmp (x_fxdhdr.signature, NLM_SIGNATURE, NLM_SIGNATURE_SIZE) != 0)
+  nlm_tdata (abfd) = (struct nlm_obj_tdata *)
+    bfd_zalloc (abfd, sizeof (struct nlm_obj_tdata));
+  if (nlm_tdata (abfd) == NULL)
     {
-      bfd_error = wrong_format;
-      return (NULL);
+      bfd_error = no_memory;
+      goto got_no_match;
     }
 
+  i_fxdhdrp = nlm_fixed_header (abfd);
+  nlm_swap_fixed_header_in (abfd, x_fxdhdr, i_fxdhdrp);
+
+  /* Check to see if we have an NLM file for this backend by matching
+     the NLM signature. */
+
+  signature = nlm_signature (abfd);
+  if (signature != NULL
+      && *signature != '\0'
+      && strncmp ((char *) i_fxdhdrp->signature, signature,
+                 NLM_SIGNATURE_SIZE) != 0)
+    goto got_wrong_format_error;
+
   /* There's no supported way to discover the endianess of an NLM, so test for
      a sane version number after doing byte swapping appropriate for this
      XVEC.  (Hack alert!) */
 
-  if (get_word (abfd, (bfd_byte *) x_fxdhdr.version) > 0xFFFF)
-    {
-      bfd_error = wrong_format;
-      return (NULL);
-    }
+  if (i_fxdhdrp->version > 0xFFFF)
+    goto got_wrong_format_error;
 
   /* There's no supported way to check for 32 bit versus 64 bit addresses,
      so ignore this distinction for now.  (FIXME) */
 
-  /* Allocate an instance of the nlm_obj_tdata structure and hook it up to
-     the tdata pointer in the bfd.
-     FIXME:  If we later decide this isn't the right format and the bfd
-     already had valid tdata, we've just blown away the tdata we wanted
-     to save for the right format. */
-
-  nlm_tdata (abfd) = (struct nlm_obj_tdata *)
-    bfd_zalloc (abfd, sizeof (struct nlm_obj_tdata));
-  if (nlm_tdata (abfd) == NULL)
-    {
-      bfd_error = no_memory;
-      return (NULL);
-    }
-
   /* FIXME:  Any return(NULL) exits below here will leak memory (tdata).
      And a memory leak also means we lost the real tdata info we wanted
      to save, because it was in the leaked memory. */
 
   /* Swap in the rest of the fixed length header. */
 
-  i_fxdhdrp = nlm_fixed_header (abfd);
-  nlm_swap_fixed_header_in (abfd, &x_fxdhdr, i_fxdhdrp);
-
   if (!nlm_swap_variable_header_in (abfd)
       || !nlm_swap_auxiliary_headers_in (abfd)
       || !add_bfd_section (abfd, NLM_CODE_NAME,
@@ -165,10 +176,7 @@ DEFUN (nlm_object_p, (abfd), bfd * abfd)
                           (file_ptr) 0,
                           i_fxdhdrp -> uninitializedDataSize,
                           SEC_ALLOC))
-    {
-      bfd_error = wrong_format;
-      return (NULL);
-    }
+    goto got_wrong_format_error;
 
   if (nlm_fixed_header (abfd)->numberOfRelocationFixups != 0
       || nlm_fixed_header (abfd)->numberOfExternalReferences != 0)
@@ -183,6 +191,12 @@ DEFUN (nlm_object_p, (abfd), bfd * abfd)
     bfd_default_set_arch_mach (abfd, arch, (unsigned long) 0);
 
   return (abfd -> xvec);
+
+ got_wrong_format_error:
+  bfd_error = wrong_format;
+ got_no_match:
+  nlm_tdata (abfd) = preserved_tdata;
+  return (NULL);
 }
 
 /* Add a section to the bfd. */
@@ -210,124 +224,6 @@ DEFUN (add_bfd_section, (abfd, name, offset, size, flags),
   return (true);
 }
 
-/* Translate an NLM fixed length file header in external format into an NLM
-   file header in internal format. */
-
-static void
-DEFUN (nlm_swap_fixed_header_in, (abfd, src, dst),
-       bfd * abfd AND
-       Nlm_External_Fixed_Header * src AND
-       Nlm_Internal_Fixed_Header * dst)
-{
-  memcpy (dst -> signature, src -> signature, NLM_SIGNATURE_SIZE);
-  memcpy (dst -> moduleName, src -> moduleName, NLM_MODULE_NAME_SIZE);
-  dst -> version =
-    get_word (abfd, (bfd_byte *) src -> version);
-  dst -> codeImageOffset =
-    get_word (abfd, (bfd_byte *) src -> codeImageOffset);
-  dst -> codeImageSize =
-    get_word (abfd, (bfd_byte *) src -> codeImageSize);
-  dst -> dataImageOffset =
-    get_word (abfd, (bfd_byte *) src -> dataImageOffset);
-  dst -> dataImageSize =
-    get_word (abfd, (bfd_byte *) src -> dataImageSize);
-  dst -> uninitializedDataSize =
-    get_word (abfd, (bfd_byte *) src -> uninitializedDataSize);
-  dst -> customDataOffset =
-    get_word (abfd, (bfd_byte *) src -> customDataOffset);
-  dst -> customDataSize =
-    get_word (abfd, (bfd_byte *) src -> customDataSize);
-  dst -> moduleDependencyOffset =
-    get_word (abfd, (bfd_byte *) src -> moduleDependencyOffset);
-  dst -> numberOfModuleDependencies =
-    get_word (abfd, (bfd_byte *) src -> numberOfModuleDependencies);
-  dst -> relocationFixupOffset =
-    get_word (abfd, (bfd_byte *) src -> relocationFixupOffset);
-  dst -> numberOfRelocationFixups =
-    get_word (abfd, (bfd_byte *) src -> numberOfRelocationFixups);
-  dst -> externalReferencesOffset =
-    get_word (abfd, (bfd_byte *) src -> externalReferencesOffset);
-  dst -> numberOfExternalReferences =
-    get_word (abfd, (bfd_byte *) src -> numberOfExternalReferences);
-  dst -> publicsOffset =
-    get_word (abfd, (bfd_byte *) src -> publicsOffset);
-  dst -> numberOfPublics =
-    get_word (abfd, (bfd_byte *) src -> numberOfPublics);
-  dst -> debugInfoOffset =
-    get_word (abfd, (bfd_byte *) src -> debugInfoOffset);
-  dst -> numberOfDebugRecords =
-    get_word (abfd, (bfd_byte *) src -> numberOfDebugRecords);
-  dst -> codeStartOffset =
-    get_word (abfd, (bfd_byte *) src -> codeStartOffset);
-  dst -> exitProcedureOffset =
-    get_word (abfd, (bfd_byte *) src -> exitProcedureOffset);
-  dst -> checkUnloadProcedureOffset =
-    get_word (abfd, (bfd_byte *) src -> checkUnloadProcedureOffset);
-  dst -> moduleType =
-    get_word (abfd, (bfd_byte *) src -> moduleType);
-  dst -> flags = 
-    get_word (abfd, (bfd_byte *) src -> flags);
-}
-
-/* Translate an NLM fixed length file header in internal format into
-   an NLM file header in external format. */
-
-static void
-DEFUN (nlm_swap_fixed_header_out, (abfd, src, dst),
-       bfd * abfd AND
-       Nlm_Internal_Fixed_Header * src AND
-       Nlm_External_Fixed_Header * dst)
-{
-  memcpy (dst -> signature, src -> signature, NLM_SIGNATURE_SIZE);
-  memcpy (dst -> moduleName, src -> moduleName, NLM_MODULE_NAME_SIZE);
-  put_word (abfd, (bfd_vma) src -> version,
-           (bfd_byte *) dst -> version);
-  put_word (abfd, (bfd_vma) src -> codeImageOffset,
-           (bfd_byte *) dst -> codeImageOffset);
-  put_word (abfd, (bfd_vma) src -> codeImageSize,
-           (bfd_byte *) dst -> codeImageSize);
-  put_word (abfd, (bfd_vma) src -> dataImageOffset,
-           (bfd_byte *) dst -> dataImageOffset);
-  put_word (abfd, (bfd_vma) src -> dataImageSize,
-           (bfd_byte *) dst -> dataImageSize);
-  put_word (abfd, (bfd_vma) src -> uninitializedDataSize,
-           (bfd_byte *) dst -> uninitializedDataSize);
-  put_word (abfd, (bfd_vma) src -> customDataOffset,
-           (bfd_byte *) dst -> customDataOffset);
-  put_word (abfd, (bfd_vma) src -> customDataSize,
-           (bfd_byte *) dst -> customDataSize);
-  put_word (abfd, (bfd_vma) src -> moduleDependencyOffset,
-           (bfd_byte *) dst -> moduleDependencyOffset);
-  put_word (abfd, (bfd_vma) src -> numberOfModuleDependencies,
-           (bfd_byte *) dst -> numberOfModuleDependencies);
-  put_word (abfd, (bfd_vma) src -> relocationFixupOffset,
-           (bfd_byte *) dst -> relocationFixupOffset);
-  put_word (abfd, (bfd_vma) src -> numberOfRelocationFixups,
-           (bfd_byte *) dst -> numberOfRelocationFixups);
-  put_word (abfd, (bfd_vma) src -> externalReferencesOffset,
-           (bfd_byte *) dst -> externalReferencesOffset);
-  put_word (abfd, (bfd_vma) src -> numberOfExternalReferences,
-           (bfd_byte *) dst -> numberOfExternalReferences);
-  put_word (abfd, (bfd_vma) src -> publicsOffset,
-           (bfd_byte *) dst -> publicsOffset);
-  put_word (abfd, (bfd_vma) src -> numberOfPublics,
-           (bfd_byte *) dst -> numberOfPublics);
-  put_word (abfd, (bfd_vma) src -> debugInfoOffset,
-           (bfd_byte *) dst -> debugInfoOffset);
-  put_word (abfd, (bfd_vma) src -> numberOfDebugRecords,
-           (bfd_byte *) dst -> numberOfDebugRecords);
-  put_word (abfd, (bfd_vma) src -> codeStartOffset,
-           (bfd_byte *) dst -> codeStartOffset);
-  put_word (abfd, (bfd_vma) src -> exitProcedureOffset,
-           (bfd_byte *) dst -> exitProcedureOffset);
-  put_word (abfd, (bfd_vma) src -> checkUnloadProcedureOffset,
-           (bfd_byte *) dst -> checkUnloadProcedureOffset);
-  put_word (abfd, (bfd_vma) src -> moduleType,
-           (bfd_byte *) dst -> moduleType);
-  put_word (abfd, (bfd_vma) src -> flags,
-           (bfd_byte *) dst -> flags);
-}
-
 /* Read and swap in the variable length header.  All the fields must
    exist in the NLM, and must exist in the order they are read here. */
 
@@ -537,7 +433,7 @@ static boolean
 DEFUN (nlm_swap_auxiliary_headers_in, (abfd),
        bfd * abfd)
 {
-  unsigned char tempstr [16];
+  char tempstr [16];
   long position;
 
   for (;;)
@@ -623,6 +519,10 @@ DEFUN (nlm_swap_auxiliary_headers_in, (abfd),
            get_word (abfd, (bfd_byte *) thdr.sharedPublicsOffset);
          nlm_extended_header (abfd) -> sharedPublicsCount =
            get_word (abfd, (bfd_byte *) thdr.sharedPublicsCount);
+         nlm_extended_header (abfd) -> sharedDebugRecordOffset =
+           get_word (abfd, (bfd_byte *) thdr.sharedDebugRecordOffset);
+         nlm_extended_header (abfd) -> sharedDebugRecordCount =
+           get_word (abfd, (bfd_byte *) thdr.sharedDebugRecordCount);
          nlm_extended_header (abfd) -> SharedInitializationOffset =
            get_word (abfd, (bfd_byte *) thdr.sharedInitializationOffset);
          nlm_extended_header (abfd) -> SharedExitProcedureOffset =
@@ -661,7 +561,6 @@ DEFUN (nlm_swap_auxiliary_headers_in, (abfd),
        }
       else if (strncmp (tempstr, "CoPyRiGhT=", 10) == 0)
        {
-         Nlm_External_Copyright_Header thdr;
          if (bfd_read ((PTR) &nlm_copyright_header (abfd)->stamp,
                        sizeof (nlm_copyright_header (abfd)->stamp),
                        1, abfd)
@@ -805,6 +704,12 @@ nlm_swap_auxiliary_headers_out (abfd)
       put_word (abfd,
                (bfd_vma) nlm_extended_header (abfd) -> sharedPublicsCount,
                (bfd_byte *) thdr.sharedPublicsCount);
+      put_word (abfd,
+               (bfd_vma) nlm_extended_header (abfd) -> sharedDebugRecordOffset,
+               (bfd_byte *) thdr.sharedDebugRecordOffset);
+      put_word (abfd,
+               (bfd_vma) nlm_extended_header (abfd) -> sharedDebugRecordCount,
+               (bfd_byte *) thdr.sharedDebugRecordCount);
       put_word (abfd,
                (bfd_vma) nlm_extended_header (abfd) -> SharedInitializationOffset,
                (bfd_byte *) thdr.sharedInitializationOffset);
@@ -1026,10 +931,9 @@ nlm_slurp_symbol_table (abfd)
   nlm_symbol_type *sym;                        /* Pointer to current bfd symbol */
   unsigned char symlength;             /* Symbol length read into here */
   unsigned char symtype;               /* Type of debugging symbol */
-  bfd_size_type rcount;                        /* Number of relocs */
   bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Symbol offsets read into here */
-  boolean (*read_reloc_func) PARAMS ((bfd *, nlm_symbol_type *, asection **,
-                                     arelent *));
+  boolean (*read_import_func) PARAMS ((bfd *, nlm_symbol_type *));
+  boolean (*set_public_section_func) PARAMS ((bfd *, nlm_symbol_type *));
 
   if (nlm_get_symbols (abfd) != NULL)
     return (true);
@@ -1066,6 +970,7 @@ nlm_slurp_symbol_table (abfd)
      termination of the loop leaves the symcount correct for the symbols that
      were read. */
 
+  set_public_section_func = nlm_set_public_section_func (abfd);
   symcount = i_fxdhdrp -> numberOfPublics;
   while (abfd -> symcount < symcount)
     {
@@ -1083,6 +988,8 @@ nlm_slurp_symbol_table (abfd)
          bfd_error = system_call_error;
          return (false);
        }
+      /* Cast away const.  */
+      ((char *) (sym -> symbol.name))[symlength] = '\0';
       if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
        {
          bfd_error = system_call_error;
@@ -1090,17 +997,27 @@ nlm_slurp_symbol_table (abfd)
        }
       sym -> symbol.flags = BSF_GLOBAL | BSF_EXPORT;
       sym -> symbol.value = get_word (abfd, temp);
-      if (sym -> symbol.value & NLM_HIBIT)
+      if (set_public_section_func)
        {
-         sym -> symbol.value &= ~NLM_HIBIT;
-         sym -> symbol.flags |= BSF_FUNCTION;
-         sym -> symbol.section =
-           bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+         /* Most backends can use the code below, but unfortunately
+            some use a different scheme.  */
+         if ((*set_public_section_func) (abfd, sym) == false)
+           return false;
        }
       else
        {
-         sym -> symbol.section =
-           bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
+         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 -> rcnt = 0;
       abfd -> symcount++;
@@ -1137,6 +1054,8 @@ nlm_slurp_symbol_table (abfd)
              bfd_error = system_call_error;
              return (false);
            }
+         /* Cast away const.  */
+         ((char *) (sym -> symbol.name))[symlength] = '\0';
          sym -> symbol.flags = BSF_LOCAL;
          sym -> symbol.value = get_word (abfd, temp);
          if (symtype == 0)
@@ -1163,8 +1082,8 @@ nlm_slurp_symbol_table (abfd)
   /* Read in the import records.  We can only do this if we know how
      to read relocs for this target.  */
 
-  read_reloc_func = nlm_read_reloc_func (abfd);
-  if (read_reloc_func != NULL)
+  read_import_func = nlm_read_import_func (abfd);
+  if (read_import_func != NULL)
     {
       if (bfd_seek (abfd, i_fxdhdrp -> externalReferencesOffset, SEEK_SET)
          == -1)
@@ -1176,50 +1095,10 @@ nlm_slurp_symbol_table (abfd)
       symcount += i_fxdhdrp -> numberOfExternalReferences;
       while (abfd -> symcount < symcount)
        {
-         struct nlm_relent *nlm_relocs;
-
-         if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
-             != sizeof (symlength))
-           {
-             bfd_error = system_call_error;
-             return (false);
-           }
-         sym -> symbol.the_bfd = abfd;
-         sym -> symbol.name = bfd_alloc (abfd, symlength + 1);
-         if (bfd_read ((PTR) sym -> symbol.name, symlength, 1, abfd)
-             != symlength)
-           {
-             bfd_error = system_call_error;
-             return (false);
-           }
-         sym -> symbol.flags = 0;
-         sym -> symbol.value = 0;
-         sym -> symbol.section = &bfd_und_section;
-         if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
-           {
-             bfd_error = system_call_error;
-             return (false);
-           }
-         rcount = get_word (abfd, temp);
-         nlm_relocs = ((struct nlm_relent *)
-                       bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
-         sym -> relocs = nlm_relocs;
-         sym -> rcnt = 0;
-         while (sym -> rcnt < rcount)
-           {
-             asection *section;
-
-             if ((*read_reloc_func) (abfd, sym, &section,
-                                     &nlm_relocs -> reloc)
-                 == false)
-               return false;
-             nlm_relocs -> section = section;
-             nlm_relocs++;
-             sym -> rcnt++;
-           }
-
-         abfd -> symcount++;
+         if ((*read_import_func) (abfd, sym) == false)
+           return false;
          sym++;
+         abfd->symcount++;
        }
     }
 
@@ -1444,7 +1323,7 @@ nlm_compute_section_file_positions (abfd)
   abfd->output_has_begun = true;
 
   /* The fixed header.  */
-  sofar = sizeof (Nlm_External_Fixed_Header);
+  sofar = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
 
   /* The variable header.  */
   sofar += (sizeof (nlm_variable_header (abfd)->descriptionLength)
@@ -1644,12 +1523,6 @@ nlm_set_section_contents (abfd, section, location, offset, count)
 /* We need to sort a list of relocs associated with sections when we
    write out the external relocs.  */
 
-struct reloc_and_sec
-{
-  arelent *rel;
-  asection *sec;
-};
-
 static int
 nlm_external_reloc_compare (p1, p2)
      const void *p1;
@@ -1694,20 +1567,23 @@ boolean
 nlm_write_object_contents (abfd)
      bfd *abfd;
 {
-  Nlm_External_Fixed_Header fixed_header;
   asection *sec;
-  boolean (*write_reloc_func) PARAMS ((bfd *, asection *, arelent *));
+  boolean (*write_import_func) PARAMS ((bfd *, asection *, arelent *));
   bfd_size_type external_reloc_count, internal_reloc_count, i, c;
   struct reloc_and_sec *external_relocs;
   asymbol **sym_ptr_ptr;
   file_ptr last;
+  boolean (*write_prefix_func) PARAMS ((bfd *));
+  unsigned char *fixed_header = alloca (nlm_fixed_header_size (abfd));
 
   if (abfd->output_has_begun == false
       && nlm_compute_section_file_positions (abfd) == false)
     return false;
 
   /* Write out the variable length headers.  */
-  if (bfd_seek (abfd, sizeof (Nlm_External_Fixed_Header), SEEK_SET) != 0)
+  if (bfd_seek (abfd,
+               nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd),
+               SEEK_SET) != 0)
     {
       bfd_error = system_call_error;
       return false;
@@ -1738,7 +1614,7 @@ nlm_write_object_contents (abfd)
   /* The format of the relocation entries is dependent upon the
      particular target.  We use an external routine to write the reloc
      out.  */
-  write_reloc_func = nlm_write_reloc_func (abfd);
+  write_import_func = nlm_write_import_func (abfd);
 
   /* Write out the internal relocation fixups.  While we're looping
      over the relocs, we also count the external relocs, which is
@@ -1753,15 +1629,12 @@ nlm_write_object_contents (abfd)
        continue;
 
       /* We can only represent relocs within a code or data    
-        section.  */
+        section.  We ignore them for a debugging section.  */
       if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0)
-       {
-         bfd_error = invalid_operation;
-         return false;
-       }
+       continue;
 
-      /* We need to know how to write out relocs.  */
-      if (write_reloc_func == NULL)
+      /* We need to know how to write out imports */
+      if (write_import_func == NULL)
        {
          bfd_error = invalid_operation;
          return false;
@@ -1780,7 +1653,7 @@ nlm_write_object_contents (abfd)
          if (bfd_get_section (sym) != &bfd_und_section)
            {
              ++internal_reloc_count;
-             if ((*write_reloc_func) (abfd, sec, rel) == false)
+             if ((*write_import_func) (abfd, sec, rel) == false)
                return false;
            }
          else
@@ -1843,24 +1716,13 @@ nlm_write_object_contents (abfd)
     {
       arelent *rel;
       asymbol *sym;
-      bfd_byte len;
       bfd_size_type j, cnt;
-      bfd_byte temp[NLM_TARGET_LONG_SIZE];
 
       ++c;
 
       rel = external_relocs[i].rel;
       sym = *rel->sym_ptr_ptr;
 
-      len = strlen (sym->name);
-      if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd)
-          != sizeof (bfd_byte))
-         || bfd_write (sym->name, len, 1, abfd) != len)
-       {
-         bfd_error = system_call_error;
-         return false;
-       }
-
       cnt = 0;
       for (j = i;
           (j < external_reloc_count
@@ -1868,30 +1730,25 @@ nlm_write_object_contents (abfd)
           j++)
        ++cnt;
 
-      put_word (abfd, (bfd_vma) cnt, temp);
-      if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
-       {
-         bfd_error = system_call_error;
-         return false;
-       }
+      if ((*nlm_write_external_func (abfd)) (abfd, cnt, sym,
+                                            &external_relocs[i])
+         == false)
+       return false;
 
-      while (cnt-- != 0)
-       {
-         if ((*write_reloc_func) (abfd, external_relocs[i].sec,
-                                  external_relocs[i].rel) == false)
-           return false;
-         ++i;
-       }
+      i += cnt;
     }
+
   nlm_fixed_header (abfd)->numberOfExternalReferences = c;
 
   /* Write out the public symbols (exports).  */
   sym_ptr_ptr = bfd_get_outsymbols (abfd);
   if (sym_ptr_ptr != (asymbol **) NULL)
     {
+      bfd_vma (*get_public_offset_func) PARAMS ((bfd *, asymbol *));
       asymbol **sym_end;
 
       nlm_fixed_header (abfd)->publicsOffset = bfd_tell (abfd);
+      get_public_offset_func = nlm_get_public_offset_func (abfd);
       c = 0;
       sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
       for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
@@ -1918,24 +1775,33 @@ nlm_write_object_contents (abfd)
              return false;
            }
 
-         offset = bfd_asymbol_value (sym);
-         sec = sym->section;
-         if (sec->flags & SEC_CODE)
-           {
-             offset -= nlm_get_text_low (abfd);
-             offset |= NLM_HIBIT;
-           }
-         else if (sec->flags & (SEC_DATA | SEC_ALLOC))
+         if (get_public_offset_func)
            {
-             /* SEC_ALLOC is for the .bss section.  */
-             offset -= nlm_get_data_low (abfd);
+             /* Most backends can use the code below, but
+                unfortunately some use a different scheme.  */
+             offset = (*get_public_offset_func) (abfd, sym);
            }
          else
            {
-             /* We can't handle an exported symbol that is not in the
-                code or data segment.  */
-             bfd_error = invalid_operation;
-             return false;
+             offset = bfd_asymbol_value (sym);
+             sec = sym->section;
+             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_error = invalid_operation;
+                 return false;
+               }
            }
 
          put_word (abfd, offset, temp);
@@ -1983,17 +1849,16 @@ nlm_write_object_contents (abfd)
 
              ++c;
 
-             offset = bfd_asymbol_value (sym);
+             offset = sym->value;
              sec = sym->section;
              if (sec->flags & SEC_CODE)
+               type = 1;
+             else if (sec->flags & SEC_DATA)
+               type = 0;
+             else if (sec->flags & SEC_ALLOC)
                {
-                 offset -= nlm_get_text_low (abfd);
-                 type = 1;
-               }
-             else if (sec->flags & (SEC_DATA | SEC_ALLOC))
-               {
-                 offset -= nlm_get_data_low (abfd);
                  type = 0;
+                 offset += nlm_fixed_header (abfd)->dataImageSize;
                }
              else
                type = 2;
@@ -2048,7 +1913,7 @@ nlm_write_object_contents (abfd)
 
   /* At this point everything has been written out except the fixed
      header.  */
-  memcpy (nlm_fixed_header (abfd)->signature, NLM_SIGNATURE,
+  memcpy (nlm_fixed_header (abfd)->signature, nlm_signature (abfd),
          NLM_SIGNATURE_SIZE);
   nlm_fixed_header (abfd)->version = NLM_HEADER_VERSION;
   nlm_fixed_header (abfd)->codeStartOffset =
@@ -2063,10 +1928,21 @@ nlm_write_object_contents (abfd)
     nlm_fixed_header (abfd)->checkUnloadProcedureOffset -=
       nlm_get_text_low (abfd);
 
-  nlm_swap_fixed_header_out (abfd, nlm_fixed_header (abfd), &fixed_header);
-  if (bfd_seek (abfd, 0, SEEK_SET) != 0
-      || (bfd_write (&fixed_header, sizeof fixed_header, 1, abfd)
-         != sizeof fixed_header))
+  if (bfd_seek (abfd, 0, SEEK_SET) != 0)
+    return false;
+    
+  write_prefix_func = nlm_write_prefix_func (abfd);
+  if (write_prefix_func)
+    {
+      if ((*write_prefix_func) (abfd) == false)
+       return false;
+    }
+
+  BFD_ASSERT (bfd_tell (abfd) == nlm_optional_prefix_size (abfd));
+
+  nlm_swap_fixed_header_out (abfd, nlm_fixed_header (abfd), fixed_header);
+  if (bfd_write (fixed_header, nlm_fixed_header_size (abfd), 1, abfd)
+      != nlm_fixed_header_size (abfd))
     {
       bfd_error = system_call_error;
       return false;