summaryrefslogtreecommitdiff
path: root/bfd/coff-rs6000.c
diff options
context:
space:
mode:
authorCl?ment Chigot <clement.chigot@atos.net>2022-04-20 15:11:47 +0100
committerNick Clifton <nickc@redhat.com>2022-04-20 15:11:47 +0100
commit2d23f9656c3fd92335683188d26db198fe2ed3ec (patch)
treed3c564dca842f9bbd216e2e05c3f03ac86eadf95 /bfd/coff-rs6000.c
parent1876a542175ef438d6aaafeccb479024994b938d (diff)
downloadbinutils-gdb-2d23f9656c3fd92335683188d26db198fe2ed3ec.tar.gz
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.c99
1 files changed, 88 insertions, 11 deletions
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index 8656dfdb4c4..8819187ab42 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. */