* elf-bfd.h (struct elf_link_hash_table): Add hgot field.
authorIan Lance Taylor <ian@airs.com>
Tue, 2 Apr 1996 19:57:33 +0000 (19:57 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 2 Apr 1996 19:57:33 +0000 (19:57 +0000)
* elf.c (_bfd_elf_link_hash_table_init): Initialize hgot field.
* elflink.c (_bfd_elf_create_got_section): Store the
_GLOBAL_OFFSET_TABLE_ hash table entry in the hgot field.
* elf32-sparc.c (elf32_sparc_check_relocs): If the size of the
global offset table goes over 0x1000, set the value of
_GLOBAL_OFFSET_TABLE_ to 0x1000 into the section.
(elf32_sparc_relocate_section): Subtract the offset of
_GLOBAL_OFFSET_TABLE_ when handling GOT relocations.
PR 9323.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf.c
bfd/elf32-sparc.c

index 42953608aa7646fef95d90ec89ecf0cd283847d0..9de2eec07e74cb4ec40bb02f58f0dc4508dfd531 100644 (file)
@@ -1,5 +1,15 @@
 Tue Apr  2 00:33:18 1996  Ian Lance Taylor  <ian@cygnus.com>
 
+       * elf-bfd.h (struct elf_link_hash_table): Add hgot field.
+       * elf.c (_bfd_elf_link_hash_table_init): Initialize hgot field.
+       * elflink.c (_bfd_elf_create_got_section): Store the
+       _GLOBAL_OFFSET_TABLE_ hash table entry in the hgot field.
+       * elf32-sparc.c (elf32_sparc_check_relocs): If the size of the
+       global offset table goes over 0x1000, set the value of
+       _GLOBAL_OFFSET_TABLE_ to 0x1000 into the section.
+       (elf32_sparc_relocate_section): Subtract the offset of
+       _GLOBAL_OFFSET_TABLE_ when handling GOT relocations.
+
        * elfcode.h: Don't include <string.h>.
 
 Mon Apr  1 10:39:24 1996  Jeffrey A Law  (law@cygnus.com)
index b6060634eb5998418e0544743651c8039230d2be..987425ea7eb5407440ac03be4df211c15b894cf2 100644 (file)
@@ -126,6 +126,10 @@ struct elf_link_hash_entry
 #define ELF_LINK_HASH_NEEDS_COPY 040
   /* Symbol needs a procedure linkage table entry.  */
 #define ELF_LINK_HASH_NEEDS_PLT 0100
+  /* Symbol appears in a non-ELF input file.  */
+#define ELF_LINK_NON_ELF 0200
+  /* Note: If you add more flags, you must change the type of
+     elf_link_hash_flags.  */
 };
 
 /* ELF linker hash table.  */
@@ -152,6 +156,8 @@ struct elf_link_hash_table
   /* A linked list of DT_NEEDED names found in dynamic objects
      included in the link.  */
   struct bfd_link_needed_list *needed;
+  /* The _GLOBAL_OFFSET_TABLE_ symbol.  */
+  struct elf_link_hash_entry *hgot;
 };
 
 /* Look up an entry in an ELF linker hash table.  */
@@ -446,9 +452,6 @@ struct elf_backend_data
   unsigned want_got_plt : 1;
   unsigned plt_readonly : 1;
   unsigned want_plt_sym : 1;
