[PATCH] Support %r_disp{8,16,32,64} and %r_plt{32,64} on SPARC
Jakub Jelinek
jakub@redhat.com
Fri Dec 21 07:21:00 GMT 2001
Hi!
The following patch adds support for the weird Solaris as pc relative
notation, ie.
.word %r_disp32(foo)
instead of
.word foo - .
Actually, Solaris as doesn't support %r_disp8 and %r_disp16, but this seems
like a logical extension to me.
Also, which is far worse,
.align 4
.byte 1
.uaword %r_disp32(foo)
in Solaris as results in ld error if linking shared library, while the
following patch figures things properly (similarly for %r_plt32, which if
aligned becomes a R_SPARC_RELATIVE reloc (on sparc32) and if not aligned,
R_SPARC_UA32 against .plt).
Richard, do you agree?
In gcc, I'm afraid we'll need to:
1) add configure check for working unaligned %r_disp32() (ie. not Solaris as)
2) if assembler has working unaligned %r_disp32(), use DW_EH_PE_pcrel|DW_EH_PE_sdata4
as preferred format for shared libs, otherwise on Solaris use DW_EH_PE_aligned
due to ld.so bugs and elsewhere DW_EH_PE_absptr.
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.
* 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.
--- bfd/elf32-sparc.c.jj Mon Dec 17 12:29:15 2001
+++ bfd/elf32-sparc.c Fri Dec 21 16:15:37 2001
@@ -76,7 +76,7 @@ reloc_howto_type _bfd_sparc_elf_howto_ta
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_ta
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_
{
{ 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_
{ 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, se
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, se
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, se
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, se
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
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
|| 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
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
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
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
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
{
long indx;
- if (h == NULL)
+ if (is_plt)
+ sec = splt;
+ else if (h == NULL)
sec = local_sections[r_symndx];
else
{
--- bfd/elf64-sparc.c.jj Fri Dec 7 13:22:19 2001
+++ bfd/elf64-sparc.c Fri Dec 21 16:21:20 2001
@@ -118,7 +118,7 @@ static reloc_howto_type sparc64_elf_howt
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),
@@ -137,8 +137,8 @@ static reloc_howto_type sparc64_elf_howt
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),
@@ -162,7 +162,7 @@ static reloc_howto_type sparc64_elf_howt
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),
@@ -182,6 +182,7 @@ static const struct elf_reloc_map sparc_
{
{ 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 },
@@ -190,6 +191,7 @@ static const struct elf_reloc_map sparc_
{ 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 },
@@ -222,6 +224,9 @@ static const struct elf_reloc_map sparc_
{ 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 },
@@ -1169,8 +1174,10 @@ sparc64_elf_check_relocs (abfd, info, se
}
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:
@@ -1931,6 +1938,7 @@ sparc64_elf_relocate_section (output_bfd
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)
@@ -2107,6 +2115,7 @@ sparc64_elf_relocate_section (output_bfd
}
}
+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))
@@ -2221,7 +2230,7 @@ sparc64_elf_relocate_section (output_bfd
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))
@@ -2245,7 +2254,9 @@ sparc64_elf_relocate_section (output_bfd
{
long indx;
- if (h == NULL)
+ if (is_plt)
+ sec = splt;
+ else if (h == NULL)
sec = local_sections[r_symndx];
else
{
@@ -2435,6 +2446,12 @@ sparc64_elf_relocate_section (output_bfd
+ 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:
--- bfd/bfd-in2.h.jj Mon Dec 17 12:29:01 2001
+++ bfd/bfd-in2.h Fri Dec 21 15:56:15 2001
@@ -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,
--- bfd/libbfd.h.jj Mon Dec 17 12:29:48 2001
+++ bfd/libbfd.h Fri Dec 21 15:56:48 2001
@@ -702,6 +702,7 @@ static const char *const bfd_reloc_code_
"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",
--- bfd/reloc.c.jj Thu Dec 13 13:09:45 2001
+++ bfd/reloc.c Fri Dec 21 15:57:38 2001
@@ -1857,6 +1857,8 @@ ENUMEQX
BFD_RELOC_SPARC_DISP64
BFD_RELOC_64_PCREL
ENUMX
+ BFD_RELOC_SPARC_PLT32
+ENUMX
BFD_RELOC_SPARC_PLT64
ENUMX
BFD_RELOC_SPARC_HIX22
--- gas/config/tc-sparc.h.jj Fri Nov 16 21:50:12 2001
+++ gas/config/tc-sparc.h Thu Dec 20 18:35:04 2001
@@ -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 *));
--- gas/config/tc-sparc.c.jj Wed Nov 28 21:24:59 2001
+++ gas/config/tc-sparc.c Fri Dec 21 16:23:52 2001
@@ -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,
&& 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)
{
--- gas/testsuite/gas/sparc/pcrel.s.jj Fri Dec 21 14:34:12 2001
+++ gas/testsuite/gas/sparc/pcrel.s Fri Dec 21 14:41:44 2001
@@ -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:
--- gas/testsuite/gas/sparc/pcrel.d.jj Fri Dec 21 14:40:36 2001
+++ gas/testsuite/gas/sparc/pcrel.d Fri Dec 21 15:05:18 2001
@@ -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
+ ...
--- gas/testsuite/gas/sparc/pcrel64.s.jj Fri Dec 21 14:47:04 2001
+++ gas/testsuite/gas/sparc/pcrel64.s Fri Dec 21 14:48:40 2001
@@ -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:
--- gas/testsuite/gas/sparc/pcrel64.d.jj Fri Dec 21 14:48:52 2001
+++ gas/testsuite/gas/sparc/pcrel64.d Fri Dec 21 15:05:51 2001
@@ -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
+ ...
--- gas/testsuite/gas/sparc/sparc.exp.jj Wed Jul 11 15:48:52 2001
+++ gas/testsuite/gas/sparc/sparc.exp Fri Dec 21 16:38:11 2001
@@ -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"
}
}
--- gas/testsuite/gas/sparc/plt.s.jj Fri Dec 21 16:28:35 2001
+++ gas/testsuite/gas/sparc/plt.s Fri Dec 21 16:22:54 2001
@@ -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
--- gas/testsuite/gas/sparc/plt.d.jj Fri Dec 21 16:28:39 2001
+++ gas/testsuite/gas/sparc/plt.d Fri Dec 21 16:42:39 2001
@@ -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
--- gas/testsuite/gas/sparc/plt64.s.jj Fri Dec 21 16:28:52 2001
+++ gas/testsuite/gas/sparc/plt64.s Fri Dec 21 16:32:28 2001
@@ -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)
--- gas/testsuite/gas/sparc/plt64.d.jj Fri Dec 21 16:30:11 2001
+++ gas/testsuite/gas/sparc/plt64.d Fri Dec 21 16:42:50 2001
@@ -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
Jakub
More information about the Binutils
mailing list