* elf32-sparc.c (_bfd_sparc_elf_howto_table): Fix dst_mask for
authorJakub Jelinek <jakub@redhat.com>
Fri, 21 Dec 2001 22:35:24 +0000 (22:35 +0000)
committerJakub Jelinek <jakub@redhat.com>
Fri, 21 Dec 2001 22:35:24 +0000 (22:35 +0000)
R_SPARC_DISP32.  Support R_SPARC_PLT32.
(sparc_reloc_map): Add BFD_RELOC_16_PCREL and BFD_RELOC_SPARC_PLT32.
(elf32_sparc_check_relocs): Handle R_SPARC_PLT32.
(elf32_sparc_relocate_section): Likewise.
* elf64-sparc.c (sparc64_elf_howto_table): Fix dst_mask for
R_SPARC_DISP32.  Support R_SPARC_PLT32 and R_SPARC_PLT64.
(sparc_reloc_map): Add BFD_RELOC_16_PCREL, BFD_RELOC_64_PCREL
and BFD_RELOC_SPARC_PLT32.
(sparc64_elf_check_relocs): Handle R_SPARC_PLT32 and R_SPARC_PLT64.
(sparc64_elf_relocate_section): Likewise.
* reloc.c (bfd_reloc_code_type): Add BFD_RELOC_SPARC_PLT32.
* bfd-in2.h, libbfd.h: Rebuilt.

* config/tc-sparc.h (TC_PARSE_CONS_EXPRESSION): Define.
(sparc_cons): Provide prototype.
* config/tc-sparc.c (tc_gen_reloc): Handle BFD_RELOC_*_PCREL and
BFD_RELOC_SPARC_PLT{32,64}.  Enumerate for which relocs
reloc->addend = fixp->fx_addnumber shouldn't be done instead of
enumarating for which pc relative ones it should be done.
(sparc_cons_special_reloc): New variable.
(sparc_cons): New function.
(cons_fix_new_sparc): Use sparc_cons_special_reloc.
* testsuite/gas/sparc/pcrel.s: New test.
* testsuite/gas/sparc/pcrel.d: Expected output.
* testsuite/gas/sparc/pcrel64.s: New test.
* testsuite/gas/sparc/pcrel64.d: Expected output.
* testsuite/gas/sparc/plt.s: New test.
* testsuite/gas/sparc/plt.d: Expected output.
* testsuite/gas/sparc/plt64.s: New test.
* testsuite/gas/sparc/plt64.d: Expected output.
* testsuite/gas/sparc/sparc.exp: Add pcrel, pcrel64, plt and plt64
tests.

18 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf32-sparc.c
bfd/elf64-sparc.c
bfd/libbfd.h
bfd/reloc.c
gas/ChangeLog
gas/config/tc-sparc.c
gas/config/tc-sparc.h
gas/testsuite/gas/sparc/pcrel.d [new file with mode: 0644]
gas/testsuite/gas/sparc/pcrel.s [new file with mode: 0644]
gas/testsuite/gas/sparc/pcrel64.d [new file with mode: 0644]
gas/testsuite/gas/sparc/pcrel64.s [new file with mode: 0644]
gas/testsuite/gas/sparc/plt.d [new file with mode: 0644]
gas/testsuite/gas/sparc/plt.s [new file with mode: 0644]
gas/testsuite/gas/sparc/plt64.d [new file with mode: 0644]
gas/testsuite/gas/sparc/plt64.s [new file with mode: 0644]
gas/testsuite/gas/sparc/sparc.exp

index a81b0b31141da7029aa15a1750f8f647f40a27a8..f0c7fe71163fd29ced750beb28abf68cc6c60883 100644 (file)
@@ -1,3 +1,19 @@
+2001-12-21  Jakub Jelinek  <jakub@redhat.com>
+
+       * elf32-sparc.c (_bfd_sparc_elf_howto_table): Fix dst_mask for
+       R_SPARC_DISP32.  Support R_SPARC_PLT32.
+       (sparc_reloc_map): Add BFD_RELOC_16_PCREL and BFD_RELOC_SPARC_PLT32.
+       (elf32_sparc_check_relocs): Handle R_SPARC_PLT32.
+       (elf32_sparc_relocate_section): Likewise.
+       * elf64-sparc.c (sparc64_elf_howto_table): Fix dst_mask for
+       R_SPARC_DISP32.  Support R_SPARC_PLT32 and R_SPARC_PLT64.
+       (sparc_reloc_map): Add BFD_RELOC_16_PCREL, BFD_RELOC_64_PCREL
+       and BFD_RELOC_SPARC_PLT32.
+       (sparc64_elf_check_relocs): Handle R_SPARC_PLT32 and R_SPARC_PLT64.
+       (sparc64_elf_relocate_section): Likewise.
+       * reloc.c (bfd_reloc_code_type): Add BFD_RELOC_SPARC_PLT32.
+       * bfd-in2.h, libbfd.h: Rebuilt.
+
 2001-12-20  Tom Rix  <trix@redhat.com>
 
        * coffcode.h (coff_compute_section_file_positions): Add special AIX 
