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 /ld/emultempl | |
parent | 1876a542175ef438d6aaafeccb479024994b938d (diff) | |
download | gdb-2d23f9656c3fd92335683188d26db198fe2ed3ec.zip gdb-2d23f9656c3fd92335683188d26db198fe2ed3ec.tar.gz 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 'ld/emultempl')
-rw-r--r-- | ld/emultempl/aix.em | 190 |
1 files changed, 186 insertions, 4 deletions
diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em index 3878d58..355e2a4 100644 --- a/ld/emultempl/aix.em +++ b/ld/emultempl/aix.em @@ -63,6 +63,15 @@ static void gld${EMULATION_NAME}_free (void *); static void gld${EMULATION_NAME}_find_relocs (lang_statement_union_type *); static void gld${EMULATION_NAME}_find_exp_assignment (etree_type *); +static asection *xcoff_add_stub_section (const char *, asection *); +static void xcoff_layout_sections_again (void); + +static struct bfd_xcoff_link_params params = { + NULL, + &xcoff_add_stub_section, + &xcoff_layout_sections_again +}; + /* The file alignment required for each section. */ static unsigned long file_align; @@ -138,6 +147,9 @@ static int rtld; /* Explicit command line library path, -blibpath */ static char *command_line_blibpath = NULL; +/* Fake input file for stubs. */ +static lang_input_statement_type *stub_file; + /* This routine is called before anything else is done. */ static void @@ -154,6 +166,7 @@ gld${EMULATION_NAME}_before_parse (void) link_info.init_function = NULL; link_info.fini_function = NULL; + } /* Handle AIX specific options. */ @@ -1009,12 +1022,157 @@ gld${EMULATION_NAME}_before_allocation (void) before_allocation_default (); } +struct hook_stub_info +{ + lang_statement_list_type add; + asection *input_section; +}; + +/* Traverse the linker tree to find the spot where the stub goes. */ + +static bool +hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp) +{ + lang_statement_union_type *l; + bool ret; + + for (; (l = *lp) != NULL; lp = &l->header.next) + { + switch (l->header.type) + { + case lang_constructors_statement_enum: + ret = hook_in_stub (info, &constructor_list.head); + if (ret) + return ret; + break; + + case lang_output_section_statement_enum: + ret = hook_in_stub (info, + &l->output_section_statement.children.head); + if (ret) + return ret; + break; + + case lang_wild_statement_enum: + ret = hook_in_stub (info, &l->wild_statement.children.head); + if (ret) + return ret; + break; + + case lang_group_statement_enum: + ret = hook_in_stub (info, &l->group_statement.children.head); + if (ret) + return ret; + break; + + case lang_input_section_enum: + if (l->input_section.section == info->input_section) + { + /* We've found our section. Insert the stub immediately + after its associated input section. */ + *(info->add.tail) = l->header.next; + l->header.next = info->add.head; + return true; + } + break; + + case lang_data_statement_enum: + case lang_reloc_statement_enum: + case lang_object_symbols_statement_enum: + case lang_output_statement_enum: + case lang_target_statement_enum: + case lang_input_statement_enum: + case lang_assignment_statement_enum: + case lang_padding_statement_enum: + case lang_address_statement_enum: + case lang_fill_statement_enum: + break; + + default: + FAIL (); + break; + } + } + return false; +} + +/* Call-back for bfd_xcoff_link_relocations. + Create a new stub section, and arrange for it to be linked + immediately before INPUT_SECTION. */ + +static asection * +xcoff_add_stub_section (const char *stub_sec_name, asection *input_section) +{ + asection *stub_sec; + flagword flags; + asection *output_section; + lang_output_section_statement_type *os; + struct hook_stub_info info; + + flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE + | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP); + stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd, + stub_sec_name, flags); + if (stub_sec == NULL) + goto err_ret; + + output_section = input_section->output_section; + os = lang_output_section_get (output_section); + + info.input_section = input_section; + lang_list_init (&info.add); + lang_add_section (&info.add, stub_sec, NULL, NULL, os); + + if (info.add.head == NULL) + goto err_ret; + + if (hook_in_stub (&info, &os->children.head)) + return stub_sec; + + err_ret: + einfo (_("%X%P: can not make stub section: %E\n")); + return NULL; +} + +/* Another call-back for bfd_xcoff_link_relocations. */ + +static void +xcoff_layout_sections_again (void) +{ + /* If we have changed sizes of the stub sections, then we need + to recalculate all the section offsets. This may mean we need to + add even more stubs. */ + lang_relax_sections (true); +} + +/* Call the back-end to verify relocations. */ + static void gld${EMULATION_NAME}_after_allocation (void) { + + /* If generating a relocatable output file, then we don't have any + stubs. */ + if (stub_file != NULL && !bfd_link_relocatable (&link_info)) + { + /* Call into the BFD backend to do the real work. */ + if (!bfd_xcoff_size_stubs (&link_info)) + einfo (_("%X%P: can not size stub sections: %E\n")); + } + /* Now that everything is in place, finalize the dynamic sections. */ if (!bfd_xcoff_build_dynamic_sections (link_info.output_bfd, &link_info)) einfo (_("%F%P: failed to layout dynamic sections: %E\n")); + + if (!bfd_link_relocatable (&link_info)) + { + /* Now build the linker stubs. */ + if (stub_file != NULL && stub_file->the_bfd->sections != NULL) + { + if (! bfd_xcoff_build_stubs (&link_info)) + einfo (_("%X%P: can not build stubs: %E\n")); + } + } } static char * @@ -1503,11 +1661,35 @@ fragment <<EOF static void gld${EMULATION_NAME}_create_output_section_statements (void) { + if ((bfd_get_flavour (link_info.output_bfd) != bfd_target_xcoff_flavour)) + return; + + /* Stub file */ + stub_file = lang_add_input_file ("linker stubs", + lang_input_file_is_fake_enum, + NULL); + stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd); + if (stub_file->the_bfd == NULL + || !bfd_set_arch_mach (stub_file->the_bfd, + bfd_get_arch (link_info.output_bfd), + bfd_get_mach (link_info.output_bfd))) + { + einfo (_("%F%P: can not create stub BFD: %E\n")); + return; + } + + stub_file->the_bfd->flags |= BFD_LINKER_CREATED; + ldlang_add_file (stub_file); + params.stub_bfd = stub_file->the_bfd; + + /* Pass linker params to the back-end. */ + if (!bfd_xcoff_link_init (&link_info, ¶ms)) + einfo (_("%F%P: can not init BFD: %E\n")); + /* __rtinit */ - if ((bfd_get_flavour (link_info.output_bfd) == bfd_target_xcoff_flavour) - && (link_info.init_function != NULL - || link_info.fini_function != NULL - || rtld)) + if (link_info.init_function != NULL + || link_info.fini_function != NULL + || rtld) { initfini_file = lang_add_input_file ("initfini", lang_input_file_is_file_enum, |