forked from Imagelibrary/binutils-gdb
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.
This commit is contained in:
committed by
Nick Clifton
parent
1876a54217
commit
2d23f9656c
@@ -778,10 +778,13 @@ xcoff64_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;
|
||||
@@ -833,6 +836,27 @@ xcoff64_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;
|
||||
@@ -1645,7 +1669,7 @@ xcoff64_ppc_relocate_section (bfd *output_bfd,
|
||||
if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION
|
||||
|| !((*xcoff64_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 */
|
||||
@@ -2386,12 +2410,32 @@ HOWTO (0, /* type */
|
||||
MINUS_ONE, /* dst_mask */
|
||||
false); /* pcrel_offset */
|
||||
|
||||
/* Indirect call stub */
|
||||
static const unsigned long xcoff64_stub_indirect_call_code[4] =
|
||||
{
|
||||
0xe9820000, /* ld r12,0(r2) */
|
||||
0xe80c0000, /* ld r0,0(r12) */
|
||||
0x7c0903a6, /* mtctr r0 */
|
||||
0x4e800420, /* bctr */
|
||||
};
|
||||
|
||||
/* Shared call stub */
|
||||
static const unsigned long xcoff64_stub_shared_call_code[6] =
|
||||
{
|
||||
0xe9820000, /* ld r12,0(r2) */
|
||||
0xf8410028, /* std r2,40(r1) */
|
||||
0xe80c0000, /* ld r0,0(r12) */
|
||||
0xe84c0008, /* ld r2,8(r12) */
|
||||
0x7c0903a6, /* mtctr r0 */
|
||||
0x4e800420, /* bctr */
|
||||
};
|
||||
|
||||
static const unsigned long xcoff64_glink_code[10] =
|
||||
{
|
||||
0xe9820000, /* ld r12,0(r2) */
|
||||
0xf8410028, /* std r2,40(r1) */
|
||||
0xe80c0000, /* ld r0,0(r12) */
|
||||
0xe84c0008, /* ld r0,8(r12) */
|
||||
0xe84c0008, /* ld r2,8(r12) */
|
||||
0x7c0903a6, /* mtctr r0 */
|
||||
0x4e800420, /* bctr */
|
||||
0x00000000, /* start of traceback table */
|
||||
@@ -2495,6 +2539,14 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
|
||||
/* rtinit. */
|
||||
88, /* _xcoff_rtinit_size */
|
||||
xcoff64_generate_rtinit,
|
||||
|
||||
/* Stub indirect call. */
|
||||
&xcoff64_stub_indirect_call_code[0],
|
||||
16, /* _xcoff_stub_indirect_call_size */
|
||||
|
||||
/* Stub shared call. */
|
||||
&xcoff64_stub_shared_call_code[0],
|
||||
24, /* _xcoff_stub_shared_call_size */
|
||||
};
|
||||
|
||||
/* The transfer vector that leads the outside world to all of the above. */
|
||||
@@ -2759,6 +2811,14 @@ static const struct xcoff_backend_data_rec bfd_xcoff_aix5_backend_data =
|
||||
/* rtinit. */
|
||||
88, /* _xcoff_rtinit_size */
|
||||
xcoff64_generate_rtinit,
|
||||
|
||||
/* Stub indirect call. */
|
||||
&xcoff64_stub_indirect_call_code[0],
|
||||
16, /* _xcoff_stub_indirect_call_size */
|
||||
|
||||
/* Stub shared call. */
|
||||
&xcoff64_stub_shared_call_code[0],
|
||||
24, /* _xcoff_stub_shared_call_size */
|
||||
};
|
||||
|
||||
/* The transfer vector that leads the outside world to all of the above. */
|
||||
|
||||
Reference in New Issue
Block a user