Automatic date update in version.in
[binutils-gdb.git] / bfd / som.c
index 02a99a336073adfc0242945c1122143df4e30702..dde1f1f8c47906566a25b7c08dc48d0b112cd612 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-2019 Free Software Foundation, Inc.
+   Copyright (C) 1990-2023 Free Software Foundation, Inc.
 
    Contributed by the Center for Software Science at the
    University of Utah.
@@ -22,7 +22,6 @@
    02110-1301, USA.  */
 
 #include "sysdep.h"
-#include "alloca-conf.h"
 #include "bfd.h"
 #include "libiberty.h"
 #include "libbfd.h"
 
 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 bool som_mkobject (bfd *);
+static bool som_is_space (asection *);
+static bool som_is_subspace (asection *);
 static int compare_subspaces (const void *, const void *);
-static unsigned long som_compute_checksum (struct som_external_header *);
-static bfd_boolean som_build_and_write_symbol_table (bfd *);
+static uint32_t som_compute_checksum (struct som_external_header *);
+static bool 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.  */
@@ -114,7 +113,7 @@ static unsigned int som_slurp_symbol_table (bfd *);
 
    Note one side effect of using a R_PREV_FIXUP is the relocation that
    is being repeated moves to the front of the queue.  */
-struct reloc_queue
+static struct reloc_queue
 {
   unsigned char *reloc;
   unsigned int size;
@@ -636,267 +635,268 @@ static const int comp3_opcodes[] =
 #define R_SHORT_PCREL_MODE 0x3e
 #endif
 
-#define SOM_HOWTO(TYPE, NAME)  \
-  HOWTO(TYPE, 0, 0, 32, FALSE, 0, 0, hppa_som_reloc, NAME, FALSE, 0, 0, FALSE)
+#define SOM_HOWTO(SIZE, TYPE)  \
+  HOWTO(TYPE, 0, SIZE, 32, false, 0, 0, hppa_som_reloc, \
+       #TYPE, false, 0, 0, false)
 
 static reloc_howto_type som_hppa_howto_table[] =
 {
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
-  SOM_HOWTO (R_ZEROES, "R_ZEROES"),
-  SOM_HOWTO (R_ZEROES, "R_ZEROES"),
-  SOM_HOWTO (R_UNINIT, "R_UNINIT"),
-  SOM_HOWTO (R_UNINIT, "R_UNINIT"),
-  SOM_HOWTO (R_RELOCATION, "R_RELOCATION"),
-  SOM_HOWTO (R_DATA_ONE_SYMBOL, "R_DATA_ONE_SYMBOL"),
-  SOM_HOWTO (R_DATA_ONE_SYMBOL, "R_DATA_ONE_SYMBOL"),
-  SOM_HOWTO (R_DATA_PLABEL, "R_DATA_PLABEL"),
-  SOM_HOWTO (R_DATA_PLABEL, "R_DATA_PLABEL"),
-  SOM_HOWTO (R_SPACE_REF, "R_SPACE_REF"),
-  SOM_HOWTO (R_REPEATED_INIT, "REPEATED_INIT"),
-  SOM_HOWTO (R_REPEATED_INIT, "REPEATED_INIT"),
-  SOM_HOWTO (R_REPEATED_INIT, "REPEATED_INIT"),
-  SOM_HOWTO (R_REPEATED_INIT, "REPEATED_INIT"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
-  SOM_HOWTO (R_SHORT_PCREL_MODE, "R_SHORT_PCREL_MODE"),
-  SOM_HOWTO (R_LONG_PCREL_MODE, "R_LONG_PCREL_MODE"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  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_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_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_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_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_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_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_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_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"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_DLT_REL, "R_DLT_REL"),
-  SOM_HOWTO (R_DLT_REL, "R_DLT_REL"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_MILLI_REL, "R_MILLI_REL"),
-  SOM_HOWTO (R_MILLI_REL, "R_MILLI_REL"),
-  SOM_HOWTO (R_CODE_PLABEL, "R_CODE_PLABEL"),
-  SOM_HOWTO (R_CODE_PLABEL, "R_CODE_PLABEL"),
-  SOM_HOWTO (R_BREAKPOINT, "R_BREAKPOINT"),
-  SOM_HOWTO (R_ENTRY, "R_ENTRY"),
-  SOM_HOWTO (R_ENTRY, "R_ENTRY"),
-  SOM_HOWTO (R_ALT_ENTRY, "R_ALT_ENTRY"),
-  SOM_HOWTO (R_EXIT, "R_EXIT"),
-  SOM_HOWTO (R_BEGIN_TRY, "R_BEGIN_TRY"),
-  SOM_HOWTO (R_END_TRY, "R_END_TRY"),
-  SOM_HOWTO (R_END_TRY, "R_END_TRY"),
-  SOM_HOWTO (R_END_TRY, "R_END_TRY"),
-  SOM_HOWTO (R_BEGIN_BRTAB, "R_BEGIN_BRTAB"),
-  SOM_HOWTO (R_END_BRTAB, "R_END_BRTAB"),
-  SOM_HOWTO (R_STATEMENT, "R_STATEMENT"),
-  SOM_HOWTO (R_STATEMENT, "R_STATEMENT"),
-  SOM_HOWTO (R_STATEMENT, "R_STATEMENT"),
-  SOM_HOWTO (R_DATA_EXPR, "R_DATA_EXPR"),
-  SOM_HOWTO (R_CODE_EXPR, "R_CODE_EXPR"),
-  SOM_HOWTO (R_FSEL, "R_FSEL"),
-  SOM_HOWTO (R_LSEL, "R_LSEL"),
-  SOM_HOWTO (R_RSEL, "R_RSEL"),
-  SOM_HOWTO (R_N_MODE, "R_N_MODE"),
-  SOM_HOWTO (R_S_MODE, "R_S_MODE"),
-  SOM_HOWTO (R_D_MODE, "R_D_MODE"),
-  SOM_HOWTO (R_R_MODE, "R_R_MODE"),
-  SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
-  SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
-  SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
-  SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
-  SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
-  SOM_HOWTO (R_TRANSLATED, "R_TRANSLATED"),
-  SOM_HOWTO (R_AUX_UNWIND, "R_AUX_UNWIND"),
-  SOM_HOWTO (R_COMP1, "R_COMP1"),
-  SOM_HOWTO (R_COMP2, "R_COMP2"),
-  SOM_HOWTO (R_COMP3, "R_COMP3"),
-  SOM_HOWTO (R_PREV_FIXUP, "R_PREV_FIXUP"),
-  SOM_HOWTO (R_PREV_FIXUP, "R_PREV_FIXUP"),
-  SOM_HOWTO (R_PREV_FIXUP, "R_PREV_FIXUP"),
-  SOM_HOWTO (R_PREV_FIXUP, "R_PREV_FIXUP"),
-  SOM_HOWTO (R_SEC_STMT, "R_SEC_STMT"),
-  SOM_HOWTO (R_N0SEL, "R_N0SEL"),
-  SOM_HOWTO (R_N1SEL, "R_N1SEL"),
-  SOM_HOWTO (R_LINETAB, "R_LINETAB"),
-  SOM_HOWTO (R_LINETAB_ESC, "R_LINETAB_ESC"),
-  SOM_HOWTO (R_LTP_OVERRIDE, "R_LTP_OVERRIDE"),
-  SOM_HOWTO (R_COMMENT, "R_COMMENT"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED"),
-  SOM_HOWTO (R_RESERVED, "R_RESERVED")
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_NO_RELOCATION),
+  SOM_HOWTO (0, R_ZEROES),
+  SOM_HOWTO (0, R_ZEROES),
+  SOM_HOWTO (0, R_UNINIT),
+  SOM_HOWTO (0, R_UNINIT),
+  SOM_HOWTO (4, R_RELOCATION),
+  SOM_HOWTO (4, R_DATA_ONE_SYMBOL),
+  SOM_HOWTO (4, R_DATA_ONE_SYMBOL),
+  SOM_HOWTO (4, R_DATA_PLABEL),
+  SOM_HOWTO (4, R_DATA_PLABEL),
+  SOM_HOWTO (4, R_SPACE_REF),
+  SOM_HOWTO (0, R_REPEATED_INIT),
+  SOM_HOWTO (0, R_REPEATED_INIT),
+  SOM_HOWTO (0, R_REPEATED_INIT),
+  SOM_HOWTO (0, R_REPEATED_INIT),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (4, R_PCREL_CALL),
+  SOM_HOWTO (0, R_SHORT_PCREL_MODE),
+  SOM_HOWTO (0, R_LONG_PCREL_MODE),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (4, R_ABS_CALL),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DP_RELATIVE),
+  SOM_HOWTO (4, R_DATA_GPREL),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (4, R_DLT_REL),
+  SOM_HOWTO (4, R_DLT_REL),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (4, R_CODE_ONE_SYMBOL),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (4, R_MILLI_REL),
+  SOM_HOWTO (4, R_MILLI_REL),
+  SOM_HOWTO (4, R_CODE_PLABEL),
+  SOM_HOWTO (4, R_CODE_PLABEL),
+  SOM_HOWTO (4, R_BREAKPOINT),
+  SOM_HOWTO (0, R_ENTRY),
+  SOM_HOWTO (0, R_ENTRY),
+  SOM_HOWTO (0, R_ALT_ENTRY),
+  SOM_HOWTO (0, R_EXIT),
+  SOM_HOWTO (0, R_BEGIN_TRY),
+  SOM_HOWTO (0, R_END_TRY),
+  SOM_HOWTO (0, R_END_TRY),
+  SOM_HOWTO (0, R_END_TRY),
+  SOM_HOWTO (0, R_BEGIN_BRTAB),
+  SOM_HOWTO (0, R_END_BRTAB),
+  SOM_HOWTO (0, R_STATEMENT),
+  SOM_HOWTO (0, R_STATEMENT),
+  SOM_HOWTO (0, R_STATEMENT),
+  SOM_HOWTO (4, R_DATA_EXPR),
+  SOM_HOWTO (4, R_CODE_EXPR),
+  SOM_HOWTO (0, R_FSEL),
+  SOM_HOWTO (0, R_LSEL),
+  SOM_HOWTO (0, R_RSEL),
+  SOM_HOWTO (0, R_N_MODE),
+  SOM_HOWTO (0, R_S_MODE),
+  SOM_HOWTO (0, R_D_MODE),
+  SOM_HOWTO (0, R_R_MODE),
+  SOM_HOWTO (0, R_DATA_OVERRIDE),
+  SOM_HOWTO (0, R_DATA_OVERRIDE),
+  SOM_HOWTO (0, R_DATA_OVERRIDE),
+  SOM_HOWTO (0, R_DATA_OVERRIDE),
+  SOM_HOWTO (0, R_DATA_OVERRIDE),
+  SOM_HOWTO (0, R_TRANSLATED),
+  SOM_HOWTO (0, R_AUX_UNWIND),
+  SOM_HOWTO (0, R_COMP1),
+  SOM_HOWTO (0, R_COMP2),
+  SOM_HOWTO (0, R_COMP3),
+  SOM_HOWTO (0, R_PREV_FIXUP),
+  SOM_HOWTO (0, R_PREV_FIXUP),
+  SOM_HOWTO (0, R_PREV_FIXUP),
+  SOM_HOWTO (0, R_PREV_FIXUP),
+  SOM_HOWTO (0, R_SEC_STMT),
+  SOM_HOWTO (0, R_N0SEL),
+  SOM_HOWTO (0, R_N1SEL),
+  SOM_HOWTO (0, R_LINETAB),
+  SOM_HOWTO (0, R_LINETAB_ESC),
+  SOM_HOWTO (0, R_LTP_OVERRIDE),
+  SOM_HOWTO (0, R_COMMENT),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED),
+  SOM_HOWTO (0, R_RESERVED)
 };
 
 /* Initialize the SOM relocation queue.  By definition the queue holds
@@ -1425,7 +1425,7 @@ hppa_som_gen_reloc_type (bfd *abfd,
       /* The difference of two symbols needs *very* special handling.  */
       if (sym_diff)
        {
-         bfd_size_type amt = sizeof (int);
+         size_t amt = sizeof (int);
 
          final_types[0] = bfd_alloc (abfd, amt);
          final_types[1] = bfd_alloc (abfd, amt);
@@ -1509,7 +1509,7 @@ hppa_som_gen_reloc_type (bfd *abfd,
       /* The difference of two symbols needs *very* special handling.  */
       if (sym_diff)
        {
-         bfd_size_type amt = sizeof (int);
+         size_t amt = sizeof (int);
 
          final_types[0] = bfd_alloc (abfd, amt);
          final_types[1] = bfd_alloc (abfd, amt);
@@ -1548,7 +1548,7 @@ hppa_som_gen_reloc_type (bfd *abfd,
        /* If we have short and long pcrel modes, then generate the proper
           mode selector, then the pcrel relocation.  Redundant selectors
           will be eliminated as the relocs are sized and emitted.  */
-       bfd_size_type amt = sizeof (int);
+       size_t amt = sizeof (int);
 
        final_types[0] = bfd_alloc (abfd, amt);
        if (!final_types[0])
@@ -1945,7 +1945,7 @@ som_swap_lst_header_in (struct som_external_lst_header *src,
 /* Perform some initialization for an object.  Save results of this
    initialization in the BFD.  */
 
-static const bfd_target *
+static bfd_cleanup
 som_object_setup (bfd *abfd,
                  struct som_header *file_hdrp,
                  struct som_exec_auxhdr *aux_hdrp,
@@ -2031,12 +2031,12 @@ som_object_setup (bfd *abfd,
          || (aux_hdrp->exec_entry & 0x3) != 0
          || ! found)
        {
-         bfd_get_start_address (abfd) = aux_hdrp->exec_flags;
+         abfd->start_address = aux_hdrp->exec_flags;
          obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_entry;
        }
       else
        {
-         bfd_get_start_address (abfd) = aux_hdrp->exec_entry + current_offset;
+         abfd->start_address = aux_hdrp->exec_entry + current_offset;
          obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_flags;
        }
     }
@@ -2044,7 +2044,7 @@ som_object_setup (bfd *abfd,
   obj_som_exec_data (abfd)->version_id = file_hdrp->version_id;
 
   bfd_default_set_arch_mach (abfd, bfd_arch_hppa, pa10);
-  bfd_get_symcount (abfd) = file_hdrp->symbol_total;
+  abfd->symcount = file_hdrp->symbol_total;
 
   /* Initialize the saved symbol table and string table to NULL.
      Save important offsets and sizes from the SOM header into
@@ -2060,7 +2060,7 @@ som_object_setup (bfd *abfd,
                                  + current_offset);
   obj_som_exec_data (abfd)->system_id = file_hdrp->system_id;
 
-  return abfd->xvec;
+  return _bfd_no_cleanup;
 }
 
 /* Convert all of the space and subspace info into BFD sections.  Each space
@@ -2069,28 +2069,30 @@ som_object_setup (bfd *abfd,
    BFD sections which correspond to spaces will overlap the sections for the
    associated subspaces.  */
 
-static bfd_boolean
+static bool
 setup_sections (bfd *abfd,
                struct som_header *file_hdr,
                unsigned long current_offset)
 {
-  char *space_strings;
+  char *space_strings = NULL;
   unsigned int space_index, i;
   unsigned int total_subspaces = 0;
   asection **subspace_sections = NULL;
   asection *section;
-  bfd_size_type amt;
+  size_t amt;
 
   /* First, read in space names.  */
   amt = file_hdr->space_strings_size;
-  space_strings = bfd_malloc (amt + 1);
-  if (space_strings == NULL && amt != 0)
-    goto error_return;
-
+  if (amt == (size_t) -1)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      goto error_return;
+    }
   if (bfd_seek (abfd, current_offset + file_hdr->space_strings_location,
                SEEK_SET) != 0)
     goto error_return;
-  if (bfd_bread (space_strings, amt, abfd) != amt)
+  space_strings = (char *) _bfd_malloc_and_read (abfd, amt + 1, amt);
+  if (space_strings == NULL)
     goto error_return;
   /* Make sure that the string table is NUL terminated.  */
   space_strings[amt] = 0;
@@ -2115,7 +2117,7 @@ setup_sections (bfd *abfd,
                    SEEK_SET) != 0)
        goto error_return;
       amt = sizeof ext_space;
-      if (bfd_bread (&ext_space, amt, abfd) != amt)
+      if (bfd_read (&ext_space, amt, abfd) != amt)
        goto error_return;
 
       som_swap_space_dictionary_in (&ext_space, &space);
@@ -2157,7 +2159,7 @@ setup_sections (bfd *abfd,
                    SEEK_SET) != 0)
        goto error_return;
       amt = sizeof ext_subspace;
-      if (bfd_bread (&ext_subspace, amt, abfd) != amt)
+      if (bfd_read (&ext_subspace, amt, abfd) != amt)
        goto error_return;
       /* Seek back to the start of the subspaces for loop below.  */
       if (bfd_seek (abfd,
@@ -2189,12 +2191,15 @@ setup_sections (bfd *abfd,
 
          /* Read in the next subspace.  */
          amt = sizeof ext_subspace;
-         if (bfd_bread (&ext_subspace, amt, abfd) != amt)
+         if (bfd_read (&ext_subspace, amt, abfd) != amt)
            goto error_return;
 
          som_swap_subspace_dictionary_in (&ext_subspace, &subspace);
 
          /* Setup the subspace name string.  */
+         if (subspace.name >= file_hdr->space_strings_size)
+           goto error_return;
+
          subspace_name = subspace.name + space_strings;
 
          amt = strlen (subspace_name) + 1;
@@ -2339,8 +2344,11 @@ setup_sections (bfd *abfd,
     }
   /* Now that we've read in all the subspace records, we need to assign
      a target index to each subspace.  */
-  amt = total_subspaces;
-  amt *= sizeof (asection *);
+  if (_bfd_mul_overflow (total_subspaces, sizeof (asection *), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      goto error_return;
+    }
   subspace_sections = bfd_malloc (amt);
   if (subspace_sections == NULL)
     goto error_return;
@@ -2361,27 +2369,20 @@ setup_sections (bfd *abfd,
   for (i = 0; i < total_subspaces; i++)
     subspace_sections[i]->target_index = i;
 
-  if (space_strings != NULL)
-    free (space_strings);
-
-  if (subspace_sections != NULL)
-    free (subspace_sections);
-
-  return TRUE;
+  free (space_strings);
+  free (subspace_sections);
+  return true;
 
  error_return:
-  if (space_strings != NULL)
-    free (space_strings);
-
-  if (subspace_sections != NULL)
-    free (subspace_sections);
-  return FALSE;
+  free (space_strings);
+  free (subspace_sections);
+  return false;
 }
 
 
 /* Read in a SOM object and make it into a BFD.  */
 
-static const bfd_target *
+static bfd_cleanup
 som_object_p (bfd *abfd)
 {
   struct som_external_header ext_file_hdr;
@@ -2390,12 +2391,12 @@ som_object_p (bfd *abfd)
   unsigned long current_offset = 0;
   struct som_external_lst_header ext_lst_header;
   struct som_external_som_entry ext_som_entry;
-  bfd_size_type amt;
+  size_t amt;
   unsigned int loc;
 #define ENTRY_SIZE sizeof (struct som_external_som_entry)
 
   amt = sizeof (struct som_external_header);
-  if (bfd_bread (&ext_file_hdr, amt, abfd) != amt)
+  if (bfd_read (&ext_file_hdr, amt, abfd) != amt)
     {
       if (bfd_get_error () != bfd_error_system_call)
        bfd_set_error (bfd_error_wrong_format);
@@ -2426,7 +2427,7 @@ som_object_p (bfd *abfd)
     case EXECLIBMAGIC:
       /* Read the lst header and determine where the SOM directory begins.  */
 
-      if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+      if (bfd_seek (abfd, 0, SEEK_SET) != 0)
        {
          if (bfd_get_error () != bfd_error_system_call)
            bfd_set_error (bfd_error_wrong_format);
@@ -2434,7 +2435,7 @@ som_object_p (bfd *abfd)
        }
 
       amt = sizeof (struct som_external_lst_header);
-      if (bfd_bread (&ext_lst_header, amt, abfd) != amt)
+      if (bfd_read (&ext_lst_header, amt, abfd) != amt)
        {
          if (bfd_get_error () != bfd_error_system_call)
            bfd_set_error (bfd_error_wrong_format);
@@ -2451,7 +2452,7 @@ som_object_p (bfd *abfd)
        }
 
       amt = ENTRY_SIZE;
-      if (bfd_bread (&ext_som_entry, amt, abfd) != amt)
+      if (bfd_read (&ext_som_entry, amt, abfd) != amt)
        {
          if (bfd_get_error () != bfd_error_system_call)
            bfd_set_error (bfd_error_wrong_format);
@@ -2469,7 +2470,7 @@ som_object_p (bfd *abfd)
 
       /* And finally, re-read the som header.  */
       amt = sizeof (struct som_external_header);
-      if (bfd_bread (&ext_file_hdr, amt, abfd) != amt)
+      if (bfd_read (&ext_file_hdr, amt, abfd) != amt)
        {
          if (bfd_get_error () != bfd_error_system_call)
            bfd_set_error (bfd_error_wrong_format);
@@ -2504,7 +2505,7 @@ som_object_p (bfd *abfd)
       if (aux_hdr_ptr == NULL)
        return NULL;
       amt = sizeof (struct som_external_exec_auxhdr);
-      if (bfd_bread (&ext_exec_auxhdr, amt, abfd) != amt)
+      if (bfd_read (&ext_exec_auxhdr, amt, abfd) != amt)
        {
          if (bfd_get_error () != bfd_error_system_call)
            bfd_set_error (bfd_error_wrong_format);
@@ -2526,31 +2527,31 @@ som_object_p (bfd *abfd)
 
 /* Create a SOM object.  */
 
-static bfd_boolean
+static bool
 som_mkobject (bfd *abfd)
 {
   /* Allocate memory to hold backend information.  */
   abfd->tdata.som_data = bfd_zalloc (abfd, (bfd_size_type) sizeof (struct som_data_struct));
   if (abfd->tdata.som_data == NULL)
-    return FALSE;
-  return TRUE;
+    return false;
+  return true;
 }
 
 /* Initialize some information in the file header.  This routine makes
    not attempt at doing the right thing for a full executable; it
    is only meant to handle relocatable objects.  */
 
-static bfd_boolean
+static bool
 som_prep_headers (bfd *abfd)
 {
   struct som_header *file_hdr;
   asection *section;
-  bfd_size_type amt = sizeof (struct som_header);
+  size_t amt = sizeof (struct som_header);
 
   /* Make and attach a file header to the BFD.  */
   file_hdr = bfd_zalloc (abfd, amt);
   if (file_hdr == NULL)
-    return FALSE;
+    return false;
   obj_som_file_hdr (abfd) = file_hdr;
 
   if (abfd->flags & (EXEC_P | DYNAMIC))
@@ -2559,7 +2560,7 @@ som_prep_headers (bfd *abfd)
       amt = sizeof (struct som_exec_auxhdr);
       obj_som_exec_hdr (abfd) = bfd_zalloc (abfd, amt);
       if (obj_som_exec_hdr (abfd) == NULL)
-       return FALSE;
+       return false;
 
       if (abfd->flags & D_PAGED)
        file_hdr->a_magic = DEMAND_MAGIC;
@@ -2601,7 +2602,7 @@ som_prep_headers (bfd *abfd)
          amt = sizeof (struct som_space_dictionary_record);
          som_section_data (section)->space_dict = bfd_zalloc (abfd, amt);
          if (som_section_data (section)->space_dict == NULL)
-           return FALSE;
+           return false;
          /* Set space attributes.  Note most attributes of SOM spaces
             are set based on the subspaces it contains.  */
          som_section_data (section)->space_dict->loader_fix_index = -1;
@@ -2623,7 +2624,7 @@ som_prep_headers (bfd *abfd)
          amt = sizeof (struct som_subspace_dictionary_record);
          som_section_data (section)->subspace_dict = bfd_zalloc (abfd, amt);
          if (som_section_data (section)->subspace_dict == NULL)
-           return FALSE;
+           return false;
 
          /* Set subspace attributes.  Basic stuff is done here, additional
             attributes are filled in later as more information becomes
@@ -2658,56 +2659,56 @@ som_prep_headers (bfd *abfd)
            som_section_data (section)->copy_data->dup_common;
        }
     }
-  return TRUE;
+  return true;
 }
 
 /* Return TRUE if the given section is a SOM space, FALSE otherwise.  */
 
-static bfd_boolean
+static bool
 som_is_space (asection *section)
 {
   /* If no copy data is available, then it's neither a space nor a
      subspace.  */
   if (som_section_data (section)->copy_data == NULL)
-    return FALSE;
+    return false;
 
   /* If the containing space isn't the same as the given section,
      then this isn't a space.  */
   if (som_section_data (section)->copy_data->container != section
       && (som_section_data (section)->copy_data->container->output_section
          != section))
-    return FALSE;
+    return false;
 
   /* OK.  Must be a space.  */
-  return TRUE;
+  return true;
 }
 
 /* Return TRUE if the given section is a SOM subspace, FALSE otherwise.  */
 
-static bfd_boolean
+static bool
 som_is_subspace (asection *section)
 {
   /* If no copy data is available, then it's neither a space nor a
      subspace.  */
   if (som_section_data (section)->copy_data == NULL)
-    return FALSE;
+    return false;
 
   /* If the containing space is the same as the given section,
      then this isn't a subspace.  */
   if (som_section_data (section)->copy_data->container == section
       || (som_section_data (section)->copy_data->container->output_section
          == section))
-    return FALSE;
+    return false;
 
   /* OK.  Must be a subspace.  */
-  return TRUE;
+  return true;
 }
 
 /* Return TRUE if the given space contains the given subspace.  It
    is safe to assume space really is a space, and subspace really
    is a subspace.  */
 
-static bfd_boolean
+static bool
 som_is_container (asection *space, asection *subspace)
 {
   return (som_section_data (subspace)->copy_data->container == space)
@@ -2795,13 +2796,16 @@ compare_subspaces (const void *arg1, const void *arg2)
 
 /* Perform various work in preparation for emitting the fixup stream.  */
 
-static void
+static bool
 som_prep_for_fixups (bfd *abfd, asymbol **syms, unsigned long num_syms)
 {
   unsigned long i;
   asection *section;
   asymbol **sorted_syms;
-  bfd_size_type amt;
+  size_t amt;
+
+  if (num_syms == 0)
+    return true;
 
   /* Most SOM relocations involving a symbol have a length which is
      dependent on the index of the symbol.  So symbols which are
@@ -2873,9 +2877,14 @@ som_prep_for_fixups (bfd *abfd, asymbol **syms, unsigned long num_syms)
 
   /* Sort a copy of the symbol table, rather than the canonical
      output symbol table.  */
-  amt = num_syms;
-  amt *= sizeof (asymbol *);
+  if (_bfd_mul_overflow (num_syms, sizeof (asymbol *), &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return false;
+    }
   sorted_syms = bfd_zalloc (abfd, amt);
+  if (sorted_syms == NULL)
+    return false;
   memcpy (sorted_syms, syms, num_syms * sizeof (asymbol *));
   qsort (sorted_syms, num_syms, sizeof (asymbol *), compare_syms);
   obj_som_sorted_syms (abfd) = sorted_syms;
@@ -2891,9 +2900,10 @@ som_prep_for_fixups (bfd *abfd, asymbol **syms, unsigned long num_syms)
       else
        som_symbol_data (sorted_syms[i])->index = i;
     }
+  return true;
 }
 
-static bfd_boolean
+static bool
 som_write_fixups (bfd *abfd,
                  unsigned long current_offset,
                  unsigned int *total_reloc_sizep)
@@ -2907,7 +2917,7 @@ som_write_fixups (bfd *abfd,
   unsigned int subspace_reloc_size = 0;
   unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
   asection *section = abfd->sections;
-  bfd_size_type amt;
+  size_t amt;
 
   memset (tmp_space, 0, SOM_TMP_BUFSIZE);
   p = tmp_space;
@@ -2924,15 +2934,17 @@ som_write_fixups (bfd *abfd,
       asection *subsection;
 
       /* Find a space.  */
-      while (!som_is_space (section))
+      while (section && !som_is_space (section))
        section = section->next;
+      if (!section)
+       break;
 
       /* Now iterate through each of its subspaces.  */
       for (subsection = abfd->sections;
           subsection != NULL;
           subsection = subsection->next)
        {
-         int reloc_offset;
+         unsigned int reloc_offset;
          unsigned int current_rounding_mode;
 #ifndef NO_PCREL_MODES
          unsigned int current_call_mode;
@@ -2962,7 +2974,7 @@ som_write_fixups (bfd *abfd,
             for this subspace in preparation for writing out its fixup
             stream.  */
          if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) != 0)
-           return FALSE;
+           return false;
 
          /* Buffer space has already been allocated.  Just perform some
             initialization here.  */
@@ -2983,6 +2995,31 @@ som_write_fixups (bfd *abfd,
              unsigned int skip;
              int sym_num;
 
+             if (bfd_reloc->address < reloc_offset)
+               {
+                 _bfd_error_handler
+                   /* xgettext:c-format */
+                   (_("%pB(%pA+%#" PRIx64 "): "
+                      "%s relocation offset out of order"),
+                    abfd, subsection, (uint64_t) bfd_reloc->address,
+                    bfd_reloc->howto->name);
+                 bfd_set_error (bfd_error_bad_value);
+                 return false;
+               }
+             if (!bfd_reloc_offset_in_range (bfd_reloc->howto,
+                                             abfd, subsection,
+                                             bfd_reloc->address))
+               {
+                 _bfd_error_handler
+                   /* xgettext:c-format */
+                   (_("%pB(%pA+%#" PRIx64 "): "
+                      "%s relocation offset out of range"),
+                    abfd, subsection, (uint64_t) bfd_reloc->address,
+                    bfd_reloc->howto->name);
+                 bfd_set_error (bfd_error_bad_value);
+                 return false;
+               }
+
              /* Get the symbol number.  Remember it's stored in a
                 special place for section symbols.  */
              if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
@@ -2994,14 +3031,16 @@ som_write_fixups (bfd *abfd,
                 then dump the current buffer contents now.  Also reinitialize
                 the relocation queue.
 
-                No single BFD relocation could ever translate into more
-                than 100 bytes of SOM relocations (20bytes is probably the
-                upper limit, but leave lots of space for growth).  */
-             if (p - tmp_space + 100 > SOM_TMP_BUFSIZE)
+                A single BFD relocation would probably only ever
+                translate into at most 20 bytes of SOM relocations.
+                However with fuzzed object files and resulting silly
+                values for "skip" below, som_reloc_skip can emit 262
+                bytes.  Leave lots of space for growth.  */
+             if (p - tmp_space + 512 > SOM_TMP_BUFSIZE)
                {
                  amt = p - tmp_space;
-                 if (bfd_bwrite ((void *) tmp_space, amt, abfd) != amt)
-                   return FALSE;
+                 if (bfd_write (tmp_space, amt, abfd) != amt)
+                   return false;
 
                  p = tmp_space;
                  som_initialize_reloc_queue (reloc_queue);
@@ -3013,42 +3052,8 @@ som_write_fixups (bfd *abfd,
              p = som_reloc_skip (abfd, skip, p,
                                  &subspace_reloc_size, reloc_queue);
 
-             /* Update reloc_offset for the next iteration.
-
-                Many relocations do not consume input bytes.  They
-                are markers, or set state necessary to perform some
-                later relocation.  */
-             switch (bfd_reloc->howto->type)
-               {
-               case R_ENTRY:
-               case R_ALT_ENTRY:
-               case R_EXIT:
-               case R_N_MODE:
-               case R_S_MODE:
-               case R_D_MODE:
-               case R_R_MODE:
-               case R_FSEL:
-               case R_LSEL:
-               case R_RSEL:
-               case R_COMP1:
-               case R_COMP2:
-               case R_BEGIN_BRTAB:
-               case R_END_BRTAB:
-               case R_BEGIN_TRY:
-               case R_END_TRY:
-               case R_N0SEL:
-               case R_N1SEL:
-#ifndef NO_PCREL_MODES
-               case R_SHORT_PCREL_MODE:
-               case R_LONG_PCREL_MODE:
-#endif
-                 reloc_offset = bfd_reloc->address;
-                 break;
-
-               default:
-                 reloc_offset = bfd_reloc->address + 4;
-                 break;
-               }
+             /* Update reloc_offset for the next iteration.  */
+             reloc_offset = bfd_reloc->address + bfd_reloc->howto->size;
 
              /* Now the actual relocation we care about.  */
              switch (bfd_reloc->howto->type)
@@ -3285,8 +3290,8 @@ som_write_fixups (bfd *abfd,
 
          /* Scribble out the relocations.  */
          amt = p - tmp_space;
-         if (bfd_bwrite ((void *) tmp_space, amt, abfd) != amt)
-           return FALSE;
+         if (bfd_write (tmp_space, amt, abfd) != amt)
+           return false;
          p = tmp_space;
 
          total_reloc_size += subspace_reloc_size;
@@ -3296,134 +3301,150 @@ som_write_fixups (bfd *abfd,
       section = section->next;
     }
   *total_reloc_sizep = total_reloc_size;
-  return TRUE;
+  return true;
+}
+
+/* Write the length of STR followed by STR to P which points into
+   *BUF, a buffer of *BUFLEN size.  Track total size in *STRINGS_SIZE,
+   setting *STRX to the current offset for STR.  When STR can't fit in
+   *BUF, flush the buffer to ABFD, possibly reallocating.  Return the
+   next available location in *BUF, or NULL on error.  */
+
+static char *
+add_string (char *p, const char *str, bfd *abfd, char **buf, size_t *buflen,
+           unsigned int *strings_size, unsigned int *strx)
+{
+  size_t length = strlen (str) + 1;
+  /* Each entry will take 4 bytes to hold the string length + the
+     string itself + null terminator + padding to a 4 byte boundary.  */
+  size_t needed = (4 + length + 3) & ~3;
+
+  /* If there is not enough room for the next entry, then dump the
+     current buffer contents now and maybe allocate a larger buffer.  */
+  if (p - *buf + needed > *buflen)
+    {
+      /* Flush buffer before refilling or reallocating.  */
+      size_t amt = p - *buf;
+      if (bfd_write (*buf, amt, abfd) != amt)
+       return NULL;
+
+      /* Reallocate if now empty buffer still too small.  */
+      if (needed > *buflen)
+       {
+         /* Ensure a minimum growth factor to avoid O(n**2) space
+            consumption for n strings.  The optimal minimum factor
+            seems to be 2.  */
+         if (*buflen * 2 < needed)
+           *buflen = needed;
+         else
+           *buflen = *buflen * 2;
+         free (*buf);
+         *buf = bfd_malloc (*buflen);
+         if (*buf == NULL)
+           return NULL;
+       }
+
+      /* Reset to beginning of the (possibly new) buffer space.  */
+      p = *buf;
+    }
+
+  /* First element in a string table entry is the length of
+     the string.  This must always be 4 byte aligned.  This is
+     also an appropriate time to fill in the string index
+     field in the symbol table entry.  */
+  bfd_put_32 (abfd, length - 1, p);
+  *strings_size += 4;
+  p += 4;
+
+  *strx = *strings_size;
+
+  /* Next comes the string itself + a null terminator.  */
+  memcpy (p, str, length);
+  p += length;
+  *strings_size += length;
+
+  /* Always align up to the next word boundary.  */
+  if (length & 3)
+    {
+      length = 4 - (length & 3);
+      memset (p, 0, length);
+      *strings_size += length;
+      p += length;
+    }
+  return p;
 }
 
 /* Write out the space/subspace string table.  */
 
-static bfd_boolean
+static bool
 som_write_space_strings (bfd *abfd,
                         unsigned long current_offset,
-                        unsigned int *string_sizep)
+                        unsigned int *strings_size)
 {
   /* Chunk of memory that we can use as buffer space, then throw
      away.  */
   size_t tmp_space_size = SOM_TMP_BUFSIZE;
-  char *tmp_space = xmalloc (tmp_space_size);
+  char *tmp_space = bfd_malloc (tmp_space_size);
   char *p = tmp_space;
-  unsigned int strings_size = 0;
   asection *section;
-  bfd_size_type amt;
-  bfd_size_type res;
+
+  if (tmp_space == NULL)
+    return false;
 
   /* Seek to the start of the space strings in preparation for writing
      them out.  */
-  if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
-    return FALSE;
+  if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
+    return false;
 
   /* Walk through all the spaces and subspaces (order is not important)
      building up and writing string table entries for their names.  */
+  *strings_size = 0;
   for (section = abfd->sections; section != NULL; section = section->next)
     {
-      size_t length;
+      unsigned int *strx;
 
       /* Only work with space/subspaces; avoid any other sections
         which might have been made (.text for example).  */
-      if (!som_is_space (section) && !som_is_subspace (section))
-       continue;
-
-      /* Get the length of the space/subspace name.  */
-      length = strlen (section->name);
-
-      /* If there is not enough room for the next entry, then dump the
-        current buffer contents now and maybe allocate a larger
-        buffer.  Each entry will take 4 bytes to hold the string
-        length + the string itself + null terminator.  */
-      if (p - tmp_space + 5 + length > tmp_space_size)
-       {
-         /* Flush buffer before refilling or reallocating.  */
-         amt = p - tmp_space;
-         if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
-           return FALSE;
-
-         /* Reallocate if now empty buffer still too small.  */
-         if (5 + length > tmp_space_size)
-           {
-             /* Ensure a minimum growth factor to avoid O(n**2) space
-                consumption for n strings.  The optimal minimum
-                factor seems to be 2, as no other value can guarantee
-                wasting less than 50% space.  (Note that we cannot
-                deallocate space allocated by `alloca' without
-                returning from this function.)  The same technique is
-                used a few more times below when a buffer is
-                reallocated.  */
-             if (2 * tmp_space_size < length + 5)
-               tmp_space_size = length + 5;
-             else
-               tmp_space_size = 2 * tmp_space_size;
-             tmp_space = xrealloc (tmp_space, tmp_space_size);
-           }
-
-         /* Reset to beginning of the (possibly new) buffer space.  */
-         p = tmp_space;
-       }
-
-      /* First element in a string table entry is the length of the
-        string.  Alignment issues are already handled.  */
-      bfd_put_32 (abfd, (bfd_vma) length, p);
-      p += 4;
-      strings_size += 4;
-
-      /* Record the index in the space/subspace records.  */
       if (som_is_space (section))
-       som_section_data (section)->space_dict->name = strings_size;
+       strx = &som_section_data (section)->space_dict->name;
+      else if (som_is_subspace (section))
+       strx = &som_section_data (section)->subspace_dict->name;
       else
-       som_section_data (section)->subspace_dict->name = strings_size;
-
-      /* Next comes the string itself + a null terminator.  */
-      strcpy (p, section->name);
-      p += length + 1;
-      strings_size += length + 1;
+       continue;
 
-      /* Always align up to the next word boundary.  */
-      while (strings_size % 4)
-       {
-         bfd_put_8 (abfd, 0, p);
-         p++;
-         strings_size++;
-       }
+      p = add_string (p, section->name, abfd, &tmp_space, &tmp_space_size,
+                     strings_size, strx);
+      if (p == NULL)
+       return false;
     }
 
   /* Done with the space/subspace strings.  Write out any information
      contained in a partial block.  */
-  amt = p - tmp_space;
-  res = bfd_bwrite ((void *) &tmp_space[0], amt, abfd);
+  size_t amt = p - tmp_space;
+  bool ok = amt ? bfd_write (tmp_space, amt, abfd) == amt : true;
   free (tmp_space);
-  if (res != amt)
-    return FALSE;
-  *string_sizep = strings_size;
-  return TRUE;
+  return ok;
 }
 
 /* Write out the symbol string table.  */
 
-static bfd_boolean
+static bool
 som_write_symbol_strings (bfd *abfd,
                          unsigned long current_offset,
                          asymbol **syms,
                          unsigned int num_syms,
-                         unsigned int *string_sizep,
+                         unsigned int *strings_size,
                          struct som_compilation_unit *compilation_unit)
 {
   unsigned int i;
   /* Chunk of memory that we can use as buffer space, then throw
      away.  */
   size_t tmp_space_size = SOM_TMP_BUFSIZE;
-  char *tmp_space = xmalloc (tmp_space_size);
+  char *tmp_space = bfd_malloc (tmp_space_size);
   char *p = tmp_space;
-  unsigned int strings_size = 0;
-  bfd_size_type amt;
-  bfd_size_type res;
+
+  if (tmp_space == NULL)
+    return false;
 
   /* This gets a bit gruesome because of the compilation unit.  The
      strings within the compilation unit are part of the symbol
@@ -3434,15 +3455,15 @@ som_write_symbol_strings (bfd *abfd,
 
   /* Seek to the start of the space strings in preparation for writing
      them out.  */
-  if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
-    return FALSE;
+  if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
+    return false;
 
+  *strings_size = 0;
   if (compilation_unit)
     {
       for (i = 0; i < 4; i++)
        {
          struct som_name_pt *name;
-         size_t length;
 
          switch (i)
            {
@@ -3462,128 +3483,35 @@ som_write_symbol_strings (bfd *abfd,
              abort ();
            }
 
-         length = strlen (name->name);
-
-         /* If there is not enough room for the next entry, then dump
-            the current buffer contents now and maybe allocate a
-            larger buffer.  */
-         if (p - tmp_space + 5 + length > tmp_space_size)
-           {
-             /* Flush buffer before refilling or reallocating.  */
-             amt = p - tmp_space;
-             if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
-               return FALSE;
-
-             /* Reallocate if now empty buffer still too small.  */
-             if (5 + length > tmp_space_size)
-               {
-                 /* See alloca above for discussion of new size.  */
-                 if (2 * tmp_space_size < 5 + length)
-                   tmp_space_size = 5 + length;
-                 else
-                   tmp_space_size = 2 * tmp_space_size;
-                 tmp_space = xrealloc (tmp_space, tmp_space_size);
-               }
-
-             /* Reset to beginning of the (possibly new) buffer
-                space.  */
-             p = tmp_space;
-           }
-
-         /* First element in a string table entry is the length of
-            the string.  This must always be 4 byte aligned.  This is
-            also an appropriate time to fill in the string index
-            field in the symbol table entry.  */
-         bfd_put_32 (abfd, (bfd_vma) length, p);
-         strings_size += 4;
-         p += 4;
-
-         /* Next comes the string itself + a null terminator.  */
-         strcpy (p, name->name);
-
-         name->strx = strings_size;
+         p = add_string (p, name->name, abfd, &tmp_space, &tmp_space_size,
+                         strings_size, &name->strx);
 
-         p += length + 1;
-         strings_size += length + 1;
-
-         /* Always align up to the next word boundary.  */
-         while (strings_size % 4)
-           {
-             bfd_put_8 (abfd, 0, p);
-             strings_size++;
-             p++;
-           }
+         if (p == NULL)
+           return false;
        }
     }
 
   for (i = 0; i < num_syms; i++)
     {
-      size_t length = strlen (syms[i]->name);
-
-      /* If there is not enough room for the next entry, then dump the
-        current buffer contents now and maybe allocate a larger buffer.  */
-     if (p - tmp_space + 5 + length > tmp_space_size)
-       {
-         /* Flush buffer before refilling or reallocating.  */
-         amt = p - tmp_space;
-         if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
-           return FALSE;
-
-         /* Reallocate if now empty buffer still too small.  */
-         if (5 + length > tmp_space_size)
-           {
-             /* See alloca above for discussion of new size.  */
-             if (2 * tmp_space_size < 5 + length)
-               tmp_space_size = 5 + length;
-             else
-               tmp_space_size = 2 * tmp_space_size;
-             tmp_space = xrealloc (tmp_space, tmp_space_size);
-           }
-
-         /* Reset to beginning of the (possibly new) buffer space.  */
-         p = tmp_space;
-       }
-
-      /* First element in a string table entry is the length of the
-        string.  This must always be 4 byte aligned.  This is also
-        an appropriate time to fill in the string index field in the
-        symbol table entry.  */
-      bfd_put_32 (abfd, (bfd_vma) length, p);
-      strings_size += 4;
-      p += 4;
-
-      /* Next comes the string itself + a null terminator.  */
-      strcpy (p, syms[i]->name);
-
-      som_symbol_data (syms[i])->stringtab_offset = strings_size;
-      p += length + 1;
-      strings_size += length + 1;
-
-      /* Always align up to the next word boundary.  */
-      while (strings_size % 4)
-       {
-         bfd_put_8 (abfd, 0, p);
-         strings_size++;
-         p++;
-       }
+      p = add_string (p, syms[i]->name, abfd, &tmp_space, &tmp_space_size,
+                     strings_size,
+                     &som_symbol_data (syms[i])->stringtab_offset);
+      if (p == NULL)
+       return false;
     }
 
   /* Scribble out any partial block.  */
-  amt = p - tmp_space;
-  res = bfd_bwrite ((void *) &tmp_space[0], amt, abfd);
+  size_t amt = p - tmp_space;
+  bool ok = amt ? bfd_write (tmp_space, amt, abfd) == amt : true;
   free (tmp_space);
-  if (res != amt)
-    return FALSE;
-
-  *string_sizep = strings_size;
-  return TRUE;
+  return ok;
 }
 
 /* Compute variable information to be placed in the SOM headers,
    space/subspace dictionaries, relocation streams, etc.  Begin
    writing parts of the object file.  */
 
-static bfd_boolean
+static bool
 som_begin_writing (bfd *abfd)
 {
   unsigned long current_offset = 0;
@@ -3628,8 +3556,8 @@ som_begin_writing (bfd *abfd)
       struct som_external_string_auxhdr ext_string_auxhdr;
       bfd_size_type len;
 
-      if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
-       return FALSE;
+      if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
+       return false;
 
       /* Write the aux_id structure and the string length.  */
       len = sizeof (struct som_external_string_auxhdr);
@@ -3637,16 +3565,15 @@ som_begin_writing (bfd *abfd)
       current_offset += len;
       som_swap_string_auxhdr_out
        (obj_som_version_hdr (abfd), &ext_string_auxhdr);
-      if (bfd_bwrite (&ext_string_auxhdr, len, abfd) != len)
-       return FALSE;
+      if (bfd_write (&ext_string_auxhdr, len, abfd) != len)
+       return false;
 
       /* Write the version string.  */
       len = obj_som_version_hdr (abfd)->header_id.length - 4;
       obj_som_file_hdr (abfd)->aux_header_size += len;
       current_offset += len;
-      if (bfd_bwrite ((void *) obj_som_version_hdr (abfd)->string, len, abfd)
-         != len)
-       return FALSE;
+      if (bfd_write (obj_som_version_hdr (abfd)->string, len, abfd) != len)
+       return false;
     }
 
   if (obj_som_copyright_hdr (abfd) != NULL)
@@ -3654,8 +3581,8 @@ som_begin_writing (bfd *abfd)
       struct som_external_string_auxhdr ext_string_auxhdr;
       bfd_size_type len;
 
-      if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
-       return FALSE;
+      if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
+       return false;
 
       /* Write the aux_id structure and the string length.  */
       len = sizeof (struct som_external_string_auxhdr);
@@ -3663,16 +3590,15 @@ som_begin_writing (bfd *abfd)
       current_offset += len;
       som_swap_string_auxhdr_out
        (obj_som_copyright_hdr (abfd), &ext_string_auxhdr);
-      if (bfd_bwrite (&ext_string_auxhdr, len, abfd) != len)
-       return FALSE;
+      if (bfd_write (&ext_string_auxhdr, len, abfd) != len)
+       return false;
 
       /* Write the copyright string.  */
       len = obj_som_copyright_hdr (abfd)->header_id.length - 4;
       obj_som_file_hdr (abfd)->aux_header_size += len;
       current_offset += len;
-      if (bfd_bwrite ((void *) obj_som_copyright_hdr (abfd)->string, len, abfd)
-         != len)
-       return FALSE;
+      if (bfd_write (obj_som_copyright_hdr (abfd)->string, len, abfd) != len)
+       return false;
     }
 
   /* Next comes the initialization pointers; we have no initialization
@@ -3722,7 +3648,7 @@ som_begin_writing (bfd *abfd)
 
   /* Scribble out the space strings.  */
   if (! som_write_space_strings (abfd, current_offset, &strings_size))
-    return FALSE;
+    return false;
 
   /* Record total string table size in the header and update the
      current offset.  */
@@ -3918,10 +3844,10 @@ som_begin_writing (bfd *abfd)
      zeros are filled in.  Ugh.  */
   if (abfd->flags & (EXEC_P | DYNAMIC))
     current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
-  if (bfd_seek (abfd, (file_ptr) current_offset - 1, SEEK_SET) != 0)
-    return FALSE;
-  if (bfd_bwrite ((void *) "", (bfd_size_type) 1, abfd) != 1)
-    return FALSE;
+  if (bfd_seek (abfd, current_offset - 1, SEEK_SET) != 0)
+    return false;
+  if (bfd_write ("", 1, abfd) != 1)
+    return false;
 
   obj_som_file_hdr (abfd)->unloadable_sp_size
     = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
@@ -3933,12 +3859,12 @@ som_begin_writing (bfd *abfd)
   /* Done.  Store the total size of the SOM so far.  */
   obj_som_file_hdr (abfd)->som_length = current_offset;
 
-  return TRUE;
+  return true;
 }
 
 /* Finally, scribble out the various headers to the disk.  */
 
-static bfd_boolean
+static bool
 som_finish_writing (bfd *abfd)
 {
   int num_spaces = som_count_spaces (abfd);
@@ -3949,7 +3875,7 @@ som_finish_writing (bfd *abfd)
   asection *section;
   unsigned long current_offset;
   unsigned int strings_size, total_reloc_size;
-  bfd_size_type amt;
+  size_t amt;
   struct som_external_header ext_header;
 
   /* We must set up the version identifier here as objcopy/strip copy
@@ -3995,7 +3921,7 @@ som_finish_writing (bfd *abfd)
   if (! som_write_symbol_strings (abfd, current_offset, syms,
                                  num_syms, &strings_size,
                                  obj_som_compilation_unit (abfd)))
-    return FALSE;
+    return false;
 
   /* Record total string table size in header and update the
      current offset.  */
@@ -4003,9 +3929,10 @@ som_finish_writing (bfd *abfd)
   current_offset += strings_size;
 
   /* Do prep work before handling fixups.  */
-  som_prep_for_fixups (abfd,
-                      bfd_get_outsymbols (abfd),
-                      bfd_get_symcount (abfd));
+  if (!som_prep_for_fixups (abfd,
+                           bfd_get_outsymbols (abfd),
+                           bfd_get_symcount (abfd)))
+    return false;
 
   /* At the end of the file is the fixup stream which starts on a
      word boundary.  */
@@ -4016,7 +3943,7 @@ som_finish_writing (bfd *abfd)
   /* Write the fixups and update fields in subspace headers which
      relate to the fixup stream.  */
   if (! som_write_fixups (abfd, current_offset, &total_reloc_size))
-    return FALSE;
+    return false;
 
   /* Record the total size of the fixup stream in the file header.  */
   obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
@@ -4027,7 +3954,7 @@ som_finish_writing (bfd *abfd)
   /* Now that the symbol table information is complete, build and
      write the symbol table.  */
   if (! som_build_and_write_symbol_table (abfd))
-    return FALSE;
+    return false;
 
   /* Subspaces are written first so that we can set up information
      about them in their containing spaces as the subspace is written.  */
@@ -4035,7 +3962,7 @@ som_finish_writing (bfd *abfd)
   /* Seek to the start of the subspace dictionary records.  */
   location = obj_som_file_hdr (abfd)->subspace_location;
   if (bfd_seek (abfd, location, SEEK_SET) != 0)
-    return FALSE;
+    return false;
 
   section = abfd->sections;
   /* Now for each loadable space write out records for its subspaces.  */
@@ -4086,8 +4013,8 @@ som_finish_writing (bfd *abfd)
          som_swap_subspace_dictionary_record_out
            (som_section_data (subsection)->subspace_dict, &ext_subspace_dict);
          amt = sizeof (struct som_subspace_dictionary_record);
-         if (bfd_bwrite (&ext_subspace_dict, amt, abfd) != amt)
-           return FALSE;
+         if (bfd_write (&ext_subspace_dict, amt, abfd) != amt)
+           return false;
        }
       /* Goto the next section.  */
       section = section->next;
@@ -4144,8 +4071,8 @@ som_finish_writing (bfd *abfd)
          som_swap_subspace_dictionary_record_out
            (som_section_data (subsection)->subspace_dict, &ext_subspace_dict);
          amt = sizeof (struct som_subspace_dictionary_record);
-         if (bfd_bwrite (&ext_subspace_dict, amt, abfd) != amt)
-           return FALSE;
+         if (bfd_write (&ext_subspace_dict, amt, abfd) != amt)
+           return false;
        }
       /* Goto the next section.  */
       section = section->next;
@@ -4158,7 +4085,7 @@ som_finish_writing (bfd *abfd)
      dictionary records.  */
   location = obj_som_file_hdr (abfd)->space_location;
   if (bfd_seek (abfd, location, SEEK_SET) != 0)
-    return FALSE;
+    return false;
 
   section = abfd->sections;
   for (i = 0; i < num_spaces; i++)
@@ -4173,8 +4100,8 @@ som_finish_writing (bfd *abfd)
       som_swap_space_dictionary_out (som_section_data (section)->space_dict,
                                     &ext_space_dict);
       amt = sizeof (struct som_external_space_dictionary_record);
-      if (bfd_bwrite (&ext_space_dict, amt, abfd) != amt)
-       return FALSE;
+      if (bfd_write (&ext_space_dict, amt, abfd) != amt)
+       return false;
 
       /* Goto the next section.  */
       section = section->next;
@@ -4187,19 +4114,19 @@ som_finish_writing (bfd *abfd)
 
       location = obj_som_file_hdr (abfd)->compiler_location;
       if (bfd_seek (abfd, location, SEEK_SET) != 0)
-       return FALSE;
+       return false;
 
       som_swap_compilation_unit_out
        (obj_som_compilation_unit (abfd), &ext_comp_unit);
 
       amt = sizeof (struct som_external_compilation_unit);
-      if (bfd_bwrite (&ext_comp_unit, amt, abfd) != amt)
-       return FALSE;
+      if (bfd_write (&ext_comp_unit, amt, abfd) != amt)
+       return false;
     }
 
   /* Setting of the system_id has to happen very late now that copying of
      BFD private data happens *after* section contents are set.  */
-  if (abfd->flags & (EXEC_P | DYNAMIC))
+  if ((abfd->flags & (EXEC_P | DYNAMIC)) && obj_som_exec_data (abfd))
     obj_som_file_hdr (abfd)->system_id = obj_som_exec_data (abfd)->system_id;
   else if (bfd_get_mach (abfd) == pa20)
     obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC2_0;
@@ -4215,11 +4142,11 @@ som_finish_writing (bfd *abfd)
 
   /* Only thing left to do is write out the file header.  It is always
      at location zero.  Seek there and write it.  */
-  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
-    return FALSE;
+  if (bfd_seek (abfd, 0, SEEK_SET) != 0)
+    return false;
   amt = sizeof (struct som_external_header);
-  if (bfd_bwrite (&ext_header, amt, abfd) != amt)
-    return FALSE;
+  if (bfd_write (&ext_header, amt, abfd) != amt)
+    return false;
 
   /* Now write the exec header.  */
   if (abfd->flags & (EXEC_P | DYNAMIC))
@@ -4230,7 +4157,8 @@ som_finish_writing (bfd *abfd)
 
       exec_header = obj_som_exec_hdr (abfd);
       exec_header->exec_entry = bfd_get_start_address (abfd);
-      exec_header->exec_flags = obj_som_exec_data (abfd)->exec_flags;
+      if (obj_som_exec_data (abfd))
+       exec_header->exec_flags = obj_som_exec_data (abfd)->exec_flags;
 
       /* Oh joys.  Ram some of the BSS data into the DATA section
         to be compatible with how the hp linker makes objects
@@ -4249,32 +4177,33 @@ som_finish_writing (bfd *abfd)
          || exec_header->exec_dfile + exec_header->exec_dsize > som_length)
        {
          bfd_set_error (bfd_error_bad_value);
-         return FALSE;
+         return false;
        }
 
       som_swap_exec_auxhdr_out (exec_header, &ext_exec_header);
 
       if (bfd_seek (abfd, obj_som_file_hdr (abfd)->aux_header_location,
                    SEEK_SET) != 0)
-       return FALSE;
+       return false;
 
       amt = sizeof (ext_exec_header);
-      if (bfd_bwrite (&ext_exec_header, amt, abfd) != amt)
-       return FALSE;
+      if (bfd_write (&ext_exec_header, amt, abfd) != amt)
+       return false;
     }
-  return TRUE;
+  return true;
 }
 
 /* Compute and return the checksum for a SOM file header.  */
 
-static unsigned long
+static uint32_t
 som_compute_checksum (struct som_external_header *hdr)
 {
-  unsigned long checksum, count, i;
-  unsigned long *buffer = (unsigned long *) hdr;
+  size_t count, i;
+  uint32_t checksum;
+  uint32_t *buffer = (uint32_t *) hdr;
 
   checksum = 0;
-  count = sizeof (struct som_external_header) / 4;
+  count = sizeof (*hdr) / sizeof (*buffer);
   for (i = 0; i < count; i++)
     checksum ^= *(buffer + i);
 
@@ -4395,9 +4324,9 @@ som_bfd_derive_misc_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
 
   /* The secondary_def field is for "weak" symbols.  */
   if (sym->flags & BSF_WEAK)
-    info->secondary_def = TRUE;
+    info->secondary_def = true;
   else
-    info->secondary_def = FALSE;
+    info->secondary_def = false;
 
   /* The is_comdat, is_common and dup_common fields provide various
      flavors of common.
@@ -4441,7 +4370,7 @@ som_bfd_derive_misc_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
 /* Build and write, in one big chunk, the entire symbol table for
    this BFD.  */
 
-static bfd_boolean
+static bool
 som_build_and_write_symbol_table (bfd *abfd)
 {
   unsigned int num_syms = bfd_get_symcount (abfd);
@@ -4450,13 +4379,19 @@ som_build_and_write_symbol_table (bfd *abfd)
   struct som_external_symbol_dictionary_record *som_symtab = NULL;
   unsigned int i;
   bfd_size_type symtab_size;
+  size_t amt;
 
   /* Compute total symbol table size and allocate a chunk of memory
      to hold the symbol table as we build it.  */
-  symtab_size = num_syms;
-  symtab_size *= sizeof (struct som_external_symbol_dictionary_record);
-  som_symtab = bfd_zmalloc (symtab_size);
-  if (som_symtab == NULL && symtab_size != 0)
+  if (_bfd_mul_overflow (num_syms,
+                        sizeof (struct som_external_symbol_dictionary_record),
+                        &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return false;
+    }
+  som_symtab = bfd_zmalloc (amt);
+  if (som_symtab == NULL && num_syms != 0)
     goto error_return;
 
   /* Walk over each symbol.  */
@@ -4494,23 +4429,24 @@ som_build_and_write_symbol_table (bfd *abfd)
   /* Everything is ready, seek to the right location and
      scribble out the symbol table.  */
   if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
-    return FALSE;
+    goto error_return;
 
-  if (bfd_bwrite ((void *) som_symtab, symtab_size, abfd) != symtab_size)
+  symtab_size = num_syms;
+  symtab_size *= sizeof (struct som_external_symbol_dictionary_record);
+  if (bfd_write (som_symtab, symtab_size, abfd) != symtab_size)
     goto error_return;
 
-  if (som_symtab != NULL)
-    free (som_symtab);
-  return TRUE;
+  free (som_symtab);
+  return true;
+
  error_return:
-  if (som_symtab != NULL)
-    free (som_symtab);
-  return FALSE;
+  free (som_symtab);
+  return false;
 }
 
 /* Write an object in SOM format.  */
 
-static bfd_boolean
+static bool
 som_write_object_contents (bfd *abfd)
 {
   if (! abfd->output_has_begun)
@@ -4518,7 +4454,7 @@ som_write_object_contents (bfd *abfd)
       /* Set up fixed parts of the file, space, and subspace headers.
         Notify the world that output has begun.  */
       som_prep_headers (abfd);
-      abfd->output_has_begun = TRUE;
+      abfd->output_has_begun = true;
       /* Start writing the object file.  This include all the string
         tables, fixup streams, and other portions of the object file.  */
       som_begin_writing (abfd);
@@ -4529,7 +4465,7 @@ som_write_object_contents (bfd *abfd)
 \f
 /* Read and save the string table associated with the given BFD.  */
 
-static bfd_boolean
+static bool
 som_slurp_string_table (bfd *abfd)
 {
   char *stringtab;
@@ -4537,7 +4473,7 @@ som_slurp_string_table (bfd *abfd)
 
   /* Use the saved version if its available.  */
   if (obj_som_stringtab (abfd) != NULL)
-    return TRUE;
+    return true;
 
   /* I don't think this can currently happen, and I'm not sure it should
      really be an error, but it's better than getting unpredictable results
@@ -4545,24 +4481,22 @@ som_slurp_string_table (bfd *abfd)
   if (obj_som_stringtab_size (abfd) == 0)
     {
       bfd_set_error (bfd_error_no_symbols);
-      return FALSE;
+      return false;
     }
 
   /* Allocate and read in the string table.  */
+  if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) != 0)
+    return false;
   amt = obj_som_stringtab_size (abfd);
-  stringtab = bfd_zmalloc (amt);
+  stringtab = (char *) _bfd_malloc_and_read (abfd, amt + 1, amt);
   if (stringtab == NULL)
-    return FALSE;
-
-  if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) != 0)
-    return FALSE;
-
-  if (bfd_bread (stringtab, amt, abfd) != amt)
-    return FALSE;
+    return false;
+  /* Make sure that the strings are zero-terminated.  */
+  stringtab[amt] = 0;
 
   /* Save our results and return success.  */
   obj_som_stringtab (abfd) = stringtab;
-  return TRUE;
+  return true;
 }
 
 /* Return the amount of data (in bytes) required to hold the symbol
@@ -4626,12 +4560,12 @@ bfd_section_from_som_symbol
 static unsigned int
 som_slurp_symbol_table (bfd *abfd)
 {
-  int symbol_count = bfd_get_symcount (abfd);
-  int symsize = sizeof (struct som_external_symbol_dictionary_record);
+  unsigned int symbol_count = bfd_get_symcount (abfd);
+  size_t symsize = sizeof (struct som_external_symbol_dictionary_record);
   char *stringtab;
   struct som_external_symbol_dictionary_record *buf = NULL, *bufp, *endbufp;
-  som_symbol_type *sym, *symbase;
-  bfd_size_type amt;
+  som_symbol_type *sym, *symbase = NULL;
+  size_t amt;
 
   /* Return saved value if it exists.  */
   if (obj_som_symtab (abfd) != NULL)
@@ -4646,21 +4580,26 @@ som_slurp_symbol_table (bfd *abfd)
 
   stringtab = obj_som_stringtab (abfd);
 
-  amt = symbol_count;
-  amt *= sizeof (som_symbol_type);
-  symbase = bfd_zmalloc (amt);
-  if (symbase == NULL)
-    goto error_return;
-
   /* Read in the external SOM representation.  */
-  amt = symbol_count;
-  amt *= symsize;
-  buf = bfd_malloc (amt);
-  if (buf == NULL && amt != 0)
-    goto error_return;
+  if (_bfd_mul_overflow (symbol_count, symsize, &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      goto error_return;
+    }
   if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) != 0)
     goto error_return;
-  if (bfd_bread (buf, amt, abfd) != amt)
+  buf = (struct som_external_symbol_dictionary_record *)
+    _bfd_malloc_and_read (abfd, amt, amt);
+  if (buf == NULL)
+    goto error_return;
+
+  if (_bfd_mul_overflow (symbol_count, sizeof (som_symbol_type), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      goto error_return;
+    }
+  symbase = bfd_zmalloc (amt);
+  if (symbase == NULL)
     goto error_return;
 
   /* Iterate over all the symbols and internalize them.  */
@@ -4672,6 +4611,7 @@ som_slurp_symbol_table (bfd *abfd)
        (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK;
       unsigned int symbol_scope =
        (flags >> SOM_SYMBOL_SCOPE_SH) & SOM_SYMBOL_SCOPE_MASK;
+      bfd_vma offset;
 
       /* I don't think we care about these.  */
       if (symbol_type == ST_SYM_EXT || symbol_type == ST_ARG_EXT)
@@ -4703,9 +4643,16 @@ som_slurp_symbol_table (bfd *abfd)
 
       /* Some reasonable defaults.  */
       sym->symbol.the_bfd = abfd;
-      sym->symbol.name = bfd_getb32 (bufp->name) + stringtab;
+      offset = bfd_getb32 (bufp->name);
+      if (offset < obj_som_stringtab_size (abfd))
+       sym->symbol.name = offset + stringtab;
+      else
+       {
+         bfd_set_error (bfd_error_bad_value);
+         goto error_return;
+       }
       sym->symbol.value = bfd_getb32 (bufp->symbol_value);
-      sym->symbol.section = 0;
+      sym->symbol.section = NULL;
       sym->symbol.flags = 0;
 
       switch (symbol_type)
@@ -4765,26 +4712,28 @@ som_slurp_symbol_table (bfd *abfd)
          sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
          sym->symbol.value -= sym->symbol.section->vma;
          break;
+
+       default:
+         sym->symbol.section = bfd_und_section_ptr;
+         break;
        }
 
       /* Check for a weak symbol.  */
       if (flags & SOM_SYMBOL_SECONDARY_DEF)
        sym->symbol.flags |= BSF_WEAK;
-
       /* Mark section symbols and symbols used by the debugger.
         Note $START$ is a magic code symbol, NOT a section symbol.  */
       if (sym->symbol.name[0] == '$'
          && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$'
          && !strcmp (sym->symbol.name, sym->symbol.section->name))
        sym->symbol.flags |= BSF_SECTION_SYM;
-      else if (CONST_STRNEQ (sym->symbol.name, "L$0\002"))
+      else if (startswith (sym->symbol.name, "L$0\002"))
        {
          sym->symbol.flags |= BSF_SECTION_SYM;
          sym->symbol.name = sym->symbol.section->name;
        }
-      else if (CONST_STRNEQ (sym->symbol.name, "L$0\001"))
+      else if (startswith (sym->symbol.name, "L$0\001"))
        sym->symbol.flags |= BSF_DEBUGGING;
-
       /* Note increment at bottom of loop, since we skip some symbols
         we can not include it as part of the for statement.  */
       sym++;
@@ -4792,19 +4741,18 @@ som_slurp_symbol_table (bfd *abfd)
 
   /* We modify the symbol count to record the number of BFD symbols we
      created.  */
-  bfd_get_symcount (abfd) = sym - symbase;
+  abfd->symcount = sym - symbase;
 
   /* Save our results and return success.  */
   obj_som_symtab (abfd) = symbase;
  successful_return:
-  if (buf != NULL)
-    free (buf);
-  return (TRUE);
+  free (buf);
+  return true;
 
  error_return:
-  if (buf != NULL)
-    free (buf);
-  return FALSE;
+  free (symbase);
+  free (buf);
+  return false;
 }
 
 /* Canonicalize a SOM symbol table.  Return the number of entries
@@ -4835,7 +4783,7 @@ som_canonicalize_symtab (bfd *abfd, asymbol **location)
 static asymbol *
 som_make_empty_symbol (bfd *abfd)
 {
-  bfd_size_type amt = sizeof (som_symbol_type);
+  size_t amt = sizeof (som_symbol_type);
   som_symbol_type *new_symbol_type = bfd_zalloc (abfd, amt);
 
   if (new_symbol_type == NULL)
@@ -4861,9 +4809,8 @@ som_print_symbol (bfd *abfd,
       fprintf (file, "%s", symbol->name);
       break;
     case bfd_print_symbol_more:
-      fprintf (file, "som ");
-      fprintf_vma (file, symbol->value);
-      fprintf (file, " %lx", (long) symbol->flags);
+      fprintf (file, "som %08" PRIx64 " %x",
+              (uint64_t) symbol->value, symbol->flags);
       break;
     case bfd_print_symbol_all:
       {
@@ -4877,7 +4824,7 @@ som_print_symbol (bfd *abfd,
     }
 }
 
-static bfd_boolean
+static bool
 som_bfd_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
                             const char *name)
 {
@@ -4903,15 +4850,12 @@ som_set_reloc_info (unsigned char *fixup,
                    arelent *internal_relocs,
                    asection *section,
                    asymbol **symbols,
-                   bfd_boolean just_count)
+                   unsigned int symcount,
+                   bool just_count)
 {
-  unsigned int op, varname, deallocate_contents = 0;
+  unsigned int deallocate_contents = 0;
   unsigned char *end_fixups = &fixup[end];
-  const struct fixup_format *fp;
-  const char *cp;
-  unsigned char *save_fixup;
-  int variables[26], stack[20], c, v, count, prev_fixup, *sp, saved_unwind_bits;
-  const int *subop;
+  int variables[26], stack[20], count, prev_fixup, *sp, saved_unwind_bits;
   arelent *rptr = internal_relocs;
   unsigned int offset = 0;
 
@@ -4930,10 +4874,14 @@ som_set_reloc_info (unsigned char *fixup,
 
   while (fixup < end_fixups)
     {
+      const char *cp;
+      unsigned int op;
+      const struct fixup_format *fp;
+
       /* Save pointer to the start of this fixup.  We'll use
         it later to determine if it is necessary to put this fixup
         on the queue.  */
-      save_fixup = fixup;
+      unsigned char *save_fixup = fixup;
 
       /* Get the fixup code and its associated format.  */
       op = *fixup++;
@@ -4942,6 +4890,11 @@ som_set_reloc_info (unsigned char *fixup,
       /* Handle a request for a previous fixup.  */
       if (*fp->format == 'P')
        {
+         if (!reloc_queue[fp->D].reloc)
+           /* The back-reference doesn't exist.  This is a broken
+              object file, likely fuzzed.  Just ignore the fixup.  */
+           continue;
+
          /* Get pointer to the beginning of the prev fixup, move
             the repeated fixup to the head of the queue.  */
          fixup = reloc_queue[fp->D].reloc;
@@ -4979,11 +4932,15 @@ som_set_reloc_info (unsigned char *fixup,
       while (*cp)
        {
          /* The variable this pass is going to compute a value for.  */
-         varname = *cp++;
+         unsigned int varname = *cp++;
+         const int *subop;
+         int c;
 
          /* Start processing RHS.  Continue until a NULL or '=' is found.  */
          do
            {
+             unsigned v;
+
              c = *cp++;
 
              /* If this is a variable, push it on the stack.  */
@@ -4996,7 +4953,7 @@ som_set_reloc_info (unsigned char *fixup,
              else if (ISLOWER (c))
                {
                  int bits = (c - 'a') * 8;
-                 for (v = 0; c > 'a'; --c)
+                 for (v = 0; c > 'a' && fixup < end_fixups; --c)
                    v = (v << 8) | *fixup++;
                  if (varname == 'V')
                    v = sign_extend (v, bits);
@@ -5057,7 +5014,7 @@ som_set_reloc_info (unsigned char *fixup,
            /* A symbol to use in the relocation.  Make a note
               of this if we are not just counting.  */
            case 'S':
-             if (! just_count)
+             if (!just_count && symbols != NULL && (unsigned int) c < symcount)
                rptr->sym_ptr_ptr = &symbols[c];
              break;
            /* Argument relocation bits for a function call.  */
@@ -5189,27 +5146,30 @@ som_set_reloc_info (unsigned char *fixup,
                     section contents.  */
                  rptr->addend = var ('V');
 
-                 if (rptr->addend == 0 && !section->contents)
+                 if (rptr->addend == 0
+                     && (section->flags & SEC_HAS_CONTENTS) != 0)
                    {
-                     /* Got to read the damn contents first.  We don't
-                        bother saving the contents (yet).  Add it one
-                        day if the need arises.  */
-                     bfd_byte *contents;
-                     if (!bfd_malloc_and_get_section (section->owner, section,
-                                                      &contents))
+                     if (!section->contents)
                        {
-                         if (contents != NULL)
-                           free (contents);
-                         return (unsigned) -1;
+                         /* Got to read the damn contents first.  We don't
+                            bother saving the contents (yet).  Add it one
+                            day if the need arises.  */
+                         bfd_byte *contents;
+                         if (!bfd_malloc_and_get_section (section->owner,
+                                                          section, &contents))
+                           {
+                             free (contents);
+                             return (unsigned) -1;
+                           }
+                         section->contents = contents;
+                         deallocate_contents = 1;
                        }
-                     section->contents = contents;
-                     deallocate_contents = 1;
+                     if (offset - var ('L') <= section->size
+                         && section->size - (offset - var ('L')) >= 4)
+                       rptr->addend = bfd_get_32 (section->owner,
+                                                  (section->contents
+                                                   + offset - var ('L')));
                    }
-                 else if (rptr->addend == 0)
-                   rptr->addend = bfd_get_32 (section->owner,
-                                              (section->contents
-                                               + offset - var ('L')));
-
                }
              else
                rptr->addend = var ('V');
@@ -5223,7 +5183,10 @@ som_set_reloc_info (unsigned char *fixup,
        }
     }
   if (deallocate_contents)
-    free (section->contents);
+    {
+      free (section->contents);
+      section->contents = NULL;
+    }
 
   return count;
 
@@ -5239,69 +5202,69 @@ som_set_reloc_info (unsigned char *fixup,
    set to TRUE to indicate it only needs a count of the number
    of actual relocations.  */
 
-static bfd_boolean
+static bool
 som_slurp_reloc_table (bfd *abfd,
                       asection *section,
                       asymbol **symbols,
-                      bfd_boolean just_count)
+                      bool just_count)
 {
   unsigned char *external_relocs;
   unsigned int fixup_stream_size;
   arelent *internal_relocs;
   unsigned int num_relocs;
-  bfd_size_type amt;
+  size_t amt;
 
   fixup_stream_size = som_section_data (section)->reloc_size;
   /* If there were no relocations, then there is nothing to do.  */
   if (section->reloc_count == 0)
-    return TRUE;
+    return true;
 
   /* If reloc_count is -1, then the relocation stream has not been
      parsed.  We must do so now to know how many relocations exist.  */
   if (section->reloc_count == (unsigned) -1)
     {
+      /* Read in the external forms.  */
+      if (bfd_seek (abfd, obj_som_reloc_filepos (abfd) + section->rel_filepos,
+                   SEEK_SET) != 0)
+       return false;
       amt = fixup_stream_size;
-      external_relocs = bfd_malloc (amt);
+      external_relocs = _bfd_malloc_and_read (abfd, amt, amt);
       if (external_relocs == NULL)
-       return FALSE;
-      /* Read in the external forms.  */
-      if (bfd_seek (abfd,
-                   obj_som_reloc_filepos (abfd) + section->rel_filepos,
-                   SEEK_SET)
-         != 0)
-       return FALSE;
-      if (bfd_bread (external_relocs, amt, abfd) != amt)
-       return FALSE;
+       return false;
 
       /* Let callers know how many relocations found.
         also save the relocation stream as we will
         need it again.  */
       section->reloc_count = som_set_reloc_info (external_relocs,
                                                 fixup_stream_size,
-                                                NULL, NULL, NULL, TRUE);
+                                                NULL, NULL, NULL, 0, true);
 
       som_section_data (section)->reloc_stream = external_relocs;
     }
 
   /* If the caller only wanted a count, then return now.  */
   if (just_count)
-    return TRUE;
+    return true;
 
   num_relocs = section->reloc_count;
   external_relocs = som_section_data (section)->reloc_stream;
   /* Return saved information about the relocations if it is available.  */
   if (section->relocation != NULL)
-    return TRUE;
+    return true;
 
-  amt = num_relocs;
-  amt *= sizeof (arelent);
-  internal_relocs = bfd_zalloc (abfd, (amt));
+  if (_bfd_mul_overflow (num_relocs, sizeof (arelent), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return false;
+    }
+  internal_relocs = bfd_zalloc (abfd, amt);
   if (internal_relocs == NULL)
-    return FALSE;
+    return false;
 
   /* Process and internalize the relocations.  */
   som_set_reloc_info (external_relocs, fixup_stream_size,
-                     internal_relocs, section, symbols, FALSE);
+                     internal_relocs, section, symbols,
+                     bfd_get_symcount (abfd), false);
 
   /* We're done with the external relocations.  Free them.  */
   free (external_relocs);
@@ -5309,7 +5272,7 @@ som_slurp_reloc_table (bfd *abfd,
 
   /* Save our results and return success.  */
   section->relocation = internal_relocs;
-  return TRUE;
+  return true;
 }
 
 /* Return the number of bytes required to store the relocation
@@ -5322,7 +5285,7 @@ som_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
      and parse it to determine how many relocations exist.  */
   if (asect->flags & SEC_RELOC)
     {
-      if (! som_slurp_reloc_table (abfd, asect, NULL, TRUE))
+      if (! som_slurp_reloc_table (abfd, asect, NULL, true))
        return -1;
       return (asect->reloc_count + 1) * sizeof (arelent *);
     }
@@ -5345,7 +5308,7 @@ som_canonicalize_reloc (bfd *abfd,
   arelent *tblptr;
   int count;
 
-  if (! som_slurp_reloc_table (abfd, section, symbols, FALSE))
+  if (! som_slurp_reloc_table (abfd, section, symbols, false))
     return -1;
 
   count = section->reloc_count;
@@ -5362,16 +5325,16 @@ extern const bfd_target hppa_som_vec;
 
 /* A hook to set up object file dependent section information.  */
 
-static bfd_boolean
+static bool
 som_new_section_hook (bfd *abfd, asection *newsect)
 {
   if (!newsect->used_by_bfd)
     {
-      bfd_size_type amt = sizeof (struct som_section_data_struct);
+      size_t amt = sizeof (struct som_section_data_struct);
 
       newsect->used_by_bfd = bfd_zalloc (abfd, amt);
       if (!newsect->used_by_bfd)
-       return FALSE;
+       return false;
     }
   newsect->alignment_power = 3;
 
@@ -5382,7 +5345,7 @@ som_new_section_hook (bfd *abfd, asection *newsect)
 /* Copy any private info we understand from the input symbol
    to the output symbol.  */
 
-static bfd_boolean
+static bool
 som_bfd_copy_private_symbol_data (bfd *ibfd,
                                  asymbol *isymbol,
                                  bfd *obfd,
@@ -5394,37 +5357,37 @@ som_bfd_copy_private_symbol_data (bfd *ibfd,
   /* One day we may try to grok other private data.  */
   if (ibfd->xvec->flavour != bfd_target_som_flavour
       || obfd->xvec->flavour != bfd_target_som_flavour)
-    return FALSE;
+    return false;
 
   /* The only private information we need to copy is the argument relocation
      bits.  */
   output_symbol->tc_data.ap.hppa_arg_reloc =
     input_symbol->tc_data.ap.hppa_arg_reloc;
 
-  return TRUE;
+  return true;
 }
 
 /* Copy any private info we understand from the input section
    to the output section.  */
 
-static bfd_boolean
+static bool
 som_bfd_copy_private_section_data (bfd *ibfd,
                                   asection *isection,
                                   bfd *obfd,
                                   asection *osection)
 {
-  bfd_size_type amt;
+  size_t amt;
 
   /* One day we may try to grok other private data.  */
   if (ibfd->xvec->flavour != bfd_target_som_flavour
       || obfd->xvec->flavour != bfd_target_som_flavour
       || (!som_is_space (isection) && !som_is_subspace (isection)))
-    return TRUE;
+    return true;
 
   amt = sizeof (struct som_copyable_section_data_struct);
   som_section_data (osection)->copy_data = bfd_zalloc (obfd, amt);
   if (som_section_data (osection)->copy_data == NULL)
-    return FALSE;
+    return false;
 
   memcpy (som_section_data (osection)->copy_data,
          som_section_data (isection)->copy_data,
@@ -5432,38 +5395,48 @@ som_bfd_copy_private_section_data (bfd *ibfd,
 
   /* Reparent if necessary.  */
   if (som_section_data (osection)->copy_data->container)
-    som_section_data (osection)->copy_data->container =
-      som_section_data (osection)->copy_data->container->output_section;
+    {
+      if (som_section_data (osection)->copy_data->container->output_section)
+       som_section_data (osection)->copy_data->container =
+         som_section_data (osection)->copy_data->container->output_section;
+      else
+       {
+         /* User has specified a subspace without its containing space.  */
+         _bfd_error_handler (_("%pB[%pA]: no output section for space %pA"),
+           obfd, osection, som_section_data (osection)->copy_data->container);
+         return false;
+       }
+    }
 
-  return TRUE;
+  return true;
 }
 
 /* Copy any private info we understand from the input bfd
    to the output bfd.  */
 
-static bfd_boolean
+static bool
 som_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
 {
   /* One day we may try to grok other private data.  */
   if (ibfd->xvec->flavour != bfd_target_som_flavour
       || obfd->xvec->flavour != bfd_target_som_flavour)
-    return TRUE;
+    return true;
 
   /* Allocate some memory to hold the data we need.  */
   obj_som_exec_data (obfd) = bfd_zalloc (obfd, (bfd_size_type) sizeof (struct som_exec_data));
   if (obj_som_exec_data (obfd) == NULL)
-    return FALSE;
+    return false;
 
   /* Now copy the data.  */
   memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
          sizeof (struct som_exec_data));
 
-  return TRUE;
+  return true;
 }
 
 /* Display the SOM header.  */
 
-static bfd_boolean
+static bool
 som_bfd_print_private_bfd_data (bfd *abfd, void *farg)
 {
   struct som_exec_auxhdr *exec_header;
@@ -5505,13 +5478,13 @@ som_bfd_print_private_bfd_data (bfd *abfd, void *farg)
       fprintf (f, "  bss initializer    %#lx\n", (long) exec_header->exec_bfill);
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Set backend info for sections which can not be described
    in the BFD data structures.  */
 
-bfd_boolean
+bool
 bfd_som_set_section_attributes (asection *section,
                                int defined,
                                int private,
@@ -5521,24 +5494,24 @@ bfd_som_set_section_attributes (asection *section,
   /* Allocate memory to hold the magic information.  */
   if (som_section_data (section)->copy_data == NULL)
     {
-      bfd_size_type amt = sizeof (struct som_copyable_section_data_struct);
+      size_t amt = sizeof (struct som_copyable_section_data_struct);
 
       som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
       if (som_section_data (section)->copy_data == NULL)
-       return FALSE;
+       return false;
     }
   som_section_data (section)->copy_data->sort_key = sort_key;
   som_section_data (section)->copy_data->is_defined = defined;
   som_section_data (section)->copy_data->is_private = private;
   som_section_data (section)->copy_data->container = section;
   som_section_data (section)->copy_data->space_number = spnum;
-  return TRUE;
+  return true;
 }
 
 /* Set backend info for subsections which can not be described
    in the BFD data structures.  */
 
-bfd_boolean
+bool
 bfd_som_set_subsection_attributes (asection *section,
                                   asection *container,
                                   int access_ctr,
@@ -5551,11 +5524,11 @@ bfd_som_set_subsection_attributes (asection *section,
   /* Allocate memory to hold the magic information.  */
   if (som_section_data (section)->copy_data == NULL)
     {
-      bfd_size_type amt = sizeof (struct som_copyable_section_data_struct);
+      size_t amt = sizeof (struct som_copyable_section_data_struct);
 
       som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
       if (som_section_data (section)->copy_data == NULL)
-       return FALSE;
+       return false;
     }
   som_section_data (section)->copy_data->sort_key = sort_key;
   som_section_data (section)->copy_data->access_control_bits = access_ctr;
@@ -5564,7 +5537,7 @@ bfd_som_set_subsection_attributes (asection *section,
   som_section_data (section)->copy_data->is_comdat = comdat;
   som_section_data (section)->copy_data->is_common = common;
   som_section_data (section)->copy_data->dup_common = dup_common;
-  return TRUE;
+  return true;
 }
 
 /* Set the full SOM symbol type.  SOM needs far more symbol information
@@ -5582,10 +5555,10 @@ bfd_som_set_symbol_type (asymbol *symbol, unsigned int type)
 /* Attach an auxiliary header to the BFD backend so that it may be
    written into the object file.  */
 
-bfd_boolean
+bool
 bfd_som_attach_aux_hdr (bfd *abfd, int type, char *string)
 {
-  bfd_size_type amt;
+  size_t amt;
 
   if (type == VERSION_AUX_ID)
     {
@@ -5597,7 +5570,7 @@ bfd_som_attach_aux_hdr (bfd *abfd, int type, char *string)
       amt = sizeof (struct som_string_auxhdr) + len + pad;
       obj_som_version_hdr (abfd) = bfd_zalloc (abfd, amt);
       if (!obj_som_version_hdr (abfd))
-       return FALSE;
+       return false;
       obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
       obj_som_version_hdr (abfd)->header_id.length = 4 + len + pad;
       obj_som_version_hdr (abfd)->string_length = len;
@@ -5606,7 +5579,7 @@ bfd_som_attach_aux_hdr (bfd *abfd, int type, char *string)
     }
   else if (type == COPYRIGHT_AUX_ID)
     {
-      int len = strlen (string);
+      size_t len = strlen (string);
       int pad = 0;
 
       if (len % 4)
@@ -5614,20 +5587,20 @@ bfd_som_attach_aux_hdr (bfd *abfd, int type, char *string)
       amt = sizeof (struct som_string_auxhdr) + len + pad;
       obj_som_copyright_hdr (abfd) = bfd_zalloc (abfd, amt);
       if (!obj_som_copyright_hdr (abfd))
-       return FALSE;
+       return false;
       obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
       obj_som_copyright_hdr (abfd)->header_id.length = len + pad + 4;
       obj_som_copyright_hdr (abfd)->string_length = len;
       memcpy (obj_som_copyright_hdr (abfd)->string, string, len);
       memset (obj_som_copyright_hdr (abfd)->string + len, 0, pad);
     }
-  return TRUE;
+  return true;
 }
 
 /* Attach a compilation unit header to the BFD backend so that it may be
    written into the object file.  */
 
-bfd_boolean
+bool
 bfd_som_attach_compilation_unit (bfd *abfd,
                                 const char *name,
                                 const char *language_name,
@@ -5639,14 +5612,14 @@ bfd_som_attach_compilation_unit (bfd *abfd,
   n = (struct som_compilation_unit *) bfd_zalloc
     (abfd, (bfd_size_type) sizeof (*n));
   if (n == NULL)
-    return FALSE;
+    return false;
 
 #define STRDUP(f) \
   if (f != NULL) \
     { \
       n->f.name = bfd_alloc (abfd, (bfd_size_type) strlen (f) + 1); \
       if (n->f.name == NULL) \
-       return FALSE; \
+       return false; \
       strcpy (n->f.name, f); \
     }
 
@@ -5659,10 +5632,10 @@ bfd_som_attach_compilation_unit (bfd *abfd,
 
   obj_som_compilation_unit (abfd) = n;
 
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
+static bool
 som_get_section_contents (bfd *abfd,
                          sec_ptr section,
                          void *location,
@@ -5670,15 +5643,15 @@ som_get_section_contents (bfd *abfd,
                          bfd_size_type count)
 {
   if (count == 0 || ((section->flags & SEC_HAS_CONTENTS) == 0))
-    return TRUE;
-  if ((bfd_size_type) (offset+count) > section->size
-      || bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
-      || bfd_bread (location, count, abfd) != count)
-    return FALSE; /* On error.  */
-  return TRUE;
+    return true;
+  if ((bfd_size_type) (offset + count) > section->size
+      || bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
+      || bfd_read (location, count, abfd) != count)
+    return false; /* On error.  */
+  return true;
 }
 
-static bfd_boolean
+static bool
 som_set_section_contents (bfd *abfd,
                          sec_ptr section,
                          const void *location,
@@ -5690,7 +5663,7 @@ som_set_section_contents (bfd *abfd,
       /* Set up fixed parts of the file, space, and subspace headers.
         Notify the world that output has begun.  */
       som_prep_headers (abfd);
-      abfd->output_has_begun = TRUE;
+      abfd->output_has_begun = true;
       /* Start writing the object file.  This include all the string
         tables, fixup streams, and other portions of the object file.  */
       som_begin_writing (abfd);
@@ -5700,20 +5673,20 @@ som_set_section_contents (bfd *abfd,
      are not generated at run time by the OS).  */
   if (!som_is_subspace (section)
       || ((section->flags & SEC_HAS_CONTENTS) == 0))
-    return TRUE;
+    return true;
 
   /* Seek to the proper offset within the object file and write the
      data.  */
   offset += som_section_data (section)->subspace_dict->file_loc_init_value;
   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
-    return FALSE;
+    return false;
 
-  if (bfd_bwrite (location, count, abfd) != count)
-    return FALSE;
-  return TRUE;
+  if (bfd_write (location, count, abfd) != count)
+    return false;
+  return true;
 }
 
-static bfd_boolean
+static bool
 som_set_arch_mach (bfd *abfd,
                   enum bfd_architecture arch,
                   unsigned long machine)
@@ -5722,7 +5695,7 @@ som_set_arch_mach (bfd *abfd,
   return bfd_default_set_arch_mach (abfd, arch, machine);
 }
 
-static bfd_boolean
+static bool
 som_find_nearest_line (bfd *abfd,
                       asymbol **symbols,
                       asection *section,
@@ -5732,7 +5705,7 @@ som_find_nearest_line (bfd *abfd,
                       unsigned int *line_ptr,
                       unsigned int *discriminator_ptr)
 {
-  bfd_boolean found;
+  bool found;
   asymbol *func;
   bfd_vma low_func;
   asymbol **p;
@@ -5744,13 +5717,13 @@ som_find_nearest_line (bfd *abfd,
                                             & found, filename_ptr,
                                             functionname_ptr, line_ptr,
                                             & somdata (abfd).line_info))
-    return FALSE;
+    return false;
 
   if (found)
-    return TRUE;
+    return true;
 
   if (symbols == NULL)
-    return FALSE;
+    return false;
 
   /* Fallback: find function name from symbols table.  */
   func = NULL;
@@ -5771,13 +5744,13 @@ som_find_nearest_line (bfd *abfd,
     }
 
   if (func == NULL)
-    return FALSE;
+    return false;
 
   *filename_ptr = NULL;
   *functionname_ptr = bfd_asymbol_name (func);
   *line_ptr = 0;
 
-  return TRUE;
+  return true;
 }
 
 static int
@@ -5808,6 +5781,11 @@ som_decode_symclass (asymbol *symbol)
 {
   char c;
 
+  /* If the symbol did not have a scope specified,
+     then it will not have associated section.  */
+  if (symbol == NULL || symbol->section == NULL)
+    return '?';
+
   if (bfd_is_com_section (symbol->section))
     return 'C';
   if (bfd_is_und_section (symbol->section))
@@ -5869,31 +5847,32 @@ som_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
 /* Count the number of symbols in the archive symbol table.  Necessary
    so that we can allocate space for all the carsyms at once.  */
 
-static bfd_boolean
+static bool
 som_bfd_count_ar_symbols (bfd *abfd,
                          struct som_lst_header *lst_header,
                          symindex *count)
 {
   unsigned int i;
   unsigned char *hash_table;
-  bfd_size_type amt;
+  size_t amt;
   file_ptr lst_filepos;
 
   lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
 
-  amt = lst_header->hash_size * 4;
-  hash_table = bfd_malloc (amt);
-  if (hash_table == NULL && amt != 0)
+  /* Read in the hash table.  The hash table is an array of 32-bit
+     file offsets which point to the hash chains.  */
+  if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return false;
+    }
+  hash_table = _bfd_malloc_and_read (abfd, amt, amt);
+  if (hash_table == NULL && lst_header->hash_size != 0)
     goto error_return;
 
   /* Don't forget to initialize the counter!  */
   *count = 0;
 
-  /* Read in the hash table.  The has table is an array of 32bit file offsets
-     which point to the hash chains.  */
-  if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
-    goto error_return;
-
   /* Walk each chain counting the number of symbols found on that particular
      chain.  */
   for (i = 0; i < lst_header->hash_size; i++)
@@ -5911,7 +5890,7 @@ som_bfd_count_ar_symbols (bfd *abfd,
 
       /* Read in this symbol and update the counter.  */
       amt = sizeof (ext_lst_symbol);
-      if (bfd_bread ((void *) &ext_lst_symbol, amt, abfd) != amt)
+      if (bfd_read (&ext_lst_symbol, amt, abfd) != amt)
        goto error_return;
 
       (*count)++;
@@ -5924,32 +5903,39 @@ som_bfd_count_ar_symbols (bfd *abfd,
          if (next_entry == 0)
            break;
 
+         /* Assume symbols on a chain are in increasing file offset
+            order.  Otherwise we can loop here with fuzzed input.  */
+         if (next_entry < hash_val + sizeof (ext_lst_symbol))
+           {
+             bfd_set_error (bfd_error_bad_value);
+             goto error_return;
+           }
+         hash_val = next_entry;
+
          /* Seek to the next symbol.  */
          if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0)
            goto error_return;
 
          /* Read the symbol in and update the counter.  */
          amt = sizeof (ext_lst_symbol);
-         if (bfd_bread ((void *) &ext_lst_symbol, amt, abfd) != amt)
+         if (bfd_read (&ext_lst_symbol, amt, abfd) != amt)
            goto error_return;
 
          (*count)++;
        }
     }
-  if (hash_table != NULL)
-    free (hash_table);
-  return TRUE;
+  free (hash_table);
+  return true;
 
  error_return:
-  if (hash_table != NULL)
-    free (hash_table);
-  return FALSE;
+  free (hash_table);
+  return false;
 }
 
 /* Fill in the canonical archive symbols (SYMS) from the archive described
    by ABFD and LST_HEADER.  */
 
-static bfd_boolean
+static bool
 som_bfd_fill_in_ar_symbols (bfd *abfd,
                            struct som_lst_header *lst_header,
                            carsym **syms)
@@ -5958,19 +5944,21 @@ som_bfd_fill_in_ar_symbols (bfd *abfd,
   carsym *set = syms[0];
   unsigned char *hash_table;
   struct som_external_som_entry *som_dict = NULL;
-  bfd_size_type amt;
+  size_t amt;
   file_ptr lst_filepos;
   unsigned int string_loc;
 
   lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
-  amt = lst_header->hash_size * 4;
-  hash_table = bfd_malloc (amt);
-  if (hash_table == NULL && amt != 0)
-    goto error_return;
 
   /* Read in the hash table.  The has table is an array of 32bit file offsets
      which point to the hash chains.  */
-  if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
+  if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return false;
+    }
+  hash_table = _bfd_malloc_and_read (abfd, amt, amt);
+  if (hash_table == NULL && lst_header->hash_size != 0)
     goto error_return;
 
   /* Seek to and read in the SOM dictionary.  We will need this to fill
@@ -5978,12 +5966,15 @@ som_bfd_fill_in_ar_symbols (bfd *abfd,
   if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) != 0)
     goto error_return;
 
-  amt = lst_header->module_count * sizeof (struct som_external_som_entry);
-  som_dict = bfd_malloc (amt);
-  if (som_dict == NULL && amt != 0)
-    goto error_return;
-
-  if (bfd_bread ((void *) som_dict, amt, abfd) != amt)
+  if (_bfd_mul_overflow (lst_header->module_count,
+                        sizeof (struct som_external_som_entry), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      goto error_return;
+    }
+  som_dict = (struct som_external_som_entry *)
+    _bfd_malloc_and_read (abfd, amt, amt);
+  if (som_dict == NULL && lst_header->module_count != 0)
     goto error_return;
 
   string_loc = lst_header->string_loc;
@@ -5993,8 +5984,10 @@ som_bfd_fill_in_ar_symbols (bfd *abfd,
     {
       struct som_external_lst_symbol_record lst_symbol;
       unsigned int hash_val;
-      unsigned int len;
+      size_t len;
       unsigned char ext_len[4];
+      char *name;
+      unsigned int ndx;
 
       /* An empty chain has zero as it's file offset.  */
       hash_val = bfd_getb32 (hash_table + 4 * i);
@@ -6006,7 +5999,7 @@ som_bfd_fill_in_ar_symbols (bfd *abfd,
        goto error_return;
 
       amt = sizeof (lst_symbol);
-      if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
+      if (bfd_read (&lst_symbol, amt, abfd) != amt)
        goto error_return;
 
       /* Get the name of the symbol, first get the length which is stored
@@ -6020,24 +6013,32 @@ som_bfd_fill_in_ar_symbols (bfd *abfd,
                           + bfd_getb32 (lst_symbol.name) - 4), SEEK_SET) != 0)
        goto error_return;
 
-      if (bfd_bread (&ext_len, (bfd_size_type) 4, abfd) != 4)
+      if (bfd_read (&ext_len, 4, abfd) != 4)
        goto error_return;
       len = bfd_getb32 (ext_len);
 
       /* Allocate space for the name and null terminate it too.  */
-      set->name = bfd_zalloc (abfd, (bfd_size_type) len + 1);
-      if (!set->name)
-       goto error_return;
-      if (bfd_bread (set->name, (bfd_size_type) len, abfd) != len)
+      if (len == (size_t) -1)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         goto error_return;
+       }
+      name = (char *) _bfd_alloc_and_read (abfd, len + 1, len);
+      if (!name)
        goto error_return;
-
-      set->name[len] = 0;
+      name[len] = 0;
+      set->name = name;
 
       /* Fill in the file offset.  Note that the "location" field points
         to the SOM itself, not the ar_hdr in front of it.  */
-      set->file_offset =
-       bfd_getb32 (som_dict[bfd_getb32 (lst_symbol.som_index)].location)
-       - sizeof (struct ar_hdr);
+      ndx = bfd_getb32 (lst_symbol.som_index);
+      if (ndx >= lst_header->module_count)
+       {
+         bfd_set_error (bfd_error_bad_value);
+         goto error_return;
+       }
+      set->file_offset
+       = bfd_getb32 (som_dict[ndx].location) - sizeof (struct ar_hdr);
 
       /* Go to the next symbol.  */
       set++;
@@ -6055,7 +6056,7 @@ som_bfd_fill_in_ar_symbols (bfd *abfd,
            goto error_return;
 
          amt = sizeof (lst_symbol);
-         if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
+         if (bfd_read (&lst_symbol, amt, abfd) != amt)
            goto error_return;
 
          /* Seek to the name length & string and read them in.  */
@@ -6063,24 +6064,32 @@ som_bfd_fill_in_ar_symbols (bfd *abfd,
                        + bfd_getb32 (lst_symbol.name) - 4, SEEK_SET) != 0)
            goto error_return;
 
-         if (bfd_bread (&ext_len, (bfd_size_type) 4, abfd) != 4)
+         if (bfd_read (&ext_len, 4, abfd) != 4)
            goto error_return;
          len = bfd_getb32 (ext_len);
 
          /* Allocate space for the name and null terminate it too.  */
-         set->name = bfd_zalloc (abfd, (bfd_size_type) len + 1);
-         if (!set->name)
-           goto error_return;
-
-         if (bfd_bread (set->name, (bfd_size_type) len, abfd) != len)
+         if (len == (size_t) -1)
+           {
+             bfd_set_error (bfd_error_no_memory);
+             goto error_return;
+           }
+         name = (char *) _bfd_alloc_and_read (abfd, len + 1, len);
+         if (!name)
            goto error_return;
-         set->name[len] = 0;
+         name[len] = 0;
+         set->name = name;
 
          /* Fill in the file offset.  Note that the "location" field points
             to the SOM itself, not the ar_hdr in front of it.  */
-         set->file_offset =
-           bfd_getb32 (som_dict[bfd_getb32 (lst_symbol.som_index)].location)
-           - sizeof (struct ar_hdr);
+         ndx = bfd_getb32 (lst_symbol.som_index);
+         if (ndx >= lst_header->module_count)
+           {
+             bfd_set_error (bfd_error_bad_value);
+             goto error_return;
+           }
+         set->file_offset
+           = bfd_getb32 (som_dict[ndx].location) - sizeof (struct ar_hdr);
 
          /* Go on to the next symbol.  */
          set++;
@@ -6088,23 +6097,19 @@ som_bfd_fill_in_ar_symbols (bfd *abfd,
     }
   /* If we haven't died by now, then we successfully read the entire
      archive symbol table.  */
-  if (hash_table != NULL)
-    free (hash_table);
-  if (som_dict != NULL)
-    free (som_dict);
-  return TRUE;
+  free (hash_table);
+  free (som_dict);
+  return true;
 
  error_return:
-  if (hash_table != NULL)
-    free (hash_table);
-  if (som_dict != NULL)
-    free (som_dict);
-  return FALSE;
+  free (hash_table);
+  free (som_dict);
+  return false;
 }
 
 /* Read in the LST from the archive.  */
 
-static bfd_boolean
+static bool
 som_slurp_armap (bfd *abfd)
 {
   struct som_external_lst_header ext_lst_header;
@@ -6113,34 +6118,34 @@ som_slurp_armap (bfd *abfd)
   unsigned int parsed_size;
   struct artdata *ardata = bfd_ardata (abfd);
   char nextname[17];
-  bfd_size_type amt = 16;
-  int i = bfd_bread ((void *) nextname, amt, abfd);
+  size_t amt = 16;
+  int i = bfd_read (nextname, amt, abfd);
 
   /* Special cases.  */
   if (i == 0)
-    return TRUE;
+    return true;
   if (i != 16)
-    return FALSE;
+    return false;
 
-  if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
-    return FALSE;
+  if (bfd_seek (abfd, -16, SEEK_CUR) != 0)
+    return false;
 
   /* For archives without .o files there is no symbol table.  */
-  if (! CONST_STRNEQ (nextname, "/               "))
+  if (! startswith (nextname, "/               "))
     {
-      bfd_has_map (abfd) = FALSE;
-      return TRUE;
+      abfd->has_armap = false;
+      return true;
     }
 
   /* Read in and sanity check the archive header.  */
   amt = sizeof (struct ar_hdr);
-  if (bfd_bread ((void *) &ar_header, amt, abfd) != amt)
-    return FALSE;
+  if (bfd_read (&ar_header, amt, abfd) != amt)
+    return false;
 
   if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
     {
       bfd_set_error (bfd_error_malformed_archive);
-      return FALSE;
+      return false;
     }
 
   /* How big is the archive symbol table entry?  */
@@ -6149,7 +6154,7 @@ som_slurp_armap (bfd *abfd)
   if (errno != 0)
     {
       bfd_set_error (bfd_error_malformed_archive);
-      return FALSE;
+      return false;
     }
 
   /* Save off the file offset of the first real user data.  */
@@ -6158,8 +6163,8 @@ som_slurp_armap (bfd *abfd)
   /* Read in the library symbol table.  We'll make heavy use of this
      in just a minute.  */
   amt = sizeof (struct som_external_lst_header);
-  if (bfd_bread ((void *) &ext_lst_header, amt, abfd) != amt)
-    return FALSE;
+  if (bfd_read (&ext_lst_header, amt, abfd) != amt)
+    return false;
 
   som_swap_lst_header_in (&ext_lst_header, &lst_header);
 
@@ -6167,39 +6172,42 @@ som_slurp_armap (bfd *abfd)
   if (lst_header.a_magic != LIBMAGIC)
     {
       bfd_set_error (bfd_error_malformed_archive);
-      return FALSE;
+      return false;
     }
 
   /* Count the number of symbols in the library symbol table.  */
   if (! som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count))
-    return FALSE;
+    return false;
 
   /* Get back to the start of the library symbol table.  */
   if (bfd_seek (abfd, (ardata->first_file_filepos - parsed_size
                       + sizeof (struct som_external_lst_header)),
                SEEK_SET) != 0)
-    return FALSE;
+    return false;
 
   /* Initialize the cache and allocate space for the library symbols.  */
   ardata->cache = 0;
-  amt = ardata->symdef_count;
-  amt *= sizeof (carsym);
+  if (_bfd_mul_overflow (ardata->symdef_count, sizeof (carsym), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return false;
+    }
   ardata->symdefs = bfd_alloc (abfd, amt);
   if (!ardata->symdefs)
-    return FALSE;
+    return false;
 
   /* Now fill in the canonical archive symbols.  */
   if (! som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs))
-    return FALSE;
+    return false;
 
   /* Seek back to the "first" file in the archive.  Note the "first"
      file may be the extended name table.  */
   if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) != 0)
-    return FALSE;
+    return false;
 
   /* Notify the generic archive code that we have a symbol map.  */
-  bfd_has_map (abfd) = TRUE;
-  return TRUE;
+  abfd->has_armap = true;
+  return true;
 }
 
 /* Begin preparing to write a SOM library symbol table.
@@ -6207,7 +6215,7 @@ som_slurp_armap (bfd *abfd)
    As part of the prep work we need to determine the number of symbols
    and the size of the associated string section.  */
 
-static bfd_boolean
+static bool
 som_bfd_prep_for_ar_write (bfd *abfd,
                           unsigned int *num_syms,
                           unsigned int *stringsize)
@@ -6236,7 +6244,7 @@ som_bfd_prep_for_ar_write (bfd *abfd,
         to it.  It's a little slimey to grab the symbols via obj_som_symtab,
         but doing so avoids allocating lots of extra memory.  */
       if (! som_slurp_symbol_table (curr_bfd))
-       return FALSE;
+       return false;
 
       sym = obj_som_symtab (curr_bfd);
       curr_count = bfd_get_symcount (curr_bfd);
@@ -6275,7 +6283,7 @@ som_bfd_prep_for_ar_write (bfd *abfd,
 
       curr_bfd = curr_bfd->archive_next;
     }
-  return TRUE;
+  return true;
 }
 
 /* Hash a symbol name based on the hashing algorithm presented in the
@@ -6297,7 +6305,7 @@ som_bfd_ar_symbol_hash (asymbol *symbol)
 /* Do the bulk of the work required to write the SOM library
    symbol table.  */
 
-static bfd_boolean
+static bool
 som_bfd_ar_write_symbol_stuff (bfd *abfd,
                               unsigned int nsyms,
                               unsigned int string_size,
@@ -6311,23 +6319,38 @@ som_bfd_ar_write_symbol_stuff (bfd *abfd,
   struct som_external_som_entry *som_dict = NULL;
   struct som_external_lst_symbol_record **last_hash_entry = NULL;
   unsigned int curr_som_offset, som_index = 0;
-  bfd_size_type amt;
+  size_t amt;
   unsigned int module_count;
   unsigned int hash_size;
 
   hash_size = bfd_getb32 (lst.hash_size);
-  amt = hash_size * 4;
+  if (_bfd_mul_overflow (hash_size, 4, &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return false;
+    }
   hash_table = bfd_zmalloc (amt);
   if (hash_table == NULL && hash_size != 0)
     goto error_return;
 
   module_count = bfd_getb32 (lst.module_count);
-  amt = module_count * sizeof (struct som_external_som_entry);
+  if (_bfd_mul_overflow (module_count,
+                        sizeof (struct som_external_som_entry), &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      goto error_return;
+    }
   som_dict = bfd_zmalloc (amt);
   if (som_dict == NULL && module_count != 0)
     goto error_return;
 
-  amt = hash_size * sizeof (struct som_external_lst_symbol_record *);
+  if (_bfd_mul_overflow (hash_size,
+                        sizeof (struct som_external_lst_symbol_record *),
+                        &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      goto error_return;
+    }
   last_hash_entry = bfd_zmalloc (amt);
   if (last_hash_entry == NULL && hash_size != 0)
     goto error_return;
@@ -6356,12 +6379,16 @@ som_bfd_ar_write_symbol_stuff (bfd *abfd,
   curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
 
   /* FIXME should be done with buffers just like everything else...  */
-  amt = nsyms;
-  amt *= sizeof (struct som_external_lst_symbol_record);
+  if (_bfd_mul_overflow (nsyms,
+                        sizeof (struct som_external_lst_symbol_record), &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      goto error_return;
+    }
   lst_syms = bfd_malloc (amt);
   if (lst_syms == NULL && nsyms != 0)
     goto error_return;
-  strings = bfd_malloc ((bfd_size_type) string_size);
+  strings = bfd_malloc (string_size);
   if (strings == NULL && string_size != 0)
     goto error_return;
 
@@ -6506,57 +6533,47 @@ som_bfd_ar_write_symbol_stuff (bfd *abfd,
     }
 
   /* Now scribble out the hash table.  */
-  amt = hash_size * 4;
-  if (bfd_bwrite ((void *) hash_table, amt, abfd) != amt)
+  amt = (size_t) hash_size * 4;
+  if (bfd_write (hash_table, amt, abfd) != amt)
     goto error_return;
 
   /* Then the SOM dictionary.  */
-  amt = module_count * sizeof (struct som_external_som_entry);
-  if (bfd_bwrite ((void *) som_dict, amt, abfd) != amt)
+  amt = (size_t) module_count * sizeof (struct som_external_som_entry);
+  if (bfd_write (som_dict, amt, abfd) != amt)
     goto error_return;
 
   /* The library symbols.  */
-  amt = nsyms * sizeof (struct som_external_lst_symbol_record);
-  if (bfd_bwrite ((void *) lst_syms, amt, abfd) != amt)
+  amt = (size_t) nsyms * sizeof (struct som_external_lst_symbol_record);
+  if (bfd_write (lst_syms, amt, abfd) != amt)
     goto error_return;
 
   /* And finally the strings.  */
   amt = string_size;
-  if (bfd_bwrite ((void *) strings, amt, abfd) != amt)
+  if (bfd_write (strings, amt, abfd) != amt)
     goto error_return;
 
-  if (hash_table != NULL)
-    free (hash_table);
-  if (som_dict != NULL)
-    free (som_dict);
-  if (last_hash_entry != NULL)
-    free (last_hash_entry);
-  if (lst_syms != NULL)
-    free (lst_syms);
-  if (strings != NULL)
-    free (strings);
-  return TRUE;
+  free (hash_table);
+  free (som_dict);
+  free (last_hash_entry);
+  free (lst_syms);
+  free (strings);
+  return true;
 
  error_return:
-  if (hash_table != NULL)
-    free (hash_table);
-  if (som_dict != NULL)
-    free (som_dict);
-  if (last_hash_entry != NULL)
-    free (last_hash_entry);
-  if (lst_syms != NULL)
-    free (lst_syms);
-  if (strings != NULL)
-    free (strings);
-
-  return FALSE;
+  free (hash_table);
+  free (som_dict);
+  free (last_hash_entry);
+  free (lst_syms);
+  free (strings);
+
+  return false;
 }
 
 /* Write out the LST for the archive.
 
    You'll never believe this is really how armaps are handled in SOM...  */
 
-static bfd_boolean
+static bool
 som_write_armap (bfd *abfd,
                 unsigned int elength,
                 struct orl *map ATTRIBUTE_UNUSED,
@@ -6569,15 +6586,15 @@ som_write_armap (bfd *abfd,
   struct ar_hdr hdr;
   struct som_external_lst_header lst;
   unsigned char *p;
-  bfd_size_type amt;
+  size_t amt;
   unsigned int csum;
   unsigned int module_count;
 
   /* We'll use this for the archive's date and mode later.  */
-  if (stat (abfd->filename, &statbuf) != 0)
+  if (stat (bfd_get_filename (abfd), &statbuf) != 0)
     {
       bfd_set_error (bfd_error_system_call);
-      return FALSE;
+      return false;
     }
   /* Fudge factor.  */
   bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
@@ -6629,7 +6646,7 @@ som_write_armap (bfd *abfd,
   /* Count how many symbols we will have on the hash chains and the
      size of the associated string table.  */
   if (! som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize))
-    return FALSE;
+    return false;
 
   lst_size += sizeof (struct som_external_lst_symbol_record) * nsyms;
 
@@ -6673,33 +6690,33 @@ som_write_armap (bfd *abfd,
 
   /* Scribble out the ar header.  */
   amt = sizeof (struct ar_hdr);
-  if (bfd_bwrite ((void *) &hdr, amt, abfd) != amt)
-    return FALSE;
+  if (bfd_write (&hdr, amt, abfd) != amt)
+    return false;
 
   /* Now scribble out the lst header.  */
   amt = sizeof (struct som_external_lst_header);
-  if (bfd_bwrite ((void *) &lst, amt, abfd) != amt)
-    return FALSE;
+  if (bfd_write (&lst, amt, abfd) != amt)
+    return false;
 
   /* Build and write the armap.  */
   if (!som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst, elength))
-    return FALSE;
+    return false;
 
   /* Done.  */
-  return TRUE;
+  return true;
 }
 
-/* Free all information we have cached for this BFD.  We can always
-   read it again later if we need it.  */
+/* Throw away some malloc'd information for this BFD.  */
 
-static bfd_boolean
+static bool
 som_bfd_free_cached_info (bfd *abfd)
 {
-  if (bfd_get_format (abfd) == bfd_object)
+  if (bfd_get_format (abfd) == bfd_object
+      || bfd_get_format (abfd) == bfd_core)
     {
       asection *o;
 
-#define FREE(x) if (x != NULL) { free (x); x = NULL; }
+#define FREE(x) do { free (x); x = NULL; } while (0)
       /* Free the native string and symbol tables.  */
       FREE (obj_som_symtab (abfd));
       FREE (obj_som_stringtab (abfd));
@@ -6713,14 +6730,16 @@ som_bfd_free_cached_info (bfd *abfd)
 #undef FREE
     }
 
-  return _bfd_generic_close_and_cleanup (abfd);
+  /* Do not call _bfd_generic_bfd_free_cached_info here.
+     som_write_armap needs to access the bfd objalloc memory.  */
+  return true;
 }
 
 /* End of miscellaneous support functions.  */
 
 /* Linker support functions.  */
 
-static bfd_boolean
+static bool
 som_bfd_link_split_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
 {
   return som_is_subspace (sec) && sec->size > 240000;
@@ -6728,7 +6747,7 @@ som_bfd_link_split_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
 
 #define som_find_line                          _bfd_nosymbols_find_line
 #define som_get_symbol_version_string          _bfd_nosymbols_get_symbol_version_string
-#define        som_close_and_cleanup                   som_bfd_free_cached_info
+#define som_close_and_cleanup                  _bfd_generic_close_and_cleanup
 #define som_read_ar_hdr                                _bfd_generic_read_ar_hdr
 #define som_write_ar_hdr                       _bfd_generic_write_ar_hdr
 #define som_openr_next_archived_file           bfd_generic_openr_next_archived_file
@@ -6787,6 +6806,7 @@ const bfd_target hppa_som_vec =
   '/',                         /* AR_pad_char.  */
   14,                          /* AR_max_namelen.  */
   0,                           /* match priority.  */
+  TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
   bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* Data.  */