More patches from Jeff Law, plus a little cleanup of my own.
authorKen Raeburn <raeburn@cygnus>
Sat, 28 Aug 1993 00:10:54 +0000 (00:10 +0000)
committerKen Raeburn <raeburn@cygnus>
Sat, 28 Aug 1993 00:10:54 +0000 (00:10 +0000)
These changes separate PA-SOM support from PA-ELF support.
A sun4-x-hppaosf assembler can now be built.

* elf32-hppa.c (elf_hppa_howto_table): Now static.
(symext_rootP, symext_lastP, global_value, GOT_value, global_symbol,
global_sym_defined, symextn_contents, symextn_contents_real_size,
elf_hppa_stub_rootP, elf32_hppa_symextn_map, elf32_hppa_symextn_map_size): Rely
on default initialization.
(hppa_elf_gen_reloc_type): Macro "UNDEFINED" doesn't need a trailing semicolon.
(hppa_look_for_stubs_in_section): Introduce temporaries to make code more
readable in 80 columns.

* libhppa.h (all functions): Now inline under GNU C.

* elf32-hppa.c (AR_WARN): Give argument which caused the invalid argument
relocation.
(AR_UNIMP): Delete unused macro.
(hppa_elf_set_section_contents): Always return a value.
(elf32_hppa_backend_table_processing): Likewise.
(elf32_hppa_backend_section_processing: Likewise.

* som.c: New file containing SOM specific code extracted from hppa.c

* som.h: New file containing SOM specific code extracted from libhppa.h

* hppa.c: Deleted.

* libhppa.h: Delete SOM specific code.  Add generic PA code which can be shared
by both SOM and ELF backends.

* Makefile.in: Replace hppa.c with som.c.  elf32-hppa.o depends on libhppa.h
now.

* configure.in (hppa_vec): Needs som.o module instead of hppa.o.

* elf32-hppa.c: Include libhppa.h.  Do not define BYTES_IN_WORD.

* elf32-hppa.h (hppa_reloc_field_selector_type): Delete now lives in libhppa.h.
(hppa_reloc_field_selector_type_alt): Likewise.

* elf32-hppa.c (hppa_elf_relocate_unwind_table): Delete unused variables.
(elf_hppa_reloc_type_lookup): Likewise.
(elf_hppa_tc_make_sections): Likewise.
(hppa_elf_arg_reloc_needed_p): Likewise.
(hppa_elf_build_long_branch_stub): Likewise.
(elf_reloc_map): Delete, no longer used.
(elf_hppa_reloc_map): Likewise.
(elf32_hppa_symextn_map_max_size): Likewise.
(elf32_hppa_get_sym_extn): Abort if type is bogus.

* elf32-hppa.c (elf32_hppa_backend_fake_sections): Add processing
of the .hppa_unwind section.

bfd/configure.in
bfd/elf32-hppa.c
bfd/elf32-hppa.h
bfd/libhppa.h
bfd/som.c [new file with mode: 0644]

index 2c375fe425ca2963124e3f6dac171dcd1e4f5438..9f236379368205a98bc9d86e2db49d86f179bdb5 100644 (file)
@@ -51,6 +51,10 @@ for targ in $target $canon_targets
 do
     bfd_target=`$srcdir/config.bfd $targ`
 
+    case "$targ" in
+       netbsd386)      bfd_target=i386-netbsd ;;
+    esac
+
     if [ "x$bfd_target" = "xall" ]; then
         all_targets=true
     else
@@ -171,9 +175,10 @@ if [ x${all_targets} = xfalse ]; then
        host_aout_vec)          tb="$tb host-aout.o aout32.o stab-syms.o" ;;
        hp300bsd_vec)           tb="$tb hp300bsd.o aout32.o stab-syms.o" ;;
        hp300hpux_vec)          tb="$tb hp300hpux.o aout32.o stab-syms.o" ;;
-       hppa_vec)               tb="$tb hppa.o" ;;
+       hppa_vec)               tb="$tb som.o" ;;
        i386aout_vec)           tb="$tb i386aout.o aout32.o stab-syms.o" ;;
        i386bsd_vec)            tb="$tb i386bsd.o aout32.o stab-syms.o" ;;
+       netbsd386_vec)          tb="$tb netbsd386.o aout32.o stab-syms.o" ;;
        i386coff_vec)           tb="$tb coff-i386.o" ;;
        i386linux_vec)          tb="$tb i386linux.o aout32.o stab-syms.o" ;;
        i386lynx_vec)           tb="$tb i386lynx.o aout32.o stab-syms.o" ;;
index afc4011ccee06eece2665152463f37b371b95e21..99801bd7c3dbcb30012bb6da3f31245670761cac 100644 (file)
@@ -45,156 +45,157 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 */
 
 #include "elf32-hppa.h"
-/*#include "libhppa.h"*/
-#define BYTES_IN_WORD 4
+#include "libhppa.h"
 #include "aout/aout64.h"
+#include "hppa_stubs.h"
 
 /* ELF/PA relocation howto entries */
 
 static bfd_reloc_status_type hppa_elf_reloc ();
 
-reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] =
+static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] =
 {
 /*  'bitpos' and 'abs' are obsolete */
 /* type                        rs sz bsz pcrel  bpos abs    ovrf  sf              name */
 /* 9.3.4. Address relocation types */
-  {R_HPPA_NONE, 0, 3, 19, false, 0, false, true, hppa_elf_reloc, "R_HPPA_NONE"},
-  {R_HPPA_32, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_32"},
-  {R_HPPA_11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_11"},
-  {R_HPPA_14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_14"},
-  {R_HPPA_17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_17"},
-{R_HPPA_L21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_L21"},
-{R_HPPA_R11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_R11"},
-{R_HPPA_R14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_R14"},
-{R_HPPA_R17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_R17"},
-  {R_HPPA_LS21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LS21"},
-  {R_HPPA_RS11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RS11"},
-  {R_HPPA_RS14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RS14"},
-  {R_HPPA_RS17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RS17"},
-  {R_HPPA_LD21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LD21"},
-  {R_HPPA_RD11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RD11"},
-  {R_HPPA_RD14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RD14"},
-  {R_HPPA_RD17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RD17"},
-  {R_HPPA_LR21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LR21"},
-  {R_HPPA_RR14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RR14"},
-  {R_HPPA_RR17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RR17"},
+  {R_HPPA_NONE, 0, 3, 19, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_NONE"},
+  {R_HPPA_32, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_32"},
+  {R_HPPA_11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_11"},
+  {R_HPPA_14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_14"},
+  {R_HPPA_17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_17"},
+{R_HPPA_L21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_L21"},
+{R_HPPA_R11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_R11"},
+{R_HPPA_R14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_R14"},
+{R_HPPA_R17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_R17"},
+  {R_HPPA_LS21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_LS21"},
+  {R_HPPA_RS11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RS11"},
+  {R_HPPA_RS14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RS14"},
+  {R_HPPA_RS17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RS17"},
+  {R_HPPA_LD21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_LD21"},
+  {R_HPPA_RD11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RD11"},
+  {R_HPPA_RD14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RD14"},
+  {R_HPPA_RD17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RD17"},
+  {R_HPPA_LR21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_LR21"},
+  {R_HPPA_RR14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RR14"},
+  {R_HPPA_RR17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RR17"},
 /* 9.3.5. GOTOFF address relocation types              */
-  {R_HPPA_GOTOFF_11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_11"},
-  {R_HPPA_GOTOFF_14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_14"},
-  {R_HPPA_GOTOFF_L21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_L21"},
-  {R_HPPA_GOTOFF_R11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_R11"},
-  {R_HPPA_GOTOFF_R14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_R14"},
-  {R_HPPA_GOTOFF_LS21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_LS21"},
-  {R_HPPA_GOTOFF_RS11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RS11"},
-  {R_HPPA_GOTOFF_RS14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RS14"},
-  {R_HPPA_GOTOFF_LD21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_LD21"},
-  {R_HPPA_GOTOFF_RD11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RD11"},
-  {R_HPPA_GOTOFF_RD14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RD14"},
-  {R_HPPA_GOTOFF_LR21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_LR21"},
-  {R_HPPA_GOTOFF_RR14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RR14"},
+  {R_HPPA_GOTOFF_11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_11"},
+  {R_HPPA_GOTOFF_14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_14"},
+  {R_HPPA_GOTOFF_L21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_L21"},
+  {R_HPPA_GOTOFF_R11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_R11"},
+  {R_HPPA_GOTOFF_R14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_R14"},
+  {R_HPPA_GOTOFF_LS21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_LS21"},
+  {R_HPPA_GOTOFF_RS11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_RS11"},
+  {R_HPPA_GOTOFF_RS14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_RS14"},
+  {R_HPPA_GOTOFF_LD21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_LD21"},
+  {R_HPPA_GOTOFF_RD11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_RD11"},
+  {R_HPPA_GOTOFF_RD14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_RD14"},
+  {R_HPPA_GOTOFF_LR21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_LR21"},
+  {R_HPPA_GOTOFF_RR14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_RR14"},
 /* 9.3.6. Absolute call relocation types       */
-  {R_HPPA_ABS_CALL_11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_11"},
-  {R_HPPA_ABS_CALL_14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_14"},
-  {R_HPPA_ABS_CALL_17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_17"},
-  {R_HPPA_ABS_CALL_L21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_L21"},
-  {R_HPPA_ABS_CALL_R11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_R11"},
-  {R_HPPA_ABS_CALL_R14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_R14"},
-  {R_HPPA_ABS_CALL_R17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_R17"},
-  {R_HPPA_ABS_CALL_LS21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_LS21"},
-  {R_HPPA_ABS_CALL_RS11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS11"},
-  {R_HPPA_ABS_CALL_RS14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS14"},
-  {R_HPPA_ABS_CALL_RS17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS17"},
-  {R_HPPA_ABS_CALL_LD21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_LD21"},
-  {R_HPPA_ABS_CALL_RD11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD11"},
-  {R_HPPA_ABS_CALL_RD14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD14"},
-  {R_HPPA_ABS_CALL_RD17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD17"},
-  {R_HPPA_ABS_CALL_LR21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_LR21"},
-  {R_HPPA_ABS_CALL_RR14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RR14"},
-  {R_HPPA_ABS_CALL_RR17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RR17"},
+  {R_HPPA_ABS_CALL_11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_11"},
+  {R_HPPA_ABS_CALL_14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_14"},
+  {R_HPPA_ABS_CALL_17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_17"},
+  {R_HPPA_ABS_CALL_L21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_L21"},
+  {R_HPPA_ABS_CALL_R11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_R11"},
+  {R_HPPA_ABS_CALL_R14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_R14"},
+  {R_HPPA_ABS_CALL_R17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_R17"},
+  {R_HPPA_ABS_CALL_LS21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_LS21"},
+  {R_HPPA_ABS_CALL_RS11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS11"},
+  {R_HPPA_ABS_CALL_RS14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS14"},
+  {R_HPPA_ABS_CALL_RS17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS17"},
+  {R_HPPA_ABS_CALL_LD21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_LD21"},
+  {R_HPPA_ABS_CALL_RD11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD11"},
+  {R_HPPA_ABS_CALL_RD14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD14"},
+  {R_HPPA_ABS_CALL_RD17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD17"},
+  {R_HPPA_ABS_CALL_LR21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_LR21"},
+  {R_HPPA_ABS_CALL_RR14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RR14"},
+  {R_HPPA_ABS_CALL_RR17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RR17"},
 /* 9.3.7. PC-relative call relocation types    */
-  {R_HPPA_PCREL_CALL_11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_11"},
-  {R_HPPA_PCREL_CALL_14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_14"},
-  {R_HPPA_PCREL_CALL_17, 0, 3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_17"},
-  {R_HPPA_PCREL_CALL_12, 0, 3, 12, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_12"},
-  {R_HPPA_PCREL_CALL_L21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_L21"},
-  {R_HPPA_PCREL_CALL_R11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R11"},
-  {R_HPPA_PCREL_CALL_R14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R14"},
-  {R_HPPA_PCREL_CALL_R17, 0, 3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R17"},
-  {R_HPPA_PCREL_CALL_LS21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LS21"},
-  {R_HPPA_PCREL_CALL_RS11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS11"},
-  {R_HPPA_PCREL_CALL_RS14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS14"},
-  {R_HPPA_PCREL_CALL_RS17, 0, 3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS17"},
-  {R_HPPA_PCREL_CALL_LD21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LD21"},
-  {R_HPPA_PCREL_CALL_RD11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD11"},
-  {R_HPPA_PCREL_CALL_RD14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD14"},
-  {R_HPPA_PCREL_CALL_RD17, 0, 3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD17"},
-  {R_HPPA_PCREL_CALL_LR21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LR21"},
-  {R_HPPA_PCREL_CALL_RR14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RR14"},
-  {R_HPPA_PCREL_CALL_RR17, 0, 3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RR17"},
+  {R_HPPA_PCREL_CALL_11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_11"},
+  {R_HPPA_PCREL_CALL_14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_14"},
+  {R_HPPA_PCREL_CALL_17, 0, 3, 17, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_17"},
+  {R_HPPA_PCREL_CALL_12, 0, 3, 12, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_12"},
+  {R_HPPA_PCREL_CALL_L21, 0, 3, 21, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_L21"},
+  {R_HPPA_PCREL_CALL_R11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R11"},
+  {R_HPPA_PCREL_CALL_R14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R14"},
+  {R_HPPA_PCREL_CALL_R17, 0, 3, 17, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R17"},
+  {R_HPPA_PCREL_CALL_LS21, 0, 3, 21, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LS21"},
+  {R_HPPA_PCREL_CALL_RS11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS11"},
+  {R_HPPA_PCREL_CALL_RS14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS14"},
+  {R_HPPA_PCREL_CALL_RS17, 0, 3, 17, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS17"},
+  {R_HPPA_PCREL_CALL_LD21, 0, 3, 21, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LD21"},
+  {R_HPPA_PCREL_CALL_RD11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD11"},
+  {R_HPPA_PCREL_CALL_RD14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD14"},
+  {R_HPPA_PCREL_CALL_RD17, 0, 3, 17, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD17"},
+  {R_HPPA_PCREL_CALL_LR21, 0, 3, 21, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LR21"},
+  {R_HPPA_PCREL_CALL_RR14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RR14"},
+  {R_HPPA_PCREL_CALL_RR17, 0, 3, 17, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RR17"},
 
 /* 9.3.8. Plabel relocation types */
-  {R_HPPA_PLABEL_32, 0, 3, 32, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_32"},
-  {R_HPPA_PLABEL_11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_11"},
-  {R_HPPA_PLABEL_14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_14"},
-  {R_HPPA_PLABEL_L21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_L21"},
-  {R_HPPA_PLABEL_R11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_R11"},
-  {R_HPPA_PLABEL_R14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_R14"},
+  {R_HPPA_PLABEL_32, 0, 3, 32, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PLABEL_32"},
+  {R_HPPA_PLABEL_11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PLABEL_11"},
+  {R_HPPA_PLABEL_14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PLABEL_14"},
+  {R_HPPA_PLABEL_L21, 0, 3, 21, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PLABEL_L21"},
+  {R_HPPA_PLABEL_R11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PLABEL_R11"},
+  {R_HPPA_PLABEL_R14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PLABEL_R14"},
 
 /* 9.3.9. Data linkage table (DLT) relocation types    */
-  {R_HPPA_DLT_32, 0, 3, 32, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_32"},
-  {R_HPPA_DLT_11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_11"},
-  {R_HPPA_DLT_14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_14"},
-  {R_HPPA_DLT_L21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_L21"},
-  {R_HPPA_DLT_R11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_R11"},
-  {R_HPPA_DLT_R14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_R14"},
+  {R_HPPA_DLT_32, 0, 3, 32, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_DLT_32"},
+  {R_HPPA_DLT_11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_DLT_11"},
+  {R_HPPA_DLT_14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_DLT_14"},
+  {R_HPPA_DLT_L21, 0, 3, 21, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_DLT_L21"},
+  {R_HPPA_DLT_R11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_DLT_R11"},
+  {R_HPPA_DLT_R14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_DLT_R14"},
 
 /* 9.3.10. Relocations for unwinder tables     */
-  {R_HPPA_UNWIND_ENTRY, 0, 3, 32, true, 0, false, true, hppa_elf_reloc, "R_HPPA_UNWIND_ENTRY"},
-  {R_HPPA_UNWIND_ENTRIES, 0, 3, 32, true, 0, false, true, hppa_elf_reloc, "R_HPPA_UNWIND_ENTRIES"},
+  {R_HPPA_UNWIND_ENTRY, 0, 3, 32, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_UNWIND_ENTRY"},
+  {R_HPPA_UNWIND_ENTRIES, 0, 3, 32, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_UNWIND_ENTRIES"},
 
 /*  9.3.11. Relocation types for complex expressions   */
-  {R_HPPA_PUSH_CONST, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_CONST"},
-  {R_HPPA_PUSH_PC, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_PC"},
-  {R_HPPA_PUSH_SYM, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_SYM"},
-  {R_HPPA_PUSH_GOTOFF, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_GOTOFF"},
-  {R_HPPA_PUSH_ABS_CALL, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_ABS_CALL"},
-  {R_HPPA_PUSH_PCREL_CALL, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_PCREL_CALL"},
-  {R_HPPA_PUSH_PLABEL, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_PLABEL"},
-{R_HPPA_MAX, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_MAX"},
-{R_HPPA_MIN, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_MIN"},
-{R_HPPA_ADD, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ADD"},
-{R_HPPA_SUB, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_SUB"},
-  {R_HPPA_MULT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_MULT"},
-{R_HPPA_DIV, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_DIV"},
-{R_HPPA_MOD, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_MOD"},
-{R_HPPA_AND, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_AND"},
-  {R_HPPA_OR, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_OR"},
-{R_HPPA_XOR, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_XOR"},
-{R_HPPA_NOT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_NOT"},
-  {R_HPPA_LSHIFT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LSHIFT"},
-  {R_HPPA_ARITH_RSHIFT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ARITH_RSHIFT"},
-  {R_HPPA_LOGIC_RSHIFT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LOGIC_RSHIFT"},
-{R_HPPA_EXPR_F, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_L"},
-  {R_HPPA_EXPR_L, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_L"},
-  {R_HPPA_EXPR_R, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_R"},
-  {R_HPPA_EXPR_LS, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_LS"},
-  {R_HPPA_EXPR_RS, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_RS"},
-  {R_HPPA_EXPR_LD, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_LD"},
-  {R_HPPA_EXPR_RD, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_RD"},
-  {R_HPPA_EXPR_LR, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_LR"},
-  {R_HPPA_EXPR_RR, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_RR"},
-
-  {R_HPPA_EXPR_32, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_32"},
-  {R_HPPA_EXPR_21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_21"},
-  {R_HPPA_EXPR_11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_11"},
-  {R_HPPA_EXPR_14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_14"},
-  {R_HPPA_EXPR_17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_17"},
-  {R_HPPA_EXPR_12, 0, 3, 12, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_12"},
-  {R_HPPA_UNIMPLEMENTED, 0, 0, 0, false, 0, false, false, NULL, "R_HPPA_UNIMPLEMENTED"},
+  {R_HPPA_PUSH_CONST, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_CONST"},
+  {R_HPPA_PUSH_PC, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_PC"},
+  {R_HPPA_PUSH_SYM, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_SYM"},
+  {R_HPPA_PUSH_GOTOFF, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_GOTOFF"},
+  {R_HPPA_PUSH_ABS_CALL, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_ABS_CALL"},
+  {R_HPPA_PUSH_PCREL_CALL, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_PCREL_CALL"},
+  {R_HPPA_PUSH_PLABEL, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_PLABEL"},
+{R_HPPA_MAX, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_MAX"},
+{R_HPPA_MIN, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_MIN"},
+{R_HPPA_ADD, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ADD"},
+{R_HPPA_SUB, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_SUB"},
+  {R_HPPA_MULT, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_MULT"},
+{R_HPPA_DIV, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_DIV"},
+{R_HPPA_MOD, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_MOD"},
+{R_HPPA_AND, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_AND"},
+  {R_HPPA_OR, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_OR"},
+{R_HPPA_XOR, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_XOR"},
+{R_HPPA_NOT, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_NOT"},
+  {R_HPPA_LSHIFT, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_LSHIFT"},
+  {R_HPPA_ARITH_RSHIFT, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ARITH_RSHIFT"},
+  {R_HPPA_LOGIC_RSHIFT, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_LOGIC_RSHIFT"},
+{R_HPPA_EXPR_F, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_L"},
+  {R_HPPA_EXPR_L, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_L"},
+  {R_HPPA_EXPR_R, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_R"},
+  {R_HPPA_EXPR_LS, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_LS"},
+  {R_HPPA_EXPR_RS, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_RS"},
+  {R_HPPA_EXPR_LD, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_LD"},
+  {R_HPPA_EXPR_RD, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_RD"},
+  {R_HPPA_EXPR_LR, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_LR"},
+  {R_HPPA_EXPR_RR, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_RR"},
+
+  {R_HPPA_EXPR_32, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_32"},
+  {R_HPPA_EXPR_21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_21"},
+  {R_HPPA_EXPR_11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_11"},
+  {R_HPPA_EXPR_14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_14"},
+  {R_HPPA_EXPR_17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_17"},
+  {R_HPPA_EXPR_12, 0, 3, 12, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_12"},
+  {R_HPPA_STUB_CALL_17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_STUB_CALL_17"},
+  {R_HPPA_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_dont, NULL, "R_HPPA_UNIMPLEMENTED"},
 };
 
-static symext_chainS *symext_rootP = NULL;
-static symext_chainS *symext_lastP = NULL;
+static symext_chainS *symext_rootP;
+static symext_chainS *symext_lastP;
 
 static unsigned long
 DEFUN (hppa_elf_rebuild_insn, (abfd, insn, value, r_type, r_field, r_format),
@@ -301,7 +302,7 @@ DEFUN (hppa_elf_relocate_insn,
       if (pcrel)
        sym_value -= address;
       sym_value = hppa_field_adjust (sym_value, constant_value, r_field);
-      return hppa_elf_rebuild_insn (abfd, insn, sym_value, r_type, r_format, r_format);
+      return hppa_elf_rebuild_insn (abfd, insn, sym_value, r_type, r_field, r_format);
 
     case COMICLR:
     case SUBI:                 /* case SUBIO: */
@@ -407,32 +408,23 @@ DEFUN (hppa_elf_relocate_unwind_table,
     case R_HPPA_UNWIND_ENTRIES:
       for (i = 0; i < r_addend; i++, hit_data += 3 * sizeof (unsigned long))
        {
-         unsigned int fsize;
+         unsigned int adjustment;
          start_offset = bfd_get_32 (abfd, hit_data);
          /* Stuff the symbol value into the first word */
          /* of the  unwind descriptor */
          bfd_put_32 (abfd, sym_value, hit_data);
+         adjustment = sym_value - start_offset;
 
          hit_data += sizeof (unsigned long);
-         end_offset = bfd_get_32 (abfd, hit_data);
-         /* We could also compute the ending offset for */
-         /* the 2nd word of the unwind entry by */
-         /* retrieving the st_size field of the Elf_Sym */
-         /* structure stored with this symbol.  We can */
-         /* get it with:       */
-         /*    e = (elf_symbol_type *)symp     */
-         /*    fsize = e->internal_elf_sym.st_size */
-
-         fsize = end_offset - start_offset;
-         relocated_value = hppa_field_adjust (sym_value, fsize, r_field);
-         bfd_put_32 (abfd, relocated_value, hit_data);
+         end_offset = adjustment + bfd_get_32 (abfd, hit_data);
+         bfd_put_32 (abfd, end_offset, hit_data);
 
          /* If this is not the last unwind entry, */
          /* adjust the symbol value. */
          if (i + 1 < r_addend)
            {
              start_offset = bfd_get_32 (abfd, hit_data + 3 * sizeof (unsigned long));
-             sym_value += fsize + start_offset - end_offset;
+              sym_value = start_offset + adjustment;
            }
        }
       break;
@@ -495,7 +487,7 @@ hppa_elf_gen_reloc_type (abfd, base_type, format, field)
      int format;
      int field;
 {
-#define UNDEFINED      hppa_elf_gen_reloc_error(base_type,format,field);
+#define UNDEFINED      hppa_elf_gen_reloc_error(base_type,format,field)
 
   elf32_hppa_reloc_type *finaltype;
   elf32_hppa_reloc_type **final_types;
@@ -1178,13 +1170,13 @@ hppa_elf_gen_reloc_type (abfd, base_type, format, field)
 
 #undef final_type
 
-/* 12.4.4. Derive format from instruction      */
+/* 12.4.4. Derive format from instruction
 
-/*     Given a machine instruction, this function determines its format.       */
-/*     The format can be determined solely from looking at the first six       */
-/*     bits (the major opcode) of the instruction.  Several major opcodes      */
-/*     map to the same format.  Opcodes which do not map to a known format     */
-/*     should probably be reported as an error.                                */
+       Given a machine instruction, this function determines its format.
+       The format can be determined solely from looking at the first six
+       bits (the major opcode) of the instruction.  Several major opcodes
+       map to the same format.  Opcodes which do not map to a known format
+       should probably be reported as an error.  */
 
 unsigned char
 hppa_elf_insn2fmt (type, insn)
@@ -1249,9 +1241,10 @@ hppa_elf_insn2fmt (type, insn)
 }
 
 /* this function is in charge of performing all the HP PA relocations */
-static long global_value = 0;
-static long GOT_value = 0;     /* XXX:  need to calculate this! For HPUX, GOT == DP */
-static asymbol *global_symbol = (asymbol *) NULL;
+static long global_value;
+static long GOT_value; /* XXX:  need to calculate this! For HPUX, GOT == DP */
+static asymbol *global_symbol;
+static int global_sym_defined;
 
 static bfd_reloc_status_type
 DEFUN (hppa_elf_reloc, (abfd, reloc_entry, symbol_in, data, input_section, output_bfd),
@@ -1293,20 +1286,15 @@ DEFUN (hppa_elf_reloc, (abfd, reloc_entry, symbol_in, data, input_section, outpu
 
   /* compute value of $global$ if it is there. */
 
-  if (global_symbol == (asymbol *) NULL)
+  if (!global_sym_defined)
     {
-      struct elf_backend_data *bed
-      = (struct elf_backend_data *) abfd->xvec->backend_data;
-
-      if (bed && bed->global_sym)
+      if (global_symbol)
        {
-         asymbol *gsym = &bed->global_sym->symbol;
-         global_value
-           = gsym->value
-           + gsym->section->output_section->vma
-           + gsym->section->output_offset;
+         global_value = (global_symbol->value
+                         + global_symbol->section->output_section->vma
+                         + global_symbol->section->output_offset);
          GOT_value = global_value;     /* XXX: For HP-UX, GOT==DP */
-         global_symbol = gsym;
+         global_sym_defined++;
        }
     }
 
@@ -1618,6 +1606,21 @@ DEFUN (hppa_elf_reloc, (abfd, reloc_entry, symbol_in, data, input_section, outpu
       fprintf (stderr, "Unimplemented reloc type %d, in module %s\n",
               r_type, abfd->filename);
       return (bfd_reloc_notsupported);
+    case R_HPPA_STUB_CALL_17:
+      /* yes, a branch to a long branch stub. Change instruction to a BLE */
+      /* or BLE,N */
+      if ( *(unsigned *)hit_data & 2 )
+       insn = BLE_N_XXX_0_0;
+      else
+       insn = BLE_XXX_0_0;
+      bfd_put_32 (abfd, insn, hit_data);
+      r_type = R_HPPA_ABS_CALL_17;
+      r_pcrel = 0;
+      insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr,
+                                    symbol_in, sym_value, r_addend,
+                                    r_type, r_format, r_field, r_pcrel);
+      break;
+      
     default:
       fprintf (stderr, "Relocation problem : ");
       fprintf (stderr, "Unrecognized reloc type %d, in module %s\n",
@@ -1632,107 +1635,11 @@ DEFUN (hppa_elf_reloc, (abfd, reloc_entry, symbol_in, data, input_section, outpu
 
 }
 
-struct elf_reloc_map
-  {
-    unsigned char bfd_reloc_val;
-    unsigned char elf_reloc_val;
-  };
-
-static CONST struct elf_reloc_map elf_hppa_reloc_map[] =
-{
-  {BFD_RELOC_NONE, R_HPPA_NONE,},
-  {BFD_RELOC_HPPA_32, R_HPPA_32,},
-  {BFD_RELOC_HPPA_11, R_HPPA_11,},
-  {BFD_RELOC_HPPA_14, R_HPPA_14,},
-  {BFD_RELOC_HPPA_17, R_HPPA_17,},
-  {BFD_RELOC_HPPA_L21, R_HPPA_L21,},
-  {BFD_RELOC_HPPA_R11, R_HPPA_R11,},
-  {BFD_RELOC_HPPA_R14, R_HPPA_R14,},
-  {BFD_RELOC_HPPA_R17, R_HPPA_R17,},
-  {BFD_RELOC_HPPA_LS21, R_HPPA_LS21,},
-  {BFD_RELOC_HPPA_RS11, R_HPPA_RS11,},
-  {BFD_RELOC_HPPA_RS14, R_HPPA_RS14,},
-  {BFD_RELOC_HPPA_RS17, R_HPPA_RS17,},
-  {BFD_RELOC_HPPA_LD21, R_HPPA_LD21,},
-  {BFD_RELOC_HPPA_RD11, R_HPPA_RD11,},
-  {BFD_RELOC_HPPA_RD14, R_HPPA_RD14,},
-  {BFD_RELOC_HPPA_RD17, R_HPPA_RD17,},
-  {BFD_RELOC_HPPA_LR21, R_HPPA_LR21,},
-  {BFD_RELOC_HPPA_RR14, R_HPPA_RR14,},
-  {BFD_RELOC_HPPA_RR17, R_HPPA_RR17,},
-  {BFD_RELOC_HPPA_GOTOFF_11, R_HPPA_GOTOFF_11,},
-  {BFD_RELOC_HPPA_GOTOFF_14, R_HPPA_GOTOFF_14,},
-  {BFD_RELOC_HPPA_GOTOFF_L21, R_HPPA_GOTOFF_L21,},
-  {BFD_RELOC_HPPA_GOTOFF_R11, R_HPPA_GOTOFF_R11,},
-  {BFD_RELOC_HPPA_GOTOFF_R14, R_HPPA_GOTOFF_R14,},
-  {BFD_RELOC_HPPA_GOTOFF_LS21, R_HPPA_GOTOFF_LS21,},
-  {BFD_RELOC_HPPA_GOTOFF_RS11, R_HPPA_GOTOFF_RS11,},
-  {BFD_RELOC_HPPA_GOTOFF_RS14, R_HPPA_GOTOFF_RS14,},
-  {BFD_RELOC_HPPA_GOTOFF_LD21, R_HPPA_GOTOFF_LD21,},
-  {BFD_RELOC_HPPA_GOTOFF_RD11, R_HPPA_GOTOFF_RD11,},
-  {BFD_RELOC_HPPA_GOTOFF_RD14, R_HPPA_GOTOFF_RD14,},
-  {BFD_RELOC_HPPA_GOTOFF_LR21, R_HPPA_GOTOFF_LR21,},
-  {BFD_RELOC_HPPA_GOTOFF_RR14, R_HPPA_GOTOFF_RR14,},
-  {BFD_RELOC_HPPA_ABS_CALL_11, R_HPPA_ABS_CALL_11,},
-  {BFD_RELOC_HPPA_ABS_CALL_14, R_HPPA_ABS_CALL_14,},
-  {BFD_RELOC_HPPA_ABS_CALL_17, R_HPPA_ABS_CALL_17,},
-  {BFD_RELOC_HPPA_ABS_CALL_L21, R_HPPA_ABS_CALL_L21,},
-  {BFD_RELOC_HPPA_ABS_CALL_R11, R_HPPA_ABS_CALL_R11,},
-  {BFD_RELOC_HPPA_ABS_CALL_R14, R_HPPA_ABS_CALL_R14,},
-  {BFD_RELOC_HPPA_ABS_CALL_R17, R_HPPA_ABS_CALL_R17,},
-  {BFD_RELOC_HPPA_ABS_CALL_LS21, R_HPPA_ABS_CALL_LS21,},
-  {BFD_RELOC_HPPA_ABS_CALL_RS11, R_HPPA_ABS_CALL_RS11,},
-  {BFD_RELOC_HPPA_ABS_CALL_RS14, R_HPPA_ABS_CALL_RS14,},
-  {BFD_RELOC_HPPA_ABS_CALL_RS17, R_HPPA_ABS_CALL_RS17,},
-  {BFD_RELOC_HPPA_ABS_CALL_LD21, R_HPPA_ABS_CALL_LD21,},
-  {BFD_RELOC_HPPA_ABS_CALL_RD11, R_HPPA_ABS_CALL_RD11,},
-  {BFD_RELOC_HPPA_ABS_CALL_RD14, R_HPPA_ABS_CALL_RD14,},
-  {BFD_RELOC_HPPA_ABS_CALL_RD17, R_HPPA_ABS_CALL_RD17,},
-  {BFD_RELOC_HPPA_ABS_CALL_LR21, R_HPPA_ABS_CALL_LR21,},
-  {BFD_RELOC_HPPA_ABS_CALL_RR14, R_HPPA_ABS_CALL_RR14,},
-  {BFD_RELOC_HPPA_ABS_CALL_RR17, R_HPPA_ABS_CALL_RR17,},
-  {BFD_RELOC_HPPA_PCREL_CALL_11, R_HPPA_PCREL_CALL_11,},
-  {BFD_RELOC_HPPA_PCREL_CALL_14, R_HPPA_PCREL_CALL_14,},
-  {BFD_RELOC_HPPA_PCREL_CALL_17, R_HPPA_PCREL_CALL_17,},
-  {BFD_RELOC_HPPA_PCREL_CALL_12, R_HPPA_PCREL_CALL_12,},
-  {BFD_RELOC_HPPA_PCREL_CALL_L21, R_HPPA_PCREL_CALL_L21,},
-  {BFD_RELOC_HPPA_PCREL_CALL_R11, R_HPPA_PCREL_CALL_R11,},
-  {BFD_RELOC_HPPA_PCREL_CALL_R14, R_HPPA_PCREL_CALL_R14,},
-  {BFD_RELOC_HPPA_PCREL_CALL_R17, R_HPPA_PCREL_CALL_R17,},
-  {BFD_RELOC_HPPA_PCREL_CALL_LS21, R_HPPA_PCREL_CALL_LS21,},
-  {BFD_RELOC_HPPA_PCREL_CALL_RS11, R_HPPA_PCREL_CALL_RS11,},
-  {BFD_RELOC_HPPA_PCREL_CALL_RS14, R_HPPA_PCREL_CALL_RS14,},
-  {BFD_RELOC_HPPA_PCREL_CALL_RS17, R_HPPA_PCREL_CALL_RS17,},
-  {BFD_RELOC_HPPA_PCREL_CALL_LD21, R_HPPA_PCREL_CALL_LD21,},
-  {BFD_RELOC_HPPA_PCREL_CALL_RD11, R_HPPA_PCREL_CALL_RD11,},
-  {BFD_RELOC_HPPA_PCREL_CALL_RD14, R_HPPA_PCREL_CALL_RD14,},
-  {BFD_RELOC_HPPA_PCREL_CALL_RD17, R_HPPA_PCREL_CALL_RD17,},
-  {BFD_RELOC_HPPA_PCREL_CALL_LR21, R_HPPA_PCREL_CALL_LR21,},
-  {BFD_RELOC_HPPA_PCREL_CALL_RR14, R_HPPA_PCREL_CALL_RR14,},
-  {BFD_RELOC_HPPA_PCREL_CALL_RR17, R_HPPA_PCREL_CALL_RR17,},
-  {BFD_RELOC_HPPA_PLABEL_32, R_HPPA_PLABEL_32,},
-  {BFD_RELOC_HPPA_PLABEL_11, R_HPPA_PLABEL_11,},
-  {BFD_RELOC_HPPA_PLABEL_14, R_HPPA_PLABEL_14,},
-  {BFD_RELOC_HPPA_PLABEL_L21, R_HPPA_PLABEL_L21,},
-  {BFD_RELOC_HPPA_PLABEL_R11, R_HPPA_PLABEL_R11,},
-  {BFD_RELOC_HPPA_PLABEL_R14, R_HPPA_PLABEL_R14,},
-  {BFD_RELOC_HPPA_DLT_32, R_HPPA_DLT_32,},
-  {BFD_RELOC_HPPA_DLT_11, R_HPPA_DLT_11,},
-  {BFD_RELOC_HPPA_DLT_14, R_HPPA_DLT_14,},
-  {BFD_RELOC_HPPA_DLT_L21, R_HPPA_DLT_L21,},
-  {BFD_RELOC_HPPA_DLT_R11, R_HPPA_DLT_R11,},
-  {BFD_RELOC_HPPA_DLT_R14, R_HPPA_DLT_R14,},
-  {BFD_RELOC_HPPA_UNWIND_ENTRY, R_HPPA_UNWIND_ENTRY,},
-  {BFD_RELOC_HPPA_UNWIND_ENTRIES, R_HPPA_UNWIND_ENTRIES,},
-};
-
 static reloc_howto_type *
 elf_hppa_reloc_type_lookup (arch, code)
      bfd_arch_info_type *arch;
      bfd_reloc_code_real_type code;
 {
-  int i;
-
   if ((int) code < (int) R_HPPA_UNIMPLEMENTED)
     {
       BFD_ASSERT ((int) elf_hppa_howto_table[(int) code].type == (int) code);
@@ -1783,8 +1690,14 @@ DEFUN (elf_hppa_tc_symbol, (abfd, symbolP, sym_idx),
     }
 }
 
-static symext_entryS *symextn_contents = NULL;
-static unsigned int symextn_contents_real_size = 0;
+/* Accessor function for the list of symbol extension records. */
+symext_chainS *elf32_hppa_get_symextn_chain()
+{
+  return symext_rootP;
+}
+
+static symext_entryS *symextn_contents;
+static unsigned int symextn_contents_real_size;
 
 void
 DEFUN (elf_hppa_tc_make_sections, (abfd, ignored),
@@ -1792,11 +1705,9 @@ DEFUN (elf_hppa_tc_make_sections, (abfd, ignored),
        PTR ignored)
 {
   symext_chainS *symextP;
-  symext_entryS *outbound_symexts;
   int size;
   int n;
   int i;
-  extern char *stub_section_contents;  /* forward declaration */
   void hppa_elf_stub_finish ();        /* forward declaration */
   asection *symextn_sec;
 
@@ -1894,6 +1805,9 @@ elf32_hppa_get_sym_extn (abfd, sym, type)
        retval = (symext_entryS) esymP->tc_data.hppa_arg_reloc;
        break;
       }
+    /* This should never happen.  */
+    default:
+      abort();
     }
   return retval;
 }
@@ -1919,7 +1833,7 @@ typedef struct Elf32_hppa_Stub_list_struct
     struct Elf32_hppa_Stub_list_struct *next;
   } Elf32_hppa_Stub_list;
 
-static Elf32_hppa_Stub_list *elf_hppa_stub_rootP = NULL;
+static Elf32_hppa_Stub_list *elf_hppa_stub_rootP;
 
 /* Locate the stub section information for the given bfd. */
 static Elf32_hppa_Stub_description *
@@ -1995,8 +1909,12 @@ add_stub (stub)
 
 #define        NO_ARG_RELOC    0
 #define R_TO_FR                1
-#define FR_TO_R                2
-#define        ARG_RELOC_ERR   3
+#define R01_TO_FR      2
+#define R23_TO_FR      3
+#define FR_TO_R                4
+#define FR_TO_R01      5
+#define FR_TO_R23      6
+#define        ARG_RELOC_ERR   7
 
 #define ARG0   0
 #define ARG1   1
@@ -2008,34 +1926,55 @@ add_stub (stub)
 #define AR_GR  1
 #define AR_FR  2
 #define AR_FU  3
+/* FP register in arg0/arg1.  This value can only appear in the arg0 location. */
+#define AR_DBL01       4
+/* FP register in arg2/arg3.  This value can only appear in the arg2 location. */
+#define AR_DBL23       5
+
+#define AR_WARN(type,loc) \
+  fprintf(stderr,"WARNING:  Illegal argument relocation: %s for %s\n", \
+         reloc_type_strings[type],reloc_loc_strings[loc])
 
 static CONST char *CONST reloc_type_strings[] =
 {
-  "NONE", "GR->FR", "FR->GR", "ERROR"
+  "NONE", "GR->FR", "GR0,GR1->FR1", "GR2,GR3->FR3", "FR->GR", "FR->GR0,GR1", "FR->GR2,GR3", "ERROR"
+};
+
+static CONST char *CONST reloc_loc_strings[] =
+{
+  "ARG0", "ARG1", "ARG2", "ARG3", "RETVAL"
 };
 
-static CONST char mismatches[4][4] =
-{                              /*      CALLEE NONE     CALLEE GR       CALLEE FR       CALLEE FU       */
+static CONST char mismatches[6][6] =
+{                              /*      CALLEE NONE     CALLEE GR       CALLEE FR       CALLEE FU       CALLEE DBL01    CALLEE DBL23    */
   /* CALLER NONE       */
- {NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC},
+ {NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, NO_ARG_RELOC},
  /* CALLER GR  */
- {NO_ARG_RELOC, NO_ARG_RELOC, R_TO_FR, R_TO_FR},
+ {NO_ARG_RELOC, NO_ARG_RELOC, R_TO_FR, ARG_RELOC_ERR, R01_TO_FR, ARG_RELOC_ERR},
  /* CALLER FR  */
- {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, NO_ARG_RELOC},
+ {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR},
  /* CALLER FU  */
- {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, NO_ARG_RELOC},
+ {ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR},
+ /* CALLER DBL01       */
+ {NO_ARG_RELOC, FR_TO_R01, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, ARG_RELOC_ERR},
+ /* CALLER DBL23       */
+ {NO_ARG_RELOC, FR_TO_R23, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, NO_ARG_RELOC},
 };
 
-static CONST char retval_mismatches[4][4] =
-{                              /*      CALLEE NONE     CALLEE GR       CALLEE FR       CALLEE FU       */
+static CONST char retval_mismatches[6][6] =
+{                              /*      CALLEE NONE     CALLEE GR       CALLEE FR       CALLEE FU       CALLEE DBL01    CALLEE DBL23    */
   /* CALLER NONE       */
- {NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC},
+ {NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, NO_ARG_RELOC},
  /* CALLER GR  */
- {NO_ARG_RELOC, NO_ARG_RELOC, R_TO_FR, R_TO_FR},
+ {NO_ARG_RELOC, NO_ARG_RELOC, R_TO_FR, ARG_RELOC_ERR, R01_TO_FR, ARG_RELOC_ERR},
  /* CALLER FR  */
- {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, NO_ARG_RELOC},
+ {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR},
  /* CALLER FU  */
- {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, NO_ARG_RELOC},
+ {ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR},
+ /* CALLER DBL01       */
+ {NO_ARG_RELOC, FR_TO_R01, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, ARG_RELOC_ERR},
+ /* CALLER DBL23       */
+ {NO_ARG_RELOC, FR_TO_R23, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, NO_ARG_RELOC},
 };
 
 static int
@@ -2057,13 +1996,16 @@ type_of_mismatch (caller_bits, callee_bits, type)
 
 #define EXTRACT_ARBITS(ar,which)       ((ar) >> (8-(which*2))) & 3
 
-#include "hppa_stubs.h"
-
 #define NEW_INSTRUCTION(desc,insn)     \
     *((desc)->stub_secp)++ = (insn);   \
     (desc)->real_size += sizeof(int);  \
     bfd_set_section_size((desc)->this_bfd,(desc)->stub_sec,(desc)->real_size);
 
+#define CURRENT_STUB_OFFSET(desc)      \
+  ((int)(desc)->stub_secp - (int)(desc)->stub_contents - 4)
+
+static boolean stubs_finished = false;
+
 void
 hppa_elf_stub_finish (output_bfd)
      bfd *output_bfd;
@@ -2073,6 +2015,9 @@ hppa_elf_stub_finish (output_bfd)
   /* All the stubs have been built.  Finish up building        */
   /* stub section.  Apply relocations to the section.  */
 
+  if ( stubs_finished )
+    return;
+
   for (; stub_list; stub_list = stub_list->next)
     {
       if (stub_list->stub->real_size)
@@ -2140,16 +2085,17 @@ hppa_elf_stub_finish (output_bfd)
          free (reloc_vector);
        }
     }
+  stubs_finished = true;
 }
 
 void
 hppa_elf_stub_branch_reloc (stub_desc, /* the bfd */
                            output_bfd, /* the output bfd */
-                           stub_sym,   /* the stub symbol */
+                           target_sym, /* the target symbol */
                            offset)     /* the offset within the stub buffer (pre-calculated) */
      Elf32_hppa_Stub_description *stub_desc;
      bfd *output_bfd;
-     asymbol *stub_sym;
+     asymbol *target_sym;
      int offset;
 {
   /* Allocate a new relocation entry. */
@@ -2179,8 +2125,61 @@ hppa_elf_stub_branch_reloc (stub_desc,   /* the bfd */
   relent.sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *));
   BFD_ASSERT (relent.sym_ptr_ptr);
 
-  relent.sym_ptr_ptr[0] = stub_sym;
-  relent.howto = bfd_reloc_type_lookup (stub_desc->this_bfd, R_HPPA_ABS_CALL_17);
+  relent.sym_ptr_ptr[0] = target_sym;
+  relent.howto = bfd_reloc_type_lookup (stub_desc->this_bfd, R_HPPA_PCREL_CALL_17);
+
+  /* Save it in the array of relocations for the stub section. */
+
+  memcpy (&stub_desc->stub_sec->relocation[stub_desc->stub_sec->reloc_count++],
+         &relent,
+         sizeof (arelent));
+}
+
+void
+hppa_elf_stub_reloc (stub_desc,        /* the bfd */
+                    output_bfd,        /* the output bfd */
+                    target_sym,        /* the target symbol */
+                    offset,    /* the offset within the stub buffer (pre-calculated) */
+                    type)
+Elf32_hppa_Stub_description *stub_desc;
+bfd *output_bfd;
+asymbol *target_sym;
+int offset;
+elf32_hppa_reloc_type type;
+{
+  /* Allocate a new relocation entry. */
+  arelent relent;
+  int size;
+  Elf_Internal_Shdr *rela_hdr;
+
+  if (stub_desc->relocs_allocated_cnt == stub_desc->stub_sec->reloc_count)
+    {
+      if (stub_desc->stub_sec->relocation == NULL)
+       {
+         stub_desc->relocs_allocated_cnt = STUB_RELOC_INCR;
+         size = sizeof (arelent) * stub_desc->relocs_allocated_cnt;
+         stub_desc->stub_sec->relocation = (arelent *) zalloc (size);
+       }
+      else
+       {
+         stub_desc->relocs_allocated_cnt += STUB_RELOC_INCR;
+         size = sizeof (arelent) * stub_desc->relocs_allocated_cnt;
+         stub_desc->stub_sec->relocation = (arelent *) realloc (stub_desc->stub_sec->relocation,
+                                                                size);
+       }
+    }
+
+  rela_hdr = &elf_section_data(stub_desc->stub_sec)->rel_hdr;
+  rela_hdr->sh_size += sizeof(Elf32_External_Rela);
+
+  /* Fill in the details. */
+  relent.address = offset;
+  relent.addend = 0;
+  relent.sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *));
+  BFD_ASSERT (relent.sym_ptr_ptr);
+
+  relent.sym_ptr_ptr[0] = target_sym;
+  relent.howto = bfd_reloc_type_lookup (stub_desc->this_bfd, type);
 
   /* Save it in the array of relocations for the stub section. */
 
@@ -2199,6 +2198,7 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
   asection *stub_sec = bfd_get_section_by_name (abfd, ".hppa_linker_stubs");
   Elf32_hppa_Stub_description *stub_desc = find_stubs (abfd, stub_sec);
   asymbol *stub_sym = NULL;
+  asymbol *target_sym = reloc_entry->sym_ptr_ptr[0];
   asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text");
   int i;
   char stub_sym_name[128];
@@ -2207,12 +2207,12 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
     {
       BFD_ASSERT (stub_desc == NULL);
       stub_sec = bfd_make_section (abfd, ".hppa_linker_stubs");
-      bfd_set_section_flags (output_bfd,
+      bfd_set_section_flags (abfd,
                             stub_sec,
                             SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_READONLY);
       stub_sec->output_section = output_text_section->output_section;
       stub_sec->output_offset = 0;
-      bfd_set_section_alignment (output_bfd, stub_sec, 2);
+      bfd_set_section_alignment (abfd, stub_sec, 2);
       stub_desc = new_stub (abfd, stub_sec);
       add_stub (stub_desc);
     }
@@ -2247,7 +2247,7 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
           "_stub_%s_%02d_%02d_%02d_%02d_%02d\000",
           reloc_entry->sym_ptr_ptr[0]->name,
   stub_types[0], stub_types[1], stub_types[2], stub_types[3], stub_types[4]);
-  stub_sym->name = bfd_zalloc (output_bfd, strlen (stub_sym_name) + 1);
+  stub_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1);
   strcpy ((char *) stub_sym->name, stub_sym_name);
   stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents;
   stub_sym->section = stub_sec;
@@ -2275,62 +2275,128 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
              switch (i)
                {
                case ARG0:
-                 NEW_INSTRUCTION (stub_desc, LDWS_M8SP_ARG0);
-                 NEW_INSTRUCTION (stub_desc, FSTWS_FARG0_M8SP);
+                 NEW_INSTRUCTION (stub_desc, STWS_ARG0_M8SP);
+                 NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG0);
                  break;
                case ARG1:
-                 NEW_INSTRUCTION (stub_desc, LDWS_M8SP_ARG1);
-                 NEW_INSTRUCTION (stub_desc, FSTWS_FARG1_M8SP);
+                 NEW_INSTRUCTION (stub_desc, STWS_ARG1_M8SP);
+                 NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG1);
                  break;
                case ARG2:
-                 NEW_INSTRUCTION (stub_desc, LDWS_M8SP_ARG1);
-                 NEW_INSTRUCTION (stub_desc, FSTWS_FARG1_M8SP);
+                 NEW_INSTRUCTION (stub_desc, STWS_ARG2_M8SP);
+                 NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG2);
                  break;
                case ARG3:
-                 NEW_INSTRUCTION (stub_desc, LDWS_M8SP_ARG1);
-                 NEW_INSTRUCTION (stub_desc, FSTWS_FARG1_M8SP);
+                 NEW_INSTRUCTION (stub_desc, STWS_ARG3_M8SP);
+                 NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG3);
                  break;
                }
+             continue;
+
+           case R01_TO_FR:
+             switch (i)
+               {
+               case ARG0:
+                 NEW_INSTRUCTION(stub_desc, STWS_ARG0_M4SP);
+                 NEW_INSTRUCTION(stub_desc, STWS_ARG1_M8SP);
+                 NEW_INSTRUCTION(stub_desc, FLDDS_M8SP_FARG1);
              break;
+               default:
+                 AR_WARN(stub_types[i],i);
+                 break;
+               }
+             continue;
+
+           case R23_TO_FR:
+             switch (i)
+               {
+               case ARG2:
+                 NEW_INSTRUCTION(stub_desc, STWS_ARG2_M4SP);
+                 NEW_INSTRUCTION(stub_desc, STWS_ARG3_M8SP);
+                 NEW_INSTRUCTION(stub_desc, FLDDS_M8SP_FARG3);
+                 break;
+               default:
+                 AR_WARN(stub_types[i],i);
+                 break;
+               }
+             continue;
 
            case FR_TO_R:
              switch (i)
                {
                case ARG0:
-                 NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG0);
-                 NEW_INSTRUCTION (stub_desc, STWS_ARG0_M8SP);
+                 NEW_INSTRUCTION (stub_desc, FSTWS_FARG0_M8SP);
+                 NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG0);
                  break;
                case ARG1:
-                 NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG1);
-                 NEW_INSTRUCTION (stub_desc, STWS_ARG1_M8SP);
+                 NEW_INSTRUCTION (stub_desc, FSTWS_FARG1_M8SP);
+                 NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG1);
                  break;
                case ARG2:
-                 NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG1);
-                 NEW_INSTRUCTION (stub_desc, STWS_ARG1_M8SP);
+                 NEW_INSTRUCTION (stub_desc, FSTWS_FARG2_M8SP);
+                 NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG2);
                  break;
                case ARG3:
-                 NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG1);
-                 NEW_INSTRUCTION (stub_desc, STWS_ARG1_M8SP);
+                 NEW_INSTRUCTION (stub_desc, FSTWS_FARG3_M8SP);
+                 NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG3);
                  break;
                }
+             continue;
+
+           case FR_TO_R01:
+             switch (i)
+               {
+               case ARG0:
+                 NEW_INSTRUCTION(stub_desc, FSTDS_FARG1_M8SP);
+                 NEW_INSTRUCTION(stub_desc, LDWS_M4SP_ARG0);
+                 NEW_INSTRUCTION(stub_desc, LDWS_M8SP_ARG1);
              break;
+               default:
+                 AR_WARN(stub_types[i],i);
+                 break;
+               }
+             continue;
 
+           case FR_TO_R23:
+             switch (i)
+               {
+               case ARG2:
+                 NEW_INSTRUCTION(stub_desc, FSTDS_FARG3_M8SP);
+                 NEW_INSTRUCTION(stub_desc, LDWS_M4SP_ARG2);
+                 NEW_INSTRUCTION(stub_desc, LDWS_M8SP_ARG3);
+                 break;
+               default:
+                 AR_WARN(stub_types[i],i);
+                 break;
            }
+             continue;
+             
        }
     }
+    }
+
+  NEW_INSTRUCTION (stub_desc, ADDI_M8_SP);
 
   /* generate the branch to the target routine */
   NEW_INSTRUCTION (stub_desc, STW_RP_M8SP);    /* First, save the return address */
-  NEW_INSTRUCTION (stub_desc, BL_XXX_RP);      /* set up a branch to the function */
-
-  /* Fix the branch to the function.  We can do this with a relocation. */
 
-  hppa_elf_stub_branch_reloc (stub_desc,
-                             output_bfd,       /* the output bfd */
-                             stub_sym, /* the stub symbol */
-          (int) stub_desc->stub_secp - (int) stub_desc->stub_contents - 4);    /* the offset within the stub buffer */
-
-  NEW_INSTRUCTION (stub_desc, NOP);
+  /* Branch to the target function. */
+  /* (Make it a long call, so we do not */
+  /* have to worry about generating a */
+  /* long call stub.)  */
+  NEW_INSTRUCTION(stub_desc, LDIL_XXX_31);
+  hppa_elf_stub_reloc (stub_desc,
+                      abfd,    /* the output bfd */
+                      target_sym,      /* the target symbol */
+                      CURRENT_STUB_OFFSET(stub_desc),  /* offset in stub buffer */
+                      R_HPPA_L21);
+  NEW_INSTRUCTION(stub_desc,BLE_XXX_0_31);
+  hppa_elf_stub_reloc (stub_desc,
+                      abfd,    /* the output bfd */
+                      target_sym,      /* the target symbol */
+                      CURRENT_STUB_OFFSET(stub_desc),  /* offset in stub buffer */
+                      R_HPPA_ABS_CALL_R17);
+  NEW_INSTRUCTION(stub_desc,COPY_31_2);
 
   /* generate the code to move the return value around */
   i = RETVAL;
@@ -2340,13 +2406,13 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
       switch (stub_types[i])
        {
        case R_TO_FR:
-         NEW_INSTRUCTION (stub_desc, LDWS_M8SP_RET0);
-         NEW_INSTRUCTION (stub_desc, FSTWS_FRET0_M8SP);
+         NEW_INSTRUCTION (stub_desc, STWS_RET0_M8SP);
+         NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FRET0);
          break;
 
        case FR_TO_R:
-         NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FRET0);
-         NEW_INSTRUCTION (stub_desc, STWS_RET0_M8SP);
+         NEW_INSTRUCTION (stub_desc, FSTWS_FRET0_M8SP);
+         NEW_INSTRUCTION (stub_desc, LDWS_M4SP_RET0);
          break;
        }
     }
@@ -2354,7 +2420,6 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
   /* generate the ending common section for all stubs */
 
   NEW_INSTRUCTION (stub_desc, LDW_M8SP_RP);    /* restore return address */
-  NEW_INSTRUCTION (stub_desc, SUBI_8_SP);
 
   /* XXX: can we assume this is a save return? */
   NEW_INSTRUCTION (stub_desc, BV_N_0RP);
@@ -2368,7 +2433,6 @@ hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types)
      arelent *reloc_entry;
      int stub_types[5];
 {
-  int i;
   /* If the symbol is still undefined, there is        */
   /* no way to know if a stub is required.     */
 
@@ -2407,22 +2471,22 @@ hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types)
 
          if (caller_loc[ARG0] == AR_FU || caller_loc[ARG1] == AR_FU)
            {
-             caller_loc[ARG0] = AR_FU;
+             caller_loc[ARG0] = AR_DBL01;
              caller_loc[ARG1] = AR_NO;
            }
          if (caller_loc[ARG2] == AR_FU || caller_loc[ARG3] == AR_FU)
            {
-             caller_loc[ARG2] = AR_FU;
+             caller_loc[ARG2] = AR_DBL23;
              caller_loc[ARG3] = AR_NO;
            }
          if (callee_loc[ARG0] == AR_FU || callee_loc[ARG1] == AR_FU)
            {
-             callee_loc[ARG0] = AR_FU;
+             callee_loc[ARG0] = AR_DBL01;
              callee_loc[ARG1] = AR_NO;
            }
          if (callee_loc[ARG2] == AR_FU || callee_loc[ARG3] == AR_FU)
            {
-             callee_loc[ARG2] = AR_FU;
+             callee_loc[ARG2] = AR_DBL23;
              callee_loc[ARG3] = AR_NO;
            }
 
@@ -2432,10 +2496,7 @@ hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types)
          stub_types[ARG3] = type_of_mismatch (caller_loc[ARG3], callee_loc[ARG3], ARGUMENTS);
          stub_types[RETVAL] = type_of_mismatch (caller_loc[RETVAL], callee_loc[RETVAL], RETURN_VALUE);
 
-         /* XXX for now, just report a */
-         /* warning */
-
-         /* But, when we start building stubs, here are the steps involved: */
+         /* Steps involved in building stubs: */
          /* 1. Determine what argument registers need to relocated.  This */
          /*    step is already done here. */
          /* 2. Build the appropriate stub in the .hppa_linker_stubs section. */
@@ -2448,7 +2509,7 @@ hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types)
          /* 4. Change the instruction of the original branch into a branch to */
          /*    the stub routine. */
          /* 5. Build a relocation entry for the instruction of the original */
-         /*    branch to be R_HPPA_ABS_CALL to the stub routine. */
+         /*    branch to be R_HPPA_PCREL_CALL to the stub routine. */
 
 
          if (stub_types[0]
@@ -2483,10 +2544,243 @@ hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types)
 }
 
 asymbol *
-hppa_elf_stub_check (abfd, output_bfd, reloc_entry)
+hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data)
+     bfd *abfd;
+     bfd *output_bfd;
+     arelent *reloc_entry;
+     asymbol *symbol;
+     unsigned *data;
+{
+  asection *stub_sec = bfd_get_section_by_name (abfd, ".hppa_linker_stubs");
+  Elf32_hppa_Stub_description *stub_desc = find_stubs (abfd, stub_sec);
+  asymbol *stub_sym = NULL;
+  asymbol *target_sym = reloc_entry->sym_ptr_ptr[0];
+  asymbol *return_sym = NULL;
+  asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text");
+  char stub_sym_name[128];
+  int milli = false;
+
+  if (!stub_sec)
+    {
+      BFD_ASSERT (stub_desc == NULL);
+      stub_sec = bfd_make_section (abfd, ".hppa_linker_stubs");
+      bfd_set_section_flags (abfd,
+                            stub_sec,
+                            SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_READONLY);
+      stub_sec->output_section = output_text_section->output_section;
+      stub_sec->output_offset = 0;
+      /* set up the ELF section header for this new section. */
+      /* This is basically the same processing as elf_make_sections() */
+      /* (elf_make_sections() is static so it is not accessible from */
+      /* here.) */
+
+      {
+       Elf_Internal_Shdr *this_hdr;
+       this_hdr = &elf_section_data (stub_sec)->this_hdr;
+
+       this_hdr->sh_addr = stub_sec->vma;
+       this_hdr->sh_size = stub_sec->_raw_size;
+       /* contents already set by elf_set_section_contents */
+
+       if (stub_sec->flags & SEC_RELOC)
+         {
+           /* emit a reloc section, and thus strtab and symtab... */
+           Elf_Internal_Shdr *rela_hdr;
+           int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
+
+           rela_hdr = &elf_section_data (stub_sec)->rel_hdr;
+
+           /* orelocation has the data, reloc_count has the count... */
+           if (use_rela_p)
+             {
+               rela_hdr->sh_type = SHT_RELA;
+               rela_hdr->sh_entsize = sizeof (Elf32_External_Rela);
+             }
+           else
+             /* REL relocations */
+             {
+               rela_hdr->sh_type = SHT_REL;
+               rela_hdr->sh_entsize = sizeof (Elf32_External_Rel);
+             }
+           rela_hdr->sh_flags = 0;
+           rela_hdr->sh_addr = 0;
+           rela_hdr->sh_offset = 0;
+           rela_hdr->sh_addralign = 0;
+           rela_hdr->size = 0;
+         }
+       if (stub_sec->flags & SEC_ALLOC)
+         {
+           this_hdr->sh_flags |= SHF_ALLOC;
+           if (stub_sec->flags & SEC_LOAD)
+             {
+               /* @@ Do something with sh_type? */
+             }
+         }
+       if (!(stub_sec->flags & SEC_READONLY))
+         this_hdr->sh_flags |= SHF_WRITE;
+
+       if (stub_sec->flags & SEC_CODE)
+         this_hdr->sh_flags |= SHF_EXECINSTR;
+      }
+
+      bfd_set_section_alignment (abfd, stub_sec, 2);
+      stub_desc = new_stub (abfd, stub_sec);
+      add_stub (stub_desc);
+    }
+
+  if (!stub_desc)
+    {
+      stub_desc = new_stub (abfd, stub_sec);
+      add_stub (stub_desc);
+    }
+
+  /* allocate some space to write the stub */
+
+  if (!stub_desc->stub_contents)
+    {
+      stub_desc->allocated_size = STUB_BUFFER_INCR;
+      stub_desc->stub_contents = (char *) malloc (STUB_BUFFER_INCR);
+    }
+  else if ((stub_desc->allocated_size - stub_desc->real_size) < STUB_MAX_SIZE)
+    {
+      stub_desc->allocated_size = stub_desc->allocated_size + STUB_BUFFER_INCR;
+      stub_desc->stub_contents = (char *) realloc (stub_desc->stub_contents,
+                                                stub_desc->allocated_size);
+    }
+
+  stub_desc->stub_secp = (int *) (stub_desc->stub_contents + stub_desc->real_size);
+
+  /* create a symbol to point to this stub */
+  stub_sym = bfd_make_empty_symbol (abfd);
+  sprintf (stub_sym_name,
+          "_lb_stub_%s\000", reloc_entry->sym_ptr_ptr[0]->name);
+  stub_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1);
+  strcpy ((char *) stub_sym->name, stub_sym_name);
+  stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents;
+  stub_sym->section = stub_sec;
+  stub_sym->flags = BSF_LOCAL | BSF_FUNCTION;
+
+  /* create a symbol to point to the return location */
+  return_sym = bfd_make_empty_symbol (abfd);
+  sprintf (stub_sym_name,
+          "_lb_rtn_%s\000", reloc_entry->sym_ptr_ptr[0]->name);
+  return_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1);
+  strcpy ((char *) return_sym->name, stub_sym_name);
+  return_sym->value = reloc_entry->address + 8;
+  return_sym->section = stub_sec;
+  return_sym->flags = BSF_LOCAL | BSF_FUNCTION;
+
+  /* redirect the original relocation from the old symbol (a function) */
+  /* to the stub (the stub calls the function).        */
+  /* XXX do we need to change the relocation type? */
+  reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *));
+  reloc_entry->sym_ptr_ptr[0] = stub_sym;
+  reloc_entry->howto = bfd_reloc_type_lookup (abfd, R_HPPA_STUB_CALL_17);
+
+  /* Build the stub */
+
+  /* A millicode call? */
+  /* If so, the return address comes in on r31 rather than r2 (rp) so a        */      
+  /* slightly different code sequence is needed.       */
+  if ( ((*data & 0x03e00000) >> 21) == 31 )
+    milli = true;
+
+  /* 1. initialization for the call. */
+
+  NEW_INSTRUCTION(stub_desc, LDSID_31_RP);
+  NEW_INSTRUCTION(stub_desc, MTSP_RP_SR0);
+  if ( !milli )
+    {
+      NEW_INSTRUCTION(stub_desc, COPY_31_2);
+
+      NEW_INSTRUCTION(stub_desc, LDIL_XXX_31);
+      hppa_elf_stub_reloc (stub_desc,
+                          abfd,        /* the output bfd */
+                          target_sym,  /* the target symbol */
+                          CURRENT_STUB_OFFSET(stub_desc),      /* offset in stub buffer */
+                          R_HPPA_L21);
+
+      /* 2. Make the call. */
+
+      NEW_INSTRUCTION(stub_desc,BE_N_XXX_0_31);
+      hppa_elf_stub_reloc (stub_desc,
+                          abfd,        /* the output bfd */
+                          target_sym,  /* the target symbol */
+                          CURRENT_STUB_OFFSET(stub_desc),      /* offset in stub buffer */
+                          R_HPPA_ABS_CALL_R17);
+      /* 3. Branch back to the original location.              */
+      /*    (accomplished with the COPY_31_2 instruction)      */
+    }
+  else
+    {
+      NEW_INSTRUCTION(stub_desc, STW_31_M24SP);
+      NEW_INSTRUCTION(stub_desc, LDIL_XXX_RP);
+      hppa_elf_stub_reloc (stub_desc,
+                          abfd,        /* the output bfd */
+                          target_sym,  /* the target symbol */
+                          CURRENT_STUB_OFFSET(stub_desc),      /* offset in stub buffer */
+                          R_HPPA_L21);
+
+      /* 2. Make the call. */
+
+      NEW_INSTRUCTION(stub_desc,BLE_XXX_0_RP);
+      hppa_elf_stub_reloc (stub_desc,
+                          abfd,        /* the output bfd */
+                          target_sym,  /* the target symbol */
+                          CURRENT_STUB_OFFSET(stub_desc),      /* offset in stub buffer */
+                          R_HPPA_ABS_CALL_R17);
+      NEW_INSTRUCTION(stub_desc,COPY_31_2);
+
+      /* 3. Branch back to the original location.              */
+      NEW_INSTRUCTION(stub_desc, LDW_M24SP_RP);
+      NEW_INSTRUCTION(stub_desc, BV_N_0RP);
+    }
+
+  return stub_sym;
+}
+
+int
+hppa_elf_long_branch_needed_p (abfd, asec, reloc_entry, symbol, insn)
+     bfd *abfd;
+     asection *asec;
+     arelent *reloc_entry;
+     asymbol *symbol;
+     unsigned insn;
+{
+  long sym_value = get_symbol_value(symbol);
+  int fmt = reloc_entry->howto->bitsize;
+  unsigned char op = get_opcode(insn);
+  unsigned raddr;
+
+#define too_far(val,num_bits)  ((int)(val) > (1<<(num_bits))-1) || ((int)(val) < (-1<<(num_bits)))
+
+  BFD_ASSERT(fmt == hppa_elf_insn2fmt(reloc_entry->howto->type,insn));
+
+  switch (op)
+    {
+    case BL:
+      raddr =
+       reloc_entry->address + asec->output_offset + asec->output_section->vma;
+      if ( too_far(sym_value - raddr,fmt+1) )
+       {
+#ifdef DETECT_STUBS
+         fprintf(stderr,"long_branch needed on BL insn: abfd=%s,sym=%s,distance=0x%x\n",abfd->filename,symbol->name,sym_value - reloc_entry->address);
+#endif
+         return 1;
+       }
+      break;
+    }  
+  return 0;
+}
+
+asymbol *
+hppa_elf_stub_check (abfd, output_bfd, input_section, reloc_entry, symbol, hit_data)
      bfd *abfd;
      bfd *output_bfd;
+     asection *input_section;
      arelent *reloc_entry;
+     asymbol *symbol;
+     bfd_byte *hit_data;
 {
   int stub_types[5];
 
@@ -2533,7 +2827,15 @@ hppa_elf_stub_check (abfd, output_bfd, reloc_entry)
       if (hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types))
        {
          /* generate a stub */
-         return hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types);
+         return hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry,
+                                               stub_types);
+       }
+      if (hppa_elf_long_branch_needed_p (abfd, input_section, reloc_entry, symbol,*(unsigned *)hit_data))
+       {
+         /* generate a stub */
+         return hppa_elf_build_long_branch_stub (abfd, output_bfd,
+                                                 reloc_entry, symbol,
+                                                 (unsigned *)hit_data);
        }
       break;
 
@@ -2547,7 +2849,8 @@ hppa_elf_stub_check (abfd, output_bfd, reloc_entry)
 #define STUB_SYM_BUFFER_INC    5
 
 asymbol *
-hppa_look_for_stubs_in_section (abfd, output_bfd, asec, syms, new_sym_cnt)
+hppa_look_for_stubs_in_section (stub_bfd, abfd, output_bfd, asec, syms, new_sym_cnt)
+     bfd *stub_bfd;
      bfd *abfd;
      bfd *output_bfd;
      asection *asec;
@@ -2628,13 +2931,44 @@ hppa_look_for_stubs_in_section (abfd, output_bfd, asec, syms, new_sym_cnt)
                {
                  /* generate a stub */
                  /* keep track of the new symbol */
+
+                 asymbol *r;
+
                  if (new_cnt == new_max)
                    {
                      new_max += STUB_SYM_BUFFER_INC;
                      new_syms = (asymbol *) realloc (new_syms, new_max * sizeof (asymbol));
                    }
-                 new_syms[new_cnt++] = *(hppa_elf_build_arg_reloc_stub (abfd, output_bfd, rle, stub_types));
+                 r = hppa_elf_build_arg_reloc_stub (stub_bfd, output_bfd, rle,
+                                                    stub_types);
+                 new_syms[new_cnt++] = *r;
                }
+             /* We need to retrieve the section contents to check for */
+             /* long branch stubs. */
+             {
+               unsigned insn;
+
+               bfd_get_section_contents(abfd, asec, &insn, rle->address, sizeof(insn));
+               if (hppa_elf_long_branch_needed_p (abfd, asec, rle, rle->sym_ptr_ptr[0], insn))
+                 {
+                   /* generate a stub */
+                   /* keep track of the new symbol */
+
+                   asymbol *r;
+
+                   if (new_cnt == new_max)
+                     {
+                       new_max += STUB_SYM_BUFFER_INC;
+                       new_syms = (asymbol *) realloc (new_syms, new_max * sizeof (asymbol));
+                     }
+                   r = hppa_elf_build_long_branch_stub (stub_bfd,
+                                                        output_bfd,
+                                                        rle,
+                                                        rle->sym_ptr_ptr[0],
+                                                        &insn);
+                   new_syms[new_cnt++] = *r;
+                 }
+             }
              break;
 
            default:
@@ -2647,12 +2981,37 @@ hppa_look_for_stubs_in_section (abfd, output_bfd, asec, syms, new_sym_cnt)
   return new_syms;
 }
 
-int
-hppa_look_for_stubs (abfd, output_bfd)
-     bfd *abfd;
-     bfd *output_bfd;
+
+char *linker_stubs = NULL;
+int linker_stubs_size = 0;
+int linker_stubs_max_size = 0;
+#define STUB_ALLOC_INCR        100
+
+boolean
+DEFUN (hppa_elf_set_section_contents, (abfd, section, location, offset, count),
+       bfd * abfd AND
+       sec_ptr section AND
+       PTR location AND
+       file_ptr offset AND
+       bfd_size_type count)
 {
-  /* bfd_map_over_sections(abfd,hppa_look_for_stubs_in_section,(PTR)output_bfd,NULL); */
+  if ( strcmp(section->name, ".hppa_linker_stubs") == 0 )
+    {
+      if ( linker_stubs_max_size < offset + count )
+       {
+         linker_stubs_max_size = offset + count + STUB_ALLOC_INCR;
+         linker_stubs = (char *)realloc(linker_stubs, linker_stubs_max_size);
+       }
+
+      if ( offset + count > linker_stubs_size )
+       linker_stubs_size = offset + count;
+
+      memcpy(linker_stubs + offset,location,count);
+      return (true);
+    }
+  else
+    return bfd_elf32_set_section_contents (abfd, section, location,
+                                          offset, count);
 }
 
 boolean
@@ -2703,9 +3062,281 @@ DEFUN (elf_info_to_howto, (abfd, cache_ptr, dst),
        arelent * cache_ptr AND
        Elf32_Internal_Rela * dst)
 {
-  abort ();
+  BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_HPPA_UNIMPLEMENTED);
+  cache_ptr->howto = &elf_hppa_howto_table[ELF32_R_TYPE(dst->r_info)];
+}
+
+static void
+DEFUN (elf32_hppa_backend_symbol_processing, (abfd, sym),
+       bfd * abfd AND
+       asymbol * sym)
+{
+  /* Is this a definition of $global$?  If so, keep it because it will be
+    needed if any relocations are performed.  */
+
+  if (!strcmp (sym->name, "$global$")
+      && sym->section != &bfd_und_section)
+    {
+      global_symbol = sym;
+    }
+}
+
+#define elf_backend_symbol_processing  elf32_hppa_backend_symbol_processing
+
+struct elf32_hppa_symextn_map_struct
+{
+  int old_index;
+  bfd *bfd;
+  asymbol *sym;
+  int new_index;
+};
+
+static struct elf32_hppa_symextn_map_struct *elf32_hppa_symextn_map;
+static int elf32_hppa_symextn_map_size;
+
+static boolean
+DEFUN (elf32_hppa_backend_symbol_table_processing, (abfd, esyms,symcnt),
+       bfd             * abfd AND
+       elf32_symbol_type *esyms AND
+       int             symcnt)
+{
+  Elf32_Internal_Shdr *symextn_hdr = bfd_elf_find_section (abfd, SYMEXTN_SECTION_NAME);
+  int i;
+  int current_sym_idx = 0;
+
+  /* If the symbol extension section does not exist, all the symbol */
+  /* all the symbol extension information is assumed to be zero.       */
+
+  if ( symextn_hdr == NULL )
+    {
+      for ( i = 0; i < symcnt; i++ )
+       {
+         esyms[i].tc_data.hppa_arg_reloc = 0;
+       }
+      return (true);
+    }
+
+  /* allocate a buffer of the appropriate size for the symextn section */
+
+  symextn_hdr->contents = bfd_zalloc(abfd,symextn_hdr->sh_size);
+  symextn_hdr->size = symextn_hdr->sh_size;
+       
+  /* read in the symextn section */
+
+  if (bfd_seek (abfd, symextn_hdr->sh_offset, SEEK_SET) == -1)
+    {
+      bfd_error = system_call_error;
+      return (false);
+    }
+  if (bfd_read ((PTR) symextn_hdr->contents, 1, symextn_hdr->size, abfd) 
+      != symextn_hdr->size)
+    {
+      free ((PTR)symextn_hdr->contents);
+      bfd_error = system_call_error;
+      return (false);
+    }  
+
+  /* parse the entries, updating the symtab entries as we go */
+
+  for ( i = 0; i < symextn_hdr->size / sizeof(symext_entryS); i++ )
+    {
+      symext_entryS *seP = ((symext_entryS *)symextn_hdr->contents) + i;
+      int se_value = ELF32_HPPA_SX_VAL(*seP);
+      int se_type = ELF32_HPPA_SX_TYPE(*seP);
+
+      switch ( se_type )
+       {
+       case HPPA_SXT_NULL:
+         break;
+
+       case HPPA_SXT_SYMNDX:
+         if ( se_value >= symcnt )
+           {
+             bfd_error = bad_value;
+             bfd_perror("elf32_hppa_backend_symbol_table_processing -- symbol index");
+             return (false);
+           }
+         current_sym_idx = se_value - 1;
+         break;
+
+       case HPPA_SXT_ARG_RELOC:
+         esyms[current_sym_idx].tc_data.hppa_arg_reloc = se_value;
+         break;
+
+       default:
+         bfd_error = bad_value;
+         bfd_perror("elf32_hppa_backend_symbol_table_processing");
+         return (false);
+       }
+    }
+  return (true);
+}
+
+#define elf_backend_symbol_table_processing    elf32_hppa_backend_symbol_table_processing
+
+static boolean
+DEFUN (elf32_hppa_backend_section_processing, (abfd, secthdr),
+       bfd             * abfd AND
+       Elf32_Internal_Shdr *secthdr)
+{
+  int i,j,k;
+
+  if ( secthdr->sh_type == SHT_HPPA_SYMEXTN )
+    {
+      for ( i = 0; i < secthdr->size / sizeof(symext_entryS); i++ )
+       {
+         symext_entryS *seP = ((symext_entryS *)secthdr->contents) + i;
+         int se_value = ELF32_HPPA_SX_VAL(*seP);
+         int se_type = ELF32_HPPA_SX_TYPE(*seP);
+         
+         switch ( se_type )
+           {
+           case HPPA_SXT_NULL:
+             break;
+             
+           case HPPA_SXT_SYMNDX:
+             for ( j = 0; j < abfd->symcount; j++ )
+               {
+                 /* locate the map entry for this symbol, if there is one. */
+                 /* modify the symbol extension section symbol index entry */
+                 /* to reflect the new symbol table index */
+                 
+                 for ( k = 0; k < elf32_hppa_symextn_map_size; k++ )
+                   {
+                     if ( elf32_hppa_symextn_map[k].old_index == se_value
+                         && elf32_hppa_symextn_map[k].bfd == abfd->outsymbols[j]->the_bfd
+                         && elf32_hppa_symextn_map[k].sym == abfd->outsymbols[j] )
+                       {
+                         bfd_put_32(abfd,
+                                    ELF32_HPPA_SX_WORD (HPPA_SXT_SYMNDX, j),
+                                    (char *)seP);
+                       }
+                   }
+               }
+             break;
+             
+           case HPPA_SXT_ARG_RELOC:
+             break;
+             
+           default:
+             bfd_error = bad_value;
+             bfd_perror("elf32_hppa_backend_section_processing");
+             return (false);
+           }
+       }
+    }
+  return true;
+}
+
+#define elf_backend_section_processing elf32_hppa_backend_section_processing
+
+static boolean
+DEFUN (elf32_hppa_backend_section_from_shdr, (abfd, hdr, name),
+       bfd             * abfd AND
+       Elf32_Internal_Shdr *hdr AND
+       char            * name)
+{
+  asection *newsect;
+
+  if ( hdr->sh_type == SHT_HPPA_SYMEXTN )
+    {
+      BFD_ASSERT ( strcmp(name,".hppa_symextn") == 0 );
+
+      /* Bits that get saved. This one is real. */
+      if (!hdr->rawdata)
+       {
+         newsect = bfd_make_section (abfd, name);
+         if (newsect != NULL)
+           {
+             newsect->vma = hdr->sh_addr;
+             newsect->_raw_size = hdr->sh_size;
+             newsect->filepos = hdr->sh_offset;        /* so we can read back the bits */
+             newsect->flags |= SEC_HAS_CONTENTS;
+             newsect->alignment_power = hdr->sh_addralign;
+
+             if (hdr->sh_flags & SHF_ALLOC)
+               {
+                 newsect->flags |= SEC_ALLOC;
+                 newsect->flags |= SEC_LOAD;
+               }
+
+             if (!(hdr->sh_flags & SHF_WRITE))
+               newsect->flags |= SEC_READONLY;
+
+             if (hdr->sh_flags & SHF_EXECINSTR)
+               newsect->flags |= SEC_CODE;     /* FIXME: may only contain SOME code */
+             else
+               newsect->flags |= SEC_DATA;
+
+             hdr->rawdata = (void *) newsect;
+           }
+       }
+      return true;
+    }
+  return false;
+}
+
+#define elf_backend_section_from_shdr  elf32_hppa_backend_section_from_shdr
+
+static boolean
+DEFUN (elf32_hppa_backend_fake_sections, (abfd, secthdr, asect),
+       bfd             * abfd AND
+       Elf_Internal_Shdr *secthdr AND
+       asection                *asect)
+{
+
+  if ( strcmp(asect->name, ".hppa_symextn") == 0 )
+    {
+      secthdr->sh_type = SHT_HPPA_SYMEXTN;
+      secthdr->sh_flags = 0;
+      secthdr->sh_info = elf_section_data(asect)->rel_hdr.sh_link;
+      secthdr->sh_link = elf_onesymtab(abfd);
+      return true;
+    }
+
+  if (!strcmp (asect->name, ".hppa_unwind"))
+    {
+      secthdr->sh_type = SHT_PROGBITS;
+      /* Unwind descriptors are not part of the program memory image.  */
+      secthdr->sh_flags = 0;
+      secthdr->sh_info = 0;
+      secthdr->sh_link = 0;
+      secthdr->sh_entsize = 16;
+      return true;
+    }
+
+  return false;
+}
+
+#define elf_backend_fake_sections      elf32_hppa_backend_fake_sections
+
+static boolean
+DEFUN (elf32_hppa_backend_section_from_bfd_section, (abfd, hdr, asect),
+       bfd                     *abfd AND
+       Elf32_Internal_Shdr     *hdr AND
+       asection                        *asect)
+{
+
+  if ( hdr->sh_type == SHT_HPPA_SYMEXTN )
+    {
+      if (hdr->rawdata)
+       {
+         if (((struct sec *) (hdr->rawdata)) == asect)
+           {
+             BFD_ASSERT( strcmp(asect->name, ".hppa_symextn") == 0 );
+             return true;
+           }
+       }
+    }
+
+  return false;
 }
 
+#define elf_backend_section_from_bfd_section   elf32_hppa_backend_section_from_bfd_section
+
+#define bfd_generic_get_section_contents       hppa_elf_get_section_contents
+#define bfd_elf32_set_section_contents         hppa_elf_set_section_contents
+
 #define TARGET_BIG_SYM         bfd_elf32_hppa_vec
 #define TARGET_BIG_NAME                "elf32-hppa"
 #define ELF_ARCH               bfd_arch_hppa
index e392eebc47a5200455e8dd20e99d2cf79302800b..77d582752b930c45314e92fe54464a7779a9dfff 100644 (file)
@@ -288,6 +288,7 @@ typedef enum
     R_HPPA_EXPR_14,            /*      pop                             -   14  */
     R_HPPA_EXPR_17,            /*      pop                             -   17  */
     R_HPPA_EXPR_12,            /*      pop                             -   12  */
+    R_HPPA_STUB_CALL_17,       /*      Symbol + Addend                 17      */
     R_HPPA_UNIMPLEMENTED       /*      N/A                                     */
   } elf32_hppa_reloc_type;
 
@@ -308,50 +309,6 @@ typedef enum
 #define        R_HPPA_COMPLEX_ABS_CALL         R_HPPA_PUSH_CONST + 2
 
 
-enum hppa_reloc_field_selector_type
-{
-  R_HPPA_FSEL = 0x0,
-  R_HPPA_LSSEL = 0x1,
-  R_HPPA_RSSEL = 0x2,
-  R_HPPA_LSEL = 0x3,
-  R_HPPA_RSEL = 0x4,
-  R_HPPA_LDSEL = 0x5,
-  R_HPPA_RDSEL = 0x6,
-  R_HPPA_LRSEL = 0x7,
-  R_HPPA_RRSEL = 0x8,
-  R_HPPA_PSEL = 0x9,           /* P'   : procedure address for shlib's */
-  R_HPPA_LPSEL = 0xa,          /* LP'  : L' for procedure addresses    */
-  R_HPPA_RPSEL = 0xb,          /* RP'  : R' for procedure addresses    */
-
-  R_HPPA_TSEL = 0xc,           /* T'   : DLT-relative offset for shlib's       */
-  R_HPPA_LTSEL = 0xd,          /* LT'  : L' for DLT-relative offsets   */
-  R_HPPA_RTSEL = 0xe           /* RT'  : R' for DLT-relative offsets   */
-
-};
-
-#define N_HPPA_FIELD_SELECTORS 15
-
-/* for compatibility */
-enum hppa_reloc_field_selector_type_alt
-{
-  e_fsel = R_HPPA_FSEL,
-  e_lssel = R_HPPA_LSSEL,
-  e_rssel = R_HPPA_RSSEL,
-  e_lsel = R_HPPA_LSEL,
-  e_rsel = R_HPPA_RSEL,
-  e_ldsel = R_HPPA_LDSEL,
-  e_rdsel = R_HPPA_RDSEL,
-  e_lrsel = R_HPPA_LRSEL,
-  e_rrsel = R_HPPA_RRSEL,
-  e_psel = R_HPPA_PSEL,                /* P'   : procedure address for shlib's */
-  e_lpsel = R_HPPA_LPSEL,      /* LP'  : L' for procedure addresses    */
-  e_rpsel = R_HPPA_RPSEL,      /* RP'  : R' for procedure addresses    */
-
-  e_tsel = R_HPPA_TSEL,                /* T'   : DLT-relative offset for shlib's       */
-  e_ltsel = R_HPPA_LTSEL,      /* LT'  : L' for DLT-relative offsets   */
-  e_rtsel = R_HPPA_RTSEL       /* RT'  : R' for DLT-relative offsets   */
-};
-
 /* PA-RISC OPCODES */
 
 #define get_opcode(insn)       ((insn) & 0xfc000000) >> 26
@@ -445,8 +402,8 @@ elf32_hppa_reloc_type **hppa_elf_gen_reloc_type ();
 #define ELF_TC_FAKE_SECTIONS 1 /* # of "hand_made" tc-specific sections */
 #define SYMEXTN_SECTION_NAME ".hppa_symextn"
 
-extern void EXFUN (elf_hppa_tc_symbol, (bfd *, elf32_symbol_type *, int));
-extern void EXFUN (elf_hppa_tc_make_sections, (bfd *, PTR));
+extern void elf_hppa_tc_symbol PARAMS ((bfd *, elf32_symbol_type *, int));
+extern void elf_hppa_tc_make_sections PARAMS ((bfd *, PTR));
 
 typedef Elf32_Word symext_entryS;
 
@@ -458,7 +415,4 @@ struct symext_chain
 
 typedef struct symext_chain symext_chainS;
 
-extern symext_chainS *symext_rootP;
-extern symext_chainS *symext_lastP;
-
 #endif /* _ELF32_HPPA_H */
index cf69813161a94f4b4d804d08681acf2c9192b1c4..14c8899040b162ae0ca3c1d0790165539363344f 100644 (file)
    Contributed by the Center for Software Science at the
    University of Utah (pa-gdb-bugs@cs.utah.edu).
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
-#ifndef _LIBHPPA_H
-#define _LIBHPPA_H
+#ifndef _HPPA_H
+#define _HPPA_H
 
-#include "../bfd/sysdep.h"
-
-#ifdef HOST_HPPAHPUX
-
-#include <sys/core.h>
-#include <sys/utsname.h>
+#define BYTES_IN_WORD 4
 
-#endif /* HOST_HPPAHPUX */
+#ifndef INLINE
+#ifdef __GNUC__
+#define INLINE inline
+#else
+#define INLINE
+#endif /* GNU C? */
+#endif /* INLINE */
 
-#ifdef HOST_HPPABSD
+/* HP PA-RISC relocation types */
 
-/* BSD uses a completely different scheme for object file identification.
-   so for now, define _PA_RISC_ID to accept any random value for a model
-   number.  */
+enum hppa_reloc_field_selector_type
+  {
+    R_HPPA_FSEL = 0x0,
+    R_HPPA_LSSEL = 0x1,
+    R_HPPA_RSSEL = 0x2,
+    R_HPPA_LSEL = 0x3,
+    R_HPPA_RSEL = 0x4,
+    R_HPPA_LDSEL = 0x5,
+    R_HPPA_RDSEL = 0x6,
+    R_HPPA_LRSEL = 0x7,
+    R_HPPA_RRSEL = 0x8,
+    R_HPPA_PSEL = 0x9,
+    R_HPPA_LPSEL = 0xa,
+    R_HPPA_RPSEL = 0xb,
+    R_HPPA_TSEL = 0xc,
+    R_HPPA_LTSEL = 0xd,
+    R_HPPA_RTSEL = 0xe
+  };
 
-#include <a.out.h>
+/* for compatibility */
+enum hppa_reloc_field_selector_type_alt
+  {
+    e_fsel = R_HPPA_FSEL,
+    e_lssel = R_HPPA_LSSEL,
+    e_rssel = R_HPPA_RSSEL,
+    e_lsel = R_HPPA_LSEL,
+    e_rsel = R_HPPA_RSEL,
+    e_ldsel = R_HPPA_LDSEL,
+    e_rdsel = R_HPPA_RDSEL,
+    e_lrsel = R_HPPA_LRSEL,
+    e_rrsel = R_HPPA_RRSEL,
+    e_psel = R_HPPA_PSEL,
+    e_lpsel = R_HPPA_LPSEL,
+    e_rpsel = R_HPPA_RPSEL,
+    e_tsel = R_HPPA_TSEL,
+    e_ltsel = R_HPPA_LTSEL,
+    e_rtsel = R_HPPA_RTSEL
+  };
 
-/* Not a very swift place to put it, but that's where the BSD port
-   puts them.  */
-#include "/hpux/usr/include/sys/core.h"
-#ifndef _PA_RISC_ID
-#define _PA_RISC_ID(__m_num) 1
-#endif
+enum hppa_reloc_expr_type
+  {
+    R_HPPA_E_ONE = 0,
+    R_HPPA_E_TWO = 1,
+    R_HPPA_E_PCREL = 2,
+    R_HPPA_E_CON = 3,
+    R_HPPA_E_PLABEL = 7,
+    R_HPPA_E_ABS = 18
+  };
 
-#endif /* HOST_HPPABSD */
+/* for compatibility */
+enum hppa_reloc_expr_type_alt
+  {
+    e_one = R_HPPA_E_ONE,
+    e_two = R_HPPA_E_TWO,
+    e_pcrel = R_HPPA_E_PCREL,
+    e_con = R_HPPA_E_CON,
+    e_plabel = R_HPPA_E_PLABEL,
+    e_abs = R_HPPA_E_ABS
+  };
+
+
+/* Some functions to manipulate PA instructions.  */
+static INLINE unsigned int
+assemble_3 (x)
+     unsigned int x;
+{
+  return (((x & 1) << 2) | ((x & 6) >> 1)) & 7;
+}
 
-/* Defining MAXCOMLEN avoids bringing in several (7 or 8) otherwise
-   useless include files which tend to clutter up the namespace.  */
+static INLINE void
+dis_assemble_3 (x, r)
+     unsigned int x;
+     unsigned int *r;
+{
+  *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
+}
 
-#define MAXCOMLEN 16
+static INLINE unsigned int
+assemble_12 (x, y)
+     unsigned int x, y;
+{
+  return (((y & 1) << 11) | ((x & 1) << 10) | ((x & 0x7fe) >> 1)) & 0xfff;
+}
 
-#define BYTES_IN_WORD 4
+static INLINE void
+dis_assemble_12 (as12, x, y)
+     unsigned int as12;
+     unsigned int *x, *y;
+{
+  *y = (as12 & 0x800) >> 11;
+  *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
+}
 
-struct header;
-struct som_exec_auxhdr;
-struct subspace_dictionary;
+static INLINE unsigned long
+assemble_17 (x, y, z)
+     unsigned int x, y, z;
+{
+  unsigned long temp;
+
+  temp = ((z & 1) << 16) |
+    ((x & 0x1f) << 11) |
+    ((y & 1) << 10) |
+    ((y & 0x7fe) >> 1);
+  return temp & 0x1ffff;
+}
+
+static INLINE void
+dis_assemble_17 (as17, x, y, z)
+     unsigned int as17;
+     unsigned int *x, *y, *z;
+{
 
-#define FILE_HDR_SIZE sizeof(struct header)
-#define AUX_HDR_SIZE sizeof(struct som_exec_auxhdr)
+  *z = (as17 & 0x10000) >> 16;
+  *x = (as17 & 0x0f800) >> 11;
+  *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
+}
 
-typedef struct hppa_symbol
+static INLINE unsigned long
+assemble_21 (x)
+     unsigned int x;
 {
-  asymbol symbol;
-  short desc;
-  char other;
-  unsigned char type;
-} hppa_symbol_type;
-
-struct hppadata
+  unsigned long temp;
+
+  temp = ((x & 1) << 20) |
+    ((x & 0xffe) << 8) |
+    ((x & 0xc000) >> 7) |
+    ((x & 0x1f0000) >> 14) |
+    ((x & 0x003000) >> 12);
+  return temp & 0x1fffff;
+}
+
+static INLINE void
+dis_assemble_21 (as21, x)
+     unsigned int as21, *x;
 {
-  struct header *file_hdr;
-  struct som_exec_auxhdr *aux_hdr;
-  hppa_symbol_type *symbols;
+  unsigned long temp;
 
-  /* We remember these offsets so that after check_file_format, we have
-     no dependencies on the particular format of the exec_hdr.  */
 
-  file_ptr sym_filepos;
-  file_ptr str_filepos;
+  temp = (as21 & 0x100000) >> 20;
+  temp |= (as21 & 0x0ffe00) >> 8;
+  temp |= (as21 & 0x000180) << 7;
+  temp |= (as21 & 0x00007c) << 14;
+  temp |= (as21 & 0x000003) << 12;
+  *x = temp;
+}
 
-  unsigned stringtab_size;
+static INLINE unsigned long
+sign_ext (x, len)
+     unsigned int x, len;
+{
+  return (x << (32 - len)) >> (32 - len);
+}
 
-  /* Size of a symbol table entry in external form */
-  unsigned hp_symbol_entry_size;
-};
+static INLINE unsigned int
+ones (n)
+     int n;
+{
+  unsigned int len_ones;
+  int i;
+
+  i = 0;
+  len_ones = 0;
+  while (i < n)
+    {
+      len_ones = (len_ones << 1) | 1;
+      i++;
+    }
+
+  return len_ones;
+}
+
+static INLINE void
+sign_unext (x, len, result)
+     unsigned int x, len;
+     unsigned int *result;
+{
+  unsigned int len_ones;
 
-struct hppa_data_struct {
-  struct hppadata a;
-};
+  len_ones = ones (len);
 
-#define padata(bfd)            ((bfd)->tdata.hppa_data->a)
-#define obj_file_hdr(bfd)      (padata(bfd).file_hdr)
-#define obj_aux_hdr(bfd)       (padata(bfd).aux_hdr)
-#define obj_pa_symbols(bfd)    (padata(bfd).symbols)
-#define obj_sym_filepos(bfd)   (padata(bfd).sym_filepos)
-#define obj_str_filepos(bfd)   (padata(bfd).str_filepos)
-#define obj_stringtab_size(bfd)        (padata(bfd).stringtab_size)
+  *result = x & len_ones;
+}
 
-/* We take the address of the first element of an asymbol to ensure that the
-   macro is only ever applied to an asymbol */
-#define hppa_symbol(asymbol) ((hppa_symbol_type *)(&(asymbol)->the_bfd))
+static INLINE unsigned long
+low_sign_ext (x, len)
+     unsigned int x, len;
+{
+  unsigned int temp1, temp2;
+  unsigned int len_ones;
 
+  len_ones = ones (len);
 
-/* These are stored in the bfd's tdata */
+  temp1 = (x & 1) << (len - 1);
+  temp2 = ((x & 0xfffffffe) & len_ones) >> 1;
+  return sign_ext ((temp1 | temp2), len);
+}
 
-struct hppa_core_struct 
+static INLINE void
+low_sign_unext (x, len, result)
+     unsigned int x, len;
+     unsigned int *result;
 {
-  int sig;
-  char cmd[MAXCOMLEN + 1];
-  asection *data_section;
-  asection *stack_section;
-  asection *reg_section;
-};
-
-#define core_hdr(bfd) ((bfd)->tdata.hppa_core_data)
-#define core_signal(bfd) (core_hdr(bfd)->sig)
-#define core_command(bfd) (core_hdr(bfd)->cmd)
-#define core_datasec(bfd) (core_hdr(bfd)->data_section)
-#define core_stacksec(bfd) (core_hdr(bfd)->stack_section)
-#define core_regsec(bfd) (core_hdr(bfd)->reg_section)
+  unsigned int temp;
+  unsigned int sign;
+  unsigned int rest;
+  unsigned int one_bit_at_len;
+  unsigned int len_ones;
 
-/* HP PA-RISC relocation types */
+  len_ones = ones (len);
+  one_bit_at_len = 1 << (len - 1);
 
-enum hppa_reloc_field_selector_type
-{
-       R_HPPA_FSEL     = 0x0,
-       R_HPPA_LSSEL    = 0x1,
-       R_HPPA_RSSEL    = 0x2,
-       R_HPPA_LSEL     = 0x3,
-       R_HPPA_RSEL     = 0x4,
-       R_HPPA_LDSEL    = 0x5,
-       R_HPPA_RDSEL    = 0x6,
-       R_HPPA_LRSEL    = 0x7,
-       R_HPPA_RRSEL    = 0x8,
-       R_HPPA_PSEL     = 0x9,  /* P'   : procedure address for shlib's */
-       R_HPPA_LPSEL    = 0xa,  /* LP'  : L' for procedure addresses    */
-       R_HPPA_RPSEL    = 0xb,  /* RP'  : R' for procedure addresses    */
-
-       R_HPPA_TSEL     = 0xc,  /* T'   : DLT-relative offset for shlib's       */
-       R_HPPA_LTSEL    = 0xd,  /* LT'  : L' for DLT-relative offsets   */
-       R_HPPA_RTSEL    = 0xe   /* RT'  : R' for DLT-relative offsets   */
-
-};
-
-/* Need to undefine things defined in <machine/som.h> */
-
-#undef e_fsel
-#undef e_lssel
-#undef e_rssel
-#undef e_lsel
-#undef e_rsel
-#undef e_ldsel
-#undef e_rdsel
-#undef e_lrsel
-#undef e_rrsel
-#undef e_psel
-#undef e_lpsel
-#undef e_rpsel
-#undef e_tsel
-#undef e_ltsel
-#undef e_rtsel
-#undef e_one
-#undef e_two
-#undef e_pcrel
-#undef e_con
-#undef e_plabel
-#undef e_abs
+  sign_unext (x, len, &temp);
+  sign = temp & one_bit_at_len;
+  sign >>= (len - 1);
 
-/* for compatibility */
-enum hppa_reloc_field_selector_type_alt
-{
-       e_fsel  = R_HPPA_FSEL,
-       e_lssel = R_HPPA_LSSEL,
-       e_rssel = R_HPPA_RSSEL,
-       e_lsel  = R_HPPA_LSEL,
-       e_rsel  = R_HPPA_RSEL,
-       e_ldsel = R_HPPA_LDSEL,
-       e_rdsel = R_HPPA_RDSEL,
-       e_lrsel = R_HPPA_LRSEL,
-       e_rrsel = R_HPPA_RRSEL,
-       e_psel  = R_HPPA_PSEL,  /* P'   : procedure address for shlib's */
-       e_lpsel = R_HPPA_LPSEL, /* LP'  : L' for procedure addresses    */
-       e_rpsel = R_HPPA_RPSEL, /* RP'  : R' for procedure addresses    */
-
-       e_tsel  = R_HPPA_TSEL,  /* T'   : DLT-relative offset for shlib's       */
-       e_ltsel = R_HPPA_LTSEL, /* LT'  : L' for DLT-relative offsets   */
-       e_rtsel = R_HPPA_RTSEL  /* RT'  : R' for DLT-relative offsets   */
-};
+  rest = temp & (len_ones ^ one_bit_at_len);
+  rest <<= 1;
 
-enum hppa_reloc_expr_type
-{
-       R_HPPA_E_ONE    = 0,
-       R_HPPA_E_TWO    = 1,
-       R_HPPA_E_PCREL  = 2,
-       R_HPPA_E_CON    = 3,
-       R_HPPA_E_PLABEL = 7,
-       R_HPPA_E_ABS    = 18
-};
+  *result = rest | sign;
+}
 
-/* for compatibility */
-enum hppa_reloc_expr_type_alt
+/* Handle field selectors for PA instructions.  */
+
+static INLINE unsigned long
+hppa_field_adjust (value, constant_value, r_field)
+     unsigned long value;
+     unsigned long constant_value;
+     unsigned short r_field;
 {
-       e_one   = R_HPPA_E_ONE,
-       e_two   = R_HPPA_E_TWO,
-       e_pcrel = R_HPPA_E_PCREL,
-       e_con   = R_HPPA_E_CON,
-       e_plabel = R_HPPA_E_PLABEL,
-       e_abs   = R_HPPA_E_ABS
-};
-
-#endif /* _LIBHPPA_H */
+  unsigned long init_value = value;
+  value += constant_value;
+  switch (r_field)
+    {
+    case e_fsel:               /* F  : no change                      */
+      break;
+
+    case e_lssel:              /* LS : if (bit 21) then add 0x800
+                                  arithmetic shift right 11 bits */
+      if (value & 0x00000400)
+       value += 0x800;
+      value = (value & 0xfffff800) >> 11;
+      break;
+
+    case e_rssel:              /* RS : Sign extend from bit 21        */
+      if (value & 0x00000400)
+       value |= 0xfffff800;
+      else
+       value &= 0x7ff;
+      break;
+
+    case e_lsel:               /* L  : Arithmetic shift right 11 bits */
+      value = (value & 0xfffff800) >> 11;
+      break;
+
+    case e_rsel:               /* R  : Set bits 0-20 to zero          */
+      value = value & 0x7ff;
+      break;
+
+    case e_ldsel:              /* LD : Add 0x800, arithmetic shift
+                                  right 11 bits                  */
+      value += 0x800;
+      value = (value & 0xfffff800) >> 11;
+      break;
+
+    case e_rdsel:              /* RD : Set bits 0-20 to one           */
+      value |= 0xfffff800;
+      break;
+
+    case e_lrsel:              /* LR : L with "rounded" constant      */
+      value = value + ((constant_value + 0x1000) & 0xffffe000);
+      value = (value & 0xfffff800) >> 11;
+      break;
+
+    case e_rrsel:              /* RR : R with "rounded" constant      */
+      value = value + ((constant_value + 0x1000) & 0xffffe000);
+      value = (value & 0x7ff) + constant_value - ((constant_value + 0x1000) & 0xffffe000);
+      break;
+
+    default:
+      abort ();
+    }
+  return value;
+
+}
+#endif /* _HPPA_H */
diff --git a/bfd/som.c b/bfd/som.c
new file mode 100644 (file)
index 0000000..8fd1324
--- /dev/null
+++ b/bfd/som.c
@@ -0,0 +1,602 @@
+/* bfd back-end for HP PA-RISC SOM objects.
+   Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "bfd.h"
+#include "sysdep.h"
+
+/* @@FIXME This is not a reasonable set of conditions to permit
+   cross-compilation, obviously.  It also isn't enough to support hppa-elf
+   targets either.  Can we eliminate the HPUX or BSD dependencies, or
+   at least get the conditionals more localized?  */
+#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD)
+
+#include "libbfd.h"
+#include "som.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <machine/reg.h>
+#include <sys/user.h>          /* After a.out.h  */
+#include <sys/file.h>
+#include <errno.h>
+
+/* Magic not defined in standard HP-UX header files until 8.0 */
+
+#ifndef CPU_PA_RISC1_0
+#define CPU_PA_RISC1_0 0x20B
+#endif /* CPU_PA_RISC1_0 */
+
+#ifndef CPU_PA_RISC1_1
+#define CPU_PA_RISC1_1 0x210
+#endif /* CPU_PA_RISC1_1 */
+
+#ifndef _PA_RISC1_0_ID
+#define _PA_RISC1_0_ID CPU_PA_RISC1_0
+#endif /* _PA_RISC1_0_ID */
+
+#ifndef _PA_RISC1_1_ID
+#define _PA_RISC1_1_ID CPU_PA_RISC1_1
+#endif /* _PA_RISC1_1_ID */
+
+#ifndef _PA_RISC_MAXID
+#define _PA_RISC_MAXID 0x2FF
+#endif /* _PA_RISC_MAXID */
+
+#ifndef _PA_RISC_ID
+#define _PA_RISC_ID(__m_num)           \
+    (((__m_num) == _PA_RISC1_0_ID) ||  \
+     ((__m_num) >= _PA_RISC1_1_ID && (__m_num) <= _PA_RISC_MAXID))
+#endif /* _PA_RISC_ID */
+
+struct container
+  {
+    struct header f;
+    struct som_exec_auxhdr e;
+  };
+
+static bfd_target *
+hppa_object_setup (abfd, file_hdrp, aux_hdrp)
+     bfd *abfd;
+     struct header *file_hdrp;
+     struct som_exec_auxhdr *aux_hdrp;
+{
+  struct container *rawptr;
+  struct header *f;
+  struct hppa_data_struct *rawptr1;
+  asection *text, *data, *bss;
+
+  rawptr = (struct container *) bfd_zalloc (abfd, sizeof (struct container));
+  if (rawptr == NULL)
+    {
+      bfd_error = no_memory;
+      return 0;
+    }
+
+  rawptr1 = (struct hppa_data_struct *) bfd_zalloc (abfd, sizeof (struct hppa_data_struct));
+  if (rawptr1 == NULL)
+    {
+      bfd_error = no_memory;
+      return 0;
+    }
+
+  abfd->tdata.hppa_data = rawptr1;
+  obj_file_hdr (abfd) = &rawptr->f;
+  obj_aux_hdr (abfd) = &rawptr->e;
+  *obj_file_hdr (abfd) = *file_hdrp;
+  *obj_aux_hdr (abfd) = *aux_hdrp;
+
+  /* Set the file flags */
+  abfd->flags = NO_FLAGS;
+  if (file_hdrp->entry_offset)
+    abfd->flags |= HAS_RELOC;
+  if (file_hdrp->symbol_total)
+    abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
+
+  bfd_get_start_address (abfd) = aux_hdrp->exec_entry;
+
+  obj_pa_symbols (abfd) = (hppa_symbol_type *) NULL;
+  bfd_get_symcount (abfd) = file_hdrp->symbol_total;
+
+  bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0);
+
+  /* create the sections.  This is raunchy, but bfd_close wants to reclaim
+     them */
+
+  text = bfd_make_section (abfd, ".text");
+  data = bfd_make_section (abfd, ".data");
+  bss = bfd_make_section (abfd, ".bss");
+
+  text->_raw_size = aux_hdrp->exec_tsize;
+  data->_raw_size = aux_hdrp->exec_dsize;
+  bss->_raw_size = aux_hdrp->exec_bsize;
+
+  text->flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS);
+  data->flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS);
+  bss->flags = (SEC_ALLOC | SEC_IS_COMMON);
+
+  /* The virtual memory addresses of the sections */
+  text->vma = aux_hdrp->exec_tmem;
+  data->vma = aux_hdrp->exec_dmem;
+  bss->vma = aux_hdrp->exec_bfill;
+
+  /* The file offsets of the sections */
+  text->filepos = aux_hdrp->exec_tfile;
+  data->filepos = aux_hdrp->exec_dfile;
+
+  /* The file offsets of the relocation info */
+  text->rel_filepos = 0;
+  data->rel_filepos = 0;
+
+  /* The file offsets of the string table and symbol table.  */
+  obj_sym_filepos (abfd) = file_hdrp->symbol_location;
+  bfd_get_symcount (abfd) = file_hdrp->symbol_total;
+  obj_str_filepos (abfd) = file_hdrp->symbol_strings_location;
+  obj_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
+
+  return abfd->xvec;
+}
+
+/* Create a new BFD section for NAME.  If NAME already exists, then create a
+   new unique name, with NAME as the prefix.  This exists because SOM .o files
+   created by the native compiler can have a $CODE$ section for each
+   subroutine.
+ */
+
+static asection *
+make_unique_section (abfd, name, num)
+     bfd *abfd;
+     CONST char *name;
+     int num;
+{
+  asection *sect;
+  char *newname;
+  char altname[100];
+
+  sect = bfd_make_section (abfd, name);
+  while (!sect)
+    {
+      sprintf (altname, "%s-%d", name, num++);
+      sect = bfd_make_section (abfd, altname);
+    }
+
+  newname = bfd_alloc (abfd, strlen (sect->name) + 1);
+  strcpy (newname, sect->name);
+
+  sect->name = newname;
+  return sect;
+}
+
+/* Convert all of the space and subspace info into BFD sections.  Each space
+   contains a number of subspaces, which in turn describe the mapping between
+   regions of the exec file, and the address space that the program runs in.
+   BFD sections which correspond to spaces will overlap the sections for the
+   associated subspaces.  */
+
+static int
+setup_sections (abfd, file_hdr)
+     bfd *abfd;
+     struct header *file_hdr;
+{
+  char *space_strings;
+  int space_index;
+
+  /* First, read in space names */
+
+  space_strings = alloca (file_hdr->space_strings_size);
+  if (!space_strings)
+    return 0;
+
+  if (bfd_seek (abfd, file_hdr->space_strings_location, SEEK_SET) < 0)
+    return 0;
+  if (bfd_read (space_strings, 1, file_hdr->space_strings_size, abfd)
+      != file_hdr->space_strings_size)
+    return 0;
+
+  /* Loop over all of the space dictionaries, building up sections */
+
+  for (space_index = 0; space_index < file_hdr->space_total; space_index++)
+    {
+      struct space_dictionary_record space;
+      struct subspace_dictionary_record subspace;
+      int subspace_index, tmp;
+      asection *space_asect;
+
+      /* Read the space dictionary element */
+      if (bfd_seek (abfd, file_hdr->space_location
+                   + space_index * sizeof space, SEEK_SET) < 0)
+       return 0;
+      if (bfd_read (&space, 1, sizeof space, abfd) != sizeof space)
+       return 0;
+
+      /* Setup the space name string */
+      space.name.n_name = space.name.n_strx + space_strings;
+
+      /* Make a section out of it */
+      space_asect = make_unique_section (abfd, space.name.n_name, space_index);
+      if (!space_asect)
+       return 0;
+
+      /* Now, read in the first subspace for this space */
+      if (bfd_seek (abfd, file_hdr->subspace_location
+                   + space.subspace_index * sizeof subspace,
+                   SEEK_SET) < 0)
+       return 0;
+      if (bfd_read (&subspace, 1, sizeof subspace, abfd) != sizeof subspace)
+       return 0;
+      /* Seek back to the start of the subspaces for loop below */
+      if (bfd_seek (abfd, file_hdr->subspace_location
+                   + space.subspace_index * sizeof subspace,
+                   SEEK_SET) < 0)
+       return 0;
+
+      /* Setup the section flags as appropriate (this is somewhat bogus, as
+        there isn't a clear mapping between what's in the space record, and
+        what BFD can describe here). */
+      if (space.is_loadable)
+       space_asect->flags |= SEC_ALLOC;
+      if (space.is_defined)
+       space_asect->flags |= SEC_LOAD;
+
+      /* Setup the start address and file loc from the first subspace record */
+      space_asect->vma = subspace.subspace_start;
+      space_asect->filepos = subspace.file_loc_init_value;
+      space_asect->alignment_power = subspace.alignment;
+
+      /* Loop over the rest of the subspaces, building up more sections */
+      for (subspace_index = 0; subspace_index < space.subspace_quantity;
+          subspace_index++)
+       {
+         asection *subspace_asect;
+
+         /* Read in the next subspace */
+         if (bfd_read (&subspace, 1, sizeof subspace, abfd)
+             != sizeof subspace)
+           return 0;
+
+         /* Setup the subspace name string */
+         subspace.name.n_name = subspace.name.n_strx + space_strings;
+
+         /* Make a section out of this subspace */
+         subspace_asect = make_unique_section (abfd, subspace.name.n_name,
+                                    space.subspace_index + subspace_index);
+
+         if (!subspace_asect)
+           return 0;
+
+         if (subspace.is_loadable)
+           subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
+         if (subspace.code_only)
+           subspace_asect->flags |= SEC_CODE;
+
+         subspace_asect->vma = subspace.subspace_start;
+         subspace_asect->_cooked_size = subspace.subspace_length;
+         subspace_asect->_raw_size = subspace.initialization_length;
+         subspace_asect->alignment_power = subspace.alignment;
+         subspace_asect->filepos = subspace.file_loc_init_value;
+
+       }
+      /* Setup the sizes for the space section based upon the info in the
+        last subspace of the space. */
+      space_asect->_cooked_size = (subspace.subspace_start - space_asect->vma)
+       + subspace.subspace_length;
+      space_asect->_raw_size = (subspace.file_loc_init_value
+                               - space_asect->filepos)
+       + subspace.initialization_length;
+    }
+}
+
+static bfd_target *
+hppa_object_p (abfd)
+     bfd *abfd;
+{
+  struct header file_hdr;
+  struct som_exec_auxhdr aux_hdr;
+
+  if (bfd_read ((PTR) & file_hdr, 1, FILE_HDR_SIZE, abfd) != FILE_HDR_SIZE)
+    return 0;
+
+  if (!_PA_RISC_ID (file_hdr.system_id))
+    {
+      bfd_error = wrong_format;
+      return 0;
+    }
+
+  switch (file_hdr.a_magic)
+    {
+    case RELOC_MAGIC:          /* I'm not really sure about all of these types... */
+    case EXEC_MAGIC:
+    case SHARE_MAGIC:
+    case DEMAND_MAGIC:
+#ifdef DL_MAGIC
+    case DL_MAGIC:
+#endif
+#ifdef SHL_MAGIC
+    case SHL_MAGIC:
+#endif
+      break;
+    default:
+      bfd_error = wrong_format;
+      return 0;
+    }
+
+  if (file_hdr.version_id != VERSION_ID
+      && file_hdr.version_id != NEW_VERSION_ID)
+    {
+      bfd_error = wrong_format;
+      return 0;
+    }
+
+  if (bfd_read ((PTR) & aux_hdr, 1, AUX_HDR_SIZE, abfd) != AUX_HDR_SIZE)
+    bfd_error = wrong_format;
+
+  if (!setup_sections (abfd, &file_hdr))
+    return 0;
+
+  return hppa_object_setup (abfd, &file_hdr, &aux_hdr);
+}
+
+static boolean
+hppa_mkobject (abfd)
+     bfd *abfd;
+{
+  fprintf (stderr, "hppa_mkobject unimplemented\n");
+  fflush (stderr);
+  abort ();
+  return (false);
+}
+
+boolean
+hppa_write_object_contents(abfd)
+     bfd *abfd;
+{
+  fprintf (stderr, "hppa_write_object_contents unimplemented\n");
+  fflush (stderr);
+  abort ();
+  return (false);
+}
+
+static unsigned int
+hppa_get_symtab_upper_bound (abfd)
+     bfd *abfd;
+{
+  fprintf (stderr, "hppa_get_symtab_upper_bound unimplemented\n");
+  fflush (stderr);
+  abort ();
+  return (0);
+}
+
+static unsigned int
+hppa_get_reloc_upper_bound (abfd, asect)
+     bfd *abfd;
+     sec_ptr asect;
+{
+  fprintf (stderr, "hppa_get_reloc_upper_bound unimplemented\n");
+  fflush (stderr);
+  abort ();
+  return (0);
+}
+
+static unsigned int
+hppa_canonicalize_reloc (abfd, section, relptr, symbols)
+     bfd *abfd;
+     sec_ptr section;
+     arelent **relptr;
+     asymbol **symbols;
+{
+  fprintf (stderr, "hppa_canonicalize_reloc unimplemented\n");
+  fflush (stderr);
+  abort ();
+}
+
+extern bfd_target hppa_vec;
+
+static unsigned int
+hppa_get_symtab (abfd, location)
+     bfd *abfd;
+     asymbol **location;
+{
+  fprintf (stderr, "hppa_get_symtab unimplemented\n");
+  fflush (stderr);
+  abort ();
+  return (0);
+}
+
+static asymbol *
+hppa_make_empty_symbol (abfd)
+     bfd *abfd;
+{
+  hppa_symbol_type *new =
+  (hppa_symbol_type *) bfd_zalloc (abfd, sizeof (hppa_symbol_type));
+  new->symbol.the_bfd = abfd;
+
+  return &new->symbol;
+}
+
+static void
+hppa_print_symbol (ignore_abfd, afile, symbol, how)
+     bfd *ignore_abfd;
+     PTR afile;
+     asymbol *symbol;
+     bfd_print_symbol_type how;
+{
+  fprintf (stderr, "hppa_print_symbol unimplemented\n");
+  fflush (stderr);
+  abort ();
+}
+
+static boolean
+hppa_new_section_hook (abfd, newsect)
+     bfd *abfd;
+     asection *newsect;
+{
+  newsect->alignment_power = 3;
+
+  /* We allow more than three sections internally */
+  return true;
+}
+
+static boolean
+hppa_set_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+     PTR location;
+     file_ptr offset;
+     bfd_size_type count;
+{
+  fprintf (stderr, "hppa_set_section_contents unimplimented\n");
+  fflush (stderr);
+  abort ();
+  return false;
+}
+
+static boolean
+hppa_set_arch_mach (abfd, arch, machine)
+     bfd *abfd;
+     enum bfd_architecture arch;
+     unsigned long machine;
+{
+  fprintf (stderr, "hppa_set_arch_mach unimplemented\n");
+  fflush (stderr);
+  /* Allow any architecture to be supported by the hppa backend */
+  return bfd_default_set_arch_mach (abfd, arch, machine);
+}
+
+static boolean
+hppa_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
+                       functionname_ptr, line_ptr)
+     bfd *abfd;
+     asection *section;
+     asymbol **symbols;
+     bfd_vma offset;
+     CONST char **filename_ptr;
+     CONST char **functionname_ptr;
+     unsigned int *line_ptr;
+{
+  fprintf (stderr, "hppa_find_nearest_line unimplemented\n");
+  fflush (stderr);
+  abort ();
+  return (false);
+}
+
+static int
+hppa_sizeof_headers (abfd, reloc)
+     bfd *abfd;
+     boolean reloc;
+{
+  fprintf (stderr, "hppa_sizeof_headers unimplemented\n");
+  fflush (stderr);
+  abort ();
+  return (0);
+}
+
+/* Return information about SOM symbol SYMBOL in RET.  */
+
+static void
+hppa_get_symbol_info (ignore_abfd, symbol, ret)
+     bfd *ignore_abfd;         /* Ignored.  */
+     asymbol *symbol;
+     symbol_info *ret;
+{
+  bfd_symbol_info (symbol, ret);
+}
+
+/* End of miscellaneous support functions. */
+
+#define hppa_bfd_debug_info_start        bfd_void
+#define hppa_bfd_debug_info_end          bfd_void
+#define hppa_bfd_debug_info_accumulate   (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
+
+#define hppa_openr_next_archived_file    bfd_generic_openr_next_archived_file
+#define hppa_generic_stat_arch_elt       bfd_generic_stat_arch_elt
+#define hppa_slurp_armap                  bfd_false
+#define hppa_slurp_extended_name_table    _bfd_slurp_extended_name_table
+#define hppa_truncate_arname              (void (*)())bfd_nullvoidptr
+#define hppa_write_armap                  0
+
+#define hppa_get_lineno                   (struct lineno_cache_entry *(*)())bfd_nullvoidptr
+#define        hppa_close_and_cleanup             bfd_generic_close_and_cleanup
+#define hppa_get_section_contents          bfd_generic_get_section_contents
+
+#define hppa_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define hppa_bfd_relax_section bfd_generic_relax_section
+#define hppa_bfd_seclet_link bfd_generic_seclet_link
+#define hppa_bfd_reloc_type_lookup \
+  ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr)
+#define hppa_bfd_make_debug_symbol \
+  ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
+
+/* Core file support is in the hpux-core backend.  */
+#define hppa_core_file_failing_command _bfd_dummy_core_file_failing_command
+#define hppa_core_file_failing_signal  _bfd_dummy_core_file_failing_signal
+#define hppa_core_file_matches_executable_p _bfd_dummy_core_file_matches_executable_p
+
+bfd_target hppa_vec =
+{
+  "hppa",                      /* name */
+  bfd_target_hppa_flavour,
+  true,                                /* target byte order */
+  true,                                /* target headers byte order */
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
+   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),        /* section flags */
+
+/* leading_symbol_char: is the first char of a user symbol
+      predictable, and if so what is it */
+  0,
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  3,                           /* minimum alignment */
+  _do_getb64, _do_getb_signed_64, _do_putb64,
+  _do_getb32, _do_getb_signed_32, _do_putb32,
+  _do_getb16, _do_getb_signed_16, _do_putb16,  /* data */
+  _do_getb64, _do_getb_signed_64, _do_putb64,
+  _do_getb32, _do_getb_signed_32, _do_putb32,
+  _do_getb16, _do_getb_signed_16, _do_putb16,  /* hdrs */
+  {_bfd_dummy_target,
+   hppa_object_p,              /* bfd_check_format */
+   bfd_generic_archive_p,
+   _bfd_dummy_target
+  },
+  {
+    bfd_false,
+    hppa_mkobject,
+    _bfd_generic_mkarchive,
+    bfd_false
+  },
+  {
+    bfd_false,
+    hppa_write_object_contents,
+    _bfd_write_archive_contents,
+    bfd_false,
+  },
+#undef hppa
+  JUMP_TABLE (hppa),
+  (PTR) 0
+};
+
+#endif /* HOST_HPPAHPUX || HOST_HPPABSD */