-
-  /* Put ELF and program headers in the first loadable segment.  */
-  unsigned want_hdr_in_seg : 1;
 };
 
 /* Information stored for each BFD section in an ELF file.  This
@@ -578,9 +581,13 @@ struct elf_obj_tdata
 
   /* The linker ELF emulation code needs to let the backend ELF linker
      know what filename should be used for a dynamic object if the
-     dynamic object is found using a search.  This field is used to
-     hold that information.  */
-  const char *dt_needed_name;
+     dynamic object is found using a search.  The emulation code then
+     sometimes needs to know what name was actually used.  Until the
+     file has been added to the linker symbol table, this field holds
+     the name the linker wants.  After it has been added, it holds the
+     name actually used, which will be the DT_SONAME entry if there is
+     one.  */
+  const char *dt_name;
 
   /* Irix 5 often screws up the symbol table, sorting local symbols
      after global symbols.  This flag is set if the symbol table in
@@ -624,7 +631,7 @@ struct elf_obj_tdata
 #define elf_sym_hashes(bfd)    (elf_tdata(bfd) -> sym_hashes)
 #define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got_offsets)
 #define elf_local_ptr_offsets(bfd) (elf_tdata(bfd) -> linker_section_pointers)
-#define elf_dt_needed_name(bfd)        (elf_tdata(bfd) -> dt_needed_name)
+#define elf_dt_name(bfd)       (elf_tdata(bfd) -> dt_name)
 #define elf_bad_symtab(bfd)    (elf_tdata(bfd) -> bad_symtab)
 #define elf_flags_init(bfd)    (elf_tdata(bfd) -> flags_init)
 #define elf_linker_section(bfd,n) (elf_tdata(bfd) -> linker_section[(int)n])
index fdc16d9091e107f4f644bbcb0711af7cf9331732..6ede06aec843d75b1b29a31692647efdad18983d 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -583,6 +583,7 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc)
   table->dynstr = NULL;
   table->bucketcount = 0;
   table->needed = NULL;
+  table->hgot = NULL;
   return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
 }
 
@@ -2078,11 +2079,9 @@ assign_file_positions_for_segments (abfd)
                      if (i == 0)
                        abort ();
                      p->p_memsz += adjust;
+                     off += adjust;
                      if ((flags & SEC_LOAD) != 0)
-                       {
-                         p->p_filesz += adjust;
-                         off += adjust;
-                       }
+                       p->p_filesz += adjust;
                    }
                }
 
index b4327b7c54a4836932f8b8cb51fe7e7b02264341..3e2343cc221afa229c11d5265320bb37d65b6f32 100644 (file)
@@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "elf-bfd.h"
 #include "elf/sparc.h"
 
-static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
+static reloc_howto_type *elf32_sparc_reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
 static void elf_info_to_howto
   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
@@ -50,70 +50,86 @@ static boolean elf32_sparc_object_p
   PARAMS ((bfd *));
 static void elf32_sparc_final_write_processing
   PARAMS ((bfd *, boolean));
-
-enum reloc_type
-  {
-    R_SPARC_NONE = 0,
-    R_SPARC_8,         R_SPARC_16,             R_SPARC_32, 
-    R_SPARC_DISP8,     R_SPARC_DISP16,         R_SPARC_DISP32, 
-    R_SPARC_WDISP30,   R_SPARC_WDISP22,
-    R_SPARC_HI22,      R_SPARC_22,
-    R_SPARC_13,                R_SPARC_LO10,
-    R_SPARC_GOT10,     R_SPARC_GOT13,          R_SPARC_GOT22,
-    R_SPARC_PC10,      R_SPARC_PC22,
-    R_SPARC_WPLT30,
-    R_SPARC_COPY,
-    R_SPARC_GLOB_DAT,  R_SPARC_JMP_SLOT,
-    R_SPARC_RELATIVE,
-    R_SPARC_UA32,
-    R_SPARC_max
-  };
-
-#if 0
-static CONST char *CONST reloc_type_names[] =
+\f
+/* The howto table and associated functions.
+   ??? elf64-sparc.c has its own copy for the moment to ease transition
+   since some of the relocation values have changed.  At some point we'll
+   want elf64-sparc.c to switch over and use this table.
+   ??? Do we want to recognize (or flag as errors) some of the 64 bit entries
+   if the target is elf32-sparc.
+*/
+
+static bfd_reloc_status_type sparc_elf_notsupported_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static bfd_reloc_status_type sparc_elf_wdisp16_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+
+reloc_howto_type _bfd_sparc_elf_howto_table[] = 
 {
-  "R_SPARC_NONE",
-  "R_SPARC_8",         "R_SPARC_16",           "R_SPARC_32",
-  "R_SPARC_DISP8",     "R_SPARC_DISP16",       "R_SPARC_DISP32",
-  "R_SPARC_WDISP30",   "R_SPARC_WDISP22",
-  "R_SPARC_HI22",      "R_SPARC_22",
-  "R_SPARC_13",                "R_SPARC_LO10",
-  "R_SPARC_GOT10",     "R_SPARC_GOT13",        "R_SPARC_GOT22",
-  "R_SPARC_PC10",      "R_SPARC_PC22",
-  "R_SPARC_WPLT30",
-  "R_SPARC_COPY",
-  "R_SPARC_GLOB_DAT",  "R_SPARC_JMP_SLOT",
-  "R_SPARC_RELATIVE",
-  "R_SPARC_UA32",
-};
+  HOWTO(R_SPARC_NONE,      0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    false,0,0x00000000,true),
+  HOWTO(R_SPARC_8,         0,0, 8,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_8",       false,0,0x000000ff,true),
+  HOWTO(R_SPARC_16,        0,1,16,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_16",      false,0,0x0000ffff,true),
+  HOWTO(R_SPARC_32,        0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_32",      false,0,0xffffffff,true),
+  HOWTO(R_SPARC_DISP8,     0,0, 8,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP8",   false,0,0x000000ff,true),
+  HOWTO(R_SPARC_DISP16,    0,1,16,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP16",  false,0,0x0000ffff,true),
+  HOWTO(R_SPARC_DISP32,    0,2,32,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP32",  false,0,0x00ffffff,true),
+  HOWTO(R_SPARC_WDISP30,   2,2,30,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP30", false,0,0x3fffffff,true),
+  HOWTO(R_SPARC_WDISP22,   2,2,22,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP22", false,0,0x003fffff,true),
+  HOWTO(R_SPARC_HI22,     10,2,22,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_HI22",    false,0,0x003fffff,true),
+  HOWTO(R_SPARC_22,        0,2,22,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_22",      false,0,0x003fffff,true),
+  HOWTO(R_SPARC_13,        0,2,13,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_13",      false,0,0x00001fff,true),
+  HOWTO(R_SPARC_LO10,      0,2,10,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_LO10",    false,0,0x000003ff,true),
+  HOWTO(R_SPARC_GOT10,     0,2,10,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_GOT10",   false,0,0x000003ff,true),
+  HOWTO(R_SPARC_GOT13,     0,2,13,false,0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_GOT13",   false,0,0x00001fff,true),
+  HOWTO(R_SPARC_GOT22,    10,2,22,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_GOT22",   false,0,0x003fffff,true),
+  HOWTO(R_SPARC_PC10,      0,2,10,true, 0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_PC10",    false,0,0x000003ff,true),
+  HOWTO(R_SPARC_PC22,     10,2,22,true, 0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PC22",    false,0,0x003fffff,true),
+  HOWTO(R_SPARC_WPLT30,    2,2,30,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WPLT30",  false,0,0x3fffffff,true),
+  HOWTO(R_SPARC_COPY,      0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_COPY",    false,0,0x00000000,true),
+  HOWTO(R_SPARC_GLOB_DAT,  0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_GLOB_DAT",false,0,0x00000000,true),
+  HOWTO(R_SPARC_JMP_SLOT,  0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_JMP_SLOT",false,0,0x00000000,true),
+  HOWTO(R_SPARC_RELATIVE,  0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_RELATIVE",false,0,0x00000000,true),
+  HOWTO(R_SPARC_UA32,      0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_UA32",    false,0,0x00000000,true),
+  HOWTO(R_SPARC_PLT32,     0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PLT32",    false,0,0x00000000,true),
+  HOWTO(R_SPARC_HIPLT22,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_HIPLT22",  false,0,0x00000000,true),
+  HOWTO(R_SPARC_LOPLT10,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_LOPLT10",  false,0,0x00000000,true),
+  HOWTO(R_SPARC_PCPLT32,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PCPLT32",  false,0,0x00000000,true),
+  HOWTO(R_SPARC_PCPLT22,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PCPLT22",  false,0,0x00000000,true),
+  HOWTO(R_SPARC_PCPLT10,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PCPLT10",  false,0,0x00000000,true),
+  HOWTO(R_SPARC_10,        0,2,10,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_10",      false,0,0x000003ff,true),
+  HOWTO(R_SPARC_11,        0,2,11,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_11",      false,0,0x000007ff,true),
+  /* ??? If we need to handle R_SPARC_64 then we need (figuratively)
+     --enable-64-bit-bfd.  That causes objdump to print address as 64 bits
+     which we really don't want on an elf32-sparc system.  There may be other
+     consequences which we may not want (at least not until it's proven they're
+     necessary) so for now these are only enabled ifdef BFD64.  */
+#ifdef BFD64
+  HOWTO(R_SPARC_64,        0,4,00,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_64",      false,0,~ (bfd_vma) 0, true),
+  /* ??? These don't make sense except in 64 bit systems so they're disabled
+     ifndef BFD64 too (for now).  */
+  HOWTO(R_SPARC_OLO10,     0,2,10,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_OLO10",   false,0,0x000003ff,true),
+  HOWTO(R_SPARC_HH22,     42,2,22,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_HH22",    false,0,0x003fffff,true),
+  HOWTO(R_SPARC_HM10,     32,2,10,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_HM10",    false,0,0x000003ff,true),
+  HOWTO(R_SPARC_LM22,     10,2,22,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_LM22",    false,0,0x003fffff,true),
+  HOWTO(R_SPARC_PC_HH22,  42,2,22,true, 0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_HH22",    false,0,0x003fffff,true),
+  HOWTO(R_SPARC_PC_HM10,  32,2,10,true, 0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_HM10",    false,0,0x000003ff,true),
+  HOWTO(R_SPARC_PC_LM22,  10,2,22,true, 0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_LM22",    false,0,0x003fffff,true),
+#else
+  HOWTO(R_SPARC_64,      0,0,00,false,0,complain_overflow_dont,      sparc_elf_notsupported_reloc,  "R_SPARC_64",      false,0,0x00000000,true),
+  HOWTO(R_SPARC_OLO10,      0,0,00,false,0,complain_overflow_dont,   sparc_elf_notsupported_reloc,  "R_SPARC_OLO10",   false,0,0x00000000,true),
+  HOWTO(R_SPARC_HH22,      0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_HH22",    false,0,0x00000000,true),
+  HOWTO(R_SPARC_HM10,      0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_HM10",    false,0,0x00000000,true),
+  HOWTO(R_SPARC_LM22,      0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_LM22",    false,0,0x00000000,true),
+  HOWTO(R_SPARC_PC_HH22,      0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc,  "R_SPARC_PC_HH22", false,0,0x00000000,true),
+  HOWTO(R_SPARC_PC_HM10,      0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc,  "R_SPARC_PC_HM10", false,0,0x00000000,true),
+  HOWTO(R_SPARC_PC_LM22,      0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc,  "R_SPARC_PC_LM22", false,0,0x00000000,true),
 #endif
-
-static reloc_howto_type elf_sparc_howto_table[] = 
-{
-  HOWTO(R_SPARC_NONE,    0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,"R_SPARC_NONE",    false,0,0x00000000,true),
-  HOWTO(R_SPARC_8,       0,0, 8,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_8",       false,0,0x000000ff,true),
-  HOWTO(R_SPARC_16,      0,1,16,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_16",      false,0,0x0000ffff,true),
-  HOWTO(R_SPARC_32,      0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_32",      false,0,0xffffffff,true),
-  HOWTO(R_SPARC_DISP8,   0,0, 8,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,"R_SPARC_DISP8",   false,0,0x000000ff,true),
-  HOWTO(R_SPARC_DISP16,  0,1,16,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,"R_SPARC_DISP16",  false,0,0x0000ffff,true),
-  HOWTO(R_SPARC_DISP32,  0,2,32,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,"R_SPARC_DISP32",  false,0,0x00ffffff,true),
-  HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,"R_SPARC_WDISP30", false,0,0x3fffffff,true),
-  HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,"R_SPARC_WDISP22", false,0,0x003fffff,true),
-  HOWTO(R_SPARC_HI22,   10,2,22,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,"R_SPARC_HI22",    false,0,0x003fffff,true),
-  HOWTO(R_SPARC_22,      0,2,22,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_22",      false,0,0x003fffff,true),
-  HOWTO(R_SPARC_13,      0,2,13,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_13",      false,0,0x00001fff,true),
-  HOWTO(R_SPARC_LO10,    0,2,10,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,"R_SPARC_LO10",    false,0,0x000003ff,true),
-  HOWTO(R_SPARC_GOT10,   0,2,10,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,"R_SPARC_GOT10",   false,0,0x000003ff,true),
-  HOWTO(R_SPARC_GOT13,   0,2,13,false,0,complain_overflow_signed,  bfd_elf_generic_reloc,"R_SPARC_GOT13",   false,0,0x00001fff,true),
-  HOWTO(R_SPARC_GOT22,  10,2,22,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,"R_SPARC_GOT22",   false,0,0x003fffff,true),
-  HOWTO(R_SPARC_PC10,    0,2,10,true, 0,complain_overflow_dont,    bfd_elf_generic_reloc,"R_SPARC_PC10",    false,0,0x000003ff,true),
-  HOWTO(R_SPARC_PC22,   10,2,22,true, 0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_PC22",    false,0,0x003fffff,true),
-  HOWTO(R_SPARC_WPLT30,  2,2,30,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,"R_SPARC_WPLT30",  false,0,0x3fffffff,true),
-  HOWTO(R_SPARC_COPY,    0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,"R_SPARC_COPY",    false,0,0x00000000,true),
-  HOWTO(R_SPARC_GLOB_DAT,0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,"R_SPARC_GLOB_DAT",false,0,0x00000000,true),
-  HOWTO(R_SPARC_JMP_SLOT,0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,"R_SPARC_JMP_SLOT",false,0,0x00000000,true),
-  HOWTO(R_SPARC_RELATIVE,0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,"R_SPARC_RELATIVE",false,0,0x00000000,true),
-  HOWTO(R_SPARC_UA32,    0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,"R_SPARC_UA32",    false,0,0x00000000,true),
+  HOWTO(R_SPARC_WDISP16,   2,2,16,true, 0,complain_overflow_signed,  sparc_elf_wdisp16_reloc,"R_SPARC_WDISP16", false,0,0x00000000,true),
+  HOWTO(R_SPARC_WDISP19,   2,2,22,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP19", false,0,0x0007ffff,true),
+  HOWTO(R_SPARC_GLOB_JMP,  0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_GLOB_DAT",false,0,0x00000000,true),
+  HOWTO(R_SPARC_7,         0,2, 7,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_7",       false,0,0x0000007f,true),
+  HOWTO(R_SPARC_5,         0,2, 5,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_5",       false,0,0x0000001f,true),
+  HOWTO(R_SPARC_6,         0,2, 6,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_6",       false,0,0x0000003f,true),
 };
 
 struct elf_reloc_map {
@@ -127,6 +143,8 @@ static CONST struct elf_reloc_map sparc_reloc_map[] =
   { BFD_RELOC_16, R_SPARC_16, },
   { BFD_RELOC_8, R_SPARC_8 },
   { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
+  /* ??? This might cause us to need separate functions in elf{32,64}-sparc.c
+     (we could still have just one table), but is this reloc ever used?  */
   { BFD_RELOC_CTOR, R_SPARC_32 }, /* @@ Assumes 32 bits.  */
   { BFD_RELOC_32, R_SPARC_32 },
   { BFD_RELOC_32_PCREL, R_SPARC_DISP32 },
@@ -146,11 +164,28 @@ static CONST struct elf_reloc_map sparc_reloc_map[] =
   { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT },
   { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE },
   { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 },
+  /* ??? Doesn't dwarf use this?  */
 /*{ BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */
+  {BFD_RELOC_SPARC_10, R_SPARC_10},
+  {BFD_RELOC_SPARC_11, R_SPARC_11},
+  {BFD_RELOC_SPARC_64, R_SPARC_64},
+  {BFD_RELOC_SPARC_OLO10, R_SPARC_OLO10},
+  {BFD_RELOC_SPARC_HH22, R_SPARC_HH22},
+  {BFD_RELOC_SPARC_HM10, R_SPARC_HM10},
+  {BFD_RELOC_SPARC_LM22, R_SPARC_LM22},
+  {BFD_RELOC_SPARC_PC_HH22, R_SPARC_PC_HH22},
+  {BFD_RELOC_SPARC_PC_HM10, R_SPARC_PC_HM10},
+  {BFD_RELOC_SPARC_PC_LM22, R_SPARC_PC_LM22},
+  {BFD_RELOC_SPARC_WDISP16, R_SPARC_WDISP16},
+  {BFD_RELOC_SPARC_WDISP19, R_SPARC_WDISP19},
+  {BFD_RELOC_SPARC_GLOB_JMP, R_SPARC_GLOB_JMP},
+  {BFD_RELOC_SPARC_7, R_SPARC_7},
+  {BFD_RELOC_SPARC_5, R_SPARC_5},
+  {BFD_RELOC_SPARC_6, R_SPARC_6},
 };
 
 static reloc_howto_type *
-bfd_elf32_bfd_reloc_type_lookup (abfd, code)
+elf32_sparc_reloc_type_lookup (abfd, code)
      bfd *abfd;
      bfd_reloc_code_real_type code;
 {
@@ -158,11 +193,14 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code)
   for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++)
     {
       if (sparc_reloc_map[i].bfd_reloc_val == code)
-       return &elf_sparc_howto_table[(int) sparc_reloc_map[i].elf_reloc_val];
+       return &_bfd_sparc_elf_howto_table[(int) sparc_reloc_map[i].elf_reloc_val];
     }
   return 0;
 }
 
+/* We need to use ELF32_R_TYPE so we have our own copy of this function,
+   and elf64-sparc.c has its own copy.  */
+
 static void
 elf_info_to_howto (abfd, cache_ptr, dst)
      bfd *abfd;
@@ -170,9 +208,85 @@ elf_info_to_howto (abfd, cache_ptr, dst)
      Elf_Internal_Rela *dst;
 {
   BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_SPARC_max);
-  cache_ptr->howto = &elf_sparc_howto_table[ELF32_R_TYPE(dst->r_info)];
+  cache_ptr->howto = &_bfd_sparc_elf_howto_table[ELF32_R_TYPE(dst->r_info)];
 }
+\f
+/* For unsupported relocs.  */
+
+static bfd_reloc_status_type
+sparc_elf_notsupported_reloc (abfd,
+                            reloc_entry,
+                            symbol,
+                            data,
+                            input_section,
+                            output_bfd,
+                            error_message)
+     bfd *abfd;
+     arelent *reloc_entry;
+     asymbol *symbol;
+     PTR data;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message;
+{
+  return bfd_reloc_notsupported;
+}
+
+/* Handle the WDISP16 reloc.  */
+
+static bfd_reloc_status_type
+sparc_elf_wdisp16_reloc (abfd,
+                        reloc_entry,
+                        symbol,
+                        data,
+                        input_section,
+                        output_bfd,
+                        error_message)
+     bfd *abfd;
+     arelent *reloc_entry;
+     asymbol *symbol;
+     PTR data;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message;
+{
+  bfd_vma relocation;
+  bfd_vma x;
 
+  if (output_bfd != (bfd *) NULL
+      && (symbol->flags & BSF_SECTION_SYM) == 0
+      && (! reloc_entry->howto->partial_inplace
+         || reloc_entry->addend == 0))
+    {
+      reloc_entry->address += input_section->output_offset;
+      return bfd_reloc_ok;
+    }
+
+  if (output_bfd != NULL)
+    return bfd_reloc_continue;
+
+  if (reloc_entry->address > input_section->_cooked_size)
+    return bfd_reloc_outofrange;
+
+  relocation = (symbol->value
+               + symbol->section->output_section->vma
+               + symbol->section->output_offset);
+  relocation += reloc_entry->addend;
+  relocation -=        (input_section->output_section->vma
+                + input_section->output_offset);
+  relocation -= reloc_entry->address;
+
+  x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
+  x |= ((((relocation >> 2) & 0xc000) << 6)
+       | ((relocation >> 2) & 0x3fff));
+  bfd_put_32 (abfd, x, (char *) data + reloc_entry->address);
+
+  if ((bfd_signed_vma) relocation < - 0x40000
+      || (bfd_signed_vma) relocation > 0x3ffff)
+    return bfd_reloc_overflow;
+  else
+    return bfd_reloc_ok;
+}
 \f
 /* Functions for the SPARC ELF linker.  */
 
@@ -339,6 +453,13 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
 
          sgot->_raw_size += 4;
 
+         /* If the .got section is more than 0x1000 bytes, we add
+            0x1000 to the value of _GLOBAL_OFFSET_TABLE_, so that 13
+            bit relocations have a greater chance of working.  */
+         if (sgot->_raw_size >= 0x1000
+             && elf_hash_table (info)->hgot->root.u.def.value == 0)
+           elf_hash_table (info)->hgot->root.u.def.value = 0x1000;
+
          break;
 
        case R_SPARC_WPLT30:
@@ -378,6 +499,8 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
        case R_SPARC_DISP32:
        case R_SPARC_WDISP30:
        case R_SPARC_WDISP22:
+       case R_SPARC_WDISP19:
+       case R_SPARC_WDISP16:
          if (h == NULL)
            break;
          /* Fall through.  */
@@ -821,6 +944,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   bfd_vma *local_got_offsets;
+  bfd_vma got_base;
   asection *sgot;
   asection *splt;
   asection *sreloc;
@@ -832,6 +956,11 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
   sym_hashes = elf_sym_hashes (input_bfd);
   local_got_offsets = elf_local_got_offsets (input_bfd);
 
+  if (elf_hash_table (info)->hgot == NULL)
+    got_base = 0;
+  else
+    got_base = elf_hash_table (info)->hgot->root.u.def.value;
+
   sgot = NULL;
   splt = NULL;
   sreloc = NULL;
@@ -855,7 +984,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
          bfd_set_error (bfd_error_bad_value);
          return false;
        }
-      howto = elf_sparc_howto_table + r_type;
+      howto = _bfd_sparc_elf_howto_table + r_type;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
 
@@ -893,6 +1022,9 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
       else
        {
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+         while (h->root.type == bfd_link_hash_indirect
+                || h->root.type == bfd_link_hash_warning)
+           h = (struct elf_link_hash_entry *) h->root.u.i.link;
          if (h->root.type == bfd_link_hash_defined
              || h->root.type == bfd_link_hash_defweak)
            {
@@ -920,6 +1052,8 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
                          || r_type == R_SPARC_DISP32
                          || r_type == R_SPARC_WDISP30
                          || r_type == R_SPARC_WDISP22
+                         || r_type == R_SPARC_WDISP19
+                         || r_type == R_SPARC_WDISP16
                          || r_type == R_SPARC_HI22
                          || r_type == R_SPARC_22
                          || r_type == R_SPARC_13
@@ -1000,7 +1134,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
                    }
                }
 
-             relocation = sgot->output_offset + off;
+             relocation = sgot->output_offset + off - got_base;
            }
          else
            {
@@ -1045,7 +1179,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
                  local_got_offsets[r_symndx] |= 1;
                }
 
-             relocation = sgot->output_offset + off;
+             relocation = sgot->output_offset + off - got_base;
            }
 
          break;
@@ -1085,6 +1219,8 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_SPARC_DISP32:
        case R_SPARC_WDISP30:
        case R_SPARC_WDISP22:
+       case R_SPARC_WDISP19:
+       case R_SPARC_WDISP16:
          if (h == NULL)
            break;
          /* Fall through.  */
@@ -1194,9 +1330,30 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
          break;
        }               
 
-      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
-                                   contents, rel->r_offset,
-                                   relocation, rel->r_addend);
+      if (r_type != R_SPARC_WDISP16)
+       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+                                     contents, rel->r_offset,
+                                     relocation, rel->r_addend);
+      else
+       {
+         bfd_vma x;
+
+         relocation += rel->r_addend;
+         relocation -= (input_section->output_section->vma
+                        + input_section->output_offset);
+         relocation -= rel->r_offset;
+
+         x = bfd_get_32 (input_bfd, contents + rel->r_offset);
+         x |= ((((relocation >> 2) & 0xc000) << 6)
+               | ((relocation >> 2) & 0x3fff));
+         bfd_put_32 (input_bfd, x, contents + rel->r_offset);
+
+         if ((bfd_signed_vma) relocation < - 0x40000
+             || (bfd_signed_vma) relocation > 0x3ffff)
+           r = bfd_reloc_overflow;
+         else
+           r = bfd_reloc_ok;
+       }
 
       if (r != bfd_reloc_ok)
        {
@@ -1625,6 +1782,8 @@ elf32_sparc_final_write_processing (abfd, linker)
 #define ELF_MACHINE_CODE EM_SPARC
 #define ELF_MACHINE_ALT1 EM_SPARC32PLUS
 #define ELF_MAXPAGESIZE 0x10000
+
+#define bfd_elf32_bfd_reloc_type_lookup        elf32_sparc_reloc_type_lookup
 #define elf_backend_create_dynamic_sections \
                                        _bfd_elf_create_dynamic_sections
 #define elf_backend_check_relocs       elf32_sparc_check_relocs