From 1c2de46353b80e9e5b4d80d5edab00a42b8ba77d Mon Sep 17 00:00:00 2001 From: Sandra Loosemore Date: Mon, 3 Feb 2014 08:42:42 -0800 Subject: [PATCH] Nios II large-GOT relocations 2014-02-03 Sandra Loosemore include/elf/ * nios2.h (R_NIOS2_GOT_LO, R_NIOS2_GOT_HA): New. (R_NIOS2_CALL_LO, R_NIOS2_CALL_HA): New. (R_NIOS2_ILLEGAL): Adjust. gas/ * config/tc-nios2.c (md_apply_fix): Test for new relocs. (nios2_special_reloc): Add %call_lo, %call_hiadj, %got_lo, %got_hiadj relocation operators. Sort table and add comment to explain ordering. (nios2_fix_adjustable): Test for new relocs. * doc/c-nios2.texi (Nios II Relocations): Document new relocation operators. bfd/ * reloc.c (BFD_RELOC_NIOS2_GOT_LO, BFD_RELOC_NIOS2_GOT_HA): New. (BFD_RELOC_NIOS2_CALL_LO, BFD_RELOC_NIOS2_CALL_HA): New. * libbfd.h: Regenerated. * bfd-in2.h: Regenerated. * elf32-nios2.c (elf_nios2_howto_table_rel): Add new relocations. (nios2_reloc_map): Likewise. (GOT_USED, CALL_USED): Renamed from GOT16_USED and CALL16_USED. Fixed all references. (nios2_elf32_relocate_section): Add new relocations. (nios2_elf32_check_relocs): Likewise. (nios2_elf32_gc_sweep_hook): Likewise. --- bfd/ChangeLog | 14 +++++ bfd/bfd-in2.h | 4 ++ bfd/elf32-nios2.c | 126 +++++++++++++++++++++++++++++++++++++----- bfd/libbfd.h | 4 ++ bfd/reloc.c | 8 +++ gas/ChangeLog | 10 ++++ gas/config/tc-nios2.c | 24 ++++++-- gas/doc/c-nios2.texi | 8 +++ include/elf/ChangeLog | 6 ++ include/elf/nios2.h | 6 +- 10 files changed, 192 insertions(+), 18 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 2793df0c70..b5d658b591 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +2014-02-03 Sandra Loosemore + + * reloc.c (BFD_RELOC_NIOS2_GOT_LO, BFD_RELOC_NIOS2_GOT_HA): New. + (BFD_RELOC_NIOS2_CALL_LO, BFD_RELOC_NIOS2_CALL_HA): New. + * libbfd.h: Regenerated. + * bfd-in2.h: Regenerated. + * elf32-nios2.c (elf_nios2_howto_table_rel): Add new relocations. + (nios2_reloc_map): Likewise. + (GOT_USED, CALL_USED): Renamed from GOT16_USED and CALL16_USED. + Fixed all references. + (nios2_elf32_relocate_section): Add new relocations. + (nios2_elf32_check_relocs): Likewise. + (nios2_elf32_gc_sweep_hook): Likewise. + 2014-02-03 Alan Modra * elf32-ppc.c (struct ppc_elf_link_hash_table): Add params. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 036f65addd..33792f45a5 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -5227,6 +5227,10 @@ a matching LO8XG part. */ BFD_RELOC_NIOS2_RELATIVE, BFD_RELOC_NIOS2_GOTOFF, BFD_RELOC_NIOS2_CALL26_NOAT, + BFD_RELOC_NIOS2_GOT_LO, + BFD_RELOC_NIOS2_GOT_HA, + BFD_RELOC_NIOS2_CALL_LO, + BFD_RELOC_NIOS2_CALL_HA, /* IQ2000 Relocations. */ BFD_RELOC_IQ2000_OFFSET_16, diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c index dbe52891ba..b6a60ff96c 100644 --- a/bfd/elf32-nios2.c +++ b/bfd/elf32-nios2.c @@ -670,6 +670,62 @@ static reloc_howto_type elf_nios2_howto_table_rel[] = { 0xffffffc0, /* dst_mask */ FALSE), /* pcrel_offset */ + HOWTO (R_NIOS2_GOT_LO, + 0, + 2, + 16, + FALSE, + 6, + complain_overflow_dont, + bfd_elf_generic_reloc, + "R_NIOS2_GOT_LO", + FALSE, + 0x003fffc0, + 0x003fffc0, + FALSE), + + HOWTO (R_NIOS2_GOT_HA, + 0, + 2, + 16, + FALSE, + 6, + complain_overflow_dont, + bfd_elf_generic_reloc, + "R_NIOS2_GOT_HA", + FALSE, + 0x003fffc0, + 0x003fffc0, + FALSE), + + HOWTO (R_NIOS2_CALL_LO, + 0, + 2, + 16, + FALSE, + 6, + complain_overflow_dont, + bfd_elf_generic_reloc, + "R_NIOS2_CALL_LO", + FALSE, + 0x003fffc0, + 0x003fffc0, + FALSE), + + HOWTO (R_NIOS2_CALL_HA, + 0, + 2, + 16, + FALSE, + 6, + complain_overflow_dont, + bfd_elf_generic_reloc, + "R_NIOS2_CALL_HA", + FALSE, + 0x003fffc0, + 0x003fffc0, + FALSE), + /* Add other relocations here. */ }; @@ -749,6 +805,10 @@ static const struct elf_reloc_map nios2_reloc_map[] = { {BFD_RELOC_NIOS2_RELATIVE, R_NIOS2_RELATIVE}, {BFD_RELOC_NIOS2_GOTOFF, R_NIOS2_GOTOFF}, {BFD_RELOC_NIOS2_CALL26_NOAT, R_NIOS2_CALL26_NOAT}, + {BFD_RELOC_NIOS2_GOT_LO, R_NIOS2_GOT_LO}, + {BFD_RELOC_NIOS2_GOT_HA, R_NIOS2_GOT_HA}, + {BFD_RELOC_NIOS2_CALL_LO, R_NIOS2_CALL_LO}, + {BFD_RELOC_NIOS2_CALL_HA, R_NIOS2_CALL_HA}, }; enum elf32_nios2_stub_type @@ -839,10 +899,11 @@ struct elf32_nios2_link_hash_entry a dynamic GOT reloc in shared objects, only a dynamic PLT reloc. Lazy linking will not work if the dynamic GOT reloc exists. To check for this condition efficiently, we compare got_types_used against - CALL16_USED, meaning - (got_types_used & (GOT16_USED | CALL16_USED)) == CALL16_USED. */ -#define GOT16_USED 1 -#define CALL16_USED 2 + CALL_USED, meaning + (got_types_used & (GOT_USED | CALL_USED)) == CALL_USED. + */ +#define GOT_USED 1 +#define CALL_USED 2 unsigned char got_types_used; }; @@ -2942,6 +3003,10 @@ nios2_elf32_relocate_section (bfd *output_bfd, case R_NIOS2_GOT16: case R_NIOS2_CALL16: + case R_NIOS2_GOT_LO: + case R_NIOS2_GOT_HA: + case R_NIOS2_CALL_LO: + case R_NIOS2_CALL_HA: /* Relocation is to the entry for this symbol in the global offset table. */ if (sgot == NULL) @@ -2957,7 +3022,7 @@ nios2_elf32_relocate_section (bfd *output_bfd, bfd_boolean dyn; eh = (struct elf32_nios2_link_hash_entry *)h; - use_plt = (eh->got_types_used == CALL16_USED + use_plt = (eh->got_types_used == CALL_USED && h->plt.offset != (bfd_vma) -1); off = h->got.offset; @@ -3044,9 +3109,30 @@ nios2_elf32_relocate_section (bfd *output_bfd, /* This relocation does not use the addend. */ rel->r_addend = 0; - r = _bfd_final_link_relocate (howto, input_bfd, input_section, - contents, rel->r_offset, - relocation, rel->r_addend); + switch (howto->type) + { + case R_NIOS2_GOT_LO: + case R_NIOS2_CALL_LO: + r = nios2_elf32_do_lo16_relocate (input_bfd, howto, + input_section, contents, + rel->r_offset, relocation, + rel->r_addend); + break; + case R_NIOS2_GOT_HA: + case R_NIOS2_CALL_HA: + r = nios2_elf32_do_hiadj16_relocate (input_bfd, howto, + input_section, contents, + rel->r_offset, + relocation, + rel->r_addend); + break; + default: + r = _bfd_final_link_relocate (howto, input_bfd, + input_section, contents, + rel->r_offset, relocation, + rel->r_addend); + break; + } break; case R_NIOS2_GOTOFF_LO: @@ -3671,7 +3757,11 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, switch (r_type) { case R_NIOS2_GOT16: + case R_NIOS2_GOT_LO: + case R_NIOS2_GOT_HA: case R_NIOS2_CALL16: + case R_NIOS2_CALL_LO: + case R_NIOS2_CALL_HA: case R_NIOS2_TLS_GD16: case R_NIOS2_TLS_IE16: /* This symbol requires a global offset table entry. */ @@ -3682,7 +3772,11 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, { default: case R_NIOS2_GOT16: + case R_NIOS2_GOT_LO: + case R_NIOS2_GOT_HA: case R_NIOS2_CALL16: + case R_NIOS2_CALL_LO: + case R_NIOS2_CALL_HA: tls_type = GOT_NORMAL; break; case R_NIOS2_TLS_GD16: @@ -3719,7 +3813,9 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, = (struct elf32_nios2_link_hash_entry *)h; h->got.refcount++; old_tls_type = elf32_nios2_hash_entry(h)->tls_type; - if (r_type == R_NIOS2_CALL16) + if (r_type == R_NIOS2_CALL16 + || r_type == R_NIOS2_CALL_LO + || r_type == R_NIOS2_CALL_HA) { /* Make sure a plt entry is created for this symbol if it turns out to be a function defined by a dynamic @@ -3727,10 +3823,10 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, h->plt.refcount++; h->needs_plt = 1; h->type = STT_FUNC; - eh->got_types_used |= CALL16_USED; + eh->got_types_used |= CALL_USED; } else - eh->got_types_used |= GOT16_USED; + eh->got_types_used |= GOT_USED; } else { @@ -3964,7 +4060,11 @@ nios2_elf32_gc_sweep_hook (bfd *abfd, switch (r_type) { case R_NIOS2_GOT16: + case R_NIOS2_GOT_LO: + case R_NIOS2_GOT_HA: case R_NIOS2_CALL16: + case R_NIOS2_CALL_LO: + case R_NIOS2_CALL_HA: if (h != NULL) { if (h->got.refcount > 0) @@ -4114,7 +4214,7 @@ nios2_elf32_finish_dynamic_symbol (bfd *output_bfd, } } - use_plt = (eh->got_types_used == CALL16_USED + use_plt = (eh->got_types_used == CALL_USED && h->plt.offset != (bfd_vma) -1); if (!use_plt && h->got.offset != (bfd_vma) -1 @@ -4587,7 +4687,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf) } eh = (struct elf32_nios2_link_hash_entry *) h; - use_plt = (eh->got_types_used == CALL16_USED + use_plt = (eh->got_types_used == CALL_USED && h->plt.offset != (bfd_vma) -1); if (h->got.refcount > 0) diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 9711e171bd..bbca43fda7 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -2533,6 +2533,10 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_NIOS2_RELATIVE", "BFD_RELOC_NIOS2_GOTOFF", "BFD_RELOC_NIOS2_CALL26_NOAT", + "BFD_RELOC_NIOS2_GOT_LO", + "BFD_RELOC_NIOS2_GOT_HA", + "BFD_RELOC_NIOS2_CALL_LO", + "BFD_RELOC_NIOS2_CALL_HA", "BFD_RELOC_IQ2000_OFFSET_16", "BFD_RELOC_IQ2000_OFFSET_21", "BFD_RELOC_IQ2000_UHI16", diff --git a/bfd/reloc.c b/bfd/reloc.c index 3d1256d7ef..5cc6e0ce38 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -6067,6 +6067,14 @@ ENUMX BFD_RELOC_NIOS2_GOTOFF ENUMX BFD_RELOC_NIOS2_CALL26_NOAT +ENUMX + BFD_RELOC_NIOS2_GOT_LO +ENUMX + BFD_RELOC_NIOS2_GOT_HA +ENUMX + BFD_RELOC_NIOS2_CALL_LO +ENUMX + BFD_RELOC_NIOS2_CALL_HA ENUMDOC Relocations used by the Altera Nios II core. diff --git a/gas/ChangeLog b/gas/ChangeLog index a3f0f03ca5..19d402500f 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2014-02-03 Sandra Loosemore + + * config/tc-nios2.c (md_apply_fix): Test for new relocs. + (nios2_special_reloc): Add %call_lo, %call_hiadj, %got_lo, + %got_hiadj relocation operators. Sort table and add comment + to explain ordering. + (nios2_fix_adjustable): Test for new relocs. + * doc/c-nios2.texi (Nios II Relocations): Document new relocation + operators. + 2014-01-30 Sandra Loosemore * config/tc-nios2.c (md_apply_fix): Handle BFD_RELOC_NIOS2_CALL26_NOAT. diff --git a/gas/config/tc-nios2.c b/gas/config/tc-nios2.c index eb81b352d8..3d52048664 100644 --- a/gas/config/tc-nios2.c +++ b/gas/config/tc-nios2.c @@ -1139,7 +1139,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) || fixP->fx_r_type == BFD_RELOC_NIOS2_U16 || fixP->fx_r_type == BFD_RELOC_16_PCREL || fixP->fx_r_type == BFD_RELOC_NIOS2_CALL26 - || fixP->fx_r_type == BFD_RELOC_NIOS2_CALL26_NOAT || fixP->fx_r_type == BFD_RELOC_NIOS2_IMM5 || fixP->fx_r_type == BFD_RELOC_NIOS2_CACHE_OPX || fixP->fx_r_type == BFD_RELOC_NIOS2_IMM6 @@ -1165,6 +1164,11 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) || fixP->fx_r_type == BFD_RELOC_NIOS2_TLS_LE16 || fixP->fx_r_type == BFD_RELOC_NIOS2_GOTOFF || fixP->fx_r_type == BFD_RELOC_NIOS2_TLS_DTPREL + || fixP->fx_r_type == BFD_RELOC_NIOS2_CALL26_NOAT + || fixP->fx_r_type == BFD_RELOC_NIOS2_GOT_LO + || fixP->fx_r_type == BFD_RELOC_NIOS2_GOT_HA + || fixP->fx_r_type == BFD_RELOC_NIOS2_CALL_LO + || fixP->fx_r_type == BFD_RELOC_NIOS2_CALL_HA /* Add other relocs here as we generate them. */ )); @@ -1301,21 +1305,28 @@ struct nios2_special_relocS bfd_reloc_code_real_type reloc_type; }; +/* This table is sorted so that prefix strings are listed after the longer + strings that include them -- e.g., %got after %got_hiadj, etc. */ + struct nios2_special_relocS nios2_special_reloc[] = { {"%hiadj", BFD_RELOC_NIOS2_HIADJ16}, {"%hi", BFD_RELOC_NIOS2_HI16}, {"%lo", BFD_RELOC_NIOS2_LO16}, {"%gprel", BFD_RELOC_NIOS2_GPREL}, + {"%call_lo", BFD_RELOC_NIOS2_CALL_LO}, + {"%call_hiadj", BFD_RELOC_NIOS2_CALL_HA}, {"%call", BFD_RELOC_NIOS2_CALL16}, {"%gotoff_lo", BFD_RELOC_NIOS2_GOTOFF_LO}, {"%gotoff_hiadj", BFD_RELOC_NIOS2_GOTOFF_HA}, + {"%gotoff", BFD_RELOC_NIOS2_GOTOFF}, + {"%got_hiadj", BFD_RELOC_NIOS2_GOT_HA}, + {"%got_lo", BFD_RELOC_NIOS2_GOT_LO}, + {"%got", BFD_RELOC_NIOS2_GOT16}, {"%tls_gd", BFD_RELOC_NIOS2_TLS_GD16}, {"%tls_ldm", BFD_RELOC_NIOS2_TLS_LDM16}, {"%tls_ldo", BFD_RELOC_NIOS2_TLS_LDO16}, {"%tls_ie", BFD_RELOC_NIOS2_TLS_IE16}, {"%tls_le", BFD_RELOC_NIOS2_TLS_LE16}, - {"%gotoff", BFD_RELOC_NIOS2_GOTOFF}, - {"%got", BFD_RELOC_NIOS2_GOT16} }; #define NIOS2_NUM_SPECIAL_RELOCS \ @@ -2824,7 +2835,12 @@ nios2_fix_adjustable (fixS *fixp) || fixp->fx_r_type == BFD_RELOC_NIOS2_TLS_DTPMOD || fixp->fx_r_type == BFD_RELOC_NIOS2_TLS_DTPREL || fixp->fx_r_type == BFD_RELOC_NIOS2_TLS_TPREL - || fixp->fx_r_type == BFD_RELOC_NIOS2_GOTOFF) + || fixp->fx_r_type == BFD_RELOC_NIOS2_GOTOFF + || fixp->fx_r_type == BFD_RELOC_NIOS2_GOT_LO + || fixp->fx_r_type == BFD_RELOC_NIOS2_GOT_HA + || fixp->fx_r_type == BFD_RELOC_NIOS2_CALL_LO + || fixp->fx_r_type == BFD_RELOC_NIOS2_CALL_HA + ) return 0; return 1; diff --git a/gas/doc/c-nios2.texi b/gas/doc/c-nios2.texi index 1d45dd20b2..0ba6b9b847 100644 --- a/gas/doc/c-nios2.texi +++ b/gas/doc/c-nios2.texi @@ -131,7 +131,11 @@ fastint: @end smallexample @cindex @code{call} directive, Nios II +@cindex @code{call_lo} directive, Nios II +@cindex @code{call_hiadj} directive, Nios II @cindex @code{got} directive, Nios II +@cindex @code{got_lo} directive, Nios II +@cindex @code{got_hiadj} directive, Nios II @cindex @code{gotoff} directive, Nios II @cindex @code{gotoff_lo} directive, Nios II @cindex @code{gotoff_hiadj} directive, Nios II @@ -141,7 +145,11 @@ fastint: @cindex @code{tls_ldm} directive, Nios II @cindex @code{tls_ldo} directive, Nios II @item %call(@var{expression}) +@item %call_lo(@var{expression}) +@item %call_hiadj(@var{expression}) @itemx %got(@var{expression}) +@itemx %got_lo(@var{expression}) +@itemx %got_hiadj(@var{expression}) @itemx %gotoff(@var{expression}) @itemx %gotoff_lo(@var{expression}) @itemx %gotoff_hiadj(@var{expression}) diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index 28272d8338..6d144b4076 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,9 @@ +2014-02-03 Sandra Loosemore + + * nios2.h (R_NIOS2_GOT_LO, R_NIOS2_GOT_HA): New. + (R_NIOS2_CALL_LO, R_NIOS2_CALL_HA): New. + (R_NIOS2_ILLEGAL): Adjust. + 2014-01-30 Sandra Loosemore * nios2.h (elf_nios2_reloc_type): Add R_NIOS2_CALL26_NOAT. diff --git a/include/elf/nios2.h b/include/elf/nios2.h index 76863508bf..47afc0fd45 100644 --- a/include/elf/nios2.h +++ b/include/elf/nios2.h @@ -76,7 +76,11 @@ START_RELOC_NUMBERS (elf_nios2_reloc_type) RELOC_NUMBER (R_NIOS2_RELATIVE, 39) RELOC_NUMBER (R_NIOS2_GOTOFF, 40) RELOC_NUMBER (R_NIOS2_CALL26_NOAT, 41) - RELOC_NUMBER (R_NIOS2_ILLEGAL, 42) + RELOC_NUMBER (R_NIOS2_GOT_LO, 42) + RELOC_NUMBER (R_NIOS2_GOT_HA, 43) + RELOC_NUMBER (R_NIOS2_CALL_LO, 44) + RELOC_NUMBER (R_NIOS2_CALL_HA, 45) + RELOC_NUMBER (R_NIOS2_ILLEGAL, 46) END_RELOC_NUMBERS (R_NIOS2_maxext) /* Processor-specific section flags. */ -- 2.34.1