From bd5e6e7e3a8be60699e596633cd828d3446e75ee Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 21 Dec 2001 22:35:24 +0000 Subject: [PATCH] * 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/ChangeLog | 16 +++ bfd/bfd-in2.h | 1 + bfd/elf32-sparc.c | 36 ++++++- bfd/elf64-sparc.c | 31 ++++-- bfd/libbfd.h | 1 + bfd/reloc.c | 2 + gas/ChangeLog | 22 ++++ gas/config/tc-sparc.c | 167 +++++++++++++++++++++++++++++- gas/config/tc-sparc.h | 5 + gas/testsuite/gas/sparc/pcrel.d | 34 ++++++ gas/testsuite/gas/sparc/pcrel.s | 26 +++++ gas/testsuite/gas/sparc/pcrel64.d | 40 +++++++ gas/testsuite/gas/sparc/pcrel64.s | 32 ++++++ gas/testsuite/gas/sparc/plt.d | 23 ++++ gas/testsuite/gas/sparc/plt.s | 12 +++ gas/testsuite/gas/sparc/plt64.d | 26 +++++ gas/testsuite/gas/sparc/plt64.s | 13 +++ gas/testsuite/gas/sparc/sparc.exp | 4 + 18 files changed, 475 insertions(+), 16 deletions(-) create mode 100644 gas/testsuite/gas/sparc/pcrel.d create mode 100644 gas/testsuite/gas/sparc/pcrel.s create mode 100644 gas/testsuite/gas/sparc/pcrel64.d create mode 100644 gas/testsuite/gas/sparc/pcrel64.s create mode 100644 gas/testsuite/gas/sparc/plt.d create mode 100644 gas/testsuite/gas/sparc/plt.s create mode 100644 gas/testsuite/gas/sparc/plt64.d create mode 100644 gas/testsuite/gas/sparc/plt64.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a81b0b31141..f0c7fe71163 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,19 @@ +2001-12-21 Jakub Jelinek + + * 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 * coffcode.h (coff_compute_section_file_positions): Add special AIX diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 1e8b0b4bbab..920df8de488 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -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, diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c index e10cec1e73d..f0f97464056 100644 --- a/bfd/elf32-sparc.c +++ b/bfd/elf32-sparc.c @@ -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 { diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c index d636a209431..07c78bc9eba 100644 --- a/bfd/elf64-sparc.c +++ b/bfd/elf64-sparc.c @@ -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: diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 54629cf5db0..911ff0830e8 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -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", diff --git a/bfd/reloc.c b/bfd/reloc.c index c7c1c378f71..d73ad243964 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -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 diff --git a/gas/ChangeLog b/gas/ChangeLog index 08164b3991b..65cad8cc41a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,25 @@ +2001-12-21 Jakub Jelinek + + * 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 Daniel Jacobowitz diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c index 2db2bac12ba..fe9f3f7b776 100644 --- a/gas/config/tc-sparc.c +++ b/gas/config/tc-sparc.c @@ -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) { diff --git a/gas/config/tc-sparc.h b/gas/config/tc-sparc.h index 78653d7ea35..5d545de0e23 100644 --- a/gas/config/tc-sparc.h +++ b/gas/config/tc-sparc.h @@ -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 index 00000000000..2d37010a023 --- /dev/null +++ b/gas/testsuite/gas/sparc/pcrel.d @@ -0,0 +1,34 @@ +#as: +#objdump: -Dr +#name: pc relative relocs + +.*: +file format .*sparc.* + +Disassembly of section .text: + +0+ : + 0: 01 00 00 00 nop + 4: 01 00 00 00 nop + +0+8 : + 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 index 00000000000..ac59454408c --- /dev/null +++ b/gas/testsuite/gas/sparc/pcrel.s @@ -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 index 00000000000..a93ead91b65 --- /dev/null +++ b/gas/testsuite/gas/sparc/pcrel64.d @@ -0,0 +1,40 @@ +#as: -64 -K PIC +#objdump: -Dr +#name: pc relative 64-bit relocs + +.*: +file format .*sparc.* + +Disassembly of section .text: + +0+ : + 0: 01 00 00 00 nop + 4: 01 00 00 00 nop + +0+8 : + 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 index 00000000000..166b11985f8 --- /dev/null +++ b/gas/testsuite/gas/sparc/pcrel64.s @@ -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 index 00000000000..6b4ac271db9 --- /dev/null +++ b/gas/testsuite/gas/sparc/plt.d @@ -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 index 00000000000..b7b4d094010 --- /dev/null +++ b/gas/testsuite/gas/sparc/plt.s @@ -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 index 00000000000..736515b0ac3 --- /dev/null +++ b/gas/testsuite/gas/sparc/plt64.d @@ -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 index 00000000000..e5faf201e83 --- /dev/null +++ b/gas/testsuite/gas/sparc/plt64.s @@ -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) diff --git a/gas/testsuite/gas/sparc/sparc.exp b/gas/testsuite/gas/sparc/sparc.exp index 39bf0f93950..7298256d95b 100644 --- a/gas/testsuite/gas/sparc/sparc.exp +++ b/gas/testsuite/gas/sparc/sparc.exp @@ -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" } } -- 2.30.2