From 8fb73a8834169d39ed90c5dcf25a1cdf62e95e09 Mon Sep 17 00:00:00 2001 From: Dave Korn Date: Sun, 20 Feb 2011 00:38:54 +0000 Subject: [PATCH] Perform second link stage and ignore now-obsolete linker -pass-through= option. ld/ChangeLog: 2011-02-20 Dave Korn <... PR ld/12365 * ldcref.c (cref_hash_table_free): New function. * ld.h (cref_hash_table_free): Add prototype. * ldlang.c (lang_gc_sections): Dont de-exclude claimed file sections. (set_exclude): New function. (reopen_inputs): Likewise. Walk list of input objects, excluding claimed (IR-only) files and archive members, then re-walk list, closing and re-opening and re-adding the symbols from objects and libs. (lang_process): After opening plugin-supplied objects and scanning their library dependencies, tear down existing link, cref and already-linked-section hashes, erase link_info input bfds list, finally call reopen_inputs. * plugin.c (plugin_opt_plugin_arg): Discard any instances of the now-obsolete "-pass-through=" option if found. --- ld/ld.h | 1 + ld/ldcref.c | 18 +++++++++++ ld/ldlang.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ld/plugin.c | 3 ++ 4 files changed, 115 insertions(+), 0 deletions(-) diff --git a/ld/ld.h b/ld/ld.h index 564cb73..dfa3f2e 100644 --- a/ld/ld.h +++ b/ld/ld.h @@ -327,6 +327,7 @@ extern int parsing_defsym; extern int yyparse (void); extern void add_cref (const char *, bfd *, asection *, bfd_vma); +extern void cref_hash_table_free (void); extern bfd_boolean handle_asneeded_cref (bfd *, enum notice_asneeded_action); extern void output_cref (FILE *); extern void check_nocrossrefs (void); diff --git a/ld/ldcref.c b/ld/ldcref.c index 2f6a46c..889b38a 100644 --- a/ld/ldcref.c +++ b/ld/ldcref.c @@ -198,6 +198,24 @@ add_cref (const char *name, r->def = TRUE; } +/* Free the cref hash table. */ + +void +cref_hash_table_free (void) +{ + if (cref_initialized) + { + bfd_hash_table_free (&cref_table.root); + cref_initialized = FALSE; + cref_symcount = 0; + old_table = NULL; + old_size = 0; + old_count = 0; + old_symcount = 0; + alloc_mark = NULL; + } +} + /* Called before loading an as-needed library to take a snapshot of the cref hash table, and after we have loaded or found that the library was not needed. */ diff --git a/ld/ldlang.c b/ld/ldlang.c index 7a1753d..7330dc0 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -6269,6 +6269,10 @@ lang_gc_sections (void) LANG_FOR_EACH_INPUT_STATEMENT (f) { asection *sec; +#ifdef ENABLE_PLUGINS + if (f->claimed) + continue; +#endif /* ENABLE_PLUGINS */ for (sec = f->the_bfd->sections; sec != NULL; sec = sec->next) if ((sec->flags & SEC_DEBUGGING) == 0) sec->flags &= ~SEC_EXCLUDE; @@ -6442,6 +6446,69 @@ find_replacements_insert_point (void) insert point. */ return lastobject; } + +/* Mapped over sections of claimed IR BFDs to exclude them from the + final link. */ + +static void +set_exclude (bfd *abfd, asection *sect, void *obj ATTRIBUTE_UNUSED) +{ + bfd_set_section_flags (abfd, + sect, + SEC_EXCLUDE | bfd_get_section_flags (abfd, sect)); + sect->output_section = NULL; +} + +/* This runs two passes over the inputs. First we exclude any IR + BFDs and archive members from the link; then we re-run it by + re-opening all the object files and archives and re-adding + their symbols to the fresh linker hash table. */ + +static void +reopen_inputs (void) +{ + lang_input_statement_type *stmt; + + /* Exclude dummy IR files and archive members. */ + for (stmt = &file_chain.head->input_statement; + stmt != NULL; + stmt = &stmt->next->input_statement) + { + if (stmt->claimed || (stmt->the_bfd && bfd_my_archive (stmt->the_bfd))) + { + bfd_map_over_sections (stmt->the_bfd, set_exclude, 0); + stmt->claimed = TRUE; + } + } + + /* Re-open real objects and libs, recalculating link as we go. */ + for (stmt = &input_file_chain.head->input_statement; + stmt != NULL; + stmt = &stmt->next_real_file->input_statement) + { + if (!stmt->claimed && stmt->the_bfd && !bfd_my_archive (stmt->the_bfd)) + { + bfd *oldbfd = stmt->the_bfd; + stmt->the_bfd = NULL; + ldfile_open_file (stmt); + bfd_check_format (stmt->the_bfd, bfd_get_format (oldbfd)); + if (bfd_get_format (stmt->the_bfd) != bfd_archive) + { + *link_info.input_bfds_tail = stmt->the_bfd; + stmt->the_bfd->link_next = NULL; + link_info.input_bfds_tail = &stmt->the_bfd->link_next; + } + stmt->the_bfd->usrdata = stmt; + bfd_set_gp_size (stmt->the_bfd, g_switch_value); + bfd_map_over_sections (stmt->the_bfd, section_already_linked, stmt); + bfd_link_add_symbols (stmt->the_bfd, &link_info); + /* We need to hold archive BFDs open while we still have statements + indicating them; plain object files we are finished with now. */ + if (bfd_get_format (oldbfd) == bfd_object) + bfd_close (oldbfd); + } + } +} #endif /* ENABLE_PLUGINS */ void @@ -6518,6 +6585,32 @@ lang_process (void) else lang_list_insert_after (&file_chain, &files, &file_chain.head); } + + /* Free the old already linked table and create a new one. */ + bfd_section_already_linked_table_free (); + if (!bfd_section_already_linked_table_init ()) + einfo (_("%P%F: Failed to create hash table\n")); + + /* Free the old hash table and create a new one. */ + bfd_link_hash_table_free (link_info.output_bfd, + link_info.hash); + link_info.hash + = bfd_link_hash_table_create (link_info.output_bfd); + if (link_info.hash == NULL) + einfo (_("%P%F: can not create hash table: %E\n")); + + /* Re-add to the hash table all undefineds on the command line. */ + lang_place_undefineds (); + + /* Free the old cref hash table. */ + cref_hash_table_free (); + + /* And relink the input bfds list. */ + link_info.input_bfds = NULL; + link_info.input_bfds_tail = &link_info.input_bfds; + + /* Now run round the input objects re-adding symbols. */ + reopen_inputs (); } #endif /* ENABLE_PLUGINS */ diff --git a/ld/plugin.c b/ld/plugin.c index c1672f6..db3ad07 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -207,6 +207,9 @@ plugin_opt_plugin_arg (const char *arg) if (!last_plugin) return set_plugin_error (_("")); + if (CONST_STRNEQ (arg, "-pass-through=")) + return 0; + newarg = xmalloc (sizeof *newarg); newarg->arg = arg; newarg->next = NULL;