index 1e8b0b4bbabac6a9d6b207ca517042f1c7225cb5..920df8de488df8bc6317abddc3612e08856090f5 100644 (file)
@@ -2022,6 +2022,7 @@ relocation types already defined. */
   BFD_RELOC_SPARC_6,
   BFD_RELOC_SPARC_5,
 #define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL
+  BFD_RELOC_SPARC_PLT32,
   BFD_RELOC_SPARC_PLT64,
   BFD_RELOC_SPARC_HIX22,
   BFD_RELOC_SPARC_LOX10,
index e10cec1e73de48be3a6c66af6223a463b13629ac..f0f97464056eda7d58fe278a7ac1640d026d1561 100644 (file)
@@ -76,7 +76,7 @@ reloc_howto_type _bfd_sparc_elf_howto_table[] =
   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_DISP32,    0,2,32,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP32",  false,0,0xffffffff,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),
@@ -94,7 +94,7 @@ reloc_howto_type _bfd_sparc_elf_howto_table[] =
   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,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_UA32",    false,0,0xffffffff,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_PLT32,     0,0,00,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PLT32",   false,0,0xffffffff,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),
@@ -146,6 +146,7 @@ static const struct elf_reloc_map sparc_reloc_map[] =
 {
   { BFD_RELOC_NONE, R_SPARC_NONE, },
   { BFD_RELOC_16, R_SPARC_16, },
+  { BFD_RELOC_16_PCREL, R_SPARC_DISP16 },
   { BFD_RELOC_8, R_SPARC_8 },
   { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
   { BFD_RELOC_CTOR, R_SPARC_32 },
@@ -154,6 +155,7 @@ static const struct elf_reloc_map sparc_reloc_map[] =
   { BFD_RELOC_HI22, R_SPARC_HI22 },
   { BFD_RELOC_LO10, R_SPARC_LO10, },
   { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
+  { BFD_RELOC_SPARC_PLT32, R_SPARC_PLT32 },
   { BFD_RELOC_SPARC22, R_SPARC_22 },
   { BFD_RELOC_SPARC13, R_SPARC_13 },
   { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
@@ -494,6 +496,7 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
 
          break;
 
+       case R_SPARC_PLT32:
        case R_SPARC_WPLT30:
          /* This symbol requires a procedure linkage table entry.  We
              actually build the entry in adjust_dynamic_symbol,
@@ -507,6 +510,8 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
                  reloc for a local symbol if you assemble a call from
                  one section to another when using -K pic.  We treat
                  it as WDISP30.  */
+             if (ELF32_R_TYPE (rel->r_info) != R_SPARC_WPLT30)
+               goto r_sparc_plt32;
              break;
            }
 
@@ -519,6 +524,8 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
 
          h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
 
+         if (ELF32_R_TYPE (rel->r_info) != R_SPARC_WPLT30)
+           goto r_sparc_plt32;
          break;
 
        case R_SPARC_PC10:
@@ -566,6 +573,7 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
          if (h != NULL)
            h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
 
+       r_sparc_plt32:
          if (info->shared && (sec->flags & SEC_ALLOC))
            {
              /* When creating a shared object, we must copy these
@@ -1127,6 +1135,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
       asection *sec;
       bfd_vma relocation;
       bfd_reloc_status_type r;
+      boolean is_plt = false;
 
       r_type = ELF32_R_TYPE (rel->r_info);
 
@@ -1182,7 +1191,8 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
              || h->root.type == bfd_link_hash_defweak)
            {
              sec = h->root.u.def.section;
-             if ((r_type == R_SPARC_WPLT30
+             if (((r_type == R_SPARC_WPLT30
+                   || r_type == R_SPARC_PLT32)
                   && h->plt.offset != (bfd_vma) -1)
                  || ((r_type == R_SPARC_GOT10
                       || r_type == R_SPARC_GOT13
@@ -1351,6 +1361,13 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
 
          break;
 
+       case R_SPARC_PLT32:
+         if (h == NULL || h->plt.offset == (bfd_vma) -1)
+           {
+             r_type = R_SPARC_32;
+             goto r_sparc_plt32;
+           }
+         /* Fall through.  */
        case R_SPARC_WPLT30:
          /* Relocation is to the entry for this symbol in the
              procedure linkage table.  */
@@ -1379,6 +1396,12 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
          relocation = (splt->output_section->vma
                        + splt->output_offset
                        + h->plt.offset);
+         if (r_type == R_SPARC_PLT32)
+           {
+             r_type = R_SPARC_32;
+             is_plt = true;
+             goto r_sparc_plt32;
+           }
          break;
 
        case R_SPARC_PC10:
@@ -1409,6 +1432,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_SPARC_LO10:
        case R_SPARC_UA16:
        case R_SPARC_UA32:
+       r_sparc_plt32:
          if (info->shared
              && r_symndx != 0
              && (input_section->flags & SEC_ALLOC))
@@ -1476,7 +1500,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
                memset (&outrel, 0, sizeof outrel);
              /* h->dynindx may be -1 if the symbol was marked to
                  become local.  */
-             else if (h != NULL
+             else if (h != NULL && ! is_plt
                       && ((! info->symbolic && h->dynindx != -1)
                           || (h->elf_link_hash_flags
                               & ELF_LINK_HASH_DEF_REGULAR) == 0))
@@ -1496,7 +1520,9 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
                    {
                      long indx;
 
-                     if (h == NULL)
+                     if (is_plt)
+                       sec = splt;
+                     else if (h == NULL)
                        sec = local_sections[r_symndx];
                      else
                        {
index d636a20943102031784c635894d5e0fdc4141aba..07c78bc9eba8fafeb12239695b5185d48344428b 100644 (file)
@@ -116,7 +116,7 @@ static reloc_howto_type sparc64_elf_howto_table[] =
   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_DISP32,    0,2,32,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP32",  false,0,0xffffffff,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),
@@ -135,8 +135,8 @@ static reloc_howto_type sparc64_elf_howto_table[] =
   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,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_UA32",    false,0,0xffffffff,true),
 #ifndef SPARC64_OLD_RELOCS
+  HOWTO(R_SPARC_PLT32,     0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PLT32",   false,0,0xffffffff,true),
   /* These aren't implemented yet.  */
-  HOWTO(R_SPARC_PLT32,     0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_PLT32",    false,0,0x00000000,true),
   HOWTO(R_SPARC_HIPLT22,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_HIPLT22",  false,0,0x00000000,true),
   HOWTO(R_SPARC_LOPLT10,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_LOPLT10",  false,0,0x00000000,true),
   HOWTO(R_SPARC_PCPLT32,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_PCPLT32",  false,0,0x00000000,true),
@@ -160,7 +160,7 @@ static reloc_howto_type sparc64_elf_howto_table[] =
   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),
   HOWTO(R_SPARC_DISP64,    0,4,64,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP64",  false,0,MINUS_ONE, true),
-  HOWTO(R_SPARC_PLT64,     0,4,64,false,0,complain_overflow_bitfield,sparc_elf_notsup_reloc, "R_SPARC_PLT64",   false,0,MINUS_ONE, false),
+  HOWTO(R_SPARC_PLT64,     0,4,64,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PLT64",   false,0,MINUS_ONE, true),
   HOWTO(R_SPARC_HIX22,     0,4, 0,false,0,complain_overflow_bitfield,sparc_elf_hix22_reloc,  "R_SPARC_HIX22",   false,0,MINUS_ONE, false),
   HOWTO(R_SPARC_LOX10,     0,4, 0,false,0,complain_overflow_dont,    sparc_elf_lox10_reloc,  "R_SPARC_LOX10",   false,0,MINUS_ONE, false),
   HOWTO(R_SPARC_H44,      22,2,22,false,0,complain_overflow_unsigned,bfd_elf_generic_reloc,  "R_SPARC_H44",     false,0,0x003fffff,false),
@@ -180,6 +180,7 @@ static const struct elf_reloc_map sparc_reloc_map[] =
 {
   { BFD_RELOC_NONE, R_SPARC_NONE, },
   { BFD_RELOC_16, R_SPARC_16, },
+  { BFD_RELOC_16_PCREL, R_SPARC_DISP16 },
   { BFD_RELOC_8, R_SPARC_8 },
   { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
   { BFD_RELOC_CTOR, R_SPARC_64 },
@@ -188,6 +189,7 @@ static const struct elf_reloc_map sparc_reloc_map[] =
   { BFD_RELOC_HI22, R_SPARC_HI22 },
   { BFD_RELOC_LO10, R_SPARC_LO10, },
   { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
+  { BFD_RELOC_64_PCREL, R_SPARC_DISP64 },
   { BFD_RELOC_SPARC22, R_SPARC_22 },
   { BFD_RELOC_SPARC13, R_SPARC_13 },
   { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
@@ -220,6 +222,9 @@ static const struct elf_reloc_map sparc_reloc_map[] =
   { BFD_RELOC_SPARC_5, R_SPARC_5 },
   { BFD_RELOC_SPARC_6, R_SPARC_6 },
   { BFD_RELOC_SPARC_DISP64, R_SPARC_DISP64 },
+#ifndef SPARC64_OLD_RELOCS
+  { BFD_RELOC_SPARC_PLT32, R_SPARC_PLT32 },
+#endif
   { BFD_RELOC_SPARC_PLT64, R_SPARC_PLT64 },
   { BFD_RELOC_SPARC_HIX22, R_SPARC_HIX22 },
   { BFD_RELOC_SPARC_LOX10, R_SPARC_LOX10 },
@@ -1167,8 +1172,10 @@ sparc64_elf_check_relocs (abfd, info, sec, relocs)
            }
 
          h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
-         break;
-
+         if (ELF64_R_TYPE_ID (rel->r_info) != R_SPARC_PLT32
+             && ELF64_R_TYPE_ID (rel->r_info) != R_SPARC_PLT64)
+           break;
+         /* Fall through.  */
        case R_SPARC_PC10:
        case R_SPARC_PC22:
        case R_SPARC_PC_HH22:
@@ -1929,6 +1936,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
       asection *sec;
       bfd_vma relocation;
       bfd_reloc_status_type r;
+      boolean is_plt = false;
 
       r_type = ELF64_R_TYPE_ID (rel->r_info);
       if (r_type < 0 || r_type >= (int) R_SPARC_max_std)
@@ -2105,6 +2113,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            }
        }
 
+do_dynreloc:
       /* When generating a shared object, these relocations are copied
         into the output file to be resolved at run time.  */
       if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC))
@@ -2219,7 +2228,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  memset (&outrel, 0, sizeof outrel);
                /* h->dynindx may be -1 if the symbol was marked to
                   become local.  */
-               else if (h != NULL
+               else if (h != NULL && ! is_plt
                         && ((! info->symbolic && h->dynindx != -1)
                             || (h->elf_link_hash_flags
                                 & ELF_LINK_HASH_DEF_REGULAR) == 0))
@@ -2243,7 +2252,9 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                      {
                        long indx;
 
-                       if (h == NULL)
+                       if (is_plt)
+                         sec = splt;
+                       else if (h == NULL)
                          sec = local_sections[r_symndx];
                        else
                          {
@@ -2433,6 +2444,12 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                        + sparc64_elf_plt_entry_offset (h->plt.offset));
          if (r_type == R_SPARC_WPLT30)
            goto do_wplt30;
+         if (r_type == R_SPARC_PLT32 || r_type == R_SPARC_PLT64)
+           {
+             r_type = r_type == R_SPARC_PLT32 ? R_SPARC_32 : R_SPARC_64;
+             is_plt = true;
+             goto do_dynreloc;
+           }
          goto do_default;
 
        case R_SPARC_OLO10:
index 54629cf5db0ce31b32c1e496337eb2926ea09684..911ff0830e8d0e30c5cc16dc5aec2090b4db5eb4 100644 (file)
@@ -702,6 +702,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_SPARC_7",
   "BFD_RELOC_SPARC_6",
   "BFD_RELOC_SPARC_5",
+  "BFD_RELOC_SPARC_PLT32",
   "BFD_RELOC_SPARC_PLT64",
   "BFD_RELOC_SPARC_HIX22",
   "BFD_RELOC_SPARC_LOX10",
index c7c1c378f7157fd6de3326b871ff8f08fab0e712..d73ad2439645fbd592149f392995cdfd784c4cfd 100644 (file)
@@ -1856,6 +1856,8 @@ ENUMX
 ENUMEQX
   BFD_RELOC_SPARC_DISP64
   BFD_RELOC_64_PCREL
+ENUMX
+  BFD_RELOC_SPARC_PLT32
 ENUMX
   BFD_RELOC_SPARC_PLT64
 ENUMX
index 08164b3991b3d769560e5d33efbc6d37f673b5d3..65cad8cc41a0e035f148e6e0b03542cb52c6f4cd 100644 (file)
@@ -1,3 +1,25 @@
+2001-12-21  Jakub Jelinek  <jakub@redhat.com>
+
+       * config/tc-sparc.h (TC_PARSE_CONS_EXPRESSION): Define.
+       (sparc_cons): Provide prototype.
+       * config/tc-sparc.c (tc_gen_reloc): Handle BFD_RELOC_*_PCREL and
+       BFD_RELOC_SPARC_PLT{32,64}.  Enumerate for which relocs
+       reloc->addend = fixp->fx_addnumber shouldn't be done instead of
+       enumarating for which pc relative ones it should be done.
+       (sparc_cons_special_reloc): New variable.
+       (sparc_cons): New function.
+       (cons_fix_new_sparc): Use sparc_cons_special_reloc.
+       * testsuite/gas/sparc/pcrel.s: New test.
+       * testsuite/gas/sparc/pcrel.d: Expected output.
+       * testsuite/gas/sparc/pcrel64.s: New test.
+       * testsuite/gas/sparc/pcrel64.d: Expected output.
+       * testsuite/gas/sparc/plt.s: New test.
+       * testsuite/gas/sparc/plt.d: Expected output.
+       * testsuite/gas/sparc/plt64.s: New test.
+       * testsuite/gas/sparc/plt64.d: Expected output.
+       * testsuite/gas/sparc/sparc.exp: Add pcrel, pcrel64, plt and plt64
+       tests.
+
 2001-12-20  Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
            Daniel Jacobowitz <drow@mvista.com>
 
index 2db2bac12ba7f5980851c8262ee7259d1b33ccbf..fe9f3f7b776cef477bd22d163edea8bea34eafa1 100644 (file)
@@ -3313,6 +3313,12 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_SPARC_UA16:
     case BFD_RELOC_SPARC_UA32:
     case BFD_RELOC_SPARC_UA64:
+    case BFD_RELOC_8_PCREL:
+    case BFD_RELOC_16_PCREL:
+    case BFD_RELOC_32_PCREL:
+    case BFD_RELOC_64_PCREL:
+    case BFD_RELOC_SPARC_PLT32:
+    case BFD_RELOC_SPARC_PLT64:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
       code = fixp->fx_r_type;
@@ -3402,9 +3408,11 @@ tc_gen_reloc (section, fixp)
 
 #else /* elf or coff  */
 
-  if (reloc->howto->pc_relative == 0
-      || code == BFD_RELOC_SPARC_PC10
-      || code == BFD_RELOC_SPARC_PC22)
+  if (code != BFD_RELOC_32_PCREL_S2
+      && code != BFD_RELOC_SPARC_WDISP22
+      && code != BFD_RELOC_SPARC_WDISP16
+      && code != BFD_RELOC_SPARC_WDISP19
+      && code != BFD_RELOC_SPARC_WPLT30)
     reloc->addend = fixp->fx_addnumber;
   else if (symbol_section_p (fixp->fx_addsy))
     reloc->addend = (section->vma
@@ -3900,6 +3908,11 @@ s_proc (ignore)
 
 static int sparc_no_align_cons = 0;
 
+/* This static variable is set by sparc_cons to emit requested types
+   of relocations in cons_fix_new_sparc.  */
+
+static const char *sparc_cons_special_reloc;
+
 /* This handles the unaligned space allocation pseudo-ops, such as
    .uaword.  .uaword is just like .word, but the value does not need
    to be aligned.  */
@@ -4172,6 +4185,134 @@ sparc_elf_final_processing ()
   else if (current_architecture == SPARC_OPCODE_ARCH_V9B)
     elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1|EF_SPARC_SUN_US3;
 }
+
+void
+sparc_cons (exp, size)
+     expressionS *exp;
+     int size;
+{
+  char *save;
+
+  SKIP_WHITESPACE ();
+  sparc_cons_special_reloc = NULL;
+  save = input_line_pointer;
+  if (input_line_pointer[0] == '%'
+      && input_line_pointer[1] == 'r'
+      && input_line_pointer[2] == '_')
+    {
+      if (strncmp (input_line_pointer + 3, "disp", 4) == 0)
+       {
+         input_line_pointer += 7;
+         sparc_cons_special_reloc = "disp";
+       }
+      else if (strncmp (input_line_pointer + 3, "plt", 3) == 0)
+       {
+         if (size != 4 && size != 8)
+           as_bad (_("Illegal operands: %%r_plt in %d-byte data field"), size);
+         else
+           {
+             input_line_pointer += 6;
+             sparc_cons_special_reloc = "plt";
+           }
+       }
+      if (sparc_cons_special_reloc)
+       {
+         int bad = 0;
+
+         switch (size)
+           {
+           case 1:
+             if (*input_line_pointer != '8')
+               bad = 1;
+             input_line_pointer--;
+             break;
+           case 2:
+             if (input_line_pointer[0] != '1' || input_line_pointer[1] != '6')
+               bad = 1;
+             break;
+           case 4:
+             if (input_line_pointer[0] != '3' || input_line_pointer[1] != '2')
+               bad = 1;
+             break;
+           case 8:
+             if (input_line_pointer[0] != '6' || input_line_pointer[1] != '4')
+               bad = 1;
+             break;
+           default:
+             bad = 1;
+             break;
+           }
+
+         if (bad)
+           {
+             as_bad (_("Illegal operands: Only %%r_%s%d allowed in %d-byte data fields"),
+                     sparc_cons_special_reloc, size * 8, size);
+           }
+         else
+           {
+             input_line_pointer += 2;
+             if (*input_line_pointer != '(')
+               {
+                 as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+                         sparc_cons_special_reloc, size * 8);
+                 bad = 1;
+               }
+           }
+
+         if (bad)
+           {
+             input_line_pointer = save;
+             sparc_cons_special_reloc = NULL;
+           }
+         else
+           {
+             int c;
+             char *end = ++input_line_pointer;
+             int npar = 0;
+
+             while (! is_end_of_line[(c = *end)])
+               {
+                 if (c == '(')
+                   npar++;
+                 else if (c == ')')
+                   {
+                     if (!npar)
+                       break;
+                     npar--;
+                   }
+                 end++;
+               }
+
+             if (c != ')')
+               as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+                       sparc_cons_special_reloc, size * 8);
+             else
+               {
+                 *end = '\0';
+                 expression (exp);
+                 *end = c;
+                 if (input_line_pointer != end)
+                   {
+                     as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+                             sparc_cons_special_reloc, size * 8);
+                   }
+                 else
+                   {
+                     input_line_pointer++;
+                     SKIP_WHITESPACE ();
+                     c = *input_line_pointer;
+                     if (! is_end_of_line[c] && c != ',')
+                       as_bad (_("Illegal operands: garbage after %%r_%s%d()"),
+                               sparc_cons_special_reloc, size * 8);
+                   }
+               }
+           }
+       }
+    }
+  if (sparc_cons_special_reloc == NULL)
+    expression (exp);
+}
+
 #endif
 
 /* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
@@ -4196,7 +4337,25 @@ cons_fix_new_sparc (frag, where, nbytes, exp)
       && now_seg->flags & SEC_ALLOC)
     r = BFD_RELOC_SPARC_REV32;
 
-  if (sparc_no_align_cons)
+  if (sparc_cons_special_reloc)
+    {
+      if (*sparc_cons_special_reloc == 'd')
+       switch (nbytes)
+         {
+         case 1: r = BFD_RELOC_8_PCREL; break;
+         case 2: r = BFD_RELOC_16_PCREL; break;
+         case 4: r = BFD_RELOC_32_PCREL; break;
+         case 8: r = BFD_RELOC_64_PCREL; break;
+         default: abort ();
+         }
+      else
+       switch (nbytes)
+         {
+         case 4: r = BFD_RELOC_SPARC_PLT32; break;
+         case 8: r = BFD_RELOC_SPARC_PLT64; break;
+         }
+    }
+  else if (sparc_no_align_cons)
     {
       switch (nbytes)
        {
index 78653d7ea3510d07437612f307286448013d5063..5d545de0e23e0f321e695e58867e8f2c01a5e99c 100644 (file)
@@ -166,6 +166,11 @@ extern void sparc_md_end PARAMS ((void));
 
 #endif
 
+#ifdef OBJ_ELF
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) sparc_cons (EXP, NBYTES)
+extern void sparc_cons PARAMS ((expressionS *, int));
+#endif
+
 #define TC_CONS_FIX_NEW cons_fix_new_sparc
 extern void cons_fix_new_sparc
   PARAMS ((struct frag *, int, unsigned int, struct expressionS *));
diff --git a/gas/testsuite/gas/sparc/pcrel.d b/gas/testsuite/gas/sparc/pcrel.d
new file mode 100644 (file)
index 0000000..2d37010
--- /dev/null
@@ -0,0 +1,34 @@
+#as: 
+#objdump: -Dr
+#name: pc relative relocs
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <foo-0x8>:
+   0:  01 00 00 00     nop 
+   4:  01 00 00 00     nop 
+
+0+8 <foo>:
+   8:  01 00 00 00     nop 
+Disassembly of section .data:
+
+0+ <.data>:
+   0:  00 00 00 00     (unimp|illtrap)  0
+   4:  00 00 00 01     (unimp|illtrap)  0x1
+       ...
+                       8: R_SPARC_32   .text\+0x10
+                       c: R_SPARC_DISP32       .text\+0x10
+                       10: R_SPARC_32  .text\+0x10
+                       14: R_SPARC_DISP32      .text\+0x10
+                       18: R_SPARC_32  foo
+                       1c: R_SPARC_DISP32      foo
+                       20: R_SPARC_32  foo\+0x10
+                       24: R_SPARC_DISP32      foo\+0x10
+                       28: R_SPARC_DISP8       .data\+0x18
+                       29: R_SPARC_DISP8       .data\+0x34
+                       2a: R_SPARC_DISP16      .data\+0x18
+                       2c: R_SPARC_DISP16      .data\+0x34
+  30:  00 02 00 00     (unimp|illtrap)  0x20000
+       ...
diff --git a/gas/testsuite/gas/sparc/pcrel.s b/gas/testsuite/gas/sparc/pcrel.s
new file mode 100644 (file)
index 0000000..ac59454
--- /dev/null
@@ -0,0 +1,26 @@
+       .text
+       .align 4
+1:     nop
+2:     nop
+       .globl foo
+foo:   nop
+
+       .data
+       .align 32
+       .word 0
+       .word 1
+       .word 1b + 16
+       .word %r_disp32(1b + 16)
+       .word 1b + 16
+       .word %r_disp32(1b + 16)
+3:     .word foo
+       .word %r_disp32(foo)
+       .word foo + 16
+       .word %r_disp32(foo + 16)
+       .byte %r_disp8(3b)
+       .byte %r_disp8(4f)
+       .half %r_disp16(3b)
+       .half %r_disp16(4f)
+       .uaword 2
+       .half 0
+4:
diff --git a/gas/testsuite/gas/sparc/pcrel64.d b/gas/testsuite/gas/sparc/pcrel64.d
new file mode 100644 (file)
index 0000000..a93ead9
--- /dev/null
@@ -0,0 +1,40 @@
+#as: -64 -K PIC
+#objdump: -Dr
+#name: pc relative 64-bit relocs
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <foo-0x8>:
+   0:  01 00 00 00     nop 
+   4:  01 00 00 00     nop 
+
+0+8 <foo>:
+   8:  01 00 00 00     nop 
+Disassembly of section .data:
+
+0+ <.data>:
+   0:  00 00 00 00     illtrap  0
+   4:  00 00 00 01     illtrap  0x1
+       ...
+                       8: R_SPARC_32   .text\+0x10
+                       c: R_SPARC_DISP32       .text\+0x10
+                       10: R_SPARC_32  .text\+0x10
+                       14: R_SPARC_DISP32      .text\+0x10
+                       18: R_SPARC_32  foo
+                       1c: R_SPARC_DISP32      foo
+                       20: R_SPARC_32  foo\+0x10
+                       24: R_SPARC_DISP32      foo\+0x10
+                       28: R_SPARC_64  .text\+0x8
+                       30: R_SPARC_DISP64      .text\+0x8
+                       38: R_SPARC_64  foo
+                       40: R_SPARC_DISP64      foo
+                       48: R_SPARC_64  foo\+0x10
+                       50: R_SPARC_DISP64      foo\+0x10
+                       58: R_SPARC_DISP8       .data\+0x18
+                       59: R_SPARC_DISP8       .data\+0x64
+                       5a: R_SPARC_DISP16      .data\+0x18
+                       5c: R_SPARC_DISP16      .data\+0x64
+  60:  00 02 00 00     illtrap  0x20000
+       ...
diff --git a/gas/testsuite/gas/sparc/pcrel64.s b/gas/testsuite/gas/sparc/pcrel64.s
new file mode 100644 (file)
index 0000000..166b119
--- /dev/null
@@ -0,0 +1,32 @@
+       .text
+       .align 4
+1:     nop
+2:     nop
+       .globl foo
+foo:   nop
+
+       .data
+       .align 32
+       .word 0
+       .word 1
+       .word 1b + 16
+       .word %r_disp32(1b + 16)
+       .word 1b + 16
+       .word %r_disp32(1b + 16)
+3:     .word foo
+       .word %r_disp32(foo)
+       .word foo + 16
+       .word %r_disp32(foo + 16)
+       .xword 2b + 4
+       .xword %r_disp64(2b + 4)
+       .xword foo
+       .xword %r_disp64(foo)
+       .xword foo + 16
+       .xword %r_disp64(foo + 16)
+       .byte %r_disp8(3b)
+       .byte %r_disp8(4f)
+       .half %r_disp16(3b)
+       .half %r_disp16(4f)
+       .uaword 2
+       .half 0
+4:
diff --git a/gas/testsuite/gas/sparc/plt.d b/gas/testsuite/gas/sparc/plt.d
new file mode 100644 (file)
index 0000000..6b4ac27
--- /dev/null
@@ -0,0 +1,23 @@
+#as: -K PIC
+#objdump: -Dr
+#name: plt relocs
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+   0:  40 00 00 00     call  0x0
+                       0: R_SPARC_WPLT30       foo
+   4:  01 00 00 00     nop 
+   8:  40 00 00 00     call  0x8
+                       8: R_SPARC_WPLT30       bar\+0x4
+Disassembly of section .data:
+
+0+ <.data>:
+       ...
+                       0: R_SPARC_PLT32        foo
+                       4: R_SPARC_PLT32        bar\+0x4
+   8:  01 00 00 00     nop 
+                       9: R_SPARC_PLT32        foo
+   c:  00 02 03 04     (unimp|illtrap)  0x20304
diff --git a/gas/testsuite/gas/sparc/plt.s b/gas/testsuite/gas/sparc/plt.s
new file mode 100644 (file)
index 0000000..b7b4d09
--- /dev/null
@@ -0,0 +1,12 @@
+       .text
+       .align 4
+       call    foo
+        nop
+       call    bar + 4
+       .data
+       .align 4
+       .word   %r_plt32(foo)
+       .word   %r_plt32(bar + 4)
+       .byte   1
+       .uaword %r_plt32(foo)
+       .byte   2, 3, 4
diff --git a/gas/testsuite/gas/sparc/plt64.d b/gas/testsuite/gas/sparc/plt64.d
new file mode 100644 (file)
index 0000000..736515b
--- /dev/null
@@ -0,0 +1,26 @@
+#as: -K PIC -64
+#objdump: -Dr
+#name: plt 64-bit relocs
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+   0:  40 00 00 00     call  0x0
+                       0: R_SPARC_WPLT30       foo
+   4:  01 00 00 00     nop 
+   8:  40 00 00 00     call  0x8
+                       8: R_SPARC_WPLT30       bar\+0x4
+Disassembly of section .data:
+
+0+ <.data>:
+       ...
+                       0: R_SPARC_PLT64        foo
+                       8: R_SPARC_PLT64        bar\+0x4
+  10:  01 00 00 00     nop 
+                       11: R_SPARC_PLT64       foo
+  14:  00 00 00 00     illtrap  0
+  18:  00 02 03 04     illtrap  0x20304
+  1c:  00 00 00 00     illtrap  0
+                       1c: R_SPARC_PLT32       bar\+0x4
diff --git a/gas/testsuite/gas/sparc/plt64.s b/gas/testsuite/gas/sparc/plt64.s
new file mode 100644 (file)
index 0000000..e5faf20
--- /dev/null
@@ -0,0 +1,13 @@
+       .text
+       .align 4
+       call    foo
+        nop
+       call    bar + 4
+       .data
+       .align 8
+       .xword  %r_plt64(foo)
+       .xword  %r_plt64(bar + 4)
+        .byte   1
+       .uaxword %r_plt64(foo)
+       .byte   2, 3, 4
+       .word   %r_plt32(bar + 4)
index 39bf0f9395001d80abb6e60c82adea3cfb48ebd8..7298256d95bd09128220f3fda26328de0a7e2f09 100644 (file)
@@ -19,6 +19,8 @@ proc gas_64_check { } {
 if [istarget sparc*-*-*] {
     run_dump_test "synth"
     run_dump_test "unalign"
+    run_dump_test "pcrel"
+    run_dump_test "plt"
     if [gas_64_check] {
        run_dump_test "asi"
        run_dump_test "membar"
@@ -28,6 +30,8 @@ if [istarget sparc*-*-*] {
        run_dump_test "rdpr"
        run_dump_test "wrpr"
        run_dump_test "reloc64"
+       run_dump_test "pcrel64"
+       run_dump_test "plt64"
     }
 }