1fae548d3Szrj /* Plugin support for BFD.
2fae548d3Szrj Copyright (C) 2009-2020 Free Software Foundation, Inc.
3fae548d3Szrj
4fae548d3Szrj This file is part of BFD, the Binary File Descriptor library.
5fae548d3Szrj
6fae548d3Szrj This program is free software; you can redistribute it and/or modify
7fae548d3Szrj it under the terms of the GNU General Public License as published by
8fae548d3Szrj the Free Software Foundation; either version 3 of the License, or
9fae548d3Szrj (at your option) any later version.
10fae548d3Szrj
11fae548d3Szrj This program is distributed in the hope that it will be useful,
12fae548d3Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
13fae548d3Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14fae548d3Szrj GNU General Public License for more details.
15fae548d3Szrj
16fae548d3Szrj You should have received a copy of the GNU General Public License
17fae548d3Szrj along with this program; if not, write to the Free Software
18fae548d3Szrj Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19fae548d3Szrj MA 02110-1301, USA. */
20fae548d3Szrj
21fae548d3Szrj #include "sysdep.h"
22fae548d3Szrj #include "bfd.h"
23fae548d3Szrj
24fae548d3Szrj #if BFD_SUPPORTS_PLUGINS
25fae548d3Szrj
26fae548d3Szrj #include <assert.h>
27fae548d3Szrj #ifdef HAVE_DLFCN_H
28fae548d3Szrj #include <dlfcn.h>
29fae548d3Szrj #elif defined (HAVE_WINDOWS_H)
30fae548d3Szrj #include <windows.h>
31fae548d3Szrj #else
32fae548d3Szrj #error Unknown how to handle dynamic-load-libraries.
33fae548d3Szrj #endif
34fae548d3Szrj #include <stdarg.h>
35fae548d3Szrj #include "plugin-api.h"
36fae548d3Szrj #include "plugin.h"
37fae548d3Szrj #include "libbfd.h"
38fae548d3Szrj #include "libiberty.h"
39fae548d3Szrj #include <dirent.h>
40fae548d3Szrj
41fae548d3Szrj #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
42fae548d3Szrj
43fae548d3Szrj #define RTLD_NOW 0 /* Dummy value. */
44fae548d3Szrj
45fae548d3Szrj static void *
dlopen(const char * file,int mode ATTRIBUTE_UNUSED)46fae548d3Szrj dlopen (const char *file, int mode ATTRIBUTE_UNUSED)
47fae548d3Szrj {
48fae548d3Szrj return LoadLibrary (file);
49fae548d3Szrj }
50fae548d3Szrj
51fae548d3Szrj static void *
dlsym(void * handle,const char * name)52fae548d3Szrj dlsym (void *handle, const char *name)
53fae548d3Szrj {
54fae548d3Szrj return GetProcAddress (handle, name);
55fae548d3Szrj }
56fae548d3Szrj
57fae548d3Szrj static int ATTRIBUTE_UNUSED
dlclose(void * handle)58fae548d3Szrj dlclose (void *handle)
59fae548d3Szrj {
60fae548d3Szrj FreeLibrary (handle);
61fae548d3Szrj return 0;
62fae548d3Szrj }
63fae548d3Szrj
64fae548d3Szrj static const char *
dlerror(void)65fae548d3Szrj dlerror (void)
66fae548d3Szrj {
67fae548d3Szrj return "Unable to load DLL.";
68fae548d3Szrj }
69fae548d3Szrj
70fae548d3Szrj #endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) */
71fae548d3Szrj
72fae548d3Szrj #define bfd_plugin_close_and_cleanup _bfd_generic_close_and_cleanup
73fae548d3Szrj #define bfd_plugin_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
74fae548d3Szrj #define bfd_plugin_new_section_hook _bfd_generic_new_section_hook
75fae548d3Szrj #define bfd_plugin_get_section_contents _bfd_generic_get_section_contents
76fae548d3Szrj #define bfd_plugin_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
77fae548d3Szrj #define bfd_plugin_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
78fae548d3Szrj #define bfd_plugin_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
79fae548d3Szrj #define bfd_plugin_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
80fae548d3Szrj #define bfd_plugin_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
81fae548d3Szrj #define bfd_plugin_core_file_matches_executable_p generic_core_file_matches_executable_p
82fae548d3Szrj #define bfd_plugin_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
83fae548d3Szrj #define bfd_plugin_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false
84fae548d3Szrj #define bfd_plugin_get_lineno _bfd_nosymbols_get_lineno
85fae548d3Szrj #define bfd_plugin_find_nearest_line _bfd_nosymbols_find_nearest_line
86fae548d3Szrj #define bfd_plugin_find_line _bfd_nosymbols_find_line
87fae548d3Szrj #define bfd_plugin_find_inliner_info _bfd_nosymbols_find_inliner_info
88fae548d3Szrj #define bfd_plugin_get_symbol_version_string _bfd_nosymbols_get_symbol_version_string
89fae548d3Szrj #define bfd_plugin_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
90fae548d3Szrj #define bfd_plugin_read_minisymbols _bfd_generic_read_minisymbols
91fae548d3Szrj #define bfd_plugin_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
92fae548d3Szrj #define bfd_plugin_set_arch_mach bfd_default_set_arch_mach
93fae548d3Szrj #define bfd_plugin_set_section_contents _bfd_generic_set_section_contents
94fae548d3Szrj #define bfd_plugin_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
95fae548d3Szrj #define bfd_plugin_bfd_relax_section bfd_generic_relax_section
96fae548d3Szrj #define bfd_plugin_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
97fae548d3Szrj #define bfd_plugin_bfd_link_add_symbols _bfd_generic_link_add_symbols
98fae548d3Szrj #define bfd_plugin_bfd_link_just_syms _bfd_generic_link_just_syms
99fae548d3Szrj #define bfd_plugin_bfd_final_link _bfd_generic_final_link
100fae548d3Szrj #define bfd_plugin_bfd_link_split_section _bfd_generic_link_split_section
101fae548d3Szrj #define bfd_plugin_bfd_gc_sections bfd_generic_gc_sections
102fae548d3Szrj #define bfd_plugin_bfd_lookup_section_flags bfd_generic_lookup_section_flags
103fae548d3Szrj #define bfd_plugin_bfd_merge_sections bfd_generic_merge_sections
104fae548d3Szrj #define bfd_plugin_bfd_is_group_section bfd_generic_is_group_section
105fae548d3Szrj #define bfd_plugin_bfd_group_name bfd_generic_group_name
106fae548d3Szrj #define bfd_plugin_bfd_discard_group bfd_generic_discard_group
107fae548d3Szrj #define bfd_plugin_section_already_linked _bfd_generic_section_already_linked
108fae548d3Szrj #define bfd_plugin_bfd_define_common_symbol bfd_generic_define_common_symbol
109fae548d3Szrj #define bfd_plugin_bfd_link_hide_symbol _bfd_generic_link_hide_symbol
110fae548d3Szrj #define bfd_plugin_bfd_define_start_stop bfd_generic_define_start_stop
111fae548d3Szrj #define bfd_plugin_bfd_copy_link_hash_symbol_type _bfd_generic_copy_link_hash_symbol_type
112fae548d3Szrj #define bfd_plugin_bfd_link_check_relocs _bfd_generic_link_check_relocs
113fae548d3Szrj
114fae548d3Szrj static enum ld_plugin_status
message(int level ATTRIBUTE_UNUSED,const char * format,...)115fae548d3Szrj message (int level ATTRIBUTE_UNUSED,
116fae548d3Szrj const char * format, ...)
117fae548d3Szrj {
118fae548d3Szrj va_list args;
119fae548d3Szrj va_start (args, format);
120fae548d3Szrj printf ("bfd plugin: ");
121fae548d3Szrj vprintf (format, args);
122fae548d3Szrj putchar ('\n');
123fae548d3Szrj va_end (args);
124fae548d3Szrj return LDPS_OK;
125fae548d3Szrj }
126fae548d3Szrj
127fae548d3Szrj /* Register a claim-file handler. */
128fae548d3Szrj static ld_plugin_claim_file_handler claim_file = NULL;
129fae548d3Szrj
130fae548d3Szrj static enum ld_plugin_status
register_claim_file(ld_plugin_claim_file_handler handler)131fae548d3Szrj register_claim_file (ld_plugin_claim_file_handler handler)
132fae548d3Szrj {
133fae548d3Szrj claim_file = handler;
134fae548d3Szrj return LDPS_OK;
135fae548d3Szrj }
136fae548d3Szrj
137fae548d3Szrj static enum ld_plugin_status
add_symbols(void * handle,int nsyms,const struct ld_plugin_symbol * syms)138fae548d3Szrj add_symbols (void * handle,
139fae548d3Szrj int nsyms,
140fae548d3Szrj const struct ld_plugin_symbol * syms)
141fae548d3Szrj {
142fae548d3Szrj bfd *abfd = handle;
143fae548d3Szrj struct plugin_data_struct *plugin_data =
144fae548d3Szrj bfd_alloc (abfd, sizeof (plugin_data_struct));
145fae548d3Szrj
146fae548d3Szrj plugin_data->nsyms = nsyms;
147fae548d3Szrj plugin_data->syms = syms;
148fae548d3Szrj
149fae548d3Szrj if (nsyms != 0)
150fae548d3Szrj abfd->flags |= HAS_SYMS;
151fae548d3Szrj
152fae548d3Szrj abfd->tdata.plugin_data = plugin_data;
153fae548d3Szrj return LDPS_OK;
154fae548d3Szrj }
155fae548d3Szrj
156fae548d3Szrj static const char *plugin_program_name;
157fae548d3Szrj
158fae548d3Szrj void
bfd_plugin_set_program_name(const char * program_name)159fae548d3Szrj bfd_plugin_set_program_name (const char *program_name)
160fae548d3Szrj {
161fae548d3Szrj plugin_program_name = program_name;
162fae548d3Szrj }
163fae548d3Szrj
164fae548d3Szrj int
bfd_plugin_open_input(bfd * ibfd,struct ld_plugin_input_file * file)165fae548d3Szrj bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file)
166fae548d3Szrj {
167fae548d3Szrj bfd *iobfd;
168fae548d3Szrj
169fae548d3Szrj iobfd = ibfd;
170fae548d3Szrj while (iobfd->my_archive
171fae548d3Szrj && !bfd_is_thin_archive (iobfd->my_archive))
172fae548d3Szrj iobfd = iobfd->my_archive;
173fae548d3Szrj file->name = iobfd->filename;
174fae548d3Szrj
175fae548d3Szrj if (!iobfd->iostream && !bfd_open_file (iobfd))
176fae548d3Szrj return 0;
177fae548d3Szrj
178fae548d3Szrj /* The plugin API expects that the file descriptor won't be closed
179fae548d3Szrj and reused as done by the bfd file cache. So open it again.
180fae548d3Szrj dup isn't good enough. plugin IO uses lseek/read while BFD uses
181fae548d3Szrj fseek/fread. It isn't wise to mix the unistd and stdio calls on
182fae548d3Szrj the same underlying file descriptor. */
183fae548d3Szrj file->fd = open (file->name, O_RDONLY | O_BINARY);
184fae548d3Szrj if (file->fd < 0)
185fae548d3Szrj return 0;
186fae548d3Szrj
187fae548d3Szrj if (iobfd == ibfd)
188fae548d3Szrj {
189fae548d3Szrj struct stat stat_buf;
190fae548d3Szrj
191fae548d3Szrj if (fstat (file->fd, &stat_buf))
192fae548d3Szrj {
193fae548d3Szrj close(file->fd);
194fae548d3Szrj return 0;
195fae548d3Szrj }
196fae548d3Szrj
197fae548d3Szrj file->offset = 0;
198fae548d3Szrj file->filesize = stat_buf.st_size;
199fae548d3Szrj }
200fae548d3Szrj else
201fae548d3Szrj {
202fae548d3Szrj file->offset = ibfd->origin;
203fae548d3Szrj file->filesize = arelt_size (ibfd);
204fae548d3Szrj }
205fae548d3Szrj return 1;
206fae548d3Szrj }
207fae548d3Szrj
208fae548d3Szrj static int
try_claim(bfd * abfd)209fae548d3Szrj try_claim (bfd *abfd)
210fae548d3Szrj {
211fae548d3Szrj int claimed = 0;
212fae548d3Szrj struct ld_plugin_input_file file;
213fae548d3Szrj
214fae548d3Szrj file.handle = abfd;
215fae548d3Szrj if (!bfd_plugin_open_input (abfd, &file))
216fae548d3Szrj return 0;
217fae548d3Szrj if (claim_file)
218fae548d3Szrj claim_file (&file, &claimed);
219fae548d3Szrj close (file.fd);
220fae548d3Szrj return claimed;
221fae548d3Szrj }
222fae548d3Szrj
223fae548d3Szrj struct plugin_list_entry
224fae548d3Szrj {
225fae548d3Szrj void * handle;
226fae548d3Szrj ld_plugin_claim_file_handler claim_file;
227fae548d3Szrj struct plugin_list_entry * next;
228fae548d3Szrj };
229fae548d3Szrj
230fae548d3Szrj static struct plugin_list_entry * plugin_list = NULL;
231fae548d3Szrj
232fae548d3Szrj static int
try_load_plugin(const char * pname,bfd * abfd,int * has_plugin_p)233fae548d3Szrj try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
234fae548d3Szrj {
235fae548d3Szrj void *plugin_handle = NULL;
236fae548d3Szrj struct ld_plugin_tv tv[4];
237fae548d3Szrj int i;
238fae548d3Szrj ld_plugin_onload onload;
239fae548d3Szrj enum ld_plugin_status status;
240fae548d3Szrj struct plugin_list_entry *plugin_list_iter;
241fae548d3Szrj
242fae548d3Szrj *has_plugin_p = 0;
243fae548d3Szrj
244fae548d3Szrj plugin_handle = dlopen (pname, RTLD_NOW);
245fae548d3Szrj if (!plugin_handle)
246fae548d3Szrj {
247fae548d3Szrj _bfd_error_handler ("%s\n", dlerror ());
248fae548d3Szrj return 0;
249fae548d3Szrj }
250fae548d3Szrj
251fae548d3Szrj for (plugin_list_iter = plugin_list;
252fae548d3Szrj plugin_list_iter;
253fae548d3Szrj plugin_list_iter = plugin_list_iter->next)
254fae548d3Szrj {
255fae548d3Szrj if (plugin_handle == plugin_list_iter->handle)
256fae548d3Szrj {
257fae548d3Szrj dlclose (plugin_handle);
258fae548d3Szrj if (!plugin_list_iter->claim_file)
259fae548d3Szrj return 0;
260fae548d3Szrj
261fae548d3Szrj register_claim_file (plugin_list_iter->claim_file);
262fae548d3Szrj goto have_claim_file;
263fae548d3Szrj }
264fae548d3Szrj }
265fae548d3Szrj
266fae548d3Szrj plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter);
267fae548d3Szrj if (plugin_list_iter == NULL)
268fae548d3Szrj return 0;
269fae548d3Szrj plugin_list_iter->handle = plugin_handle;
270fae548d3Szrj plugin_list_iter->claim_file = NULL;
271fae548d3Szrj plugin_list_iter->next = plugin_list;
272fae548d3Szrj plugin_list = plugin_list_iter;
273fae548d3Szrj
274fae548d3Szrj onload = dlsym (plugin_handle, "onload");
275fae548d3Szrj if (!onload)
276fae548d3Szrj return 0;
277fae548d3Szrj
278fae548d3Szrj i = 0;
279fae548d3Szrj tv[i].tv_tag = LDPT_MESSAGE;
280fae548d3Szrj tv[i].tv_u.tv_message = message;
281fae548d3Szrj
282fae548d3Szrj ++i;
283fae548d3Szrj tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK;
284fae548d3Szrj tv[i].tv_u.tv_register_claim_file = register_claim_file;
285fae548d3Szrj
286fae548d3Szrj ++i;
287fae548d3Szrj tv[i].tv_tag = LDPT_ADD_SYMBOLS;
288fae548d3Szrj tv[i].tv_u.tv_add_symbols = add_symbols;
289fae548d3Szrj
290fae548d3Szrj ++i;
291fae548d3Szrj tv[i].tv_tag = LDPT_NULL;
292fae548d3Szrj tv[i].tv_u.tv_val = 0;
293fae548d3Szrj
294fae548d3Szrj status = (*onload)(tv);
295fae548d3Szrj
296fae548d3Szrj if (status != LDPS_OK)
297fae548d3Szrj return 0;
298fae548d3Szrj
299fae548d3Szrj plugin_list_iter->claim_file = claim_file;
300fae548d3Szrj
301fae548d3Szrj have_claim_file:
302fae548d3Szrj *has_plugin_p = 1;
303fae548d3Szrj
304fae548d3Szrj abfd->plugin_format = bfd_plugin_no;
305fae548d3Szrj
306fae548d3Szrj if (!claim_file)
307fae548d3Szrj return 0;
308fae548d3Szrj
309fae548d3Szrj if (!try_claim (abfd))
310fae548d3Szrj return 0;
311fae548d3Szrj
312fae548d3Szrj abfd->plugin_format = bfd_plugin_yes;
313fae548d3Szrj return 1;
314fae548d3Szrj }
315fae548d3Szrj
316fae548d3Szrj /* There may be plugin libraries in lib/bfd-plugins. */
317fae548d3Szrj
318fae548d3Szrj static int has_plugin = -1;
319fae548d3Szrj
320fae548d3Szrj static const bfd_target *(*ld_plugin_object_p) (bfd *);
321fae548d3Szrj
322fae548d3Szrj static const char *plugin_name;
323fae548d3Szrj
324fae548d3Szrj void
bfd_plugin_set_plugin(const char * p)325fae548d3Szrj bfd_plugin_set_plugin (const char *p)
326fae548d3Szrj {
327fae548d3Szrj plugin_name = p;
328fae548d3Szrj has_plugin = p != NULL;
329fae548d3Szrj }
330fae548d3Szrj
331fae548d3Szrj /* Return TRUE if a plugin library is used. */
332fae548d3Szrj
333fae548d3Szrj bfd_boolean
bfd_plugin_specified_p(void)334fae548d3Szrj bfd_plugin_specified_p (void)
335fae548d3Szrj {
336fae548d3Szrj return has_plugin > 0;
337fae548d3Szrj }
338fae548d3Szrj
339fae548d3Szrj /* Return TRUE if ABFD can be claimed by linker LTO plugin. */
340fae548d3Szrj
341fae548d3Szrj bfd_boolean
bfd_link_plugin_object_p(bfd * abfd)342fae548d3Szrj bfd_link_plugin_object_p (bfd *abfd)
343fae548d3Szrj {
344fae548d3Szrj if (ld_plugin_object_p)
345fae548d3Szrj return ld_plugin_object_p (abfd) != NULL;
346fae548d3Szrj return FALSE;
347fae548d3Szrj }
348fae548d3Szrj
349fae548d3Szrj extern const bfd_target plugin_vec;
350fae548d3Szrj
351fae548d3Szrj /* Return TRUE if TARGET is a pointer to plugin_vec. */
352fae548d3Szrj
353fae548d3Szrj bfd_boolean
bfd_plugin_target_p(const bfd_target * target)354fae548d3Szrj bfd_plugin_target_p (const bfd_target *target)
355fae548d3Szrj {
356fae548d3Szrj return target == &plugin_vec;
357fae548d3Szrj }
358fae548d3Szrj
359fae548d3Szrj /* Register OBJECT_P to be used by bfd_plugin_object_p. */
360fae548d3Szrj
361fae548d3Szrj void
register_ld_plugin_object_p(const bfd_target * (* object_p)(bfd *))362fae548d3Szrj register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *))
363fae548d3Szrj {
364fae548d3Szrj ld_plugin_object_p = object_p;
365fae548d3Szrj }
366fae548d3Szrj
367fae548d3Szrj static int
load_plugin(bfd * abfd)368fae548d3Szrj load_plugin (bfd *abfd)
369fae548d3Szrj {
370fae548d3Szrj /* The intent was to search ${libdir}/bfd-plugins for plugins, but
371fae548d3Szrj unfortunately the original implementation wasn't precisely that
372fae548d3Szrj when configuring binutils using --libdir. Search in the proper
373fae548d3Szrj path first, then the old one for backwards compatibility. */
374fae548d3Szrj static const char *path[]
375*a72d4fb1Szrj = { PLUGINLIBDIR "/bfd-plugins", BINDIR RELPLUGINDIR};
376fae548d3Szrj struct stat last_st;
377fae548d3Szrj int found = 0;
378fae548d3Szrj unsigned int i;
379fae548d3Szrj
380fae548d3Szrj if (!has_plugin)
381fae548d3Szrj return found;
382fae548d3Szrj
383fae548d3Szrj if (plugin_name)
384fae548d3Szrj return try_load_plugin (plugin_name, abfd, &has_plugin);
385fae548d3Szrj
386fae548d3Szrj if (plugin_program_name == NULL)
387fae548d3Szrj return found;
388fae548d3Szrj
389fae548d3Szrj /* Try not to search the same dir twice, by looking at st_dev and
390fae548d3Szrj st_ino for the dir. If we are on a file system that always sets
391fae548d3Szrj st_ino to zero or the actual st_ino is zero we might waste some
392fae548d3Szrj time, but that doesn't matter too much. */
393fae548d3Szrj last_st.st_dev = 0;
394fae548d3Szrj last_st.st_ino = 0;
395fae548d3Szrj for (i = 0; i < sizeof (path) / sizeof (path[0]); i++)
396fae548d3Szrj {
397fae548d3Szrj char *plugin_dir = make_relative_prefix (plugin_program_name,
398fae548d3Szrj BINDIR,
399fae548d3Szrj path[i]);
400fae548d3Szrj if (plugin_dir)
401fae548d3Szrj {
402fae548d3Szrj struct stat st;
403fae548d3Szrj DIR *d;
404fae548d3Szrj
405fae548d3Szrj if (stat (plugin_dir, &st) == 0
406fae548d3Szrj && S_ISDIR (st.st_mode)
407fae548d3Szrj && !(last_st.st_dev == st.st_dev
408fae548d3Szrj && last_st.st_ino == st.st_ino
409fae548d3Szrj && st.st_ino != 0)
410fae548d3Szrj && (d = opendir (plugin_dir)) != NULL)
411fae548d3Szrj {
412fae548d3Szrj struct dirent *ent;
413fae548d3Szrj
414fae548d3Szrj last_st.st_dev = st.st_dev;
415fae548d3Szrj last_st.st_ino = st.st_ino;
416fae548d3Szrj while ((ent = readdir (d)) != NULL)
417fae548d3Szrj {
418fae548d3Szrj char *full_name;
419fae548d3Szrj
420fae548d3Szrj full_name = concat (plugin_dir, "/", ent->d_name, NULL);
421fae548d3Szrj if (stat (full_name, &st) == 0 && S_ISREG (st.st_mode))
422fae548d3Szrj {
423fae548d3Szrj int valid_plugin;
424fae548d3Szrj
425fae548d3Szrj found = try_load_plugin (full_name, abfd, &valid_plugin);
426fae548d3Szrj if (has_plugin <= 0)
427fae548d3Szrj has_plugin = valid_plugin;
428fae548d3Szrj }
429fae548d3Szrj free (full_name);
430fae548d3Szrj if (found)
431fae548d3Szrj break;
432fae548d3Szrj }
433fae548d3Szrj closedir (d);
434fae548d3Szrj }
435fae548d3Szrj free (plugin_dir);
436fae548d3Szrj }
437fae548d3Szrj if (found)
438fae548d3Szrj break;
439fae548d3Szrj }
440fae548d3Szrj
441fae548d3Szrj return found;
442fae548d3Szrj }
443fae548d3Szrj
444fae548d3Szrj
445fae548d3Szrj static const bfd_target *
bfd_plugin_object_p(bfd * abfd)446fae548d3Szrj bfd_plugin_object_p (bfd *abfd)
447fae548d3Szrj {
448fae548d3Szrj if (ld_plugin_object_p)
449fae548d3Szrj return ld_plugin_object_p (abfd);
450fae548d3Szrj
451fae548d3Szrj if (abfd->plugin_format == bfd_plugin_unknown && !load_plugin (abfd))
452fae548d3Szrj return NULL;
453fae548d3Szrj
454fae548d3Szrj return abfd->plugin_format == bfd_plugin_yes ? abfd->xvec : NULL;
455fae548d3Szrj }
456fae548d3Szrj
457fae548d3Szrj /* Copy any private info we understand from the input bfd
458fae548d3Szrj to the output bfd. */
459fae548d3Szrj
460fae548d3Szrj static bfd_boolean
bfd_plugin_bfd_copy_private_bfd_data(bfd * ibfd ATTRIBUTE_UNUSED,bfd * obfd ATTRIBUTE_UNUSED)461fae548d3Szrj bfd_plugin_bfd_copy_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED,
462fae548d3Szrj bfd *obfd ATTRIBUTE_UNUSED)
463fae548d3Szrj {
464fae548d3Szrj BFD_ASSERT (0);
465fae548d3Szrj return TRUE;
466fae548d3Szrj }
467fae548d3Szrj
468fae548d3Szrj /* Copy any private info we understand from the input section
469fae548d3Szrj to the output section. */
470fae548d3Szrj
471fae548d3Szrj static bfd_boolean
bfd_plugin_bfd_copy_private_section_data(bfd * ibfd ATTRIBUTE_UNUSED,asection * isection ATTRIBUTE_UNUSED,bfd * obfd ATTRIBUTE_UNUSED,asection * osection ATTRIBUTE_UNUSED)472fae548d3Szrj bfd_plugin_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
473fae548d3Szrj asection *isection ATTRIBUTE_UNUSED,
474fae548d3Szrj bfd *obfd ATTRIBUTE_UNUSED,
475fae548d3Szrj asection *osection ATTRIBUTE_UNUSED)
476fae548d3Szrj {
477fae548d3Szrj BFD_ASSERT (0);
478fae548d3Szrj return TRUE;
479fae548d3Szrj }
480fae548d3Szrj
481fae548d3Szrj /* Copy any private info we understand from the input symbol
482fae548d3Szrj to the output symbol. */
483fae548d3Szrj
484fae548d3Szrj static bfd_boolean
bfd_plugin_bfd_copy_private_symbol_data(bfd * ibfd ATTRIBUTE_UNUSED,asymbol * isymbol ATTRIBUTE_UNUSED,bfd * obfd ATTRIBUTE_UNUSED,asymbol * osymbol ATTRIBUTE_UNUSED)485fae548d3Szrj bfd_plugin_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
486fae548d3Szrj asymbol *isymbol ATTRIBUTE_UNUSED,
487fae548d3Szrj bfd *obfd ATTRIBUTE_UNUSED,
488fae548d3Szrj asymbol *osymbol ATTRIBUTE_UNUSED)
489fae548d3Szrj {
490fae548d3Szrj BFD_ASSERT (0);
491fae548d3Szrj return TRUE;
492fae548d3Szrj }
493fae548d3Szrj
494fae548d3Szrj static bfd_boolean
bfd_plugin_bfd_print_private_bfd_data(bfd * abfd ATTRIBUTE_UNUSED,PTR ptr ATTRIBUTE_UNUSED)495fae548d3Szrj bfd_plugin_bfd_print_private_bfd_data (bfd *abfd ATTRIBUTE_UNUSED, PTR ptr ATTRIBUTE_UNUSED)
496fae548d3Szrj {
497fae548d3Szrj BFD_ASSERT (0);
498fae548d3Szrj return TRUE;
499fae548d3Szrj }
500fae548d3Szrj
501fae548d3Szrj static char *
bfd_plugin_core_file_failing_command(bfd * abfd ATTRIBUTE_UNUSED)502fae548d3Szrj bfd_plugin_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
503fae548d3Szrj {
504fae548d3Szrj BFD_ASSERT (0);
505fae548d3Szrj return NULL;
506fae548d3Szrj }
507fae548d3Szrj
508fae548d3Szrj static int
bfd_plugin_core_file_failing_signal(bfd * abfd ATTRIBUTE_UNUSED)509fae548d3Szrj bfd_plugin_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
510fae548d3Szrj {
511fae548d3Szrj BFD_ASSERT (0);
512fae548d3Szrj return 0;
513fae548d3Szrj }
514fae548d3Szrj
515fae548d3Szrj static int
bfd_plugin_core_file_pid(bfd * abfd ATTRIBUTE_UNUSED)516fae548d3Szrj bfd_plugin_core_file_pid (bfd *abfd ATTRIBUTE_UNUSED)
517fae548d3Szrj {
518fae548d3Szrj BFD_ASSERT (0);
519fae548d3Szrj return 0;
520fae548d3Szrj }
521fae548d3Szrj
522fae548d3Szrj static long
bfd_plugin_get_symtab_upper_bound(bfd * abfd)523fae548d3Szrj bfd_plugin_get_symtab_upper_bound (bfd *abfd)
524fae548d3Szrj {
525fae548d3Szrj struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
526fae548d3Szrj long nsyms = plugin_data->nsyms;
527fae548d3Szrj
528fae548d3Szrj BFD_ASSERT (nsyms >= 0);
529fae548d3Szrj
530fae548d3Szrj return ((nsyms + 1) * sizeof (asymbol *));
531fae548d3Szrj }
532fae548d3Szrj
533fae548d3Szrj static flagword
convert_flags(const struct ld_plugin_symbol * sym)534fae548d3Szrj convert_flags (const struct ld_plugin_symbol *sym)
535fae548d3Szrj {
536fae548d3Szrj switch (sym->def)
537fae548d3Szrj {
538fae548d3Szrj case LDPK_DEF:
539fae548d3Szrj case LDPK_COMMON:
540fae548d3Szrj case LDPK_UNDEF:
541fae548d3Szrj return BSF_GLOBAL;
542fae548d3Szrj
543fae548d3Szrj case LDPK_WEAKUNDEF:
544fae548d3Szrj case LDPK_WEAKDEF:
545fae548d3Szrj return BSF_GLOBAL | BSF_WEAK;
546fae548d3Szrj
547fae548d3Szrj default:
548fae548d3Szrj BFD_ASSERT (0);
549fae548d3Szrj return 0;
550fae548d3Szrj }
551fae548d3Szrj }
552fae548d3Szrj
553fae548d3Szrj static long
bfd_plugin_canonicalize_symtab(bfd * abfd,asymbol ** alocation)554fae548d3Szrj bfd_plugin_canonicalize_symtab (bfd *abfd,
555fae548d3Szrj asymbol **alocation)
556fae548d3Szrj {
557fae548d3Szrj struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
558fae548d3Szrj long nsyms = plugin_data->nsyms;
559fae548d3Szrj const struct ld_plugin_symbol *syms = plugin_data->syms;
560fae548d3Szrj static asection fake_section
561fae548d3Szrj = BFD_FAKE_SECTION (fake_section, NULL, "plug", 0,
562fae548d3Szrj SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS);
563fae548d3Szrj static asection fake_common_section
564fae548d3Szrj = BFD_FAKE_SECTION (fake_common_section, NULL, "plug", 0, SEC_IS_COMMON);
565fae548d3Szrj int i;
566fae548d3Szrj
567fae548d3Szrj for (i = 0; i < nsyms; i++)
568fae548d3Szrj {
569fae548d3Szrj asymbol *s = bfd_alloc (abfd, sizeof (asymbol));
570fae548d3Szrj
571fae548d3Szrj BFD_ASSERT (s);
572fae548d3Szrj alocation[i] = s;
573fae548d3Szrj
574fae548d3Szrj s->the_bfd = abfd;
575fae548d3Szrj s->name = syms[i].name;
576fae548d3Szrj s->value = 0;
577fae548d3Szrj s->flags = convert_flags (&syms[i]);
578fae548d3Szrj switch (syms[i].def)
579fae548d3Szrj {
580fae548d3Szrj case LDPK_COMMON:
581fae548d3Szrj s->section = &fake_common_section;
582fae548d3Szrj break;
583fae548d3Szrj case LDPK_UNDEF:
584fae548d3Szrj case LDPK_WEAKUNDEF:
585fae548d3Szrj s->section = bfd_und_section_ptr;
586fae548d3Szrj break;
587fae548d3Szrj case LDPK_DEF:
588fae548d3Szrj case LDPK_WEAKDEF:
589fae548d3Szrj s->section = &fake_section;
590fae548d3Szrj break;
591fae548d3Szrj default:
592fae548d3Szrj BFD_ASSERT (0);
593fae548d3Szrj }
594fae548d3Szrj
595fae548d3Szrj s->udata.p = (void *) &syms[i];
596fae548d3Szrj }
597fae548d3Szrj
598fae548d3Szrj return nsyms;
599fae548d3Szrj }
600fae548d3Szrj
601fae548d3Szrj static void
bfd_plugin_print_symbol(bfd * abfd ATTRIBUTE_UNUSED,PTR afile ATTRIBUTE_UNUSED,asymbol * symbol ATTRIBUTE_UNUSED,bfd_print_symbol_type how ATTRIBUTE_UNUSED)602fae548d3Szrj bfd_plugin_print_symbol (bfd *abfd ATTRIBUTE_UNUSED,
603fae548d3Szrj PTR afile ATTRIBUTE_UNUSED,
604fae548d3Szrj asymbol *symbol ATTRIBUTE_UNUSED,
605fae548d3Szrj bfd_print_symbol_type how ATTRIBUTE_UNUSED)
606fae548d3Szrj {
607fae548d3Szrj BFD_ASSERT (0);
608fae548d3Szrj }
609fae548d3Szrj
610fae548d3Szrj static void
bfd_plugin_get_symbol_info(bfd * abfd ATTRIBUTE_UNUSED,asymbol * symbol,symbol_info * ret)611fae548d3Szrj bfd_plugin_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
612fae548d3Szrj asymbol *symbol,
613fae548d3Szrj symbol_info *ret)
614fae548d3Szrj {
615fae548d3Szrj bfd_symbol_info (symbol, ret);
616fae548d3Szrj }
617fae548d3Szrj
618fae548d3Szrj /* Make an empty symbol. */
619fae548d3Szrj
620fae548d3Szrj static asymbol *
bfd_plugin_make_empty_symbol(bfd * abfd)621fae548d3Szrj bfd_plugin_make_empty_symbol (bfd *abfd)
622fae548d3Szrj {
623fae548d3Szrj asymbol *new_symbol = bfd_zalloc (abfd, sizeof (asymbol));
624fae548d3Szrj if (new_symbol == NULL)
625fae548d3Szrj return new_symbol;
626fae548d3Szrj new_symbol->the_bfd = abfd;
627fae548d3Szrj return new_symbol;
628fae548d3Szrj }
629fae548d3Szrj
630fae548d3Szrj static int
bfd_plugin_sizeof_headers(bfd * a ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED)631fae548d3Szrj bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
632fae548d3Szrj struct bfd_link_info *info ATTRIBUTE_UNUSED)
633fae548d3Szrj {
634fae548d3Szrj BFD_ASSERT (0);
635fae548d3Szrj return 0;
636fae548d3Szrj }
637fae548d3Szrj
638fae548d3Szrj const bfd_target plugin_vec =
639fae548d3Szrj {
640fae548d3Szrj "plugin", /* Name. */
641fae548d3Szrj bfd_target_unknown_flavour,
642fae548d3Szrj BFD_ENDIAN_LITTLE, /* Target byte order. */
643fae548d3Szrj BFD_ENDIAN_LITTLE, /* Target headers byte order. */
644fae548d3Szrj (HAS_RELOC | EXEC_P | /* Object flags. */
645fae548d3Szrj HAS_LINENO | HAS_DEBUG |
646fae548d3Szrj HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
647fae548d3Szrj (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
648fae548d3Szrj | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags. */
649fae548d3Szrj 0, /* symbol_leading_char. */
650fae548d3Szrj '/', /* ar_pad_char. */
651fae548d3Szrj 15, /* ar_max_namelen. */
652fae548d3Szrj 255, /* match priority. */
653fae548d3Szrj
654fae548d3Szrj bfd_getl64, bfd_getl_signed_64, bfd_putl64,
655fae548d3Szrj bfd_getl32, bfd_getl_signed_32, bfd_putl32,
656fae548d3Szrj bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
657fae548d3Szrj bfd_getl64, bfd_getl_signed_64, bfd_putl64,
658fae548d3Szrj bfd_getl32, bfd_getl_signed_32, bfd_putl32,
659fae548d3Szrj bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
660fae548d3Szrj
661fae548d3Szrj { /* bfd_check_format. */
662fae548d3Szrj _bfd_dummy_target,
663fae548d3Szrj bfd_plugin_object_p,
664fae548d3Szrj bfd_generic_archive_p,
665fae548d3Szrj _bfd_dummy_target
666fae548d3Szrj },
667fae548d3Szrj { /* bfd_set_format. */
668fae548d3Szrj _bfd_bool_bfd_false_error,
669fae548d3Szrj _bfd_bool_bfd_false_error,
670fae548d3Szrj _bfd_generic_mkarchive,
671fae548d3Szrj _bfd_bool_bfd_false_error,
672fae548d3Szrj },
673fae548d3Szrj { /* bfd_write_contents. */
674fae548d3Szrj _bfd_bool_bfd_false_error,
675fae548d3Szrj _bfd_bool_bfd_false_error,
676fae548d3Szrj _bfd_write_archive_contents,
677fae548d3Szrj _bfd_bool_bfd_false_error,
678fae548d3Szrj },
679fae548d3Szrj
680fae548d3Szrj BFD_JUMP_TABLE_GENERIC (bfd_plugin),
681fae548d3Szrj BFD_JUMP_TABLE_COPY (bfd_plugin),
682fae548d3Szrj BFD_JUMP_TABLE_CORE (bfd_plugin),
683fae548d3Szrj #ifdef USE_64_BIT_ARCHIVE
684fae548d3Szrj BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_64_bit),
685fae548d3Szrj #else
686fae548d3Szrj BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
687fae548d3Szrj #endif
688fae548d3Szrj BFD_JUMP_TABLE_SYMBOLS (bfd_plugin),
689fae548d3Szrj BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
690fae548d3Szrj BFD_JUMP_TABLE_WRITE (bfd_plugin),
691fae548d3Szrj BFD_JUMP_TABLE_LINK (bfd_plugin),
692fae548d3Szrj BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
693fae548d3Szrj
694fae548d3Szrj NULL,
695fae548d3Szrj
696fae548d3Szrj NULL /* backend_data. */
697fae548d3Szrj };
698fae548d3Szrj #endif /* BFD_SUPPORTS_PLUGIN */
699