PATCH: 2 stage BFD linker for LTO plugin
H.J. Lu
hjl.tools@gmail.com
Sat Dec 4 06:07:00 GMT 2010
On Fri, Dec 3, 2010 at 6:34 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Dec 3, 2010 at 6:23 PM, Dave Korn <dave.korn.cygwin@gmail.com> wrote:
>> On 04/12/2010 01:24, H.J. Lu wrote:
>>
>>> I checked in a patch to implement stage 2 linking. Everything
>>> seems to work, including "gcc -static ... -lm".
>>
>> Any chance you could send a complete diff?
>>
>
> I will submit a complete diff after I fix a few corner cases.
> In the meantime, you can clone my git tree and do a "git diff".
>
Hi,
This patch implements 2 stage BFD linker for LTO plugin.
It works with current LTO API on all cases I tested.
Known issue: --whole-archive will call plugin on archives with IR
in stage 2 linking. But ld never calls plugin to get back object files.
I will try to avoid it in a follow up patch.
OK for trunk?
Thanks.
--
H.J.
---
bfd/
2010-12-03 H.J. Lu <hongjiu.lu@intel.com>
PR driver/42690
* 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 <hongjiu.lu@intel.com>
PR driver/42690
* 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.
* 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 <hongjiu.lu@intel.com>
PR driver/42690
* 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.
-------------- next part --------------
bfd/
2010-12-03 H.J. Lu <hongjiu.lu@intel.com>
PR driver/42690
* 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 <hongjiu.lu@intel.com>
* 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.
* 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 <hongjiu.lu@intel.com>
PR driver/42690
* 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..3737db9 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 ();
+ }
+ 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 f74c1b5..458d856 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);
@@ -6419,21 +6427,67 @@ 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 *abfd = bfd_my_archive (p);
+ if (!abfd)
+ abfd = p;
+ if ((abfd->flags & BFD_PLUGIN) != 0)
+ {
+ 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 */
@@ -7853,3 +7907,153 @@ 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 (void)
+{
+ 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
+ && !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..d0aea1d 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 (void);
+
#endif
diff --git a/ld/lexsup.c b/ld/lexsup.c
index b6274f8..f3d8684 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -720,6 +720,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
@@ -758,7 +759,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:
@@ -915,7 +919,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 = "-";
@@ -1100,9 +1107,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;
}
}
@@ -1484,6 +1493,7 @@ parse_args (unsigned argc, char **argv)
break;
case '(':
lang_enter_group ();
+ cmdline_list_append (cmdline_is_enter_group_enum, NULL);
ingroup++;
break;
case ')':
@@ -1491,6 +1501,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..c321996 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 (_("<no plugin>"));
+ /* 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,7 @@ 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;
+ cmdline_list_insert_claimed_output (xstrdup (pathname));
return LDPS_OK;
}
@@ -531,9 +540,7 @@ 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;
+ 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
}
More information about the Binutils
mailing list