From 4cbe42ea236bce32da4262f6f12328b58bac8f0f Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Fri, 22 Apr 2016 05:25:25 -0700 Subject: [PATCH] Add a fake bfd to hold linker created dynamic sections Currently, we hold linker created dynamic sections in an input shared object, which has its own dynamic sections, when the first input file from linker is a shared object. It may lead to conflicts between linker created dynamic sections and shared object's dynamic sections. We can use a a fake bfd to hold linker created dynamic sections. Unfortunately, it doesn't work due to BFD_LINKER_CREATED. Dynamic sections in bfd with BFD_LINKER_CREATED may be ignored. --- bfd/elflink.c | 33 ++++++--------------------------- ld/emultempl/aarch64elf.em | 2 ++ ld/emultempl/armelf.em | 2 ++ ld/emultempl/avrelf.em | 1 + ld/emultempl/elf32.em | 45 ++++++++++++++++++++++++++++++++++++++++++++- ld/emultempl/hppaelf.em | 2 ++ ld/emultempl/m68hc1xelf.em | 2 ++ ld/emultempl/m68kelf.em | 2 ++ ld/emultempl/metagelf.em | 2 ++ ld/emultempl/mipself.em | 2 ++ ld/emultempl/nds32elf.em | 2 ++ ld/emultempl/nios2elf.em | 2 ++ ld/emultempl/ppc32elf.em | 2 ++ ld/emultempl/ppc64elf.em | 2 ++ ld/emultempl/rxelf.em | 2 ++ 15 files changed, 75 insertions(+), 28 deletions(-) diff --git a/bfd/elflink.c b/bfd/elflink.c index 6f67266..5656ca0 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -198,31 +198,11 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) /* Create a strtab to hold the dynamic symbol names. */ static bfd_boolean -_bfd_elf_link_create_dynstrtab (bfd *abfd, struct bfd_link_info *info) +_bfd_elf_link_create_dynstrtab (struct bfd_link_info *info) { struct elf_link_hash_table *hash_table; hash_table = elf_hash_table (info); - if (hash_table->dynobj == NULL) - { - /* We may not set dynobj, an input file holding linker created - dynamic sections to abfd, which may be a dynamic object with - its own dynamic sections. We need to find a normal input file - to hold linker created sections if possible. */ - if ((abfd->flags & (DYNAMIC | BFD_PLUGIN)) != 0) - { - bfd *ibfd; - for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next) - if ((ibfd->flags - & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0) - { - abfd = ibfd; - break; - } - } - hash_table->dynobj = abfd; - } - if (hash_table->dynstr == NULL) { hash_table->dynstr = _bfd_elf_strtab_init (); @@ -253,7 +233,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (elf_hash_table (info)->dynamic_sections_created) return TRUE; - if (!_bfd_elf_link_create_dynstrtab (abfd, info)) + if (!_bfd_elf_link_create_dynstrtab (info)) return FALSE; abfd = elf_hash_table (info)->dynobj; @@ -3206,15 +3186,14 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info, 1 if a DT_NEEDED tag already exists, and 0 on success. */ static int -elf_add_dt_needed_tag (bfd *abfd, - struct bfd_link_info *info, +elf_add_dt_needed_tag (struct bfd_link_info *info, const char *soname, bfd_boolean do_it) { struct elf_link_hash_table *hash_table; bfd_size_type strindex; - if (!_bfd_elf_link_create_dynstrtab (abfd, info)) + if (!_bfd_elf_link_create_dynstrtab (info)) return -1; hash_table = elf_hash_table (info); @@ -3908,7 +3887,7 @@ error_free_dyn: will need to know it. */ elf_dt_name (abfd) = soname; - ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed); + ret = elf_add_dt_needed_tag (info, soname, add_needed); if (ret < 0) goto error_return; @@ -4717,7 +4696,7 @@ error_free_dyn: (elf_dyn_lib_class (abfd) & ~DYN_AS_NEEDED); add_needed = TRUE; - ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed); + ret = elf_add_dt_needed_tag (info, soname, add_needed); if (ret < 0) goto error_free_vers; diff --git a/ld/emultempl/aarch64elf.em b/ld/emultempl/aarch64elf.em index 9923be3..c961b9e 100644 --- a/ld/emultempl/aarch64elf.em +++ b/ld/emultempl/aarch64elf.em @@ -322,6 +322,8 @@ aarch64_elf_create_output_section_statements (void) stub_file->the_bfd->flags |= BFD_LINKER_CREATED; ldlang_add_file (stub_file); + + gld${EMULATION_NAME}_create_output_section_statements (); } /* Avoid processing the fake stub_file in vercheck, stat_needed and diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em index 2e43172..b7b9463 100644 --- a/ld/emultempl/armelf.em +++ b/ld/emultempl/armelf.em @@ -514,6 +514,8 @@ arm_elf_create_output_section_statements (void) /* Also use the stub file for stubs placed in a single output section. */ bfd_elf32_arm_add_glue_sections_to_bfd (stub_file->the_bfd, &link_info); bfd_elf32_arm_get_bfd_for_interworking (stub_file->the_bfd, &link_info); + + gld${EMULATION_NAME}_create_output_section_statements (); } /* Avoid processing the fake stub_file in vercheck, stat_needed and diff --git a/ld/emultempl/avrelf.em b/ld/emultempl/avrelf.em index 4710b6e..80526ac 100644 --- a/ld/emultempl/avrelf.em +++ b/ld/emultempl/avrelf.em @@ -136,6 +136,7 @@ avr_elf_create_output_section_statements (void) ldlang_add_file (stub_file); + gld${EMULATION_NAME}_create_output_section_statements (); return; err_ret: diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 4f5d1a4..e90af48 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -64,6 +64,7 @@ static void gld${EMULATION_NAME}_after_parse (void); static void gld${EMULATION_NAME}_after_open (void); static void gld${EMULATION_NAME}_before_allocation (void); static void gld${EMULATION_NAME}_after_allocation (void); +static void gld${EMULATION_NAME}_create_output_section_statements (void); static lang_output_section_statement_type *gld${EMULATION_NAME}_place_orphan (asection *, const char *, int); EOF @@ -263,6 +264,8 @@ gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s) return; if (s->the_bfd == NULL) return; + if ((s->the_bfd->flags & BFD_LINKER_CREATED) != 0) + return; /* If this input file was an as-needed entry, and wasn't found to be needed at the stage it was linked, then don't say we have loaded it. */ @@ -1400,6 +1403,46 @@ gld${EMULATION_NAME}_find_statement_assignment (lang_statement_union_type *s) EOF +if test x"$LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS" != xgld"$EMULATION_NAME"create_output_section_statements; then +fragment <the_bfd = bfd_create (" dynobj ", link_info.output_bfd); + if (dynobj->the_bfd == NULL + || !bfd_set_arch_mach (dynobj->the_bfd, + bfd_get_arch (link_info.output_bfd), + bfd_get_mach (link_info.output_bfd))) + { + einfo ("%F%P: can not create BFD to hold dynamic sections: %E\n"); + return; + } + + dynobj->the_bfd->flags |= BFD_LINKER_CREATED; + elf_elfheader (dynobj->the_bfd)->e_ident[EI_CLASS] + = (get_elf_backend_data (link_info.output_bfd)->s->arch_size == 64 + ? ELFCLASS64 : ELFCLASS32); + elf_hash_table (&link_info)->dynobj = dynobj->the_bfd; + + ldlang_add_file (dynobj); +} + +EOF +fi + if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then if test x"${ELF_INTERPRETER_NAME+set}" = xset; then ELF_INTERPRETER_SET_DEFAULT=" @@ -2515,7 +2558,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = "${EMULATION_NAME}", "${OUTPUT_FORMAT}", ${LDEMUL_FINISH-finish_default}, - ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL}, + ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-gld${EMULATION_NAME}_create_output_section_statements}, ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive}, ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan}, ${LDEMUL_SET_SYMBOLS-NULL}, diff --git a/ld/emultempl/hppaelf.em b/ld/emultempl/hppaelf.em index a1d2e80..5965e9b 100644 --- a/ld/emultempl/hppaelf.em +++ b/ld/emultempl/hppaelf.em @@ -88,6 +88,8 @@ hppaelf_create_output_section_statements (void) stub_file->the_bfd->flags |= BFD_LINKER_CREATED; ldlang_add_file (stub_file); + + gld${EMULATION_NAME}_create_output_section_statements (); } diff --git a/ld/emultempl/m68hc1xelf.em b/ld/emultempl/m68hc1xelf.em index 739479d..b2e8fa1 100644 --- a/ld/emultempl/m68hc1xelf.em +++ b/ld/emultempl/m68hc1xelf.em @@ -155,6 +155,8 @@ m68hc11elf_create_output_section_statements (void) } ldlang_add_file (stub_file); + + gld${EMULATION_NAME}_create_output_section_statements (); } diff --git a/ld/emultempl/m68kelf.em b/ld/emultempl/m68kelf.em index c1a514c..17150ac 100644 --- a/ld/emultempl/m68kelf.em +++ b/ld/emultempl/m68kelf.em @@ -208,6 +208,8 @@ static void elf_m68k_create_output_section_statements (void) { bfd_elf_m68k_set_target_options (&link_info, got_handling); + + gld${EMULATION_NAME}_create_output_section_statements (); } EOF diff --git a/ld/emultempl/metagelf.em b/ld/emultempl/metagelf.em index 5626eca..95900d7 100644 --- a/ld/emultempl/metagelf.em +++ b/ld/emultempl/metagelf.em @@ -65,6 +65,8 @@ metagelf_create_output_section_statements (void) stub_file->the_bfd->flags |= BFD_LINKER_CREATED; ldlang_add_file (stub_file); + + gld${EMULATION_NAME}_create_output_section_statements (); } diff --git a/ld/emultempl/mipself.em b/ld/emultempl/mipself.em index dbff36b..d64ca0d 100644 --- a/ld/emultempl/mipself.em +++ b/ld/emultempl/mipself.em @@ -206,6 +206,8 @@ mips_create_output_section_statements (void) if (is_mips_elf (link_info.output_bfd)) _bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section); + + gld${EMULATION_NAME}_create_output_section_statements (); } /* This is called after we have merged the private data of the input bfds. */ diff --git a/ld/emultempl/nds32elf.em b/ld/emultempl/nds32elf.em index 08da695..eee5087 100644 --- a/ld/emultempl/nds32elf.em +++ b/ld/emultempl/nds32elf.em @@ -65,6 +65,8 @@ nds32_elf_create_output_section_statements (void) ex9_export_file, ex9_import_file, update_ex9_table, ex9_limit, ex9_loop_aware, ifc_loop_aware); + + gld${EMULATION_NAME}_create_output_section_statements (); } static void diff --git a/ld/emultempl/nios2elf.em b/ld/emultempl/nios2elf.em index da4bea0..3b1275c 100644 --- a/ld/emultempl/nios2elf.em +++ b/ld/emultempl/nios2elf.em @@ -70,6 +70,8 @@ nios2elf_create_output_section_statements (void) stub_file->the_bfd->flags |= BFD_LINKER_CREATED; ldlang_add_file (stub_file); + + gld${EMULATION_NAME}_create_output_section_statements (); } diff --git a/ld/emultempl/ppc32elf.em b/ld/emultempl/ppc32elf.em index a0255cd..37dcc95 100644 --- a/ld/emultempl/ppc32elf.em +++ b/ld/emultempl/ppc32elf.em @@ -53,6 +53,8 @@ ppc_after_open_output (void) pagesize = config.commonpagesize; params.pagesize_p2 = bfd_log2 (pagesize); ppc_elf_link_params (&link_info, ¶ms); + + gld${EMULATION_NAME}_create_output_section_statements (); } EOF diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index d7c0686..1f48ab1 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -98,6 +98,8 @@ ppc_create_output_section_statements (void) params.save_restore_funcs = !bfd_link_relocatable (&link_info); if (!ppc64_elf_init_stub_bfd (&link_info, ¶ms)) einfo ("%F%P: can not init BFD: %E\n"); + + gld${EMULATION_NAME}_create_output_section_statements (); } /* Called after opening files but before mapping sections. */ diff --git a/ld/emultempl/rxelf.em b/ld/emultempl/rxelf.em index 36be1ba..d1fc9fa 100644 --- a/ld/emultempl/rxelf.em +++ b/ld/emultempl/rxelf.em @@ -38,6 +38,8 @@ rx_elf_create_output_section_statements (void) extern void bfd_elf32_rx_set_target_flags (bfd_boolean, bfd_boolean); bfd_elf32_rx_set_target_flags (no_flag_mismatch_warnings, ignore_lma); + + gld${EMULATION_NAME}_create_output_section_statements (); } EOF -- 2.5.5