bfd/ 2010-12-03 H.J. Lu PR ld/12248 * bfd.c (BFD_PLUGIN): New. (BFD_FLAGS_SAVED): Add BFD_PLUGIN. (BFD_FLAGS_FOR_BFD_USE_MASK): Likewise. * bfd-in2.h: Regenerated. ld/ 2010-12-03 H.J. Lu PR ld/12248 * ldfile.c (ldfile_try_open_bfd): Turn on BFD_PLUGIN and set claimed to false on non-object files and unclaimed object files. Set stage1. * ldlang.c (cmdline_list): New. (cmdline_next_claimed_output): Likewise. (cmdline_list_init): Likewise. (cmdline_get_stage2_input_files): Likewise. (debug_cmdline_list): Likewise. (cmdline_list_append): Likewise. (cmdline_set_next_claimed_output): Likewise. (cmdline_list_insert_claimed_output): Likewise. (new_afile): Set stage1 to FALSE; (lang_init): Call cmdline_list_init. (lang_process): Call plugin_active_plugins_p to check plugin support. Check cmdline_next_claimed_output before opening stage 2 input. Call debug_cmdline_list if trace_file_tries is set. Call cmdline_get_stage2_input_files to get stage 2 input files. * ldlang.h (lang_input_statement_struct): Add stage1. (cmdline_enum_type): New. (cmdline_header_type): Likewise. (cmdline_input_statement_type): Likewise. (cmdline_claimed_output_type): Likewise. (cmdline_union_type): Likewise. (cmdline_list_type): Likewise. (cmdline_list_append): Likewise. (cmdline_list_insert_claimed_output): Likewise. (cmdline_set_next_claimed_output): Likewise. * ldmain.c (add_archive_element): Call cmdline_set_next_claimed_output with archive BFD. Set BFD_PLUGIN if input isn't claimed by plugin. * lexsup.c (parse_args): Call cmdline_list_append if needed. * plugin.c (plugin_opt_plugin_arg): Ignore -pass-through=. (add_input_file): Replace lang_add_input_file with cmdline_list_insert_claimed_output. (add_input_library): Likewise. ld/testsuite/ 2010-12-03 H.J. Lu PR ld/12248 * ld-plugin/func1i.c: New. * ld-plugin/func2.c: Likewise. * ld-plugin/func2h.c: Likewise. * ld-plugin/func3p.c: Likewise. * ld-plugin/plugin.exp: Add object files for symbols claimed or created by testplugin. * ld-plugin/plugin-7.d: Updated. * ld-plugin/plugin-8.d: Likewise. * ld-plugin/plugin-9.d: Likewise. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index e7805b6..10dbe83 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -5085,14 +5085,17 @@ struct bfd /* Decompress sections in this BFD. */ #define BFD_DECOMPRESS 0x10000 + /* This BFD has been processed by the linker plugin. */ +#define BFD_PLUGIN 0x20000 + /* Flags bits to be saved in bfd_preserve_save. */ #define BFD_FLAGS_SAVED \ - (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS) + (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN) /* Flags bits which are for BFD use only. */ #define BFD_FLAGS_FOR_BFD_USE_MASK \ (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \ - | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT) + | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT | BFD_PLUGIN) /* Currently my_archive is tested before adding origin to anything. I believe that this can become always an add of diff --git a/bfd/bfd.c b/bfd/bfd.c index a9ce7cc..7265156 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -157,14 +157,17 @@ CODE_FRAGMENT . {* Decompress sections in this BFD. *} .#define BFD_DECOMPRESS 0x10000 . +. {* This BFD has been processed by the linker plugin. *} +.#define BFD_PLUGIN 0x20000 +. . {* Flags bits to be saved in bfd_preserve_save. *} .#define BFD_FLAGS_SAVED \ -. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS) +. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN) . . {* Flags bits which are for BFD use only. *} .#define BFD_FLAGS_FOR_BFD_USE_MASK \ . (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \ -. | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT) +. | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT | BFD_PLUGIN) . . {* Currently my_archive is tested before adding origin to . anything. I believe that this can become always an add of diff --git a/ld/ldfile.c b/ld/ldfile.c index 3d9feb5..a708dc2 100644 --- a/ld/ldfile.c +++ b/ld/ldfile.c @@ -312,46 +312,63 @@ success: bfd_object that it sets the bfd's arch and mach, which will be needed when and if we want to bfd_create a new one using this one as a template. */ - if (bfd_check_format (entry->the_bfd, bfd_object) - && plugin_active_plugins_p ()) + if (plugin_active_plugins_p ()) { - int fd = open (attempt, O_RDONLY | O_BINARY); - if (fd >= 0) + if (bfd_check_format (entry->the_bfd, bfd_object)) { - struct ld_plugin_input_file file; - int claimed = 0; - - file.name = attempt; - file.offset = 0; - file.filesize = lseek (fd, 0, SEEK_END); - file.fd = fd; - /* We create a dummy BFD, initially empty, to house - whatever symbols the plugin may want to add. */ - file.handle = plugin_get_ir_dummy_bfd (attempt, entry->the_bfd); - if (plugin_call_claim_file (&file, &claimed)) - einfo (_("%P%F: %s: plugin reported error claiming file\n"), - plugin_error_plugin ()); - /* fd belongs to us, not the plugin; but we don't need it. */ - close (fd); - if (claimed) + int fd = open (attempt, O_RDONLY | O_BINARY); + if (fd >= 0) { - /* Discard the real file's BFD and substitute the dummy one. */ - bfd_close (entry->the_bfd); - entry->the_bfd = file.handle; - entry->claimed = TRUE; - bfd_make_readable (entry->the_bfd); - } - else - { - /* If plugin didn't claim the file, we don't need the dummy - bfd. Can't avoid speculatively creating it, alas. */ - bfd_close_all_done (file.handle); - entry->claimed = FALSE; + struct ld_plugin_input_file file; + int claimed = 0; + + file.name = attempt; + file.offset = 0; + file.filesize = lseek (fd, 0, SEEK_END); + file.fd = fd; + /* We create a dummy BFD, initially empty, to house + whatever symbols the plugin may want to add. */ + file.handle = plugin_get_ir_dummy_bfd (attempt, + entry->the_bfd); + if (plugin_call_claim_file (&file, &claimed)) + einfo (_("%P%F: %s: plugin reported error claiming file\n"), + plugin_error_plugin ()); + /* fd belongs to us, not the plugin; but we don't need it. */ + close (fd); + if (claimed) + { + /* Discard the real file's BFD and substitute the + dummy one. */ + bfd_close (entry->the_bfd); + entry->the_bfd = file.handle; + entry->claimed = TRUE; + bfd_make_readable (entry->the_bfd); + cmdline_set_next_claimed_output (NULL); + } + else + { + /* If plugin didn't claim the file, we don't need the + dummy bfd. Can't avoid speculatively creating it, + alas. */ + bfd_close_all_done (file.handle); + /* Mark this input has been processed by plugin. */ + entry->the_bfd->flags |= BFD_PLUGIN; + entry->claimed = FALSE; + } } } + else + { + /* Mark this input has been processed by plugin. */ + entry->the_bfd->flags |= BFD_PLUGIN; + entry->claimed = FALSE; + } } #endif /* ENABLE_PLUGINS */ + /* Stage 1 is done. */ + entry->stage1 = TRUE; + /* It opened OK, the format checked out, and the plugins have had their chance to claim it, so this is success. */ return TRUE; diff --git a/ld/ldlang.c b/ld/ldlang.c index 2927ec8..1ff8e97 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -70,6 +70,8 @@ static lang_statement_list_type *stat_save[10]; static lang_statement_list_type **stat_save_ptr = &stat_save[0]; static struct unique_sections *unique_section_list; static bfd_boolean ldlang_sysrooted_script = FALSE; +static cmdline_list_type cmdline_list; +static cmdline_union_type **cmdline_next_claimed_output; /* Forward declarations. */ static void exp_init_os (etree_type *); @@ -90,6 +92,9 @@ static void lang_record_phdrs (void); static void lang_do_version_exports_section (void); static void lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *); +static void cmdline_list_init (void); +static void cmdline_get_stage2_input_files (void); +static void debug_cmdline_list (void); /* Exported variables. */ const char *output_target; @@ -1003,6 +1008,7 @@ new_afile (const char *name, lang_has_input_file = TRUE; p->target = target; p->sysrooted = FALSE; + p->stage1 = FALSE; if (file_type == lang_input_file_is_l_enum && name[0] == ':' && name[1] != '\0') @@ -1177,6 +1183,8 @@ lang_init (void) output_section_statement_table_init (); + cmdline_list_init (); + lang_list_init (stat_ptr); lang_list_init (&input_file_chain); @@ -6418,21 +6426,71 @@ lang_process (void) open_input_bfds (statement_list.head, FALSE); #ifdef ENABLE_PLUGINS + /* We call plugin_active_plugins_p () to check any plugin errors + from plugin_call_all_symbols_read (). */ + if (plugin_active_plugins_p ()) { + bfd *p; union lang_statement_union **listend; - /* Now all files are read, let the plugin(s) decide if there - are any more to be added to the link before we call the + /* Now all files are read, get outputs from input files claimed + by plugin(s) and prepare for stage 2 linking before we call the emulation's after_open hook. */ listend = statement_list.tail; ASSERT (!*listend); if (plugin_call_all_symbols_read ()) einfo (_("%P%F: %s: plugin reported error after all symbols read\n"), plugin_error_plugin ()); - /* If any new files were added, they will be on the end of the - statement list, and we can open them now by getting open_input_bfds - to carry on from where it ended last time. */ - if (*listend) - open_input_bfds (*listend, FALSE); + + if (cmdline_next_claimed_output) + { + if (trace_file_tries) + debug_cmdline_list (); + + /* Get stage 2 input files. */ + cmdline_get_stage2_input_files (); + + /* Must have stage 2 inputs. */ + ASSERT (*listend); + + /* Exclude all sections in input bfd files processed by the + plugin. */ + for (p = link_info.input_bfds; p != (bfd *) NULL; + p = p->link_next) + { + bfd_boolean exclude = (p->flags & BFD_PLUGIN) != 0; + if (!exclude) + { + bfd *abfd = bfd_my_archive (p); + if (abfd) + exclude = (abfd->flags & BFD_PLUGIN) != 0; + } + if (exclude) + { + asection *sec; + for (sec = p->sections; sec != NULL; sec = sec->next) + sec->flags |= SEC_EXCLUDE; + } + } + + /* 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")); + + /* When stage 2 input files are added, they will be on the + end of the statement list, and we can open them now by + getting open_input_bfds to carry on from where it ended + last time. */ + open_input_bfds (*listend, FALSE); + } } #endif /* ENABLE_PLUGINS */ @@ -7852,3 +7910,162 @@ lang_append_dynamic_list_cpp_new (void) lang_append_dynamic_list (dynamic); } + +static void +cmdline_list_init (void) +{ + cmdline_list.tail = &cmdline_list.head; +} + +/* Append a cmmand line option to cmdline_list. */ + +void +cmdline_list_append (cmdline_enum_type type, void *data) +{ + cmdline_union_type *new_opt; + + new_opt = (cmdline_union_type *) stat_alloc (sizeof (*new_opt)); + new_opt->header.type = type; + new_opt->header.next = NULL; + *cmdline_list.tail = new_opt; + cmdline_list.tail = &new_opt->header.next; + if (type == cmdline_is_lang_input_statement_enum) + new_opt->input_statement.input = (lang_input_statement_type *) data; +} + +/* Set cmdline_next_claimed_output. */ + +void +cmdline_set_next_claimed_output (bfd *archive) +{ + if (!cmdline_next_claimed_output) + { + cmdline_union_type *c; + cmdline_next_claimed_output = &cmdline_list.head; + for (c = cmdline_list.head; c != NULL; c = c->header.next) + if (c->header.type == cmdline_is_lang_input_statement_enum) + { + /* We must put object files generated by plugin before + the archive containing the IR object. */ + if (archive == c->input_statement.input->the_bfd) + { + cmdline_next_claimed_output = &c; + break; + } + else if (!c->input_statement.input->stage1) + { + cmdline_next_claimed_output = &c->header.next; + break; + } + } + } +} + +/* Insert claimed output after cmdline_next_claimed_output. */ + +void +cmdline_list_insert_claimed_output (const char *output) +{ + cmdline_union_type *new_opt, *next; + + new_opt = (cmdline_union_type *) stat_alloc (sizeof (*new_opt)); + new_opt->header.type = cmdline_is_claimed_output_enum; + new_opt->claimed_output.output = output; + + next = *cmdline_next_claimed_output; + *cmdline_next_claimed_output = new_opt; + new_opt->header.next = next; + if (cmdline_list.tail == cmdline_next_claimed_output) + { + cmdline_next_claimed_output = &new_opt->header.next; + cmdline_list.tail = cmdline_next_claimed_output; + } + else + cmdline_next_claimed_output = &new_opt->header.next; +} + +/* Get stage 2 input files. */ + +static void +cmdline_get_stage2_input_files (void) +{ + cmdline_union_type *c; + int ingroup = 0; + + for (c = cmdline_list.head; c != NULL; c = c->header.next) + switch (c->header.type) + { + default: + abort (); + case cmdline_is_lang_input_statement_enum: + if (!c->input_statement.input->claimed) + { + lang_input_statement_type *input; + input = lang_add_input_file (c->input_statement.input->filename, + lang_input_file_is_file_enum, + NULL); + input->add_DT_NEEDED_for_dynamic + = c->input_statement.input->add_DT_NEEDED_for_dynamic; + input->add_DT_NEEDED_for_regular + = c->input_statement.input->add_DT_NEEDED_for_regular; + input->whole_archive + = c->input_statement.input->whole_archive; + } + break; + case cmdline_is_claimed_output_enum: + lang_add_input_file (c->claimed_output.output, + lang_input_file_is_file_enum, NULL); + break; + case cmdline_is_enter_group_enum: + lang_enter_group (); + ingroup++; + break; + case cmdline_is_leave_group_enum: + lang_leave_group (); + ingroup--; + break; + } + + while (ingroup) + { + lang_leave_group (); + ingroup--; + } +} + +static void +debug_cmdline_list (void) +{ + cmdline_union_type *c; + + printf (_("Stage 2 command line:\n ")); + + for (c = cmdline_list.head; c != NULL; c = c->header.next) + switch (c->header.type) + { + default: + abort (); + case cmdline_is_lang_input_statement_enum: + if (!c->input_statement.input->claimed) + { + if (c->input_statement.input->the_bfd + && (bfd_get_format (c->input_statement.input->the_bfd) + == bfd_archive)) + printf (" %s", (c->input_statement.input->whole_archive + ? "--whole-archive" : "--no-whole-archive")); + printf (" %s", c->input_statement.input->filename); + } + break; + case cmdline_is_claimed_output_enum: + printf (" %s", c->claimed_output.output); + break; + case cmdline_is_enter_group_enum: + printf (" --start-group"); + break; + case cmdline_is_leave_group_enum: + printf (" --end-group"); + break; + } + + printf ("\n"); +} diff --git a/ld/ldlang.h b/ld/ldlang.h index 0b7b43b..8ba3e5a 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -279,6 +279,9 @@ typedef struct lang_input_statement_struct /* Whether to include the entire contents of an archive. */ unsigned int whole_archive : 1; + /* Set if the file has been processed in stage 1 . */ + unsigned int stage1 : 1; + /* Set when bfd opening is successful. */ unsigned int loaded : 1; @@ -650,4 +653,47 @@ extern bfd_boolean ldlang_override_segment_assignment (struct bfd_link_info *, bfd *, asection *, asection *, bfd_boolean); +typedef enum +{ + cmdline_is_lang_input_statement_enum, + cmdline_is_claimed_output_enum, + cmdline_is_enter_group_enum, + cmdline_is_leave_group_enum, +} cmdline_enum_type; + +typedef struct cmdlin_header_struct +{ + union cmdline_union *next; + cmdline_enum_type type; +} cmdline_header_type; + +typedef struct cmdline_input_statement_struct +{ + cmdline_header_type header; + lang_input_statement_type *input; +} cmdline_input_statement_type; + +typedef struct cmdline_claimed_output_struct +{ + cmdline_header_type header; + const char *output; +} cmdline_claimed_output_type; + +typedef union cmdline_union +{ + cmdline_header_type header; + cmdline_input_statement_type input_statement; + cmdline_claimed_output_type claimed_output; +} cmdline_union_type; + +typedef struct cmdline_list +{ + cmdline_union_type *head; + cmdline_union_type **tail; +} cmdline_list_type; + +extern void cmdline_list_append (cmdline_enum_type, void *); +extern void cmdline_list_insert_claimed_output (const char *); +extern void cmdline_set_next_claimed_output (bfd *); + #endif diff --git a/ld/ldmain.c b/ld/ldmain.c index c5b7d88..7810a01 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -798,6 +798,9 @@ add_archive_element (struct bfd_link_info *info, { lang_input_statement_type *input; lang_input_statement_type orig_input; +#ifdef ENABLE_PLUGINS + bfd *archive; +#endif input = (lang_input_statement_type *) xcalloc (1, sizeof (lang_input_statement_type)); @@ -810,10 +813,11 @@ add_archive_element (struct bfd_link_info *info, BFD, but we still want to output the original BFD filename. */ orig_input = *input; #ifdef ENABLE_PLUGINS - if (bfd_my_archive (abfd) != NULL && plugin_active_plugins_p ()) + archive = bfd_my_archive (abfd); + if (archive != NULL && plugin_active_plugins_p ()) { /* We must offer this archive member to the plugins to claim. */ - int fd = open (bfd_my_archive (abfd)->filename, O_RDONLY | O_BINARY); + int fd = open (archive->filename, O_RDONLY | O_BINARY); if (fd >= 0) { struct ld_plugin_input_file file; @@ -822,7 +826,7 @@ add_archive_element (struct bfd_link_info *info, member, not the whole file, and must exclude the header. Fortunately for us, that is how the data is stored in the origin field of the bfd and in the arelt_data. */ - file.name = bfd_my_archive (abfd)->filename; + file.name = archive->filename; file.offset = abfd->origin; file.filesize = arelt_size (abfd); file.fd = fd; @@ -836,6 +840,9 @@ add_archive_element (struct bfd_link_info *info, close (fd); if (claimed) { + /* Need to put object files generated by plugin before + the archive. */ + cmdline_set_next_claimed_output (archive); /* Substitute the dummy BFD. */ input->the_bfd = file.handle; input->claimed = TRUE; @@ -846,6 +853,8 @@ add_archive_element (struct bfd_link_info *info, { /* Abandon the dummy BFD. */ bfd_close_all_done (file.handle); + /* Mark this input has been processed by plugin. */ + input->the_bfd->flags |= BFD_PLUGIN; input->claimed = FALSE; } } diff --git a/ld/lexsup.c b/ld/lexsup.c index e4356bc..722bbf6 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -719,6 +719,7 @@ parse_args (unsigned argc, char **argv) { int longind; int optc; + lang_input_statement_type *input; /* Using last_optind lets us avoid calling ldemul_parse_args multiple times on a single option, which would lead to @@ -757,7 +758,10 @@ parse_args (unsigned argc, char **argv) einfo (_("%P%F: use the --help option for usage information\n")); case 1: /* File name. */ - lang_add_input_file (optarg, lang_input_file_is_file_enum, NULL); + input = lang_add_input_file (optarg, + lang_input_file_is_file_enum, NULL); + cmdline_list_append (cmdline_is_lang_input_statement_enum, + input); break; case OPTION_IGNORE: @@ -914,7 +918,10 @@ parse_args (unsigned argc, char **argv) ldfile_add_library_path (optarg, TRUE); break; case 'l': - lang_add_input_file (optarg, lang_input_file_is_l_enum, NULL); + input = lang_add_input_file (optarg, + lang_input_file_is_l_enum, NULL); + cmdline_list_append (cmdline_is_lang_input_statement_enum, + input); break; case 'M': config.map_filename = "-"; @@ -1099,9 +1106,11 @@ parse_args (unsigned argc, char **argv) if (stat (optarg, &s) >= 0 && ! S_ISDIR (s.st_mode)) { - lang_add_input_file (optarg, - lang_input_file_is_symbols_only_enum, - NULL); + input = lang_add_input_file (optarg, + lang_input_file_is_symbols_only_enum, + NULL); + cmdline_list_append (cmdline_is_lang_input_statement_enum, + input); break; } } @@ -1483,6 +1492,7 @@ parse_args (unsigned argc, char **argv) break; case '(': lang_enter_group (); + cmdline_list_append (cmdline_is_enter_group_enum, NULL); ingroup++; break; case ')': @@ -1490,6 +1500,7 @@ parse_args (unsigned argc, char **argv) einfo (_("%P%F: group ended before it began (--help for usage)\n")); lang_leave_group (); + cmdline_list_append (cmdline_is_leave_group_enum, NULL); ingroup--; break; diff --git a/ld/plugin.c b/ld/plugin.c index 6afc14b..d9f7162 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -211,6 +211,17 @@ plugin_opt_plugin_arg (const char *arg) if (!last_plugin) return set_plugin_error (_("")); + /* Ignore -pass-through= from GCC driver. */ + if (*arg == '-') + { + const char *p; + for (p = arg + 1; p; p++) + if (*p != '-') + break; + if (strncmp (p, "pass-through=", 13) == 0) + return 0; + } + newarg = xmalloc (sizeof *newarg); newarg->arg = arg; newarg->next = NULL; @@ -520,9 +531,9 @@ static enum ld_plugin_status add_input_file (const char *pathname) { ASSERT (called_plugin); - if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum, - NULL)) - return LDPS_ERR; + if (trace_files || trace_file_tries) + info_msg ("Plugin add input file: %s\n", pathname); + cmdline_list_insert_claimed_output (xstrdup (pathname)); return LDPS_OK; } @@ -531,9 +542,9 @@ static enum ld_plugin_status add_input_library (const char *pathname) { ASSERT (called_plugin); - if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum, - NULL)) - return LDPS_ERR; + if (trace_files || trace_file_tries) + info_msg ("Plugin add input library: %s\n", pathname); + cmdline_list_insert_claimed_output (xstrdup (pathname)); return LDPS_OK; } diff --git a/ld/testsuite/ld-plugin/func1i.c b/ld/testsuite/ld-plugin/func1i.c new file mode 100644 index 0000000..eb334a8 --- /dev/null +++ b/ld/testsuite/ld-plugin/func1i.c @@ -0,0 +1,8 @@ +extern int retval; + +int +__attribute__ ((visibility ("internal"))) +func1 (void) +{ + return retval; +} diff --git a/ld/testsuite/ld-plugin/func2.c b/ld/testsuite/ld-plugin/func2.c new file mode 100644 index 0000000..d233fcf --- /dev/null +++ b/ld/testsuite/ld-plugin/func2.c @@ -0,0 +1,7 @@ + +extern int retval; + +int func2 (void) +{ + return retval; +} diff --git a/ld/testsuite/ld-plugin/func2h.c b/ld/testsuite/ld-plugin/func2h.c new file mode 100644 index 0000000..9398108 --- /dev/null +++ b/ld/testsuite/ld-plugin/func2h.c @@ -0,0 +1,8 @@ +extern int retval; + +int +__attribute__ ((visibility ("hidden"))) +func2 (void) +{ + return retval; +} diff --git a/ld/testsuite/ld-plugin/func3p.c b/ld/testsuite/ld-plugin/func3p.c new file mode 100644 index 0000000..fdba15b --- /dev/null +++ b/ld/testsuite/ld-plugin/func3p.c @@ -0,0 +1,8 @@ +extern int retval; + +int +__attribute__ ((visibility ("protected"))) +func3 (void) +{ + return retval; +} diff --git a/ld/testsuite/ld-plugin/plugin-7.d b/ld/testsuite/ld-plugin/plugin-7.d index 75f25e0..ee7a6eb 100644 --- a/ld/testsuite/ld-plugin/plugin-7.d +++ b/ld/testsuite/ld-plugin/plugin-7.d @@ -19,7 +19,8 @@ tv\[16\]: LDPT_OPTION 'registerallsymbolsread' tv\[17\]: LDPT_OPTION 'registercleanup' tv\[18\]: LDPT_OPTION 'claim:tmpdir/func.o' tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0' -tv\[20\]: LDPT_NULL value 0x0 \(0\) +tv\[20\]: LDPT_OPTION 'add:tmpdir/func.o' +tv\[21\]: LDPT_NULL value 0x0 \(0\) #... hook called: claim_file tmpdir/main.o \[@0/.* not claimed hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED diff --git a/ld/testsuite/ld-plugin/plugin-8.d b/ld/testsuite/ld-plugin/plugin-8.d index e72b039..a4db899 100644 --- a/ld/testsuite/ld-plugin/plugin-8.d +++ b/ld/testsuite/ld-plugin/plugin-8.d @@ -21,7 +21,9 @@ tv\[18\]: LDPT_OPTION 'claim:tmpdir/func.o' tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0' tv\[20\]: LDPT_OPTION 'sym:_?func2::0:0:0' tv\[21\]: LDPT_OPTION 'dumpresolutions' -tv\[22\]: LDPT_NULL value 0x0 \(0\) +tv\[22\]: LDPT_OPTION 'add:tmpdir/func.o' +tv\[23\]: LDPT_OPTION 'add:tmpdir/func2.o' +tv\[24\]: LDPT_NULL value 0x0 \(0\) #... hook called: claim_file tmpdir/main.o \[@0/.* not claimed hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED diff --git a/ld/testsuite/ld-plugin/plugin-9.d b/ld/testsuite/ld-plugin/plugin-9.d index b74f4a6..a4db899 100644 --- a/ld/testsuite/ld-plugin/plugin-9.d +++ b/ld/testsuite/ld-plugin/plugin-9.d @@ -22,7 +22,8 @@ tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0' tv\[20\]: LDPT_OPTION 'sym:_?func2::0:0:0' tv\[21\]: LDPT_OPTION 'dumpresolutions' tv\[22\]: LDPT_OPTION 'add:tmpdir/func.o' -tv\[23\]: LDPT_NULL value 0x0 \(0\) +tv\[23\]: LDPT_OPTION 'add:tmpdir/func2.o' +tv\[24\]: LDPT_NULL value 0x0 \(0\) #... hook called: claim_file tmpdir/main.o \[@0/.* not claimed hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED diff --git a/ld/testsuite/ld-plugin/plugin.exp b/ld/testsuite/ld-plugin/plugin.exp index 8952f1d..665c2b4 100644 --- a/ld/testsuite/ld-plugin/plugin.exp +++ b/ld/testsuite/ld-plugin/plugin.exp @@ -70,6 +70,7 @@ set plugin_nm_output "" if { $can_compile && \ (![ld_compile "$CC $CFLAGS" $srcdir/$subdir/main.c tmpdir/main.o] \ || ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/func.c tmpdir/func.o] \ + || ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/func2.c tmpdir/func2.o] \ || ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/text.c tmpdir/text.o]) } { # Defer fail until we have list of tests set. set failed_compile 1 @@ -108,12 +109,15 @@ set plugin_tests [list \ [list "plugin claimfile replace symbol" "-plugin $plugin_path $regclm \ $regas $regcln -plugin-opt claim:tmpdir/func.o \ -plugin-opt sym:${_}func::0:0:0 \ + -plugin-opt add:tmpdir/func.o \ $testobjfiles $libs" "" "" {{ld plugin-7.d}} "main.x" ] \ [list "plugin claimfile resolve symbol" "-plugin $plugin_path $regclm \ $regas $regcln -plugin-opt claim:tmpdir/func.o \ -plugin-opt sym:${_}func::0:0:0 \ -plugin-opt sym:${_}func2::0:0:0 \ -plugin-opt dumpresolutions \ + -plugin-opt add:tmpdir/func.o \ + -plugin-opt add:tmpdir/func2.o \ $testobjfiles $libs" "" "" {{ld plugin-8.d}} "main.x" ] \ [list "plugin claimfile replace file" "-plugin $plugin_path $regclm \ $regas $regcln -plugin-opt claim:tmpdir/func.o \ @@ -121,6 +125,7 @@ set plugin_tests [list \ -plugin-opt sym:${_}func2::0:0:0 \ -plugin-opt dumpresolutions \ -plugin-opt add:tmpdir/func.o \ + -plugin-opt add:tmpdir/func2.o \ $testobjfiles $libs" "" "" {{ld plugin-9.d}} "main.x" ] \ ] @@ -152,6 +157,10 @@ set plugin_extra_elf_tests [list \ -plugin-opt sym:${_}func2::0:2:0 \ -plugin-opt sym:${_}func3::0:3:0 \ -plugin-opt dumpresolutions \ + -plugin-opt add:tmpdir/func.o \ + -plugin-opt add:tmpdir/func1i.o \ + -plugin-opt add:tmpdir/func2h.o \ + -plugin-opt add:tmpdir/func3p.o \ $testobjfiles $libs" "" "" {{ld plugin-ignore.d} \ {readelf -s plugin-vis-1.d}} "main.x" ] \ ] @@ -170,7 +179,10 @@ if { !$can_compile || $failed_compile } { run_ld_link_tests $plugin_tests -if { [is_elf_format] } { +if { [is_elf_format] \ + && [ld_compile "$CC $CFLAGS" $srcdir/$subdir/func1i.c tmpdir/func1i.o] \ + && [ld_compile "$CC $CFLAGS" $srcdir/$subdir/func2h.c tmpdir/func2h.o] \ + && [ld_compile "$CC $CFLAGS" $srcdir/$subdir/func3p.c tmpdir/func3p.o] } { run_ld_link_tests $plugin_extra_elf_tests }