diff options
author | Cl?ment Chigot <clement.chigot@atos.net> | 2022-04-20 15:11:47 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2022-04-20 15:11:47 +0100 |
commit | 2d23f9656c3fd92335683188d26db198fe2ed3ec (patch) | |
tree | d3c564dca842f9bbd216e2e05c3f03ac86eadf95 /bfd/coff-rs6000.c | |
parent | 1876a542175ef438d6aaafeccb479024994b938d (diff) | |
download | fsf-binutils-gdb-2d23f9656c3fd92335683188d26db198fe2ed3ec.zip fsf-binutils-gdb-2d23f9656c3fd92335683188d26db198fe2ed3ec.tar.gz fsf-binutils-gdb-2d23f9656c3fd92335683188d26db198fe2ed3ec.tar.bz2 |
xcoff: implement linker relaxation
bfd/ChangeLog:
* coff-rs6000.c (xcoff_reloc_type_noop): Add info argument.
(xcoff_reloc_type_fail): Likewise.
(xcoff_reloc_type_pos): Likewise.
(xcoff_reloc_type_neg): Likewise.
(xcoff_reloc_type_rel): Likewise.
(xcoff_reloc_type_toc): Likewise.
(xcoff_reloc_type_ba): Likewise.
(xcoff_reloc_type_crel): Likewise.
(xcoff_reloc_type_tls): Likewise.
(xcoff_reloc_type_br): Add stub handler.
(xcoff_ppc_relocate_section): Add info to
xcoff_calculate_relocation.
(xcoff_stub_indirect_call_code): New constant.
(xcoff_stub_shared_call_code): Likewise.
(bfd_xcoff_backend_data): Add stub code fields.
(bfd_pmac_xcoff_backend_data): Likewise.
* coff64-rs6000.c (xcoff64_reloc_type_br): Add stub handler.
(xcoff64_ppc_relocate_section): Add info to
xcoff64_calculate_relocation.
(xcoff64_stub_indirect_call_code): New constant.
(xcoff64_stub_shared_call_code): Likewise.
(bfd_xcoff_backend_data): Add stub code fields.
(bfd_xcoff_aix5_backend_data): Likewise.
* libxcoff.h (struct xcoff_backend_data_rec): Add stub fields.
(bfd_xcoff_stub_indirect_call_code): New define.
(bfd_xcoff_stub_indirect_call_size): New define.
(bfd_xcoff_stub_shared_call_code): New define.
(bfd_xcoff_stub_shared_call_size): New define.
(xcoff_reloc_function): Add info argument.
(enum xcoff_stub_type): New enum.
(struct xcoff_stub_hash_entry): New structure.
* xcofflink.c (struct xcoff_link_hash_table): Add stub hash
table and params fields.
(xcoff_stub_hash_entry): New define.
(xcoff_stub_hash_lookup): New define.
(stub_hash_newfunc): New function.
(_bfd_xcoff_bfd_link_hash_table_free): Free the new stub hash
table.
(_bfd_xcoff_bfd_link_hash_table_create): Create the new stub
hash table.
(xcoff_link_add_symbols): Save rawsize for XTY_SD.
(bfd_xcoff_link_init): New function.
(xcoff_stub_csect_name): New function.
(xcoff_stub_get_csect_in_range): New function.
(xcoff_stub_name): New function.
(bfd_xcoff_get_stub_entry): New function.
(bfd_xcoff_type_of_stub): New function.
(xcoff_add_stub): New function.
(xcoff_build_one_stub): New function.
(bfd_xcoff_size_stubs): New function.
(bfd_xcoff_build_stubs): New function.
(xcoff_stub_create_relocations): New function.
(xcoff_link_input_bfd): Adapt relocations to stub.
(xcoff_write_global_symbol): Adapt to new TOC entries generated
for stubs.
(_bfd_xcoff_bfd_final_link): Handle stub file.
* xcofflink.h (struct bfd_xcoff_link_params): New structure.
ld/ChangeLog:
* emultempl/aix.em (params): New variable.
(stub_file): New variable.
(xcoff_add_stub_section): New function.
(xcoff_layout_sections_again): New function
(hook_in_stub): New function.
(_after_allocation): Add stub creation.
(_create_output_section_statements): Allocate stub file and
pass params to backend.
Diffstat (limited to 'bfd/coff-rs6000.c')
-rw-r--r-- | bfd/coff-rs6000.c | 99 |
1 files changed, 88 insertions, 11 deletions
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c index 8656dfd..8819187 100644 --- a/bfd/coff-rs6000.c +++ b/bfd/coff-rs6000.c @@ -2937,7 +2937,8 @@ xcoff_reloc_type_noop (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val ATTRIBUTE_UNUSED, bfd_vma addend ATTRIBUTE_UNUSED, bfd_vma *relocation ATTRIBUTE_UNUSED, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { return true; } @@ -2952,7 +2953,8 @@ xcoff_reloc_type_fail (bfd *input_bfd, bfd_vma val ATTRIBUTE_UNUSED, bfd_vma addend ATTRIBUTE_UNUSED, bfd_vma *relocation ATTRIBUTE_UNUSED, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { _bfd_error_handler /* xgettext: c-format */ @@ -2972,7 +2974,8 @@ xcoff_reloc_type_pos (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { *relocation = val + addend; return true; @@ -2988,7 +2991,8 @@ xcoff_reloc_type_neg (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { *relocation = - val - addend; return true; @@ -3004,7 +3008,8 @@ xcoff_reloc_type_rel (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { howto->pc_relative = true; @@ -3027,7 +3032,8 @@ xcoff_reloc_type_toc (bfd *input_bfd, bfd_vma val, bfd_vma addend ATTRIBUTE_UNUSED, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { struct xcoff_link_hash_entry *h; @@ -3076,7 +3082,8 @@ xcoff_reloc_type_ba (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { howto->src_mask &= ~3; howto->dst_mask = howto->src_mask; @@ -3096,10 +3103,13 @@ xcoff_reloc_type_br (bfd *input_bfd, bfd_vma val, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents) + bfd_byte *contents, + struct bfd_link_info *info) { struct xcoff_link_hash_entry *h; bfd_vma section_offset; + struct xcoff_stub_hash_entry *stub_entry = NULL; + enum xcoff_stub_type stub_type; if (0 > rel->r_symndx) return false; @@ -3153,6 +3163,27 @@ xcoff_reloc_type_br (bfd *input_bfd, howto->complain_on_overflow = complain_overflow_dont; } + /* Check if a stub is needed. */ + stub_type = bfd_xcoff_type_of_stub (input_section, rel, val, h); + if (stub_type != xcoff_stub_none) + { + asection *stub_csect; + + stub_entry = bfd_xcoff_get_stub_entry (input_section, h, info); + if (stub_entry == NULL) + { + _bfd_error_handler (_("Unable to find the stub entry targeting %s"), + h->root.root.string); + bfd_set_error (bfd_error_bad_value); + return false; + } + + stub_csect = stub_entry->hcsect->root.u.def.section; + val = (stub_entry->stub_offset + + stub_csect->output_section->vma + + stub_csect->output_offset); + } + /* The original PC-relative relocation is biased by -r_vaddr, so adding the value below will give the absolute target address. */ *relocation = val + addend + rel->r_vaddr; @@ -3202,7 +3233,8 @@ xcoff_reloc_type_crel (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val ATTRIBUTE_UNUSED, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { howto->pc_relative = true; howto->src_mask &= ~3; @@ -3227,7 +3259,8 @@ xcoff_reloc_type_tls (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { struct xcoff_link_hash_entry *h; @@ -3763,7 +3796,7 @@ xcoff_ppc_relocate_section (bfd *output_bfd, if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION || !((*xcoff_calculate_relocation[rel->r_type]) (input_bfd, input_section, output_bfd, rel, sym, &howto, val, - addend, &relocation, contents))) + addend, &relocation, contents, info))) return false; /* address */ @@ -4281,6 +4314,34 @@ HOWTO (0, /* type */ 0xffffffff, /* dst_mask */ false); /* pcrel_offset */ +/* Indirect call stub + The first word of the code must be modified by filling in + the correct TOC offset. */ + +static const unsigned long xcoff_stub_indirect_call_code[4] = + { + 0x81820000, /* lwz r12,0(r2) */ + 0x800c0000, /* lwz r0,0(r12) */ + 0x7c0903a6, /* mtctr r0 */ + 0x4e800420, /* bctr */ + }; + +/* Shared call stub + The first word of the code must be modified by filling in + the correct TOC offset. + This is exactly as the glink code but without the traceback, + as it won't be an independent function. */ + +static const unsigned long xcoff_stub_shared_call_code[6] = + { + 0x81820000, /* lwz r12,0(r2) */ + 0x90410014, /* stw r2,20(r1) */ + 0x800c0000, /* lwz r0,0(r12) */ + 0x804c0004, /* lwz r2,4(r12) */ + 0x7c0903a6, /* mtctr r0 */ + 0x4e800420, /* bctr */ + }; + /* glink The first word of global linkage code must be modified by filling in @@ -4497,6 +4558,14 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data = /* rtinit */ 64, /* _xcoff_rtinit_size */ xcoff_generate_rtinit, + + /* Stub indirect call. */ + &xcoff_stub_indirect_call_code[0], + 16, /* _xcoff_stub_indirect_call_size */ + + /* Stub shared call. */ + &xcoff_stub_shared_call_code[0], + 24, /* _xcoff_stub_shared_call_size */ }; /* The transfer vector that leads the outside world to all of the above. */ @@ -4679,6 +4748,14 @@ static const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data = /* rtinit */ 0, /* _xcoff_rtinit_size */ xcoff_generate_rtinit, + + /* Stub indirect call. */ + &xcoff_stub_indirect_call_code[0], + 16, /* _xcoff_stub_indirect_call_size */ + + /* Stub shared call. */ + &xcoff_stub_shared_call_code[0], + 24, /* _xcoff_stub_shared_call_size */ }; /* The transfer vector that leads the outside world to all of the above. */ |