Rev 5199 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5199 | Rev 6324 | ||
---|---|---|---|
1 | /* Plugin control for the GNU linker. |
1 | /* Plugin control for the GNU linker. |
2 | Copyright 2010, 2011, 2012, 2013 Free Software Foundation, Inc. |
2 | Copyright (C) 2010-2015 Free Software Foundation, Inc. |
3 | 3 | ||
4 | This file is part of the GNU Binutils. |
4 | This file is part of the GNU Binutils. |
5 | 5 | ||
6 | This program is free software; you can redistribute it and/or modify |
6 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by |
7 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 3 of the License, or |
8 | the Free Software Foundation; either version 3 of the License, or |
9 | (at your option) any later version. |
9 | (at your option) any later version. |
10 | 10 | ||
11 | This program is distributed in the hope that it will be useful, |
11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | GNU General Public License for more details. |
14 | GNU General Public License for more details. |
15 | 15 | ||
16 | You should have received a copy of the GNU General Public License |
16 | You should have received a copy of the GNU General Public License |
17 | along with this program; if not, write to the Free Software |
17 | along with this program; if not, write to the Free Software |
18 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
18 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
19 | MA 02110-1301, USA. */ |
19 | MA 02110-1301, USA. */ |
20 | 20 | ||
21 | #include "sysdep.h" |
21 | #include "sysdep.h" |
22 | #include "libiberty.h" |
22 | #include "libiberty.h" |
23 | #include "bfd.h" |
23 | #include "bfd.h" |
- | 24 | #include "libbfd.h" |
|
24 | #include "bfdlink.h" |
25 | #include "bfdlink.h" |
25 | #include "bfdver.h" |
26 | #include "bfdver.h" |
26 | #include "ld.h" |
27 | #include "ld.h" |
27 | #include "ldmain.h" |
28 | #include "ldmain.h" |
28 | #include "ldmisc.h" |
29 | #include "ldmisc.h" |
29 | #include "ldexp.h" |
30 | #include "ldexp.h" |
30 | #include "ldlang.h" |
31 | #include "ldlang.h" |
31 | #include "ldfile.h" |
32 | #include "ldfile.h" |
- | 33 | #include "../bfd/plugin.h" |
|
32 | #include "plugin.h" |
34 | #include "plugin.h" |
33 | #include "plugin-api.h" |
35 | #include "plugin-api.h" |
34 | #include "elf-bfd.h" |
36 | #include "elf-bfd.h" |
35 | #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) |
37 | #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) |
36 | #include |
38 | #include |
37 | #endif |
39 | #endif |
38 | 40 | ||
39 | /* Report plugin symbols. */ |
41 | /* Report plugin symbols. */ |
40 | bfd_boolean report_plugin_symbols; |
42 | bfd_boolean report_plugin_symbols; |
41 | 43 | ||
42 | /* The suffix to append to the name of the real (claimed) object file |
44 | /* The suffix to append to the name of the real (claimed) object file |
43 | when generating a dummy BFD to hold the IR symbols sent from the |
45 | when generating a dummy BFD to hold the IR symbols sent from the |
44 | plugin. For cosmetic use only; appears in maps, crefs etc. */ |
46 | plugin. For cosmetic use only; appears in maps, crefs etc. */ |
45 | #define IRONLY_SUFFIX " (symbol from plugin)" |
47 | #define IRONLY_SUFFIX " (symbol from plugin)" |
46 | 48 | ||
47 | /* Stores a single argument passed to a plugin. */ |
49 | /* Stores a single argument passed to a plugin. */ |
48 | typedef struct plugin_arg |
50 | typedef struct plugin_arg |
49 | { |
51 | { |
50 | struct plugin_arg *next; |
52 | struct plugin_arg *next; |
51 | const char *arg; |
53 | const char *arg; |
52 | } plugin_arg_t; |
54 | } plugin_arg_t; |
53 | 55 | ||
54 | /* Holds all details of a single plugin. */ |
56 | /* Holds all details of a single plugin. */ |
55 | typedef struct plugin |
57 | typedef struct plugin |
56 | { |
58 | { |
57 | /* Next on the list of plugins, or NULL at end of chain. */ |
59 | /* Next on the list of plugins, or NULL at end of chain. */ |
58 | struct plugin *next; |
60 | struct plugin *next; |
59 | /* The argument string given to --plugin. */ |
61 | /* The argument string given to --plugin. */ |
60 | const char *name; |
62 | const char *name; |
61 | /* The shared library handle returned by dlopen. */ |
63 | /* The shared library handle returned by dlopen. */ |
62 | void *dlhandle; |
64 | void *dlhandle; |
63 | /* The list of argument string given to --plugin-opt. */ |
65 | /* The list of argument string given to --plugin-opt. */ |
64 | plugin_arg_t *args; |
66 | plugin_arg_t *args; |
65 | /* Number of args in the list, for convenience. */ |
67 | /* Number of args in the list, for convenience. */ |
66 | size_t n_args; |
68 | size_t n_args; |
67 | /* The plugin's event handlers. */ |
69 | /* The plugin's event handlers. */ |
68 | ld_plugin_claim_file_handler claim_file_handler; |
70 | ld_plugin_claim_file_handler claim_file_handler; |
69 | ld_plugin_all_symbols_read_handler all_symbols_read_handler; |
71 | ld_plugin_all_symbols_read_handler all_symbols_read_handler; |
70 | ld_plugin_cleanup_handler cleanup_handler; |
72 | ld_plugin_cleanup_handler cleanup_handler; |
71 | /* TRUE if the cleanup handlers have been called. */ |
73 | /* TRUE if the cleanup handlers have been called. */ |
72 | bfd_boolean cleanup_done; |
74 | bfd_boolean cleanup_done; |
73 | } plugin_t; |
75 | } plugin_t; |
- | 76 | ||
- | 77 | typedef struct view_buffer |
|
- | 78 | { |
|
- | 79 | char *addr; |
|
- | 80 | size_t filesize; |
|
- | 81 | off_t offset; |
|
- | 82 | } view_buffer_t; |
|
- | 83 | ||
- | 84 | /* The internal version of struct ld_plugin_input_file with a BFD |
|
- | 85 | pointer. */ |
|
- | 86 | typedef struct plugin_input_file |
|
- | 87 | { |
|
- | 88 | bfd *abfd; |
|
- | 89 | view_buffer_t view_buffer; |
|
- | 90 | char *name; |
|
- | 91 | int fd; |
|
- | 92 | bfd_boolean use_mmap; |
|
- | 93 | off_t offset; |
|
- | 94 | off_t filesize; |
|
- | 95 | } plugin_input_file_t; |
|
74 | 96 | ||
75 | /* The master list of all plugins. */ |
97 | /* The master list of all plugins. */ |
76 | static plugin_t *plugins_list = NULL; |
98 | static plugin_t *plugins_list = NULL; |
77 | 99 | ||
78 | /* We keep a tail pointer for easy linking on the end. */ |
100 | /* We keep a tail pointer for easy linking on the end. */ |
79 | static plugin_t **plugins_tail_chain_ptr = &plugins_list; |
101 | static plugin_t **plugins_tail_chain_ptr = &plugins_list; |
80 | 102 | ||
81 | /* The last plugin added to the list, for receiving args. */ |
103 | /* The last plugin added to the list, for receiving args. */ |
82 | static plugin_t *last_plugin = NULL; |
104 | static plugin_t *last_plugin = NULL; |
83 | 105 | ||
84 | /* The tail of the arg chain of the last plugin added to the list. */ |
106 | /* The tail of the arg chain of the last plugin added to the list. */ |
85 | static plugin_arg_t **last_plugin_args_tail_chain_ptr = NULL; |
107 | static plugin_arg_t **last_plugin_args_tail_chain_ptr = NULL; |
86 | 108 | ||
87 | /* The plugin which is currently having a callback executed. */ |
109 | /* The plugin which is currently having a callback executed. */ |
88 | static plugin_t *called_plugin = NULL; |
110 | static plugin_t *called_plugin = NULL; |
89 | 111 | ||
90 | /* Last plugin to cause an error, if any. */ |
112 | /* Last plugin to cause an error, if any. */ |
91 | static const char *error_plugin = NULL; |
113 | static const char *error_plugin = NULL; |
92 | 114 | ||
93 | /* State of linker "notice" interface before we poked at it. */ |
115 | /* State of linker "notice" interface before we poked at it. */ |
94 | static bfd_boolean orig_notice_all; |
116 | static bfd_boolean orig_notice_all; |
95 | 117 | ||
96 | /* Original linker callbacks, and the plugin version. */ |
118 | /* Original linker callbacks, and the plugin version. */ |
97 | static const struct bfd_link_callbacks *orig_callbacks; |
119 | static const struct bfd_link_callbacks *orig_callbacks; |
98 | static struct bfd_link_callbacks plugin_callbacks; |
120 | static struct bfd_link_callbacks plugin_callbacks; |
99 | 121 | ||
100 | /* Set at all symbols read time, to avoid recursively offering the plugin |
122 | /* Set at all symbols read time, to avoid recursively offering the plugin |
101 | its own newly-added input files and libs to claim. */ |
123 | its own newly-added input files and libs to claim. */ |
102 | bfd_boolean no_more_claiming = FALSE; |
124 | bfd_boolean no_more_claiming = FALSE; |
103 | 125 | ||
104 | /* List of tags to set in the constant leading part of the tv array. */ |
126 | /* List of tags to set in the constant leading part of the tv array. */ |
105 | static const enum ld_plugin_tag tv_header_tags[] = |
127 | static const enum ld_plugin_tag tv_header_tags[] = |
106 | { |
128 | { |
107 | LDPT_MESSAGE, |
129 | LDPT_MESSAGE, |
108 | LDPT_API_VERSION, |
130 | LDPT_API_VERSION, |
109 | LDPT_GNU_LD_VERSION, |
131 | LDPT_GNU_LD_VERSION, |
110 | LDPT_LINKER_OUTPUT, |
132 | LDPT_LINKER_OUTPUT, |
111 | LDPT_OUTPUT_NAME, |
133 | LDPT_OUTPUT_NAME, |
112 | LDPT_REGISTER_CLAIM_FILE_HOOK, |
134 | LDPT_REGISTER_CLAIM_FILE_HOOK, |
113 | LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK, |
135 | LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK, |
114 | LDPT_REGISTER_CLEANUP_HOOK, |
136 | LDPT_REGISTER_CLEANUP_HOOK, |
115 | LDPT_ADD_SYMBOLS, |
137 | LDPT_ADD_SYMBOLS, |
116 | LDPT_GET_INPUT_FILE, |
138 | LDPT_GET_INPUT_FILE, |
- | 139 | LDPT_GET_VIEW, |
|
117 | LDPT_RELEASE_INPUT_FILE, |
140 | LDPT_RELEASE_INPUT_FILE, |
118 | LDPT_GET_SYMBOLS, |
141 | LDPT_GET_SYMBOLS, |
119 | LDPT_GET_SYMBOLS_V2, |
142 | LDPT_GET_SYMBOLS_V2, |
120 | LDPT_ADD_INPUT_FILE, |
143 | LDPT_ADD_INPUT_FILE, |
121 | LDPT_ADD_INPUT_LIBRARY, |
144 | LDPT_ADD_INPUT_LIBRARY, |
122 | LDPT_SET_EXTRA_LIBRARY_PATH |
145 | LDPT_SET_EXTRA_LIBRARY_PATH |
123 | }; |
146 | }; |
124 | 147 | ||
125 | /* How many entries in the constant leading part of the tv array. */ |
148 | /* How many entries in the constant leading part of the tv array. */ |
126 | static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags); |
149 | static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags); |
127 | 150 | ||
128 | /* Forward references. */ |
151 | /* Forward references. */ |
129 | static bfd_boolean plugin_notice (struct bfd_link_info *, |
152 | static bfd_boolean plugin_notice (struct bfd_link_info *, |
- | 153 | struct bfd_link_hash_entry *, |
|
130 | struct bfd_link_hash_entry *, bfd *, |
154 | struct bfd_link_hash_entry *, |
131 | asection *, bfd_vma, flagword, const char *); |
155 | bfd *, asection *, bfd_vma, flagword); |
- | 156 | ||
- | 157 | static const bfd_target * plugin_object_p (bfd *); |
|
132 | 158 | ||
133 | #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) |
159 | #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) |
134 | 160 | ||
135 | #define RTLD_NOW 0 /* Dummy value. */ |
161 | #define RTLD_NOW 0 /* Dummy value. */ |
136 | 162 | ||
137 | static void * |
163 | static void * |
138 | dlopen (const char *file, int mode ATTRIBUTE_UNUSED) |
164 | dlopen (const char *file, int mode ATTRIBUTE_UNUSED) |
139 | { |
165 | { |
140 | return LoadLibrary (file); |
166 | return LoadLibrary (file); |
141 | } |
167 | } |
142 | 168 | ||
143 | static void * |
169 | static void * |
144 | dlsym (void *handle, const char *name) |
170 | dlsym (void *handle, const char *name) |
145 | { |
171 | { |
146 | return GetProcAddress (handle, name); |
172 | return GetProcAddress (handle, name); |
147 | } |
173 | } |
148 | 174 | ||
149 | static int |
175 | static int |
150 | dlclose (void *handle) |
176 | dlclose (void *handle) |
151 | { |
177 | { |
152 | FreeLibrary (handle); |
178 | FreeLibrary (handle); |
153 | return 0; |
179 | return 0; |
154 | } |
180 | } |
155 | 181 | ||
156 | #endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) */ |
182 | #endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) */ |
157 | 183 | ||
158 | #ifndef HAVE_DLFCN_H |
184 | #ifndef HAVE_DLFCN_H |
159 | static const char * |
185 | static const char * |
160 | dlerror (void) |
186 | dlerror (void) |
161 | { |
187 | { |
162 | return ""; |
188 | return ""; |
163 | } |
189 | } |
164 | #endif |
190 | #endif |
165 | 191 | ||
166 | /* Helper function for exiting with error status. */ |
192 | /* Helper function for exiting with error status. */ |
167 | static int |
193 | static int |
168 | set_plugin_error (const char *plugin) |
194 | set_plugin_error (const char *plugin) |
169 | { |
195 | { |
170 | error_plugin = plugin; |
196 | error_plugin = plugin; |
171 | return -1; |
197 | return -1; |
172 | } |
198 | } |
173 | 199 | ||
174 | /* Test if an error occurred. */ |
200 | /* Test if an error occurred. */ |
175 | static bfd_boolean |
201 | static bfd_boolean |
176 | plugin_error_p (void) |
202 | plugin_error_p (void) |
177 | { |
203 | { |
178 | return error_plugin != NULL; |
204 | return error_plugin != NULL; |
179 | } |
205 | } |
180 | 206 | ||
181 | /* Return name of plugin which caused an error if any. */ |
207 | /* Return name of plugin which caused an error if any. */ |
182 | const char * |
208 | const char * |
183 | plugin_error_plugin (void) |
209 | plugin_error_plugin (void) |
184 | { |
210 | { |
185 | return error_plugin ? error_plugin : _(" |
211 | return error_plugin ? error_plugin : _(" |
186 | } |
212 | } |
187 | 213 | ||
188 | /* Handle -plugin arg: find and load plugin, or return error. */ |
214 | /* Handle -plugin arg: find and load plugin, or return error. */ |
189 | void |
215 | void |
190 | plugin_opt_plugin (const char *plugin) |
216 | plugin_opt_plugin (const char *plugin) |
191 | { |
217 | { |
192 | plugin_t *newplug; |
218 | plugin_t *newplug; |
193 | 219 | ||
194 | newplug = xmalloc (sizeof *newplug); |
220 | newplug = xmalloc (sizeof *newplug); |
195 | memset (newplug, 0, sizeof *newplug); |
221 | memset (newplug, 0, sizeof *newplug); |
196 | newplug->name = plugin; |
222 | newplug->name = plugin; |
197 | newplug->dlhandle = dlopen (plugin, RTLD_NOW); |
223 | newplug->dlhandle = dlopen (plugin, RTLD_NOW); |
198 | if (!newplug->dlhandle) |
224 | if (!newplug->dlhandle) |
199 | einfo (_("%P%F: %s: error loading plugin: %s\n"), plugin, dlerror ()); |
225 | einfo (_("%P%F: %s: error loading plugin: %s\n"), plugin, dlerror ()); |
200 | 226 | ||
201 | /* Chain on end, so when we run list it is in command-line order. */ |
227 | /* Chain on end, so when we run list it is in command-line order. */ |
202 | *plugins_tail_chain_ptr = newplug; |
228 | *plugins_tail_chain_ptr = newplug; |
203 | plugins_tail_chain_ptr = &newplug->next; |
229 | plugins_tail_chain_ptr = &newplug->next; |
204 | 230 | ||
205 | /* Record it as current plugin for receiving args. */ |
231 | /* Record it as current plugin for receiving args. */ |
206 | last_plugin = newplug; |
232 | last_plugin = newplug; |
207 | last_plugin_args_tail_chain_ptr = &newplug->args; |
233 | last_plugin_args_tail_chain_ptr = &newplug->args; |
208 | } |
234 | } |
209 | 235 | ||
210 | /* Accumulate option arguments for last-loaded plugin, or return |
236 | /* Accumulate option arguments for last-loaded plugin, or return |
211 | error if none. */ |
237 | error if none. */ |
212 | int |
238 | int |
213 | plugin_opt_plugin_arg (const char *arg) |
239 | plugin_opt_plugin_arg (const char *arg) |
214 | { |
240 | { |
215 | plugin_arg_t *newarg; |
241 | plugin_arg_t *newarg; |
216 | 242 | ||
217 | if (!last_plugin) |
243 | if (!last_plugin) |
218 | return set_plugin_error (_(" |
244 | return set_plugin_error (_(" |
- | 245 | ||
- | 246 | /* Ignore -pass-through= from GCC driver. */ |
|
- | 247 | if (*arg == '-') |
|
- | 248 | { |
|
- | 249 | const char *p = arg + 1; |
|
- | 250 | ||
- | 251 | if (*p == '-') |
|
- | 252 | ++p; |
|
- | 253 | if (strncmp (p, "pass-through=", 13) == 0) |
|
- | 254 | return 0; |
|
- | 255 | } |
|
219 | 256 | ||
220 | newarg = xmalloc (sizeof *newarg); |
257 | newarg = xmalloc (sizeof *newarg); |
221 | newarg->arg = arg; |
258 | newarg->arg = arg; |
222 | newarg->next = NULL; |
259 | newarg->next = NULL; |
223 | 260 | ||
224 | /* Chain on end to preserve command-line order. */ |
261 | /* Chain on end to preserve command-line order. */ |
225 | *last_plugin_args_tail_chain_ptr = newarg; |
262 | *last_plugin_args_tail_chain_ptr = newarg; |
226 | last_plugin_args_tail_chain_ptr = &newarg->next; |
263 | last_plugin_args_tail_chain_ptr = &newarg->next; |
227 | last_plugin->n_args++; |
264 | last_plugin->n_args++; |
228 | return 0; |
265 | return 0; |
229 | } |
266 | } |
230 | 267 | ||
- | 268 | /* Generate a dummy BFD to represent an IR file, for any callers of |
|
- | 269 | plugin_call_claim_file to use as the handle in the ld_plugin_input_file |
|
- | 270 | struct that they build to pass in. The BFD is initially writable, so |
|
- | 271 | that symbols can be added to it; it must be made readable after the |
|
231 | /* Create a dummy BFD. */ |
272 | add_symbols hook has been called so that it can be read when linking. */ |
232 | bfd * |
273 | static bfd * |
233 | plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate) |
274 | plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate) |
234 | { |
275 | { |
235 | bfd *abfd; |
276 | bfd *abfd; |
- | 277 | bfd_boolean bfd_plugin_target; |
|
236 | 278 | ||
- | 279 | bfd_use_reserved_id = 1; |
|
237 | bfd_use_reserved_id = 1; |
280 | bfd_plugin_target = bfd_plugin_target_p (srctemplate->xvec); |
238 | abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL), |
281 | abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL), |
239 | srctemplate); |
282 | bfd_plugin_target ? link_info.output_bfd : srctemplate); |
240 | if (abfd != NULL) |
283 | if (abfd != NULL) |
241 | { |
284 | { |
242 | abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN; |
285 | abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN; |
- | 286 | if (!bfd_make_writable (abfd)) |
|
- | 287 | goto report_error; |
|
- | 288 | if (!bfd_plugin_target) |
|
- | 289 | { |
|
243 | bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate)); |
290 | bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate)); |
244 | bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate)); |
291 | bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate)); |
245 | if (bfd_make_writable (abfd) |
- | |
246 | && bfd_copy_private_bfd_data (srctemplate, abfd)) |
292 | if (!bfd_copy_private_bfd_data (srctemplate, abfd)) |
- | 293 | goto report_error; |
|
- | 294 | } |
|
247 | { |
295 | { |
248 | flagword flags; |
296 | flagword flags; |
249 | 297 | ||
250 | /* Create section to own the symbols. */ |
298 | /* Create section to own the symbols. */ |
251 | flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY |
299 | flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY |
252 | | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE); |
300 | | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE); |
253 | if (bfd_make_section_anyway_with_flags (abfd, ".text", flags)) |
301 | if (bfd_make_section_anyway_with_flags (abfd, ".text", flags)) |
254 | return abfd; |
302 | return abfd; |
255 | } |
303 | } |
256 | } |
304 | } |
- | 305 | report_error: |
|
257 | einfo (_("could not create dummy IR bfd: %F%E\n")); |
306 | einfo (_("could not create dummy IR bfd: %F%E\n")); |
258 | return NULL; |
307 | return NULL; |
259 | } |
308 | } |
260 | 309 | ||
261 | /* Check if the BFD passed in is an IR dummy object file. */ |
310 | /* Check if the BFD passed in is an IR dummy object file. */ |
262 | static bfd_boolean |
311 | static inline bfd_boolean |
263 | is_ir_dummy_bfd (const bfd *abfd) |
312 | is_ir_dummy_bfd (const bfd *abfd) |
264 | { |
313 | { |
265 | /* ABFD can sometimes legitimately be NULL, e.g. when called from one |
314 | /* ABFD can sometimes legitimately be NULL, e.g. when called from one |
266 | of the linker callbacks for a symbol in the *ABS* or *UND* sections. |
315 | of the linker callbacks for a symbol in the *ABS* or *UND* sections. */ |
267 | Likewise, the usrdata field may be NULL if ABFD was added by the |
316 | return abfd != NULL && (abfd->flags & BFD_PLUGIN) != 0; |
268 | backend without a corresponding input statement, as happens e.g. |
- | |
269 | when processing DT_NEEDED dependencies. */ |
- | |
270 | return (abfd |
- | |
271 | && abfd->usrdata |
- | |
272 | && ((lang_input_statement_type *)(abfd->usrdata))->flags.claimed); |
- | |
273 | } |
317 | } |
274 | 318 | ||
275 | /* Helpers to convert between BFD and GOLD symbol formats. */ |
319 | /* Helpers to convert between BFD and GOLD symbol formats. */ |
276 | static enum ld_plugin_status |
320 | static enum ld_plugin_status |
277 | asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym, |
321 | asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym, |
278 | const struct ld_plugin_symbol *ldsym) |
322 | const struct ld_plugin_symbol *ldsym) |
279 | { |
323 | { |
280 | flagword flags = BSF_NO_FLAGS; |
324 | flagword flags = BSF_NO_FLAGS; |
281 | struct bfd_section *section; |
325 | struct bfd_section *section; |
282 | 326 | ||
283 | asym->the_bfd = abfd; |
327 | asym->the_bfd = abfd; |
284 | asym->name = (ldsym->version |
328 | asym->name = (ldsym->version |
285 | ? concat (ldsym->name, "@", ldsym->version, (const char *) NULL) |
329 | ? concat (ldsym->name, "@", ldsym->version, (const char *) NULL) |
286 | : ldsym->name); |
330 | : ldsym->name); |
287 | asym->value = 0; |
331 | asym->value = 0; |
288 | switch (ldsym->def) |
332 | switch (ldsym->def) |
289 | { |
333 | { |
290 | case LDPK_WEAKDEF: |
334 | case LDPK_WEAKDEF: |
291 | flags = BSF_WEAK; |
335 | flags = BSF_WEAK; |
292 | /* FALLTHRU */ |
336 | /* FALLTHRU */ |
293 | case LDPK_DEF: |
337 | case LDPK_DEF: |
294 | flags |= BSF_GLOBAL; |
338 | flags |= BSF_GLOBAL; |
295 | if (ldsym->comdat_key) |
339 | if (ldsym->comdat_key) |
296 | { |
340 | { |
297 | char *name = concat (".gnu.linkonce.t.", ldsym->comdat_key, |
341 | char *name = concat (".gnu.linkonce.t.", ldsym->comdat_key, |
298 | (const char *) NULL); |
342 | (const char *) NULL); |
299 | section = bfd_get_section_by_name (abfd, name); |
343 | section = bfd_get_section_by_name (abfd, name); |
300 | if (section != NULL) |
344 | if (section != NULL) |
301 | free (name); |
345 | free (name); |
302 | else |
346 | else |
303 | { |
347 | { |
304 | flagword sflags; |
348 | flagword sflags; |
305 | 349 | ||
306 | sflags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY |
350 | sflags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY |
307 | | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE |
351 | | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE |
308 | | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD); |
352 | | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD); |
309 | section = bfd_make_section_anyway_with_flags (abfd, name, sflags); |
353 | section = bfd_make_section_anyway_with_flags (abfd, name, sflags); |
310 | if (section == NULL) |
354 | if (section == NULL) |
311 | return LDPS_ERR; |
355 | return LDPS_ERR; |
312 | } |
356 | } |
313 | } |
357 | } |
314 | else |
358 | else |
315 | section = bfd_get_section_by_name (abfd, ".text"); |
359 | section = bfd_get_section_by_name (abfd, ".text"); |
316 | break; |
360 | break; |
317 | 361 | ||
318 | case LDPK_WEAKUNDEF: |
362 | case LDPK_WEAKUNDEF: |
319 | flags = BSF_WEAK; |
363 | flags = BSF_WEAK; |
320 | /* FALLTHRU */ |
364 | /* FALLTHRU */ |
321 | case LDPK_UNDEF: |
365 | case LDPK_UNDEF: |
322 | section = bfd_und_section_ptr; |
366 | section = bfd_und_section_ptr; |
323 | break; |
367 | break; |
324 | 368 | ||
325 | case LDPK_COMMON: |
369 | case LDPK_COMMON: |
326 | flags = BSF_GLOBAL; |
370 | flags = BSF_GLOBAL; |
327 | section = bfd_com_section_ptr; |
371 | section = bfd_com_section_ptr; |
328 | asym->value = ldsym->size; |
372 | asym->value = ldsym->size; |
329 | /* For ELF targets, set alignment of common symbol to 1. */ |
373 | /* For ELF targets, set alignment of common symbol to 1. */ |
330 | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) |
374 | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) |
331 | { |
375 | { |
332 | ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON; |
376 | ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON; |
333 | ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1; |
377 | ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1; |
334 | } |
378 | } |
335 | break; |
379 | break; |
336 | 380 | ||
337 | default: |
381 | default: |
338 | return LDPS_ERR; |
382 | return LDPS_ERR; |
339 | } |
383 | } |
340 | asym->flags = flags; |
384 | asym->flags = flags; |
341 | asym->section = section; |
385 | asym->section = section; |
342 | 386 | ||
343 | /* Visibility only applies on ELF targets. */ |
387 | /* Visibility only applies on ELF targets. */ |
344 | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) |
388 | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) |
345 | { |
389 | { |
346 | elf_symbol_type *elfsym = elf_symbol_from (abfd, asym); |
390 | elf_symbol_type *elfsym = elf_symbol_from (abfd, asym); |
347 | unsigned char visibility; |
391 | unsigned char visibility; |
348 | 392 | ||
349 | if (!elfsym) |
393 | if (!elfsym) |
350 | einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name); |
394 | einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name); |
351 | switch (ldsym->visibility) |
395 | switch (ldsym->visibility) |
352 | { |
396 | { |
353 | default: |
397 | default: |
354 | einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"), |
398 | einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"), |
355 | ldsym->visibility); |
399 | ldsym->visibility); |
356 | case LDPV_DEFAULT: |
400 | case LDPV_DEFAULT: |
357 | visibility = STV_DEFAULT; |
401 | visibility = STV_DEFAULT; |
358 | break; |
402 | break; |
359 | case LDPV_PROTECTED: |
403 | case LDPV_PROTECTED: |
360 | visibility = STV_PROTECTED; |
404 | visibility = STV_PROTECTED; |
361 | break; |
405 | break; |
362 | case LDPV_INTERNAL: |
406 | case LDPV_INTERNAL: |
363 | visibility = STV_INTERNAL; |
407 | visibility = STV_INTERNAL; |
364 | break; |
408 | break; |
365 | case LDPV_HIDDEN: |
409 | case LDPV_HIDDEN: |
366 | visibility = STV_HIDDEN; |
410 | visibility = STV_HIDDEN; |
367 | break; |
411 | break; |
368 | } |
412 | } |
369 | elfsym->internal_elf_sym.st_other |
413 | elfsym->internal_elf_sym.st_other |
370 | = (visibility | (elfsym->internal_elf_sym.st_other |
414 | = (visibility | (elfsym->internal_elf_sym.st_other |
371 | & ~ELF_ST_VISIBILITY (-1))); |
415 | & ~ELF_ST_VISIBILITY (-1))); |
372 | } |
416 | } |
373 | 417 | ||
374 | return LDPS_OK; |
418 | return LDPS_OK; |
375 | } |
419 | } |
376 | 420 | ||
377 | /* Register a claim-file handler. */ |
421 | /* Register a claim-file handler. */ |
378 | static enum ld_plugin_status |
422 | static enum ld_plugin_status |
379 | register_claim_file (ld_plugin_claim_file_handler handler) |
423 | register_claim_file (ld_plugin_claim_file_handler handler) |
380 | { |
424 | { |
381 | ASSERT (called_plugin); |
425 | ASSERT (called_plugin); |
382 | called_plugin->claim_file_handler = handler; |
426 | called_plugin->claim_file_handler = handler; |
383 | return LDPS_OK; |
427 | return LDPS_OK; |
384 | } |
428 | } |
385 | 429 | ||
386 | /* Register an all-symbols-read handler. */ |
430 | /* Register an all-symbols-read handler. */ |
387 | static enum ld_plugin_status |
431 | static enum ld_plugin_status |
388 | register_all_symbols_read (ld_plugin_all_symbols_read_handler handler) |
432 | register_all_symbols_read (ld_plugin_all_symbols_read_handler handler) |
389 | { |
433 | { |
390 | ASSERT (called_plugin); |
434 | ASSERT (called_plugin); |
391 | called_plugin->all_symbols_read_handler = handler; |
435 | called_plugin->all_symbols_read_handler = handler; |
392 | return LDPS_OK; |
436 | return LDPS_OK; |
393 | } |
437 | } |
394 | 438 | ||
395 | /* Register a cleanup handler. */ |
439 | /* Register a cleanup handler. */ |
396 | static enum ld_plugin_status |
440 | static enum ld_plugin_status |
397 | register_cleanup (ld_plugin_cleanup_handler handler) |
441 | register_cleanup (ld_plugin_cleanup_handler handler) |
398 | { |
442 | { |
399 | ASSERT (called_plugin); |
443 | ASSERT (called_plugin); |
400 | called_plugin->cleanup_handler = handler; |
444 | called_plugin->cleanup_handler = handler; |
401 | return LDPS_OK; |
445 | return LDPS_OK; |
402 | } |
446 | } |
403 | 447 | ||
404 | /* Add symbols from a plugin-claimed input file. */ |
448 | /* Add symbols from a plugin-claimed input file. */ |
405 | static enum ld_plugin_status |
449 | static enum ld_plugin_status |
406 | add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms) |
450 | add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms) |
407 | { |
451 | { |
408 | asymbol **symptrs; |
452 | asymbol **symptrs; |
- | 453 | plugin_input_file_t *input = handle; |
|
409 | bfd *abfd = handle; |
454 | bfd *abfd = input->abfd; |
410 | int n; |
455 | int n; |
411 | 456 | ||
412 | ASSERT (called_plugin); |
457 | ASSERT (called_plugin); |
413 | symptrs = xmalloc (nsyms * sizeof *symptrs); |
458 | symptrs = xmalloc (nsyms * sizeof *symptrs); |
414 | for (n = 0; n < nsyms; n++) |
459 | for (n = 0; n < nsyms; n++) |
415 | { |
460 | { |
416 | enum ld_plugin_status rv; |
461 | enum ld_plugin_status rv; |
417 | asymbol *bfdsym; |
462 | asymbol *bfdsym; |
418 | 463 | ||
419 | bfdsym = bfd_make_empty_symbol (abfd); |
464 | bfdsym = bfd_make_empty_symbol (abfd); |
420 | symptrs[n] = bfdsym; |
465 | symptrs[n] = bfdsym; |
421 | rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n); |
466 | rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n); |
422 | if (rv != LDPS_OK) |
467 | if (rv != LDPS_OK) |
423 | return rv; |
468 | return rv; |
424 | } |
469 | } |
425 | bfd_set_symtab (abfd, symptrs, nsyms); |
470 | bfd_set_symtab (abfd, symptrs, nsyms); |
426 | return LDPS_OK; |
471 | return LDPS_OK; |
427 | } |
472 | } |
428 | 473 | ||
429 | /* Get the input file information with an open (possibly re-opened) |
474 | /* Get the input file information with an open (possibly re-opened) |
430 | file descriptor. */ |
475 | file descriptor. */ |
431 | static enum ld_plugin_status |
476 | static enum ld_plugin_status |
432 | get_input_file (const void *handle ATTRIBUTE_UNUSED, |
477 | get_input_file (const void *handle, struct ld_plugin_input_file *file) |
- | 478 | { |
|
433 | struct ld_plugin_input_file *file ATTRIBUTE_UNUSED) |
479 | const plugin_input_file_t *input = handle; |
- | 480 | ||
- | 481 | ASSERT (called_plugin); |
|
- | 482 | ||
- | 483 | file->name = input->name; |
|
- | 484 | file->offset = input->offset; |
|
- | 485 | file->filesize = input->filesize; |
|
- | 486 | file->handle = (void *) handle; |
|
- | 487 | ||
- | 488 | return LDPS_OK; |
|
- | 489 | } |
|
- | 490 | ||
- | 491 | /* Get view of the input file. */ |
|
- | 492 | static enum ld_plugin_status |
|
- | 493 | get_view (const void *handle, const void **viewp) |
|
434 | { |
494 | { |
435 | ASSERT (called_plugin); |
495 | ASSERT (called_plugin); |
436 | return LDPS_ERR; |
496 | return LDPS_ERR; |
437 | } |
497 | } |
438 | 498 | ||
439 | /* Release the input file. */ |
499 | /* Release the input file. */ |
440 | static enum ld_plugin_status |
500 | static enum ld_plugin_status |
441 | release_input_file (const void *handle ATTRIBUTE_UNUSED) |
501 | release_input_file (const void *handle) |
442 | { |
502 | { |
443 | ASSERT (called_plugin); |
503 | ASSERT (called_plugin); |
444 | return LDPS_ERR; |
504 | return LDPS_ERR; |
445 | } |
505 | } |
446 | 506 | ||
447 | /* Return TRUE if a defined symbol might be reachable from outside the |
507 | /* Return TRUE if a defined symbol might be reachable from outside the |
448 | universe of claimed objects. */ |
508 | universe of claimed objects. */ |
449 | static inline bfd_boolean |
509 | static inline bfd_boolean |
450 | is_visible_from_outside (struct ld_plugin_symbol *lsym, |
510 | is_visible_from_outside (struct ld_plugin_symbol *lsym, |
451 | struct bfd_link_hash_entry *blhe) |
511 | struct bfd_link_hash_entry *blhe) |
452 | { |
512 | { |
453 | struct bfd_sym_chain *sym; |
513 | struct bfd_sym_chain *sym; |
454 | 514 | ||
455 | if (link_info.relocatable) |
515 | if (bfd_link_relocatable (&link_info)) |
456 | return TRUE; |
516 | return TRUE; |
457 | if (link_info.export_dynamic || !link_info.executable) |
517 | if (link_info.export_dynamic || bfd_link_dll (&link_info)) |
458 | { |
518 | { |
459 | /* Check if symbol is hidden by version script. */ |
519 | /* Check if symbol is hidden by version script. */ |
460 | if (bfd_hide_sym_by_version (link_info.version_info, |
520 | if (bfd_hide_sym_by_version (link_info.version_info, |
461 | blhe->root.string)) |
521 | blhe->root.string)) |
462 | return FALSE; |
522 | return FALSE; |
463 | /* Only ELF symbols really have visibility. */ |
523 | /* Only ELF symbols really have visibility. */ |
464 | if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour) |
524 | if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour) |
465 | { |
525 | { |
466 | struct elf_link_hash_entry *el = (struct elf_link_hash_entry *)blhe; |
526 | struct elf_link_hash_entry *el = (struct elf_link_hash_entry *)blhe; |
467 | int vis = ELF_ST_VISIBILITY (el->other); |
527 | int vis = ELF_ST_VISIBILITY (el->other); |
468 | return vis == STV_DEFAULT || vis == STV_PROTECTED; |
528 | return vis == STV_DEFAULT || vis == STV_PROTECTED; |
469 | } |
529 | } |
470 | /* On non-ELF targets, we can safely make inferences by considering |
530 | /* On non-ELF targets, we can safely make inferences by considering |
471 | what visibility the plugin would have liked to apply when it first |
531 | what visibility the plugin would have liked to apply when it first |
472 | sent us the symbol. During ELF symbol processing, visibility only |
532 | sent us the symbol. During ELF symbol processing, visibility only |
473 | ever becomes more restrictive, not less, when symbols are merged, |
533 | ever becomes more restrictive, not less, when symbols are merged, |
474 | so this is a conservative estimate; it may give false positives, |
534 | so this is a conservative estimate; it may give false positives, |
475 | declaring something visible from outside when it in fact would |
535 | declaring something visible from outside when it in fact would |
476 | not have been, but this will only lead to missed optimisation |
536 | not have been, but this will only lead to missed optimisation |
477 | opportunities during LTRANS at worst; it will not give false |
537 | opportunities during LTRANS at worst; it will not give false |
478 | negatives, which can lead to the disastrous conclusion that the |
538 | negatives, which can lead to the disastrous conclusion that the |
479 | related symbol is IRONLY. (See GCC PR46319 for an example.) */ |
539 | related symbol is IRONLY. (See GCC PR46319 for an example.) */ |
480 | return (lsym->visibility == LDPV_DEFAULT |
540 | return (lsym->visibility == LDPV_DEFAULT |
481 | || lsym->visibility == LDPV_PROTECTED); |
541 | || lsym->visibility == LDPV_PROTECTED); |
482 | } |
542 | } |
483 | 543 | ||
484 | for (sym = &entry_symbol; sym != NULL; sym = sym->next) |
544 | for (sym = &entry_symbol; sym != NULL; sym = sym->next) |
485 | if (sym->name |
545 | if (sym->name |
486 | && strcmp (sym->name, blhe->root.string) == 0) |
546 | && strcmp (sym->name, blhe->root.string) == 0) |
487 | return TRUE; |
547 | return TRUE; |
488 | 548 | ||
489 | return FALSE; |
549 | return FALSE; |
490 | } |
550 | } |
491 | 551 | ||
492 | /* Get the symbol resolution info for a plugin-claimed input file. */ |
552 | /* Get the symbol resolution info for a plugin-claimed input file. */ |
493 | static enum ld_plugin_status |
553 | static enum ld_plugin_status |
494 | get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms, |
554 | get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms, |
495 | int def_ironly_exp) |
555 | int def_ironly_exp) |
496 | { |
556 | { |
- | 557 | const plugin_input_file_t *input = handle; |
|
497 | const bfd *abfd = handle; |
558 | const bfd *abfd = (const bfd *) input->abfd; |
498 | int n; |
559 | int n; |
499 | 560 | ||
500 | ASSERT (called_plugin); |
561 | ASSERT (called_plugin); |
501 | for (n = 0; n < nsyms; n++) |
562 | for (n = 0; n < nsyms; n++) |
502 | { |
563 | { |
503 | struct bfd_link_hash_entry *blhe; |
564 | struct bfd_link_hash_entry *blhe; |
504 | asection *owner_sec; |
565 | asection *owner_sec; |
505 | int res; |
566 | int res; |
506 | 567 | ||
507 | if (syms[n].def != LDPK_UNDEF) |
568 | if (syms[n].def != LDPK_UNDEF) |
508 | blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name, |
569 | blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name, |
509 | FALSE, FALSE, TRUE); |
570 | FALSE, FALSE, TRUE); |
510 | else |
571 | else |
511 | blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd, &link_info, |
572 | blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd, &link_info, |
512 | syms[n].name, FALSE, FALSE, TRUE); |
573 | syms[n].name, FALSE, FALSE, TRUE); |
513 | if (!blhe) |
574 | if (!blhe) |
514 | { |
575 | { |
515 | res = LDPR_UNKNOWN; |
576 | res = LDPR_UNKNOWN; |
516 | goto report_symbol; |
577 | goto report_symbol; |
517 | } |
578 | } |
518 | 579 | ||
519 | /* Determine resolution from blhe type and symbol's original type. */ |
580 | /* Determine resolution from blhe type and symbol's original type. */ |
520 | if (blhe->type == bfd_link_hash_undefined |
581 | if (blhe->type == bfd_link_hash_undefined |
521 | || blhe->type == bfd_link_hash_undefweak) |
582 | || blhe->type == bfd_link_hash_undefweak) |
522 | { |
583 | { |
523 | res = LDPR_UNDEF; |
584 | res = LDPR_UNDEF; |
524 | goto report_symbol; |
585 | goto report_symbol; |
525 | } |
586 | } |
526 | if (blhe->type != bfd_link_hash_defined |
587 | if (blhe->type != bfd_link_hash_defined |
527 | && blhe->type != bfd_link_hash_defweak |
588 | && blhe->type != bfd_link_hash_defweak |
528 | && blhe->type != bfd_link_hash_common) |
589 | && blhe->type != bfd_link_hash_common) |
529 | { |
590 | { |
530 | /* We should not have a new, indirect or warning symbol here. */ |
591 | /* We should not have a new, indirect or warning symbol here. */ |
531 | einfo ("%P%F: %s: plugin symbol table corrupt (sym type %d)\n", |
592 | einfo ("%P%F: %s: plugin symbol table corrupt (sym type %d)\n", |
532 | called_plugin->name, blhe->type); |
593 | called_plugin->name, blhe->type); |
533 | } |
594 | } |
534 | 595 | ||
535 | /* Find out which section owns the symbol. Since it's not undef, |
596 | /* Find out which section owns the symbol. Since it's not undef, |
536 | it must have an owner; if it's not a common symbol, both defs |
597 | it must have an owner; if it's not a common symbol, both defs |
537 | and weakdefs keep it in the same place. */ |
598 | and weakdefs keep it in the same place. */ |
538 | owner_sec = (blhe->type == bfd_link_hash_common |
599 | owner_sec = (blhe->type == bfd_link_hash_common |
539 | ? blhe->u.c.p->section |
600 | ? blhe->u.c.p->section |
540 | : blhe->u.def.section); |
601 | : blhe->u.def.section); |
541 | 602 | ||
542 | 603 | ||
543 | /* If it was originally undefined or common, then it has been |
604 | /* If it was originally undefined or common, then it has been |
544 | resolved; determine how. */ |
605 | resolved; determine how. */ |
545 | if (syms[n].def == LDPK_UNDEF |
606 | if (syms[n].def == LDPK_UNDEF |
546 | || syms[n].def == LDPK_WEAKUNDEF |
607 | || syms[n].def == LDPK_WEAKUNDEF |
547 | || syms[n].def == LDPK_COMMON) |
608 | || syms[n].def == LDPK_COMMON) |
548 | { |
609 | { |
549 | if (owner_sec->owner == link_info.output_bfd) |
610 | if (owner_sec->owner == link_info.output_bfd) |
550 | res = LDPR_RESOLVED_EXEC; |
611 | res = LDPR_RESOLVED_EXEC; |
551 | else if (owner_sec->owner == abfd) |
612 | else if (owner_sec->owner == abfd) |
552 | res = LDPR_PREVAILING_DEF_IRONLY; |
613 | res = LDPR_PREVAILING_DEF_IRONLY; |
553 | else if (is_ir_dummy_bfd (owner_sec->owner)) |
614 | else if (is_ir_dummy_bfd (owner_sec->owner)) |
554 | res = LDPR_RESOLVED_IR; |
615 | res = LDPR_RESOLVED_IR; |
555 | else if (owner_sec->owner != NULL |
616 | else if (owner_sec->owner != NULL |
556 | && (owner_sec->owner->flags & DYNAMIC) != 0) |
617 | && (owner_sec->owner->flags & DYNAMIC) != 0) |
557 | res = LDPR_RESOLVED_DYN; |
618 | res = LDPR_RESOLVED_DYN; |
558 | else |
619 | else |
559 | res = LDPR_RESOLVED_EXEC; |
620 | res = LDPR_RESOLVED_EXEC; |
560 | } |
621 | } |
561 | 622 | ||
562 | /* Was originally def, or weakdef. Does it prevail? If the |
623 | /* Was originally def, or weakdef. Does it prevail? If the |
563 | owner is the original dummy bfd that supplied it, then this |
624 | owner is the original dummy bfd that supplied it, then this |
564 | is the definition that has prevailed. */ |
625 | is the definition that has prevailed. */ |
565 | else if (owner_sec->owner == link_info.output_bfd) |
626 | else if (owner_sec->owner == link_info.output_bfd) |
566 | res = LDPR_PREEMPTED_REG; |
627 | res = LDPR_PREEMPTED_REG; |
567 | else if (owner_sec->owner == abfd) |
628 | else if (owner_sec->owner == abfd) |
568 | res = LDPR_PREVAILING_DEF_IRONLY; |
629 | res = LDPR_PREVAILING_DEF_IRONLY; |
569 | 630 | ||
570 | /* Was originally def, weakdef, or common, but has been pre-empted. */ |
631 | /* Was originally def, weakdef, or common, but has been pre-empted. */ |
571 | else if (is_ir_dummy_bfd (owner_sec->owner)) |
632 | else if (is_ir_dummy_bfd (owner_sec->owner)) |
572 | res = LDPR_PREEMPTED_IR; |
633 | res = LDPR_PREEMPTED_IR; |
573 | else |
634 | else |
574 | res = LDPR_PREEMPTED_REG; |
635 | res = LDPR_PREEMPTED_REG; |
575 | 636 | ||
576 | if (res == LDPR_PREVAILING_DEF_IRONLY) |
637 | if (res == LDPR_PREVAILING_DEF_IRONLY) |
577 | { |
638 | { |
578 | /* We need to know if the sym is referenced from non-IR files. Or |
639 | /* We need to know if the sym is referenced from non-IR files. Or |
579 | even potentially-referenced, perhaps in a future final link if |
640 | even potentially-referenced, perhaps in a future final link if |
580 | this is a partial one, perhaps dynamically at load-time if the |
641 | this is a partial one, perhaps dynamically at load-time if the |
581 | symbol is externally visible. */ |
642 | symbol is externally visible. */ |
582 | if (blhe->non_ir_ref) |
643 | if (blhe->non_ir_ref) |
583 | res = LDPR_PREVAILING_DEF; |
644 | res = LDPR_PREVAILING_DEF; |
584 | else if (is_visible_from_outside (&syms[n], blhe)) |
645 | else if (is_visible_from_outside (&syms[n], blhe)) |
585 | res = def_ironly_exp; |
646 | res = def_ironly_exp; |
586 | } |
647 | } |
587 | 648 | ||
588 | report_symbol: |
649 | report_symbol: |
589 | syms[n].resolution = res; |
650 | syms[n].resolution = res; |
590 | if (report_plugin_symbols) |
651 | if (report_plugin_symbols) |
591 | einfo (_("%P: %B: symbol `%s' " |
652 | einfo (_("%P: %B: symbol `%s' " |
592 | "definition: %d, visibility: %d, resolution: %d\n"), |
653 | "definition: %d, visibility: %d, resolution: %d\n"), |
593 | abfd, syms[n].name, |
654 | abfd, syms[n].name, |
594 | syms[n].def, syms[n].visibility, res); |
655 | syms[n].def, syms[n].visibility, res); |
595 | } |
656 | } |
596 | return LDPS_OK; |
657 | return LDPS_OK; |
597 | } |
658 | } |
598 | 659 | ||
599 | static enum ld_plugin_status |
660 | static enum ld_plugin_status |
600 | get_symbols_v1 (const void *handle, int nsyms, struct ld_plugin_symbol *syms) |
661 | get_symbols_v1 (const void *handle, int nsyms, struct ld_plugin_symbol *syms) |
601 | { |
662 | { |
602 | return get_symbols (handle, nsyms, syms, LDPR_PREVAILING_DEF); |
663 | return get_symbols (handle, nsyms, syms, LDPR_PREVAILING_DEF); |
603 | } |
664 | } |
604 | 665 | ||
605 | static enum ld_plugin_status |
666 | static enum ld_plugin_status |
606 | get_symbols_v2 (const void *handle, int nsyms, struct ld_plugin_symbol *syms) |
667 | get_symbols_v2 (const void *handle, int nsyms, struct ld_plugin_symbol *syms) |
607 | { |
668 | { |
608 | return get_symbols (handle, nsyms, syms, LDPR_PREVAILING_DEF_IRONLY_EXP); |
669 | return get_symbols (handle, nsyms, syms, LDPR_PREVAILING_DEF_IRONLY_EXP); |
609 | } |
670 | } |
610 | 671 | ||
611 | /* Add a new (real) input file generated by a plugin. */ |
672 | /* Add a new (real) input file generated by a plugin. */ |
612 | static enum ld_plugin_status |
673 | static enum ld_plugin_status |
613 | add_input_file (const char *pathname) |
674 | add_input_file (const char *pathname) |
614 | { |
675 | { |
- | 676 | lang_input_statement_type *is; |
|
- | 677 | ||
615 | ASSERT (called_plugin); |
678 | ASSERT (called_plugin); |
616 | if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum, |
679 | is = lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum, |
617 | NULL)) |
680 | NULL); |
- | 681 | if (!is) |
|
618 | return LDPS_ERR; |
682 | return LDPS_ERR; |
- | 683 | is->flags.lto_output = 1; |
|
619 | return LDPS_OK; |
684 | return LDPS_OK; |
620 | } |
685 | } |
621 | 686 | ||
622 | /* Add a new (real) library required by a plugin. */ |
687 | /* Add a new (real) library required by a plugin. */ |
623 | static enum ld_plugin_status |
688 | static enum ld_plugin_status |
624 | add_input_library (const char *pathname) |
689 | add_input_library (const char *pathname) |
625 | { |
690 | { |
- | 691 | lang_input_statement_type *is; |
|
- | 692 | ||
626 | ASSERT (called_plugin); |
693 | ASSERT (called_plugin); |
627 | if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum, |
694 | is = lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum, |
628 | NULL)) |
695 | NULL); |
- | 696 | if (!is) |
|
629 | return LDPS_ERR; |
697 | return LDPS_ERR; |
- | 698 | is->flags.lto_output = 1; |
|
630 | return LDPS_OK; |
699 | return LDPS_OK; |
631 | } |
700 | } |
632 | 701 | ||
633 | /* Set the extra library path to be used by libraries added via |
702 | /* Set the extra library path to be used by libraries added via |
634 | add_input_library. */ |
703 | add_input_library. */ |
635 | static enum ld_plugin_status |
704 | static enum ld_plugin_status |
636 | set_extra_library_path (const char *path) |
705 | set_extra_library_path (const char *path) |
637 | { |
706 | { |
638 | ASSERT (called_plugin); |
707 | ASSERT (called_plugin); |
639 | ldfile_add_library_path (xstrdup (path), FALSE); |
708 | ldfile_add_library_path (xstrdup (path), FALSE); |
640 | return LDPS_OK; |
709 | return LDPS_OK; |
641 | } |
710 | } |
642 | 711 | ||
643 | /* Issue a diagnostic message from a plugin. */ |
712 | /* Issue a diagnostic message from a plugin. */ |
644 | static enum ld_plugin_status |
713 | static enum ld_plugin_status |
645 | message (int level, const char *format, ...) |
714 | message (int level, const char *format, ...) |
646 | { |
715 | { |
647 | va_list args; |
716 | va_list args; |
648 | va_start (args, format); |
717 | va_start (args, format); |
649 | 718 | ||
650 | switch (level) |
719 | switch (level) |
651 | { |
720 | { |
652 | case LDPL_INFO: |
721 | case LDPL_INFO: |
653 | vfinfo (stdout, format, args, FALSE); |
722 | vfinfo (stdout, format, args, FALSE); |
654 | putchar ('\n'); |
723 | putchar ('\n'); |
655 | break; |
724 | break; |
656 | case LDPL_WARNING: |
725 | case LDPL_WARNING: |
- | 726 | { |
|
- | 727 | char *newfmt = ACONCAT (("%P: warning: ", format, "\n", |
|
- | 728 | (const char *) NULL)); |
|
657 | vfinfo (stdout, format, args, TRUE); |
729 | vfinfo (stdout, newfmt, args, TRUE); |
658 | putchar ('\n'); |
730 | } |
659 | break; |
731 | break; |
660 | case LDPL_FATAL: |
732 | case LDPL_FATAL: |
661 | case LDPL_ERROR: |
733 | case LDPL_ERROR: |
662 | default: |
734 | default: |
663 | { |
735 | { |
664 | char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%P%F: " : "%P%X: ", |
736 | char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%P%F" : "%P%X", |
- | 737 | ": error: ", format, "\n", |
|
665 | format, "\n", (const char *) NULL)); |
738 | (const char *) NULL)); |
666 | fflush (stdout); |
739 | fflush (stdout); |
667 | vfinfo (stderr, newfmt, args, TRUE); |
740 | vfinfo (stderr, newfmt, args, TRUE); |
668 | fflush (stderr); |
741 | fflush (stderr); |
669 | } |
742 | } |
670 | break; |
743 | break; |
671 | } |
744 | } |
672 | 745 | ||
673 | va_end (args); |
746 | va_end (args); |
674 | return LDPS_OK; |
747 | return LDPS_OK; |
675 | } |
748 | } |
676 | 749 | ||
677 | /* Helper to size leading part of tv array and set it up. */ |
750 | /* Helper to size leading part of tv array and set it up. */ |
678 | static void |
751 | static void |
679 | set_tv_header (struct ld_plugin_tv *tv) |
752 | set_tv_header (struct ld_plugin_tv *tv) |
680 | { |
753 | { |
681 | size_t i; |
754 | size_t i; |
682 | 755 | ||
683 | /* Version info. */ |
756 | /* Version info. */ |
684 | static const unsigned int major = (unsigned)(BFD_VERSION / 100000000UL); |
757 | static const unsigned int major = (unsigned)(BFD_VERSION / 100000000UL); |
685 | static const unsigned int minor = (unsigned)(BFD_VERSION / 1000000UL) % 100; |
758 | static const unsigned int minor = (unsigned)(BFD_VERSION / 1000000UL) % 100; |
686 | 759 | ||
687 | for (i = 0; i < tv_header_size; i++) |
760 | for (i = 0; i < tv_header_size; i++) |
688 | { |
761 | { |
689 | tv[i].tv_tag = tv_header_tags[i]; |
762 | tv[i].tv_tag = tv_header_tags[i]; |
690 | #define TVU(x) tv[i].tv_u.tv_ ## x |
763 | #define TVU(x) tv[i].tv_u.tv_ ## x |
691 | switch (tv[i].tv_tag) |
764 | switch (tv[i].tv_tag) |
692 | { |
765 | { |
693 | case LDPT_MESSAGE: |
766 | case LDPT_MESSAGE: |
694 | TVU(message) = message; |
767 | TVU(message) = message; |
695 | break; |
768 | break; |
696 | case LDPT_API_VERSION: |
769 | case LDPT_API_VERSION: |
697 | TVU(val) = LD_PLUGIN_API_VERSION; |
770 | TVU(val) = LD_PLUGIN_API_VERSION; |
698 | break; |
771 | break; |
699 | case LDPT_GNU_LD_VERSION: |
772 | case LDPT_GNU_LD_VERSION: |
700 | TVU(val) = major * 100 + minor; |
773 | TVU(val) = major * 100 + minor; |
701 | break; |
774 | break; |
702 | case LDPT_LINKER_OUTPUT: |
775 | case LDPT_LINKER_OUTPUT: |
703 | TVU(val) = (link_info.relocatable |
776 | TVU(val) = (bfd_link_relocatable (&link_info) ? LDPO_REL |
704 | ? LDPO_REL |
- | |
705 | : (link_info.executable |
777 | : bfd_link_pde (&link_info) ? LDPO_EXEC |
706 | ? (link_info.pie ? LDPO_PIE : LDPO_EXEC) |
778 | : bfd_link_pie (&link_info) ? LDPO_PIE |
707 | : LDPO_DYN)); |
779 | : LDPO_DYN); |
708 | break; |
780 | break; |
709 | case LDPT_OUTPUT_NAME: |
781 | case LDPT_OUTPUT_NAME: |
710 | TVU(string) = output_filename; |
782 | TVU(string) = output_filename; |
711 | break; |
783 | break; |
712 | case LDPT_REGISTER_CLAIM_FILE_HOOK: |
784 | case LDPT_REGISTER_CLAIM_FILE_HOOK: |
713 | TVU(register_claim_file) = register_claim_file; |
785 | TVU(register_claim_file) = register_claim_file; |
714 | break; |
786 | break; |
715 | case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: |
787 | case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: |
716 | TVU(register_all_symbols_read) = register_all_symbols_read; |
788 | TVU(register_all_symbols_read) = register_all_symbols_read; |
717 | break; |
789 | break; |
718 | case LDPT_REGISTER_CLEANUP_HOOK: |
790 | case LDPT_REGISTER_CLEANUP_HOOK: |
719 | TVU(register_cleanup) = register_cleanup; |
791 | TVU(register_cleanup) = register_cleanup; |
720 | break; |
792 | break; |
721 | case LDPT_ADD_SYMBOLS: |
793 | case LDPT_ADD_SYMBOLS: |
722 | TVU(add_symbols) = add_symbols; |
794 | TVU(add_symbols) = add_symbols; |
723 | break; |
795 | break; |
724 | case LDPT_GET_INPUT_FILE: |
796 | case LDPT_GET_INPUT_FILE: |
725 | TVU(get_input_file) = get_input_file; |
797 | TVU(get_input_file) = get_input_file; |
726 | break; |
798 | break; |
- | 799 | case LDPT_GET_VIEW: |
|
- | 800 | TVU(get_view) = get_view; |
|
- | 801 | break; |
|
727 | case LDPT_RELEASE_INPUT_FILE: |
802 | case LDPT_RELEASE_INPUT_FILE: |
728 | TVU(release_input_file) = release_input_file; |
803 | TVU(release_input_file) = release_input_file; |
729 | break; |
804 | break; |
730 | case LDPT_GET_SYMBOLS: |
805 | case LDPT_GET_SYMBOLS: |
731 | TVU(get_symbols) = get_symbols_v1; |
806 | TVU(get_symbols) = get_symbols_v1; |
732 | break; |
807 | break; |
733 | case LDPT_GET_SYMBOLS_V2: |
808 | case LDPT_GET_SYMBOLS_V2: |
734 | TVU(get_symbols) = get_symbols_v2; |
809 | TVU(get_symbols) = get_symbols_v2; |
735 | break; |
810 | break; |
736 | case LDPT_ADD_INPUT_FILE: |
811 | case LDPT_ADD_INPUT_FILE: |
737 | TVU(add_input_file) = add_input_file; |
812 | TVU(add_input_file) = add_input_file; |
738 | break; |
813 | break; |
739 | case LDPT_ADD_INPUT_LIBRARY: |
814 | case LDPT_ADD_INPUT_LIBRARY: |
740 | TVU(add_input_library) = add_input_library; |
815 | TVU(add_input_library) = add_input_library; |
741 | break; |
816 | break; |
742 | case LDPT_SET_EXTRA_LIBRARY_PATH: |
817 | case LDPT_SET_EXTRA_LIBRARY_PATH: |
743 | TVU(set_extra_library_path) = set_extra_library_path; |
818 | TVU(set_extra_library_path) = set_extra_library_path; |
744 | break; |
819 | break; |
745 | default: |
820 | default: |
746 | /* Added a new entry to the array without adding |
821 | /* Added a new entry to the array without adding |
747 | a new case to set up its value is a bug. */ |
822 | a new case to set up its value is a bug. */ |
748 | FAIL (); |
823 | FAIL (); |
749 | } |
824 | } |
750 | #undef TVU |
825 | #undef TVU |
751 | } |
826 | } |
752 | } |
827 | } |
753 | 828 | ||
754 | /* Append the per-plugin args list and trailing LDPT_NULL to tv. */ |
829 | /* Append the per-plugin args list and trailing LDPT_NULL to tv. */ |
755 | static void |
830 | static void |
756 | set_tv_plugin_args (plugin_t *plugin, struct ld_plugin_tv *tv) |
831 | set_tv_plugin_args (plugin_t *plugin, struct ld_plugin_tv *tv) |
757 | { |
832 | { |
758 | plugin_arg_t *arg = plugin->args; |
833 | plugin_arg_t *arg = plugin->args; |
759 | while (arg) |
834 | while (arg) |
760 | { |
835 | { |
761 | tv->tv_tag = LDPT_OPTION; |
836 | tv->tv_tag = LDPT_OPTION; |
762 | tv->tv_u.tv_string = arg->arg; |
837 | tv->tv_u.tv_string = arg->arg; |
763 | arg = arg->next; |
838 | arg = arg->next; |
764 | tv++; |
839 | tv++; |
765 | } |
840 | } |
766 | tv->tv_tag = LDPT_NULL; |
841 | tv->tv_tag = LDPT_NULL; |
767 | tv->tv_u.tv_val = 0; |
842 | tv->tv_u.tv_val = 0; |
768 | } |
843 | } |
769 | - | ||
770 | /* Return true if any plugins are active this run. Only valid |
- | |
771 | after options have been processed. */ |
- | |
772 | bfd_boolean |
- | |
773 | plugin_active_plugins_p (void) |
- | |
774 | { |
- | |
775 | return plugins_list != NULL; |
- | |
776 | } |
- | |
777 | 844 | ||
778 | /* Load up and initialise all plugins after argument parsing. */ |
845 | /* Load up and initialise all plugins after argument parsing. */ |
779 | void |
846 | void |
780 | plugin_load_plugins (void) |
847 | plugin_load_plugins (void) |
781 | { |
848 | { |
782 | struct ld_plugin_tv *my_tv; |
849 | struct ld_plugin_tv *my_tv; |
783 | unsigned int max_args = 0; |
850 | unsigned int max_args = 0; |
784 | plugin_t *curplug = plugins_list; |
851 | plugin_t *curplug = plugins_list; |
785 | 852 | ||
786 | /* If there are no plugins, we need do nothing this run. */ |
853 | /* If there are no plugins, we need do nothing this run. */ |
787 | if (!curplug) |
854 | if (!curplug) |
788 | return; |
855 | return; |
789 | 856 | ||
790 | /* First pass over plugins to find max # args needed so that we |
857 | /* First pass over plugins to find max # args needed so that we |
791 | can size and allocate the tv array. */ |
858 | can size and allocate the tv array. */ |
792 | while (curplug) |
859 | while (curplug) |
793 | { |
860 | { |
794 | if (curplug->n_args > max_args) |
861 | if (curplug->n_args > max_args) |
795 | max_args = curplug->n_args; |
862 | max_args = curplug->n_args; |
796 | curplug = curplug->next; |
863 | curplug = curplug->next; |
797 | } |
864 | } |
798 | 865 | ||
799 | /* Allocate tv array and initialise constant part. */ |
866 | /* Allocate tv array and initialise constant part. */ |
800 | my_tv = xmalloc ((max_args + 1 + tv_header_size) * sizeof *my_tv); |
867 | my_tv = xmalloc ((max_args + 1 + tv_header_size) * sizeof *my_tv); |
801 | set_tv_header (my_tv); |
868 | set_tv_header (my_tv); |
802 | 869 | ||
803 | /* Pass over plugins again, activating them. */ |
870 | /* Pass over plugins again, activating them. */ |
804 | curplug = plugins_list; |
871 | curplug = plugins_list; |
805 | while (curplug) |
872 | while (curplug) |
806 | { |
873 | { |
807 | enum ld_plugin_status rv; |
874 | enum ld_plugin_status rv; |
808 | ld_plugin_onload onloadfn; |
875 | ld_plugin_onload onloadfn; |
809 | 876 | ||
810 | onloadfn = (ld_plugin_onload) dlsym (curplug->dlhandle, "onload"); |
877 | onloadfn = (ld_plugin_onload) dlsym (curplug->dlhandle, "onload"); |
811 | if (!onloadfn) |
878 | if (!onloadfn) |
812 | onloadfn = (ld_plugin_onload) dlsym (curplug->dlhandle, "_onload"); |
879 | onloadfn = (ld_plugin_onload) dlsym (curplug->dlhandle, "_onload"); |
813 | if (!onloadfn) |
880 | if (!onloadfn) |
814 | einfo (_("%P%F: %s: error loading plugin: %s\n"), |
881 | einfo (_("%P%F: %s: error loading plugin: %s\n"), |
815 | curplug->name, dlerror ()); |
882 | curplug->name, dlerror ()); |
816 | set_tv_plugin_args (curplug, &my_tv[tv_header_size]); |
883 | set_tv_plugin_args (curplug, &my_tv[tv_header_size]); |
817 | called_plugin = curplug; |
884 | called_plugin = curplug; |
818 | rv = (*onloadfn) (my_tv); |
885 | rv = (*onloadfn) (my_tv); |
819 | called_plugin = NULL; |
886 | called_plugin = NULL; |
820 | if (rv != LDPS_OK) |
887 | if (rv != LDPS_OK) |
821 | einfo (_("%P%F: %s: plugin error: %d\n"), curplug->name, rv); |
888 | einfo (_("%P%F: %s: plugin error: %d\n"), curplug->name, rv); |
822 | curplug = curplug->next; |
889 | curplug = curplug->next; |
823 | } |
890 | } |
824 | 891 | ||
825 | /* Since plugin(s) inited ok, assume they're going to want symbol |
892 | /* Since plugin(s) inited ok, assume they're going to want symbol |
826 | resolutions, which needs us to track which symbols are referenced |
893 | resolutions, which needs us to track which symbols are referenced |
827 | by non-IR files using the linker's notice callback. */ |
894 | by non-IR files using the linker's notice callback. */ |
828 | orig_notice_all = link_info.notice_all; |
895 | orig_notice_all = link_info.notice_all; |
829 | orig_callbacks = link_info.callbacks; |
896 | orig_callbacks = link_info.callbacks; |
830 | plugin_callbacks = *orig_callbacks; |
897 | plugin_callbacks = *orig_callbacks; |
831 | plugin_callbacks.notice = &plugin_notice; |
898 | plugin_callbacks.notice = &plugin_notice; |
832 | link_info.notice_all = TRUE; |
899 | link_info.notice_all = TRUE; |
- | 900 | link_info.lto_plugin_active = TRUE; |
|
833 | link_info.callbacks = &plugin_callbacks; |
901 | link_info.callbacks = &plugin_callbacks; |
- | 902 | ||
- | 903 | register_ld_plugin_object_p (plugin_object_p); |
|
- | 904 | ||
- | 905 | #if HAVE_MMAP && HAVE_GETPAGESIZE |
|
- | 906 | plugin_pagesize = getpagesize (); |
|
- | 907 | #endif |
|
834 | } |
908 | } |
835 | 909 | ||
836 | /* Call 'claim file' hook for all plugins. */ |
910 | /* Call 'claim file' hook for all plugins. */ |
837 | static int |
911 | static int |
838 | plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed) |
912 | plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed) |
839 | { |
913 | { |
840 | plugin_t *curplug = plugins_list; |
914 | plugin_t *curplug = plugins_list; |
841 | *claimed = FALSE; |
915 | *claimed = FALSE; |
842 | if (no_more_claiming) |
916 | if (no_more_claiming) |
843 | return 0; |
917 | return 0; |
844 | while (curplug && !*claimed) |
918 | while (curplug && !*claimed) |
845 | { |
919 | { |
846 | if (curplug->claim_file_handler) |
920 | if (curplug->claim_file_handler) |
847 | { |
921 | { |
848 | enum ld_plugin_status rv; |
922 | enum ld_plugin_status rv; |
849 | called_plugin = curplug; |
923 | called_plugin = curplug; |
850 | rv = (*curplug->claim_file_handler) (file, claimed); |
924 | rv = (*curplug->claim_file_handler) (file, claimed); |
851 | called_plugin = NULL; |
925 | called_plugin = NULL; |
852 | if (rv != LDPS_OK) |
926 | if (rv != LDPS_OK) |
853 | set_plugin_error (curplug->name); |
927 | set_plugin_error (curplug->name); |
854 | } |
928 | } |
855 | curplug = curplug->next; |
929 | curplug = curplug->next; |
856 | } |
930 | } |
857 | return plugin_error_p () ? -1 : 0; |
931 | return plugin_error_p () ? -1 : 0; |
858 | } |
932 | } |
- | 933 | ||
859 | 934 | /* Duplicates a character string with memory attached to ABFD. */ |
|
860 | void |
935 | |
861 | plugin_maybe_claim (struct ld_plugin_input_file *file, |
936 | static char * |
862 | lang_input_statement_type *entry) |
937 | plugin_strdup (bfd *abfd, const char *str) |
- | 938 | { |
|
- | 939 | size_t strlength; |
|
- | 940 | char *copy; |
|
- | 941 | strlength = strlen (str) + 1; |
|
- | 942 | copy = bfd_alloc (abfd, strlength); |
|
- | 943 | if (copy == NULL) |
|
- | 944 | einfo (_("%P%F: plugin_strdup failed to allocate memory: %s\n"), |
|
- | 945 | bfd_get_error ()); |
|
- | 946 | memcpy (copy, str, strlength); |
|
- | 947 | return copy; |
|
- | 948 | } |
|
- | 949 | ||
- | 950 | static const bfd_target * |
|
- | 951 | plugin_object_p (bfd *ibfd) |
|
863 | { |
952 | { |
- | 953 | int claimed; |
|
- | 954 | plugin_input_file_t *input; |
|
- | 955 | off_t offset, filesize; |
|
- | 956 | struct ld_plugin_input_file file; |
|
- | 957 | bfd *abfd; |
|
- | 958 | bfd_boolean inarchive; |
|
- | 959 | const char *name; |
|
- | 960 | int fd; |
|
- | 961 | ||
- | 962 | /* Don't try the dummy object file. */ |
|
- | 963 | if ((ibfd->flags & BFD_PLUGIN) != 0) |
|
- | 964 | return NULL; |
|
- | 965 | ||
- | 966 | if (ibfd->plugin_format != bfd_plugin_uknown) |
|
- | 967 | { |
|
- | 968 | if (ibfd->plugin_format == bfd_plugin_yes) |
|
- | 969 | return ibfd->plugin_dummy_bfd->xvec; |
|
- | 970 | else |
|
- | 971 | return NULL; |
|
- | 972 | } |
|
- | 973 | ||
- | 974 | inarchive = bfd_my_archive (ibfd) != NULL; |
|
- | 975 | name = inarchive ? bfd_my_archive (ibfd)->filename : ibfd->filename; |
|
- | 976 | fd = open (name, O_RDONLY | O_BINARY); |
|
- | 977 | ||
- | 978 | if (fd < 0) |
|
864 | int claimed = 0; |
979 | return NULL; |
865 | 980 | ||
866 | /* We create a dummy BFD, initially empty, to house whatever symbols |
981 | /* We create a dummy BFD, initially empty, to house whatever symbols |
867 | the plugin may want to add. */ |
982 | the plugin may want to add. */ |
868 | file->handle = plugin_get_ir_dummy_bfd (entry->the_bfd->filename, |
983 | abfd = plugin_get_ir_dummy_bfd (ibfd->filename, ibfd); |
- | 984 | ||
- | 985 | input = bfd_alloc (abfd, sizeof (*input)); |
|
- | 986 | if (input == NULL) |
|
- | 987 | einfo (_("%P%F: plugin failed to allocate memory for input: %s\n"), |
|
- | 988 | bfd_get_error ()); |
|
- | 989 | ||
- | 990 | if (inarchive) |
|
- | 991 | { |
|
- | 992 | /* Offset and filesize must refer to the individual archive |
|
- | 993 | member, not the whole file, and must exclude the header. |
|
- | 994 | Fortunately for us, that is how the data is stored in the |
|
- | 995 | origin field of the bfd and in the arelt_data. */ |
|
- | 996 | offset = ibfd->origin; |
|
- | 997 | filesize = arelt_size (ibfd); |
|
- | 998 | } |
|
- | 999 | else |
|
- | 1000 | { |
|
- | 1001 | offset = 0; |
|
- | 1002 | filesize = lseek (fd, 0, SEEK_END); |
|
- | 1003 | ||
- | 1004 | /* We must copy filename attached to ibfd if it is not an archive |
|
- | 1005 | member since it may be freed by bfd_close below. */ |
|
- | 1006 | name = plugin_strdup (abfd, name); |
|
- | 1007 | } |
|
- | 1008 | ||
- | 1009 | file.name = name; |
|
- | 1010 | file.offset = offset; |
|
- | 1011 | file.filesize = filesize; |
|
- | 1012 | file.fd = fd; |
|
- | 1013 | file.handle = input; |
|
- | 1014 | ||
- | 1015 | input->abfd = abfd; |
|
- | 1016 | input->view_buffer.addr = NULL; |
|
- | 1017 | input->view_buffer.filesize = 0; |
|
- | 1018 | input->view_buffer.offset = 0; |
|
869 | entry->the_bfd); |
1019 | input->fd = fd; |
- | 1020 | input->use_mmap = FALSE; |
|
- | 1021 | input->offset = offset; |
|
- | 1022 | input->filesize = filesize; |
|
- | 1023 | input->name = plugin_strdup (abfd, ibfd->filename); |
|
- | 1024 | ||
- | 1025 | claimed = 0; |
|
- | 1026 | ||
870 | if (plugin_call_claim_file (file, &claimed)) |
1027 | if (plugin_call_claim_file (&file, &claimed)) |
871 | einfo (_("%P%F: %s: plugin reported error claiming file\n"), |
1028 | einfo (_("%P%F: %s: plugin reported error claiming file\n"), |
872 | plugin_error_plugin ()); |
1029 | plugin_error_plugin ()); |
- | 1030 | ||
- | 1031 | if (input->fd != -1 && ! bfd_plugin_target_p (ibfd->xvec)) |
|
- | 1032 | { |
|
873 | /* fd belongs to us, not the plugin; but we don't need it. */ |
1033 | /* FIXME: fd belongs to us, not the plugin. GCC plugin, which |
- | 1034 | doesn't need fd after plugin_call_claim_file, doesn't use |
|
- | 1035 | BFD plugin target vector. Since GCC plugin doesn't call |
|
- | 1036 | release_input_file, we close it here. LLVM plugin, which |
|
- | 1037 | needs fd after plugin_call_claim_file and calls |
|
- | 1038 | release_input_file after it is done, uses BFD plugin target |
|
- | 1039 | vector. This scheme doesn't work when a plugin needs fd and |
|
- | 1040 | doesn't use BFD plugin target vector neither. */ |
|
874 | close (file->fd); |
1041 | close (fd); |
- | 1042 | input->fd = -1; |
|
- | 1043 | } |
|
- | 1044 | ||
875 | if (claimed) |
1045 | if (claimed) |
876 | { |
1046 | { |
- | 1047 | ibfd->plugin_format = bfd_plugin_yes; |
|
- | 1048 | ibfd->plugin_dummy_bfd = abfd; |
|
- | 1049 | bfd_make_readable (abfd); |
|
- | 1050 | return abfd->xvec; |
|
- | 1051 | } |
|
- | 1052 | else |
|
- | 1053 | { |
|
- | 1054 | #if HAVE_MMAP |
|
- | 1055 | if (input->use_mmap) |
|
- | 1056 | { |
|
- | 1057 | /* If plugin didn't claim the file, unmap the buffer. */ |
|
- | 1058 | char *addr = input->view_buffer.addr; |
|
- | 1059 | off_t size = input->view_buffer.filesize; |
|
- | 1060 | # if HAVE_GETPAGESIZE |
|
- | 1061 | off_t bias = input->view_buffer.offset % plugin_pagesize; |
|
- | 1062 | size += bias; |
|
- | 1063 | addr -= bias; |
|
- | 1064 | # endif |
|
- | 1065 | munmap (addr, size); |
|
- | 1066 | } |
|
- | 1067 | #endif |
|
- | 1068 | ||
- | 1069 | /* If plugin didn't claim the file, we don't need the dummy bfd. |
|
- | 1070 | Can't avoid speculatively creating it, alas. */ |
|
- | 1071 | ibfd->plugin_format = bfd_plugin_no; |
|
- | 1072 | bfd_close_all_done (abfd); |
|
- | 1073 | return NULL; |
|
- | 1074 | } |
|
- | 1075 | } |
|
- | 1076 | ||
- | 1077 | void |
|
- | 1078 | plugin_maybe_claim (lang_input_statement_type *entry) |
|
- | 1079 | { |
|
- | 1080 | if (plugin_object_p (entry->the_bfd)) |
|
- | 1081 | { |
|
- | 1082 | bfd *abfd = entry->the_bfd->plugin_dummy_bfd; |
|
- | 1083 | ||
877 | /* Discard the real file's BFD and substitute the dummy one. */ |
1084 | /* Discard the real file's BFD and substitute the dummy one. */ |
878 | 1085 | ||
879 | /* BFD archive handling caches elements so we can't call |
1086 | /* BFD archive handling caches elements so we can't call |
880 | bfd_close for archives. */ |
1087 | bfd_close for archives. */ |
881 | if (entry->the_bfd->my_archive == NULL) |
1088 | if (entry->the_bfd->my_archive == NULL) |
882 | bfd_close (entry->the_bfd); |
1089 | bfd_close (entry->the_bfd); |
883 | entry->the_bfd = file->handle; |
1090 | entry->the_bfd = abfd; |
884 | entry->flags.claimed = TRUE; |
1091 | entry->flags.claimed = 1; |
885 | bfd_make_readable (entry->the_bfd); |
- | |
886 | } |
- | |
887 | else |
- | |
888 | { |
- | |
889 | /* If plugin didn't claim the file, we don't need the dummy bfd. |
- | |
890 | Can't avoid speculatively creating it, alas. */ |
- | |
891 | bfd_close_all_done (file->handle); |
- | |
892 | entry->flags.claimed = FALSE; |
- | |
893 | } |
1092 | } |
894 | } |
1093 | } |
895 | 1094 | ||
896 | /* Call 'all symbols read' hook for all plugins. */ |
1095 | /* Call 'all symbols read' hook for all plugins. */ |
897 | int |
1096 | int |
898 | plugin_call_all_symbols_read (void) |
1097 | plugin_call_all_symbols_read (void) |
899 | { |
1098 | { |
900 | plugin_t *curplug = plugins_list; |
1099 | plugin_t *curplug = plugins_list; |
901 | 1100 | ||
902 | /* Disable any further file-claiming. */ |
1101 | /* Disable any further file-claiming. */ |
903 | no_more_claiming = TRUE; |
1102 | no_more_claiming = TRUE; |
904 | 1103 | ||
905 | while (curplug) |
1104 | while (curplug) |
906 | { |
1105 | { |
907 | if (curplug->all_symbols_read_handler) |
1106 | if (curplug->all_symbols_read_handler) |
908 | { |
1107 | { |
909 | enum ld_plugin_status rv; |
1108 | enum ld_plugin_status rv; |
910 | called_plugin = curplug; |
1109 | called_plugin = curplug; |
911 | rv = (*curplug->all_symbols_read_handler) (); |
1110 | rv = (*curplug->all_symbols_read_handler) (); |
912 | called_plugin = NULL; |
1111 | called_plugin = NULL; |
913 | if (rv != LDPS_OK) |
1112 | if (rv != LDPS_OK) |
914 | set_plugin_error (curplug->name); |
1113 | set_plugin_error (curplug->name); |
915 | } |
1114 | } |
916 | curplug = curplug->next; |
1115 | curplug = curplug->next; |
917 | } |
1116 | } |
918 | return plugin_error_p () ? -1 : 0; |
1117 | return plugin_error_p () ? -1 : 0; |
919 | } |
1118 | } |
920 | 1119 | ||
921 | /* Call 'cleanup' hook for all plugins at exit. */ |
1120 | /* Call 'cleanup' hook for all plugins at exit. */ |
922 | void |
1121 | void |
923 | plugin_call_cleanup (void) |
1122 | plugin_call_cleanup (void) |
924 | { |
1123 | { |
925 | plugin_t *curplug = plugins_list; |
1124 | plugin_t *curplug = plugins_list; |
926 | while (curplug) |
1125 | while (curplug) |
927 | { |
1126 | { |
928 | if (curplug->cleanup_handler && !curplug->cleanup_done) |
1127 | if (curplug->cleanup_handler && !curplug->cleanup_done) |
929 | { |
1128 | { |
930 | enum ld_plugin_status rv; |
1129 | enum ld_plugin_status rv; |
931 | curplug->cleanup_done = TRUE; |
1130 | curplug->cleanup_done = TRUE; |
932 | called_plugin = curplug; |
1131 | called_plugin = curplug; |
933 | rv = (*curplug->cleanup_handler) (); |
1132 | rv = (*curplug->cleanup_handler) (); |
934 | called_plugin = NULL; |
1133 | called_plugin = NULL; |
935 | if (rv != LDPS_OK) |
1134 | if (rv != LDPS_OK) |
936 | info_msg (_("%P: %s: error in plugin cleanup: %d (ignored)\n"), |
1135 | info_msg (_("%P: %s: error in plugin cleanup: %d (ignored)\n"), |
937 | curplug->name, rv); |
1136 | curplug->name, rv); |
938 | dlclose (curplug->dlhandle); |
1137 | dlclose (curplug->dlhandle); |
939 | } |
1138 | } |
940 | curplug = curplug->next; |
1139 | curplug = curplug->next; |
941 | } |
1140 | } |
942 | } |
1141 | } |
943 | 1142 | ||
944 | /* To determine which symbols should be resolved LDPR_PREVAILING_DEF |
1143 | /* To determine which symbols should be resolved LDPR_PREVAILING_DEF |
945 | and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as |
1144 | and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as |
946 | the linker adds them to the linker hash table. Mark those |
1145 | the linker adds them to the linker hash table. Mark those |
947 | referenced from a non-IR file with non_ir_ref. We have to |
1146 | referenced from a non-IR file with non_ir_ref. We have to |
948 | notice_all symbols, because we won't necessarily know until later |
1147 | notice_all symbols, because we won't necessarily know until later |
949 | which ones will be contributed by IR files. */ |
1148 | which ones will be contributed by IR files. */ |
950 | static bfd_boolean |
1149 | static bfd_boolean |
951 | plugin_notice (struct bfd_link_info *info, |
1150 | plugin_notice (struct bfd_link_info *info, |
952 | struct bfd_link_hash_entry *h, |
1151 | struct bfd_link_hash_entry *h, |
- | 1152 | struct bfd_link_hash_entry *inh, |
|
953 | bfd *abfd, |
1153 | bfd *abfd, |
954 | asection *section, |
1154 | asection *section, |
955 | bfd_vma value, |
1155 | bfd_vma value, |
956 | flagword flags, |
1156 | flagword flags) |
957 | const char *string) |
- | |
958 | { |
1157 | { |
- | 1158 | struct bfd_link_hash_entry *orig_h = h; |
|
- | 1159 | ||
959 | if (h != NULL) |
1160 | if (h != NULL) |
960 | { |
1161 | { |
961 | bfd *sym_bfd; |
1162 | bfd *sym_bfd; |
- | 1163 | ||
- | 1164 | if (h->type == bfd_link_hash_warning) |
|
- | 1165 | h = h->u.i.link; |
|
962 | 1166 | ||
963 | /* Nothing to do here if this def/ref is from an IR dummy BFD. */ |
1167 | /* Nothing to do here if this def/ref is from an IR dummy BFD. */ |
964 | if (is_ir_dummy_bfd (abfd)) |
1168 | if (is_ir_dummy_bfd (abfd)) |
965 | ; |
1169 | ; |
966 | 1170 | ||
967 | /* Making an indirect symbol counts as a reference unless this |
1171 | /* Making an indirect symbol counts as a reference unless this |
968 | is a brand new symbol. */ |
1172 | is a brand new symbol. */ |
969 | else if (bfd_is_ind_section (section) |
1173 | else if (bfd_is_ind_section (section) |
970 | || (flags & BSF_INDIRECT) != 0) |
1174 | || (flags & BSF_INDIRECT) != 0) |
971 | { |
1175 | { |
- | 1176 | /* ??? Some of this is questionable. See comments in |
|
- | 1177 | _bfd_generic_link_add_one_symbol for case IND. */ |
|
972 | if (h->type != bfd_link_hash_new) |
1178 | if (h->type != bfd_link_hash_new) |
973 | { |
1179 | { |
974 | struct bfd_link_hash_entry *inh; |
- | |
975 | - | ||
976 | h->non_ir_ref = TRUE; |
1180 | h->non_ir_ref = TRUE; |
977 | inh = bfd_wrapped_link_hash_lookup (abfd, info, string, FALSE, |
- | |
978 | FALSE, FALSE); |
- | |
979 | if (inh != NULL) |
- | |
980 | inh->non_ir_ref = TRUE; |
1181 | inh->non_ir_ref = TRUE; |
981 | } |
1182 | } |
- | 1183 | else if (inh->type == bfd_link_hash_new) |
|
- | 1184 | inh->non_ir_ref = TRUE; |
|
982 | } |
1185 | } |
983 | 1186 | ||
984 | /* Nothing to do here for warning symbols. */ |
1187 | /* Nothing to do here for warning symbols. */ |
985 | else if ((flags & BSF_WARNING) != 0) |
1188 | else if ((flags & BSF_WARNING) != 0) |
986 | ; |
1189 | ; |
987 | 1190 | ||
988 | /* Nothing to do here for constructor symbols. */ |
1191 | /* Nothing to do here for constructor symbols. */ |
989 | else if ((flags & BSF_CONSTRUCTOR) != 0) |
1192 | else if ((flags & BSF_CONSTRUCTOR) != 0) |
990 | ; |
1193 | ; |
991 | 1194 | ||
992 | /* If this is a ref, set non_ir_ref. */ |
1195 | /* If this is a ref, set non_ir_ref. */ |
993 | else if (bfd_is_und_section (section)) |
1196 | else if (bfd_is_und_section (section)) |
994 | { |
1197 | { |
995 | /* Replace the undefined dummy bfd with the real one. */ |
1198 | /* Replace the undefined dummy bfd with the real one. */ |
996 | if ((h->type == bfd_link_hash_undefined |
1199 | if ((h->type == bfd_link_hash_undefined |
997 | || h->type == bfd_link_hash_undefweak) |
1200 | || h->type == bfd_link_hash_undefweak) |
998 | && (h->u.undef.abfd == NULL |
1201 | && (h->u.undef.abfd == NULL |
999 | || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0)) |
1202 | || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0)) |
1000 | h->u.undef.abfd = abfd; |
1203 | h->u.undef.abfd = abfd; |
1001 | h->non_ir_ref = TRUE; |
1204 | h->non_ir_ref = TRUE; |
1002 | } |
1205 | } |
1003 | 1206 | ||
1004 | /* Otherwise, it must be a new def. Ensure any symbol defined |
1207 | /* Otherwise, it must be a new def. Ensure any symbol defined |
1005 | in an IR dummy BFD takes on a new value from a real BFD. |
1208 | in an IR dummy BFD takes on a new value from a real BFD. |
1006 | Weak symbols are not normally overridden by a new weak |
1209 | Weak symbols are not normally overridden by a new weak |
1007 | definition, and strong symbols will normally cause multiple |
1210 | definition, and strong symbols will normally cause multiple |
1008 | definition errors. Avoid this by making the symbol appear |
1211 | definition errors. Avoid this by making the symbol appear |
1009 | to be undefined. */ |
1212 | to be undefined. */ |
1010 | else if (((h->type == bfd_link_hash_defweak |
1213 | else if (((h->type == bfd_link_hash_defweak |
1011 | || h->type == bfd_link_hash_defined) |
1214 | || h->type == bfd_link_hash_defined) |
1012 | && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner)) |
1215 | && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner)) |
1013 | || (h->type == bfd_link_hash_common |
1216 | || (h->type == bfd_link_hash_common |
1014 | && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner))) |
1217 | && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner))) |
1015 | { |
1218 | { |
1016 | h->type = bfd_link_hash_undefweak; |
1219 | h->type = bfd_link_hash_undefweak; |
1017 | h->u.undef.abfd = sym_bfd; |
1220 | h->u.undef.abfd = sym_bfd; |
1018 | } |
1221 | } |
1019 | } |
1222 | } |
1020 | 1223 | ||
1021 | /* Continue with cref/nocrossref/trace-sym processing. */ |
1224 | /* Continue with cref/nocrossref/trace-sym processing. */ |
1022 | if (h == NULL |
1225 | if (orig_h == NULL |
1023 | || orig_notice_all |
1226 | || orig_notice_all |
1024 | || (info->notice_hash != NULL |
1227 | || (info->notice_hash != NULL |
1025 | && bfd_hash_lookup (info->notice_hash, h->root.string, |
1228 | && bfd_hash_lookup (info->notice_hash, orig_h->root.string, |
1026 | FALSE, FALSE) != NULL)) |
1229 | FALSE, FALSE) != NULL)) |
1027 | return (*orig_callbacks->notice) (info, h, |
1230 | return (*orig_callbacks->notice) (info, orig_h, inh, |
1028 | abfd, section, value, flags, string); |
1231 | abfd, section, value, flags); |
1029 | return TRUE; |
1232 | return TRUE; |
1030 | } |
1233 | }>>>> |
1031 | - | ||
1032 | /* Return true if bfd is a dynamic library that should be reloaded. */ |
- | |
1033 | - | ||
1034 | bfd_boolean |
- | |
1035 | plugin_should_reload (bfd *abfd) |
- | |
1036 | { |
- | |
1037 | return ((abfd->flags & DYNAMIC) != 0 |
- | |
1038 | && bfd_get_flavour (abfd) == bfd_target_elf_flavour |
- | |
1039 | && bfd_get_format (abfd) == bfd_object |
- | |
1040 | && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0); |
- | |
1041 | }>>> |
- |